Repository navigation
feat(eql-bindings): produce IntegerEq, BigintEq, RealEq and DoubleEq, and name each type's real blocker - #1241
Conversation
… and name each type's real blocker vitaminc 0.6 is released, and the engine already derived integer and float equality over ADR-0002's semantic baseline, so the four number equality types were held back by nothing but the list in eql-codegen. They join ENCRYPTION_DOMAINS: one integer value has one term at either width, and a float's -0.0 and every NaN fold to one value each, which is Postgres's own float8 equality. The ciphertext keeps the exact value. The reasons stashgen shows for the types it still refuses told Go developers to wait for vitaminc 0.6. Each now names the issue that tracks the real blocker: a kind the value enum lacks (#1144), order keys (#1236), text's order types (#1131), block ORE (#1132) or the JSON index (#1060). The Go Profile model gains a field of each type. Its generated Eq queries match the Rust dispatch byte for byte (v4_queries.json), and the rows it seals are inserted into eql_v4 columns and found with = in PostgreSQL by the Rust suite (v4_rows.json). Closes #1239 Claude-Session: https://claude.ai/code/session_01BZhkvKLpNtKuzj3HCfMXoL
|
| Name | Type |
|---|---|
| @cipherstash/eql | Minor |
| stash | Patch |
| @cipherstash/stack-prisma | Patch |
| @cipherstash/basic-example | Patch |
| @cipherstash/e2e | Patch |
| @cipherstash/prisma-example | Patch |
| @cipherstash/stack-drizzle | Patch |
| @cipherstash/stack-supabase | Patch |
| @cipherstash/stack | Patch |
| @cipherstash/wizard | Patch |
| @cipherstash/bench | Patch |
| @cipherstash/test-kit | Patch |
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
…lity types The guest crate pins the producible types and each one's operators separately from eql-codegen, so it still listed the eight types from before IntegerEq, BigintEq, RealEq and DoubleEq were produced. Each answers eq through its equality index, as TextEq does. Claude-Session: https://claude.ai/code/session_01BZhkvKLpNtKuzj3HCfMXoL
There was a problem hiding this comment.
🔵 Needs a closer look
Persisted equality terms and Rust–WASI–Go compatibility warrant human confirmation of the integration results.
No open issues 🎉
2 files not reviewed
languages/golang/encrypt/eql/eql_gen.go: Generated filelanguages/golang/encrypt/internal/testusers/profile_stash.go: Generated file
What changed in this PR
Enables numeric equality searches through EQL v4’s Rust bindings and Go SDK, addressing #1239 and the equality portion of #1130.
Changes:
- Enables
IntegerEq,BigintEq,RealEq, andDoubleEq. - Replaces stale refusal messages with specific blockers.
- Adds equality semantics, PostgreSQL, and Rust–Go interoperability coverage.
| File | Description |
|---|---|
| packages/eql/tests/encryption/tests/v4_types.rs | Tests numeric equality and interoperability. |
| packages/eql/tests/encryption/tests/targets.rs | Updates supported types and refusal expectations. |
| packages/eql/tests/encryption/fixtures/v4_rows.json | Adds Go-sealed numeric equality fields. |
| packages/eql/tests/encryption/fixtures/v4_queries.json | Adds numeric query fixtures. |
| packages/eql/crates/eql-codegen/src/targets.rs | Updates blocker documentation and tests. |
| packages/eql/crates/eql-codegen/src/go_eql.rs | Updates refusal-message assertion. |
| packages/eql/crates/eql-codegen/src/bindings.rs | Enables equality derives and revises blockers. |
| packages/eql/crates/eql-bindings/src/v4/targets.rs | Regenerates catalog and numeric dispatch. |
| packages/eql/crates/eql-bindings/src/v4/real.rs | Adds float32 equality derives. |
| packages/eql/crates/eql-bindings/src/v4/integer.rs | Adds int32 equality derives. |
| packages/eql/crates/eql-bindings/src/v4/double.rs | Adds float64 equality derives. |
| packages/eql/crates/eql-bindings/src/v4/bigint.rs | Adds int64 equality derives. |
| packages/eql/crates/eql-bindings/src/encryption/targets.rs | Updates refusal assertion. |
| packages/eql/crates/eql-bindings/src/encryption/plaintext.rs | Documents numeric equality semantics. |
| packages/eql/crates/eql-bindings/README.md | Documents supported types and blockers. |
| packages/eql/crates/eql-bindings/CHANGELOG.md | Records numeric equality support. |
| languages/golang/stashgen/refusal_test.go | Uses an unsupported ordered type. |
| languages/golang/encrypt/README.md | Documents numeric types and comparisons. |
| languages/golang/encrypt/query_test.go | Checks new equality operators. |
| languages/golang/encrypt/internal/testusers/profiles.go | Adds numeric equality model fields. |
| languages/golang/encrypt/internal/testusers/profile_stash.go | Regenerates codecs and query methods. |
| languages/golang/encrypt/guest/tests/native_ops.rs | Updates guest catalog expectations. |
| languages/golang/encrypt/guest/src/targets.rs | Updates supported-type assertions. |
| languages/golang/encrypt/eql/eql_test.go | Checks numeric type mappings. |
| languages/golang/encrypt/eql/eql_gen.go | Regenerates availability and blocker messages. |
| languages/golang/encrypt/eql_v4_test.go | Extends cross-language fixture checks. |
| languages/golang/CHANGELOG.md | Records equality support and diagnostics. |
| .changeset/eql-v4-bindings.md | Updates unreleased EQL release notes. |
Review effort: Balanced
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
cipherstash-agent
left a comment
There was a problem hiding this comment.
Automated review attestation — source: Claude Code /code-review medium + /cross-check-review-findings, run on head 7f8cb75.
Result: no critical or blocking issues; no findings to report.
Checked:
- The
IntegerEq/BigintEq/RealEq/DoubleEqstored and query structs carry the samestack-encryptderives and field attrs as the existingTextEq, and use the matchingInt32/Int64/Float32/Float64plaintext newtypes. ENCRYPTION_DOMAINS,encryption_gapandtargets.rsagree: the four Eq types are producible, and every remaining gap names a tracking issue (#1131, #1132, #1144, #1236, #1060).- No stale "held back / once vitaminc 0.6" wording remains in Rust, Go or Markdown sources (CHANGELOGs excluded).
- Tests cover the ADR-0002 baseline: one integer term across widths,
-0.0/NaN folding, stored vs. query term equality, and exact ciphertext round-trip of-0.0/NaN. The Postgres test is#[ignore]d and needsEQL_TEST_DATABASE_URL. - The changeset is present (
@cipherstash/eqlminor).
Not verified: I did not run the cargo or Go suites, so CI is the check for the generated eql_gen.go and *_stash.go drift guards.
Generated by Claude Code
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f8cb75288
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ("integer", "eq"), | ||
| ("bigint", ""), | ||
| ("bigint", "eq"), |
There was a problem hiding this comment.
Update the Go supported-type references
When Go users choose an encrypt_into type from the primary package or generator documentation, languages/golang/encrypt/doc.go:23-25 and languages/golang/cmd/stashgen/README.md:157-166 still list only the storage-only numeric types and omit these newly supported equality variants. That contradicts the generated target table and can steer users toward Integer, Bigint, Real, or Double, which provide no Eq query method; update both references to include the new *Eq types.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🔵 Needs a closer look
Persistent encrypted-value compatibility across Rust, WASI, Go, and PostgreSQL warrants final human validation despite no identified blocking defects.
No open issues 🎉
2 files not reviewed
languages/golang/encrypt/eql/eql_gen.go: Generated filelanguages/golang/encrypt/internal/testusers/profile_stash.go: Generated file
Review effort: Balanced
…encrypt feature Only Stack Encrypt produces an EQL v4 value, yet the v4 module compiled without the feature and every generated derive, stash attribute and doc line was wrapped in its own cfg_attr on it. The module itself is now gated in lib.rs, and eql-codegen emits the v4 derives and docs unconditionally. v4_parity.rs runs under the feature, where test:encryption runs it. The Go docs listing what encrypt_into takes (encrypt/doc.go and the stashgen README) now name the four number equality types, and say which types answer Eq and which are stored and read only. Claude-Session: https://claude.ai/code/session_01BZhkvKLpNtKuzj3HCfMXoL
|
@coderdan, on the comment at Fixed in 7c8e018:
Checks: The same commit also fixes the Codex finding about the Go type lists. |
|
Review feedback, all addressed in 7c8e018:
|
… boolean plaintexts Integer, Bigint, Boolean, Real and Double, and their equality types, now take i32, i64, bool, f32 and f64, as the text types take String. The encryption::plaintext newtypes are gone: the derive and the by-name dispatch need nothing a primitive lacks, and the dispatch still accepts only the matching runtime kind. A typed decrypt now reads a leaf as vitaminc reads it into the primitive: an integer of another width that fits opens unchanged, and an f64 opens an f32. A value that does not fit, or of another kind, is still refused. The newtypes refused every other width, but every writer seals at the type's width, so that refused only payloads none of them writes. eql-bindings no longer depends on vitaminc-aead directly.
…gainst v3 A v4 payload is never a v3 one: Stack Encrypt's ciphertext is not cipherstash-client's. So the v4 checks no longer compare v4 with v3. v4_parity.rs becomes v4_inventory.rs: - The inventory, its schema ids and its term keys are still checked against the eql-domains catalog. - Query entries are checked to live in the eql_v4 schema. They are no longer required to be the same set as v3's. - The cross-generation version test becomes a v4 one: a v4 type admits "v": 4 and refuses every other version, by type and through the inventory. v3's own refusal stays in domain_payload.rs.
Summary
Go developers can now store integers and floats in EQL columns they can search by equality:
IntegerEq,BigintEq,RealEqandDoubleEq. EQL is the SQL library we install into a customer's PostgreSQL database to store and query encrypted values; Stack Encrypt is our Rust encryption engine, which the Go SDK runs as a WebAssembly guest. The engine could already compute these equality terms under vitaminc 0.6, which is now released, so the only thing holding the four types back was a list in the code generator. This also replaces the stale "wait for vitaminc 0.6" message thatstashgen(the Go code generator) showed for every type it still refuses. Each refusal now names the issue that tracks the real blocker.Changes
eql-codegen and eql-bindings
ENCRYPTION_DOMAINS, so their v4 structs deriveEncryptFromandDecryptIntoand the by-name dispatch handles them. That takes the producible types from 8 of 51 to 12.int16is widened toInt32, and there's no way to encrypt a date, timestamp, decimal or 128-bit integer #1144), order terms are not yet derived over ADR-0002's order keys (Stack Encrypt cannot order floats, dates, timestamps or decimals, and its integer order keys predate ADR-0002: derive every order term over vitaminc-ore #1236), no EQL type is built from text's order terms yet (stashgen refuses TextMatch, TextSearch, TextOrd and TextOrdOpe — the engine derives their terms, but no EQL type is built from them #1131), EQL stores block ORE terms where the engine derives CLLW ORE (stashgen refuses TextOrdOre and TextSearchOre — EQL stores block ORE terms and the engine derives CLLW ORE #1132), or the JSON index doesn't exist yet (stack-encrypt has no searchable JSON — add aJsonindex that seals a document's entries under one data key #1060).v4/{integer,bigint,real,double,targets}.rsand Go'sencrypt/eql/eql_gen.go.plaintext.rs, the crate README and the CHANGELOG. The unreleased@cipherstash/eqlchangeset is rewritten to match.Tests (packages/eql/tests/encryption)
IntegerEq(42)andBigintEq(42)share a term,-0.0and0.0share a term, every NaN shares one term, and anf32hashes as thef64it widens to. Each query twin derives the term its stored value holds. The ciphertext still decrypts to the exact value, including-0.0.=on eacheql_v4_*_eqcolumn finds exactly the expected rows,-0.0 = 0.0and NaN payloads included.v4_queries.jsonfixture gains an equality query for each type, andv4_rows.jsongains the four Go-sealed columns. The PostgreSQL test of those Go rows now also checks=.Go
Profiletest model gainsAge(IntegerEq),Rank(BigintEq),Weight(RealEq) andPrice(DoubleEq). stashgen generates anEqmethod on each, and each one's query matches the Rust fixture byte for byte.-0.0and NaN compare. Tests that listed the producible types or their operators are updated. Added a CHANGELOG entry.Verification
cargo test -p eql-codegenpassed (153 unit tests plus the parity tests).mise run types:checkpassed on the commit.mise run test:encryptionpassed.mise run test:encryption:postgrespassed against a disposablepostgres:17with the v4 bundle built from the tree. That coverspostgres_finds_number_equality_rows,postgres_stores_and_queries_rows_the_go_sdk_sealedandpostgres_stores_and_queries_every_producible_v4_type.mise run test:cratespassed.languages/golang:go vet ./...andgo test ./... -count=1passed with the guests built, andgo generate ./...leaves no diff.Related
Closes #1239
Refs #1130: this is the equality part of producing the number types. The ordered types wait on #1236.
https://claude.ai/code/session_01BZhkvKLpNtKuzj3HCfMXoL
Summary by CodeRabbit