Repository navigation
fix(persistence): validate pre-existing membership share budgets on 0010 upgrade #619
Description
Finding
Migration 0010_membership_same_role_share_budget must prove that rows persisted before 0010 are reconstructable by the Membership owner. Two predecessor states are otherwise schema-admissible but owner-invalid:
- a positive
NUMERICweight admitted by0006/0009that underflows to binary64 zero (for example1e-10000), although Membership scientific(membership): reject zero-share active affiliations #613 requires a strictly positive represented binary64 share; and - overlapping same-member/same-role rows whose exact represented binary64 shares exceed one at a common event-time state, including the scientific(membership): make same-role share-budget admission exact at the binary64 boundary #612 boundary case.
The earlier live contracts reset to an empty database and tested only post-0010 writes, so they could not detect invalid pre-existing state.
Required acceptance
Upgrade from the canonical embedded predecessor through 0009, seed pre-existing data while it is still predecessor-admissible, then require 0010 to fail closed for:
- one positive
NUMERICthat becomes binary64 zero; - an ordinary overlapping same-role overrun such as
0.75 + 0.5; - the scientific(membership): make same-role share-budget admission exact at the binary64 boundary #612 binary64-boundary counterexample;
- the duplicate temporal-edge case refined by fix(persistence): preserve Membership duplicate-edge temporal invariant #621.
Positive controls must preserve exact unity, disjoint event-time spells, role separation, pointwise-valid spanning membership, and bounded/unbounded/open/closed temporal ranges.
Do not rewrite 0006/0009, normalize/clamp legacy rows, or fabricate membership mass. Remediation of invalid historical data requires explicit product/data-owner action.
Cutover rule after #622
#622 supersedes the earlier idea of validating historical rows before installing the trigger. Because the repository applies migration statements sequentially, that ordering has a validation-to-trigger write race. The successor must install retry-safe fail-closed admission first, then perform the expensive historical scan. Therefore an invalid predecessor dataset fails the migration while leaving future writes protected; explicit remediation can then be followed by an idempotent retry without dropping the gate.
Current ordinary-forward candidate lineage on #615:
- upgrade RED/acceptance
44e310839bcc24bcefc503db4777b899614120de; - pointwise historical validator
aa43c6520f71744504c703bd853a97a53571341f; - duplicate-edge refinement
98abb27c7c5a29f4ec4ea7502375987cdea84035; - retry-safe trigger-before-validation repair
84e5859a34a7864f06d74794bac2f6180ac05e97; - protected failed-upgrade + remediation/retry live contract
f471211abbce2503d51c503533d5d197f6c0b09e; - no-gap retry trigger contract
54bf6128333b6698c2926ed20b9945aa917ecf43→CREATE OR REPLACE TRIGGERrepair10b07fcdf47f867e3c7b78ba1b8e8a2a668cc4b3.
Refs #604, #605, #610, #612, #613, #614, #615, #616, #617, #618, #620, #621, #622.
Activity
fix(persistence): enforce pointwise membership share budgets (#619 #620)
fix(persistence): rollback pointwise membership helpers (#619 #620)
test(persistence): verify 0010 legacy-state upgrade admission (#619)
test(persistence): verify protected retryable membership cutover (#619 …