Project filesystem policy
Choose explicit read and write rules for the project. Review the execution boundary before enabling restrictions: operations that cannot enforce those paths pause rather than silently bypassing the policy.
Set project path rules
Settings → Projects & access stores owner-managed read and write rules per project. Each save uses the exact displayed revision; conflicting saves preserve the browser draft. Private files live at CODEFLOW_HOME/filesystem-policies/<project>.json, with version 1, a revision, timestamp and SHA-256 content hash. Corrupt or symbolic policy storage fails closed without replacing it with unrestricted defaults.
Rules use literal relative repository paths. . covers the whole repository; src covers that file or subtree. Each read/write operation must match an allow entry and no deny entry. Empty allow lists deny everything. Denies also match conservatively across case and Unicode compatibility variants. There are no globs, traversal components, absolute paths or Git internals. Credential paths, private keys and symbolic filesystem ancestors have fixed application-level denies. Policies from every matching project and the run's pinned snapshots intersect: choosing another project or weakening today's policy cannot silently weaken an older run's pinned policy.
The application enforces paths for repository file reads, tree and filename search, textual content search, file editing and filtered run diffs. Read and write checks run again before returning content or publishing a file edit. Both sides of a renamed diff must be readable. Restricted projects' raw run history, event transcripts, exports, configuration, memory and other evidence that cannot be reliably filtered are unavailable. Restricted results are omitted before list pagination, search and totals, including shared review dashboards. Existing feeds close and reconnect with a new snapshot generation when policy changes. Unscoped statistics, private notes, memory, saved automation/queue requests, diagnostics, notification payloads and maintenance data are also unavailable while any custom restriction is active. Project names, repository membership and policy metadata remain available to the owner.
Execution boundary
Any custom read or write restriction pauses normal application-managed execution across every project. The owner-only Filtered Docker task is the dedicated enforcing exception: it runs one manual turn against an isolated fresh Git snapshot and imports permitted changes only into a separately reviewed branch. Native agents, commands, ordinary Docker mounts, SSH workers, full Git object databases and trusted JavaScript extensions do not currently provide an enforcing filtered filesystem. The application refuses these backends rather than representing prompts or a filtered checkout as a security boundary. This includes run creation, resumption, follow-ups, verification, repository readiness execution, terminals, previews, development services, code-host actions and queued dispatch. Health responses avoid Python/provider probes under a restriction. Public read-only phone views are disabled under any custom restriction.
Policy activation requires globally idle execution, closed terminals, stopped development services, no preparing/importing or unconfirmed filtered task, and no unresolved accepted/running/unknown remote receipts. Unavailable filtered-task receipt storage also blocks activation until repaired. Background PR watches, source sweeps, deferred/coordinated readiness checks and notifications pause and finish their current work before the durable policy commit. Their underlying preparation promises remain tracked even if a queue timeout has already expired. The manager holds a global execution lease during the commit. An operation still running in another repository makes activation fail instead of racing it. Policy changes never implicitly contact a remote worker to resolve uncertain receipts: inspect or cancel them deliberately first.
Trusted extensions can retain host authority after importing, including bundles rejected after initialization. If extensions were attempted in the current process, restrictive activation is refused: disable extension configuration, restart, then apply the restriction. On later startup, saved restrictions are checked before importing any extension bundle; imports remain deferred until restrictions are deliberately removed and the application restarts. Automatic launches, watches and notification delivery stay paused until all current policies are unrestricted. Deliberately clearing restrictions resumes those services; it does not erase a run's pinned policy.
This is an application policy with fail-closed execution, not an OS sandbox or retroactive erasure. The owner, other local processes, existing external backups and manually started processes remain outside this boundary. Historical journal bytes are retained privately; the application blocks unsafe presentation instead of rewriting provenance. Filtered tasks provide an isolated filesystem and synthetic Git database for their narrow manual execution path. Native agents, SSH workers and normal automated/multi-agent workflows remain unsupported under restrictions.
HTTP contract
Owner-only GET /api/projects/:id/filesystem-policy returns the committed snapshot. PUT accepts {revision, read:{allow,deny}, write:{allow,deny}}; each list has at most 100 paths, each at most 500 characters. Saves return the next committed snapshot. Revision, activity or unsupported execution conflicts return 409; denied data returns 403; invalid paths return 400; unreadable private policy storage returns 503. /api/v1 follows the same authorization and policy. Shared accounts cannot edit policy. Parsed JSON is reused by authorization and dispatch, while a later endpoint-specific byte limit remains enforced.
Tests cover exact CAS/hash/private storage, failures before activation, pinned policy intersection, case/traversal/credential/symlink rejection, actual browser allowed/denied reads and writes, version aliases, global execution denial and cross-repository activation races. Startup regressions ensure saved policies prevent trusted plugin initialization, interpreter probes and public phone history, and remove restricted results from shared feeds.