Bridge persistence and enrollment atomicity¶
The BridgePersistenceAdapter is the narrow PostgreSQL boundary for Bridge
identity and enrollment state. The phase-1 authenticated HTTP enrollment
transport in bridge_transport.py calls the adapter on the request-owned
transaction connection. (The in-memory BridgeIdentityRegistry and
BridgeEnrollmentService contracts that preceded it were never used by the
server and have been removed.)
Stored data¶
The adapter stores only:
- project and Bridge identity metadata;
- lifecycle status and allowed account references;
- challenge identifiers, public-key fingerprints, expiry and consumed time;
- SHA-256 hashes of challenge nonces.
- SHA-256 hashes of one-time bootstrap credentials and opaque Bridge tokens.
It never accepts or stores private keys, raw nonces, signatures, raw access tokens, or provider credential payloads. The transport verifies the Ed25519 proof before asking the adapter to activate a Bridge and inserts only the token hash in the same transaction.
Atomic activation¶
The enrollment proof route calls
consume_and_activate_with_token_in_transaction on the request's own
transaction connection, after the transport has verified the Ed25519 proof.
In that one transaction it:
- locks the project-scoped Bridge identity with
SELECT ... FOR UPDATE; - locks the project-scoped challenge with
SELECT ... FOR UPDATE; - rejects missing, mismatched, revoked, non-pending, consumed or expired state;
- sets
consumed_atexactly once; - activates the pending identity with the account references stored on the challenge;
- inserts the hash of the new Bridge access token.
The route then binds the Bridge to the project in the same transaction. The request commits all of these together or none of them. If any step fails, the challenge stays unconsumed and the identity stays pending. A second request cannot consume the same challenge after the first successful activation because the identity is no longer pending and the row locks serialize concurrent transactions.
consume_and_activate is an older variant that owns its own transaction,
takes the account references as an argument and mints no token. The server
does not call it; only the adapter's tests do.
The adapter fences every lookup and update with project_id. A Bridge ID or
challenge from another project is not visible through this contract. The
bootstrap credential carries approved account references; the Bridge cannot
choose those references in its request.
Migrations¶
013_bridge_identities.sql, 014_bridge_enrollment_challenges.sql and
015_bridge_enrollment_transport.sql hold this state. The server uses this
adapter for every Bridge enrollment. The exact HTTP contract is documented in
Bridge enrollment HTTP contract.