# v0.82.0 — Frontier and CDC Durability Gate

> **Status:** Implemented; release gates pending environment-backed validation
> **Scope:** Very Large
> **Driven by:** August 2026 pre-scaling hardening review
> **Renumbered:** previously planned as v0.81.1. It changes user-visible
> behaviour — differential refresh now fails closed on missing CDC state,
> scheduler fusion is disabled by default, and unknown
> `change_buffer_durability` values are rejected instead of silently downgraded
> — which does not belong in a patch release.

## Theme

Eliminate every known path that can acknowledge, discard, or advance past a
committed source change without first making that change durable and visible.
This is a stop-the-line correctness release: the product arc (v0.86.0 onward)
cannot begin until the frontier, CDC, crash-recovery, and refresh-finalization
invariants below are proven under concurrency.

## Sequencing

v0.82.0 and [v0.83.0](v0.83.0.md) are strictly ordered: DVM semantics are only
meaningful once the frontier that feeds them is trustworthy.
[v0.84.0](v0.84.0.md) (catalog/privilege/upgrade) and [v0.85.0](v0.85.0.md)
(scheduler/resource) touch disjoint subsystems and may be developed in parallel
with this release; only their *release order* is fixed, so a stall in one gate
does not idle the others.

## Non-Goals

- No new CDC backend or transport.
- No external workers.
- No throughput optimization that weakens committed-change durability.

## Items

### DUR-81-1: One Safe Frontier Contract

Replace raw current-LSN capture in manual refresh paths with the same safe
upper-bound contract used by scheduled refreshes. The holdback probe must cover
both `backend_xid` and `backend_xmin`, prepared transactions, and first-tick or
restart behavior. Probe failure and an unknown initial bound fail closed rather
than advancing to the current write LSN.

The coordinator-captured bound becomes immutable job input, scoped by database
and dispatch tick. Dynamic workers must never read a cluster-global watermark
that another database scheduler can overwrite.

### DUR-81-2: Snapshot-Aligned FULL Refresh

Establish FULL refresh source positions from the same protected snapshot that
materializes the stream table. Manual and scheduled FULL refreshes must either
lock source writes while establishing the snapshot/bound or use an equivalent
snapshot-safe protocol. A transaction that is invisible to the FULL query may
not be included in its stored frontier.

### DUR-81-3: WAL Consumption Without Blind Fast-Forward

Remove direct replication-slot advancement to `pg_current_wal_lsn()` after a
FULL refresh. Retained WAL may be released only after events are decoded into a
durable shared change buffer or a snapshot-aligned proof shows that every
dependent stream table materialized them.

Make WAL-to-trigger fallback an ordered cutover: block source DML, install
trigger capture, drain through a defined LSN, switch catalog state, then remove
WAL resources. If the drain cannot be proven, force every dependent stream
table through FULL reinitialization.

### DUR-81-4: Missing CDC State Fails Closed

A missing, truncated, malformed, or inaccessible required change buffer is not
a zero-row differential refresh. Return a typed error, preserve the previous
frontier, repair CDC infrastructure, and require a successful FULL
reinitialization before differential refresh resumes.

### DUR-81-5: Common Refresh Finalization

Route normal differential, FULL fallback, TopK, and fused scheduler execution
through one correctness finalizer. It must atomically handle frontier storage,
`last_refresh_at` and `data_timestamp`, downstream stream-table CDC capture,
buffer cleanup, refresh history, outbox delivery, cost summaries, and
post-refresh actions.

Disable scheduler fusion by default until a fused chain passes the same
finalization contract. Approximate metadata is not acceptable for a successful
refresh.

### DUR-81-6: Honest Buffer Durability Modes

Implement the documented `sync` behavior, including effective
`synchronous_commit = on` for change-buffer writes. Reject unknown
`change_buffer_durability` values instead of mapping them to `unlogged`, and
make code, GUC descriptions, and documentation agree on the crash-safe default.

Replace empty-table inference for UNLOGGED crash recovery with a durable crash
generation or sentinel. New post-restart writes must not hide loss of older
buffer rows, and a clean restart with an empty buffer must not trigger a false
loss report.

## Release Gate

v0.82.0 will not ship until all of the following pass:

- Idle READ COMMITTED writer, prepared transaction, first-tick, restart, and
  writer-replacement tests prove that no invisible row is acknowledged.
- A slow FULL refresh with concurrent commits converges for one stream table and
  for two stream tables sharing the source.
- Manual and scheduler refreshes pass the same long-transaction matrix.
- WAL FULL refresh and WAL-to-trigger cutover tests account for every committed
  event before slot advancement or resource removal.
- Dropping a required buffer preserves the frontier and causes repair plus FULL
  reinitialization.
- TopK and fused-chain tests prove downstream propagation, metadata completion,
  and bounded buffers.
- A postmaster crash with pending UNLOGGED changes followed immediately by new
  DML forces safe resynchronization.

Any unexplained source-versus-stream-table mismatch is a release blocker.
