Skip to content

Bump cratestack to 0.7.8 and regenerate migrations - #136

Merged
stephane-segning merged 1 commit into
mainfrom
claude/cratestack-078-bump
Aug 8, 2026
Merged

Bump cratestack to 0.7.8 and regenerate migrations#136
stephane-segning merged 1 commit into
mainfrom
claude/cratestack-078-bump

Conversation

@stephane-segning

Copy link
Copy Markdown
Contributor

Summary

Bumps cratestack-pg and cratestack-codec-json from =0.6.7 to =0.7.8, regenerates migrations with a version-matched CLI, and corrects two AGENTS.md claims the bump falsified.

Recommendation: merge. The evidence came out considerably better than expected — see Verification.

Intent

AGENTS.md documents a live trap: a 0.7.x CLI emits foreign-key ALTER TABLE statements the pinned 0.6.7 emitter never produces. Anyone following the documented "regenerate migrations after a schema change" workflow therefore produced migrations the compiled library would not generate — silently. #134 requires a schema change, so the trap was armed for whoever touched it next.

The bump also picks up the Decimal fix (cratestack#455 / #456) that unblocked the generated TypeScript client, plus #449 (model responses no longer projected through serde_json::Value) and #464 (default-features leak across the feature graph).

Scope

  • Cargo.toml / Cargo.lock — pin moved to =0.7.8. No source changes were required; cargo check --workspace passes untouched.
  • schema/migrations/postgres/0001_init/{up,down}.sql — regenerated with the CLI matched to the new pin.
  • docs/architecture.md §2.10 and schema/migrations/postgres/0002_bootstrap/up.sql — seven now-redundant hand-written foreign keys removed; three rewritten (see below).
  • AGENTS.md — two corrections.

The migration diff, characterised

0001_init is purely additive: 24 insertions, zero deletions, every changed line an ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY.

Critically, enum column representation did not change. That was the specific regression this bump was checked against: 0.5.0 silently moved enum columns from native CREATE TYPE ... AS ENUM to TEXT + CHECK, which broke the message_state/job_state transition tables at psql time while cargo build and cratestack check both stayed green. Nothing comparable happened here.

0.7.8's emitter now writes a plain ON DELETE NO ACTION foreign key for every @relation — all twelve. Seven hand-written duplicates therefore left §2.10 and 0002_bootstrap.

The trap worth recording

Three relations were not simply deleted, because two FOREIGN KEY constraints on the same column enforce independently.

Leaving the emitted NO ACTION constraint in place beside a hand-written CASCADE one does not resolve toward the more permissive behaviour. Postgres checks both, and raises violates foreign key constraint on the NO ACTION one before the CASCADE one ever runs — silently reinstating the block you thought you had removed.

So message_parts, delivery_receipts and webhook_attempts drop the emitted constraint by name and replace it with the cascading one. Verified directly in the catalog: exactly one FK per table, confdeltype = 'c'.

This matters beyond tidiness: retention purge (#67, unbuilt) depends on cascade actually cascading, and no current test covers it. Getting this wrong would have surfaced only when purge was first run against real data.

Verification

Everything against a real database, not a parse — AGENTS.md is explicit that "parses" ≠ "compiles" ≠ "applies", and only applying for real caught the 0.5.0 change.

check result
cargo check --workspace passes, no source changes needed
Both migrations → scratch Postgres 16 apply cleanly, in order
ci/test-state-machine.sql ALL ASSERTIONS PASSED
Cascade constraints in pg_constraint one FK per table, confdeltype='c'
Full live-Postgres sweep twice, zero failures
just parity 25 message edges, 8 job edges, agree
just lint (fmt + clippy -D warnings) clean
./ci/assert-no-raw-sqlx.sh R1 OK

Container count returned to baseline; the harness container was label-scoped throughout and no unrelated container was touched.

Screenshots/Evidence

N/A — dependency bump, generated SQL, and docs.

Risk Assessment

Lower than a five-minor-version framework bump would normally imply, because the diff is additive and the live sweep is clean twice over. Residual risks:

  • #449 changed how model responses are projected. The live suites exercise the real REST surface and pass, but no exhaustive response-shape comparison against 0.6.7 was made.
  • The generated TypeScript client (PR Generate the TypeScript client at build time, not committed (T3) #135) is produced by the 0.7.8 CLI. With this merged, CLI and library agree, which removes a skew rather than adding one.
  • AGENTS.md's aws-lc-rs/feature-graph analysis was not re-run against #464. Flagged as unverified rather than assumed unchanged.

AI Usage Declaration

Investigated by a Claude Code subagent (Sonnet 5); the agent stalled before writing its report, so verification was completed and the change landed by Claude Opus 5.

  • I ran the migration application, state-machine test, cascade catalog check, and both live sweeps myself rather than relying on the agent's summary.
  • I confirmed the 0001_init diff is additive and that enum representation is unchanged — the specific regression this bump was checked for.
  • I verified the cascade fix in pg_constraint rather than trusting the SQL text.
  • I state plainly what was not verified: the #464 feature-graph re-analysis, and an exhaustive response-shape diff for #449.

Reviewer Focus

Whether merging a five-minor-version framework bump is acceptable with a production release under discussion. My read: the skew it removes is a larger risk than the bump itself, particularly because #134 needs a schema change and would otherwise be regenerated by a mismatched CLI. The aws-lc-rs re-analysis is worth doing separately.

Aligns the library pin with the released CLI, removing a documented trap:
AGENTS.md records that a 0.7.x CLI emits foreign-key `ALTER TABLE`s the
pinned 0.6.7 emitter never produces, so anyone following the documented
"regenerate migrations after a schema change" workflow silently produced
migrations the compiled library would not generate. #134 requires a schema
change, so that trap was armed for whoever touched it next.

The bump required **no code changes** — `cargo check --workspace` passes
untouched. The migration diff is the interesting part.

`0001_init` is **purely additive**: 24 insertions, zero deletions, every
changed line an `ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY`. In
particular the enum column representation did **not** change; 0.5.0 silently
moved enums from native `CREATE TYPE ... AS ENUM` to `TEXT` + `CHECK` and
broke the transition tables at psql time while `cargo build` and
`cratestack check` both stayed green, so that was the specific regression
this bump was checked against.

0.7.8's emitter now writes a plain `ON DELETE NO ACTION` foreign key for
every `@relation`, covering all twelve relations. Seven hand-written
duplicates therefore left §2.10 and `0002_bootstrap`.

Three did not, and the reason is a trap worth recording: **two FOREIGN KEY
constraints on the same column enforce independently.** Leaving the emitted
`NO ACTION` constraint beside a hand-written `CASCADE` one does not resolve
toward the permissive behaviour — Postgres checks both and raises
`violates foreign key constraint` on `NO ACTION` before `CASCADE` runs,
silently reinstating the block. So `message_parts`, `delivery_receipts` and
`webhook_attempts` drop the emitted constraint by name and replace it with
the cascading one. Verified in `pg_constraint`: exactly one FK per table,
`confdeltype = 'c'`.

Migrations were regenerated with the CLI matched to the new pin, per
AGENTS.md's workflow, and `schema.snapshot.json` deleted (this repo does not
use snapshot diffing).

Verification, all against a real database rather than a parse:
  - both migrations apply cleanly to a scratch Postgres 16
  - `ci/test-state-machine.sql` — ALL ASSERTIONS PASSED
  - full live-Postgres sweep, twice, zero failures
  - `just parity` (25 message edges, 8 job edges), `just lint`,
    `./ci/assert-no-raw-sqlx.sh` all green

Also corrects two AGENTS.md claims this bump falsified: the pinned-version
table still said `=0.5.0` (the pin had been 0.6.7 for some time), and §2.0
still said the emitter produces no foreign keys.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c7b9697

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@stephane-segning
stephane-segning merged commit 5eab542 into main Aug 8, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant