[READ-ONLY] Mirror of https://github.com/andrioid/pi-fence. Fence wrapper for Pi coding agent. Wraps bash calls and intercepts reads/writes according to fence config
0

Configure Feed

Select the types of activity you want to include in your feed.

pi-fence / policy / starter-template.ts
8.5 kB 266 lines
1/** 2 * Pi-fence starter `fence.jsonc` template. 3 * 4 * This is a vendored, opinionated baseline that pi-fence scaffolds into 5 * project roots that have no existing fence config. It is intentionally 6 * self-contained (no `extends`) because fence's slice-merge semantics 7 * are append-only — a child config cannot remove inherited rules. The 8 * only way to express "I want code's allowlist but a *narrower* 9 * denyWrite" is to author the policy from scratch. 10 * 11 * What this template is, relative to fence's built-in `code`: 12 * 13 * - Same network allowlist + deniedDomains, plus the language-toolchain 14 * CDNs that fence's `code` doesn't carry today (mise infra, nodejs.org, 15 * dl.google.com, hashicorp, rust). These cover the most common 16 * `mise install <runtime>@<ver>` workflows. 17 * 18 * - Same `allowWrite` set, plus `~/Library/Caches/**`. mise on macOS 19 * resolves its cache to `~/Library/Caches/mise/` (platform dirs 20 * convention); without this every install fails with EPERM mid-tar. 21 * 22 * - Same `denyRead` (secret/credentials carve-out). Unchanged. 23 * 24 * - **denyWrite scoped to the project tree (`./**\/...`)** instead of 25 * `**\/...`. Same security signal — agent can't write `.env`, 26 * `*.pem`, `*.key` into the repo — but no longer false-positives on 27 * tarball test fixtures (Go stdlib, Node source, npm packages with 28 * test certs) extracted into ~/.local/share, /tmp, or any cache dir. 29 * 30 * - Same `command.deny` list (git push, npm publish, sudo, gh ...). 31 * Unchanged. 32 * 33 * When fence's `code` template gains new rules upstream, this file needs 34 * a manual resync. Diff against `fence config show --template code | jq -S .` 35 * and update accordingly. Bumped versions of pi-fence may ship with a 36 * refreshed template; users who want to follow upstream more closely can 37 * delete their project `fence.jsonc` and let pi-fence re-scaffold (or 38 * change the file to `extends: "code"` and accept the mise/npm gaps). 39 * 40 * Pi-fence source-of-truth diff is recorded in PLAN.md §"Starter template". 41 */ 42 43/** 44 * The literal JSONC content pi-fence writes when scaffolding. We keep 45 * comments in the on-disk file so users can read what each section does 46 * without leaving their editor — that's why this is a string and not a 47 * structured object piped through JSON.stringify. 48 * 49 * Trailing newline is intentional (POSIX text-file convention). 50 */ 51export const STARTER_TEMPLATE = `// fence.jsonc — pi-fence starter policy. 52// 53// Scaffolded by pi-fence. Edit freely; pi-fence will not overwrite it. 54// Reference: https://github.com/Use-Tusk/fence/blob/main/docs/configuration.md 55// 56// Why this is self-contained instead of \`extends: "code"\`: fence's 57// \`code\` template carries a global \`denyWrite: ["**/*.pem", "**/*.key", ...]\` 58// that false-positives on language-toolchain extractions (e.g. Go's 59// crypto/tls/testdata/*.pem). Slice fields only append on extends, so 60// the only way to scope those denies to the project tree is to author 61// the full policy here. See pi-fence README §"Project scaffolding" 62// for the rationale and how this template differs from \`code\`. 63{ 64 "$schema": "https://raw.githubusercontent.com/Use-Tusk/fence/main/docs/schema/fence.schema.json", 65 "allowPty": true, 66 67 "network": { 68 "allowedDomains": [ 69 // LLM providers 70 "api.openai.com", 71 "*.anthropic.com", 72 "api.githubcopilot.com", 73 "generativelanguage.googleapis.com", 74 "api.mistral.ai", 75 "api.cohere.ai", 76 "api.together.xyz", 77 "openrouter.ai", 78 "api.morphllm.com", 79 "*.amazonaws.com", 80 "opencode.ai", 81 "api.opencode.ai", 82 "ampcode.com", 83 "*.ampcode.com", 84 "*.factory.ai", 85 "api.workos.com", 86 "*.cursor.sh", 87 "data.charm.land", 88 "catwalk.charm.sh", 89 "*.githubcopilot.com", 90 "models.dev", 91 92 // Source hosting 93 "github.com", 94 "api.github.com", 95 "raw.githubusercontent.com", 96 "codeload.github.com", 97 "objects.githubusercontent.com", 98 "release-assets.githubusercontent.com", 99 "gitlab.com", 100 101 // Package registries 102 "registry.npmjs.org", 103 "*.npmjs.org", 104 "registry.yarnpkg.com", 105 "pypi.org", 106 "files.pythonhosted.org", 107 "crates.io", 108 "static.crates.io", 109 "index.crates.io", 110 "proxy.golang.org", 111 "sum.golang.org", 112 "formulae.brew.sh", 113 114 // Language toolchain CDNs (pi-fence additions over fence's "code") 115 "*.jdx.dev", // mise infrastructure (mise.jdx.dev, mise-versions.jdx.dev) 116 "nodejs.org", // node downloads (mise install node@...) 117 "dl.google.com", // go downloads (mise install go@...) 118 "static.rust-lang.org", // rust toolchains (mise install rust@...) 119 "releases.hashicorp.com" // terraform/vault/consul/... 120 ], 121 "deniedDomains": [ 122 "169.254.169.254", 123 "metadata.google.internal", 124 "instance-data.ec2.internal", 125 "statsig.anthropic.com", 126 "*.sentry.io" 127 ], 128 "allowLocalBinding": true, 129 "allowLocalOutbound": true 130 }, 131 132 "filesystem": { 133 // Reads are default-allow; only the listed paths are blocked. 134 // Common credential/secret stores — kept identical to fence "code". 135 "denyRead": [ 136 "~/.ssh/id_*", 137 "~/.ssh/config", 138 "~/.ssh/*.pem", 139 "~/.gnupg/**", 140 "~/.aws/**", 141 "~/.config/gcloud/**", 142 "~/.kube/**", 143 "~/.docker/**", 144 "~/.pypirc", 145 "~/.netrc", 146 "~/.git-credentials", 147 "~/.cargo/credentials", 148 "~/.cargo/credentials.toml" 149 ], 150 151 // Writes are default-deny; only listed paths are writable. 152 "allowWrite": [ 153 // Project + scratch 154 ".", 155 "/tmp", 156 157 // Generic caches 158 "~/.cache", 159 "~/.cache/**", 160 "~/Library/Caches/**", // macOS platform cache (mise, many tools) — pi-fence addition 161 162 // Pi & sibling agent state dirs (so agents can persist their own state) 163 "~/.pi/**", 164 "~/.claude*", 165 "~/.claude/**", 166 "~/.amp", 167 "~/.codex/**", 168 "~/.cursor/**", 169 "~/.opencode/**", 170 "~/.gemini/**", 171 "~/.factory/**", 172 "~/.copilot/**", 173 "~/.kiro/**", 174 "~/Library/Application Support/kiro-cli/**", 175 176 // XDG-ish state and share 177 "~/.local/state/**", 178 "~/.local/share/**", 179 "~/.config/**", 180 181 // Per-language tool dirs 182 "~/.npm/_cacache", 183 "~/.npm/_npx", 184 "~/.bun/**", 185 "~/.cargo/registry/**", 186 "~/.cargo/git/**", 187 "~/.cargo/.package-cache", 188 189 // Misc 190 "~/.zcompdump*" 191 ], 192 193 // Tripwires for "agent writing fresh secrets into the repo". 194 // Scoped to ./**/* so package-manager extractions outside the project 195 // (which legitimately ship test fixtures named *.pem / *.key) are not 196 // false-positived. Pi-fence's mandatory denies (extension/skill dirs, 197 // global fence config, audit log) are appended at runtime. 198 "denyWrite": [ 199 "./**/.env", 200 "./**/.env.*", 201 "./**/*.key", 202 "./**/*.pem", 203 "./**/*.p12", 204 "./**/*.pfx" 205 ] 206 }, 207 208 "command": { 209 "deny": [ 210 // Destructive git 211 "git push", 212 "git reset", 213 "git clean", 214 "git checkout --", 215 "git rebase", 216 "git merge", 217 218 // Package publishing 219 "npm publish", 220 "pnpm publish", 221 "yarn publish", 222 "cargo publish", 223 "twine upload", 224 "gem push", 225 226 // Privilege 227 "sudo", 228 229 // gh — destructive / publishing / auth 230 "gh pr create", 231 "gh pr merge", 232 "gh pr close", 233 "gh pr reopen", 234 "gh pr review", 235 "gh pr comment", 236 "gh release create", 237 "gh release delete", 238 "gh repo create", 239 "gh repo fork", 240 "gh repo delete", 241 "gh issue create", 242 "gh issue close", 243 "gh issue comment", 244 "gh gist create", 245 "gh workflow run", 246 "gh api", 247 "gh auth login", 248 "gh secret set", 249 "gh secret delete", 250 "gh variable set", 251 "gh variable delete" 252 ], 253 "useDefaults": true 254 } 255} 256`; 257 258/** 259 * Stable identifier for the template version we last shipped. Bumped 260 * when STARTER_TEMPLATE changes meaningfully (new domain, new path). 261 * 262 * Currently unused at runtime; reserved for future "your scaffold is 263 * stale" lint warnings if pi-fence wants to nudge users to refresh 264 * after upstream `code` template additions. 265 */ 266export const STARTER_TEMPLATE_VERSION = "2026.05.10";