Skip to content

security(state): reconverge publication roles after recovery - #217

Draft
seonghobae wants to merge 22 commits into
chatgpt/postgres-foundation-migrations-atomic-redfrom
chatgpt/postgres-publication-recovery-role-red
Draft

security(state): reconverge publication roles after recovery#217
seonghobae wants to merge 22 commits into
chatgpt/postgres-foundation-migrations-atomic-redfrom
chatgpt/postgres-publication-recovery-role-red

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Refs #80 #192 #208 #209 #210 #216. Draft child of exact #216@7c7b980b7a2f41e2a369a71bb32e945de7f30bfd.

Causal RED lineage

  1. Missing executable recovery boundary: test-only 3999f0583eddfe87bc07b7ef477998a66fefe246, hosted CI 34259899229 / rust 102174943790; checkout/toolchain/formatting passed, Test failed because deploy/postgresql/reputation_state_recovery.sql did not exist.
  2. Recovery-evidence bypass: formatted test-only 6a18312c9cc74d4b02daf54dc1033a4335a04a87, CI 34263214416 / rust 102186066201; real PostgreSQL 18.4 proved that after 0003 rollback/reapply, simply restoring runtime EXECUTE lets a later surviving generation publish with expected_prior = NULL and become a new first head while prior publication evidence/head is missing.
  3. Supported-shape recovery gap: formatted test-only 30bc7e77592b6b7cf4e861760aeea2af24f5fc50, CI 34264941085 / rust 102191822902; real PostgreSQL 18.4 failed from the complete 0002 predecessor because role convergence ran before migration 0003 existed (relation "public.reputation_source_publication" does not exist). Candidate 09c6b896898f0a98e83d36d6ca0d87ff7e8ade3c, CI 34265174608 / rust 102192601576, then proved client-side \quit 3 was not a reliable nonzero partial-shape refusal contract.

Minimum causal repair

deploy/postgresql/reputation_state_recovery.sql is a sequencer, not a second schema/role authority.

  • Complete 0002 (publication tables/function all absent) advances through canonical transactional migration 0003 via relative \ir.
  • Complete 0003 skips schema DDL.
  • Any mixed/partial publication table/head/function shape raises a PostgreSQL exception under ON_ERROR_STOP, returns nonzero, and remains untouched for diagnosis.
  • Positive cluster-role/grant/function-ownership truth stays single-sourced in canonical transactional reputation_state_roles.sql, invoked via relative \ir.
  • After owner/grant convergence, if any surviving generation-bearing (tenant_id, source_id) lacks an authoritative publication head, runtime outer-function EXECUTE is globally revoked. This prevents recovery from using the normal expected_prior = NULL first-publication path to skip rollback-removed last-known-good evidence.
  • Verified prior publication evidence is replayed only under controlled deployment/recovery authority. Rerunning the sequencer restores bounded runtime EXECUTE only after every such evidence gap is closed; runtime then advances only through exact-prior/monotonic publication.

Normal publication semantics remain unchanged. StateAuthority::Postgres remains fail closed.

Exact-current GREEN

Current exact head is 7a6cb5c55e7d440768792dfa3f750a1594ef3ebe. Fresh compare to exact #216 is ahead 22 / behind 0 with #216 as exact merge base. Parent-relative delta is exactly seven paths: recovery sequencer; three real PostgreSQL recovery regressions (owner, evidence-gap, supported-shape); Proposed recovery ADR; ADR index; Unreleased CHANGELOG.

Exact-current hosted CI 34265888259, rust 102195122469, is terminal SUCCESS on unchanged 7a6cb5c...: hosted ubuntu-24.04, exact checkout, pinned toolchain, formatting, all locked workspace tests including all PostgreSQL 18.4 recovery regressions, strict Clippy and cleanup passed. Fresh submitted reviews: 0. Fresh inline review threads: 0.

Parallel preservation lanes were repaired rather than discarded. #214's valid migration-atomicity delta is fully transferred to exact #216 and #214 is now closed as verified-successor transfer. #215's valid complete-0002/complete-0003 preflight, partial-state refusal and restartability delta is reconstructed here; its unsafe NULL-prior post-recovery behavior is positively disproved by the #217 hostile RED and was not transferred. #215 is now closed as verified-successor transfer.

Remaining boundary

Keep Draft behind #216. This slice does not provide production login/principal membership, application repository/transaction wiring, pooled transaction-local tenant-context checkout/reset, startup migration locking/version compatibility, crash/retry/idempotency, authoritative backup/restore of generation plus publication history/head with retention/encryption/RPO/RTO, readiness/degraded evidence, protected integration or immutable release evidence. Those remain #80/#192 work. No force update, destructive rebase, self/model approval, routine bypass, gate weakening, no-op workflow churn, mutable foreign dependency, source copy or cross-service SQL.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant