docs(server): re-point forge scope-enforcement record to the governed server root (RIG-2679) - #601
Conversation
|
Compass engineering docs preview: https://compass-server-rig-2679-forg.compass-eng-docs.pages.dev Deployed from Changed pages: |
…9 B) Review PR #601 (2 low, advisory on a design record): - L1: reword the Ledger-impact amend attribution — the A8 no-scope posture lives in DL-200's implementing comment (forge.go:16-18) tracing to the board 'Resolved decision 2' ruling, not in the DL-200 row text. - L2: name the exhaustiveness test's residual (a mis-classified write arm) and add the T2 signature cross-check (read/unimplemented sets hold only no-caller handlers) that closes it structurally, in §A3 and T2. Ledger-impact: deferred to freeze
…9 B) Review PR #601 (2 low, advisory on a design record): - L1: reword the Ledger-impact amend attribution — the A8 no-scope posture lives in DL-200's implementing comment (forge.go:16-18) tracing to the board 'Resolved decision 2' ruling, not in the DL-200 row text. - L2: name the exhaustiveness test's residual (a mis-classified write arm) and add the T2 signature cross-check (read/unimplemented sets hold only no-caller handlers) that closes it structurally, in §A3 and T2. Ledger-impact: deferred to freeze
20634fb to
f2900f5
Compare
e6b2a3e to
40cd38d
Compare
|
Heads up from RIG-2577 T10 (#832, now open): that PR removed the transitional This PR adds
Before merge, please re-point the record to |
…ve-family sweep (RIG-3113) The final task (T10) of the RIG-2577 design-docs reorg. T8 dissolved `product/` into `agent/`/`server/`/`ui/`/`meta/` but left the native-app family under the transitional `product/` governed root while RIG-2542's client-only direction settled. RIG-2542 is closed (Done, 2026-08-23) and T8/T9 have merged (#825), so this empties and removes `product/`. ## What moved The 8 remaining records `product/` → `ui/` (all UI/native-shell surface): - `compass-native-app/`, `compass-native-client-mode/`, `compass-native-client-only/`, `compass-native-packaging/` - `compass-multi-window/`, `compass-stack-cross-process-teardown/`, `compass-gtk4-migration/` - `compass-tauri-shell.md` (stays flat at the `ui/` root; the corpus's only supersession pointer) ## Re-points (same PR, per CONTRIBUTING §"Moving a record is not a freeze violation") - **Ledger:** 18 `DECISIONS.md` Record cells `product/<r>` → `ui/<r>`. - **Supersession pointer:** `compass-tauri-shell.md`'s `Status: Superseded by compass-native-app/design.md` is already the final same-bucket record-relative form; verified it resolves under the generalized `resolveRecordRelative` (no `../` escape) now that both endpoints sit in `ui/`. - **Cross-bucket citations to the 8:** `infra/ci/compass-agent-image-publish`, `infra/ci/compass-dogfood-e2e`, `infra/release/compass-release-bundling`, `infra/release/compass-distribution`, `infra/runtime/compass-runner-arbitrary-uid`, plus the two moved records' own self/sibling citations. - **Code/config:** `go/e2e/client_mode_test.go`, `tools/renovate/config.json5`. ## De-govern + delete - Removed `"product"` from `GOVERNED_ROOTS` in `tools/design-ledger-gate/index.ts` (now `[ui, agent, server, meta, infra, observability, repo]`) and updated its doc comment. - Deleted the now-empty `docs/designs/product/` directory. - Dropped CONTRIBUTING §6's `product/ is transitional` subsection and the "plus the transitional `product/` root" clause; the transitional state is over. - Updated the gate's own test fixtures (`index.test.ts`) that used `product/` as a governed-bucket stand-in to `ui/` (a de-governed bucket would flip their `touchesRecord(...).toBe(true)` assertions). ## Verification - `design-ledger-gate`: OK — 284 ledger rows, 120 record headers valid, exit 0. - Gate test suite: 81 pass / 0 fail. - eng-docs `gather`: 187 docs + index + sidebar, exit 0. - Relative `.md` link resolution across all 135 design records: 0 dangling. - The ~108 remaining `docs/designs/product/...` mentions are pre-existing historical prose in frozen records (old `product/DECISIONS.md` ledger path relocated at T2, deleted `compass-0.x` version records, the old `PRODUCT_DIR` gate constant, and the separate `docs/specs/product/` tree) — none reference a moved record, and rewriting frozen records' decision prose is out of scope. ## Coordination note Two open draft PRs add new NON-native records into `product/` against the pre-T8 flat taxonomy: #601 (`compass-forge-scope-enforcement` → belongs in `server/`) and #662 (`compass-first-run-tour` → belongs in `ui/`). Both must re-point their record to the correct bucket before merge (mis-filed against the dissolved taxonomy regardless). Flagged on both PRs. Refs RIG-3113. Refs RIG-2577. Ledger-impact: 18 Record-cell path re-points (product/ → ui/); no decision rows added, flipped, or removed. Spec-impact: none. Co-authored-by: Matt Wilkinson <matt@rigel.build>
…ve-family sweep (RIG-3113) (#832) * refactor(design-docs): dissolve transitional product/ into ui/ — native-family sweep (RIG-3113) The final task (T10) of the RIG-2577 design-docs reorg. T8 dissolved `product/` into `agent/`/`server/`/`ui/`/`meta/` but left the native-app family under the transitional `product/` governed root while RIG-2542's client-only direction settled. RIG-2542 is closed (Done, 2026-08-23) and T8/T9 have merged (#825), so this empties and removes `product/`. ## What moved The 8 remaining records `product/` → `ui/` (all UI/native-shell surface): - `compass-native-app/`, `compass-native-client-mode/`, `compass-native-client-only/`, `compass-native-packaging/` - `compass-multi-window/`, `compass-stack-cross-process-teardown/`, `compass-gtk4-migration/` - `compass-tauri-shell.md` (stays flat at the `ui/` root; the corpus's only supersession pointer) ## Re-points (same PR, per CONTRIBUTING §"Moving a record is not a freeze violation") - **Ledger:** 18 `DECISIONS.md` Record cells `product/<r>` → `ui/<r>`. - **Supersession pointer:** `compass-tauri-shell.md`'s `Status: Superseded by compass-native-app/design.md` is already the final same-bucket record-relative form; verified it resolves under the generalized `resolveRecordRelative` (no `../` escape) now that both endpoints sit in `ui/`. - **Cross-bucket citations to the 8:** `infra/ci/compass-agent-image-publish`, `infra/ci/compass-dogfood-e2e`, `infra/release/compass-release-bundling`, `infra/release/compass-distribution`, `infra/runtime/compass-runner-arbitrary-uid`, plus the two moved records' own self/sibling citations. - **Code/config:** `go/e2e/client_mode_test.go`, `tools/renovate/config.json5`. ## De-govern + delete - Removed `"product"` from `GOVERNED_ROOTS` in `tools/design-ledger-gate/index.ts` (now `[ui, agent, server, meta, infra, observability, repo]`) and updated its doc comment. - Deleted the now-empty `docs/designs/product/` directory. - Dropped CONTRIBUTING §6's `product/ is transitional` subsection and the "plus the transitional `product/` root" clause; the transitional state is over. - Updated the gate's own test fixtures (`index.test.ts`) that used `product/` as a governed-bucket stand-in to `ui/` (a de-governed bucket would flip their `touchesRecord(...).toBe(true)` assertions). ## Verification - `design-ledger-gate`: OK — 284 ledger rows, 120 record headers valid, exit 0. - Gate test suite: 81 pass / 0 fail. - eng-docs `gather`: 187 docs + index + sidebar, exit 0. - Relative `.md` link resolution across all 135 design records: 0 dangling. - The ~108 remaining `docs/designs/product/...` mentions are pre-existing historical prose in frozen records (old `product/DECISIONS.md` ledger path relocated at T2, deleted `compass-0.x` version records, the old `PRODUCT_DIR` gate constant, and the separate `docs/specs/product/` tree) — none reference a moved record, and rewriting frozen records' decision prose is out of scope. ## Coordination note Two open draft PRs add new NON-native records into `product/` against the pre-T8 flat taxonomy: #601 (`compass-forge-scope-enforcement` → belongs in `server/`) and #662 (`compass-first-run-tour` → belongs in `ui/`). Both must re-point their record to the correct bucket before merge (mis-filed against the dissolved taxonomy regardless). Flagged on both PRs. Refs RIG-3113. Refs RIG-2577. Ledger-impact: 18 Record-cell path re-points (product/ → ui/); no decision rows added, flipped, or removed. Spec-impact: none. Co-authored-by: Matt Wilkinson <matt@rigel.build> * fix(design-docs): correct two link citations flagged in review (RIG-3113) Two backtick-code-span path citations left dangling by the product/->ui/ sweep, both on lines the T10 PR edited: - infra/ci/compass-dogfood-e2e:50 and ui/compass-native-client-mode:744 — the sweep over-reached into out-of-scope old-ledger-path prose and rewrote it to a nonexistent docs/designs/ui/DECISIONS.md (there is no per-bucket ledger; the single ledger is docs/designs/DECISIONS.md). Reverted both to the frozen base value docs/designs/product/DECISIONS.md to match the untouched sibling records. - infra/release/compass-distribution:75 — a cross-bucket citation to the moved compass-native-client-only record had a wrong relative depth (../../ui/ resolves to infra/ui/, which does not exist). Corrected to ../../../ui/ so it resolves to docs/designs/ui/compass-native-client-only/design.md. Co-authored-by: Matt Wilkinson <matt@rigel.build> Refs RIG-3113 --------- Co-authored-by: Matt Wilkinson <matt@rigel.build>
|
Update: #832 merged ( |
… server root (RIG-2679) PR 832 dissolved docs/designs/product/ and dropped 'product' from GOVERNED_ROOTS, so this record's path no longer existed and no rename carried it. Rebuilt on current main at docs/designs/server/, where the ledger gate governs it. Moving into a governed root exposed seven retired SEA-1527 references the gate could not previously see; rewritten to RIG-1527 (already cited in three records on main). Three review rounds against the relocated record found defects the move had carried unexamined: - Subscribe/Unsubscribe were described as unimplemented. Both are implemented, take a caller, and write to the store, so the write-arm exhaustiveness test would have classified two real write arms as out of scope and left them ungated. - account_forge_scopes omitted tenant_id, opting an authorization table out of row-level tenant isolation that 26 of 30 tables carry. - All 119 path:line citations replaced with symbol anchors. Most no longer resolved to the quoted text; one cited a range 116 lines past a file's end. Line citations drift on every edit above them, so a frozen record's anchors rot without the record changing. - The RLS enrollment instruction split the CREATE TABLE and the tenant_tables[] entry across two migrations, which is inert on any already-applied database. Both halves now land in 0001_init.sql, and the pre-dogfood premise that licenses folding is stated rather than assumed, with the branch to take if it lapses. Also: a stale ledger max that resolved to a taken id, a wrong DL reference, a nonexistent env var, an incorrect proto field list, and a dangling migration pointer. The record is Status: Draft and proposes its ledger row rather than appending it: the id is assigned at freeze, since any max hardcoded here goes stale the moment another record merges. The record's own Ledger delta section carries the proposed row and the DL-200 relationship. Ledger-impact: none in this PR — the record proposes one row (Comms & tools) that lands at freeze; DECISIONS.md is untouched here. Co-authored-by: Matt Wilkinson <matt@rigel.build>
40cd38d to
b8b4cd7
Compare
The deferred A8 forge scope control, in two enforcement legs sharing one per-account allowlist (
account_forge_scopes).A1-A4 — forge-API write chokepoint
requireForgeScopein every write arm ofExecuteForgeCallAsAccount— after coordinate resolution, on create arms after the F3 idempotency-memo check, before any provider call — rejecting out-of-scope targets as the in-bandForgeCallError{code:"not_found"}, byte-identical to the 403/404 flatten (no probe oracle). Gated byForgeConfig.EnforceScopes: off for Dogfood, mandatory for Beta.A5 / T4-T5 — git clone/push/pull scope (Matt's 2026-08-26 expansion)
Scope the credential, not the git call: mint a GitHub App installation token narrowed via the
repositoriesfield to the workstream repo + the account's granted repo set, so an out-of-scopegit push/clonefails at GitHub itself — zero enforcement code inside the agent-controlled container. The self-clone invariant keeps the agent's own workstream repo always clonable (else provisioning succeeds but the agent is dead on arrival); zero/insufficient-grant provision fails loud. Both credential surfaces (.git-credentials+ gh-CLIhosts.yml) carry the narrowed token from provision (t=0), not only after first refresh. A new T4.5 (proto) task carries the minted token across the Server→Runner process boundary (ProvisionAgentWorkspaceRequestcarries no credential today) with a server-driven refresh push keyed by a per-live-container scheduler registry; T5 hardens refresh (margin, backoff, keep-old-token-on-failure, atomic rewrite, both surfaces).Review history
Prior design-critic + code-review passes on the forge-API core (A1-A4) folded. Git-op leg (A5/T4/T4.5/T5) added; a design-critic red-team folded (self-clone invariant, Server→Runner wire path, loud PAT-fallback); then a three-round code-review loop reached all-clear at the high+medium floor — round 1 (1 high / 3 med / 2 low: SEA-1527 miscitation → OQ-8, hosts.yml refresh surface, refresh-scheduler state, read/write asymmetry, 404/403, owner-alias), round 2 (provision-time hosts.yml gap + co-resident gh-host preservation + projection phrasing), round 3 all-clear. Sub-floor items (same-host token precedence, citation normalization) dispositioned inline.
Open questions — SIX load-bearing, four handed to Matt by name
Corrected: earlier status lines from me named only OQ-1 and OQ-6. Enumerated from the record's own bullet labels — 6 load-bearing / 2 not / 8 total.
agent_accountscolumn, or store-side spawn-target record); reverses a prior Matt ruling, so it is his call. Blocks T4/T4.5/T5.Non-load-bearing, recorded not asked: OQ-4 (read arms stay ungated this slice) and OQ-5 (wildcard grammar).
Status: at freeze gate pending six rulings. A record cannot freeze with live load-bearing OQs.
Ledger-impact: none in this PR — the record is
Status: Draftand proposes one Comms & tools row that lands at freeze, amending DL-200's inherited no-scope-rejection A8 clause without superseding it.DECISIONS.mdis untouched here. Row id assigned at freeze:origin/mainatc374bb98carries 304 rows, max DL-337 (sort -nover a full extraction, not a rendering; POS-CTRL DL-337 present, NEG-CTRL DL-999 absent), which alone licenses next free ≥ DL-338 — DL-338..343 all measured absent on that tree. Folding in-flight mints raises it, but each belongs to a different tree and is stated as such: #900 atad63e1b4mints DL-340, and #913 at15e86552mints only DL-338/339 — #913 is stacked on #900 (baseRefName== #900'sheadRefName;merge-base --is-ancestorYES; the DL-340 row is byte-identical at both heads, md59159954a06ba), so its DL-340 is inherited, not double-minted. A stacked PR must be diffed against its base, not trunk, or its parent's rows are attributed to it. and DL-341 reported by #932's owner, which I have not measured — no local ref for that branch. So: ≥ DL-338 on main; ≥ DL-341 on the trees I verified; ≥ DL-342 only if #932's mint holds. Note the ledger is not id-ordered — 22 descents, last positional row DL-323 against a max of DL-337 — so an extremum must come from a full extraction, never from a prefix or a truncated listing.Refs RIG-2679
Spec-impact: none