Bump cratestack to 0.7.8 and regenerate migrations - #136
Merged
Conversation
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>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bumps
cratestack-pgandcratestack-codec-jsonfrom=0.6.7to=0.7.8, regenerates migrations with a version-matched CLI, and corrects twoAGENTS.mdclaims the bump falsified.Recommendation: merge. The evidence came out considerably better than expected — see Verification.
Intent
AGENTS.mddocuments a live trap: a 0.7.x CLI emits foreign-keyALTER TABLEstatements the pinned0.6.7emitter 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
Decimalfix (cratestack#455 / #456) that unblocked the generated TypeScript client, plus #449 (model responses no longer projected throughserde_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 --workspacepasses untouched.schema/migrations/postgres/0001_init/{up,down}.sql— regenerated with the CLI matched to the new pin.docs/architecture.md§2.10 andschema/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_initis purely additive: 24 insertions, zero deletions, every changed line anALTER 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 ENUMtoTEXT+CHECK, which broke themessage_state/job_statetransition tables atpsqltime whilecargo buildandcratestack checkboth stayed green. Nothing comparable happened here.0.7.8's emitter now writes a plain
ON DELETE NO ACTIONforeign key for every@relation— all twelve. Seven hand-written duplicates therefore left §2.10 and0002_bootstrap.The trap worth recording
Three relations were not simply deleted, because two
FOREIGN KEYconstraints on the same column enforce independently.Leaving the emitted
NO ACTIONconstraint in place beside a hand-writtenCASCADEone does not resolve toward the more permissive behaviour. Postgres checks both, and raisesviolates foreign key constrainton theNO ACTIONone before theCASCADEone ever runs — silently reinstating the block you thought you had removed.So
message_parts,delivery_receiptsandwebhook_attemptsdrop 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.mdis explicit that "parses" ≠ "compiles" ≠ "applies", and only applying for real caught the 0.5.0 change.cargo check --workspaceci/test-state-machine.sqlpg_constraintconfdeltype='c'just parityjust lint(fmt + clippy-D warnings)./ci/assert-no-raw-sqlx.shContainer 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:
AGENTS.md'saws-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.
0001_initdiff is additive and that enum representation is unchanged — the specific regression this bump was checked for.pg_constraintrather than trusting the SQL text.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-rsre-analysis is worth doing separately.