Skip to content

Go and Rust plans cannot target EQL domains, so Go writes rows EQL cannot query — make domains plan field targets #1062

Description

@coderdan

Updated 2026-10-05 (PDT). The Go SDK design is PR cipherstash/stack#1070: docs/plans/2026-10-04-plan-builder.md, "The Go SDK", and the principles in docs/sdk-design-principles.md (ADR-0008). Dan's "EQL Plans in Go" proposal is taken. Item 2 keeps this issue's shape: eql-codegen emits a dispatch table beside inventory.rs, the plan grammar gains a target field form, and the guest build that holds the EQL types runs the Rust-derived plan for the named type. The Go package encrypt/eql holds generated structs that store the EQL value the guest returns, and it embeds that guest build. Item 3: the envelope is decided. A Stack Encrypt EQL value has the EQL v3 envelope (v: 3, eql_v3 domains) with a ciphertext prefixed stack-encrypt:1:; "EQL v4" names that form. Item 5: the record fixture guards the bytes (each side opens the other's records, same term bytes); there is no Go encoder to fixture. The engine produces TextEq only today; stashgen refuses the other types until the engine can produce them. The size of the guest build with the EQL types is measured before the SDK ships two builds or one.

Background

EQL (Encrypt Query Language) is our PostgreSQL library: SQL we install into a customer database that stores and queries encrypted payloads. Each EQL domain (TextEq, IntegerOrd, Json, …) fixes the JSON shape a column stores: a version, the column identifier i ({"t": table, "c": column}), the ciphertext, and the search terms that domain needs. packages/eql/crates/eql-bindings/ holds the Rust types for those domains; PR cipherstash/stack#971 added text encryption and queries there through stack-encrypt, our Rust field-level encryption library.

The plan builder (docs/plans/2026-10-04-plan-builder.md, PR cipherstash/stack#1052) lets a field's target be any EncryptFrom type. So an EQL domain can be a plan field target with no builder work.

Problem

  • Rust: there is no way to say "this plan field is stored as EQL TextEq" inside a plan.
  • Go: the binding's record output is its own map ({"c","eq","match","ore","ope"}), which is not an EQL payload, so Go cannot write rows EQL can query. There are no Go domain types.
  • Name lookup: a binding sends a domain name as data. Nothing maps that name to the Rust type, and inferring the domain from a payload's keys would be unsafe (two domains can share keys).

Proposal

From the plan doc's "EQL v3 domains as field targets" section. Not yet verified by implementation.

  1. Rust: encrypt_into::<Domain>(name) on the fields chain, for any EncryptFrom type, using <Domain as EncryptFrom<S>>::encryption() as that field's description.
  2. A name-to-type table in eql-bindings: an explicit lookup from domain name to type, never inferred from payload keys. It lives in eql-bindings so every binding reuses it.
  3. Go: a package generated by eql-codegen into languages/golang, inside the one Go module and the one guest, with every domain, and constructors only for domains that have Rust derives. Module size is measured and reported in the PR.
  4. A domain wraps an index's output for EQL's wire format. The index stays in stack-encrypt. For example the JSON domain frames the Json index's document (#1060) into EQL's JSON envelope the way TextEq frames an equality term.
  5. Remove the Go record output map (c/eq/match/ore/ope) once domains are field targets.

Naming note: the plan doc calls the generated Go package eqlv3 and the section "EQL v3 domains". Payloads emitted by stack-encrypt are intended to be EQL v4. The generated package name and the envelope version must follow the EQL v4 envelope work, and the plan doc's eqlv3 naming is to be corrected.

Relationship to other work

  • Blocked by #1057 (the plan builder), #1046 (the Go chain), and the EQL v4 envelope work (the version and shape of the payload stack-encrypt emits).
  • Blocks #1065 (TypeScript on stack-encrypt).
  • Supersedes the "EQL v3 outputs as EncryptAs targets" section previously in #1046.
  • Design: docs/plans/2026-10-04-plan-builder.md on PR cipherstash/stack#1052.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

SDKenhancementNew feature or requestrustPull requests that update Rust code

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions