diff --git a/sw-block/design/v3-phase-15-g9f2-authority-request-bridge-mini-plan.md b/sw-block/design/v3-phase-15-g9f2-authority-request-bridge-mini-plan.md new file mode 100644 index 000000000..98a657179 --- /dev/null +++ b/sw-block/design/v3-phase-15-g9f2-authority-request-bridge-mini-plan.md @@ -0,0 +1,80 @@ +# V3 Phase 15 G9F-2 - Verified Placement To Authority Request Bridge Mini-Plan + +Date: 2026-05-02 +Status: first TDD slice implemented at `seaweed_block@05f0011`; product-loop wiring still requires §1.A acceptance +Branch target: `p15-g9f2/authority-request-bridge` +Scope: first bounded bridge from `VerifiedPlacement` to `authority.AssignmentAsk` + +## 0. Why This Gate Exists + +G9D/F closed the verify-only fact layer: + +```text +DesiredVolume + NodeInventory + PlacementIntent + Observation -> VerifiedPlacement +``` + +M01 needs the next edge: + +```text +VerifiedPlacement -> AssignmentAsk -> authority.Publisher -> AssignmentFact +``` + +This is the first authority-adjacent bridge. It must not become a shortcut where placement intent or heartbeat observation directly mints epoch/endpoint-version truth. + +## 1.A Architect Bindings + +Bindings used by the first TDD slice: + +1. **Bridge owner**: bridge code lives in `core/host/master` or another controller seam, not in `core/lifecycle`. +2. **Lifecycle purity**: `core/lifecycle` remains authority-free and must not import `core/authority`. +3. **Input condition**: only `VerifiedPlacement{Verified:true}` can produce asks. +4. **Negative condition**: placement-only and observation-only inputs produce no asks. +5. **Publisher seam**: bridge produces `authority.AssignmentAsk`; only `authority.Publisher` mints epoch and endpoint-version. +6. **No frontend shortcut**: bridge output does not imply `frontend_primary_ready`. +7. **Stop rule**: if this requires proto/control API changes, engine mode changes, or direct `AssignmentInfo` construction, stop and split a new gate. + +## 2. Algorithm Sketch + +For one verified placement: + +1. Reject if `Verified == false`. +2. For each verified slot: + - require `VolumeID`, `DataAddr`, and `CtrlAddr`; + - existing-replica slot must carry `ReplicaID`; + - blank-pool slot needs a controller-assigned replica id before it can emit an ask. +3. Emit `authority.AssignmentAsk` with: + - `VolumeID` + - `ReplicaID` + - observed `DataAddr` + - observed `CtrlAddr` + - `IntentBind` for first-close scope. +4. Do not call publisher from the bridge helper itself. + +First slice can reject blank-pool slots until a replica-id allocator is ratified. + +## 3. TDD Plan + +Red tests first: + +1. `TestG9F2_UnverifiedPlacementProducesNoAssignmentAsk` +2. `TestG9F2_VerifiedExistingReplicaProducesBindAsk` +3. `TestG9F2_AssignmentRequestShapeHasNoEpochOrEndpointVersion` +4. `TestG9F2_PlacementBridgeOutputPublishesThroughAuthorityPublisher` +5. `TestG9F2_LifecyclePackageDoesNotImportAuthority` + +## 4. Close Criteria + +G9F-2 first slice closes when: + +1. tests in §3 are green; +2. no `AssignmentInfo` construction is added outside the existing allowlist; +3. docs state that bridge output is an ask, not authority; +4. G9G product-loop mini-plan can start from a real `AssignmentAsk` producer. + +## 5. Non-Claims + +- No create-volume API. +- No blockvolume startup loop. +- No frontend readiness claim. +- No recovery/rebuild decision. +- No RF/quorum ACK policy change. diff --git a/sw-block/design/v3-phase-15-priority-mvp-plan.md b/sw-block/design/v3-phase-15-priority-mvp-plan.md index 83dcc0e96..2ae98b483 100644 --- a/sw-block/design/v3-phase-15-priority-mvp-plan.md +++ b/sw-block/design/v3-phase-15-priority-mvp-plan.md @@ -128,12 +128,13 @@ Do not use one boolean `Healthy` as the product state for all four concepts. `He P15-P0: Freeze and close G7 -> P15-P1: G7 follow-up hardening -> P15-P2: G8 failover data continuity [CLOSED 2026-05-02 for first-close scope] - -> P15-P3: G9 lifecycle product verbs - -> P15-P4: G9A flat placement / desired topology - -> P15-P5: G17-lite observability + G15a CSI MVP in parallel - -> P15-P6: internal K8s dogfood checkpoint - -> P15-P7: remaining beta gates by dogfood feedback - -> P15-P8: G22 final validation + -> P15-P3: G9D/F lifecycle facts and verified placement [DONE at phase-15@eeef486] + -> P15-P4: G9F-2 verified placement -> authority request bridge + -> P15-P5: G9G blockmaster product loop to publisher + -> P15-P6: G17-lite observability + G15a CSI MVP in parallel + -> P15-P7: internal K8s dogfood checkpoint + -> P15-P8: remaining beta gates by dogfood feedback + -> P15-P9: G22 final validation ``` This preserves the canonical gate graph while making the execution path concrete. @@ -252,7 +253,68 @@ This boundary prevents G7 from becoming an unbounded recovery rewrite while stil --- -### P15-P3 — G9 Volume Lifecycle +### P15-P3 — G9D/F Lifecycle Facts And Verified Placement — ✅ done + +**Goal**: master can persist desired volumes, persist node inventory, compute placement intent, intersect it with fresh observation, and expose `VerifiedPlacement` without granting authority. + +**Status**: done at `phase-15@eeef486`. + +**Proven**: + +1. desired volume records persist; +2. node inventory records persist; +3. placement reconciler writes non-authority placement intent; +4. verified placement requires fresh observation; +5. verified placement does not mint authority or mutate publisher state. + +**Non-claim**: no product assignment loop yet; no blockvolume becomes primary/replica from lifecycle alone. + +--- + +### P15-P4 — G9F-2 Verified Placement To Authority Request Bridge + +**Goal**: convert verified placement into bounded `authority.AssignmentAsk` values through a controller bridge, while preserving publisher-only authority minting. + +**Why this moved before lifecycle verbs**: an M01-usable product loop needs assignment publication before create/attach/delete can be meaningful. G9D/F already proved fact/readiness; the next missing link is `VerifiedPlacement -> AssignmentAsk -> Publisher`, not more verify-only lifecycle state. + +**Must ship**: + +1. bridge lives outside `core/lifecycle`; lifecycle remains fact/intent only; +2. bridge accepts only `VerifiedPlacement{Verified:true}`; +3. placement-only and observation-only inputs produce no asks; +4. blank-pool slots emit first-bind asks only when a replica id can be allocated by the bridge/controller; +5. existing-replica slots emit asks using the observed data/control addresses; +6. publisher remains the only epoch/endpoint-version author. + +**TDD first**: + +1. unverified placement produces no ask; +2. verified existing-replica placement emits `IntentBind` for first authority line; +3. bridge output has no epoch/endpoint-version fields; +4. running bridge output through real `authority.Publisher` mints exactly one authority line; +5. lifecycle package does not import authority. + +**Pass**: component test proves verified placement can request authority through the publisher seam, and negative tests prove neither placement intent nor observation alone can do it. + +--- + +### P15-P5 — G9G Product Loop To Publisher + +**Goal**: blockmaster can run the lifecycle/placement/verified-placement/authority-request loop without manual topology stuffing. + +**Must ship**: + +1. blockmaster opens lifecycle store and authority store; +2. reconcile loop computes verified placement; +3. bridge emits assignment asks into publisher directive; +4. blockvolume receives assignment via existing subscription path; +5. first L2 product-loop test shows automatic assignment after volume/node registration. + +**Pass**: subprocess L2 starts real blockmaster + blockvolume processes, registers product facts, observes assignment delivery, and reaches frontend-ready precondition without hand-authored assignment state. + +--- + +### Deferred From Original G9 Volume Lifecycle **Goal**: users/tools can create, attach, detach, and delete volumes without hand-authoring internal authority state.