v0.10.0
Status: Released
All roadmap items for v0.10 "Phase 13 — Safety Contract Repair & Multi-Project
Isolation" are complete. This release repairs the safety contract (lock lifecycle,
resume, heartbeat, scheduler pause ordering) and establishes the multi-project
isolation invariant required for shared PostgreSQL deployments.
What's new
Critical Correctness Fixes
-
C-01 / C-11: Consumer-only plans are no longer silently skipped as no-ops.
PlanSummarynow tracksconsumer_creates,consumer_drops, andconsumer_alters
separately;is_empty()andtotal_changes()include consumer deltas. All renderer
totals updated. -
C-03:
RecordSnapshotnow usesquery_onewithRETURNING versionto capture
the actual bigserial value assigned by the database instead of recording the planned
version number. -
C-04: Backfill steps are documented as "Triggered by pg_trickle on table
creation — no explicit wait" in renderers and log messages. -
C-05:
read_live_state()now populatessourcesby deserialising the latest
spec_jsonbfromaqueduct.dag_versionsinstead of always returningvec![]. -
C-06 / C-07:
read_live_state()andread_live_consumers()both accept an
optionalprojectparameter and filter results via the new
aqueduct.stream_table_ownershiptable.destroy_projectverifies ownership before
dropping any table; use--force-unownedto bypass. -
C-09:
check_pgtrickle_version()probesto_regprocedure(...)before calling
the function to avoid a database error when pg_trickle is absent. -
C-10:
classify_delta()no longer panics on missingdesired/actualin the
AlterQueryarm; returnsRebuildinstead. -
C-12:
read_live_state()project filter enablesdiff --from last-appliedand
diff --from desiredmodes.
Safety & Idempotency Fixes
-
S-01 / S-02: Failed migrations are now marked
recoverable_failureand can be
resumed. On resume,LockDagalways re-executes — DDL steps are only skipped for
steps already confirmed complete in the checkpoint. -
S-03: Scheduler pause now happens inside the
LockDagexecutor arm, after the
lock is acquired, preventing a pre-lock pause from affecting other projects. -
S-04: Heartbeat SQL is now holder-bound
(WHERE project = $1 AND holder = $2). Zero rows affected is detected and logged as
a lock-stolen warning. -
S-05: The project lock is released on all exit paths (success and error) via an
explicit cleanup block after the step loop. -
S-06: Step progress checkpoint writes are now fatal — a failed write returns an
error rather than silently continuing. -
S-07:
aqueduct apply --dry-runuses a plain connection (no catalog migration)
to avoid upgrading the schema during previews. -
S-10:
DROP TABLEfallback indestroyand the executor no longer uses
CASCADE. Dependent objects must be dropped manually; use--force-cascadeto
opt in. -
S-11:
aqueduct rollbacknow enforces the--accept-data-lossflag when the
rollback plan contains rebuild-class steps. -
S-12: First-time stream table creations increment
create_countand not
rebuild_count, preventing false-positive maintenance-window blocking on initial
deployments. -
S-13: Lock holder string is now
aqueduct/{version}/{hostname}/{pid}/{ts}
making concurrent processes distinguishable. -
S-14: Scheduler pause failure is now a fatal error by default.
Catalog Schema v3
- Added
aqueduct.stream_table_ownership(project, schema_name, table_name, managed_since)
table with aPRIMARY KEY (schema_name, table_name)constraint. status_checkconstraint onaqueduct.migrationsnow includesrecoverable_failure.- Auto-migration from v2 to v3 applied on
connect_and_migrate.
New Tests (6)
test_consumer_only_apply_end_to_end: consumer view create with no stream table changes.test_concurrent_apply_race: two applies, second getsLockContention.test_stale_plan_detection: plan from_version mismatch vs DB version.test_two_project_isolation: destroy project A, project B tables intact.test_resume_skips_non_safety_steps: LockDag always at index 0.test_heartbeat_lock_is_holder_bound: wrong holder returns 0 rows.