Skip to content

fix(persistence): close 0010 validation-to-trigger cutover race #622

Open

Description

@seonghobae

Finding

#619 introduced historical-state validation for 0010, but LiveDocumentRepository::apply_migrations applies catalog statements sequentially. A validation-before-trigger order therefore had a cutover race: a predecessor 0009 writer could commit invalid state after the scan and before admission enforcement. Holding a long explicit table lock across the scientific scan is the wrong operational trade-off for a potentially large membership table.

A first repair installed the trigger before validation, but review found a second retry gap: DROP TRIGGER; CREATE TRIGGER itself spans separate statements, so an idempotent retry after remediation could briefly commit without admission protection.

RED → causal repair

  • 84e5859a34a7864f06d74794bac2f6180ac05e97 moves retry-safe guard/RLS/function/trigger installation before the historical scan. Invalid predecessor data therefore fails validation while future writes remain protected;
  • live acceptance f471211abbce2503d51c503533d5d197f6c0b09e proves a failed underflow validation leaves the guard/trigger installed, rejects another invalid write, and succeeds on retry after explicit data-owner remediation;
  • no-gap RED 54bf6128333b6698c2926ed20b9945aa917ecf43 statically forbids the remaining DROP TRIGGER ...; CREATE TRIGGER retry pattern;
  • causal repair 10b07fcdf47f867e3c7b78ba1b8e8a2a668cc4b3 uses PostgreSQL 18 CREATE OR REPLACE TRIGGER, replacing the active trigger without a committed drop/create interval.

The guard table uses CREATE TABLE IF NOT EXISTS; policy/function definitions are retryable; historical validation runs last. No explicit long-running table lock, write-disable window, normalization, owner-invariant weakening, or manual DDL teardown is introduced.

Current authority

Surviving vehicle #615 is Draft/open/mergeable at exact 10b07fcdf47f867e3c7b78ba1b8e8a2a668cc4b3. Fresh exact-head Rust Foundation run 35463797907 is queued, so this lineage is not GREEN and predecessor receipts do not transfer. #622 remains open until hosted PostgreSQL 18 cutover/retry acceptance, exact-head quality/security gates, qualifying independent review, prerequisite reconciliation, and normal landing.

Refs #287, #604, #605, #615, #619, #620, #621.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions