Skip to content

feat(notary): move correctness state to PostgreSQL#364

Merged
jeremi merged 35 commits into
mainfrom
agent/notary-postgresql
Jul 16, 2026
Merged

feat(notary): move correctness state to PostgreSQL#364
jeremi merged 35 commits into
mainfrom
agent/notary-postgresql

Conversation

@jeremi

@jeremi jeremi commented Jul 16, 2026

Copy link
Copy Markdown
Member

Summary

  • replace every production Notary correctness-state path with typed, Notary-owned PostgreSQL schemas and transactions
  • preserve replay, generation-safe nonce consumption, evaluation and batch idempotency, credential status, machine and subject quotas, and preauthorization semantics across replicas, restarts, restore, and adjacent-major upgrades
  • add isolated owner/runtime roles, schema fingerprinting, fail-closed startup and readiness checks, encrypted sensitive state, live key attestation, and production adapter recovery probes
  • remove the production Redis dependency, configuration, images, and compatibility paths atomically
  • add implementer-facing Registry project authoring, concise configuration, diagnostics, and operations guidance
  • document the bounded execution specification, retention, backup/restore, recovery, and PostgreSQL upgrade procedures

Why

Registry Stack 1.0 needs one understandable production state topology. Keeping Notary correctness state across Redis and process-local stores added operational dependencies and left multi-instance behavior ambiguous. This change gives each Notary an explicit PostgreSQL-owned state boundary while keeping Relay and Notary schemas, migrations, transactions, and readiness separate.

This is an intentional pre-1.0 breaking cutover. Removed Redis and legacy state configuration does not retain compatibility aliases.

Security and correctness notes

  • Notary does not reuse Relay tables or migrations.
  • State is modeled as fixed domain transactions rather than an opaque generic framework.
  • Only genuinely identical low-level PostgreSQL connection and TLS mechanics are candidates for later Relay/Notary sharing.
  • Nonces use generation-safe, exactly-once consumption semantics.
  • Sensitive preauthorization state is encrypted with bounded retention and verified key availability.
  • Startup and readiness fail closed on unavailable, read-only, misconfigured, incompatible, wrongly permissioned, or semantically drifted databases.
  • Restore verification covers every typed domain and decrypts sensitive state through the production adapter.

Validation

  • cargo fmt --all -- --check
  • cargo metadata --locked --format-version 1
  • cargo check --locked --workspace --all-targets
  • cargo clippy --locked --workspace --all-targets -- -D warnings
  • cargo test --locked --workspace
  • cargo deny check
  • Notary just ci-preflight
  • PostgreSQL conformance on 16, 17, and 18
  • logical 16 to 17 and 17 to 18 upgrade paths
  • multi-instance, lost-ack, process restart, database restart, logical restore, and readiness-negative proofs
  • production Docker image build
  • docs tests and full current/archived/link checks
  • source-built six-authority Solmara smoke with down/up persistence
  • eSignet plugin Maven suite and browser-driven UserInfo integration journey
  • independent PostgreSQL, state-security, semantic-boundary, and final code reviews with no unresolved P1/P2 findings
  • DCO sign-off audit for every branch commit

The source-built Solmara results are integration evidence, not proof that the currently published v0.8.4 images support the new commands. Fresh-clone implementer verification is intentionally sequenced after this PR: publish one Registry Stack tag containing #355 and #364, atomically repin Solmara PR #9, run its smoke/restart/reader gates, merge it, then update the public tutorial against protected solmara-lab/main.

Post-1.0 follow-ups

Closes #356

jeremi added 25 commits July 15, 2026 00:03
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c331f14012

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/registry-notary-server/src/preauth_state.rs Outdated
Comment thread crates/registry-notary-server/src/standalone/assembly.rs
jeremi added 3 commits July 16, 2026 20:12
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
jeremi added 5 commits July 16, 2026 20:13
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
jeremi added 2 commits July 16, 2026 20:52
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c56e38ac3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +343 to +344
let scope_hash = self.keys.replay_scope_hash(scope);
let jti_hash = self.keys.identifier_hash(JTI_IDENTIFIER_CONTEXT, jti);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep preauth replay keys stable across key rotation

For PostgreSQL-backed no-PIN pre-authorized codes (tx_code_required=false), the replay row is the only durable one-time-use state after redemption, but both the replay scope and JTI hashes here are derived from REGISTRY_NOTARY_SENSITIVE_STATE_KEY. If that key is rotated while a no-PIN code JWT is still unexpired, activation does not reject the rotation because there is no live login or tx-code row for that code, and a previously redeemed code is looked up under different hashes and can be redeemed again to mint another access token. Use a replay hash that is stable across sensitive-state key rotations, or persist/attest key generation for no-PIN code JTIs as well.

Useful? React with 👍 / 👎.

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.

Notary: move production correctness state to PostgreSQL and remove Redis

1 participant