Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 14 additions & 23 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,41 +489,32 @@ All database access. Uses `sqlx::query()` (runtime, not compile-time macros) —
- Approval tokens: `create_approval` receives the raw token and hashes it internally with SHA-256.
- DDL injection protection in partition manager: allowlist of table names + strict suffix/date validators.

### Supported Writer Contract (transition state)

The repository is moving toward a **supported-writer contract** where relay-owned
write APIs provide the only supported mutation path for tenant data. The current
shape is an explicit transition, not a flag day:

- **Trajectory:** converge from trigger/function/FK-enforced fencing toward
application-owned transaction protocols, while keeping existing DB backstops
in place until coverage and fleet gates are proven.
- **Community fence (transition foundation):** runtime admission APIs now offer
one shared community deletion lock per transaction, while deletion lifecycle
transitions take the matching exclusive lock. A supported serving transaction
never spans communities. Serving leases use the same application admission.
Startup and deletion catalog validation tolerate the universal fence objects
being absent; inventories still record live fences for older executors.
### Supported Writer Contract

Relay-owned write APIs provide the supported mutation path for tenant data:

- **Community fence:** supported serving writers admit each tenant transaction
through the runtime API, which takes one shared community deletion lock and
checks active, undeleted state. Deletion lifecycle transitions take the
matching exclusive lock. A serving transaction never spans communities.
The universal per-table write-fence triggers and their functions have been
retired after writer coverage and fleet gates; the community tombstone guard
remains.
- **Replica floor (transition foundation):** runtime now provides a shared
replica-floor lock helper for compliant channel-event writers, and the writer
probe handshake takes the exclusive counterpart before sampling `S`, scanning
activity, and committing the heartbeat token last. `probe_once` remains the
sole token/fence-wall publication path; there is no separately persisted active
floor cutoff. Commit-time trigger+GUC enforcement remains authoritative for all
paths.
- **Dual enforcement (current):** application-owned lock+precheck paths run in
front of the existing trigger/function enforcement; commit-time trigger checks
remain authoritative during this phase. Removing those backstops is a separate
gated migration, after every pod tolerates their absence and no rollback below
that version is expected.
- **Role separation:** relay/runtime code owns admission and lock protocols;
operator maintenance/backfill workflows must either use those protocols or run
under explicit reviewed procedures that keep routing fences closed.
- **Unsupported shape:** direct owner SQL that bypasses supported transaction and
lock protocols is not a supported write path.
- **Fleet gates and reconciliation:** startup/fence probes verify guard catalog +
behavior, pgschema bootstraps run reconciliation, and lock/pool metrics remain
the operational evidence path for rollout safety.
- **Fleet gates and reconciliation:** startup probes verify the remaining guard
catalog and behavior, pgschema bootstraps run reconciliation, and lock/pool
metrics remain the operational evidence path for rollout safety.

**Does NOT:** cache queries, implement connection pooling logic (delegated to sqlx), or make network calls outside Postgres.

Expand Down
8 changes: 4 additions & 4 deletions crates/buzz-db/src/runtime/admitted_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ use crate::Result;
/// statements on it, and [`AdmittedTx::commit`] and [`AdmittedTx::rollback`]
/// are the only ways it can end the transaction. Inside the crate, the
/// `conn()` accessor hands statements the connection; the type can't stop
/// crate code from issuing a raw `COMMIT` through it, so the database
/// community write fences remain the backstop while deployed. Internal writers
/// must preserve this boundary and use `commit()` for staged follow-up work.
/// Dropping the value without committing rolls back, as with [`sqlx::Transaction`].
/// crate code from issuing a raw `COMMIT` through it. Internal writers must
/// preserve this transaction boundary and use `commit()` for staged follow-up
/// work. Dropping the value without committing rolls back, as with
/// [`sqlx::Transaction`].
///
/// These are live regressions for the guarantee. Event-write helpers accept an
/// admitted transaction:
Expand Down
Loading
Loading