Context
The EQL v3 install migrations in @cipherstash/prisma-next now bake the install SQL into their ops.json at emit time, digest-verified against the @cipherstash/eql release manifest (installSqlSha256) — replacing the runtime-injection design whose environment-dependent migration hashes wedged consumer repos (PN-MIG-5002) on every EQL bump, and whose recomputed hash could never detect a tampered EQL package.
Already enforced in CI (no action needed):
- Provenance pin — the committed SQL's sha256 must equal the installed
@cipherstash/eql manifest's digest; an EQL bump without the matching new migration fails.
- Frozen-hash pins — published migration hashes are hard-coded in tests; any byte change to published history fails.
- Vendored-space parity — the example's
migrations/cipherstash/ must be byte-identical to the shipped artefacts.
This issue tracks the follow-ups that came out of that work.
Tasks
1. Digest-pin the CLI and stack EQL installers (pre-GA, security)
stash eql install (packages/cli, readV3InstallSql) and the stack install helper (installEqlV3IfNeeded) still execute readInstallSql() from node_modules unverified — the same laundering class the migration path had. The strong fix pins an expected digest in our shipped code (as prisma-next now does), not merely checking the EQL package against its own manifest, which a tampered package would rewrite too. Touches packages/cli + packages/stack; needs the stash-cli skill check per AGENTS.md.
2. Document the EQL upgrade window (GA docs)
Upgrade migrations run DROP SCHEMA eql_v3 CASCADE + recreate. In-flight queries against eql_v3.* fail during that transaction, and any customer-created object depending on those functions (e.g. a functional index over an eql_v3 expression) would cascade-drop. This is an EQL property, not packaging — needs a sentence in the upgrade guide on cipherstash.com/docs.
3. Decide the re-baseline cadence
Each EQL release adds ~2.7 MB (one baked migration) to the tarball and one more replayed install on fresh databases (baseline + every upgrade edge). Correct and idempotent, but linearly wasteful. Decide now that roughly every N releases we cut a fresh genesis migration (new baseline baking current SQL, old chain retained for existing markers) — scheduled maintenance, not a reaction.
4. Dependabot policy for @cipherstash/eql
An automated bump PR will be red by design — the provenance pin demands the new upgrade migration, which a bot can't author. Either add @cipherstash/eql to the Dependabot ignores alongside the auth lockstep set (documenting the manual bump procedure), or accept the red PR as the reminder.
5. Investigate the db-ref planning workflow in the example
A second prisma-next migration plan in examples/prisma replans the whole schema from scratch (from: null) because no db ref (migrations/app/refs/db.json) was ever recorded — resolveFromForPlan treats a missing db ref as greenfield. Affects anyone using the example as a template, and is a prerequisite for the pending two-model include() e2e test. Needs a short look at the intended upstream ref workflow (prisma-next ref set).
Out of scope
More machinery around the seed phase or hash scheme — each failure mode found is covered by a specific tripwire above; the content-addressing makes the rest structurally impossible.
Context
The EQL v3 install migrations in
@cipherstash/prisma-nextnow bake the install SQL into theirops.jsonat emit time, digest-verified against the@cipherstash/eqlrelease manifest (installSqlSha256) — replacing the runtime-injection design whose environment-dependent migration hashes wedged consumer repos (PN-MIG-5002) on every EQL bump, and whose recomputed hash could never detect a tampered EQL package.Already enforced in CI (no action needed):
@cipherstash/eqlmanifest's digest; an EQL bump without the matching new migration fails.migrations/cipherstash/must be byte-identical to the shipped artefacts.This issue tracks the follow-ups that came out of that work.
Tasks
1. Digest-pin the CLI and stack EQL installers (pre-GA, security)
stash eql install(packages/cli,readV3InstallSql) and the stack install helper (installEqlV3IfNeeded) still executereadInstallSql()fromnode_modulesunverified — the same laundering class the migration path had. The strong fix pins an expected digest in our shipped code (as prisma-next now does), not merely checking the EQL package against its own manifest, which a tampered package would rewrite too. Touchespackages/cli+packages/stack; needs thestash-cliskill check per AGENTS.md.2. Document the EQL upgrade window (GA docs)
Upgrade migrations run
DROP SCHEMA eql_v3 CASCADE+ recreate. In-flight queries againsteql_v3.*fail during that transaction, and any customer-created object depending on those functions (e.g. a functional index over aneql_v3expression) would cascade-drop. This is an EQL property, not packaging — needs a sentence in the upgrade guide on cipherstash.com/docs.3. Decide the re-baseline cadence
Each EQL release adds ~2.7 MB (one baked migration) to the tarball and one more replayed install on fresh databases (baseline + every upgrade edge). Correct and idempotent, but linearly wasteful. Decide now that roughly every N releases we cut a fresh genesis migration (new baseline baking current SQL, old chain retained for existing markers) — scheduled maintenance, not a reaction.
4. Dependabot policy for
@cipherstash/eqlAn automated bump PR will be red by design — the provenance pin demands the new upgrade migration, which a bot can't author. Either add
@cipherstash/eqlto the Dependabot ignores alongside the auth lockstep set (documenting the manual bump procedure), or accept the red PR as the reminder.5. Investigate the
db-ref planning workflow in the exampleA second
prisma-next migration planinexamples/prismareplans the whole schema from scratch (from: null) because nodbref (migrations/app/refs/db.json) was ever recorded —resolveFromForPlantreats a missingdbref as greenfield. Affects anyone using the example as a template, and is a prerequisite for the pending two-modelinclude()e2e test. Needs a short look at the intended upstream ref workflow (prisma-next ref set).Out of scope
More machinery around the seed phase or hash scheme — each failure mode found is covered by a specific tripwire above; the content-addressing makes the rest structurally impossible.