You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(db): #1464 (Phase B) composite-aware engine — shared_schema FK/UNIQUE parity
The #1431 migration engine's snapshot was lossy: FKs per-column ({col: table}),
composite UNIQUE(tenant_id,id) flattened to a column set, indexes non-deduped. So
a shared_schema intra-tenant ref produced a simple (fk)→Parent(id) FK +
UNIQUE(id) + a bogus UNIQUE(tenant_id), and composite list indexes could
double-emit (DuplicateTable at upgrade).
schema_snapshot.project_schema now reads table-level ForeignKeyConstraints
(cols→reftable+refcols) + UniqueConstraint column-tuples + a deduped index set
(extracted to _table_fks/_table_uniques/_table_index_keys helpers, keeping CC<15);
schema_diff op models carry composite columns (+ _coerce_fks/_coerce_uniques
backward-compat for legacy embedded snapshots); schema_render emits the composite
FK/UNIQUE (was hard-coded ["id"]). Cross-tenant referential integrity
(tenant_id, fk)→Parent(tenant_id, id) is now enforced by the migration-built
schema, not just create_all.
Removed the #1464 xfail; baseline + new incremental-revision parity oracles GREEN
on real PG (now composite-aware via an independent pg_catalog read).
Adversarial review caught a CRITICAL FK-name mismatch (sa_schema fk_{entity}_{field}
vs engine fk_{entity}_{partition_key}_{field}) → aligned sa_schema so both paths
name composite FKs identically; + name-alignment regression test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+7-1Lines changed: 7 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
10
10
## [Unreleased]
11
11
12
-
## [0.85.1] - 2026-06-24
12
+
## [0.85.2] - 2026-06-24
13
+
14
+
### Fixed
15
+
- **#1464 (Phase B — engine fix) `db baseline` now reproduces shared_schema composite tenant-scoped constraints with full `create_all` parity.** The #1431 migration engine's snapshot model was lossy — FKs stored per-column (`{col: table}`, no referred columns), composite `UNIQUE(tenant_id, id)` flattened to a column set, indexes in a non-deduped list — so a shared_schema intra-tenant ref produced a *simple* `(fk) → Parent(id)` FK + `UNIQUE(id)` + a bogus, unusable `UNIQUE(tenant_id)` (one row per tenant), and composite "list" indexes could double-emit (`DuplicateTable` at upgrade). `schema_snapshot.project_schema` now reads table-level `ForeignKeyConstraint`s (constrained cols → referred table + referred cols) and `UniqueConstraint` column-tuples, and de-duplicates index keys; `schema_diff` op models (`AddForeignKey`/`DropForeignKey`/`AddUnique`/`DropUnique`) carry composite columns; `schema_render` emits the composite FK/UNIQUE (was hard-coded `["id"]`). Legacy embedded snapshots are upgraded in-place (`_coerce_fks`/`_coerce_uniques`) so an incremental `db revision` against a pre-#1464 baseline stays correct. **Cross-tenant referential integrity (`(tenant_id, fk) → Parent(tenant_id, id)`) is now structurally enforced by the migration-built schema, not just by `create_all`.** Verified on real Postgres (baseline + incremental-revision parity oracles, now composite-aware: they compare FK *structure* + UNIQUE column-tuples via an independent `pg_catalog` read). Adversarially reviewed: a CRITICAL constraint-name mismatch was caught and fixed — `sa_schema` named the composite FK `fk_{entity}_{field}` while the engine named it `fk_{entity}_{partition_key}_{field}`; both now agree, so the two provisioning paths produce byte-identical names (an engine drop/downgrade against a `create_all` DB would otherwise target a non-existent name).
16
+
17
+
### Agent Guidance
18
+
- **The migration engine's schema snapshot is composite-aware.** `project_schema` FKs are `[(constrained_cols, ref_table, ref_cols), ...]` and uniques are `[(col, ...), ...]` (tuples, embedded via `pprint`). When adding constraint handling, go through table-level `ForeignKeyConstraint`/`UniqueConstraint`, not per-column `.foreign_keys`/`col.unique`. Composite constraint names join all columns (`fk_{table}_{c1}_{c2}`); keep `sa_schema` (create_all) and `schema_render` (engine) naming aligned or the parity oracle's intent (byte-identical schemas) is lost.
13
19
14
20
### Added
15
21
- **#1464 (Phase A — reproducer) engine-baseline parity oracle now detects shared_schema composite-constraint divergence.** The `db baseline ≡ create_all` parity gate (`tests/integration/test_engine_baseline_parity_pg.py`) was blind to composite tenant-scoped constraints: it compared FKs by `column→table` (not structure) and omitted UNIQUE constraints entirely, both via the engine's own lossy snapshot. Added an independent `pg_catalog`-based introspection (`_pg_constraint_shapes`) that captures composite FK structure (`(constrained cols) → table(referred cols)`) and UNIQUE column-tuples, plus an inline `shared_schema_intra_fk` corpus fixture (Workspace tenant-root; `Project.owner → Member` intra-tenant ref). The fixture reproduces #1464 — the engine baseline emits a simple `(owner) → Member` FK + `UNIQUE(id)` + bogus `UNIQUE(tenant_id)` instead of the composite `(tenant_id, owner) → Member(tenant_id, id)` + `UNIQUE(tenant_id, id)` — and is marked `xfail(strict=True)` so CI stays green while the gap is tracked in-repo. The engine fix (Phase B) flips it to pass.
0 commit comments