Files
my-pi/pi-permission-system/docs/retro/0639-permission-policy-model-adr.md
T

3.2 KiB

issue, issue_title
issue issue_title
639 pi-permission-system: decide the permission policy model — capabilities, config shape, prior art (ADR 0009)

Retro: #639 — decide the permission policy model (ADR 0009)

Stage: Planning (2026-02-14T00:00:00Z)

Session summary

This session began as /plan-issue for #609 (third-party, hcrosse: govern bash output redirects separately from the command) and deliberately widened. Successive ask_user gates moved the operator from a wrapper-style ask floor, through path-surface routing, through a path_read/path_write capability-facet design, to the decision that the permission policy model itself deserves a deliberative ADR with nothing locked down — including the current config format. Filed [#639] as the dedicated ADR issue (the #581/#591 precedent), committed plan docs/plans/0639-permission-policy-model-adr.md, and left #609 open to be re-planned after the ADR lands.

Observations

  • Key technical findings from #609 exploration, needed by the eventual implementation: BashProgram.commands() strips redirects from command text; collectRedirectTokens gathers targets but they are shape-filtered like any token, so a bare in-cwd target (> out.txt) is not a rule candidate today; tree-sitter file_redirect nodes expose the operator as an anonymous child (>, >>, &>, >&) plus an optional file_descriptor, and a >&-to-number form (2>&1) is an fd-duplication, not a file write; <> rw.txt parses with an ERROR node.
  • Operator's decision criteria, stated verbatim: clarity, simplicity ("straightforward, avoiding complex calculus of interactions between rules, and ambiguity"), user-first. The "calculus of interactions" phrase puts the most-restrictive multi-surface lattice itself on the table — the plan's option O6 (single ordered rule list) exists for that reason.
  • Leanings recorded but explicitly reopened by the operator: path_read/path_write naming over fs.*; shipped ask default for redirect writes (breaking, feat!:); the effect-centered sketch (structural proof + command-effects knowledge base + explicit unknowns) as one candidate, not the target.
  • Nesting facets under path was analyzed and found grammatically ambiguous (path: { "read": "allow" } already means a file literally named read; denyWithReason object values collide with a map-valued discriminator) — the analysis should ride into the ADR.
  • Prior-art naming survey done in-session (Node --allow-fs-read/--allow-fs-write, Landlock ACCESS_FS_*, Seatbelt file-read*, Deno, WASI, systemd); the full survey with citations is Build Order step 1.
  • Process note: the operator answered only part of some ask_user gates and asked follow-up questions in the notes — treating each partial answer as a redirection (not re-asking the same question) kept the conversation productive.
  • The /build-plan session must run survey → ask_user decision gates → prose, in that order; the #581 revert (transcription instead of deliberation) is the named failure mode.