CB-548: config-declared architect slots + Role.ARCHITECT authz (corrected premise) #20

Merged
ltms merged 3 commits from worker/cb-548-authz-v2-586df6-8 into main 2026-08-13 18:33:11 +02:00
Member

Supersedes #19 (same CB-548 unit, corrected premise per review). Replaces the earlier premise that architect identity is recognised from config the way a lead is.

What this corrects vs #19

  • Config = stable name + profile only. The architects: slot is a gateway-local name → strong-model workers: profile. Removed the configured/pinned terminal field and architectTerminals(), and dropped the 'recognised like a leader' claim. On startup every slot is idle: config never supplies a terminal, so no architect terminal resolves at boot.
  • ArchitectRegistry owns the live bindings. It now holds thread-safe, mutable, initially-empty terminal → slot bindings rather than a config-derived read-only supplier. Exposes bind(slot, terminal) (validates the slot exists; atomically refuses a terminal in two slots and a slot with two terminals; same-pair rebind is an idempotent no-op) and compare-safe unbind(slot, expectedTerminal) (a stale unbind never removes a replacement). Also snapshot() (immutable copy), slotForTerminal, profileForSlot, isSlot.
  • CallerResolver consumes the registry's live snapshot. Bridged wires architects::snapshot in on both auth paths. Resolve order preserved: lead > architect > generic worker. The rest of #19's Role/Authz/Principal/whoami work is kept unchanged.
  • Duplicate YAML slot keys now rejected. Determined empirically that Jackson's YAML parser is last-wins on duplicate map keys (a duplicated architects: slot name silently dropped one slot). Added parse-time detection (rejectDuplicateArchitectSlots in load), scoped to the architects: block, failing with an IllegalStateException that names the duplicated slot.

Tests

Focused architect tests (ArchitectRegistry/Config/CallerResolver/Authz/BridgeMcp) plus new invariant + 2-concurrency tests for the registry and a duplicate-key config test.

mvn clean install → Tests run: 519, Failures: 0, Errors: 0, Skipped: 0; BUILD SUCCESS.

Residual

  • The wiki/ Features entry for the architect registry is not updated here (worker cannot touch the wiki submodule) — recommend a follow-up feature entry.
  • Leftover terminal: under an architects: slot is silently ignored (record is ignoreUnknown); an upgrade note/test documents that it no longer binds anything.
Supersedes **#19** (same CB-548 unit, corrected premise per review). Replaces the earlier premise that architect identity is recognised from config the way a lead is. ## What this corrects vs #19 - **Config = stable name + profile only.** The `architects:` slot is a gateway-local name → strong-model `workers:` profile. Removed the configured/`pinned` `terminal` field and `architectTerminals()`, and dropped the 'recognised like a leader' claim. On startup every slot is idle: config never supplies a terminal, so **no architect terminal resolves at boot**. - **ArchitectRegistry owns the live bindings.** It now holds thread-safe, *mutable*, initially-empty `terminal → slot` bindings rather than a config-derived read-only supplier. Exposes `bind(slot, terminal)` (validates the slot exists; atomically refuses a terminal in two slots and a slot with two terminals; same-pair rebind is an idempotent no-op) and compare-safe `unbind(slot, expectedTerminal)` (a stale unbind never removes a replacement). Also `snapshot()` (immutable copy), `slotForTerminal`, `profileForSlot`, `isSlot`. - **CallerResolver consumes the registry's live snapshot.** Bridged wires `architects::snapshot` in on both auth paths. Resolve order preserved: lead > architect > generic worker. The rest of #19's Role/Authz/Principal/whoami work is kept unchanged. - **Duplicate YAML slot keys now rejected.** Determined empirically that Jackson's YAML parser is last-wins on duplicate map keys (a duplicated `architects:` slot name silently dropped one slot). Added parse-time detection (`rejectDuplicateArchitectSlots` in `load`), scoped to the `architects:` block, failing with an `IllegalStateException` that names the duplicated slot. ## Tests Focused architect tests (ArchitectRegistry/Config/CallerResolver/Authz/BridgeMcp) plus new invariant + 2-concurrency tests for the registry and a duplicate-key config test. `mvn clean install` → **Tests run: 519, Failures: 0, Errors: 0, Skipped: 0; BUILD SUCCESS**. ## Residual - The `wiki/` Features entry for the architect registry is not updated here (worker cannot touch the wiki submodule) — recommend a follow-up feature entry. - Leftover `terminal:` under an `architects:` slot is silently ignored (record is `ignoreUnknown`); an upgrade note/test documents that it no longer binds anything.
agent added 2 commits 2026-08-13 18:07:48 +02:00
CB-548: config-declared architect slots + Role.ARCHITECT authz
CI / build (pull_request) Successful in 55s
CI / contract (pull_request) Successful in 1m6s
21cfc09f8e
CB-548: correct architect premise — profile-only slots, registry-owned bindings, dup-key rejection
CI / build (pull_request) Successful in 54s
CI / contract (pull_request) Successful in 1m6s
6123576c68
ltms added 1 commit 2026-08-13 18:31:32 +02:00
CB-548: make duplicate-architect-slot detection top-level-only and depth-safe
CI / contract (pull_request) Successful in 42s
CI / build (pull_request) Successful in 1m13s
f004a0c654
ltms merged commit 6dee84ca71 into main 2026-08-13 18:33:11 +02:00
Sign in to join this conversation.