[4/6] feat(eql-mapper): rewrite SQL to the EQL v3 functional-index form#428
[4/6] feat(eql-mapper): rewrite SQL to the EQL v3 functional-index form#428freshtonic wants to merge 17 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
717589f to
c251fb8
Compare
Review — v3 rewrite pipelineCareful, well-documented implementation. ADR-0003 is genuinely load-bearing, the domain-capability logic is exhaustively unit-tested, and the Nice catch on the LIKE capability bypass — the old arm just did 🔴 Blocking-ish1. The 2. No execution anywhere. CONTEXT.md says it: "End-to-end validation against a live database with EQL v3 installed is still pending." Every test is 🟡 Test gaps (all verified absent)
🟡 Question —
|
3cad2c5 to
1a81cf2
Compare
… double domain Fills the rewrite-output test gaps called out in review of the v3 rewrite pipeline (#428): - ILIKE and NOT LIKE / NOT ILIKE — the negated match arm in RewriteEqlMatchOps had no rewrite-output coverage (only positive LIKE/@@ did). - UPDATE SET stored-value cast — of ADR-0003's two stored-value contexts only INSERT had cast-target coverage; UPDATE now pins `SET salary = 'ENCRYPTED'::JSONB::public.eql_v3_text`. - native LIKE still type-checks — regression lock for routing LIKE/ILIKE through the TokenMatch-bounded rule (Native satisfies all bounds). - the `double` token does not swallow its capability suffix — pins the eql_v3_double_ord invariant that suffix()/stores_* only documents in a comment. Stable-Commit-Id: q-47bk2x9aqbw7j8v04j81ecbec4
The queue changes user-visible behaviour (v3 typed jsonb domains replace eql_v2_encrypted, cipherstash-client 0.42.0 / EQL 3.0.2, LIKE/ILIKE now capability-checked, `@@` newly supported) but touched no CHANGELOG entry. Add one [Unreleased] section covering the migration, per CLAUDE.md and the review notes on #424/#428. Stable-Commit-Id: q-0s2fx8fb1q2563t7b45x9crjmf
c251fb8 to
081333f
Compare
1a81cf2 to
4b016ae
Compare
… double domain Fills the rewrite-output test gaps called out in review of the v3 rewrite pipeline (#428): - ILIKE and NOT LIKE / NOT ILIKE — the negated match arm in RewriteEqlMatchOps had no rewrite-output coverage (only positive LIKE/@@ did). - UPDATE SET stored-value cast — of ADR-0003's two stored-value contexts only INSERT had cast-target coverage; UPDATE now pins `SET salary = 'ENCRYPTED'::JSONB::public.eql_v3_text`. - native LIKE still type-checks — regression lock for routing LIKE/ILIKE through the TokenMatch-bounded rule (Native satisfies all bounds). - the `double` token does not swallow its capability suffix — pins the eql_v3_double_ord invariant that suffix()/stores_* only documents in a comment. Stable-Commit-Id: q-47bk2x9aqbw7j8v04j81ecbec4
The queue changes user-visible behaviour (v3 typed jsonb domains replace eql_v2_encrypted, cipherstash-client 0.42.0 / EQL 3.0.2, LIKE/ILIKE now capability-checked, `@@` newly supported) but touched no CHANGELOG entry. Add one [Unreleased] section covering the migration, per CLAUDE.md and the review notes on #424/#428. Stable-Commit-Id: q-0s2fx8fb1q2563t7b45x9crjmf
081333f to
627e45e
Compare
|
Addressed the review (all pushed):
|
4b016ae to
3fd4309
Compare
… double domain Fills the rewrite-output test gaps called out in review of the v3 rewrite pipeline (#428): - ILIKE and NOT LIKE / NOT ILIKE — the negated match arm in RewriteEqlMatchOps had no rewrite-output coverage (only positive LIKE/@@ did). - UPDATE SET stored-value cast — of ADR-0003's two stored-value contexts only INSERT had cast-target coverage; UPDATE now pins `SET salary = 'ENCRYPTED'::JSONB::public.eql_v3_text`. - native LIKE still type-checks — regression lock for routing LIKE/ILIKE through the TokenMatch-bounded rule (Native satisfies all bounds). - the `double` token does not swallow its capability suffix — pins the eql_v3_double_ord invariant that suffix()/stores_* only documents in a comment. Stable-Commit-Id: q-47bk2x9aqbw7j8v04j81ecbec4
The queue changes user-visible behaviour (v3 typed jsonb domains replace eql_v2_encrypted, cipherstash-client 0.42.0 / EQL 3.0.2, LIKE/ILIKE now capability-checked, `@@` newly supported) but touched no CHANGELOG entry. Add one [Unreleased] section covering the migration, per CLAUDE.md and the review notes on #424/#428. Stable-Commit-Id: q-0s2fx8fb1q2563t7b45x9crjmf
627e45e to
79de888
Compare
|
Review notes. Verified against the shipped EQL 3.0.2 Blocking1. Every rewritten predicate raises a domain CHECK violation. CREATE DOMAIN eql_v3.query_text_eq AS jsonb
CHECK (... AND VALUE ? 'hm' AND NOT (VALUE ? 'c') AND VALUE->>'v' = '3');Query operands are 2. EQL v2 shipped 3. Signature is ADR-0003's premiseADR-0003 justifies the functional-index form on managed Postgres forbidding operator DDL.
Smallest correct change is probably: drop the comparison rewrite and the Verified fine — no action
Minor
|
3fd4309 to
13bbd4a
Compare
… double domain Fills the rewrite-output test gaps called out in review of the v3 rewrite pipeline (#428): - ILIKE and NOT LIKE / NOT ILIKE — the negated match arm in RewriteEqlMatchOps had no rewrite-output coverage (only positive LIKE/@@ did). - UPDATE SET stored-value cast — of ADR-0003's two stored-value contexts only INSERT had cast-target coverage; UPDATE now pins `SET salary = 'ENCRYPTED'::JSONB::public.eql_v3_text`. - native LIKE still type-checks — regression lock for routing LIKE/ILIKE through the TokenMatch-bounded rule (Native satisfies all bounds). - the `double` token does not swallow its capability suffix — pins the eql_v3_double_ord invariant that suffix()/stores_* only documents in a comment. Stable-Commit-Id: q-47bk2x9aqbw7j8v04j81ecbec4
The queue changes user-visible behaviour (v3 typed jsonb domains replace eql_v2_encrypted, cipherstash-client 0.42.0 / EQL 3.0.2, LIKE/ILIKE now capability-checked, `@@` newly supported) but touched no CHANGELOG entry. Add one [Unreleased] section covering the migration, per CLAUDE.md and the review notes on #424/#428. Stable-Commit-Id: q-0s2fx8fb1q2563t7b45x9crjmf
636f874 to
8af1493
Compare
13bbd4a to
a3c7b4d
Compare
… double domain Fills the rewrite-output test gaps called out in review of the v3 rewrite pipeline (#428): - ILIKE and NOT LIKE / NOT ILIKE — the negated match arm in RewriteEqlMatchOps had no rewrite-output coverage (only positive LIKE/@@ did). - UPDATE SET stored-value cast — of ADR-0003's two stored-value contexts only INSERT had cast-target coverage; UPDATE now pins `SET salary = 'ENCRYPTED'::JSONB::public.eql_v3_text`. - native LIKE still type-checks — regression lock for routing LIKE/ILIKE through the TokenMatch-bounded rule (Native satisfies all bounds). - the `double` token does not swallow its capability suffix — pins the eql_v3_double_ord invariant that suffix()/stores_* only documents in a comment. Stable-Commit-Id: q-47bk2x9aqbw7j8v04j81ecbec4
The queue changes user-visible behaviour (v3 typed jsonb domains replace eql_v2_encrypted, cipherstash-client 0.42.0 / EQL 3.0.2, LIKE/ILIKE now capability-checked, `@@` newly supported) but touched no CHANGELOG entry. Add one [Unreleased] section covering the migration, per CLAUDE.md and the review notes on #424/#428. Stable-Commit-Id: q-0s2fx8fb1q2563t7b45x9crjmf
8af1493 to
aa1c4d8
Compare
…ation
Starts the v3 functional-index rewrite (ADR-0001) by pinning the pipeline
design and landing its hardest, most correctness-sensitive piece: choosing
the eql_v3 term-extraction function for an operator on a given column.
- ADR-0003 records the v3 rewrite pipeline: the stored-value vs query-operand
context split (column domain vs query twin cast targets), operator ->
term-function rewriting, JSON containment retained (not deleted), and the
rule inventory. All operand/term details verified against the installed
cipherstash-encrypt.sql, not the docs.
- DomainIdentity gains stores_hm/op/ob/bf and eq_term_fn/ord_term_fn/
match_term_fn/query_twin. These encode the verified selection rules:
* eq_term only where hm is stored; =/<> otherwise fall back to the ordering
term (an ord-only scalar like integer_ord compares via ord_term, exactly
as eql_v3.eq does).
* ord_term (op) vs ord_term_ore (ob) chosen from the domain typname.
* text is the hm exception (text_ord* stores hm alongside its order term).
* query_twin names the term-only operand domain (eql_v3.query_<bare>).
Unit-tested against the SEM-term table. The rewrite rule that consumes these
lands next.
Refs CIP-3599.
Stable-Commit-Id: q-4fed4c4vg8sehf76wwrn5yaysf
…ex form
First working slice of the v3 rewrite pipeline (ADR-0003). Scalar
comparisons on encrypted columns now emit the functional-index form, and
all cast targets move from the opaque eql_v2_encrypted to real v3 domains.
- New RewriteEqlComparisonOps: `col <op> x` -> `eql_v3.<term>(col) <op>
eql_v3.<term>(x)`, the term function chosen from the column's domain
identity (eq_term / ord_term / ord_term_ore). A domain with no term for
the operator is a capability error.
- Cast rules retargeted (helpers::cast_to_v3_domain): a query operand casts
to the eql_v3.query_* twin, a stored value (INSERT/UPDATE) to the
public.eql_v3_* column domain. Role is detected from the AST context
(post-order traversal + full NodePath ancestry): a value under a
comparison predicate is an operand, otherwise stored.
- CastLiteralsAsEncrypted gains node_types so it can name the target domain;
EqlTerm gains eql_value(); helpers gain eql_v3_term_call / is_comparison_op.
Example:
WHERE salary > $1
-> WHERE eql_v3.ord_term(salary) > eql_v3.ord_term($1::JSONB::eql_v3.query_text_ord)
Transitional: JSON (->, @>, jsonb_*) and aggregate (min/max) rewriting still
emit the eql_v2.* function wrappers over v3-cast operands; those wrappers are
retargeted in the next slices. Tests updated to the current output; the
params fixture gains `EQL: Eq` since a bare (capability-less) v3 column is
storage-only and rightly rejects `=`.
eql-mapper 85 passing; workspace check, clippy, fmt clean.
Refs CIP-3599.
Stable-Commit-Id: q-62kqdp86gcbb66tvwhy69tgn5s
Continues the v3 rewrite (ADR-0003). min/max and the jsonb_* passthrough functions on encrypted columns now rewrite to their eql_v3 counterparts. - RewriteStandardSqlFnsOnEqlTypes resolves a pg_catalog function to its eql_v3 counterpart via the new get_eql_v3_function_name, and rewrites only when one is declared. This fixes the long-standing count bug: count has no eql_v3 counterpart (it runs natively on the encrypted value), so it is no longer rewritten to a non-existent eql_v3.count. - sql_decls: the min/max/jsonb_path_*/jsonb_array_* target declarations move from eql_v2 to eql_v3. The containment declarations (jsonb_array, jsonb_contains, jsonb_contained_by) stay under eql_v2 until the containment slice. min(salary) -> eql_v3.min(salary) jsonb_path_query(col, '$.x') -> eql_v3.jsonb_path_query(col, '$.x'::...) count(col) -> count(col) (unchanged) eql-mapper 85 passing; workspace check, clippy, fmt clean. Refs CIP-3599. Stable-Commit-Id: q-092hd8jb1d31ck4va4n7r2gzet
Continues the v3 rewrite (ADR-0003). `@>`/`<@` on encrypted JSON columns now rewrite to the eql_v3 containment functions. Containment is retained in v3, scoped to JSON (ADR-0002 amendment) — `@>`/`<@` on scalar encrypted columns still raise. - RewriteContainmentOps emits eql_v3.jsonb_contains / jsonb_contained_by. - sql_decls: the jsonb_array / jsonb_contains / jsonb_contained_by target declarations move from eql_v2 to eql_v3. notes @> needle -> eql_v3.jsonb_contains(notes, needle) needle <@ notes -> eql_v3.jsonb_contained_by(needle, notes) No eql_v2.* function names remain in the mapper's rewrite output. eql-mapper 85 passing; clippy, fmt clean. Refs CIP-3599. Stable-Commit-Id: q-6dne3hbwwfsj7q42yqf4da8rqv
Continues the v3 rewrite (ADR-0003). `->`/`->>` on encrypted JSON columns are functionalised, since managed Postgres (Supabase) forbids the CREATE OPERATOR DDL the native operators would need (ADR-0001). - RewriteContainmentOps (now the general encrypted-JSON binary-op rule) also rewrites `col -> sel` -> `eql_v3."->"(col, sel)` and `col ->> sel` -> `eql_v3."->>"(col, sel)`. Operator-symbol function names are quoted; ordinary names are not. - CastLiteralsAsEncrypted passes a JSON field selector (an EqlTerm::JsonAccessor, the RHS of ->/->>) as encrypted *text* rather than a jsonb-domain cast, to match eql_v3."->"(json_search, text). notes -> 'medications' -> eql_v3."->"(notes, '<encrypted-selector>') ASSUMPTION TO CONFIRM (flagged in code): the encrypted selector replacement is the selector string itself. If the encrypt pipeline instead produces a jsonb payload for JSON selectors, the selector must be extracted rather than emitted verbatim — a one-line change once confirmed. eql-mapper 88 passing; clippy, fmt clean. Refs CIP-3599. Stable-Commit-Id: q-03j8aeq7we1c74jhkrgrny3rt4
LIKE/ILIKE on an encrypted column previously only unified the result with Native, so it bypassed the trait system entirely — a column with no match capability silently accepted LIKE. They now apply the `~~`/`~~*` (and negated) operator rules, so the encrypted LHS must implement TokenMatch and the pattern takes its Tokenized associated type. Adds tests: LIKE on a TokenMatch column type-checks; LIKE on an Eq-only encrypted column is a capability error. (The v3 rewrite of LIKE/@@ to `eql_v3.match_term(a) @> eql_v3.match_term(b)` is a separate follow-up; this fixes the type-checking gap.) eql-mapper 87 passing; clippy, fmt clean. Refs CIP-3599. Stable-Commit-Id: q-429ag1vxhrefpb1vy71sbkzg34
Continues the v3 rewrite (ADR-0003). LIKE/ILIKE on encrypted columns now
rewrite to the fuzzy-match functional form.
- New RewriteEqlMatchOps: `col LIKE pat` -> `eql_v3.match_term(col) @>
eql_v3.match_term(pat)`; `NOT LIKE` wraps it in `NOT (...)`. Fuzzy match
compares bloom-filter terms with @> (containment), so the operator becomes
@> between the two match_term calls, mirroring eql_v3.matches. A column
whose domain stores no bloom filter has no match_term -> capability error.
- Operand role detection (helpers::is_query_operand) now also treats a value
under a LIKE/ILIKE predicate as a query operand, so the pattern casts to the
query twin.
email LIKE 'a%'
-> eql_v3.match_term(email) @> eql_v3.match_term('<ct>'::JSONB::eql_v3.query_text_match)
`@@` (BinaryOperator::AtAt) is the remaining fuzzy-match surface; it needs the
operator declaration to parse first (separate slice).
eql-mapper 88 passing; clippy, fmt clean.
Refs CIP-3599.
Stable-Commit-Id: q-0gdjjy9gdt34jne9yhvs1kjw9m
… double domain Fills the rewrite-output test gaps called out in review of the v3 rewrite pipeline (#428): - ILIKE and NOT LIKE / NOT ILIKE — the negated match arm in RewriteEqlMatchOps had no rewrite-output coverage (only positive LIKE/@@ did). - UPDATE SET stored-value cast — of ADR-0003's two stored-value contexts only INSERT had cast-target coverage; UPDATE now pins `SET salary = 'ENCRYPTED'::JSONB::public.eql_v3_text`. - native LIKE still type-checks — regression lock for routing LIKE/ILIKE through the TokenMatch-bounded rule (Native satisfies all bounds). - the `double` token does not swallow its capability suffix — pins the eql_v3_double_ord invariant that suffix()/stores_* only documents in a comment. Stable-Commit-Id: q-47bk2x9aqbw7j8v04j81ecbec4
Completes the fuzzy-match surface (ADR-0003). `@@` now parses in the
operator DSL and rewrites like LIKE/ILIKE.
- eql-mapper-macros: the binary-operator parser accepts `@@` (it previously
only accepted `@>` after `@`), so `@@` can be declared.
- sql_decls: declare `<T>(T @@ <T as TokenMatch>::Tokenized) -> Native where
T: TokenMatch` — `@@` requires the match capability.
- RewriteEqlMatchOps now also handles `BinaryOp::AtAt`:
col @@ pat -> eql_v3.match_term(col) @> eql_v3.match_term(pat)
and `is_query_operand` treats an `@@` operand as a query operand so the
pattern casts to the query twin.
eql-mapper 89 passing; eql-mapper-macros 3 passing; clippy, fmt clean.
Refs CIP-3599.
Stable-Commit-Id: q-7s39kd5jdyhfjh1qyhkg2s858f
Validates the schema! EQL("<domain>") explicit-domain form end to end: a
block-ORE ordering column (eql_v3_integer_ord_ore) rewrites through
ord_term_ore (not ord_term) with the query_integer_ord_ore twin. This
exercises the ord-vs-ord_ore distinction that the inert domain identity
(ADR-0002) exists to carry.
seq > 5 -> eql_v3.ord_term_ore(seq) > eql_v3.ord_term_ore(...::eql_v3.query_integer_ord_ore)
eql-mapper 90 passing.
Refs CIP-3599, CIP-3600.
Stable-Commit-Id: q-0pjttkst7g5xwva2ag41v1nk6j
The queue changes user-visible behaviour (v3 typed jsonb domains replace eql_v2_encrypted, cipherstash-client 0.42.0 / EQL 3.0.2, LIKE/ILIKE now capability-checked, `@@` newly supported) but touched no CHANGELOG entry. Add one [Unreleased] section covering the migration, per CLAUDE.md and the review notes on #424/#428. Stable-Commit-Id: q-0s2fx8fb1q2563t7b45x9crjmf
query_twin() built the query-operand type as query_<bare-domain>, so a JSON column (eql_v3_json / eql_v3_json_search) cast its query operand to a non-existent eql_v3.query_json_search. The catalog defines a single jsonb query operand type, eql_v3.query_json, for every JSON domain — the shape of a jsonb needle does not vary by searchable capability. Special-case the JSON token so it maps to eql_v3.query_json; scalars keep query_<bare>. Found by running the integration suite end-to-end against a live EQL v3 DB. NOTE: this unblocks the operand *type*, but the jsonb operator surface still has a deeper gap — the mapper rewrites `col -> sel` to `eql_v3."->"(col, sel::...::eql_v3.query_json)` while the catalog's `eql_v3."->"` takes a plain text selector, so jsonb queries remain broken (the reviewer's JsonAccessor-selector concern; tracked separately). Stable-Commit-Id: q-7sq54hzge8yqq1xz0wmdmv30xe
The RHS of `->`/`->>` and the path arg of `jsonb_path_query` are SELECTORS, passed to the EQL v3 functions as encrypted-selector *text* (`eql_v3."->"(json, text)`, `jsonb_path_query(json, text)`), not a jsonb query-domain payload. The literal path already special-cased JsonAccessor, but the param path (cast_params_as_encrypted) cast every operand to the query twin — so a `->` selector param became `$1::JSONB::eql_v3.query_json` and matched no function. Leave JsonAccessor/JsonPath param placeholders bare (type inferred from the function signature; the proxy encrypts them as SteVec selectors via QueryOp::SteVecSelector), and extend the literal path to JsonPath. Resolves the reviewer's 'JsonAccessor selector assumption' NOTE — confirmed against the live encrypt path (the client emits the tokenized selector string). Found by running the integration suite against a live EQL v3 DB: this makes the `->`/jsonb_path_query SQL valid. Deeper jsonb gaps remain (field-access results, `ord_term` comparison) but those live in the EQL functions / client term encoding, not the mapper. Stable-Commit-Id: q-1216j97nm8w014hketysnfns6n
a3c7b4d to
b503aef
Compare
aa1c4d8 to
8b6a2a9
Compare
A jsonb selector (RHS of `->`/`->>`, or the `jsonb_path_query` path) is emitted by cipherstash-client as `EqlQueryPayloadV3::Selector(String)` — a bare tokenized-selector hash used directly as the `text` argument of `eql_v3."->"(json, text)` / `eql_v3.jsonb_path_query(json, text)`. Both bind paths serialized the whole EqlOutput as JSON — the literal path via `to_json_literal_value` (`serde_json::to_string`) and the param path via `Bind::rewrite` (`serde_json::to_value(..).to_string()`). For the bare-string Selector variant that re-adds JSON quotes, so the proxy bound `"<hash>"` (quoted). The function matches `@.s == $sel` against the stored per-entry `s` (unquoted hash), so it never matched and `->` returned NULL. Special-case the Selector variant in both paths to bind the raw token. Verified live: `encrypted_jsonb -> 'string'` now matches the stored entry (was NULL). NOTE: the matched entry still comes back encrypted — return-path decryption of the eql_v3_json_entry is a separate, remaining gap (CIP-3631). Stable-Commit-Id: q-642wqbdcnchf6v1y21111edetb
8b6a2a9 to
89f5b39
Compare
`encrypted_jsonb -> 'field'` and `jsonb_path_query{,_first}(...)` rewrite to
`eql_v3."->"(...)` / `eql_v3.jsonb_path_query(...)`, which return a single
`eql_v3_json_entry`. Two proxy-side gaps left those queries returning NULL or
an undecrypted entry:
- Return path: a json_entry `{v,i,h,s,c,op}` carries a `c`, so it deserialised
as a scalar `Encrypted` payload whose ciphertext is not self-decryptable
(an entry ciphertext only opens with its selector-derived nonce). Detect the
bare entry by its root-level selector `s` and reshape it into a one-entry
SteVec document `{v,k:"sv",i,h,sv:[{s,c,op?}]}` so the existing SteVec
decrypt path recovers the field value.
- Param path: the tokenized selector is bound as `text`, but a binary Bind
unconditionally prepended the jsonb version byte (0x01), corrupting the
selector so `->` matched no stored entry. Bind it as bare text with no
header (the binary wire form of `text` is just its raw bytes).
Together these make encrypted JSON field access and path queries work over
both the simple and extended protocols (17 integration tests). The remaining
jsonb ordering, containment, array and term-filter gaps are tracked in
CIP-3630 / CIP-3631.
Stable-Commit-Id: q-2rq44tjqgd12sceeq283d6gk1s
89f5b39 to
a193749
Compare
Implements `WHERE col -> sel <op> value` (`<`, `<=`, `>`, `>=`, and the
`jsonb_path_query_first(col, sel) <op> value` form) over encrypted JSON, in
both the simple and extended protocols. Rewrites to the EQL v3 functional-index
form (matching the stack adapters' `eql_v3.gt(col -> $1, $2::query_*_ord)`):
eql_v3.ord_term(eql_v3."->"(col, <selector>))
> eql_v3.ord_term($2::jsonb::eql_v3.query_integer_ord)
- New `EqlTerm::JsonOrd` / `EqlTermVariant::JsonOrd` — the scalar ordering
operand of a JSON field comparison. Inferred (infer_type_impls/expr.rs) for
the non-`->` side of a `<`/`<=`/`>`/`>=` comparison whose other side is a
JsonLike field access. Equality is intentionally excluded (exact JSON equality
is value-selector containment, a separate feature).
- The operand casts to `eql_v3.query_integer_ord` — a shape-only, type-agnostic
ord twin. `eql_v3.ord_term` extracts the `op` bytes regardless of scalar type
and the twin's CHECK is shape-only (`{v,i,op}`), so ONE twin serves any JSON
leaf type. This is what makes it work in the extended protocol, where the
operand's scalar type is unknown at rewrite time.
- The proxy encrypts a JsonOrd operand via `QueryOp::SteVecTerm` (zerokms.rs)
and encodes the scalar to match the stored leaf's `for_json_value` SteVec `op`
(from_sql.rs): a JSON number → float (the 8-block CLLW-OPE encoding, NOT a
small int), a JSON string → its unquoted text. Both the bare-literal
(`> '4'` / `> 'C'`) and text-format jsonb-param renderings are parsed as JSON
to recover the scalar type/content.
Fixes the 8 `select_where_jsonb_{gt,gte,lt,lte}` integration tests (numeric and
string); no regressions (mapper 97 unit tests green, jsonb suite 54→62 passing).
Stable-Commit-Id: q-3ecs5hbqrk8vw4827atp3zp17n
Cleanup pass (CIP-3601), now that the v3 rewrite is in place. - eql-mapper-macros: the EqlTrait / operator parse-error messages listed only Eq, Ord, TokenMatch, JsonLike but Contain is a valid keyword (retained in v3 for JSON containment). Both messages now include Contain. - eql-mapper CONTEXT.md: the "migration in flight" note claimed the code still emits the v2 surface; it now emits v3 (no eql_v2.* names remain in output), with end-to-end validation still pending. Note on the default()/all() reconciliation (the other CIP-3601 item): no production change is needed. schema_delta's collect_ddl never fabricates EQL traits (new/added columns are Native), so its EqlTraits::default() only appears in test assertions, consistent with the schema! macro's bare `EQL` (a capability-less, storage-only v3 column). The former mismatch was the loader's hardcoded all(), which CIP-3598 replaced with domain-derived capability. eql-mapper 90 passing; eql-mapper-macros 3 passing; fmt clean. Refs CIP-3601. Stable-Commit-Id: q-56sd3v5nxbdh5b4kpepyc1mm31
a193749 to
16e0902
Compare
📚 eql-v3 PR · 4 of 6
Part of a queue. The PRs merge in FIFO order — the numbered order below, #1 first. Merging one supersedes the PRs after it until the author runs
git queue sync(rebases the rest onto the merged base) andgit queue submit(retargets their PRs).✅🟢 #422
queue/eql-v3/setup-skills→main✅🟢 #423
queue/eql-v3/upgrade-deps→queue/eql-v3/setup-skills♻️🟢 #424
queue/eql-v3/typecheck→queue/eql-v3/upgrade-deps✅🟢 #428
queue/eql-v3/transform→queue/eql-v3/typecheck👈 this PR✅🟢 #426
queue/eql-v3/showcase→queue/eql-v3/transform⏳🟢 #427
queue/eql-v3/integration→queue/eql-v3/showcase✅ approved · ♻️ changes requested · ⏳ review pending | 🟣 merged · 🟢 open · ⚫ closed — status as of the last
git queue submit.🥞 Managed by git-queue — do not edit this list by hand.
About this queue
Migrates CipherStash Proxy from EQL v2 to EQL v3 (cipherstash-client 0.34.1-alpha.4 → 0.42.0, EQL 2.3.0-pre.3 → 3.0.2), replacing the opaque eql_v2_encrypted composite type with 53 typed jsonb domains that encode both scalar type and searchable capability in the column type itself.