diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 71989fa0..e03c3414 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,44 @@ and must not be cited as merge evidence. Rely on reviewer clearance + real CI. Three independent live instances in a single session — format gate, agent context reset, queue guard — is the class confirmed, not anecdote. +### D-15 — token scope is not repository permission (a THIRD capability layer) + +`f10-coder` was provisioned with `gitea-mosaicstack-f10-coder.token`, scopes `write:repository` + +`write:issue`, and the mint was verified by "repo access returns 200". It then failed to push: + +``` +remote: error: User permission denied for writing. +remote: error: pre-receive hook declined +``` + +Verified objectively rather than inferred (per the charter principle): + +| probe | result | +| ------------------------------------------------------ | ------------------------------------------- | +| `GET /repos/mosaicstack/stack/collaborators/f10-coder` | **404** — not a collaborator | +| repo permissions as seen by **its own token** | `admin: false`, `push: false`, `pull: true` | + +**Capability has at least three independent layers, and satisfying two proves nothing about the third:** + +1. **Token file exists** → raw-API authentication works (D-11b). +2. **`tea` login exists** → tea-dependent wrapper paths work (D-13). +3. **Repository permission granted** (collaborator/team membership) → _writes_ are actually authorised. + +A token can carry `write:repository` scope and still be refused, because **scope bounds what a token +may attempt; repository permission decides what the user may do.** They are different systems. + +**This is the charter principle failing on the very check meant to confirm capability.** The mint was +validated by an HTTP 200 on a _read_. A 200 proves reachability; it does not prove the property that +was required, which was **write**. Both the provisioner and I accepted it — the same +`written-unverified` treated as `verified` as D-12, one layer up, on a check whose entire purpose was +verification. + +**Requirements.** RM-50's pre-dispatch capability check must probe the **effective permission for the +operation intended** — for push authority, assert `permissions.push == true` as that seat, not token +existence and not a 200 on a read. RM-04's registry reconciliation covers all three layers, with a +must-fail control for each. A capability check that cannot fail on a seat lacking write permission is +itself an inert gate. + ### D-14 — a ruled decision did not propagate to the authoritative record DECISION-1 (the corrected choke-point wire-in target) was ruled by the coordinator and applied to