Conversation
The crate's single lib.rs had grown to 1215 lines, ~55% of it tests, with each enum's definition interleaved with its impl block. Reorganise for readability so the catalog reads top-to-bottom: - lib.rs (~240 lines) keeps the *definitions* — the six type defs, the two crate-internal macros (fixtures!, int_values!), and all catalog data (ORDERED_INT_DOMAINS, INT*_FIXTURES, INT4/INT2/INT8/DATE, CATALOG, INT*_VALUES). - Inherent impls move to sibling modules: kind.rs (BoundedIntKind, ScalarKind), term.rs (Term), fixture.rs (Fixture), spec.rs (ScalarSpec). Methods travel with their types, so no re-exports are needed. - The 7 unit-test modules move verbatim into tests.rs (#[cfg(test)] mod tests), kept as one group because rust_tests spans multiple types; use super::* becomes use crate::*. Pure code-move, zero behaviour change. Public API surface of the crate is unchanged. Verified: cargo test -p eql-scalars (40 pass), codegen:parity (byte-for-byte identical int4 golden), test:crates clippy -D warnings clean, eql-codegen/eql-tests-macros build unchanged.
The docstring claimed all returned strings are Rust type names as they appear in generated source, but Numeric/Text/Jsonb return SQL tokens (numeric/text/jsonb) and have no generated surface. Clarify that only I16/I32/I64/Date return canonical Rust type names and the rest are placeholders, and note the sole call site (tests.rs).
The three compare_ore_block_u64_8_256_term(s) overloads (term×term, term[]×term[], composite×composite) are now IMMUTABLE, diverging from the v2 originals which default to VOLATILE. The comparison is deterministic — its only crypto call, pgcrypto encrypt(), is IMMUTABLE — so the planner can fold/cache in ordering and index contexts. NOT STRICT: the NULL-handling branches are load-bearing. T8 (family::sem::ore_comparators_are_immutable) asserts exactly 3 overloads exist and all have provolatile = 'i', so a silent regression to VOLATILE fails CI.
Widen the existing T8 catalog query to also assert all three compare_ore_block_u64_8_256_term(s) overloads are NOT STRICT, closing the lopsided pin where the equally load-bearing non-STRICT property was only guarded behaviourally (T3, term overload only). Now pinned at the same catalog layer T8 already queries, covering the array/composite overloads T3 does not directly assert.
…-only) Add the timestamptz scalar encrypted-domain type to the eql_v3 family as EQUALITY-ONLY: storage + eql_v3.timestamptz_eq (= / <> via HMAC), no ord domains, no MIN/MAX aggregates. Ordering is deferred: cipherstash encrypts Plaintext::Timestamp at native 12-block ORE width, but EQL's only ORE comparator (eql_v2.compare_ore_block_u64_8_256_term) is hardcoded to 8 blocks, so an ordered timestamptz domain would silently mis-order. Ordering follows once a wide-ORE (12-block) term lands. - catalog: add EQ_ONLY_DOMAINS (storage + _eq); point TIMESTAMPTZ at it. Replace all_types_share_the_same_domain_shape with a shape-aware test (every type matches one of two known shapes) plus a pin of which token uses which shape. - dispatch: extend the scalar_types! entry grammar with an optional [eq_only] marker; eq-only entries emit eq_only_scalar_matrix! instead of ordered_numeric_matrix!. ordered int4/int2/date emission is byte-identical. - matrix: eq_only_scalar_matrix! now derives its three pivots from the ScalarType impl (like the ordered macro) instead of requiring explicit pivots — the first consumer wires cleanly with no per-call pivot authoring. - inventory: make mise test:matrix:inventory shape-aware. Add the second canonical snapshot matrix_tests_eq_only.txt; each discovered type is compared against the snapshot matching its shape (ordered vs eq-only). Document the two-shape mechanism in snapshots/README.md. matrix_tests.txt is unchanged. - CHANGELOG: timestamptz ships equality-only, ordering deferred.
…ctness Address PR #257 review feedback. The temporal_values! auto-generated tests re-run the exact parse closure over all-UTC (`…Z`) catalog fixtures, so they cannot catch a regression that drops the offset→UTC conversion, and fixture distinctness is keyed by string upstream in eql-scalars (which is zero-dep, no chrono) so two RFC3339 strings denoting the same UTC instant pass as distinct. Add two harness-side guards alongside the timestamptz temporal_values! call: - rfc3339_offset_is_normalized_to_utc: feeds an offset-bearing RFC3339 string and asserts it resolves to the same instant as the Z form (fails on a switch to .naive_utc()). - fixtures_are_distinct_by_instant: dedups timestamptz_values() by parsed DateTime<Utc>, guarding the property the fixture table keys on.
Adds the `Bloom` index `Term` (json key `bf`, extractor `match_term`, ctor `bloom_filter`, role `match`, operators `@>`/`<@`) and the `text` row to the scalar `CATALOG`: `ScalarKind::Text`, a `_match` (Bloom) domain on top of the ordered shape, and the `TEXT_FIXTURES` / `TEXT_VALUES` plaintext list (materialised by a `text_values!` macro alongside `int_values!`). `Fixture::Zero` is gated to the integer kinds. Covered by `term_tests` and catalog `#[test]`s.
The searchable-encrypted-metadata `match` term for text. Adds the `eql_v3.bloom_filter` domain (`smallint[]`) and the inlinable `eql_v3.bloom_filter(jsonb)` extractor + `has_bloom_filter` predicate, mirroring `eql_v3.hmac_256`: no RAISE, no pinned search_path, so the functional GIN index on `match_term(col)` engages structurally. The extractor gates on `jsonb_typeof(val -> 'bf') = 'array'`, returning NULL (not erroring) for absent or malformed `bf` outside the domain CHECK. Adds the inline-critical clause to `pin_search_path.sql` and allowlists `match_term`/containment in the splinter lint so the unpinned extractor stays inlinable. Covered by family/sem.rs.
Teaches the codegen operator surface about the `@>`/`<@` containment operators so they are generated only on domains carrying the `Bloom` term (the `text_match` domain), and blocked elsewhere via the usual domain-fallback blockers. The operator-metadata test is table-driven, so a new term's surface is one table row.
Registers `text => String` in the `scalar_types!` list and teaches the harness about an owned, non-Copy scalar: `ScalarType`/fixtures go `Copy` -> `Clone`, `to_sql_literal` takes `&Self`, and `String` gets a hand-written `impl ScalarType` (lexicographic pivots, single-quote SQL literal). The `eql-tests-macros` dispatch is catalog-derived (`is_int_token`/`is_temporal_token`/`is_text_token` read from `eql_scalars::CATALOG`) rather than a dispatch-list marker, and the `scalar_fixture!` macro gains a `text` arm stamping the `Match` index. Adds the sealed `EqlPlaintext` impl for `String` (text cast + `Plaintext::Text`).
…x text "" pivot (#262) The scalar matrix's third pivot was hardwired to `Default::default()` — `0` for int, the epoch for date, but `""` for text, which encrypts to an empty ORE term and broke ordering/aggregates. Introduce the taxonomy as traits: - `ScalarType` (base) — identity, fixtures, literal rendering. - `OrderedScalar: ScalarType` — `min_pivot`/`max_pivot` + an overridable interior `mid_pivot` (default `Self::default()`). int/date inherit (0/epoch); text overrides to a real median ("frank"), never the degenerate "". - `SignedScalar: OrderedScalar` — `origin()` (numeric zero / sign boundary). int and date only; text is NOT `SignedScalar`. The proc-macro and the `temporal_values!` macro emit the `OrderedScalar` (+ `SignedScalar`) impls; the unified `scalar_matrix!` sweeps `min`/`mid`/`max` from `OrderedScalar` (the `_pivot_zero_` -> `_pivot_mid_` snapshot rename). The signed-only sign-boundary test lives in `encrypted_domain/signed.rs`, generic over `SignedScalar`, so a `text` instantiation is a compile error. Drops `""` from `TEXT_FIXTURES`.
SQLx coverage for the text family beyond the generated matrix: `text_smoke` exercises `eql_v3.text_match @> match` and the blocked `=` plus empty-bloom set semantics; `text_match` is the dedicated containment suite (self / substring / disjoint / bare-operator GIN index engagement). Both live under `encrypted_domain/text/` (outside the `scalars::` namespace) so the matrix inventory snapshot stays the uniform per-type set, and are registered alongside the signed-only suite in `encrypted_domain.rs`.
Documents the `eql_v3.text` family (eq / match / ord) and the `Bloom` index term in the scalar-encrypted-domain reference guide — including the `OrderedScalar`/`SignedScalar` pivot-trait section and the catalog-derived (marker-free) text dispatch — and adds the `[Unreleased]` changelog entry (#260).
…(STRICT) The `eql_v3.ore_block_u64_8_256(jsonb)` extractor is `STRICT`, so PostgreSQL already short-circuits to NULL on a NULL argument — the explicit `IF val IS NULL` guard is dead code. Adjacent cleanup to the SEM extractors; no behaviour change.
The bloom containment surface (eql_v3.text_match @>/<@) replaces deprecated LIKE/ILIKE but is semantically different (probabilistic, ngram-based, no wildcards/anchoring), which confuses users. Close the coverage gaps: - <@ (contained-by) was implemented in SQL but completely untested: add positive, negative, and commutator (a @> b == b <@ a) assertions, plus a literal-payload <@ engage and empty-set test. - match_null_propagates: @>/<@ are STRICT, so a NULL operand yields NULL. - text_match_containment_requires_all_elements: pins set-containment semantics (every needle ngram must be present) — the property that makes @> not LIKE. - text_match_like_ilike_absent: ~~/~~* resolve to 'operator does not exist' on text_match, the domain a LIKE user would reach for. - text_match_payload_check_rejects_missing_bf: the domain CHECK requires bf. Hand-written suites only (bloom is text-only, outside the cross-type matrix); no SQL/fixture changes — reuses existing eql_v2_text fixtures.
Adds the four characterization tests @auxesis requested on #260, each pinning a branch the existing suite never reached: - has_bloom_filter(jsonb) presence predicate (present/absent/{"bf":null} -> false) — the IS NOT NULL half of its guard was untested, and it is not reached transitively by the extractor or domain CHECK. - bloom_filter(jsonb) empty-array branch: {"bf":[]} -> empty smallint[], not NULL (the extractor basis for empty-set containment semantics). - String::to_sql_literal single-quote escaping (O'Brien -> 'O''Brien'); all TEXT fixtures are quote-free so no DB test hit the .replace. - Fixture::Zero/Min/Max -> None on non-integer kinds (Date/Text), the arm changed from unconditional Some(0); previously only guarded indirectly by the pivot_sentinels_only_appear_with_integer_kinds catalog invariant. All four pass; behaviour was already correct, these are regression nets.
Reconcile the adding-a-scalar guide with the post-timestamptz/text catalog: correct the claim that timestamptz is ordered (it is equality-only via EQ_ONLY_DOMAINS), add the missing Timestamptz/Date enum variants, and note that @>/<@ back onto Bloom containment wrappers rather than blockers. Document the previously-undocumented mechanics a follower needs: eq-only is selected by the catalog domain slice (caps auto-derived), a new-capability domain like _match needs hand-written #[path]-registered suites, non-integer types need the third scalar_domains.rs registration, and the Bloom splinter allowlist names.
The extractor doc and its sibling test comment claimed the text_match domain
CHECK guarantees `bf` is an array, so a non-array `bf` could only occur outside
the domain. The CHECK only asserts key presence (`VALUE ? 'bf'`), so a typed
value like {"bf": null} reaches the extractor with a non-array `bf` — which is
exactly why the array-gate and its test exist. Also fix a stale macro name
(`ordered_numeric_matrix!` -> `scalar_matrix!`) and trim a thrice-repeated
rationale in the text_values wiring.
Adds int2/int8/date/text/timestamptz reference goldens alongside the existing int4 set, generated once with `cargo run -p eql-codegen` and byte-identical to the generator output. These cover the eq-only and Bloom `text_match` render shapes that int4 never exercises. Pure generated SQL. The parity machinery that discovers these dirs and gates each against the generator (dynamic discovery + `reference_dirs_match_catalog_tokens`) lands in the stacked follow-up (eql-codegen/eql-scalars review hardening), which depends on these files existing. Until then the existing int4 parity test is unaffected.
…lars Acts on the three-agent code review of the v3 scalar codegen crates (quality, idiomatic-Rust, test coverage). No user-facing behaviour change: generated SQL is byte-identical (parity gate green, no churn in release/ or src/). Parity gate (the High findings): - Commit goldens for every catalog type (int2/int8/date/timestamptz/ text), generated once, not just int4 — catches regressions in the eq-only and Bloom text_match render shapes int4 never exercises. - Parity tests discover reference dirs dynamically and cross-check the set against CATALOG (reference_dirs_match_catalog_tokens); shell gate loops every dir. - Add a determinism test (two runs byte-identical) and an extractor_terms dedup unit test. Type-system seams: - Introduce Role enum; is_ord_capable compares == Role::Ord instead of a stringly-typed "ord" (a typo can no longer disable aggregate codegen). - wrapper_entry/unsupported_entry take &Operator (no per-signature re-scan); add a should_panic guard for operator() on unknown symbols. Dead code / consolidation / errors: - Delete unused Fixture::render_literal; collapse three token+suffix impls into DomainSpec::name_with_token; move extractor_terms into eql-scalars; WriteError derives std::error::Error via thiserror; ScalarKind::rust_type panics on the no-surface numeric/jsonb arms. Coverage + low cleanup: - Tests for WriteError::Io and the commute_op/expected_forward panic guards; commit matrix_tests_eq_only.txt and pin the eq-only derivation. - Shared eql_codegen::repo_root; Drop-cleaned parity tempdir; const AUTO_GENERATED_MARKER; ScalarKind::is_text; doc/comment fixes.
Sweep prose, comments, scripts, mise descriptions, and test identifiers to use the codebase's existing "reference" vocabulary (the dir is already tests/codegen/reference/). Renames the parity test functions rust_generator_matches_golden_files -> rust_generator_matches_reference_files and generator_matches_reference_goldens -> generator_matches_reference_files, plus the shell golden_set -> reference_set, with all cross-references updated.
AUTO_GENERATED_HEADER was a #[cfg(test)]-only duplicate of
AUTO_GENERATED_MARKER + "\n", kept in sync by two dedicated tests. Drop
it: tests now build file bodies with format!("{AUTO_GENERATED_MARKER}\n...")
and the lone starts_with check appends the newline inline. One source of
truth, no behavior change.
…gration READMEs
Review caught build_validation_tests.rs still reading cipherstash-encrypt-v3.sql
after the Task 9 rename to the canonical name — would fail CI. Repoint all five
path literals to cipherstash-encrypt{,-uninstall}.sql. Also refresh the migration
READMEs that still documented the deleted 002-007 migrations.
The v2-coupled tasks/pin_search_path.sql is removed; the v3 build appends tasks/pin_search_path_v3.sql. Update the prose references in src/v3 doc comments and inlinability.rs accordingly (comment-only; no functional change).
…lan in ADR The structural guard `encrypted_domain_blockers_are_plpgsql_and_non_strict` matched only `%encrypted_domain_unsupported_bool%`, so a `_jsonb` (`#>`, `||`, `-`) or `_text` (`#>>`, `->>`) blocker regressing to LANGUAGE sql / STRICT would escape it — even though that test exists to backstop `eql_v3.lints()` without depending on it. Broaden to `%encrypted_domain_unsupported%`, matching the `encrypted_domain_blockers` CTE in src/v3/lint/lints.sql verbatim so the two cannot drift. The jsonb-domain-arg EXISTS still excludes the shared `encrypted_domain_unsupported_*(text, text)` helpers. Also cross-link the deferred Tier-1 reference-doc rewrite plan from ADR-0001's Related section so the follow-up is discoverable.
Port version introspection to the self-contained eql_v3 surface after the eql_v2 removal dropped eql_v2.version() (and left tasks/build.sh's --version flag consumed nowhere). - src/v3/version.template: eql_v3.version() returns bare-semver text, plus a COMMENT ON SCHEMA eql_v3 marker for obj_description() discoverability. REQUIRE src/v3/schema.sql only; self-contained, no eql_v2 symbols. The generated src/v3/version.sql is gitignored like the other v3 SQL. - tasks/build.sh: sed-substitute the template before the v3 glob, reviving the --version flag (usage_version, DEV fallback). - release workflows: pass prefix-stripped bare semver to --version; fix the stale 'eql_v2.version() byte-identical' comment. - CHANGELOG/ADR-0001: document the re-home (not a silent drop). version() is pinned by pin_search_path_v3.sql (not inline-critical), so the splinter function_search_path_mutable lint does not flag it. User-facing doc repointing is owned by the migrate-docs-to-eql-v3 branch.
- v3_jsonb_operator_surface_tests: drop dead eql_v2_encrypted exclusion subqueries (composite type removed -> subquery is always-true) and the now-stale explanatory comment - xml-to-markdown.py: make the operator-schema match v3-aware (['eql_v2','public'] -> add 'eql_v3') so v3-only doc generation resolves eql_v3 operator names - matrix.rs: fix now-false comment claiming the generic eql_v2_encrypted MIN/MAX overload is reachable via cast (overload removed); logic unchanged - eql_plaintext.rs: reword Cast doc-comment off the removed eql_v2.add_search_config reference
Remove eql_v2 — ship only the self-contained eql_v3 surface
…iants and eql_v3.json
…b durable performance guidance; drop operator-class recipe
…-author operators and keep eql_v3 surface
… client-side config round-trip
…inks to client-side config
…ts, permissions, getting started, versioning)
…solete documentation-inventory.md
The doc migration predated the version() port, so version() was documented
nowhere and docker/README still referenced the removed eql_v2 surface.
- README.md: add a 'SELECT eql_v3.version()' check to the Versioning section.
- docker/README.md: repoint the intro prose ('eql_v2 schema') and the version
example onto eql_v3 (the file was missed by the migration).
- docs_v3_grep.sh: add docker/README.md to the Tier-1 gate so it stays
eql_v2-free.
eql_v3.version() ships from the remove-eql-v2 branch.
…urface Replace the removed eql_v2 architecture (eql_v2_encrypted composite, config table, old src/ layout, db-side index config) with the v3 model: per-scalar eql_v3.<T> domains, the catalog/codegen build, functional indexes on extractors, and client-side configuration.
…md links - json-support: fix ste_vec ORE leaf term key ocv/ocf -> oc (matches src/v3/jsonb) - releasing-an-alpha: correct artifact model to the two real release artifacts (cipherstash-encrypt.sql is the self-contained eql_v3 surface) + docs bundle - sql-documentation-templates: drop dead @see add_search_config; AS [base_type] -> AS jsonb (no domain-over-domain footgun) - repoint inbound PAYLOAD.md links (docs index, eql-functions, proxy-configuration) to crates/eql-types (canonical wire types) + json-support.md - WHY: markdown spacing fix
…ng docs Correct the remaining "eql_v2 coexists / is the unchanged public API" framing to match reality: eql_v2 was removed in 3.0.0 and eql_v3 is the sole shipped surface. - DEVELOPMENT.md: replace the coexistence "Schemas" section with an accurate "The eql_v3 surface" section (v2 removed, fork-provenance/historical mentions flagged as deliberate); fix TOC anchor. - CLAUDE.md: fix the Schema bullet and Versioning paragraph that still asserted eql_v2 coexists/unchanged. - SUPABASE.md: reword the two remaining v2 callouts to teach the v3 way with no v2 references (a separate v2->v3 migration guide can come later). - docs/development/reference-sync-rules.md: update stale eql_v2 examples to verified v3 symbols (eql_v3.ciphertext, eql_v3.eq_term). Remove obsolete/invented artifacts and dead v2 fixtures: - delete docs/decisions/0001-remove-eql-v2.md and docs/plans/add-doxygen-sql-comments-plan.md; strip the 3 dangling ADR links from CHANGELOG (entries already explain the why inline). - delete tests/ORE_FIXTURES.md (documented the removed v2 proxy fixture flow; v3 ORE coverage is subsumed by catalog-generated scalar fixtures) and the orphaned tests/ore.sql / tests/ore_text.sql data files (loaded by nothing). Guard: refactor tasks/test/docs_v3_grep.sh from a hand-maintained allowlist to scan-all-with-exclusions over git-tracked docs (new reference/tutorial/concept pages covered automatically; untracked scratch ignored), and wire it into the docs-static CI job (runs on every PR, already in ci-required).
Migrate user-facing docs to the eql_v3
Re-verify the eql_v3 implementation audit against the current tree and correct drift introduced by the 3.0.0 overhaul (single self-contained installer; eql_v2 removed): - §1/§6: eql_v2 is removed, not 'the documented public API, unchanged'; reframe the ORE-comparator note as historical fork provenance. - §5: replace the 4-variant build table with the single-artifact build; re-cite build.sh and rename pin_search_path.sql -> pin_search_path_v3.sql. - §3.3: drop stale 'Supabase variant' exclusion; explain the functional- index rationale that made the subset build redundant. - §4.3: v3_ste_vec.sql is now generated/gitignored, not a committed fixture. - §2.4: fix drifted scalar_domains.rs / spec.rs line citations. De-enumerate snapshot baseline counts so they can't rot: CLAUDE.md and audit §4.2 now point at tests/sqlx/snapshots/README.md as the source of truth, and that README now documents matrix_jsonb_entry_tests.txt.
…ng comment The `eql_v3.json` domain flattens to native `jsonb` when an operator's RHS is an unknown-typed literal, so a bare `col -> 'sel'` binds the NATIVE `jsonb -> text` (a root-key lookup on the envelope) instead of the v3 selector-lookup operator — a silent wrong answer for direct-SQL callers (the Proxy is unaffected because it always sends typed `$n`). This is intrinsic to the domain type-kind and cannot be closed by an extra operator/blocker; it can only be pinned. - Re-land v3_jsonb_bare_operand_flattens_to_native (blocker face: `?` / `||` succeed as native on a bare RHS, raise on a typed RHS), recovered from the dropped commit 817a9660. - Add v3_jsonb_arrow_bare_operand_flattens_to_native (supported-operator face): assert via pg_typeof which operator binds AND the user-visible value divergence, so a resolution change in either direction goes red. Verified empirically against PG 17 (bare `-> 'sv'` -> jsonb `[]`; typed `-> 'sv'::text` -> eql_v3.ste_vec_entry NULL). - Regenerate snapshots/v3_jsonb_tests.txt (74 -> 76) for test:v3-jsonb:inventory. - Fix the inline comment in operators.sql (integer `->` overload): it claimed a bare `e -> 'sv'` would bind the v3 operator — empirically false and contrary to the file's own @warning. Bare binds native; the custom operator does not capture an untyped literal. Comment-only, no behaviour change.
…allthrough test(eql-v3): pin ->/->> bare-literal domain-flattening; fix misleading comment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Long-running integration branch for the EQL v3 major release. Tracks
eql_v3againstmain.v3 introduces a new, additional
eql_v3schema of type-safe, per-capability encrypted-domain types. The existingeql_v2surface is unchanged and remains the documented public API.Scalar encrypted-domain families
Per-type jsonb-backed domains, each with
_eq(=/<>via HMAC) and_ord/_ord_ore(<<=>>=,MIN/MAXvia ORE block terms) variants, plus a storage-only base domain. Supported operators resolve to inlinable wrappers; nativejsonboperators reachable via domain fallback are blocked rather than silently mis-resolving.int2,int4,int8(feat(encrypted-domain): add int2 scalar domain family #243, feat: eql_v2_int4 variant family (v3) #239, feat(int8): add eql_v3.int8 encrypted-domain type family #253)date,timestamptz(UTC-normalized),numeric— ordered, ORE wider than 8 blocks (feat(scalars): add eql_v3.date encrypted-domain type + temporal wiring #256, feat(scalars): add eql_v3.timestamptz encrypted-domain type (equality-only) #257, Generalize ORE block comparator to N blocks (not hardcoded 8) for wide-term ordering (decimal/timestamp) #241/feat(v3): N-block ORE comparator + ordered numeric & timestamptz #276)float4/float8— ordered (feat(v3): float4/float8 encrypted-domain types #299)bool— storage/encryption-only (feat(eql_v3): addboolstorage-only encrypted-domain type #295)text—text_eq,text_match,text_ord,text_search(feat(scalars): add eql_v3.text encrypted-domain family (eq / match / ord) #260)Encrypted-JSONB (SteVec) document type
Self-contained encrypted-JSONB surface:
eql_v3.jsonstorage domain plusste_vec_entry/ste_vec_query. Searchable without decryption via containment (@>,<@), field/array access, entry equality, and entry-level ordered range via CLLW ORE. Comparisons are leaf-level only; root-document and native-jsonb operators are blocked. (#267)SEM index-term types
eql_v3owns its searchable-encrypted-metadata index-term types directly —hmac_256,ore_block_256,ore_cllw,bloom_filter— with noeql_v2dependency. The ORE block comparator orders ciphertexts of any block count (#241).=/<>on the v2 ORE term now declare aCOMMUTATOR(#239).Codegen
Scalar domains are generated from a Rust catalog (
eql-scalars::CATALOG) by theeql-codegenmaterializer. The Python codegen toolchain is removed. Supporting crates:eql-types(canonical payload types + JSON Schemas),eql-scalars,eql-codegen. (#252, #236, #269)Packaging
Self-contained, standalone
release/cipherstash-encrypt-v3.sqlinstaller + uninstaller, attached to GitHub Releases. (#255, #307)