ci/woodpecker/pr/ci Pipeline failed
Addresses CPS-PRD-REV1-REVIEW-Q90 findings F1 and F3 on PR #1491: F1 (format gate): `prettier --write` on the 18 rev1 bundle documents. Whitespace, table padding, list markers and emphasis delimiters only — a normalized token comparison of every file before/after shows zero content difference, so the ratified text is unchanged and no re-ratification applies. F3 (rev0 relative links): the archived rev0 PRD stays byte-identical (sha256 60cc2f98...36afdf verified) per GOV.1 archive-never-edit. A sibling docs/PRDs/2026-08-26_PRD_rev0/README.md records the digest, the original location, the owner disposition that the in-file links are intentionally historical, and a resolution table for all 9 targets (11 occurrences), each verified to exist. Future relocated archives ship the same README instead of edited bytes. F2 (test step) is investigated separately against the CI log.
147 lines
8.2 KiB
Markdown
147 lines
8.2 KiB
Markdown
---
|
||
id: AUTHZ.1
|
||
status: ratified
|
||
ratified: 2026-09-01 (Jason Woltje; PRD rev1 ratification PR)
|
||
---
|
||
|
||
# AUTHZ.1 — Capability authority, enforcement, and accepted risk
|
||
|
||
The agent-side authority model: what binds a seat, where it is enforced, what
|
||
is closed by construction, and what is accepted as residual risk. Sources: the
|
||
L2 authorization contracts, `mosaic-core` (measured 2026-08-31), and the lane's
|
||
`AUTHORIZATION-GAPS.md`.
|
||
|
||
## Glossary
|
||
|
||
**Privilege escapation** _(Jason, 2026-08-31)_ — the outcome class in which an
|
||
agent exercises authority it was never granted, regardless of mechanism.
|
||
Deliberately collapses escalation and misdirection: the outcome is identical;
|
||
the distinction matters only when choosing a control.
|
||
|
||
## Authority composition is pure intersection
|
||
|
||
```
|
||
role capability ceiling
|
||
∩ assignment scope ∩ lease scope ∩ workflow state
|
||
∩ target policy ∩ trusted backend availability
|
||
= effective capability grant
|
||
```
|
||
|
||
No operation adds capability. Only an authenticated principal with
|
||
role-management authority may create, edit, activate, bind, or roll back roles
|
||
(L2-D13); agents cannot, ever. Orchestrators cannot deploy seats at all —
|
||
coordination goes through `mosaic coord` requests to the coordinator service
|
||
(register OD-08/OD-09). Cycle detection is unnecessary because no grant edge
|
||
exists.
|
||
|
||
## Enforcement point: `mosaic-core`
|
||
|
||
A tracked, non-npm Pi extension loaded via role-scoped settings. Per seat, per
|
||
launch: trusted-path manifest load
|
||
(`<brainHome>/fleet/roles/<role>/mosaic-core.manifest.json` — committed,
|
||
non-symlink, role cross-checked), fail-closed state machine
|
||
(`not-applied | applied | fail-closed`), exact active-tool reconciliation,
|
||
per-call interception with read containment (canonicalization + realpath +
|
||
credential-path deny), per-incarnation append-only journal. Capabilities C1–C8
|
||
are the authority; tools are their bound projections; `tools[]` must equal the
|
||
bound bindings exactly. The capability map is closed and hardcoded in the
|
||
canary phase (gap G7 — by design for now; L2-D21 is the end state).
|
||
|
||
## The firewall rules
|
||
|
||
1. **Agents never reach role-management surfaces** (L2-D13). A seat that can
|
||
invoke role management can self-grant, voiding the model.
|
||
2. **The coordinator is a service, never a seat** (gap G4; register OD-08). A
|
||
coordinator-as-seat turns the intersection chain into a cycle.
|
||
|
||
## Closed vs accepted
|
||
|
||
**Closed by construction: escalation.** The intersection chain admits no
|
||
capability-adding edge.
|
||
|
||
**Accepted within reason: misdirection.** A rogue or colluding orchestrator can
|
||
still _route work_ to a seat that already legitimately holds a capability. The
|
||
authority is genuine, so no structural control can refuse it. Jason's ruling:
|
||
escalation and misdirection are tiered **by outcome — identically**; locking
|
||
down far enough to mechanically prevent misdirection cripples the system to
|
||
inoperability. Mitigation posture: **audit and visibility, not prevention** —
|
||
see the audit surface in [[UI.1-webui-surfaces]] and gap G3 below.
|
||
|
||
## Role separation as the working mitigation
|
||
|
||
Design intent (not yet enforced by any manifest — gap C3 in the lane ledger):
|
||
|
||
| Role | Must NOT |
|
||
| -------------- | -------------------------------- |
|
||
| coding agent | create remote git repositories |
|
||
| gate agent | code |
|
||
| review agent | code |
|
||
| interact agent | code, create remote repositories |
|
||
|
||
Breaking the monopoly means no single seat holds an exit path; escape requires
|
||
inter-seat coordination, which is exactly what the audit exists to catch.
|
||
Register OD-25–OD-34 (review/gate/arena families, independence rules) carry the
|
||
role taxonomy this matrix projects onto.
|
||
|
||
## Gap register (measured 2026-08-31)
|
||
|
||
| ID | Gap | Status |
|
||
| --- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
||
| G1 | No least-privilege language anywhere in L1/L2/NORTH-STAR (grep-verified) | **L2-D52 amendment drafted** |
|
||
| G2 | Assignment issuance criteria unspecified (renewal names criteria; issuance does not) — full-ceiling requests validate cleanly | **L2-D52 amendment drafted** |
|
||
| G3 | No misdirection audit exists — no tooling, agent, or surface | open → [[UI.1-webui-surfaces]] §Audit |
|
||
| G4 | Coordinator-as-seat would collapse the model | firewall — never violate |
|
||
| G5 | Seat config mixes authority classes (role binding beside a model dropdown) | open → [[SEAT.1-seat-profile]] |
|
||
| G6 | `role-harness-config/DESIGN.md` scope defect (unstated surface) | fix drafted (amendment in `proposed/docs/`) |
|
||
| G7 | Capability map closed/hardcoded | by design (canary phase) |
|
||
|
||
Amendments staged in `proposed/docs/` per the lane convention; ledger items
|
||
A3/A4 track ratification. The auditor-identity question (an auditor agent is
|
||
itself a seat, itself subject to misdirection) is on the grill:
|
||
[[GOV.5-open-questions]] Q-A1.
|
||
|
||
## E2 inputs (triage 2026-08-31; see [[GOV.2-docs-inventory]])
|
||
|
||
**Canonical ground truth**: `DEVELOPER-GUIDE/architecture/mutator-class-gate.md`
|
||
(the default-deny whole-class gate this section's language must match),
|
||
`lease-broker-protocol.md` + `lease-broker-security.md` (incl. the named
|
||
promote-lease-lost-ACK residual), `ADMIN-GUIDE/security/discord-ingress.md`
|
||
(the one implemented admission/role model).
|
||
**Pending pulls**: DRAFT S2 `rbac-grant-model.md` (granular RBAC per rev0 §4).
|
||
|
||
## S2 contract feed (extraction 2026-08-31)
|
||
|
||
Full extraction record: lane `S2-EXTRACTION-2026-08-31.md` (per-contract cores, dependency edges, ruling cross-checks). Pulls binding on this section:
|
||
|
||
- **Three-layer authority (contract 2)**: platform role (member/admin,
|
||
instance administration only, **no implicit tenant access** — two live admin
|
||
bypass paths named non-conformant and scheduled for retirement:
|
||
`command-authorization.service.ts` admin short-circuit, `mcp.service.ts`
|
||
scope derivation); hierarchy grants (viewer/member/owner, deny-by-default,
|
||
down-chain, effective = max, live fail-closed); workspace membership
|
||
(its own mechanism, REQ-ID-001). The layers are non-substitutable.
|
||
- **Agents are not a valid grant subject** — grant subject is exactly-one-of
|
||
user_id/team_id. Structural enforcement of the agents-never-reach-role-
|
||
surfaces ruling, stronger than policy.
|
||
- **Consent ≠ authorization (contract 7 §5.7)**: consent records govern
|
||
agentic/feature data access, are distinct from hierarchy grants, and confer
|
||
no platform authorization; default-deny with **no platform-admin bypass**;
|
||
consent mutation is subject-only (admins refused at write time).
|
||
- **Bounded revocation propagation**: next authz decision denies; open
|
||
Socket.IO connections re-evaluated within 30s or next inbound message.
|
||
- **company-CRUD capability**: platform-scoped, admin-assigned, audited
|
||
delegation of exactly one visibility-mutation command (`platform_capabilities`
|
||
table) — the model's template for narrow capability delegation.
|
||
- **Membership locality + no-existence-oracle (contract 8 §3)**:
|
||
member-readable workspaces contribute only at their own node, never promoted
|
||
upward; unreadable vs nonexistent are byte-equivalent.
|
||
|
||
## Audit implementation ruling (Q-A1/Q-A2, Jason 2026-09-01)
|
||
|
||
The authorization audit is **mechanical tooling**: deterministic checks over
|
||
the grant/assignment record, witness-style (the S2 writer-coverage pattern),
|
||
feeding the audit page read-only. Agents may consume audit output but never
|
||
produce the verdict — prompt adherence is not an enforcement mechanism. Q-A2
|
||
(who audits the auditor) dissolves: the auditor is code, audited by ordinary
|
||
review and CI.
|