Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a8ec17c
feat(eql_v3): add storage-only public.eql_v3_json; rename JSON family…
tobyhede Jul 14, 2026
6aa8b96
fix: apply CodeRabbit auto-fixes
tobyhede Jul 15, 2026
5890243
fix: correct stale TOC anchor for json-support querying section
tobyhede Jul 15, 2026
89a1da5
test(json): extract real-ciphertext storage fixture + suite from PR #397
tobyhede Jul 15, 2026
e73f6f6
test(json): storage-only eql_v3_json domain — real-ciphertext matrix …
tobyhede Jul 15, 2026
a51c1f4
test(json): isolate storage-reject payload + fix identity in clean-in…
tobyhede Jul 15, 2026
bd8af9d
docs(codegen): fix stale jsonb→json binding refs; generalize mixed-fa…
tobyhede Jul 15, 2026
920ce73
style: rustfmt v3_json_storage_tests
tobyhede Jul 15, 2026
3d342d7
chore(changeset): json storage/rename is a patch (3.0.1)
tobyhede Jul 15, 2026
d4ff8c6
chore(release): open eql-3.0.1 release batching branch
tobyhede Jul 16, 2026
30b2550
Merge pull request #398 from cipherstash/feat/eql-v3-json-storage-and…
tobyhede Jul 16, 2026
18d58e7
feat(eql_v3)!: rename text bloom fuzzy match to `@@` / `eql_v3.matches`
tobyhede Jul 15, 2026
36b9843
refactor(eql-codegen): model operator symbol as OpSymbol enum
tobyhede Jul 15, 2026
f6d5b5e
Merge pull request #406 from cipherstash/eql-v3-rename-text-match-ope…
tobyhede Jul 16, 2026
0aa9f6a
Merge pull request #408 from cipherstash/refactor/eql-codegen-opsymbo…
tobyhede Jul 16, 2026
e0db50c
ci(release): allow prereleases from any non-main branch
tobyhede Jul 16, 2026
e7790ab
chore(release): eql 3.0.1-alpha.0
tobyhede Jul 16, 2026
0d87403
docs(eql_v3): fix stale/inverted CLLW-OPE migration comments (CIP-3490)
freshtonic Jul 14, 2026
4623cab
test(eql_v3): close CLLW-OPE migration coverage gaps (CIP-3491)
freshtonic Jul 14, 2026
fa31d49
ci(splinter): drop 10 stale ore_cllw allowlist rows, add unused-row c…
freshtonic Jul 14, 2026
8cfcdd9
Merge pull request #399 from cipherstash/james/cip-3490-cllw-ope-migr…
freshtonic Jul 16, 2026
49ef541
ci(known-failures): close four fail-open / false-positive paths (CIP-…
freshtonic Jul 14, 2026
bbd4d18
Merge pull request #402 from cipherstash/james/cip-3489-splintersh-10…
freshtonic Jul 16, 2026
87e5aae
Merge pull request #401 from cipherstash/james/cip-3488-harden-the-kn…
freshtonic Jul 16, 2026
aacb4a5
test(sqlx): size the test Postgres lock table for concurrent uninstalls
freshtonic Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/json-storage-and-search-rename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cipherstash/eql': patch
---

**The encrypted-JSON domains are renamed for a consistent `public.eql_v3_json` family, and a new ciphertext-only storage domain is added.** The bare name `public.eql_v3_json` is now a **storage-only** domain (a single opaque ciphertext, `{v,i,c}` envelope, no index terms — the JSON analogue of `public.eql_v3_boolean`, for encrypt-at-rest with no server-side searchability). The searchable SteVec document that previously held the bare `public.eql_v3_json` name is renamed to `public.eql_v3_json_search`; its supporting domains follow: `public.eql_v3_jsonb_entry` → `public.eql_v3_json_entry`, and the containment needle `eql_v3.query_jsonb` → `eql_v3.query_json`. This makes the JSON family follow the same convention as every scalar family — the bare family name is the storage-only domain and a suffix (`_search`, mirroring text's `_search`) marks the searchable variant. Reach for `public.eql_v3_json_search` when you need containment/field queries over encrypted JSON (`@>`, path access) and `public.eql_v3_json` when you only need to store and round-trip an encrypted JSON value. Callers on the previous names must update column declarations and query casts (`WHERE doc @> $1::eql_v3.query_json`); the bindings, `DomainPayload`/`QueryPayload` parse names, and published JSON Schema file names all move to the new names.
5 changes: 5 additions & 0 deletions .changeset/rename-text-match-operator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cipherstash/eql': patch
---

**Text bloom fuzzy match is renamed to `@@` / `eql_v3.matches` — it is n-gram token matching, not containment.** On the text match/search domains (`public.eql_v3_text_match`, `public.eql_v3_text_search`, `public.eql_v3_text_search_ore`) the fuzzy match was previously spelled with the containment operators `@>` / `<@`, backed by `eql_v3.contains` / `eql_v3.contained_by`. That promised substring/containment semantics the operation does not provide: it is array containment over two bloom filters built from the downcased 3-gram token set — a probabilistic, order- and multiplicity-insensitive, one-sided match (a `true` may be a false positive; a `false` never is). The match is now a single directional operator `@@` backed by `eql_v3.matches` (`WHERE col @@ $1::public.eql_v3_text_match`), and the reverse `contained_by` direction is dropped. `@>` and `<@` now **raise** "operator not supported" on the text match domains. The functional GIN index recipe is unchanged (`GIN (eql_v3.match_term(col))`): `col @@ $1` inlines through `match_term` to the same array-containment the index supports. Genuine JSON containment (`public.eql_v3_json_search` `@>`/`<@`, `eql_v3.ste_vec_contains`) keeps the containment vocabulary and is unaffected. This is the SQL-layer counterpart of the SDK's `contains()` → `matches()` rename; callers or SDKs emitting `eql_v3.contains(col, …)` / `col @> $1` for text match must switch to `eql_v3.matches(col, …)` / `col @@ $1` in lockstep. See upgrade note U-008.
20 changes: 13 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ name: "Release"
# Single release entry point for the EQL release line.
#
# - `main` uses Changesets to version and publish the production release.
# - `eql_v3` can cut prereleases from an explicit conventional release commit.
# The release commit itself is the marker: `chore(release): ...`.
# - Any non-`main` branch can cut a prerelease from an explicit conventional
# release commit, triggered via workflow_dispatch against that branch (e.g.
# `gh workflow run release.yml --ref eql-3.0.1`). The release commit itself is
# the marker: `chore(release): ...`. This lets a batching branch ship an
# alpha/rc for pre-merge testing without merging to `main`.
#
# Prereleases publish the npm package directly from this workflow and dispatch
# the Rust crate publish through `release-plz.yml` so crates.io Trusted
Expand All @@ -23,7 +26,6 @@ on:
push:
branches:
- main
- eql_v3
workflow_dispatch: {}

concurrency:
Expand Down Expand Up @@ -60,10 +62,14 @@ jobs:

if [[ "$branch" == "main" ]]; then
mode="production"
elif [[ "$branch" == "eql_v3" ]]; then
# Exactly `chore(release):` — a bare `release:` prefix would let an
# unrelated commit ("release: fix runbook") re-trigger the publish
# pipeline for the currently pinned identity.
else
# Any non-main branch cuts a prerelease from an explicit
# conventional release commit (dispatched via workflow_dispatch).
# Safety comes from the three guards below — the marker commit, the
# prerelease-shaped version, and the tag-idempotency short-circuit —
# not from the branch name. Exactly `chore(release):`; a bare
# `release:` prefix must NOT re-trigger the publish pipeline for the
# currently pinned identity.
case "$subject" in
chore\(release\):*)
mode="prerelease"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ tests/sqlx/migrations/001_install_eql.sql
# never commit — stale fixtures hide bugs)
tests/sqlx/fixtures/eql_v3*
tests/sqlx/fixtures/v3_ste_vec.sql
tests/sqlx/fixtures/v3_json_storage.sql
tests/sqlx/fixtures/v3_doc_integer.sql
tests/sqlx/fixtures/v3_numeric_collision.sql
tests/sqlx/fixtures/v3_text_empty.sql
Expand Down
8 changes: 4 additions & 4 deletions CLAUDE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 12 additions & 11 deletions SUPABASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ or [CipherStash Stack](https://github.com/cipherstash/stack):

- `public.<T>_eq` carries an `hm` term — supports `=` / `<>`, `GROUP BY`, `DISTINCT`.
- `public.<T>_ord` (and the `_ord_ope` twin) carries an `op` term — adds `<` `<=` `>` `>=`, `ORDER BY`, `MIN` / `MAX`. `public.<T>_ord_ore` is the block-ORE (`ob`) equivalent.
- `public.eql_v3_text_match` carries a `bf` term — supports bloom-filter token containment (`@>` / `<@`).
- `public.eql_v3_text_match` carries a `bf` term — supports bloom-filter token match (`@@` / `eql_v3.matches`; `@>` / `<@` raise).
- `public.eql_v3_text_search` carries all three terms — equality, ordering, and containment on `text`. `public.eql_v3_text_search_ore` is its block-ORE equivalent.

Configuring those columns is a client-side concern. See:
Expand All @@ -88,11 +88,10 @@ is awkward to express.
| `<=` | `eql_v3.lte(col, $1)` | `SELECT * FROM events WHERE eql_v3.lte(encrypted_at, $1)` |
| `>` | `eql_v3.gt(col, $1)` | `SELECT * FROM events WHERE eql_v3.gt(encrypted_at, $1)` |
| `>=` | `eql_v3.gte(col, $1)` | `SELECT * FROM events WHERE eql_v3.gte(encrypted_at, $1)` |
| `@>` | `eql_v3.contains(col, $1)` | `SELECT * FROM users WHERE eql_v3.contains(encrypted_name, $1)` |
| `<@` | `eql_v3.contained_by(col, $1)` | `SELECT * FROM users WHERE eql_v3.contained_by(encrypted_name, $1)` |
| `@@` | `eql_v3.matches(col, $1)` | `SELECT * FROM users WHERE eql_v3.matches(encrypted_name, $1)` |

`eql_v3.eq` / `neq` / `lt` / `lte` / `gt` / `gte` / `contains` /
`contained_by` are each overloaded for `(domain, domain)`, `(domain, jsonb)`,
`eql_v3.eq` / `neq` / `lt` / `lte` / `gt` / `gte` / `matches`
are each overloaded for `(domain, domain)`, `(domain, jsonb)`,
and `(jsonb, domain)`, so a `jsonb` operand is accepted directly and resolved
against the typed side.

Expand Down Expand Up @@ -162,16 +161,18 @@ There is **no SQL `LIKE` / `ILIKE` pattern matching on encrypted text in
`eql_v3`**. The `LIKE` / `ILIKE` operators (`~~` / `~~*`) are blocked on every
encrypted domain variant and raise an "operator not supported" exception.

Text search is now **bloom-filter token containment** via `@>` / `<@` on a
column typed `public.eql_v3_text_match` or `public.eql_v3_text_search`. This tests whether
the encrypted text contains the (encrypted) search terms — a probabilistic
ngram match, not a SQL pattern match:
Text search is now **bloom-filter token matching** via the `@@` operator
(`eql_v3.matches`) on a column typed `public.eql_v3_text_match` or
`public.eql_v3_text_search`. This tests whether the encrypted text matches the
(encrypted) search terms — a probabilistic ngram match, not a SQL pattern match
and not containment (the `@>` / `<@` containment operators raise on these
domains):

```sql
-- Column typed public.eql_v3_text_match or public.eql_v3_text_search,
-- with: CREATE INDEX ... USING gin (eql_v3.match_term(encrypted_name));
SELECT * FROM users WHERE encrypted_name @> $1;
SELECT * FROM users WHERE eql_v3.contains(encrypted_name, $1);
SELECT * FROM users WHERE encrypted_name @@ $1;
SELECT * FROM users WHERE eql_v3.matches(encrypted_name, $1);
```

Case sensitivity and tokenisation are properties of how the value was
Expand Down
2 changes: 1 addition & 1 deletion crates/eql-bindings/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "eql-bindings"
version = "3.0.0"
version = "3.0.1-alpha.0"
edition = "2021"
description = "Canonical wire types for EQL payloads — single source of truth for Rust, TypeScript (ts-rs), and JSON Schema (schemars)."
# crates.io metadata. `license` is REQUIRED by crates.io — publish fails without
Expand Down
5 changes: 3 additions & 2 deletions crates/eql-bindings/bindings/v3/BloomFilter.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

/**
* Bloom-filter match term — the `bf` wire key. Backs the `_match` domains
* (`@>`/`<@` containment).
* Bloom-filter match term — the `bf` wire key. Backs the fuzzy-match `@@`
* (`eql_v3.matches`) surface on the `_match` domains; the containment operators
* `@>`/`<@` survive only as internal blockers that raise (CIP-3517).
*
* **Signed** i16, not u16: EQL stores the filter as PostgreSQL `smallint[]`,
* and filters sized above 32768 emit upper-half bit positions as negative
Expand Down
11 changes: 11 additions & 0 deletions crates/eql-bindings/bindings/v3/Json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Ciphertext } from "./Ciphertext";
import type { Identifier } from "./Identifier";
import type { SchemaVersion } from "./SchemaVersion";

/**
* `public.eql_v3_json` — storage-only domain.
*
* Operators: none. Required keys: `v` `i` `c`.
*/
export type Json = { v: SchemaVersion, i: Identifier, c: Ciphertext, };
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/Selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

/**
* A SteVec selector — the `s` wire key. Addresses a JSON path leaf within an
* encrypted document (`public.eql_v3_json`); present on every entry and query element.
* encrypted document (`public.eql_v3_json_search`); present on every entry and query element.
*/
export type Selector = string;
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/SteVecDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { SteVecEntry } from "./SteVecEntry";
import type { SteVecForm } from "./SteVecForm";

/**
* `public.eql_v3_json` — a SteVec encrypted-JSONB document (`{v, k, i, sv:[entry]}`,
* `public.eql_v3_json_search` — a SteVec encrypted-JSON document (`{v, k, i, sv:[entry]}`,
* no root ciphertext). Strict. `k` is the `"sv"` form discriminator (see
* [`SteVecForm`]) — carried on the real wire, so the strict struct models it.
*/
Expand Down
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/SteVecEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { OpeCllw } from "./OpeCllw";
import type { Selector } from "./Selector";

/**
* `public.eql_v3_jsonb_entry` — one sv element (returned by `->`). Carries a selector
* `public.eql_v3_json_entry` — one sv element (returned by `->`). Carries a selector
* `s`, ciphertext `c`, optional array-membership marker `a`, and exactly one of
* `hm` XOR `op`. LAX (flatten precludes `deny_unknown_fields`): tolerates the
* root `i`/`v` merged in by `->`. XOR of the term is enforced by the SQL CHECK.
Expand Down
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/SteVecQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
import type { SteVecQueryEntry } from "./SteVecQueryEntry";

/**
* `eql_v3.query_jsonb` — a containment needle (`{sv:[query-entry]}`). Strict.
* `eql_v3.query_json` — a containment needle (`{sv:[query-entry]}`). Strict.
*/
export type SteVecQuery = { sv: Array<SteVecQueryEntry>, };
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/TextMatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ import type { SchemaVersion } from "./SchemaVersion";
/**
* `public.eql_v3_text_match` — match domain.
*
* Operators: `@>` `<@`. Required keys: `v` `i` `c` `bf`.
* Operators: `@@`. Required keys: `v` `i` `c` `bf`.
*/
export type TextMatch = { v: SchemaVersion, i: Identifier, c: Ciphertext, bf: BloomFilter, };
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/TextMatchQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ import type { SchemaVersion } from "./SchemaVersion";
/**
* `eql_v3.query_text_match` — match domain query operand.
*
* Operators: `@>` `<@`. Required keys: `v` `i` `bf`.
* Operators: `@@`. Required keys: `v` `i` `bf`.
*/
export type TextMatchQuery = { v: SchemaVersion, i: Identifier, bf: BloomFilter, };
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/TextSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ import type { SchemaVersion } from "./SchemaVersion";
/**
* `public.eql_v3_text_search` — search domain.
*
* Operators: `=` `<>` `<` `<=` `>` `>=` `@>` `<@`. Required keys: `v` `i` `c` `hm` `op` `bf`.
* Operators: `=` `<>` `<` `<=` `>` `>=` `@@`. Required keys: `v` `i` `c` `hm` `op` `bf`.
*/
export type TextSearch = { v: SchemaVersion, i: Identifier, c: Ciphertext, hm: Hmac256, op: OpeCllw, bf: BloomFilter, };
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/TextSearchOre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ import type { SchemaVersion } from "./SchemaVersion";
/**
* `public.eql_v3_text_search_ore` — search domain.
*
* Operators: `=` `<>` `<` `<=` `>` `>=` `@>` `<@`. Required keys: `v` `i` `c` `hm` `ob` `bf`.
* Operators: `=` `<>` `<` `<=` `>` `>=` `@@`. Required keys: `v` `i` `c` `hm` `ob` `bf`.
*/
export type TextSearchOre = { v: SchemaVersion, i: Identifier, c: Ciphertext, hm: Hmac256, ob: OreBlock256, bf: BloomFilter, };
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/TextSearchOreQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ import type { SchemaVersion } from "./SchemaVersion";
/**
* `eql_v3.query_text_search_ore` — search domain query operand.
*
* Operators: `=` `<>` `<` `<=` `>` `>=` `@>` `<@`. Required keys: `v` `i` `hm` `ob` `bf`.
* Operators: `=` `<>` `<` `<=` `>` `>=` `@@`. Required keys: `v` `i` `hm` `ob` `bf`.
*/
export type TextSearchOreQuery = { v: SchemaVersion, i: Identifier, hm: Hmac256, ob: OreBlock256, bf: BloomFilter, };
2 changes: 1 addition & 1 deletion crates/eql-bindings/bindings/v3/TextSearchQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ import type { SchemaVersion } from "./SchemaVersion";
/**
* `eql_v3.query_text_search` — search domain query operand.
*
* Operators: `=` `<>` `<` `<=` `>` `>=` `@>` `<@`. Required keys: `v` `i` `hm` `op` `bf`.
* Operators: `=` `<>` `<` `<=` `>` `>=` `@@`. Required keys: `v` `i` `hm` `op` `bf`.
*/
export type TextSearchQuery = { v: SchemaVersion, i: Identifier, hm: Hmac256, op: OpeCllw, bf: BloomFilter, };
82 changes: 6 additions & 76 deletions crates/eql-bindings/schema/v3/eql_v3_json.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
"description": "mp_base85 source ciphertext — the `c` envelope key.\n\nRequired by every v3 domain CHECK; present on every payload.",
"type": "string"
},
"Hmac256": {
"description": "HMAC-SHA-256 equality term — the `hm` wire key. Backs the `_eq` domains\n(`=`, `<>`). SQL-side constructor: `eql_v3_internal.hmac_256`.",
"type": "string"
},
"Identifier": {
"additionalProperties": false,
"description": "Table + column identifier — wire shape `{\"t\": \"...\", \"c\": \"...\"}`.\n\nShared by every payload.",
Expand All @@ -27,98 +23,32 @@
],
"type": "object"
},
"OpeCllw": {
"description": "CLLW-OPE order term — the `op` wire key. Backs the scalar `_ord` (the\ndefault ordering domain), `_ord_ope`, and `text_search` domains, their\n`query_` operands (`=` `<>` `<` `<=` `>` `>=`), and the ordered entries\nof a SteVec document (exactly one of `hm` (equality) XOR `op` (ordering)\nper entry — enforced by the SQL domain CHECK): a hex-encoded CLLW OPE\nciphertext, sortable via native bytea comparison after hex-decode —\nunlike `ob` (block-ORE) it needs no custom comparator. Extracted by\n`eql_v3.ord_term` (scalar domains and the `public.jsonb_entry` overload\nalike); SQL-side constructor: `eql_v3_internal.ope_cllw`.",
"type": "string"
},
"SchemaVersion": {
"const": 3,
"description": "The envelope version field (`v`) — always exactly `3` on the wire.",
"type": "integer"
},
"Selector": {
"description": "A SteVec selector — the `s` wire key. Addresses a JSON path leaf within an\nencrypted document (`public.eql_v3_json`); present on every entry and query element.",
"type": "string"
},
"SteVecEntry": {
"anyOf": [
{
"properties": {
"hm": {
"$ref": "#/$defs/Hmac256"
}
},
"required": [
"hm"
],
"type": "object"
},
{
"properties": {
"op": {
"$ref": "#/$defs/OpeCllw"
}
},
"required": [
"op"
],
"type": "object"
}
],
"description": "`public.eql_v3_jsonb_entry` — one sv element (returned by `->`). Carries a selector\n`s`, ciphertext `c`, optional array-membership marker `a`, and exactly one of\n`hm` XOR `op`. LAX (flatten precludes `deny_unknown_fields`): tolerates the\nroot `i`/`v` merged in by `->`. XOR of the term is enforced by the SQL CHECK.",
"properties": {
"a": {
"type": [
"boolean",
"null"
]
},
"c": {
"$ref": "#/$defs/Ciphertext"
},
"s": {
"$ref": "#/$defs/Selector"
}
},
"required": [
"s",
"c"
],
"type": "object"
},
"SteVecForm": {
"const": "sv",
"description": "The `k` envelope form discriminator — always `\"sv\"` for a SteVec document.",
"type": "string"
}
},
"$id": "https://schemas.cipherstash.com/eql/v3/eql_v3_json.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"description": "`public.eql_v3_json` — a SteVec encrypted-JSONB document (`{v, k, i, sv:[entry]}`,\nno root ciphertext). Strict. `k` is the `\"sv\"` form discriminator (see\n[`SteVecForm`]) — carried on the real wire, so the strict struct models it.",
"description": "`public.eql_v3_json` — storage-only domain.\n\nOperators: none. Required keys: `v` `i` `c`.",
"properties": {
"c": {
"$ref": "#/$defs/Ciphertext"
},
"i": {
"$ref": "#/$defs/Identifier"
},
"k": {
"$ref": "#/$defs/SteVecForm"
},
"sv": {
"items": {
"$ref": "#/$defs/SteVecEntry"
},
"type": "array"
},
"v": {
"$ref": "#/$defs/SchemaVersion"
}
},
"required": [
"v",
"k",
"i",
"sv"
"c"
],
"title": "SteVecDocument",
"title": "Json",
"type": "object"
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
"type": "string"
},
"Selector": {
"description": "A SteVec selector — the `s` wire key. Addresses a JSON path leaf within an\nencrypted document (`public.eql_v3_json`); present on every entry and query element.",
"description": "A SteVec selector — the `s` wire key. Addresses a JSON path leaf within an\nencrypted document (`public.eql_v3_json_search`); present on every entry and query element.",
"type": "string"
}
},
"$id": "https://schemas.cipherstash.com/eql/v3/eql_v3_jsonb_entry.json",
"$id": "https://schemas.cipherstash.com/eql/v3/eql_v3_json_entry.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"anyOf": [
{
Expand All @@ -43,7 +43,7 @@
"type": "object"
}
],
"description": "`public.eql_v3_jsonb_entry` — one sv element (returned by `->`). Carries a selector\n`s`, ciphertext `c`, optional array-membership marker `a`, and exactly one of\n`hm` XOR `op`. LAX (flatten precludes `deny_unknown_fields`): tolerates the\nroot `i`/`v` merged in by `->`. XOR of the term is enforced by the SQL CHECK.",
"description": "`public.eql_v3_json_entry` — one sv element (returned by `->`). Carries a selector\n`s`, ciphertext `c`, optional array-membership marker `a`, and exactly one of\n`hm` XOR `op`. LAX (flatten precludes `deny_unknown_fields`): tolerates the\nroot `i`/`v` merged in by `->`. XOR of the term is enforced by the SQL CHECK.",
"properties": {
"a": {
"type": [
Expand Down
Loading
Loading