Skip to content

stash init scaffolds the EQL v2 authoring surface into customer repos, against a v3 database #733

Description

@tobyhede

stash init installs an EQL v3 database (since #732 / PR #705) but the client-scaffold code it writes into the customer's repo still teaches v2. So init hands the customer's coding agent v2 authoring guidance — Encryption, encryptedColumn('x').equality().freeTextSearch(), encryptedType<T>('x', { equality: true }) — against a v3 database. The scaffold and the database disagree.

Split out from #732, which fixed the database side (routing) but explicitly left the code side (scaffold templates) as follow-up.

Where

packages/cli/src/commands/init/utils.ts. Two live surfaces emit v2:

  • generatePlaceholderClientDRIZZLE_PLACEHOLDER / GENERIC_PLACEHOLDER — what stash init writes, and the eql install safety net (db/client-scaffold.ts).
  • generateClientFromSchemas → the Drizzle/generic generators — reached via stash schema build introspection.

The core difficulty

v3 has no chainable capability tuners — capabilities are fixed by the concrete domain type. So { equality: true, freeTextSearch: true } does not map mechanically to v3; each SearchOp combination has to be resolved to the v3 domain whose fixed capability set matches (packages/stack/src/eql/v3/columns.ts).

Fix

PR #734. Ports both placeholders and both live plural generators to EncryptionV3 + types.* (@cipherstash/stack/v3, @cipherstash/stack-drizzle/v3), via a shared SearchOp-set → v3-domain mapping. Deletes the dead singular generators (generateClientFromSchema + helpers — zero callers) rather than porting v2 dead code.

Surfaced one real capability difference: v2 allowed equality on a boolean; v3 has no boolean eq/ord domain, so booleans map to storage-only.

Follow-up beyond this

Numeric collapses to the Integer* family — there is no width/float signal in the introspected SearchOp model, matching how v2 collapsed everything to dataType: 'number'. If v3 float/decimal domains should be scaffolded distinctly, that needs a richer introspection signal and is out of scope here.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions