fn hard_blocked(atom: &Scope) -> boolExpand description
Whether this atom is one this server never grants, whatever a ceiling
says: plan/scope-policy.md’s hard-blocked capabilities, and any atom the
grammar cannot read. verdict_for drops each from the request whole, so
the rest can be granted and the agent sees it in cut.
account and identity are on that list because key rotation and
migrating out are boundaries an operator draws deliberately rather than
ones an app asks its way past. blob is not: an upload is checked
against the grant at uploadBlob and judged by policy twice, so a
blob: scope says what an app may upload rather than handing it the
account. transition:* is on it for
the opposite reason — it is not narrow but enormous, carrying records,
blobs and RPC in one string, which is what makes every granular rule
beside it decorative.
Deliberately here and not in crate::oauth::scope. That module is the
grammar — what a scope string means, and how two of them overlap — and
this is a policy about which of them this deployment will consider at
all. A grammar that knew the list could not be read by anything that
disagreed with it.