G5-5C addendum: inscribe INV-G5-FRONTEND-CAPACITY-FROM-DURABLE-CONFIG

Per architect ruling 2026-04-28 + sw addendum landing at
seaweed_block@a250b52: inscribe new INV in the ledger.

Statement: iSCSI/NVMe externally-visible volume capacity and block
size MUST derive from --durable-blocks × --durable-blocksize when
--durable-root is set, not silently fall back to frontend defaults
(DefaultVolumeBlocks=2048 × DefaultBlockSize=512 = 1 MiB). Without
this plumb-through, a daemon configured for N MiB durable storage
advertises a 1 MiB iSCSI/NVMe LUN and any workload above LBA 256
fails.

Test pointers: cmd/blockvolume/frontend_capacity_test.go (6 tests:
ProductOfBlocksAndBlockSize, RejectsZero, OverflowGuard,
IscsiHandlerCapacity, NvmeHandlerCapacity, FrontendDefaults_
StillReturn1MiB). Source-side: cmd/blockvolume/main.go::
computeFrontendVolumeSize flows into both iscsi.TargetConfig and
nvme.TargetConfig handler.

First introduced: P15 G5-5C addendum (P0 product fix).
Owner layer: host (binary, frontend wiring).
Last verified: 2026-04-28 (G5-5C addendum P0; m01 hardware re-
verification pending QA).
Status: ACTIVE.

Awaiting m01 hardware re-run for full §close ledger update.
This commit is contained in:
pingqiu
2026-04-27 23:19:32 -07:00
parent 9a2c939b9a
commit a5c39fde34
+1
View File
@@ -109,6 +109,7 @@ IDs are **append-only**. If an invariant is retired, move its row to §6 (archiv
| `INV-BIN-WIRING-LISTENER-LIFECYCLE-LIFO` | `ReplicaListener` Stop runs BEFORE durable storage close in `cmd/blockvolume/main.go` shutdown chain (LIFO with construction). Listener borrows `LogicalStorage` from `DurableProvider`; tearing down storage first would race with in-flight handler conns | P15 G5-4 | host (binary lifecycle) | `cmd/blockvolume/g5_4_l2_replication_test.go:TestG54_BinaryWiring_RoleSplit_2NodeSmoke` (TCP dial on replica's `--data-addr` succeeds during host lifetime — pins the listener IS bound during the data-addr window). Source-side check: `cmd/blockvolume/main.go` shutdown block — `replListen.Stop()` before `durableProv.Close()` | 2026-04-27 (G5-5 §close — Tier 2 m01 cross-node hardware Integration backstop: `seaweed_block@5c4718f` rounds 1-14 surfaced + verified the binary-wiring chain end-to-end; G5-4 close pinned at component+subprocess scope, G5-5 upgrades to real-hardware) | ACTIVE |
| `INV-BIN-WIRING-ASSIGNMENT-DRIVES-MEMBERPRESENT` | Binary doesn't fake `MemberPresent`; it waits for first `AssignmentFact` with `fact.ReplicaID == self.ReplicaID` to set it via the engine apply path. Replica role (no self-named fact) keeps `MemberPresent=false` indefinitely (correct: replica isn't frontend-primary-write-ready) | P15 G5-4 | engine + host (binary) | `cmd/blockvolume/g5_4_l2_replication_test.go:TestG54_BinaryWiring_RoleSplit_2NodeSmoke` (replica's status response shows `Healthy=false` even after 10s — pins MemberPresent never flips for replica role; primary's `Healthy=true` pins MemberPresent flips on self-named fact). Backstop: `core/engine/apply.go:applyAssignment` test coverage in `apply_test.go` | 2026-04-27 (G5-5 §close — Tier 2 m01 cross-node hardware Integration backstop: `seaweed_block@5c4718f` rounds 1-14 surfaced + verified the binary-wiring chain end-to-end; G5-4 close pinned at component+subprocess scope, G5-5 upgrades to real-hardware) | ACTIVE |
| `INV-BIN-WIRING-SESSIONID-VIA-ADAPTER` | Binary path mints sessionIDs ONLY through `core/adapter` (process-wide `sessionIDCounter atomic.Uint64` at `adapter.go:70`); MUST NOT bypass adapter with hardcoded sessionIDs the way component-framework shortcuts (`WithLiveShip`, `CatchUpReplica`) do. Adapter-routed dispatch is the production path; framework shortcuts are test conveniences with a known sessionID-collision gap (T4c §I carry; QA G5-1 round 1 SKIP). Pinning this invariant ensures the gap stays test-side | P15 G5-4 | adapter | `cmd/blockvolume/main.go` (binary path: peer-set updates flow through `replication.UpdateReplicaSet` → `ReplicaPeer` → `BlockExecutor` calls dispatched by `adapter.VolumeReplicaAdapter`, which mints fresh sessionIDs at every dispatch site). Source-side check: `cmd/blockvolume/main.go` does not import `core/replication/component` (mini-plan v0.4 §7.1 #2 fence). Backstop: `core/adapter/adapter.go:70` declares `sessionIDCounter` with file-local visibility; only `adapter.go:353,359,377,392,402` mint via `Add(1)` | 2026-04-27 (G5-5 §close — Tier 2 m01 cross-node hardware Integration backstop: `seaweed_block@5c4718f` rounds 1-14 surfaced + verified the binary-wiring chain end-to-end; G5-4 close pinned at component+subprocess scope, G5-5 upgrades to real-hardware) | ACTIVE |
| `INV-G5-FRONTEND-CAPACITY-FROM-DURABLE-CONFIG` | iSCSI/NVMe externally-visible volume capacity and block size MUST derive from the daemon's `--durable-blocks` × `--durable-blocksize`, not silently fall back to frontend defaults (`DefaultVolumeBlocks=2048` × `DefaultBlockSize=512` = 1 MiB). Without this plumb-through, a daemon configured for N MiB durable storage advertises a 1 MiB iSCSI/NVMe LUN and any workload above LBA 256 fails | P15 G5-5C addendum (P0 product fix) | host (binary, frontend wiring) | Unit: `cmd/blockvolume/frontend_capacity_test.go:TestComputeFrontendVolumeSize_ProductOfBlocksAndBlockSize` (5 cases incl. 256 MiB), `TestComputeFrontendVolumeSize_RejectsZero`, `TestComputeFrontendVolumeSize_OverflowGuard`, `TestIscsiHandlerCapacity_FromDurableConfig`, `TestNvmeHandlerCapacity_FromDurableConfig` (capacity round-trip via `iscsi.NewSCSIHandler` / `nvme.NewIOHandler`), `TestFrontendDefaults_StillReturn1MiB` (negative-control documenting the bug shape). Source-side check: `cmd/blockvolume/main.go::computeFrontendVolumeSize` flows into both `iscsi.TargetConfig.Handler.{BlockSize, VolumeSize}` and `nvme.TargetConfig.Handler.{BlockSize, VolumeSize}`. Hardware: m01 scale-sequential (1000 LBAs × 4 KiB = 4 MiB) verified at G5-5C addendum hardware re-run | 2026-04-28 (G5-5C addendum P0 — surfaced by QA scale-sequential test on `seaweed_block@712cbc47`; fixed at `seaweed_block@a250b52`; m01 hardware re-verification pending QA on this tree) | ACTIVE |
> **The table above is a schema seed.** P15 QA establishment populates it fully from the four sources listed in §2, cross-referenced with [`v3-semantic-constraint-checklist.md`](./v3-semantic-constraint-checklist.md).