Skip to content
Open
Show file tree
Hide file tree
Changes from 167 commits
Commits
Show all changes
183 commits
Select commit Hold shift + click to select a range
7616858
docs: add target architecture roadmap for pg-delta and pg-topo
jgoux Jun 12, 2026
fca2fc8
docs: rewrite target architecture as north-star technical optimum
jgoux Jun 12, 2026
1bf515b
docs: specify normalized fact model as the north-star state layer
jgoux Jun 12, 2026
2903635
docs: specify test architecture and strengthen the proof loop
jgoux Jun 12, 2026
61f88d1
docs: add integration policy layer and implementer guardrails
jgoux Jun 12, 2026
a9c127b
docs: address external review findings on north-star architecture
jgoux Jun 12, 2026
3af622e
docs: revise north star as clean-room library with full breaking changes
jgoux Jun 12, 2026
6a387a5
docs: add per-stage implementation guides and corpus-first stage 0
jgoux Jun 12, 2026
b9ab85f
docs(stage-09): specify declarative export with provable round-trip f…
jgoux Jun 12, 2026
c75a6b1
docs(stage-07): document the unorderable-input case and the ordering …
jgoux Jun 12, 2026
44be5b2
docs(stage-06): specify three-valued transactionality for the segment…
jgoux Jun 12, 2026
d7fc248
docs: final review pass — fix inconsistencies, close ownership gaps
jgoux Jun 12, 2026
5bd2253
feat(pg-delta-next): stage 1+4 core — identity codec, hashing, fact b…
jgoux Jun 12, 2026
febb256
feat(pg-delta-next): stage 2 extractor — core kinds, column-grain pg_…
jgoux Jun 12, 2026
8adac31
feat(pg-delta-next): stages 0+5+6 — corpus, rule table, one-graph pla…
jgoux Jun 12, 2026
86ca93f
feat(pg-delta-next): provePlan API, shadow-DB frontend, seeds, CI lane
jgoux Jun 12, 2026
34347ce
feat(pg-delta-next): full kind coverage + 195-scenario corpus port (3…
jgoux Jun 12, 2026
869018b
docs(pg-delta-next): consolidated PORTING.md ledger + README coverage…
jgoux Jun 12, 2026
cdac2d8
docs(pg-delta-next): remove per-agent porting ledgers (merged into PO…
jgoux Jun 12, 2026
f420077
fix(pg-delta-next): drive the corpus proof loop to 390/390 green
jgoux Jun 12, 2026
8819c5d
feat(pg-delta-next): implement stages 5-10 (execution, compaction, po…
jgoux Jun 13, 2026
1e5d5cc
refactor(pg-delta-next): close review gaps + lift per-kind policy int…
jgoux Jun 13, 2026
80baf02
feat(pg-delta-next): normalize composite-type attributes + publicatio…
jgoux Jun 13, 2026
742cfc3
test(pg-delta-next): convert open field issues to corpus scenarios; f…
jgoux Jun 13, 2026
766188d
docs(pg-delta-next): add extension-intent design and Linear issue ass…
jgoux Jun 13, 2026
322da44
feat(pg-delta-next): stop dropping pg_partman-managed partitions (CLI…
jgoux Jun 13, 2026
4ac54bb
feat(pg-delta-next): make the proof loop managed-extension aware
jgoux Jun 13, 2026
736e22b
docs(pg-delta-next): park the Phase B (intent replay) implementation …
jgoux Jun 13, 2026
20c906f
docs(pg-delta-next): hardening plan responding to the architecture re…
jgoux Jun 13, 2026
c107696
feat(pg-delta-next): project the plan target through policy filtering…
jgoux Jun 13, 2026
5e5bbe2
feat(pg-delta-next): proof reports coverage + content fingerprints (r…
jgoux Jun 13, 2026
96f343d
feat(pg-delta-next): typed policy predicates — edgeKind + idField val…
jgoux Jun 13, 2026
d3e7beb
fix(pg-delta-next): metadata satellites never outlive their target (r…
jgoux Jun 13, 2026
6ba281b
fix(pg-delta-next): commitBoundaryAfter unconditionally ends its segm…
jgoux Jun 13, 2026
6087b0b
fix(pg-delta-next): explicit per-file transaction in the shadow loade…
jgoux Jun 13, 2026
a83e081
docs(pg-delta-next): record shipped hardening items; scope 4b as dedi…
jgoux Jun 13, 2026
da9acf8
fix(pg-delta-next): proof schemaSig captures composite structure + ty…
jgoux Jun 13, 2026
24c2a3e
feat(pg-delta-next): default extension-member projection (4b Stage 0+1)
jgoux Jun 13, 2026
6c37415
feat(pg-delta-next): observe extension members in extractor (4b Stage 2)
jgoux Jun 13, 2026
a902d9f
feat(pg-delta-next): keep resolver collapse for member ordering (4b S…
jgoux Jun 14, 2026
7e7c031
docs(pg-delta-next): record 4b (provenance flip) shipped + gates green
jgoux Jun 14, 2026
166e7da
refactor(pg-delta-next): extract planner phases to internal module (I…
jgoux Jun 14, 2026
04381ad
docs(pg-delta-next): hardening plan complete — all 8 items shipped
jgoux Jun 14, 2026
ea5831e
docs(pg-delta-next): README reflects 4b (members observed + projected)
jgoux Jun 14, 2026
24e0532
test(pg-delta-next): prove SECURITY LABEL end-to-end via dummy_seclab…
jgoux Jun 14, 2026
aadbf87
docs(pg-delta-next): inventory of remaining work beyond the hardening…
jgoux Jun 14, 2026
1fd9937
docs(pg-delta-next): expand remaining-work into per-tier implementati…
jgoux Jun 14, 2026
e068f05
docs(pg-delta-next): canonical managed-view architecture
jgoux Jun 14, 2026
989e4cb
refactor(pg-delta-next): derive CREATE EXTENSION SCHEMA from extreloc…
jgoux Jun 14, 2026
09c4efe
refactor(pg-delta-next): extract shared fact-level projection primitive
jgoux Jun 14, 2026
8a4c19f
docs(pg-delta-next): reorder managed-view build sequence
jgoux Jun 14, 2026
ad66740
feat(pg-delta-next): resolveView — fold policy scope rules into the f…
jgoux Jun 14, 2026
5eafa7c
feat(pg-delta-next): owner-as-edge + edge→action, delete skipAuthoriz…
jgoux Jun 14, 2026
e750d3b
docs(pg-delta-next): refresh owner/serialize docs for the managed view
jgoux Jun 14, 2026
40f52e6
feat(pg-delta-next): applier-capability-restricted view (move 6)
jgoux Jun 14, 2026
e5450c3
feat(pg-delta-next): owner-residue capability fail-fast (follow-up 1)
jgoux Jun 14, 2026
2912cbd
feat(pg-delta-next): verify FDW-grant rule; keep Rule 9 (follow-up 2 …
jgoux Jun 14, 2026
02fcbad
feat(pg-delta-next): thread applier capability through the plan artif…
jgoux Jun 14, 2026
b1f4a42
docs(pg-delta-next): reframe remaining work as a correctness-first v1…
jgoux Jun 14, 2026
04abf8f
docs: reorganize into architecture/roadmap/archive and add rewrite ov…
jgoux Jun 15, 2026
6ae0304
test(pg-delta-next): live corpus progress + testcontainer reclaim script
jgoux Jun 15, 2026
a7e2036
feat(pg-delta-next): v1 correctness — unmodeled-kind detection, diagn…
jgoux Jun 15, 2026
3ddc973
test(pg-delta-next): add pg_depend edge-set oracle + statement-timeou…
jgoux Jun 15, 2026
22a2aaa
perf(pg-delta-next): set-based pg_depend resolver — 4.2x faster extra…
jgoux Jun 15, 2026
fe6a14a
docs(pg-delta-next): presentation-ready overview, memory roadmap, cor…
jgoux Jun 15, 2026
559e21e
test(pg-delta-next): regression tests + foreign-table corpus for the …
jgoux Jun 15, 2026
0770cf8
fix(pg-delta-next): address 2026-06-15 branch review (P0–P3)
jgoux Jun 15, 2026
71c983d
perf(pg-delta-next): reverse-index planner rebuild + bounded-concurre…
jgoux Jun 15, 2026
108c1db
refactor(pg-delta-next): split extractor by catalog family and rules …
jgoux Jun 15, 2026
d37e244
feat(pg-delta-next): support PostgreSQL 14 and 16
jgoux Jun 15, 2026
85e0ffd
fix(pg-delta-next): preserve ownership across accepted renames
jgoux Jun 15, 2026
1042bf7
test(pg-delta-next): pin proof violation .table to the relKey contract
jgoux Jun 15, 2026
3b83d73
refactor(pg-delta-next): structured table identity in ProofVerdict
jgoux Jun 15, 2026
62957b5
test(pg-delta-next): add failing regressions for the 2026-06-15 follo…
jgoux Jun 15, 2026
04ab587
fix(pg-delta-next): address 2026-06-15 follow-up review (P1 + docs)
jgoux Jun 15, 2026
3b55021
test(pg-delta-next): add failing regressions for the 2026-06-15 secon…
jgoux Jun 15, 2026
a37d14e
fix(pg-delta-next): address 2026-06-15 second follow-up review (P1 ow…
jgoux Jun 15, 2026
304ca67
test(pg-delta-next): add failing regressions for the 2026-06-16 third…
jgoux Jun 16, 2026
4282f2a
fix(pg-delta-next): carry role-name-bearing facts through accepted ro…
jgoux Jun 16, 2026
24a254c
test(pg-delta-next): add failing regressions for the 2026-06-16 fourt…
jgoux Jun 16, 2026
b4ef836
fix(pg-delta-next): carry role-name-bearing facts with changed payloa…
jgoux Jun 16, 2026
f8f24eb
test(pg-delta-next): add failing regression for redundant ACL-replace…
jgoux Jun 16, 2026
b8cd4f1
fix(pg-delta-next): elide redundant replace-drop in compaction (ACL d…
jgoux Jun 16, 2026
6f13da0
docs(pg-delta-next): spec for integration profile / managed-view unif…
jgoux Jun 16, 2026
5a26169
fix(pg-delta-next): resolveView projects out managedBy (single projec…
jgoux Jun 16, 2026
debb227
refactor(pg-delta-next): run extension handlers inside the extraction…
jgoux Jun 16, 2026
087e2d1
feat(pg-delta-next): integration profile unifying the managed view (P1)
jgoux Jun 16, 2026
d3e05c7
feat(pg-delta-next): CLI --profile for plan/apply/prove (P2)
jgoux Jun 16, 2026
d57b2b4
fix(pg-delta-next): scope loadSqlFiles DML check to managed user tabl…
jgoux Jun 16, 2026
21cde1c
docs(pg-delta-next): refresh managed-view + extension-intent for the …
jgoux Jun 16, 2026
846af66
test(pg-delta-next): end-to-end profile apply-gate regression + lint …
jgoux Jun 16, 2026
40fcdfe
fix(pg-delta-next): stamp the integration profile on the plan artifac…
jgoux Jun 16, 2026
fe1d497
docs(pg-delta-next): retarget Phase B roadmap onto the integration pr…
jgoux Jun 16, 2026
6e3372a
docs(pg-delta-next): reframe profile-less plans (not legacy artifacts)
jgoux Jun 16, 2026
9deb78e
test(pg-delta-next): add failing regression for procedure metadata/AC…
jgoux Jun 16, 2026
c9f254b
fix(pg-delta-next): split function/procedure stable ids so metadata r…
jgoux Jun 16, 2026
5cee6f0
test(pg-delta-next): add failing regression for CREATE ROLE config em…
jgoux Jun 16, 2026
a4ffb0e
fix(pg-delta-next): materialize role GUC config on CREATE ROLE
jgoux Jun 16, 2026
585ed40
test(pg-delta-next): add failing regression for security-label comple…
jgoux Jun 16, 2026
2997a9a
fix(pg-delta-next): complete security-label extraction + diagnose unm…
jgoux Jun 16, 2026
2788bba
test(pg-delta-next): add failing regression for profile-aware schema …
jgoux Jun 16, 2026
9af27f6
fix(pg-delta-next): make schema export/apply profile-aware
jgoux Jun 16, 2026
1d2d89c
refactor(pg-delta-next): extract ActionGraph phase from plan()
jgoux Jun 16, 2026
ff69c7b
refactor(pg-delta-next): extract ReplacementExpansion phase from plan()
jgoux Jun 16, 2026
95a797e
refactor(pg-delta-next): extract ChangeSet phase from plan()
jgoux Jun 16, 2026
7e6e3fe
refactor(pg-delta-next): extract ActionEmitter phase from plan()
jgoux Jun 16, 2026
d08a6c8
docs(pg-delta-next): refresh internal.ts header for the phased planner
jgoux Jun 16, 2026
4d0a202
test(pg-delta-next): add failing regression for deep-chain shadow loa…
jgoux Jun 16, 2026
cee094a
fix(pg-delta-next): scale shadow-load maxRounds with file count
jgoux Jun 16, 2026
38f11f7
docs(pg-delta-next): design for ephemeral/auto-provisioned schema-app…
jgoux Jun 17, 2026
60d8f63
docs(pg-delta-next): corpus-is-cheap agent guidance + archive profile…
jgoux Jun 17, 2026
62eb739
docs(pg-delta-next): restructure docs for the v1 PR
jgoux Jun 17, 2026
f530082
fix(pg-delta-next): capture view and table reloptions
jgoux Jun 17, 2026
4b24ac5
fix(pg-delta-next): exclude Supabase platform-managed extensions from…
jgoux Jun 17, 2026
d2cdbf7
fix(pg-delta-next): address Codex PR review (policy/domain/export)
jgoux Jun 17, 2026
3cdee21
ci(pg-delta-next): set least-privilege workflow permissions
jgoux Jun 17, 2026
1fbdc69
feat(pg-delta-next): capture full CREATE AGGREGATE option set
jgoux Jun 17, 2026
528bc60
feat(pg-delta-next): capture subscription replication options
jgoux Jun 17, 2026
ed1bcdd
feat(pg-delta-next): capture range-type subtype opclass and multirang…
jgoux Jun 17, 2026
a638ecf
feat(pg-delta-next): capture identity-column sequence options
jgoux Jun 17, 2026
0b3b5a7
fix(pg-delta-next): version-gate PG15+ subscription columns for PG14
jgoux Jun 17, 2026
790c840
feat(pg-delta-next): orderless declarative apply, grouped export, for…
avallete Jul 6, 2026
daf286e
Merge branch 'main' into feat/pg-delta-next
avallete Jul 6, 2026
5616ef1
fix(ci): build pg-topo before format-and-lint so oxlint-tsgolint reso…
avallete Jul 6, 2026
fff4087
feat(pg-delta-next): pg_cron intent, render command, and loadable pro…
avallete Jul 7, 2026
f9b6cbe
feat(pg-delta)!: promote clean-room engine as @supabase/pg-delta
avallete Jul 7, 2026
9e86439
chore(release): collapse pending changesets into one rewrite entry
avallete Jul 7, 2026
98e97b0
ci(pg-delta): replace legacy test machinery with the clean-room engin…
avallete Jul 7, 2026
9a12f5b
docs(pg-delta): retarget guidance and user-facing text to the promote…
avallete Jul 7, 2026
a7551e8
fix(pg-delta): fix build ordering and rehome dbdev fixture after the …
avallete Jul 7, 2026
9f982f7
chore(pg-delta): restore local coverage instrumentation and document …
avallete Jul 7, 2026
1f8b5b3
fix(pg-delta): replay pg_cron database/username/active via schedule_i…
avallete Jul 7, 2026
ada0ab5
docs(pg-delta): record PR #299 Codex engine-hardening backlog
avallete Jul 7, 2026
671a799
docs(pg-delta): record wave-2 Codex engine-hardening findings
avallete Jul 7, 2026
b8653e8
test(pg-delta): add failing regression for export of ext member under…
avallete Jul 7, 2026
5e26a52
fix(pg-delta): exclude extension members from the export pristine bas…
avallete Jul 7, 2026
bd68f7b
docs(pg-delta): record wave-3 Codex engine-hardening findings
avallete Jul 7, 2026
3f9f78b
docs(pg-delta): record wave-4 Codex engine-hardening findings
avallete Jul 7, 2026
08aec31
feat(pg-delta): export as source of truth — round-trip fidelity + pro…
avallete Jul 9, 2026
1c891a0
chore(release): re-collapse accumulated changesets into the rewrite e…
avallete Jul 9, 2026
6380022
fix(pg-delta): make schema apply --profile supabase work for non-supe…
avallete Jul 14, 2026
c84367b
fix(pg-delta): round-trip fidelity fixes from middleware export dogfo…
avallete Jul 16, 2026
4d887d3
chore(pg-delta): apply oxfmt formatting drift from #331 merge
avallete Jul 16, 2026
0d91055
docs(pg-toolbelt): warn against reverting formatter output to scope d…
avallete Jul 16, 2026
19618cd
fix(pg-delta): don't retain owner edges for policy-excluded roles
avallete Jul 16, 2026
122a79d
fix(pg-delta): review fidelity fixes — range guard, rule enabled, inh…
avallete Jul 16, 2026
673b574
Merge origin/main into feat/pg-delta-next
avallete Jul 17, 2026
1625773
fix(pg-delta): require @supabase/pg-topo alpha.3 for the reorder assist
avallete Jul 17, 2026
da2d75c
fix(pg-delta): role-drop fail-loud and in-place alter dependency orde…
avallete Jul 17, 2026
1a32341
Merge remote-tracking branch 'origin/main' into feat/pg-delta-next
avallete Jul 17, 2026
1af7df9
feat(pg-delta): export reusable schema frontends for CLI embedding
avallete Jul 17, 2026
6a895e5
fix(pg-delta): add pgdelta --version and schema --help (#342)
avallete Jul 17, 2026
13ca4db
fix(pg-delta): exported commands throw instead of process.exit
avallete Jul 17, 2026
529975e
fix(pg-delta): preserve column ACL keys across role renames
avallete Jul 17, 2026
4d98b7a
fix(pg-delta): enable createrole self-grant during shadow load
avallete Jul 17, 2026
137ed7a
style(pg-delta): oxfmt createrole self-grant changes
avallete Jul 17, 2026
f29fecf
fix(pg-delta): don't emit CREATE INDEX CONCURRENTLY for partitioned p…
avallete Jul 20, 2026
904064a
fix(pg-delta): parse column-qualified ACL ids in the stable-id codec
avallete Jul 20, 2026
8da191b
fix(pg-delta): loader user-mapping classification, snapshot profile s…
avallete Jul 20, 2026
2257c47
fix(pg-delta): safety batch — destructive flags, no-CASCADE revoke, o…
avallete Jul 20, 2026
d4b3e56
fix(pg-delta): version-gate the multi-grantor expected-red corpus pin
avallete Jul 20, 2026
43db742
fix(pg-delta)!: canonicalize extraction search_path to pg_catalog
avallete Jul 20, 2026
39b7638
fix(pg-delta): canonicalize the two identity-formatting paths F5 missed
avallete Jul 20, 2026
fd3e47e
fix(pg-delta): render session restore, honest prove coverage, extensi…
avallete Jul 20, 2026
9c9c81d
fix(pg-delta): agg metadata signatures, ESM-only exports, render prun…
avallete Jul 20, 2026
c471de5
fix(pg-delta): atomic sequence bounds, reorder parse guard, ACL dedup…
avallete Jul 20, 2026
d3f9162
fix(pg-delta): namespace-safe enum rebuild temp names; declared colum…
avallete Jul 20, 2026
bc0a817
fix(pg-delta): subscription safety, composite-attr ordering, cycle va…
avallete Jul 20, 2026
5d02a9e
fix(pg-delta): RESTART only on disjoint ranges, seclabel type-kind ro…
avallete Jul 20, 2026
a7fabcf
docs(pg-delta): add parallel agent-track briefs for architecture foll…
avallete Jul 20, 2026
03b6d69
docs(pg-delta): correct agent-track briefs after rename-mechanics fac…
avallete Jul 20, 2026
3c976f4
docs(pg-delta): round-3 agent-track amendments after adversarial cros…
avallete Jul 20, 2026
3a7c8f2
docs(pg-delta): round-4 agent-track amendments — contracts pinned for…
avallete Jul 20, 2026
b551829
docs(pg-delta): round-5 agent-track amendments — P2 defaults pinned, …
avallete Jul 20, 2026
36ee1e6
docs(pg-delta): link agent-tracks OVERVIEW tour from roadmap README
avallete Jul 20, 2026
e306775
docs(pg-delta): round-6 final editorial fixes — review closed, ready …
avallete Jul 20, 2026
fdbb7b4
chore(docs): update docs execute D0 from agent-roadmap (#348)
avallete Jul 20, 2026
732dd53
fix(pg-delta): avoid role rename policy dependency cycle (#349)
avallete Jul 21, 2026
7c52e79
docs(pg-delta): mark server replacement follow-up resolved (#352)
avallete Jul 21, 2026
cf80086
refactor(pg-delta): centralize managed view reconstruction (#351)
avallete Jul 21, 2026
a537d02
docs(pg-delta): document identity and ACL invariants (#353)
avallete Jul 21, 2026
a987a74
feat(pg-delta): report per-table autoSeed outcomes and enforce corpus…
avallete Jul 21, 2026
3dbf75c
test(pg-delta): backfill corpus seeds and support reverse-direction s…
avallete Jul 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .changeset/adp-owner-self-entry-roundtrip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@supabase/pg-delta": patch
---

Canonicalize the grantor's own default-privilege self-entry at extraction so `pg_default_acl` rows round-trip. For a PER-SCHEMA row, one built by explicit grants to the owner (`{owner=arwdDxtm/owner, other=…}`) and one built purely from grants to other roles (`{other=…}`, no owner entry) are behaviorally identical — Postgres re-adds the owner's `acldefault` entry to every new object at creation time regardless of the stored row. Previously the extractor emitted a spurious `revoked_default` marker for the owner whenever it was absent from the stored ACL, so re-exporting a replayed database produced a spurious `alter default privileges … revoke all … from <owner>` self-revoke. The owner's own revoked-default marker is now suppressed where its absence is a behavioral no-op (PUBLIC and other-role markers are unaffected; a partial owner self-reduction that differs from `acldefault` is still represented as a positive fact; a GLOBAL row where the owner's absence is a real revoke keeps its marker — see the companion global-self-revoke changeset).
5 changes: 5 additions & 0 deletions .changeset/adp-owner-self-revoke-global.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@supabase/pg-delta": patch
---

Extract a GLOBAL (cluster-wide) default-privilege owner self-revoke as a real `revoked_default` marker instead of silently dropping it. The previous canonicalization suppressed the grantor's own revoked-default marker unconditionally, which is only correct for per-schema rows (Postgres always re-merges the owner's `acldefault` entry at object creation) and for a bare global self-revoke with an empty stored ACL (the created object's relacl degenerates to NULL and the owner keeps its privileges). On a GLOBAL row that still carries other grantees (e.g. `alter default privileges for role alice revoke all on tables from alice; ... grant select on tables to bob` → `{bob=r/alice}`), Postgres uses the stored ACL verbatim at creation, so the owner really loses its own privileges — a genuine customization that must survive export/apply/reverse. The suppression is now conditional (per-schema and bare-empty-global stay no-ops; global-with-other-grantees emits the owner marker so the `revoke`/`grant` round-trips).
11 changes: 11 additions & 0 deletions .changeset/agg-sig-render-prune-strict-labels-enum-guard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@supabase/pg-delta": patch
---

Several correctness and packaging fixes:

- **Ordered-set aggregate metadata**: `COMMENT ON` / `SECURITY LABEL ON` an ordered-set or hypothetical-set aggregate now address it with the `agg(direct ORDER BY ordered)` signature (reusing the aggregate DDL's `aggSig`), instead of the flat argument list that PostgreSQL rejects at apply.
- **`render` prunes stale segments**: re-rendering a plan to the same `--out` base now deletes the previous render's segment files (`<base>.sql` / `<base>_<n>.sql`) that the new render no longer produces, so a runner scanning the directory can no longer replay obsolete (possibly destructive) segments. Only render-owned files matching that naming scheme are touched; foreign files are left in place.
- **`--strict-coverage` blocks unresolved security labels**: a valid `SECURITY LABEL` on an unsupported object (language / database / large object / tablespace) now escalates to a blocking diagnostic under `--strict-coverage`, matching `unmodeled_kind`, instead of silently producing an artifact that omits the label.
- **Enum value-set rebuild guard**: removing or reordering enum values while a non-column dependent (a `DOMAIN` over the enum, a `COMPOSITE` attribute using it, or a `RANGE` over it) survives now fails loudly at plan time. The rebuild only migrates column dependents, so such objects would otherwise leave the final `DROP TYPE` failing at apply. Full migration of non-column dependents remains out of scope.
- **ESM-only packaging**: removed the misleading `require` conditions from every `exports` entry. The package is `type: module` with a NodeNext build and ships no CommonJS output, so a `require` condition pointing at ESM was a false CJS signal (`ERR_REQUIRE_ESM` on Node <22). CommonJS consumers must use dynamic `import()`, or Node >=22 (which can `require()` ESM synchronously). ESM consumers are unaffected.
5 changes: 5 additions & 0 deletions .changeset/apply-owner-shadow-guard-and-absent-verbose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@supabase/pg-delta": patch
---

`schema apply` now (1) fails closed when an explicit `--shadow`'s connection role differs from the export's stamped default owner — the shadow would otherwise load omitted-`OWNER TO` objects as its own role and plan spurious ownership drift — and (2) treats a directory with no manifest default-owner record as verbose, honoring every explicit `OWNER TO` in the files instead of synthesizing a target default and pruning owner edges to it (which silently dropped an explicit owner change when the target object was owned by a different role).
20 changes: 20 additions & 0 deletions .changeset/canonical-search-path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@supabase/pg-delta": minor
---

Canonicalize the extraction session's `search_path` to `pg_catalog` (pg_dump
convention). Postgres deparsers (`format_type`, `pg_get_*def`, `pg_get_expr`)
path-relativize names, so any object visible on the session path previously came
back UNQUALIFIED — meaning the same catalog extracted under different search_paths
(e.g. a target database carrying `ALTER DATABASE … SET search_path`, versus a
freshly-created shadow with the default path) produced DIFFERENT payloads and
hashes, causing mass false drift in the shadow-vs-target compare and shifting
routine stable-ids. Extraction now pins the deparse path so identical catalogs
hash identically regardless of session/database/role path settings, and rendered
DDL is fully schema-qualified.

The plan preamble now also pins `search_path` to `pg_catalog` at apply time so
rendered DDL resolves identically regardless of the applier role's defaults.

`ENGINE_VERSION` is bumped to `0.2.0` (hash-invalidating): plan artifacts,
snapshots, and baselines captured before this change must be regenerated.
5 changes: 5 additions & 0 deletions .changeset/composite-attribute-order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@supabase/pg-delta": patch
---

Preserve composite type attribute order. The composite `CREATE TYPE … AS (…)` rule assembled attributes in encoded-id (name) order, silently reordering columns (e.g. `errors` before `wal`) on every reconstruction — a row-layout change that broke composite-returning dependents at body validation. The extractor now carries the declared attribute position (as the non-semantic `_position` payload key, excluded from hash/diff), and the composite create renders attributes in that order.
9 changes: 9 additions & 0 deletions .changeset/concurrent-indexes-partitioned.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@supabase/pg-delta": patch
---

The `concurrentIndexes` serialize option no longer inserts `CONCURRENTLY` for
indexes on partitioned tables. PostgreSQL rejects `CREATE INDEX CONCURRENTLY`
on a partitioned table's parent index (relkind `p`), so such a plan failed at
apply time. Those indexes are now created plainly (transactionally) while
indexes on regular tables keep the concurrent, non-transactional path.
5 changes: 5 additions & 0 deletions .changeset/createrole-self-grant-load.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@supabase/pg-delta": patch
---

`loadSqlFiles` enables `createrole_self_grant` on PG 16+ so a CREATEROLE non-superuser (Supabase `postgres`) can load `CREATE SCHEMA … AUTHORIZATION new_role`, and strips the resulting bootstrap memberships from the extracted fact base so plans do not emit a failing `GRANT … TO <applier> WITH ADMIN OPTION`. Assumed-schema seeding uses the same GUC on a dedicated pool client.
12 changes: 12 additions & 0 deletions .changeset/drop-role-no-drop-owned-by.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@supabase/pg-delta": patch
---

Fix role drop to no longer emit `DROP OWNED BY <role>` ahead of `DROP ROLE <role>`.
`DROP OWNED BY` swept up anything the role owned outside the managed/projected
view (objects the engine never extracted), silently destroying unmanaged data
when applying the plan. Managed grants, default ACLs, and owned objects are
already revoked/reassigned/dropped by their own plan actions before the role
drop runs, so a plain `DROP ROLE` succeeds when everything is managed, and now
Postgres fails loud ("role cannot be dropped because some objects depend on
it") instead of silently destroying data when unmanaged ownership remains.
7 changes: 7 additions & 0 deletions .changeset/enum-tempname-column-order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@supabase/pg-delta": minor
---

Enum value-set rebuilds now pick a namespace- and length-safe temp name for the old enum: the collision check consults every occupant of the type namespace (enums/composites/ranges, domains, and the implicit row types of tables/views/matviews/foreign tables/sequences), and the generated identifier is clipped to ≤ 63 bytes so PostgreSQL never truncates it back onto an occupied name.

Table `CREATE`s and schema exports now render columns in DECLARED order instead of alphabetical name order. Column position (`pg_attribute.attnum`) is captured at extract time as a non-semantic field, so a from-empty create/export reproduces the original `SELECT *`, positional-INSERT, and row-type layout; order-only differences on an existing table remain undiffed by design (the field is excluded from the fact hash and diff).
5 changes: 5 additions & 0 deletions .changeset/export-constraint-on-deferred-column.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@supabase/pg-delta": patch
---

Fix `schema export` folding a table constraint inline into `CREATE TABLE` when the column it references was deferred to a later `ALTER TABLE … ADD COLUMN` (a domain-typed column whose fold crosses the domain-create edge, or a generated column that never hints). The constraint fold pass bypassed the crossing guard for all constraints (to keep validated FKs to later-created tables foldable), which produced `CREATE TABLE … CONSTRAINT … UNIQUE (slug)` where `slug` was not yet a column, so the export failed to reload with `column "slug" named in key does not exist`. The guard now vetoes a constraint fold only when a same-table column of the fold target is deferred, while still tolerating crossings to other relations (an FK's referenced table, backing indexes/types elsewhere). Such constraints now render as standalone `ALTER TABLE … ADD CONSTRAINT`.
25 changes: 25 additions & 0 deletions .changeset/export-default-owner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
"@supabase/pg-delta": minor
---

`schema export` now serializes object ownership as `ALTER … OWNER TO` (an assumed
role reference, consistent with how ACLs already round-trip) instead of dropping
it at the default `--scope database`. Ownership is suppressed only for the
resolved DEFAULT owner so exports stay human-readable: the default resolves
`--default-owner <role|none>` (new flag) > the profile-declared default (Supabase
→ `postgres`) > the database owner (`datdba`). `--default-owner none` emits every
`OWNER TO` for maximum fidelity.

Previously, database-scope exports dropped all ownership, so objects owned by a
non-applier role (e.g. Supabase's `auth_admin`) reloaded applier-owned and then
showed up as spurious `ALTER … OWNER TO` / `REVOKE … FROM postgres` drift. This
now holds even when the database has extensions or assumed schemas present: the
managed view is rebuilt to attach reference-only marks in that case, and the
rebuild no longer silently re-prunes the retained owner references (which had made
a real Supabase export emit zero `OWNER TO`).

The export manifest stamps the resolved default owner (a role name, or `null` for
a verbose export; a field-absent directory is treated as pre-feature). `schema
apply` reconstructs the identical view and fails closed (exit 2) when the target
connection role differs from a role-name default. Policy-based owner exclusion is
unchanged.
11 changes: 11 additions & 0 deletions .changeset/export-identity-sequence-name.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@supabase/pg-delta": patch
---

`schema export` now emits `SEQUENCE NAME` for identity columns whose implicit
backing sequence name differs from the `<table>_<column>_seq` default (renamed
sequences, or ones created via `SEQUENCE NAME`). Previously the export rendered
a bare `GENERATED … AS IDENTITY`, so reload let PostgreSQL re-derive the default
name and the next diff produced a spurious `ALTER SEQUENCE … RENAME`. Renamed
identity sequences now round-trip cleanly; default-named identity columns stay
bare so ordinary exports remain minimal.
15 changes: 15 additions & 0 deletions .changeset/fix-owner-edge-policy-exclusion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"@supabase/pg-delta": patch
---

Fix policy hard-exclusion laundering an excluded owner role back into the plan.
`excludeFactsAndDescendants` no longer mints a dangling `owner -> role` edge for
a role that THIS exclusion removes (it only preserves edges that were already
dangling on input, the seed-rebuild case). Previously a policy-excluded role
retained its owner edge, was auto-assumed in `plan.ts`, and re-emerged as
`CREATE SCHEMA … AUTHORIZATION <role>` / `OWNER TO <role>` while silencing the
missing-requirement guard. Now the guard correctly fires when a kept object's
ACL (or ownership) references a policy-excluded role. Also fixes the
"typo'd function body is caught by re-validation" test to opt into
`strictFunctionBodies` (a user-routine body-lint is a warning by default under
lenient function bodies).
11 changes: 11 additions & 0 deletions .changeset/foreign-server-extension-subpartition-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@supabase/pg-delta": patch
---

Fix five round-trip fidelity gaps in the planner:

- Multi-level partitions keep their own `PARTITION BY` clause, so a partition that is itself partitioned can have sub-partitions attached.
- Removing a foreign server `VERSION` (which has no `ALTER SERVER` grammar) now routes to a drop + recreate instead of crashing planning.
- `ALTER EXTENSION … SET SCHEMA` is no longer emitted for non-relocatable extensions; relocation is planned as a drop + recreate in the new schema.
- Zero-argument aggregate `COMMENT` / `SECURITY LABEL` targets render `name(*)` instead of the invalid `name()`.
- Replacing a foreign server that has dependent foreign tables / user mappings now drops and recreates those children around the replace (the parent `DROP SERVER` does not cascade), instead of failing on the surviving dependents.
5 changes: 5 additions & 0 deletions .changeset/in-place-alter-consumes-releases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@supabase/pg-delta": patch
---

Make in-place `ALTER` actions participate in the plan's dependency walk by declaring `consumes`/`releases` on four rule sites, so they no longer sort before the `CREATE` of a new dependency or after the `DROP` of an old one. Column `TYPE …` changes now consume the new column type and release the old one; `ALTER EXTENSION … SET SCHEMA` releases the old schema; sequence `OWNED BY` reassignment releases the old owning column; and `ALTER POLICY … TO` consumes newly-listed roles and releases removed roles. Previously each of these could be emitted against a not-yet-created target ("type/relation/policy does not exist") or block a same-plan `DROP` of the object it stopped referencing.
5 changes: 5 additions & 0 deletions .changeset/issue-333-domain-enum-array-notvalid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@supabase/pg-delta": patch
---

Three planning fixes from issue #333: (1) a domain whose `baseType`/`collation` change is a drop+recreate — the planner now fails loud at plan time (instead of emitting a plan Postgres rejects at apply) when a surviving table column still depends on the domain, mirroring the existing in-use range-type guard. (2) An enum value-set rebuild (removal/reorder) migrated every dependent column with a scalar `col::text::<enum>` cast regardless of the column's own declared type; an `enum[]` column now casts correctly (`TYPE <enum>[] USING col::text[]::<enum>[]`) instead of erroring or silently narrowing to scalar. (3) A constraint's `validated` attribute going from `true` to `false` (VALIDATED → NOT VALID) threw `constraint cannot be de-validated in place` instead of planning a fix; it now replaces the constraint (`DROP CONSTRAINT` + `ADD CONSTRAINT … NOT VALID`), matching how `create()` already renders a fresh NOT VALID constraint.
7 changes: 7 additions & 0 deletions .changeset/lenient-function-bodies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@supabase/pg-delta": minor
---

`schema apply` (and the `loadSqlFiles` loader) now treat a USER routine whose body fails the post-load `check_function_bodies = on` re-validation as a loud WARNING instead of a fatal error. Postgres itself accepts such a function under `check_function_bodies = off` — which pg-delta's own apply executor emits in every plan preamble — so refusing to READ back a function pg-delta would happily WRITE was an asymmetry that blocked round-tripping any schema relying on check-off (legacy forward references, tolerated casts, etc.). The warning still flows through the diagnostics output loudly; the load now proceeds and apply faithfully materializes exactly what was declared. Pass `--strict-function-bodies` (loader option `strictFunctionBodies: true`) to restore the fatal gate for CI.

Seeded/reference-only routine failures are unchanged (still a warning) and now carry the distinct `invalid_seeded_routine_body` code so they can be told apart from user-routine failures. Changing an assumed-schema routine (a new overload, or a `CREATE OR REPLACE` that alters the body of a seeded routine) still fails loud, because assumed-schema facts are reference-only in the diff and such a change would otherwise be a silent no-op.
9 changes: 9 additions & 0 deletions .changeset/loader-snapshot-baseline-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@supabase/pg-delta": patch
---

Three fixes to the SQL loader, snapshot metadata, and baseline subtraction:

- **Loader:** `CREATE|ALTER|DROP USER MAPPING …` statements are no longer misclassified as cluster-global role DDL. The role-lifecycle scanners now use a `user(?!\s+mapping)` negative lookahead, so database-scope `schema apply` accepts (and `--skip-cluster-ddl` no longer strips) the user mappings pg-delta itself emits in foreign-data exports.
- **Snapshots:** `pgdelta snapshot` now stamps the profile it was captured under (a declared id, `null` for a raw capture, or absent for pre-feature legacy snapshots — never folded into the digest). `drift` and `prove` reconcile that stamp against any `--profile` flag: an omitted flag adopts the stamped profile, a contradicting flag fails closed with an actionable error, and a legacy (un-stamped) snapshot keeps the previous behavior with a one-line note.
- **Baseline subtraction:** `subtractBaseline` now compares each fact's outgoing-edge signature alongside its payload hash, so an equal-payload fact whose ownership/provenance edge changed (e.g. `OWNER` A→B) is no longer subtracted and pruned away invisibly. Owner→role edges to subtracted platform roles are retained as dangling assumed references so ownership still serializes.
11 changes: 11 additions & 0 deletions .changeset/non-superuser-extract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@supabase/pg-delta": patch
---

Fix `extract()` failing with `permission denied for table pg_user_mapping` when connecting as a non-superuser: user mappings now fall back to the world-readable `pg_user_mappings` view (with a warning diagnostic, since the view hides options the role isn't authorized on). Mappings whose options the view hides from the current role are skipped with that diagnostic instead of being recorded with fabricated empty options. `plan()` now refuses to plan changes touching a user mapping whose state was unreadable (and therefore unknown) on either side, instead of silently emitting a wrong CREATE/DROP USER MAPPING.

The unreadable-user-mapping diagnostic now survives extension-handler profiles (e.g. Supabase) instead of being silently dropped by the handler-triggered fact-base rebuild. Snapshots now carry `FactBase.diagnostics` (excluded from the digest), so the `plan()` gate still fires when one side is a deserialized snapshot rather than a live extraction; old snapshots without this field simply remain ungated, same as before. The gate itself now also refuses a `DROP SERVER` or `DROP ROLE` that would implicitly destroy a hidden mapping, not just a direct change to the mapping itself.

`pgdelta drift` now surfaces diagnostics carried by the snapshot side; the plan gate also covers replace-class server changes (`server.type`/`server.fdw`, which have no in-place ALTER and would otherwise silently drop-and-recreate the server, destroying an unreadable mapping's server, instead of throwing).

`pgdelta prove` now surfaces diagnostics carried by the desired snapshot and annotates a passing proof with their count.
7 changes: 0 additions & 7 deletions .changeset/non-superuser-extraction.md

This file was deleted.

Loading
Loading