# v0.68.0 Full Details — Assessment-13 Correctness & Durability Sprint > **Summary:** [v0.68.0.md](v0.68.0.md) > **Assessment source:** [plans/PLAN_OVERALL_ASSESSMENT_13.md](../plans/PLAN_OVERALL_ASSESSMENT_13.md) --- ## Motivation The v0.67.0 overall assessment (Assessment 13) found 36 findings across the codebase. This release resolves the subset of HIGH-severity findings where a code defect produces silent data loss, audit integrity loss, or incorrect operator-visible behaviour. The principle is: fix the bugs before delivering more features. The six items resolved here were selected because: - COR-001 leaves fused refresh completely invisible in the audit history. - COR-003/ARCH-001 makes a documented GUC a no-op, which is a lie to operators. - COR-004 silently destroys timestamp values in the DuckLake export path. - SCAL-001 keeps dead code that would break on activation. - TEST-003 and TEST-004 are the verification gates for the above fixes. --- ## Detailed Implementation ### COR-001: Fused Refresh Audit Trail **Files changed:** - `sql/pg_trickle--0.67.0--0.68.0.sql` — add `'SCHEDULER_FUSED'` to the `initiated_by` CHECK constraint; add `merge_strategy` column to `pgt_refresh_history` - `sql/pg_trickle--0.68.0.sql` — full schema update - `src/scheduler/mod.rs` — pass `Some("SCHEDULER_FUSED")` to `RefreshRecord::insert()`; convert audit insert errors to `pgrx::warning!` plus abort the tick - `src/catalog.rs` — add `merge_strategy: Option<&str>` to `RefreshRecord`, extend `insert()` accordingly - `tests/e2e_refresh_tests.rs` — new `test_fused_refresh_scheduler_audit_trail` - `tests/common/mod.rs` — add `SCHEDULER_FUSED` and `fused_chain` to harness schema **Acceptance criteria:** 1. `cargo test -p pg_trickle -- test_fused_refresh_scheduler_audit_trail` passes. 2. The upgrade migration applies cleanly on a database with existing `pgt_refresh_history` rows. 3. `just test-integration` passes with zero new failures. --- ### COR-003 / ARCH-001: `change_buffer_durability` Wired **Files changed:** - `src/config.rs` — add deprecation warning to `pg_trickle_unlogged_buffers()`; map old bool to `ChangeBufferDurability` at read time - `src/cdc/mod.rs` — replace `pg_trickle_unlogged_buffers()` call with `pg_trickle_change_buffer_durability()` in `create_change_buffer_table()` and `create_st_change_buffer_table()`; handle `Sync` variant - `docs/GUC_CATALOG.md` — deprecate `unlogged_buffers`; document migration path to `change_buffer_durability` - `tests/e2e_unlogged_buffer_tests.rs` — add `test_change_buffer_durability_*` tests; mark existing bool tests as testing the backward-compat shim **Acceptance criteria:** 1. `SET pg_trickle.change_buffer_durability = 'unlogged'` creates a buffer with `relpersistence = 'u'`. 2. `SET pg_trickle.change_buffer_durability = 'logged'` creates a buffer with `relpersistence = 'p'`. 3. `SET pg_trickle.unlogged_buffers = true` emits a `WARNING` and maps to `change_buffer_durability = 'unlogged'`. --- ### COR-004: DuckLake Timestamp Fix **Files changed:** - `src/ducklake_sink.rs` — `fetch_stream_table_rows()`: detect `timestamp`/`timestamptz` type OIDs and emit `EXTRACT(EPOCH FROM "col"::timestamptz) * 1000000` in the SELECT list; `write_parquet_bytes()`: parse the fetched value as `i64` directly - `tests/e2e_ducklake_tests.rs` — new `test_ducklake_sink_timestamp_roundtrip` that creates a stream table with a `timestamptz` column, inserts a known value, triggers a sink write, reads the Parquet output file with the Arrow reader, and asserts the timestamp value is preserved **Acceptance criteria:** 1. The round-trip test passes. 2. NULL columns remain NULL; non-NULL timestamps map to the correct microsecond epoch. --- ### SCAL-001: Pool Path Deletion **Files changed:** - `src/scheduler/pool.rs` — deleted - `src/scheduler/mod.rs` — remove `mod pool` and any `use pool::` references - `plans/adrs/PLAN_ADRS.md` — add ADR-004 documenting the pool-worker design decision and explaining why dynamic workers are the sole supported path **Acceptance criteria:** 1. `cargo build` with no new warnings. 2. `just test-unit` passes. --- ### TEST-003: Scheduler-Driven Fused Refresh E2E **Files changed:** - `tests/e2e_refresh_tests.rs` — new `test_fused_refresh_scheduler_audit_trail`: wait for scheduler dispatch, query `pgt_refresh_history`, assert valid `initiated_by`/`merge_strategy` --- ### TEST-004: Durability Mode E2E Tests **Files changed:** - `tests/e2e_unlogged_buffer_tests.rs` — three new test functions --- ## Upgrade Notes ```sql -- Run the upgrade migration: ALTER EXTENSION pg_trickle UPDATE TO '0.68.0'; -- Migrate any application code that mirrors the old CHECK constraint: -- Old: CHECK (initiated_by IN ('SCHEDULER','MANUAL','INITIAL','SELF_MONITOR')) -- New: CHECK (initiated_by IN ('SCHEDULER','MANUAL','INITIAL','SELF_MONITOR','SCHEDULER_FUSED')) ``` The `pg_trickle.unlogged_buffers` GUC continues to work and is still valid; the only visible change is a `WARNING` message in the PostgreSQL log advising migration to `pg_trickle.change_buffer_durability`. No action is required before v1.0. --- ## Implementation Status | ID | Title | Status | |----|-------|--------| | COR-001 | Fused refresh audit trail — add `SCHEDULER_FUSED` to CHECK constraint | ✅ Done | | COR-003 / ARCH-001 | `change_buffer_durability` GUC wired into CDC buffer creation | ✅ Done | | COR-004 | DuckLake timestamp NULL fix — microsecond-epoch serialisation | ✅ Done | | SCAL-001 | Pool path deleted (`pool.rs` removed, ADR-024 written) | ✅ Done | | TEST-003 | Scheduler-driven fused refresh E2E audit trail test | ✅ Done | | TEST-004 | Durability mode E2E tests (unlogged / logged / legacy shim) | ✅ Done | --- ## Exit Criteria - [x] All P0 items ✅ Done - [x] `just test-unit` passes (2305 tests) - [x] `just lint` passes with zero warnings - [x] `just check-version-sync` exits 0 - [x] CHANGELOG.md entry written - [ ] ROADMAP.md v0.68.0 row marked ✅ Released