/** * #502 review: paths no role may write because the OPERATOR's own processes * run or trust what is in them. A role that could write one could get code * run outside every role sandbox: * - `/.claude/` — the operator's Claude Code session in the * project loads its settings, hooks and helpers; * - `~/.monomind/` — the org skill library that decides the MCP tools the * daemon grants, the terminal-execution opt-in gate, the broker * registry, audit logs… — except the entries the CLI legitimately * writes while a role uses it (ROLE_WRITABLE_MONOMIND); * - `/.monomind/org-skills/` (the project skill library); * - #576: `/.monomind/catalog/` — the catalog's state and * packages, whose active `org` skills (their content and grantedTools, * which decide the MCP tools the daemon grants) and blueprints roles get * at start. Only the operator's `monomind catalog` writes it; * - #580: the project config other runtimes' operator sessions load and * act on, as Claude Code loads `.claude/` and `.mcp.json` * (PROJECT_RUNTIME_CONFIG): `.agents/skills` (the catalog's other * projection surface), the hook bridge, `.gemini/`, `.codex/`, … Like * `.claude/` none is pre-created (that would leave stray dirs in every * repo); while missing each is on the planted-path watch * (planted-paths.ts); * - `~/.npm/_npx` (what `npx -y monomind …` runs), `~/.npmrc`, * `~/.local/bin`, and shell startup files beyond HOME_DENY_WRITE; * - #527: the node, npm, claude and monomind installs the operator's * processes run, the version-manager roots they live in, the directories * on PATH, mise's trust store and direnv's allow list * (operator-toolchain-paths.ts), and toolchain config files. * * Enforced three ways: the SDK sandbox's `denyWrite`, read-only binds in the * bubblewrap authority mask, and the file tools' deny pass (policy.ts). The * directories on the way to them are mount points in both OS layers * (operatorMountPoints), so none can be renamed aside and replaced. An * explicit, signed `policy.sandbox.allowWrite` entry at or inside one of * these paths is the opt-out for an org that really must write it. */ /** `~/.monomind` entries a role's own `monomind` commands write: browser * automation state, the embedding-model cache, per-project memory, update * checks, runner session dirs, and the release locks. Nothing the * operator's processes execute or treat as a grant. */ export declare const ROLE_WRITABLE_MONOMIND: Set; /** #502 review round 2: the bubblewrap mask's layout for ~/.monomind (and * $MONOMIND_HOME): the directory itself read-only, so no new top-level * entry can be planted, and only the allowlisted entries bound writable * again — the same pattern as the orgs dir. An allowlisted FILE that does * not exist yet cannot be created inside the mask. */ export declare function monomindMaskLayout(home: string, env: NodeJS.ProcessEnv): { readOnly: string[]; writable: string[]; }; /** Under $HOME, beyond file-roots.ts's HOME_DENY_WRITE. */ export declare const HOME_OPERATOR_EXEC: string[]; /** Under $XDG_CONFIG_HOME (default ~/.config), like HOME_OPERATOR_EXEC. */ export declare const XDG_CONFIG_OPERATOR_EXEC: string[]; /** Inside ~/.claude, the entries Claude Code executes or obeys. Used by the * bubblewrap mask, which also wraps Claude Code itself and so cannot make * the whole of ~/.claude (sessions, todos, credentials) read-only. */ export declare const CLAUDE_HOME_EXEC: string[]; export declare const PROJECT_RUNTIME_CONFIG: string[]; export declare const monomindHome: (home: string, env: NodeJS.ProcessEnv) => string; interface ProtectedCtx { home: string; env: NodeJS.ProcessEnv; orgRoot?: string; cwd?: string; allowWrite?: string[]; } /** The signed `policy.sandbox.allowWrite` entries, absolute. */ export declare const optInPaths: (ctx: ProtectedCtx) => string[]; /** Is `p` protected: inside a protected path and not inside an opt-in? */ export declare function isOperatorProtected(p: string, ctx: ProtectedCtx, real: (x: string) => string, /** How a protected path contains `p`: the caller's DENY comparison * (policy.ts passes `isWithin(…, fold.deny)`, so `.Claude/` or * `.MCP.json` are refused where the filesystem folds case). An opt-in * (a signed allowWrite) always compares exactly. */ insideProtected?: (container: string, target: string) => boolean): string | undefined; /** Every protected path (existing or not) for a role with this org root and * cwd, with what a signed `policy.sandbox.allowWrite` entry opts into * carved out — the form the SDK sandbox and the bubblewrap mask take. */ export declare function operatorProtectedPaths(ctx: ProtectedCtx): string[]; /** #527: the directories on the way to each protected path that a role could * rename aside (operator-toolchain-paths.ts's mountPointAncestors). The SDK * sandbox lists them in allowWrite and the mask binds them onto themselves: * either way a mount point, which cannot be renamed. */ export declare function operatorMountPoints(ctx: ProtectedCtx): string[]; /** Paths the bubblewrap mask binds read-only: the protected paths plus the * guard-undoing home files, with ~/.claude narrowed to CLAUDE_HOME_EXEC. */ export declare function maskReadOnlyPaths(ctx: { home: string; env: NodeJS.ProcessEnv; orgRoot?: string; cwd?: string; allowWrite?: string[]; homeDenyWrite: string[]; }): string[]; /** Create what must exist before a role starts for the denies to hold: an * OS sandbox can only protect a path that exists, and a role creating one * of these first would plant it. The skill libraries and the npx cache are * empty directories; the terminal gate is written as disabled, which is * what its absence already meant (terminal-tools-core.ts); and the * HOME_DENY_WRITE stubs below (#526). An empty `.monomind/catalog/` means * what its absence meant: no state.json, catalog not configured. */ export declare function ensureOperatorProtectedPaths(ctx: { home: string; env: NodeJS.ProcessEnv; orgRoot?: string; platform?: NodeJS.Platform; }): void; /** #526: HOME_DENY_WRITE entries created in the operator's HOME when they * are absent, at org or session start (never overwriting), so the SDK * sandbox's denyWrite (which drops missing paths) and the mask's read-only * binds cover them too. Each is either an empty file or an empty 0700 * directory, and each means exactly what its absence meant: * - `.npmrc`: npm merges an empty user config into nothing; * - `.bashrc`: read only by interactive bash, which runs nothing from it; * - `.profile`: read by sh/dash login shells, and by bash only when * `.bash_profile` and `.bash_login` are absent; zsh never reads it; * empty, it runs nothing in any of them. Not created when $SHELL is zsh * or fish: installers such as nvm's append to ~/.profile when it exists * instead of the shell's own rc file, which that shell would then miss; * - `.ssh`, `.config/git`, `.config/gh`, `.config/npm`: tools read files * inside them, never the directory itself (git's `--global` target * depends on `~/.config/git/config`, a file, not on the directory). * `~/.config` is created too when it is missing. * Linux only. On macOS the SDK's seatbelt denies a missing path by rule * (role-sandbox-restrictions.ts), so only `~/.config` is created there, so * that the entries below it can be passed (their parent must exist). */ export declare const HOME_DENY_WRITE_STUB_DIRS: string[]; export declare const HOME_DENY_WRITE_STUB_FILES: string[]; /** Never created, left to the planted-path watch (planted-paths.ts; on * macOS the SDK's seatbelt also denies creating them, by path): * - `.bash_profile`, `.bash_login`: an empty one makes a bash login shell * skip `~/.profile`; * - `.gitconfig`: once it exists, `git config --global` writes go to it * instead of a `~/.config/git/config` the operator creates later; * - `.zshrc`, `.zprofile`, `.zshenv`, `.zlogin`: with none of them, zsh * runs its new-user setup, and an empty one would stop that; * - `.claude`, `.claude.json`: Claude Code's own state (an empty * `.claude.json` is a corrupt config); * - `.monomind/deps`: optional-deps.ts creates it. */ export declare const HOME_DENY_WRITE_NOT_STUBBED: string[]; export {}; //# sourceMappingURL=operator-protected-paths.d.ts.map