The policy model — who is allowed to do what¶
A policy is the list of what a connected account is allowed to do: read its emails? prepare drafts? write to Drive, and where exactly? The base rule is deliberately cautious — what is not explicitly allowed is denied — and it is you who widens it, never the assistant.
Concretely, each account carries a small file
~/.config/gws-accounts/<alias>/policy.json, checked by
policy-check.py
before every command — whether you type mag … or the
assistant goes through the MCP. mag add writes a cautious one by default: a brand-new
account is therefore already restricted. For everyday use, see
Everyday usage.
Default-deny, per service¶
A service missing from the policy is denied (except auth / schema,
local introspection) — including for reads. A service that is present is fail
closed: only a category explicitly set to true passes. mag add writes
a cautious policy automatically, so a fresh profile is restricted
from the start. Consequence: services the admin does not model (chat, meet,
people, slides, forms, script…) are denied by default — no action visible
from the outside escapes control.
- Drive — by zones: read everywhere, write only under the authorized
folders (subfolders included — parents are walked up via the API). Legacy
modes:
open,readonly,restricted. - Gmail — categories
read,drafts,send,labels,update,delete,settings. The winning combo: drafts without sending — the LLM prepares, you send. - Calendar / Keep / other modeled services —
read,create,update,delete,share.
mag policy mw allow "LLM" # Drive: PERMANENT zone under the "LLM" folder
mag policy mw show # shows the profile's full policy
mag mw drive files create --json '{"name":"x"}' # ✗ denied (no authorized parent)
mag mw gmail users messages send --json '…' # ✗ denied if "send": false
mag policy mw clear # Drive goes back to open (other services unchanged)
Temporary zones — the Drive elicitation flow¶
By default a zonesOnly profile is allowed to write nowhere. When
an LLM wants to write somewhere, it runs into a refusal that tells it what to
ask for; it is you who grants, for a limited time (default 8 h,
automatic expiry — so it has to be asked again for each work session):
mag grant coloc "Compta 2026" 4 # write under this folder for 4 h
mag grants coloc # active temporary authorizations
mag grant coloc revoke <folderId> # revoke before expiry
Every refusal is logged and invites the LLM to ask for the widening —
elicitation, again. Accepted limit: it is the wrapper that enforces, not
Google — the only 100% Google-side lock would be the drive.file scope.
Per-session rights — the fine grain (ADR-0007)¶
The policy and zones above are the machine floor. On top of that, each conversation (LLM session) carries its own rights, signed and time-limited — another conversation does not inherit them. This is the finest grain: per service × operation × resource.
- The human opens a session (
mag session open) — a signed gesture (Touch ID under strongauth) that returns a token; the assistant presents this token on every call (without a token: no access to data, only the creation request). - Each capability grant is signed too — never a silent widening:
mag session open # creates a signed session → token
mag session grant-capability <jeton> mw gmail read # this session: Gmail read
mag session grant-capability <jeton> mw drive create "Compta 2026" # zoned write
mag session list # active sessions + their config
- Effective rights = account policy ∩ project manifest ∩ session capabilities
(intersection, fail closed). Outside a git repo (no manifest),
policy ∩ session; but a tampered manifest closes everything (anti-downgrade). - Sub-agents inherit a subset of the parent's rights (never more) and cannot widen them on their own; the parent revokes its whole descendance in one action.
Design details: ADR-0007.
Hardenings of this model that are already settled: see the backlog item
features/done/0002-durcir-modele-policy-default-deny.md (default-deny
verified and tested) and threat-model.md.