Skip to content

chore: release candidate for EQL v4 and Stack Encrypt Rust and Go support - #1229

Open
coderdan wants to merge 299 commits into
mainfrom
next
Open

coderdan wants to merge 299 commits into
mainfrom
next

Conversation

@coderdan

Copy link
Copy Markdown
Contributor

Summary

This is the integration branch for a release candidate of EQL v4 and of Stack Encrypt's Rust and Go support. EQL is the SQL that lets PostgreSQL store and search encrypted values; EQL v4 is a second copy of it for values written by Stack Encrypt, the Rust encryption engine behind the Go SDK. The open pull requests for both are merged here first, so they can be tested together before any of them reaches main.

The release version is not decided yet.

Why a branch, not main

Some of this work depends on vitaminc and ore.rs code that is not yet on crates.io, so it pins those crates to a git commit. stack-encrypt and eql-bindings are published crates, and cargo publish drops those git pins, so nothing on this branch can be released until vitaminc 0.6 is published (cipherstash/vitaminc#389, which waits on cipherstash/vitaminc#463). Once it is, the git pins become crates.io versions and this branch merges to main as a normal release.

What lands here, in order

  1. EQL v4: docs(adr): one value model, three encodings in vitaminc, EQL v4 by producer #1139, refactor(eql): write the SQL source with schema and version placeholders #1147, feat(eql): build the eql_v4 bundle beside eql_v3 #1161, feat(eql-bindings): generate EQL v4 bindings and derive Stack Encrypt traits on v4 only #1162, feat(eql-bindings): produce the unordered EQL v4 number, boolean and text types #1163, feat(eql-bindings): produce EQL v4 TextMatch from Stack Encrypt match terms #1164, test(golang): prove the EQL v4 types from Go, against Rust and PostgreSQL #1165. Uses vitaminc 0.5.1 from crates.io only.
  2. Stack Encrypt operators: docs(adr): ADR-0009, operators select the index and a query term is not the stored term #1177, feat(stack-encrypt)!: a query names an operator, not an index #1190, feat(stack-encrypt): verify a match query's rows after decrypt #1191, feat(stack-encrypt): size a match query's fetch with target_limit #1192, feat(stack-encrypt): store short TextMatch text as an empty filter, refuse only short queries #1206, feat(stack-encrypt): ordering operators Lt, Lte, Gt, Gte and Between, and remove query_index #1208, feat(stack-encrypt): JSON operators Contains, ContainedBy and AtPath #1209, feat(stack-encrypt)!: move the stack crates, the guests and the Go module onto vitaminc ADR 0001 #1213, feat(stack-encrypt)!: derive terms through vitaminc-normalize and walk dynamic values as Plaintext #1214, feat(stack-encrypt): query a plan field by operator through the guest, with verify and target_limit as exports #1215, feat(golang)!: generate one query method per operator, with Verify and TargetLimit on a matches query #1216. Before it lands, feat(stack-encrypt)!: move the stack crates, the guests and the Go module onto vitaminc ADR 0001 #1213 moves its vitaminc pin from the deleted branch feat/aead-remove-legacy-traits to one commit on vitaminc main, and takes vitaminc's breaking changes since then.
  3. Not planned yet: the KMS stack (feat(stack-kms): ZeroKMS as a vitaminc key provider (CIP-3965) #1084, feat(stack-encrypt)!: keysets resolve through a KeysetRegistry, and sealed leaves move to format 2 (CIP-4140) #1085, feat(stack-encrypt): run vendor KMS backends through a static keyset registry (CIP-3965) #1083). It is built on a vitaminc commit that is no longer on any branch, and it needs vitaminc's KMS work rebased first.

Rules for this branch

  • Pin vitaminc and ore.rs with rev, never branch. A branch is deleted when its stack merges.
  • Use one vitaminc commit in every Cargo workspace that pins one: the root, both Go guests, packages/eql and packages/stack-encrypt/fuzz. Two commits mean two copies of vitaminc's traits, and the code stops compiling.

Changes

  • One empty commit, so the branch has a pull request. The stacks above add the content.

Verification

  • next was created from main at 2a70a47. Nothing has been built yet, because nothing has changed.

Related

@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 712 files, which is 612 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

Usage-priced reviews support at most 300 files.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI; Enforced overrides: Organization
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b0be6a6a-cb3c-4ef0-beec-08df415c5163
Commits

Reviewing files that changed from the base of the PR and between 8d48bbc and 7d63656.

Files ignored due to path filters: 10
  • Cargo.lock is excluded by !**/*.lock
  • languages/golang/auth/guest/Cargo.lock is excluded by !**/*.lock
  • languages/golang/encrypt/guest/Cargo.lock is excluded by !**/*.lock
  • languages/golang/go.sum is excluded by !**/*.sum
  • languages/typescript/packages/protect-ffi/Cargo.lock is excluded by !**/*.lock
  • packages/eql/Cargo.lock is excluded by !**/*.lock
  • packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.lock is excluded by !**/*.lock
  • packages/stack-auth/fuzz/Cargo.lock is excluded by !**/*.lock
  • packages/stack-encrypt/fuzz/Cargo.lock is excluded by !**/*.lock
  • packages/stack-kms/fuzz/Cargo.lock is excluded by !**/*.lock
Files selected for processing: 712
  • .cargo/mutants.toml
  • .changeset/chacha20-0-10-2.md
  • .changeset/eql-bindings-optional-storage-only.md
  • .changeset/eql-lints-own-domains.md
  • .changeset/eql-plan-field-targets.md
  • .changeset/eql-target-match-options.md
  • .changeset/eql-text-equality-transcoding.md
  • .changeset/eql-v4-bindings.md
  • .changeset/eql-v4-block-ore-types.md
  • .changeset/eql-v4-date-timestamp-numeric.md
  • .changeset/eql-v4-order-term-shape.md
  • .changeset/eql-v4-ordered-date-timestamp-numeric.md
  • .changeset/eql-v4-ordered-ope-types.md
  • .changeset/eql-v4-smallint.md
  • .changeset/eql-v4-text-search-optional-terms.md
  • .github/actions/build-ffi-binding/action.yml
  • .github/copilot-instructions.md
  • .github/dependabot.yml
  • .github/workflows/integration-drizzle.yml
  • .github/workflows/integration-prisma-next.yml
  • .github/workflows/integration-protect-ffi.yml
  • .github/workflows/integration-supabase.yml
  • .github/workflows/prisma-example-readme-e2e.yml
  • .github/workflows/prisma-next-e2e.yml
  • .github/workflows/test-eql.yml
  • .github/workflows/tests-bench.yml
  • .github/workflows/tests-golang.yml
  • .github/workflows/tests-rust.yml
  • .github/workflows/tests.yml
  • AGENTS.md
  • Cargo.toml
  • biome.json
  • docs/adr/0002-one-value-model-three-encodings-and-eql-v4-by-producer.md
  • docs/plans/2026-10-04-plan-builder.md
  • docs/plans/2026-10-11-order-and-equality-terms-layering.md
  • docs/plans/2026-10-17-json-tree-index.md
  • docs/plans/2026-10-17-json-tree-index/containment-oracle.sql
  • docs/plans/2026-10-17-json-tree-index/jsonb-semantics.sql
  • docs/plans/2026-10-17-json-tree-index/token-chain.sql
  • languages/golang/CHANGELOG.md
  • languages/golang/auth/cancel_test.go
  • languages/golang/auth/doc.go
  • languages/golang/auth/guest.go
  • languages/golang/auth/guest/Cargo.toml
  • languages/golang/auth/guest/src/lib.rs
  • languages/golang/auth/guest/src/ops.rs
  • languages/golang/auth/guest/tests/leak.rs
  • languages/golang/auth/store.go
  • languages/golang/auth/strategy.go
  • languages/golang/auth/transport.go
  • languages/golang/cmd/stashgen/README.md
  • languages/golang/cmd/stashgen/main_test.go
  • languages/golang/encrypt/README.md
  • languages/golang/encrypt/cancel_test.go
  • languages/golang/encrypt/checker.go
  • languages/golang/encrypt/ciphertext.go
  • languages/golang/encrypt/client.go
  • languages/golang/encrypt/context_field_test.go
  • languages/golang/encrypt/diagnostic_test.go
  • languages/golang/encrypt/doc.go
  • languages/golang/encrypt/eql/eql.go
  • languages/golang/encrypt/eql/eql_gen.go
  • languages/golang/encrypt/eql/eql_test.go
  • languages/golang/encrypt/eql_order_postgres_test.go
  • languages/golang/encrypt/eql_postgres_test.go
  • languages/golang/encrypt/eql_test.go
  • languages/golang/encrypt/eql_v4_ledger_test.go
  • languages/golang/encrypt/eql_v4_order_test.go
  • languages/golang/encrypt/eql_v4_smallint_test.go
  • languages/golang/encrypt/eql_v4_test.go
  • languages/golang/encrypt/eql_v4_text_search_test.go
  • languages/golang/encrypt/errors_test.go
  • languages/golang/encrypt/example/README.md
  • languages/golang/encrypt/example/main.go
  • languages/golang/encrypt/example/user_stash.go
  • languages/golang/encrypt/export_test.go
  • languages/golang/encrypt/fixture_test.go
  • languages/golang/encrypt/generated_paths_test.go
  • languages/golang/encrypt/gensupport/codec.go
  • languages/golang/encrypt/gensupport/convert.go
  • languages/golang/encrypt/gensupport/declaration.go
  • languages/golang/encrypt/gensupport/field.go
  • languages/golang/encrypt/gensupport/gensupport_internal_test.go
  • languages/golang/encrypt/gensupport/widen.go
  • languages/golang/encrypt/guest.go
  • languages/golang/encrypt/guest/Cargo.toml
  • languages/golang/encrypt/guest/src/abi.rs
  • languages/golang/encrypt/guest/src/config.rs
  • languages/golang/encrypt/guest/src/deterministic.rs
  • languages/golang/encrypt/guest/src/host.rs
  • languages/golang/encrypt/guest/src/io.rs
  • languages/golang/encrypt/guest/src/lib.rs
  • languages/golang/encrypt/guest/src/ops.rs
  • languages/golang/encrypt/guest/src/options.rs
  • languages/golang/encrypt/guest/src/status.rs
  • languages/golang/encrypt/guest/src/targets.rs
  • languages/golang/encrypt/guest/src/test_frame.rs
  • languages/golang/encrypt/guest/tests/leak.rs
  • languages/golang/encrypt/guest/tests/native_ops.rs
  • languages/golang/encrypt/guest/tests/support/mod.rs
  • languages/golang/encrypt/guest_test.go
  • languages/golang/encrypt/internal/testpolicy/member_stash.go
  • languages/golang/encrypt/internal/testusers/account_stash.go
  • languages/golang/encrypt/internal/testusers/birthday_stash.go
  • languages/golang/encrypt/internal/testusers/contact_stash.go
  • languages/golang/encrypt/internal/testusers/directory.go
  • languages/golang/encrypt/internal/testusers/entry_stash.go
  • languages/golang/encrypt/internal/testusers/kinds.go
  • languages/golang/encrypt/internal/testusers/kinds_stash.go
  • languages/golang/encrypt/internal/testusers/ledger.go
  • languages/golang/encrypt/internal/testusers/ledger_stash.go
  • languages/golang/encrypt/internal/testusers/lookup_stash.go
  • languages/golang/encrypt/internal/testusers/memberstash_stash.go
  • languages/golang/encrypt/internal/testusers/note_stash.go
  • languages/golang/encrypt/internal/testusers/people.go
  • languages/golang/encrypt/internal/testusers/person_stash.go
  • languages/golang/encrypt/internal/testusers/probe_stash.go
  • languages/golang/encrypt/internal/testusers/profile_stash.go
  • languages/golang/encrypt/internal/testusers/profiles.go
  • languages/golang/encrypt/internal/testusers/queryprofile_stash.go
  • languages/golang/encrypt/internal/testusers/ranking.go
  • languages/golang/encrypt/internal/testusers/ranking_stash.go
  • languages/golang/encrypt/internal/testusers/tally.go
  • languages/golang/encrypt/internal/testusers/tally_stash.go
  • languages/golang/encrypt/internal/testusers/user_stash.go
  • languages/golang/encrypt/internal/testusers/users.go
  • languages/golang/encrypt/internal/testusers/valuekinds_stash.go
  • languages/golang/encrypt/internal/testusers/widened_stash.go
  • languages/golang/encrypt/kinds_test.go
  • languages/golang/encrypt/live_test.go
  • languages/golang/encrypt/locate_test.go
  • languages/golang/encrypt/memory_test.go
  • languages/golang/encrypt/null_test.go
  • languages/golang/encrypt/order_test.go
  • languages/golang/encrypt/postgres_test.go
  • languages/golang/encrypt/query.go
  • languages/golang/encrypt/query_test.go
  • languages/golang/encrypt/records.go
  • languages/golang/encrypt/roundtrip_test.go
  • languages/golang/encrypt/step.go
  • languages/golang/encrypt/step_test.go
  • languages/golang/encrypt/targets_test.go
  • languages/golang/encrypt/transport.go
  • languages/golang/encrypt/unit_test.go
  • languages/golang/encrypt/value_kinds_test.go
  • languages/golang/encrypt/values.go
  • languages/golang/encrypt/widened_test.go
  • languages/golang/go.mod
  • languages/golang/internal/guest/call.go
  • languages/golang/internal/guest/errors.go
  • languages/golang/internal/guest/lock.go
  • languages/golang/internal/guest/lock_test.go
  • languages/golang/internal/guest/status.go
  • languages/golang/internal/record/record.go
  • languages/golang/stashgen/declaration.go
  • languages/golang/stashgen/emit.go
  • languages/golang/stashgen/engine.go
  • languages/golang/stashgen/enginetest/enginetest.go
  • languages/golang/stashgen/generate.go
  • languages/golang/stashgen/golden_test.go
  • languages/golang/stashgen/lower_test.go
  • languages/golang/stashgen/policy.go
  • languages/golang/stashgen/read.go
  • languages/golang/stashgen/refusal_test.go
  • languages/golang/stashgen/tag.go
  • languages/golang/stashgen/testdata/cases/accounts/account_stash.go.golden
  • languages/golang/stashgen/testdata/cases/contacts/contacts.go
  • languages/golang/stashgen/testdata/cases/contacts/contactstash_stash.go.golden
  • languages/golang/stashgen/testdata/cases/directory/directory.go
  • languages/golang/stashgen/testdata/cases/directory/entry_stash.go.golden
  • languages/golang/stashgen/testdata/cases/directory/go.mod
  • languages/golang/stashgen/testdata/cases/embedded/patient_stash.go.golden
  • languages/golang/stashgen/testdata/cases/foreign/individualstash_stash.go.golden
  • languages/golang/stashgen/testdata/cases/orders/order_stash.go.golden
  • languages/golang/stashgen/testdata/cases/orders/refund_stash.go.golden
  • languages/golang/stashgen/testdata/cases/tenants/note_stash.go.golden
  • languages/golang/stashgen/testdata/cases/users/model.go
  • languages/golang/stashgen/testdata/cases/users/user_stash.go.golden
  • languages/golang/stashgen/testdata/policy_individual_stash.go.golden
  • languages/golang/stashgen/testdata/stubsdk/encrypt/encrypt.go
  • languages/golang/stashgen/testdata/stubsdk/encrypt/eql/eql.go
  • languages/golang/stashgen/testdata/stubsdk/encrypt/gensupport/gensupport.go
  • mise.toml
  • packages/eql/.gitattributes
  • packages/eql/.gitignore
  • packages/eql/AGENTS.md
  • packages/eql/crates/eql-bindings/CHANGELOG.md
  • packages/eql/crates/eql-bindings/Cargo.toml
  • packages/eql/crates/eql-bindings/README.md
  • packages/eql/crates/eql-bindings/src/encryption.rs
  • packages/eql/crates/eql-bindings/src/encryption/example.rs
  • packages/eql/crates/eql-bindings/src/encryption/query.rs
  • packages/eql/crates/eql-bindings/src/encryption/query_example.rs
  • packages/eql/crates/eql-bindings/src/encryption/targets.rs
  • packages/eql/crates/eql-bindings/src/lib.rs
  • packages/eql/crates/eql-bindings/src/v3/bigint.rs
  • packages/eql/crates/eql-bindings/src/v3/boolean.rs
  • packages/eql/crates/eql-bindings/src/v3/date.rs
  • packages/eql/crates/eql-bindings/src/v3/domain_type.rs
  • packages/eql/crates/eql-bindings/src/v3/double.rs
  • packages/eql/crates/eql-bindings/src/v3/integer.rs
  • packages/eql/crates/eql-bindings/src/v3/json_storage.rs
  • packages/eql/crates/eql-bindings/src/v3/mod.rs
  • packages/eql/crates/eql-bindings/src/v3/numeric.rs
  • packages/eql/crates/eql-bindings/src/v3/real.rs
  • packages/eql/crates/eql-bindings/src/v3/smallint.rs
  • packages/eql/crates/eql-bindings/src/v3/targets.rs
  • packages/eql/crates/eql-bindings/src/v3/text.rs
  • packages/eql/crates/eql-bindings/src/v3/timestamp.rs
  • packages/eql/crates/eql-bindings/src/v4/answers.rs
  • packages/eql/crates/eql-bindings/src/v4/bigint.rs
  • packages/eql/crates/eql-bindings/src/v4/boolean.rs
  • packages/eql/crates/eql-bindings/src/v4/date.rs
  • packages/eql/crates/eql-bindings/src/v4/double.rs
  • packages/eql/crates/eql-bindings/src/v4/integer.rs
  • packages/eql/crates/eql-bindings/src/v4/inventory.rs
  • packages/eql/crates/eql-bindings/src/v4/json.rs
  • packages/eql/crates/eql-bindings/src/v4/mod.rs
  • packages/eql/crates/eql-bindings/src/v4/numeric.rs
  • packages/eql/crates/eql-bindings/src/v4/plaintext.rs
  • packages/eql/crates/eql-bindings/src/v4/real.rs
  • packages/eql/crates/eql-bindings/src/v4/smallint.rs
  • packages/eql/crates/eql-bindings/src/v4/targets.rs
  • packages/eql/crates/eql-bindings/src/v4/term_formats.rs
  • packages/eql/crates/eql-bindings/src/v4/text.rs
  • packages/eql/crates/eql-bindings/src/v4/timestamp.rs
  • packages/eql/crates/eql-bindings/tests/v4_inventory.rs
  • packages/eql/crates/eql-codegen/src/bindings.rs
  • packages/eql/crates/eql-codegen/src/consts.rs
  • packages/eql/crates/eql-codegen/src/context.rs
  • packages/eql/crates/eql-codegen/src/generate.rs
  • packages/eql/crates/eql-codegen/src/go_eql.rs
  • packages/eql/crates/eql-codegen/src/lib.rs
  • packages/eql/crates/eql-codegen/src/main.rs
  • packages/eql/crates/eql-codegen/src/range.rs
  • packages/eql/crates/eql-codegen/src/render.rs
  • packages/eql/crates/eql-codegen/src/targets.rs
  • packages/eql/crates/eql-codegen/templates/functions/extractor.sql.j2
  • packages/eql/crates/eql-codegen/templates/ore_fallback.sql.j2
  • packages/eql/crates/eql-codegen/templates/query_types.sql.j2
  • packages/eql/crates/eql-codegen/templates/range_functions.sql.j2
  • packages/eql/crates/eql-codegen/templates/range_types.sql.j2
  • packages/eql/crates/eql-codegen/templates/types.sql.j2
  • packages/eql/crates/eql-codegen/tests/bindings_parity.rs
  • packages/eql/crates/eql-codegen/tests/cli.rs
  • packages/eql/crates/eql-domains/src/lib.rs
  • packages/eql/crates/eql-domains/src/spec.rs
  • packages/eql/crates/eql-domains/src/term.rs
  • packages/eql/crates/eql-domains/src/tests.rs
  • packages/eql/docs/reference/adding-a-scalar-encrypted-domain-type.md
  • packages/eql/docs/reference/catalog-driven-architecture.md
  • packages/eql/docs/reference/eql-functions.md
  • packages/eql/docs/upgrading/v3.1.md
  • packages/eql/mise.toml
  • packages/eql/src/v3/aggregates.sql
  • packages/eql/src/v3/common.sql
  • packages/eql/src/v3/crypto.sql
  • packages/eql/src/v3/json/aggregates.sql
  • packages/eql/src/v3/json/blockers.sql
  • packages/eql/src/v3/json/functions.sql
  • packages/eql/src/v3/json/operators.sql
  • packages/eql/src/v3/json/types.sql
  • packages/eql/src/v3/lint/lints.sql
  • packages/eql/src/v3/scalars/bigint/bigint_eq_functions.sql
  • packages/eql/src/v3/scalars/bigint/bigint_eq_operators.sql
  • packages/eql/src/v3/scalars/bigint/bigint_functions.sql
  • packages/eql/src/v3/scalars/bigint/bigint_operators.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_aggregates.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_functions.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_operators.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/bigint/bigint_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/bigint/bigint_types.sql
  • packages/eql/src/v3/scalars/bigint/json_entry_bigint_functions.sql
  • packages/eql/src/v3/scalars/bigint/json_entry_bigint_operators.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_eq_functions.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_eq_operators.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_ord_functions.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_ord_operators.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_range_functions.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_range_types.sql
  • packages/eql/src/v3/scalars/bigint/query_bigint_types.sql
  • packages/eql/src/v3/scalars/boolean/boolean_functions.sql
  • packages/eql/src/v3/scalars/boolean/boolean_operators.sql
  • packages/eql/src/v3/scalars/boolean/boolean_types.sql
  • packages/eql/src/v3/scalars/date/date_eq_functions.sql
  • packages/eql/src/v3/scalars/date/date_eq_operators.sql
  • packages/eql/src/v3/scalars/date/date_functions.sql
  • packages/eql/src/v3/scalars/date/date_operators.sql
  • packages/eql/src/v3/scalars/date/date_ord_aggregates.sql
  • packages/eql/src/v3/scalars/date/date_ord_functions.sql
  • packages/eql/src/v3/scalars/date/date_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/date/date_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/date/date_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/date/date_ord_operators.sql
  • packages/eql/src/v3/scalars/date/date_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/date/date_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/date/date_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/date/date_types.sql
  • packages/eql/src/v3/scalars/date/json_entry_date_functions.sql
  • packages/eql/src/v3/scalars/date/json_entry_date_operators.sql
  • packages/eql/src/v3/scalars/date/query_date_eq_functions.sql
  • packages/eql/src/v3/scalars/date/query_date_eq_operators.sql
  • packages/eql/src/v3/scalars/date/query_date_ord_functions.sql
  • packages/eql/src/v3/scalars/date/query_date_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/date/query_date_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/date/query_date_ord_operators.sql
  • packages/eql/src/v3/scalars/date/query_date_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/date/query_date_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/date/query_date_range_functions.sql
  • packages/eql/src/v3/scalars/date/query_date_range_types.sql
  • packages/eql/src/v3/scalars/date/query_date_types.sql
  • packages/eql/src/v3/scalars/double/double_eq_functions.sql
  • packages/eql/src/v3/scalars/double/double_eq_operators.sql
  • packages/eql/src/v3/scalars/double/double_functions.sql
  • packages/eql/src/v3/scalars/double/double_operators.sql
  • packages/eql/src/v3/scalars/double/double_ord_aggregates.sql
  • packages/eql/src/v3/scalars/double/double_ord_functions.sql
  • packages/eql/src/v3/scalars/double/double_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/double/double_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/double/double_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/double/double_ord_operators.sql
  • packages/eql/src/v3/scalars/double/double_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/double/double_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/double/double_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/double/double_types.sql
  • packages/eql/src/v3/scalars/double/json_entry_double_functions.sql
  • packages/eql/src/v3/scalars/double/json_entry_double_operators.sql
  • packages/eql/src/v3/scalars/double/query_double_eq_functions.sql
  • packages/eql/src/v3/scalars/double/query_double_eq_operators.sql
  • packages/eql/src/v3/scalars/double/query_double_ord_functions.sql
  • packages/eql/src/v3/scalars/double/query_double_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/double/query_double_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/double/query_double_ord_operators.sql
  • packages/eql/src/v3/scalars/double/query_double_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/double/query_double_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/double/query_double_range_functions.sql
  • packages/eql/src/v3/scalars/double/query_double_range_types.sql
  • packages/eql/src/v3/scalars/double/query_double_types.sql
  • packages/eql/src/v3/scalars/functions.sql
  • packages/eql/src/v3/scalars/integer/integer_eq_functions.sql
  • packages/eql/src/v3/scalars/integer/integer_eq_operators.sql
  • packages/eql/src/v3/scalars/integer/integer_functions.sql
  • packages/eql/src/v3/scalars/integer/integer_operators.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_aggregates.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_functions.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_operators.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/integer/integer_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/integer/integer_types.sql
  • packages/eql/src/v3/scalars/integer/json_entry_integer_functions.sql
  • packages/eql/src/v3/scalars/integer/json_entry_integer_operators.sql
  • packages/eql/src/v3/scalars/integer/query_integer_eq_functions.sql
  • packages/eql/src/v3/scalars/integer/query_integer_eq_operators.sql
  • packages/eql/src/v3/scalars/integer/query_integer_ord_functions.sql
  • packages/eql/src/v3/scalars/integer/query_integer_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/integer/query_integer_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/integer/query_integer_ord_operators.sql
  • packages/eql/src/v3/scalars/integer/query_integer_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/integer/query_integer_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/integer/query_integer_range_functions.sql
  • packages/eql/src/v3/scalars/integer/query_integer_range_types.sql
  • packages/eql/src/v3/scalars/integer/query_integer_types.sql
  • packages/eql/src/v3/scalars/json/json_functions.sql
  • packages/eql/src/v3/scalars/json/json_operators.sql
  • packages/eql/src/v3/scalars/json/json_types.sql
  • packages/eql/src/v3/scalars/numeric/json_entry_numeric_functions.sql
  • packages/eql/src/v3/scalars/numeric/json_entry_numeric_operators.sql
  • packages/eql/src/v3/scalars/numeric/numeric_eq_functions.sql
  • packages/eql/src/v3/scalars/numeric/numeric_eq_operators.sql
  • packages/eql/src/v3/scalars/numeric/numeric_functions.sql
  • packages/eql/src/v3/scalars/numeric/numeric_operators.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_aggregates.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_functions.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_operators.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/numeric/numeric_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/numeric/numeric_types.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_eq_functions.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_eq_operators.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_ord_functions.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_ord_operators.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_range_functions.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_range_types.sql
  • packages/eql/src/v3/scalars/numeric/query_numeric_types.sql
  • packages/eql/src/v3/scalars/ore_fallback.sql
  • packages/eql/src/v3/scalars/real/json_entry_real_functions.sql
  • packages/eql/src/v3/scalars/real/json_entry_real_operators.sql
  • packages/eql/src/v3/scalars/real/query_real_eq_functions.sql
  • packages/eql/src/v3/scalars/real/query_real_eq_operators.sql
  • packages/eql/src/v3/scalars/real/query_real_ord_functions.sql
  • packages/eql/src/v3/scalars/real/query_real_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/real/query_real_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/real/query_real_ord_operators.sql
  • packages/eql/src/v3/scalars/real/query_real_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/real/query_real_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/real/query_real_range_functions.sql
  • packages/eql/src/v3/scalars/real/query_real_range_types.sql
  • packages/eql/src/v3/scalars/real/query_real_types.sql
  • packages/eql/src/v3/scalars/real/real_eq_functions.sql
  • packages/eql/src/v3/scalars/real/real_eq_operators.sql
  • packages/eql/src/v3/scalars/real/real_functions.sql
  • packages/eql/src/v3/scalars/real/real_operators.sql
  • packages/eql/src/v3/scalars/real/real_ord_aggregates.sql
  • packages/eql/src/v3/scalars/real/real_ord_functions.sql
  • packages/eql/src/v3/scalars/real/real_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/real/real_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/real/real_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/real/real_ord_operators.sql
  • packages/eql/src/v3/scalars/real/real_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/real/real_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/real/real_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/real/real_types.sql
  • packages/eql/src/v3/scalars/smallint/json_entry_smallint_functions.sql
  • packages/eql/src/v3/scalars/smallint/json_entry_smallint_operators.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_eq_functions.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_eq_operators.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_ord_functions.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_ord_operators.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_range_functions.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_range_types.sql
  • packages/eql/src/v3/scalars/smallint/query_smallint_types.sql
  • packages/eql/src/v3/scalars/smallint/smallint_eq_functions.sql
  • packages/eql/src/v3/scalars/smallint/smallint_eq_operators.sql
  • packages/eql/src/v3/scalars/smallint/smallint_functions.sql
  • packages/eql/src/v3/scalars/smallint/smallint_operators.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_aggregates.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_functions.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_operators.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/smallint/smallint_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/smallint/smallint_types.sql
  • packages/eql/src/v3/scalars/text/json_entry_text_functions.sql
  • packages/eql/src/v3/scalars/text/json_entry_text_operators.sql
  • packages/eql/src/v3/scalars/text/query_text_eq_functions.sql
  • packages/eql/src/v3/scalars/text/query_text_eq_operators.sql
  • packages/eql/src/v3/scalars/text/query_text_match_functions.sql
  • packages/eql/src/v3/scalars/text/query_text_match_operators.sql
  • packages/eql/src/v3/scalars/text/query_text_ord_functions.sql
  • packages/eql/src/v3/scalars/text/query_text_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/text/query_text_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/text/query_text_ord_operators.sql
  • packages/eql/src/v3/scalars/text/query_text_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/text/query_text_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/text/query_text_range_functions.sql
  • packages/eql/src/v3/scalars/text/query_text_range_types.sql
  • packages/eql/src/v3/scalars/text/query_text_search_functions.sql
  • packages/eql/src/v3/scalars/text/query_text_search_operators.sql
  • packages/eql/src/v3/scalars/text/query_text_search_ore_functions.sql
  • packages/eql/src/v3/scalars/text/query_text_search_ore_operators.sql
  • packages/eql/src/v3/scalars/text/query_text_types.sql
  • packages/eql/src/v3/scalars/text/text_eq_functions.sql
  • packages/eql/src/v3/scalars/text/text_eq_operators.sql
  • packages/eql/src/v3/scalars/text/text_functions.sql
  • packages/eql/src/v3/scalars/text/text_match_functions.sql
  • packages/eql/src/v3/scalars/text/text_match_operators.sql
  • packages/eql/src/v3/scalars/text/text_operators.sql
  • packages/eql/src/v3/scalars/text/text_ord_aggregates.sql
  • packages/eql/src/v3/scalars/text/text_ord_functions.sql
  • packages/eql/src/v3/scalars/text/text_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/text/text_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/text/text_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/text/text_ord_operators.sql
  • packages/eql/src/v3/scalars/text/text_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/text/text_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/text/text_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/text/text_search_aggregates.sql
  • packages/eql/src/v3/scalars/text/text_search_functions.sql
  • packages/eql/src/v3/scalars/text/text_search_operators.sql
  • packages/eql/src/v3/scalars/text/text_search_ore_aggregates.sql
  • packages/eql/src/v3/scalars/text/text_search_ore_functions.sql
  • packages/eql/src/v3/scalars/text/text_search_ore_operators.sql
  • packages/eql/src/v3/scalars/text/text_types.sql
  • packages/eql/src/v3/scalars/timestamp/json_entry_timestamp_functions.sql
  • packages/eql/src/v3/scalars/timestamp/json_entry_timestamp_operators.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_eq_functions.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_eq_operators.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_ord_functions.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_ord_operators.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_range_functions.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_range_types.sql
  • packages/eql/src/v3/scalars/timestamp/query_timestamp_types.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_eq_functions.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_eq_operators.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_functions.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_operators.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_aggregates.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_functions.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_ope_aggregates.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_ope_functions.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_ope_operators.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_operators.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_ore_aggregates.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_ore_functions.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_ord_ore_operators.sql
  • packages/eql/src/v3/scalars/timestamp/timestamp_types.sql
  • packages/eql/src/v3/schema.sql
  • packages/eql/src/v3/sem/bloom_filter/functions.sql
  • packages/eql/src/v3/sem/bloom_filter/types.sql
  • packages/eql/src/v3/sem/hmac_256/functions.sql
  • packages/eql/src/v3/sem/hmac_256/types.sql
  • packages/eql/src/v3/sem/ope_cllw/functions.sql
  • packages/eql/src/v3/sem/ope_cllw/types.sql
  • packages/eql/src/v3/sem/ore_block_256/functions.sql
  • packages/eql/src/v3/sem/ore_block_256/operator_class.sql
  • packages/eql/src/v3/sem/ore_block_256/operators.sql
  • packages/eql/src/v3/sem/ore_block_256/types.sql
  • packages/eql/src/v3/version.template
  • packages/eql/tasks/build.sh
  • packages/eql/tasks/docs/doxygen-filter.sh
  • packages/eql/tasks/docs/validate/documented-sql.sh
  • packages/eql/tasks/githooks/pre-commit
  • packages/eql/tasks/pin_search_path_v3.sql
  • packages/eql/tasks/schemas-parity.sh
  • packages/eql/tasks/test/docs_v3_grep.sh
  • packages/eql/tasks/test/v4_isolation_selftest.sh
  • packages/eql/tasks/test/verify_installer_complete.sh
  • packages/eql/tasks/test/verify_no_v3_in_v4.sh
  • packages/eql/tasks/test/verify_symbol_order_v3.sh
  • packages/eql/tasks/uninstall-v3.sql
  • packages/eql/tests/encryption/Cargo.toml
  • packages/eql/tests/encryption/fixtures/README.md
  • packages/eql/tests/encryption/fixtures/stored_v4_rows_v1.json
  • packages/eql/tests/encryption/fixtures/text_eq_query.json
  • packages/eql/tests/encryption/fixtures/v4_ledger_queries.json
  • packages/eql/tests/encryption/fixtures/v4_ledger_rows.json
  • packages/eql/tests/encryption/fixtures/v4_ordered_queries.json
  • packages/eql/tests/encryption/fixtures/v4_ordered_rows.json
  • packages/eql/tests/encryption/fixtures/v4_queries.json
  • packages/eql/tests/encryption/fixtures/v4_rows.json
  • packages/eql/tests/encryption/fixtures/v4_smallint_rows.json
  • packages/eql/tests/encryption/tests/common/mod.rs
  • packages/eql/tests/encryption/tests/heap_hygiene.rs
  • packages/eql/tests/encryption/tests/targets.rs
  • packages/eql/tests/encryption/tests/text_eq.rs
  • packages/eql/tests/encryption/tests/typed_queries.rs
  • packages/eql/tests/encryption/tests/v4_date_time_numeric.rs
  • packages/eql/tests/encryption/tests/v4_order.rs
  • packages/eql/tests/encryption/tests/v4_ore_block.rs
  • packages/eql/tests/encryption/tests/v4_range.rs
  • packages/eql/tests/encryption/tests/v4_text_search.rs
  • packages/eql/tests/encryption/tests/v4_types.rs
  • packages/eql/tests/sqlx/tests/v3_v4_coexistence_tests.rs
  • packages/eql/tests/timing/ore_block_v2/README.md
  • packages/eql/tests/timing/ore_block_v2/ctgen/.gitignore
  • packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.toml
  • packages/eql/tests/timing/ore_block_v2/ctgen/src/main.rs
  • packages/eql/tests/timing/ore_block_v2/harness.sql
  • packages/eql/tests/timing/ore_block_v2/run.sh
  • packages/stack-encrypt-derive/Cargo.toml
  • packages/stack-encrypt-derive/src/lib.rs
  • packages/stack-encrypt/CHANGELOG.md
  • packages/stack-encrypt/CONTEXT.md
  • packages/stack-encrypt/Cargo.toml
  • packages/stack-encrypt/docs/adr/0004-one-context-per-target-threaded-through-the-declaration-tree.md
  • packages/stack-encrypt/docs/adr/0007-bindings-enter-through-a-plan-never-a-second-executor.md
  • packages/stack-encrypt/docs/adr/0009-operators-select-the-index-and-a-query-term-is-not-the-stored-term.md
  • packages/stack-encrypt/docs/adr/0010-what-a-stored-value-authenticates.md
  • packages/stack-encrypt/examples/mixed_user.rs
  • packages/stack-encrypt/examples/search_terms.rs
  • packages/stack-encrypt/fuzz/Cargo.toml
  • packages/stack-encrypt/fuzz/fuzz_targets/check_record.rs
  • packages/stack-encrypt/fuzz/fuzz_targets/term_decode.rs
  • packages/stack-encrypt/src/cipher.rs
  • packages/stack-encrypt/src/codes.rs
  • packages/stack-encrypt/src/dynamic/context.rs
  • packages/stack-encrypt/src/dynamic/kind.rs
  • packages/stack-encrypt/src/dynamic/mod.rs
  • packages/stack-encrypt/src/dynamic/query.rs
  • packages/stack-encrypt/src/dynamic/record.rs
  • packages/stack-encrypt/src/dynamic/target.rs
  • packages/stack-encrypt/src/dynamic/term.rs
  • packages/stack-encrypt/src/dynamic/test_frame.rs
  • packages/stack-encrypt/src/dynamic/value.rs
  • packages/stack-encrypt/src/dynamic/value_frame.rs
  • packages/stack-encrypt/src/lib.rs
  • packages/stack-encrypt/src/op/mod.rs
  • packages/stack-encrypt/src/op/stats.rs
  • packages/stack-encrypt/src/plan/build.rs
  • packages/stack-encrypt/src/plan/chain.rs
  • packages/stack-encrypt/src/plan/error.rs
  • packages/stack-encrypt/src/plan/field_ref.rs
  • packages/stack-encrypt/src/plan/mod.rs
  • packages/stack-encrypt/src/plan/value.rs
  • packages/stack-encrypt/src/sem/mod.rs
  • packages/stack-encrypt/src/sem/tokenize.rs
  • packages/stack-encrypt/src/target/context.rs
  • packages/stack-encrypt/src/target/core.rs
  • packages/stack-encrypt/src/target/index.rs
  • packages/stack-encrypt/src/target/mod.rs
  • packages/stack-encrypt/src/target/operations.rs
  • packages/stack-encrypt/src/target/source.rs
  • packages/stack-encrypt/src/target/transcode.rs
  • packages/stack-encrypt/src/value.rs
  • packages/stack-encrypt/tests/common/mod.rs
  • packages/stack-encrypt/tests/derive.rs
  • packages/stack-encrypt/tests/derive_plan.rs
  • packages/stack-encrypt/tests/fixtures/README.md
  • packages/stack-encrypt/tests/fixtures/query_operators.json
  • packages/stack-encrypt/tests/fixtures/record_lowering.json
  • packages/stack-encrypt/tests/fixtures/stored_rows_v1.json
  • packages/stack-encrypt/tests/fixtures/value_kinds.json
  • packages/stack-encrypt/tests/frozen_bytes.rs
  • packages/stack-encrypt/tests/heap_hygiene.rs
  • packages/stack-encrypt/tests/index.rs
  • packages/stack-encrypt/tests/op.rs
  • packages/stack-encrypt/tests/ore_block.rs
  • packages/stack-encrypt/tests/plan.rs
  • packages/stack-encrypt/tests/plan_grammar.rs
  • packages/stack-encrypt/tests/query_operators.rs
  • packages/stack-encrypt/tests/record_lowering.rs
  • packages/stack-encrypt/tests/roundtrip.rs
  • packages/stack-encrypt/tests/sem_terms.rs
  • packages/stack-encrypt/tests/source_mode.rs
  • packages/stack-encrypt/tests/stored_rows.rs
  • packages/stack-encrypt/tests/target.rs
  • packages/stack-encrypt/tests/term_bytes.rs
  • packages/stack-encrypt/tests/term_serde.rs
  • packages/stack-encrypt/tests/transcode.rs
  • packages/stack-encrypt/tests/ui.rs
  • packages/stack-encrypt/tests/ui/decrypt_field_not_decryptable.stderr
  • packages/stack-encrypt/tests/ui/drop_record.stderr
  • packages/stack-encrypt/tests/ui/match_in_a_tuple_on_integer.rs
  • packages/stack-encrypt/tests/ui/match_in_a_tuple_on_integer.stderr
  • packages/stack-encrypt/tests/ui/match_on_integer.rs
  • packages/stack-encrypt/tests/ui/match_on_integer.stderr
  • packages/stack-encrypt/tests/ui/op_at_path_inherits_fidelity.rs
  • packages/stack-encrypt/tests/ui/op_at_path_inherits_fidelity.stderr
  • packages/stack-encrypt/tests/ui/op_at_path_not_a_leaf.rs
  • packages/stack-encrypt/tests/ui/op_at_path_not_a_leaf.stderr
  • packages/stack-encrypt/tests/ui/op_between_takes_a_pair.rs
  • packages/stack-encrypt/tests/ui/op_between_takes_a_pair.stderr
  • packages/stack-encrypt/tests/ui/op_case_mismatch.rs
  • packages/stack-encrypt/tests/ui/op_case_mismatch.stderr
  • packages/stack-encrypt/tests/ui/op_inexact_operator_needs_probabilistic.rs
  • packages/stack-encrypt/tests/ui/op_inexact_operator_needs_probabilistic.stderr
  • packages/stack-encrypt/tests/ui/op_json_not_answered.rs
  • packages/stack-encrypt/tests/ui/op_json_not_answered.stderr
  • packages/stack-encrypt/tests/ui/op_matches_on_integer.rs
  • packages/stack-encrypt/tests/ui/op_matches_on_integer.stderr
  • packages/stack-encrypt/tests/ui/op_order_on_bytes.rs
  • packages/stack-encrypt/tests/ui/op_order_on_bytes.stderr
  • packages/stack-encrypt/tests/ui/op_target_does_not_answer.rs
  • packages/stack-encrypt/tests/ui/op_target_does_not_answer.stderr
  • packages/stack-encrypt/tests/ui/op_target_not_labelled.rs
  • packages/stack-encrypt/tests/ui/op_target_not_labelled.stderr
  • packages/stack-encrypt/tests/ui/op_verify_exact_term.rs
  • packages/stack-encrypt/tests/ui/op_verify_exact_term.stderr
  • packages/stack-encrypt/tests/ui/order_term_of_an_8_bit_integer.rs
  • packages/stack-encrypt/tests/ui/order_term_of_an_8_bit_integer.stderr
  • packages/stack-encrypt/tests/ui/owned_fan_out_needs_clone.rs
  • packages/stack-encrypt/tests/ui/owned_fan_out_needs_clone.stderr
  • packages/stack-encrypt/tests/ui/pass/indexes.rs
  • packages/stack-encrypt/tests/ui/pass/owned_without_clone.rs
  • packages/stack-encrypt/tests/ui/pass/plan_chain.rs
  • packages/stack-encrypt/tests/ui/pass/query_only_and_borrowed.rs
  • packages/stack-encrypt/tests/ui/plaintext_needs_encrypt.stderr
  • packages/stack-encrypt/tests/ui/plan_match_on_integer.rs
  • packages/stack-encrypt/tests/ui/plan_match_on_integer.stderr
  • packages/stack-encrypt/tests/ui/plan_query_undeclared_index.rs
  • packages/stack-encrypt/tests/ui/plan_query_undeclared_index.stderr
  • packages/stack-encrypt/tests/ui/struct_field_must_open.rs
  • packages/stack-encrypt/tests/ui/struct_field_must_open.stderr
  • packages/stack-encrypt/tests/value_kinds.rs
  • packages/stack-guest-abi/Cargo.toml
  • packages/stack-guest-abi/src/abi.rs
  • packages/stack-guest-abi/src/buffers.rs
  • packages/stack-guest-abi/src/call.rs
  • packages/stack-guest-abi/src/last_error.rs
  • packages/stack-guest-abi/src/lib.rs
  • packages/stack-guest-abi/src/status.rs
  • packages/stack-guest-abi/src/step.rs
  • packages/stack-guest-abi/src/value.rs
  • scripts/__tests__/bench-index-expressions.test.mjs
  • scripts/__tests__/dependabot-eql-inherited-ignores.test.mjs
  • scripts/__tests__/ffi-binding-action.test.mjs
  • scripts/__tests__/lib/rust-compiled-files.mjs
  • scripts/__tests__/rust-compiled-files.test.mjs
  • scripts/__tests__/tests-workflow-gate.test.mjs
  • scripts/__tests__/wasm-build-inputs-paths-filter.test.mjs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@changeset-bot

changeset-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d63656

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 27 packages
Name Type
@cipherstash/protect-ffi Patch
@cipherstash/auth Patch
@cipherstash/eql Minor
stash Patch
@cipherstash/stack-drizzle Patch
@cipherstash/stack-supabase Patch
@cipherstash/stack Patch
@cipherstash/ffi-integration-tests Patch
@cipherstash/wizard Patch
@cipherstash/stack-prisma Patch
@cipherstash/bench Patch
@cipherstash/test-kit Patch
@cipherstash/basic-example Patch
@cipherstash/prisma-example Patch
@cipherstash/e2e Patch
@cipherstash/protect-ffi-darwin-arm64 Patch
@cipherstash/protect-ffi-darwin-x64 Patch
@cipherstash/protect-ffi-linux-arm64-gnu Patch
@cipherstash/protect-ffi-linux-x64-gnu Patch
@cipherstash/protect-ffi-linux-x64-musl Patch
@cipherstash/protect-ffi-win32-x64-msvc Patch
@cipherstash/auth-darwin-arm64 Patch
@cipherstash/auth-darwin-x64 Patch
@cipherstash/auth-linux-arm64-gnu Patch
@cipherstash/auth-linux-x64-gnu Patch
@cipherstash/auth-linux-x64-musl Patch
@cipherstash/auth-win32-x64-msvc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Mutation testing (cargo-mutants, --in-diff, stack-auth + stack-encrypt)

caught missed unviable timeout
543 0 404 0

Every mutant in the changed lines was caught by a test.

@coderdan
coderdan added this pull request to stack #1230 October 16, 2026 11:24
A Bloom filter can hold every bit of a query without the value holding
the needle, so a `Matches` query returns false positives. ADR-0009
decision 4 makes such a term `Probabilistic`, with `verify` as the
operator's own meaning run on a decrypted value.

- `op::Probabilistic { type Plaintext; fn verify(&self, &Plaintext) -> bool }`.
  Infallible: every outcome other than a match is `false`.
- `MatchQuery` keeps the needle's tokens as the index cut them, through a
  new `Supports::carry` taken before the value is consumed. `verify` cuts
  the decrypted value the same way and checks every needle token is among
  its tokens. The tokens are zeroized on drop and never shown by `Debug`.
- `Supports::Query` is bounded by `op::TermFor<Op>`: any query term answers
  `Eq`, only a probabilistic one answers `Matches`, so an index cannot
  claim a text match without saying how its answer is checked
  (tests/ui/op_inexact_operator_needs_probabilistic.rs).
- `verify` on an exact term does not compile (tests/ui/op_verify_exact_term.rs).

The tests plant a real Bloom false positive under a 32-bit filter and
check `verify` drops it.

Closes #1183

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
- `Supports::query` takes the sealed `QueryToken` (from the #1190 fix),
  so no caller can pair a needle with another value's filter and have
  `verify` drop the real rows. `Needle`'s doc says how one is joined.
- `TermFor`'s doc and ADR-0009 say the "only a probabilistic term answers
  `Matches`" rule binds this crate's terms; a term in another crate can
  opt in by hand.
- The tokenizer zeroizes its own copies of the text: the folded string,
  its characters, and each n-gram, built at its final size so it does not
  reallocate. `verify` runs it on every decrypted row.
- `MatchQuery`'s `PartialEq` says two needles can share a filter and still
  verify differently.
- ADR-0009 decision 4's code shows the trait as this PR ships it;
  `target_limit` joins it with #1184.
- Tests: `verify` is a token test, not a substring test ("abcd" verifies
  "abc bcd"), and the standard tokenizer verifies whole words in any
  order.

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
- A match query under a configuration with an n-gram length of zero is
  refused, not a panic. The query chain tokenizes the value for `verify`
  before the term is derived, so it reached `slice::windows(0)` ahead of
  `MatchOptions::validate`. `tokenize` now yields no tokens for a zero
  length, and the derivation refuses the options as
  `TermError::InvalidOptions`, as it always did.
- `tokenize` sizes its character buffer from the character count. Built
  with `collect`, it started from `Chars::size_hint`, about a quarter of
  the text, and each buffer it outgrew was freed holding plaintext. Its
  doc now names the one copy it cannot control, inside
  `str::to_lowercase`.
- `match_term` says where its tokens are wiped: the PRF takes them by value
  and moves each buffer into a zeroizing `Protected`.
…erifier

`Supports::Carry` and `Supports::carry` become `Supports::Verifier` and
`Supports::verifier`. "Carry" said only that something was carried; the
type is what a query term keeps of its plaintext so it can check a
decrypted row later: `()` for an exact term, the query's tokens
(`QueryTokens`) for a match query, which `verify` tests each row against.

The trait's rustdoc and ADR-0009 decision 2 now explain the verifier and
show the match index's impl, with the tokens `"alice"` is cut into.
ADR-0009 decision 5: a caller who wants `want` real matches from a
probabilistic query fetches `want + Poisson_quantile(λ = p·N, confidence)`
rows, where `p` is the mean over stored filters of `f^b`, `f` a filter's
fill and `b` the bits the query sets.

- `Probabilistic::target_limit(&self, want, &Stats) -> Limit`.
- `op::Stats::declared(rows)` uses a new `MatchConfig::expected_tokens()`
  prior, a default method returning `None`, so existing configurations
  compile unchanged; it is not part of the index's identity.
- `op::Stats::measured(rows, histogram)` takes `(set bits, rows)` buckets
  from one sampled aggregate over the column, and takes the mean of the
  power, never the power of the mean fill. An empty histogram falls back
  to the prior.
- `op::Limit` is `Rows(n)` or `Unbounded`, the latter when nothing is known
  of the stored filters or the confidence is not in (0, 1). `fetch_or(page)`
  reads either as a fetch size.
- The quantile sums the Poisson mass exactly in log space from
  `λ − 10√λ`, so it costs about `12√λ` terms; past `λ = 1e7` it is the
  conservative `λ + 8√λ`.

Unit tests reproduce the ADR's worked table and its mixed-length column,
and pin the quantile to reference values computed with `lgamma`.

Closes #1184

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
- The Poisson quantile is a bounded, normalised sum over
  `[λ − 10√λ, λ + 12√λ + 50]`. Each term is a log relative to the
  window's first, so a large `λ` no longer loses the starting term to
  cancellation, and the sums run from the top, where the terms are
  smallest, so a confidence near 1 is compared against a tail rounding did
  not swallow. It matches an exact reference to within one up to
  1 − 1e-12 (was off by thousands at λ ≈ 4.75e6), and no mutation of it
  can loop forever. `ln_factorial` is gone.
- A `Limit` never exceeds `op::MAX_ROWS` (`i64::MAX`), the largest SQL
  `LIMIT`; `reltuples` of −1 read as a `u64` no longer overflows a bind.
  The ADR's statements use `greatest(reltuples, 0)`.
- Histogram counts are summed as floats, so huge counts cannot overflow.
- The independence assumption is stated in ADR-0009 decision 5 and on
  `target_limit`: a row sharing tokens with the needle passes more often,
  so the confidence is nominal on natural text; `verify` still decides.
- Docs: the stats SQL filters NULL values; `target_limit` says a fetch
  that returned the limit is a page only when fewer than `want` verified;
  `expected_tokens` counts distinct tokens; decision 4's code shows
  `target_limit` on `Probabilistic`.
- Tests: exact references at high confidence and at λ = 1e7 (which kills
  the threshold mutant), the `MAX_ROWS` cap, float-summed counts, and the
  measured-column test bounds the fetch against the histogram's own λ.

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
CI's mutants gate found one survivor and three timeouts in
`poisson_quantile`:

- Shifting each log term by the window's peak never mattered: relative to
  the window's first term no term exceeds about e^100, so `-` → `+` there
  was equivalent. The shift is gone.
- A mutated threshold or window bound sent the `MAX_ROWS` test's λ of
  about 9e18 into a window of billions of terms. The window is now
  `22√λ + 50` wide from its start, capped at 2^20 terms whatever the
  input, so no mutation can hang a test.
- The window's end is the answer when the confidence allows no mass
  (above 1), now pinned by a test.

A focused `cargo mutants` run over `op/stats.rs` leaves no survivor and no
timeout.

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
CI's mutants gate found `start..=start + width` → `start * width`
surviving: the loop's range sat outside the cap on the window's width,
so the mutation ran for billions of terms instead of failing. The loop
now runs over `0..=width`, the capped width itself, and derives each
`k` from it.

A focused `cargo mutants` run over `op/stats.rs`: 91 mutants, 87
caught, 4 unviable, none missed, no timeouts.

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
- A `want` of 0 is `Limit::Rows(0)`. The quantile was added anyway, so a
  dense column turned a zero-row request into a large fetch.
- `Limit::fetch_or(page)` cuts `page` to `MAX_ROWS`, as the type
  promises, so `Unbounded.fetch_or(u64::MAX)` cannot wrap an `i64` bind.
- Past ten million expected false positives the `λ + 8√λ` bound covers a
  confidence up to `1 − 1e-15` and no more. A higher one is now
  `Limit::Unbounded`; `poisson_quantile` returns `None` for it.
- The row-count recipe no longer clamps `reltuples` to 0. A table never
  analysed has an unknown count, not an empty one, and 0 gave a confident
  fetch of exactly `want`. The catalog read now returns no row then, and
  the docs say to build no `Stats` and page, or run `ANALYZE`.
- `rows` counts the non-NULL rows, since the histogram's pass rate is
  over those: the recipe scales `reltuples` by `pg_stats.null_frac`.
  Charging NULL rows at the non-NULL pass rate over-fetched in proportion
  to the column's NULLs.

The rustdoc, ADR-0009 decision 5 and its examples, and the CHANGELOG say
all of this.
…er, refuse only the query

A match value that cuts no token under the index's tokenizer (empty or
separator-only text, or text shorter than the n-gram length) used to fail
term derivation on both the stored and the query side, so one two-letter
name failed a whole row. ADR-0009 splits the two: the stored term is the
empty filter, which no query matches, and only a query of such text is
refused, because its filter would match every row.

`match_term` now derives the empty filter for such text, with no PRF call,
so `MatchTerms` as a target, `KeysetCipher::match_terms` and the `dynamic`
record path all store it, and the value seals and opens as any other. The
refusal moves to the query paths: `op::Supports::check` takes the query's
value, the `Match` index refuses token-less text there with
`TermError::EmptyTermText` when the query is awaited, before any term is
derived or keyset loaded, and `dynamic::term` refuses it for a match kind.
The error keeps its code and is reworded for the query.

The Go module builds the stack-encrypt guest by path, so its round-trip test
of the old refusal is rewritten to the new behaviour: a short `TextMatch`
value seals, opens and matches no query, and a short match query is still
`ErrTerm`. The package docs and the term-failure message follow.

Two tests that used token-less text as a leaf that fails before any I/O now
use a match configuration with invalid options, which still fails during
the synchronous build.

Closes #1185

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
match_terms is no longer a query. In 0.2.0 the same call served write
time and query time and refused text that cuts no token; it now returns
the empty filter for that text, and EQL treats an empty filter as
contained by every stored filter. A caller who still sends its output as
a query gets every row and no error, so the CHANGELOG entry moves to
Breaking and says so plainly, naming cipher.query(op::Matches, ..) as the
query.

The query side validated the match options only when it derived the term,
after the new no-token check had tokenised the text, so an n-gram length
of zero panicked in the tokenizer instead of returning InvalidOptions.
Both query prechecks, op::Supports::check and dynamic::term, now validate
first, as the stored path always has.

Go's term-failure locator asks the query path for each term, and the
query path refuses short match text that a record stores as the empty
filter. It could stop at an earlier row with a short email and name the
wrong row. It now skips that one refusal by its code, and a test pins it
with a short email in row 0.

ADR-0009 and the Go package doc say that a stored empty filter tells a
reader of the column the value is empty, separator-only or shorter than
the n-gram length. The tokenizer's doc no longer says match_terms rejects
that text.
…tch, stored or queried

Rebased onto next, the EQL v4 TextMatch filter met this PR's change to
match_terms. eql-bindings builds the stored TextMatch filter and the
TextMatchQuery operand from one type, BloomFilter, through the stored-side
match_terms. Before this PR that refused text that cuts no token, so both
refused it. After it, match_terms returns the empty filter for that text,
so a TextMatchQuery of "" or "al" became `bf: []`, which EQL treats as
contained by every stored filter: a query matching every row, with no
error, through Rust's encrypt_as and through the Go SDK's generated Query.

BloomFilter's visitor now refuses an empty filter with
TermError::EmptyTermText, for the stored value and the query alike, which
is what EQL v4 TextMatch did before and what its docs, the Rust tests and
the Go test already say. Storing a short value as the empty filter while
refusing it as a query needs the query twin to have a filter type of its
own, which is a codegen change left for later.

The Go SDK README and the stashgen README still said a plain `match` index
refuses short text; they now say it stores the empty filter and refuses
only the query, and that an EQL TextMatch field is stricter.
- One rule for a match query, in one place. `QueryTokens::of_query`
  validates the options, tokenises the text and refuses text that cuts
  no token. The query chain and `dynamic::term` both call it, so the Rust
  chain and the Go guest cannot drift on what they refuse; `dynamic::term`
  no longer repeats the validate, tokenise and refuse steps by hand.
- An awaited `op::Matches` query tokenises its text once fewer.
  `Supports` gains a provided `admit`, which checks and takes the carry
  together, and a match index overrides it to tokenise once for both.
  `prepare` calls `admit` instead of a second `check` and then `carry`.
  The term itself is still derived through the index's own operation,
  which tokenises again: that is the path a write takes, and sharing it
  is what makes the query's filter the stored filter's.
… no query_index

ADR-0009 decisions 1 and 7. `op::Lt`, `Lte`, `Gt` and `Gte` take one
value and `op::Between` a pair of bounds, inclusive at both ends. The ORE
and OPE indexes answer them over the integer types (`op::Ordered`), ORE by
default and OPE through `.via(Ope)`; an ordering on text does not compile,
since text has no order term this crate produces. A comparison's query
term is the index's own term for the value: this crate's ORE is CLLW,
whose ciphertext has no left half to send alone, so what is sent is what
is stored, as for an HMAC, and `Supports` is where the left-only term of
block ORE (#1140) goes when it lands. A range's query term is one
`sem::RangeQuery` carrying both bounds' terms, derived under the one
label, read with `lo()` and `hi()`. A range whose low bound is above its
high bound is refused when the query is awaited, before either term is
derived and before any keyset is loaded (`TermError::InvertedRange`).

An operator now says what a query takes through `op::Arity`: `One`
plaintext or a `Pair` of them. `op::Input<A>` relates the value a query is
given to the plaintext the plan is checked against, and derives one term
per plaintext. `Supports`, `Answers` and `DefaultIndex` are keyed by that
input, so `Supports<Eq, S>` reads as before and `Between` is
`Supports<Between, (S, S)>`; `Supports::query` takes the input's terms.

`StackCipher::query_index` goes, with `QueryIndexBuilder` and
`QueryIndex`: every index a plan can declare is reachable through an
operator now, and the chain holds its own input, index and label.
`Resolves::resolve` takes the index and the call's context and returns
the index and the label. ADR-0009's decision 2 shows the shape that
ships, and its mentions of `query_index` are past tense.

Closes #1186

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
Ordered was public and not sealed, so a downstream crate could implement
it for its own type, such as a newtype over folded text that also
implements the CLLW traits. Between refuses an inverted range with the
type's PartialOrd while the server compares ORE terms, so such a type
could refuse a valid range or accept an empty one, and it would open
ordering on text, which ADR-0009 leaves to the catalog. Ordered now
requires op::sealed::Sealed, which the macro implements for the integer
types.

A compile_fail doctest pins it with a type that meets every other bound,
so the seal is the only reason it fails; without the seal the same
snippet compiles. A trybuild test would pin rustc's list of sample
implementors, which changes whenever a later layer seals another type.
… and AtPath

ADR-0009 decision 1 names three JSON operators. `op::Contains` and
`op::ContainedBy` are the containments (`@>` and `<@`), exact, and take
one value, the document. `op::AtPath<Op>`, written `op::AtPath(op::Eq)`,
applies another operator at a JSON path and inherits that operator's
fidelity through `TermFor`: an exact term answers `AtPath<Eq>` and
`AtPath<Lt>`, and only a probabilistic one answers `AtPath<Matches>`.

No index answers them. This crate has no JSON index, and EQL v4 has no
JSON type Stack Encrypt produces, so a containment query or a query at a
path does not compile on any plan, which the compile-fail tests pin.
`AtPath`'s arity is a new `op::Pathed`, a path and the leaf's input, and
no `op::Input` of it exists until the JSON index arrives, since the path
becomes a selector only that index can derive. The value-selector and
selector-plus-leaf term shapes the issue lists wait for the same index.

Closes #1187

Claude-Session: https://claude.ai/code/session_01VYKAWbd361xDLmqBdLoUcB
…scribed once and every leaf records its type

Pins the root workspace's vitaminc crates to the branch that implements
vitaminc ADR 0001 (cipherstash/vitaminc #439 to #445) with a temporary
`[patch.crates-io]`, and moves stack-encrypt and the guest ABI onto it.

- A value describes itself with vitaminc's `Plaintext` and reads back
  through `Decrypt`. `PendingStackCipherText::plan` walks it into
  vitaminc's pending tree with no I/O; the target layer's `Pending`
  still fetches every key of an assembly in one batched call, and the
  leaves are then sealed and opened through the bytes-only `Cipher`:
  `MintedKeys` seals each leaf under the next generated key, `BoundKeys`
  opens a leaf under the key bound to it, and vitaminc derives every
  leaf's AAD and checks the markers and container rules on both sides.
- Every leaf is tagged (wire version 2), so a Rust `u32` field and a
  data plan's `uint32` field seal the same leaf and each opens the
  other's. The record fixture is regenerated; its terms are unchanged.
- `None` is a null leaf, a passthrough is a `PassthroughFrame`, and
  `StackCipherText` is `Node<SealedValue>`.
- `dynamic::FfiValue` and `ValueKind` move into this crate, unchanged in
  shape, with `Plaintext` and a `Decrypt` sink, and cross a binding's
  boundary as transport frames. The deeper rework of `dynamic::Value`
  and `Scalar` is #1140.
- stack-guest-abi's outputs and last error are a `HostValue` written as
  a transport frame.

Closes #1118
- The CHANGELOG's `query_index` migration note no longer says
  `query(op::Matches, text)` is the same call. It returns a `MatchQuery`,
  refuses text that cuts no token, and compiles only for a configuration
  with `op::MatchCase`. `query_index(Ore, text)` and `query_index(Ope,
  text)` have no replacement until the order of text is settled, and the
  note says so.
- `op::MatchCase`'s doc no longer says a configuration without it can be
  queried by index: that path is gone, and the doc names the one-line impl
  that makes such a configuration queryable.
- `op::Ordered` has a curated diagnostic: an ordering over text, or over
  any type outside the integers, now says the orderings are integer-only.
- `query` carries the `Input<Op::Arity>` bound and `op::Input` has a
  curated diagnostic, so `query(op::Between, &40u32)` fails at the value
  and says to pass `&(lo, hi)`, not only with an E0599 on `on`.
- `op::Pathed` carries the leaf operator's arity, `Pathed<A>`, so
  `AtPath<Eq>` takes `Pathed<One>` (a path and a value) and
  `AtPath<Between>` takes `Pathed<Pair>` (a path and a pair of bounds). A
  JSON index's `Input` impls can then derive one term or two as the leaf
  needs. A unit test pins the three arities.
- `AtPath<Op>` takes only a leaf operator, the new `op::Leaf`: `Eq`, `Lt`,
  `Lte`, `Gt`, `Gte`, `Between` and `Matches`. `AtPath<Contains>`,
  `AtPath<ContainedBy>` and `AtPath<AtPath<_>>` are no longer operators,
  since none of them is one selector and value; `op::LeafArity` (sealed:
  `One` and `Pair`) keeps an accessor from nesting.
  `tests/ui/op_at_path_not_a_leaf.rs` pins the diagnostic.
- The `DefaultIndex` diagnostic says no index answers the JSON operators
  yet, instead of only pointing at `.via(index)`, which led to a second
  error. `op::Input` gains a diagnostic naming what each arity takes.
- The module intro lists the JSON operators and the `Pathed` arity, and
  `Operator::Arity`'s doc names all three arities.
…with no absent marker to fuzz

The fuzz crate is its own workspace and compiles stack-encrypt by path, so
it carries the same temporary vitaminc pin. check_record's model loses the
None node, which ADR 0001 retires, and builds its passthroughs as frames.
…guests

Both WASI guests build against the same temporary vitaminc pin as the
root workspace, and every value crosses as a transport frame.

- The encrypt guest decodes inputs with `FfiValue::from_frame`, writes
  outputs through vitaminc's `FrameWriter` into a buffer still sized
  before the first byte, and reads and writes ciphertext trees with
  `vitaminc_aead_frame`'s codec, a passthrough as its frame.
- The credential guest's outputs are `HostValue`s.
- The Go module moves vcffi and vcvalue to the same vitaminc commit,
  whose container tags and leaf kinds match the frame. The absent leaf
  kind is gone from the binding's leaf set. vcffi sends an 8- or 16-bit
  integer at its own width, which the engine reads as the 32-bit integer
  of its sign, so a generated field seals as it did.
…and drop the unpinnable capacity hint

cargo-mutants found the unused half of MintedKeys and BoundKeys, and the
UINT8 arm of FfiValue's sink, untested: no Rust source walks a u8 as an
int, so the test reads a host's frame of one. The sink's capacity hint
changed nothing a test can see, so it is gone.
… 0001 so the EQL jobs and the EQL guest stay green

eql-bindings' `stack-encrypt` feature and tests/encryption compile
stack-encrypt by path, so they move with it.

- The EQL workspace carries the same temporary vitaminc pin as the root,
  the fuzz crate and both guests: every workspace that compiles
  stack-encrypt now resolves one vitaminc.
- `encryption::targets` and the generated `v3::targets` take `FfiValue`
  and `ValueKind` from `stack_encrypt::dynamic` (the feature turns on
  stack-encrypt's `dynamic`); the generator emits the new import.
  `vitaminc-aead-value` is gone from both manifests.
- The `Ciphertext` target takes `Plaintext` in place of `Encrypt` and
  `Decrypt + Send + 'static` in place of `Decrypt<'static>`.
- The encrypt guest's lockfile drops `vitaminc-aead-value`, which only
  its `eql` build still pulled in.

No other EQL code names a vitaminc API.

Rebased onto next, which carries the EQL v4 types:

- `encryption::plaintext`'s `Int32`, `Int64`, `Bool`, `Float32` and
  `Float64` sealed vitaminc 0.5's tagged leaves through `Encrypt` and
  `DecipherVisitor`, which ADR 0001 removes. They now describe themselves
  as the primitive they wrap (`Plaintext`), so they seal the leaf a data
  plan's field of that type seals, and read back through `FromScalar`
  only a scalar of their own kind and width, as before: vitaminc's
  primitive targets would convert any integer that fits and widen an
  f32. `vitaminc-aead-value` and `vitaminc-protected` leave eql-bindings;
  `vitaminc-aead` stays for the scalar kinds.
- `tests/encryption/tests/v4_types.rs` takes `FfiValue` and `ValueKind`
  from `stack_encrypt::dynamic`.
- `v4_rows.json` is regenerated by the Go test over the deterministic EQL
  guest: ADR 0001 leaves are wire version 2, so the committed ciphertexts
  no longer opened.
…s Encrypt rename

The vitaminc crates came from `feat/aead-remove-legacy-traits` by branch
name. That stack has merged into vitaminc main and the branch is gone, so
a lockfile refresh could no longer resolve it. Every workspace that
compiles stack-encrypt (the root, both Go guests, packages/eql and the
fuzz crate) now pins one commit of cipherstash/vitaminc#464, vitaminc main
plus the order-term comparison, which is the commit ore.rs's vitaminc
implementation (cipherstash/ore.rs#115) builds against. Pinned by rev, not
branch, so a merge cannot pull it out from under the build.

Between the two commits vitaminc renamed the source trait `Plaintext` to
`Encrypt`, to pair with `Decrypt`. stack-encrypt re-exports it under the
new name, and every bound, impl, import and doc link in the stack crates,
the guests, stack-guest-abi and eql-bindings follows. `TargetError::
Plaintext`, `Supports`'s `In::Plaintext` and eql-bindings' own
`targets::Plaintext` are different things and keep their names. The
trybuild expectations follow the rename.

The other breaking changes since (Timestamp as plaintext, Copy
normalizers, vitaminc-ore's column handle and compare) reach no code at
this layer. v4_rows.json is unchanged: the leaves are the same format.
…dule to the same vitaminc

Review follow-ups for the move onto vitaminc ADR 0001.

`HostValue::Text` held a plain `String`. Before this PR the auth guest
built its output from `FfiValue::String`, whose bytes live in a
`Protected` buffer, so the access token it returns was wiped when dropped;
after it, every `token` call left a bearer token in freed guest memory.
`Text` now holds `Zeroizing<String>` on every path that builds one (the
constructor, JSON, a decoded frame), and a test pins it.

The Go module still named vcffi and vcvalue at 2e895cb9caed, the head of
the deleted `feat/aead-remove-legacy-traits` branch, which builds only
while the Go proxy has it cached. It now names the commit the five Rust
workspaces pin, 2413bd0e4bf7 (cipherstash/vitaminc#464); the Go code under
bindings/go is the same at both.

Docs that still called vitaminc's source trait `Plaintext` (CONTEXT.md,
the mixed_user example, two test headers and two manifests) say
`Encrypt`. The CHANGELOG no longer says a reader of any other type is
refused: an integer reader takes any integer width the value fits, and an
`f64` reader an `f32`, which change no value.
This reverts commit c7b1205. Text and TextEq keep their
Option<String> plaintext. A null is padded to a value's length only for
types of fixed width; for text, None seals as a null of its own.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
The generated docs for Text and TextEq said a None is sealed as long as
a value. That holds for types of fixed width only: a text null is not
padded, since text's ciphertext is as long as the text, so its length
may show that the value is absent. The changeset says the same.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
vitaminc-ore 0.8 encodes the Date, Timestamp and Decimal targets, and
clww-ore 0.6 and ore-rs 0.10 take them, so the engine can now derive their
order terms.

The typed path needs a Rust type for each that the engine can wipe and
clone. chrono's and rust_decimal's types keep private fields, and
`Orderable` is sealed, so eql-bindings' wipeable `v4::plaintext` types
could not join it. They move here as `value::{Date, Timestamp, Decimal}`
(with `RangeError`, and the chrono and rust_decimal conversions behind
features of those names), and become `Orderable` and `op::Ordered`. Their
one `unsafe`, in the test that proves `Drop` wipes in place, is allowed on
that test alone.

The data-plan path dropped a scalar's logical type when it picked an order
target, so a date would have ordered as its bare day count. `order_of` now
reads a date, timestamp or decimal into its `value` type first, and
`IndexSpec::takes` admits one exactly when it reads. With nothing left to
refuse, `Reason::OrderTermPending` is removed; it was never released.

A timestamp orders by the microsecond, floored, and a decimal by value
whatever its scale, as their equality terms already compare. Block ORE
puts a date through the 6-bit fixed-width engine and a timestamp or
decimal through the chained one.

Refs #1236

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
…umeric types

With the engine ordering dates, timestamps and decimals, the nine EQL v4
types it refused become producible: DateOrd, DateOrdOpe, DateOrdOre and
their timestamp and numeric twins. eql-codegen lists them in
ENCRYPTION_DOMAINS and loses the pending-order reason; the generated
bindings, the target table and Go's encrypt/eql table follow.

eql-bindings' `v4::plaintext` now re-exports Stack Encrypt's `value`
types, and its chrono and rust_decimal features turn on Stack Encrypt's.
Its one remaining direct use of vitaminc-aead, the null tag in the by-name
dispatch, goes through `stack_encrypt::dynamic::frame`, so the dependency
is dropped.

Tests: the OPE types join v4_order's ordering checks, the block ORE types
join v4_ore_block with a PostgreSQL comparison over dates, timestamps
(ties within a microsecond, flooring before the epoch) and decimals
(1.5 ties 1.50), and the between smoke test now ranges over every ordered
family. Tests that used DateOrdOre as the unproducible example use Json.

Go: stashgen's static engine and notices admit order indexes on decimals,
dates and timestamps; the ValueKinds model takes the order indexes the
value-kinds fixture now declares, and its test checks Lt against the
stored terms, folded queries included.

Closes #1236

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
…ncrypt's

The changeset for the unordered types still named eql-bindings'
v4::plaintext as their owner. This branch moved them to
stack_encrypt::value and re-exports them there, and the ordered types'
changeset says so, so the two entries would have shipped contradicting
each other.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
EQL v4's bindings are to store stack-encrypt's own order terms, typed by
scheme and plaintext, rather than v3's untyped hex newtypes. That needs
the terms to be serde types. OreTerm, OpeTerm and OreBlockTerm now
serialize as lowercase hex in a human-readable format and as raw bytes in
a binary one, through serdect, whose hex (base16ct) is constant-time.
Deserializing goes through from_bytes, so a term of another scheme or a
malformed one is refused at the boundary, with an error that names a
length, never a byte.

from_bytes now takes the Vec<u8> it decodes and keeps it, so neither
deserializing nor a caller that owns the bytes pays a copy; TryFrom<&[u8]>
stays and copies once. OpeTerm also checks its leading carry byte is 0 or
1: clww-ore's comparator refuses any other, but its from_bytes checks only
the length.

Upstream serde for these types is proposed in cipherstash/ore.rs#137, and
constant-time FromHex in clww-ore in cipherstash/ore.rs#138.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
… terms, stored as one hex string

EQL v4 reused v3's term newtypes for its order terms: `ob` was
`OreBlock256(Vec<String>)`, a one-element array of hex, and `op` an
`OpeCllw(String)`. Neither said which scheme or plaintext it held, and
neither checked anything when read.

A v4 `ob` field is now `stack_encrypt::sem::OreBlockTerm<T>` and an `op`
field `OpeTerm<T>`, over the type's plaintext (`DateOrdOre::ob` is an
`OreBlockTerm<Date>`). Each serializes as one lowercase hex string and is
decoded through `from_bytes` when a payload is read, so an EQL v3 array,
a term of the other scheme or a malformed term is refused there.
`v4::terms` no longer re-exports v3's order terms. `OreBlockHex` and
`OpeHex`, generated, describe the JSON to TypeScript and JSON Schema.

One catalog entry, `eql_domains::Term::v4_format`, names each term's
Stack Encrypt type, its JSON shape and the hex prefixes it starts with
(block ORE `0202`/`0203`, OPE carry `00`/`01`). Codegen writes the Rust
field, the JSON Schema pattern and the v4 domain CHECKs from it: every v4
domain carrying `ob` or `op`, stored, query or range bound, requires a
JSON string with one of those prefixes. The CHECK reads only the prefix,
so a write costs the same whatever the term's length; the comparator
still checks the full structure.

The v4 SQL reads `ob` as one hex string: `has_ore_block_v2` tests for a
string, the extractor decodes it straight to the composite, which now
holds one term rather than an array, and the one-element array overload
of the comparator is gone. The v3 bundle is byte-for-byte unchanged.

Exact per-type CHECKs (block count and length) wait on a key-free shape
API in ore-rs and clww-ore, cipherstash/ore.rs#139.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
U-003 in the 3.1 upgrade guide says what changed for a hand-written
eql_v4 payload: `ob` is one hex string, and every v4 domain carrying `ob`
or `op` checks its prefix. A database that installed an earlier v4
bundle, such as the one attached to the Go module's alpha, keeps its
stored domains across an install, so it must drop its stored order
domains first; the guide gives the query that lists them.

A changeset for @cipherstash/eql, CHANGELOG entries for eql-bindings and
the Go module, and the bindings README and catalog reference describe the
v4 term types.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
… range bounds

The changeset linked U-003 relative to the repository root, but
Changesets copies it into packages/eql/packages/eql/CHANGELOG.md, where
that path names nothing. It now uses ../../docs, as the U-001 and U-002
changesets do.

The v4 range reference still said a block ORE range's bounds are ob
arrays, which the range domains now refuse with check_violation. It
now says both bounds are one hex string, names the prefixes, and links
U-003. It also no longer says the envelope waits on the ordered types
becoming producible: they are, and a caller builds the envelope from
two single-bound queries.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
feat(golang, stack-encrypt): optional sealed fields, stored as a sealed null or SQL NULL
…-decimals

feat(stack-encrypt, eql-bindings, golang): order dates, timestamps and decimals
feat(stack-encrypt, eql-bindings, eql): EQL v4 order terms are typed, one hex string, checked when written
…les cargo compiles

The protect-ffi binding links eql-bindings by path, so its cache key and the
paths: filters of the eight workflows that build it named that crate. They
named it as `packages/eql/crates/**`: every EQL crate, with its tests, docs,
generated TypeScript bindings and the `v4` / `encryption` modules that only
compile with the `stack-encrypt` feature, which protect-ffi never enables.
The EQL v4 block ORE pull request (#1280) touched none of what the binding
compiles and still started every Drizzle, Prisma Next, Supabase and
protect-ffi suite.

The key and the filters now list the files cargo reads: the manifest,
`src/lib.rs`, `src/sql.rs`, `src/from_v2/**`, `src/v3/**` and the SQL bundle
`src/sql.rs` includes. That list is derived, not remembered. A new
`scripts/__tests__/lib/rust-compiled-files.mjs` follows a crate's modules from
`src/lib.rs` under the features it is built with, plus its include_str!
targets; for eql-bindings it agrees file for file with cargo's own dep-info.
ffi-binding-action.test.mjs now fails both ways: a compiled file the key
misses (a new module, a feature turned on), and a file beside the compiled
crates that the key hashes and cargo does not read. The filters are held to
the key as before, and wasm-build-inputs-paths-filter.test.mjs now also fails
a filter entry reaching into packages/eql/crates beyond it.

The reverse gap, found on the way: the Drizzle, Prisma Next, Supabase, Prisma
example and bench workflows install EQL from the workspace `@cipherstash/eql`
package and did not trigger on it, so an EQL release bump started none of
them. They now list `packages/eql/packages/eql/**`.
tests.yml ran its credentialed jobs (Node 22 and 24, Bun, the e2e suite and
the WASM / Deno smoke test, each building two native bindings) on every pull
request, including ones that changed only Go, the Stack Encrypt crates or
EQL's SQL. A new `changes` job now skips them unless the pull request changes
a file they can read.

The question is asked the safe way round. Instead of an allowlist, which
skips a suite on the change that breaks it the day someone forgets a
directory, the jobs run unless every changed file sits in an excluded tree.
dorny/paths-filter cannot re-include a path inside one list, so the decision
is two lists: `rest` (`**` minus the excluded trees) and `direct` (what the
jobs do read inside them: the eql-bindings files the binding compiles, the
`@cipherstash/eql` package, tests.yml itself).

The checks that read the whole tree move to an ungated `repo-checks` job: the
lint scripts, the release gate, `test:scripts`, and the suites that read
workflow files (protect-ffi's lintWiring and integrationSuiteCi, the e2e
supply-chain and skill-map checks). They ran inside `run-tests` once per Node
leg; gating that job without moving them would have left a workflow-only
change with none of its guards. `tests-required` summarises the run as one
check a branch rule can require, since a skipped job required by name never
reports.

tests-workflow-gate.test.mjs holds the lists to the jobs: every job but the
four ungated ones carries the gate; no code under the live roots reads an
excluded path (a textual scan that resolves relative paths from the file and
its package root, with each exception written down and stale-checked); the
crates the auth and profile bindings compile stay selected; and the decision
script is run once per event. wasm-build-inputs-paths-filter.test.mjs now
reads the gate as tests.yml's effective pull_request filter, so the FFI build
inputs are held against the list that actually starts the jobs.
…heck runs

repo-checks now runs test:scripts straight after install. Nothing
before it builds @cipherstash/eql, so bench-index-expressions' check
that dist/sql is a verbatim copy of sql skipped without a word. On next
the run-tests turbo builds came first and the check ran.

The job builds the package first, and sets EQL_DIST_REQUIRED, which
makes the check fail rather than skip when dist/ is missing. Locally it
still runs only after a build.

tests-required and the workflow's paths filter now say that the check
must not be required while plans-only pull requests skip the workflow.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
…tgreSQL

Nothing in CI ran the path a Go program takes: rows the Go SDK stores in
EQL columns, found by queries the Go SDK derives, through EQL's operators.
encrypt/postgres_test.go stores terms in bytea columns with no EQL, and the
Rust encryption suite runs EQL in PostgreSQL but derives its own queries, so
a change that put Go and the SQL out of step failed nowhere (#1289).

TestEQLTypesRoundTripAndQueryInPostgres walks eql.Types, the table generated
from the EQL catalog, and for every type the engine produces declares a field
of it at run time through gensupport, stores four rows in a column of its
domain, and runs each query its indexes answer (=, <, <=, >, >= and @@)
through the operand domain, asserting the exact rows. A type with no query
for an operator must be refused with EQL's own error. The rows are read back
from PostgreSQL, which stores jsonb re-serialised, and opened. A type whose
plaintext or index the test has no case for fails rather than skipping, so a
type the engine starts producing is covered or loudly not. With DATABASE_URL
set and no eql_v4 schema it fails: a skip reads the same as a pass.

CI runs it in a new eql-postgres job in tests-golang.yml, after wasi-check
and on its guests, against postgres:17 with the bundle `mise run build`
writes from the tree, through the new `mise run go:test:postgres` task (also
the local entry point, against EQL_TEST_DATABASE_URL). The task fails if
either PostgreSQL test skips. The existing bytea test moves there with it,
since its database now carries EQL. The workflow's filters gain EQL's SQL
sources and the codegen that writes the bundle.

`eql_v4.between` is not covered: the Go SDK derives no EQL range term yet
(Range on an EQL ordered field is refused by the engine), so there is no Go
query to run through it.

Closes #1289

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
next now produces the ten block ORE types (IntegerOrdOre, TextSearchOre
and the rest), and the test fails on an index it has no query for, as
it is meant to. ore_block answers lt, lte, gt and gte, as ore and ope
do. All 49 producible types pass against PostgreSQL 17.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
ci: run JS and FFI suites only on changes that can reach them
…ad back short

From review. go test -run with a pattern that matches nothing prints
"no tests to run" and PASS, so a renamed test left the job green: the
task now requires each test's own --- PASS line. The test also checks
rows.Err() after reading the stored rows back, and that it opened as
many rows as it stored, so a short read or decrypt cannot check fewer
rows and pass.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
Optional fields are what #1298 is for, and nothing ran a stored nil
through EQL in PostgreSQL. Each type now gets a fifth row with no value,
stored as the engine requires for it. A type of fixed width with no
index or equality alone stores a sealed null (17 types): its c must be as
long as a value's, EqNull must find it and only it, and IS NULL must
find nothing. Text and every ordered or match type store SQL NULL (32
types): IS NULL finds it, and no value query does. The nil row opens as
nil.

Breaking the length check and the EqNull check on purpose fails all 17
and all 8 types they cover.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
test(golang): run the Go SDK rows and queries through EQL v4 in PostgreSQL
TestEQLTypesRoundTripAndQueryInPostgres runs <, <=, > and >= over four
fixed values per type. A comparator that is only partly wrong (one that
reads only a block ORE term's first blocks, mishandles a sign bit, or
orders a decimal by its scale) still agrees with plaintext order on most
pairs, so four values say little. The Go property tests compare terms in
Go, and the SQLx property suite covers EQL v3, so nothing ran random Go
SDK values through EQL v4's operators.

TestEQLOrderMatchesPlaintextInPostgres stores about 360 values in a
temporary table for every producible ordered EQL v4 type (29 today): 300
random draws, the edges of the type's order, and thirty duplicates. Each
of 20 query values goes through each ordering operator and must find
exactly the rows plaintext comparison selects, and ORDER BY the type's
order term must return the rows in plaintext order, both ways. Plaintext
order is the engine's: text by its fold, -0.0 equal to 0.0 and NaN above
+Inf, timestamps to the microsecond, decimals by value.

The seed is fixed and logged, EQL_ORDER_SEED replaces it, and each type
draws from its own generator so one subtest replays alone. A failure
names the type, the operator, the seed and the value pair.

The connection and EQL-installed check move into a helper both tests
share, and go:test:postgres runs and requires the new test.

Closes #1343

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
The edges hold the ties the order rules make: -0.0 and 0.0, 1.5 and
1.50, two instants in one microsecond. An engine that splits one of those
ties orders the tied rows one way every time, and the ORDER BY check
accepts tied rows in either order, so only a query on one of the tied
values can show it. Four edges were picked at random as query values, and
with the default seed four of the six float types passed with a plaintext
model that tied two values the engine keeps apart. Every edge is now a
query value, and all six fail on that model.

Refs #1343.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
eqlOrderIndex kept its own list of order index names, and a type whose
index was not on it was skipped, with only a zero-types guard behind it.
The round-trip test fails on an index missing from eqlIndexOperators, so
a new order index would be added there and this test would then pass
without ever running the new types. An order index is now any index
whose operators in eqlIndexOperators include lt, so a new one reaches
runEQLOrder and fails at the missing extractor until it has one.

Refs #1343.

Claude-Session: https://claude.ai/code/session_01XQN1QpaWVDGjHEg39KEJF3
…nal tokens and the header

Two review findings on the record (#1250) read the design as written and
found two gaps that the implementation closed in #1329, with nothing in
the record saying so. A positional token as first written named the
element's children rather than the element, so a scalar element could not
be returned or identified; the implementation reaches a position from the
parent's token through a `#n:<selector>` gate and returns the reached entry
itself. The wire shape called the header opaque to SQL while the walk
needs the document's iv and the sealed-root flag from it; the
implementation reads both at fixed offsets of the frozen header layout.
Each passage now carries a dated note pointing at the implementation and
the phase notes, in the form the record already uses for superseded
sections.

Claude-Session: https://claude.ai/code/session_01N7bCqa3ZVJMcEE99RzVqEu
…pt-spike

docs(plans): a JSON index for Stack Encrypt as a new EQL v4 domain, with runnable SQL prototypes

This branch was successfully deployed

1 active (outdated) deployment
release-golang — a05affaa Deployed Oct 19, 2026 by coderdan via Tag and release #3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants