> **See also:** [ROADMAP.md](../ROADMAP.md)

## v1.0.0 — Stability Contract

**User promise:** *"The product is now boring and dependable."*

**Goal:** First officially supported release. Semantic versioning locks in.
API, catalog schema, and GUC names are considered stable. Focus is
distribution and trust: getting pg_trickle onto package registries, shipping
signed artifacts and SBOMs with provenance, and proving the supported
PostgreSQL 18 lifecycle paths.

The stable contract is:

> Supported query shapes either match PostgreSQL or fall back or suspend with
> an explicit reason. Schema evolution, backup, restore, cloning, upgrade,
> restart, and CDC failure have defined and tested behavior. Resource use is
> bounded, throttled, or reported with a forecast and reaction. Stable
> monitoring and diagnostic interfaces expose those decisions, and CI gates
> correctness, upgrades, and performance.

### The real 1.0 gate

Packaging and signing are necessary but not sufficient. The gate that actually
decides whether 1.0 ships is:

> **No known correctness issues, and boring upgrades.**

After the v0.94.0 feature freeze, v0.95.x accepts only bug fixes,
documentation, tests, compatibility work, packaging, performance regression
fixes, and simplification. It also narrows or removes unproven optimizer and
controller behavior before the release-candidate series.

That period is a **release-candidate series**, not a gap. `v1.0.0-rc.1` ships
when every gate below is believed met; each subsequent `rc.N` ships when a
blocker found by an rc user is fixed. 1.0.0 is tagged when an rc has been in the
field with no new blocker. Going straight from a feature freeze to a stability
contract with no candidate in users' hands is how a 1.0 acquires the bugs it
promised not to have.

| Gate | Condition |
|------|-----------|
| G1 | Zero open correctness defects. Every known DVM limitation is either fixed or documented in `docs/DVM_SUPPORT_MATRIX.md` with a proven FULL fallback and a reason code. |
| G2 | Upgrade from every supported prior version, on every supported PostgreSQL version, with an active workload — green, unattended, and documented. |
| G3 | `pg_upgrade` across a PostgreSQL major version with active stream tables and a non-empty change buffer — green. |
| G4 | 72-hour soak with schema changes, restarts and failure injection — zero correctness deviations, no unbounded growth. |
| G5 | Published benchmarks (write-path overhead, refresh throughput, TPC-H/Nexmark) enforced as blocking regression gates. |
| G6 | Documentation matches reality: every `#[pg_extern]` documented, every user-facing GUC justified, every claim in the README reproducible from a shipped test. |
| G7 | API, catalog schema, GUC, monitoring, and package surfaces remain compatible with the frozen v0.94.0 feature baseline. |
| G8 | At least one release candidate has been published and used, with no unresolved blocker reported against it. |

### Explicit non-goals

v1.0 does not require:

- incremental support for every PostgreSQL window frame
- distributed execution or cross-cluster federation
- external delta-compute fan-out or object-storage state
- autonomous control of every execution setting
- optimal cost-based planning for every DVM operator composition
- support for every PostgreSQL extension interaction
- removal of the correctness-preserving FULL fallback

> **Note on effort estimates.** The hour figures below cover release
> engineering only. G1–G8 are not estimated in hours because they are
> conditions, not tasks: their cost is however long it takes for the soak, the
> upgrade matrix and the rc series to come back clean. Do not read the
> "~46–86 hours" total as the cost of reaching 1.0.

### PostgreSQL 19 Forward-Compatibility (A3) — **not a 1.0 blocker**

> **In plain terms:** When PostgreSQL 19 beta stabilises and pgrx ships PG 19
> support, this milestone audits every internal `pg_sys::*` API call for
> breaking changes, adds conditional compilation gates, and validates the WAL
> decoder against any pgoutput format changes introduced in PG 19.
>
> **This is explicitly removed from the 1.0 gate.** PG 19 GA and pgrx PG 19
> support are both outside this project's control; making them blocking means
> the stability contract for PG 18 users — which is finished work — is held
> hostage to someone else's schedule. PG 19 support ships in the first minor
> release after pgrx supports it, as v1.1.0 or a v1.0.x if it turns out to be
> additive.

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| A3-1 | pgrx PG 19 support (the crate is already pinned at `=0.18.0`; this is a PG-target addition, not the version bump the earlier plan described) + `cargo pgrx init --pg19` | 2–4h | [PLAN_PG19_COMPAT.md](plans/infra/PLAN_PG19_COMPAT.md) §2 |
| A3-2 | `pg_sys::*` API audit: heap access, catalog structs, WAL decoder `LogicalDecodingContext` | 8–16h | [PLAN_PG19_COMPAT.md](plans/infra/PLAN_PG19_COMPAT.md) §3 |
| A3-3 | Conditional compilation (`#[cfg(feature = "pg19")]`) for changed APIs | 4–8h | [PLAN_PG19_COMPAT.md](plans/infra/PLAN_PG19_COMPAT.md) §4 |
| A3-4 | CI matrix expansion for PG 19 + full E2E suite run | 4–8h | [PLAN_PG19_COMPAT.md](plans/infra/PLAN_PG19_COMPAT.md) |

> **A3 subtotal: ~18–36 hours**

### Release engineering

> **In plain terms:** The 1.0 release is the official "we stand behind this
> API" declaration — from this point on the function names, catalog schema,
> and configuration settings won't change without a major version bump. The
> practical work is getting pg_trickle onto standard package registries
> (PGXN, apt, rpm) so it can be installed with the same commands as any
> other PostgreSQL extension, and hardening the CloudNativePG integration
> for Kubernetes deployments.

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| R1 | Semantic versioning policy + compatibility guarantees | 2–3h | [PLAN_VERSIONING.md](plans/infra/PLAN_VERSIONING.md) |
| R2 | apt / rpm packaging (Debian/Ubuntu `.deb` + RHEL `.rpm` via PGDG) | 8–12h | [PLAN_PACKAGING.md](plans/infra/PLAN_PACKAGING.md) |
| R2b | PGXN `release_status` → `"stable"` (flip one field; PGXN testing release ships in v0.7.0) | 30min | [PLAN_PACKAGING.md](plans/infra/PLAN_PACKAGING.md) |
| R3 | ~~Docker Hub official image~~ → CNPG extension image | ✅ Done | [PLAN_CLOUDNATIVEPG.md](plans/ecosystem/PLAN_CLOUDNATIVEPG.md) |
| R4 | ~~CNPG operator hardening (K8s 1.33+ native ImageVolume)~~ ➡️ Pulled to v0.15.0 | 4–6h | [PLAN_CLOUDNATIVEPG.md](plans/ecosystem/PLAN_CLOUDNATIVEPG.md) |
| R5 | **Docker Hub official image.** Publish `pgtrickle/pg_trickle:1.0.0-pg18` and `:latest` to Docker Hub. Sync Dockerfile.hub version tag with release. Automate via GitHub Actions release workflow. | 2–4h | — |
| R6 | **Version sync automation.** Ensure `just check-version-sync` covers all version references (Cargo.toml, extension control files, Dockerfile.hub, dbt_project.yml, CNPG manifests). Add to CI as a blocking check. | 2–3h | — |
| SAST-SEMGREP | **Elevate Semgrep to blocking in CI.** CodeQL and cargo-deny already block; Semgrep is advisory-only. Flip to blocking for consistent safety gating. Before flipping, verify zero findings across all current rules. | 1–2h | [PLAN_SAST.md](plans/testing/PLAN_SAST.md) |
| OTL-1 | **OpenTelemetry tracing spans.** Add `pgtrickle.refresh`, `pgtrickle.cdc_capture`, and `pgtrickle.snapshot` spans via the OTel SDK so every pg_trickle operation is visible to OTel collectors. Minimum viable: trace_id propagation through the refresh pipeline; attribute set = `stream_table`, `refresh_mode`, `rows_processed`. | 4–8h | [PLAN_OVERALL_ASSESSMENT_3.md](plans/PLAN_OVERALL_ASSESSMENT_3.md) §9.6 |
| SIGN-1 | **Cosign-sign GHCR release images.** Add `cosign sign` step to the GitHub Actions release workflow for `trickle-labs/pg-trickle`, `trickle-labs/pgtrickle-relay`, and `pg_trickle-ext` GHCR images. Attach Rekor transparency log entry. Document `cosign verify` command in `SECURITY.md`. | 2–4h | [PLAN_OVERALL_ASSESSMENT_3.md](plans/PLAN_OVERALL_ASSESSMENT_3.md) §9.11 |
| SIGN-2 | **Publish SBOMs for extension and release artifacts.** Generate CycloneDX or SPDX SBOMs for the extension tarball, relay binary, and release images; attach them to GitHub releases and document how operators verify them. | 2–4h | [PLAN_OVERALL_ASSESSMENT_8.md](plans/PLAN_OVERALL_ASSESSMENT_8.md) §10 |
| SIGN-3 | **Attach provenance attestations to release workflows.** Emit SLSA-style provenance or equivalent signed attestations for published binaries and images so operators can verify how each artifact was built. | 2–4h | [PLAN_OVERALL_ASSESSMENT_8.md](plans/PLAN_OVERALL_ASSESSMENT_8.md) §10 |
| MDB-1 | **Promote G17-MDB multi-database soak test to `ci.yml`.** The `stability-tests.yml` G17-MDB job runs multi-database scenarios in isolation. Move it to `ci.yml` under the "Push to main" trigger alongside the existing soak test. Gate it on a 30-min wall-clock budget for PR CI; use the full 2-hour run on schedule. | 2–3h | [PLAN_OVERALL_ASSESSMENT_3.md](plans/PLAN_OVERALL_ASSESSMENT_3.md) §9.10 |

> **v1.0.0 total: ~46–86 hours** (incl. PG 19 compat ~18–36h + release engineering ~18–30h + OTel/signing/SBOM/provenance/MDB ~12–20h)

**Exit criteria:**
- [ ] G1–G8: the stability-contract gates above are all met
- [ ] At least one `v1.0.0-rc.N` published, with no unresolved blocker
- [ ] Published on PGXN (stable) and apt/rpm via PGDG
- [ ] Docker Hub image published (`pgtrickle/pg_trickle:1.0.0-pg18` and `:latest`)
- [x] CNPG extension image published to GHCR (`pg_trickle-ext`)
- [x] CNPG cluster-example.yaml validated (Image Volume approach)
- [ ] `just check-version-sync` passes and blocks CI on mismatch
- [ ] SAST-SEMGREP: Semgrep elevated to blocking in CI; zero findings verified
- [ ] OTL-1: OTel refresh/CDC/snapshot spans emitted; visible in Jaeger test run
- [ ] SIGN-1: All GHCR release images cosign-signed; `cosign verify trickle-labs/pg-trickle:1.0.0` passes
- [ ] SIGN-2: SBOMs are published for release tarballs, relay, and release images
- [ ] SIGN-3: Provenance attestations are published and verification is documented
- [ ] MDB-1: G17-MDB soak test runs in `ci.yml` on push to main; green
- [ ] Upgrade path from v0.30.0 tested
- [ ] Semantic versioning policy in effect
- [ ] A3 / PG 19: tracked, but **not** blocking this release

---
