B-IENW-scoped-vault-write-grants
Experiences and agents declare which parts of a vault they write to. The shell asks the user once (“Agent Pants wants to write to marketplaces/, plugins/, skills/ in this vault”), issues a grant, and every note op call carries it. The notes port enforces the grant and records it on the write.
Why:
- All writes already funnel through the generic note ops (write, frontmatter splice, rename, delete), so enforcement lives at one choke point.
- Every write then carries who made it. The change feed can say “changed by Agent Pants”, “changed by agent run X”, or “changed on disk”. Attribution is the larger payoff.
- The same facility scopes external agents that hit the HTTP API.
Shape:
- Scopes are path prefixes on write, declared in the experience manifest. Reads stay open for in-app experiences at first.
- The trash folder is implicitly writable. Link rewrites outside the scope during a permitted rename are allowed and recorded.
- Consent at first write, not at install: allow, just once, or deny. Grants persist per vault per experience with a revoke list in settings. Refusals are dialogs.
- The grant travels as a header or IPC context, not as a field in every request body.
- Bearer tokens with expiry on the HTTP surface; opaque backend records for IPC.
Caveat to state in the decision doc: experiences run in the same renderer and process as the shell, so in-app the grant is consent, attribution, and a guard against mistakes, not a sandbox. For external agents it is a real boundary. Design for the agent case first.
Sequence: decision doc and plan; backend enforcement and grant store; manifest declaration, consent dialog, settings; Agent Pants declares its scopes; HTTP bearer tokens for agents. Lands after the Agent Pants view work.