Skip to content

Docs V2: EQL v3 reference section, Tailwind-shaped (CIP-3326)#38

Merged
coderdan merged 7 commits into
v2from
cip-3326-eql-v3-reference
Jul 2, 2026
Merged

Docs V2: EQL v3 reference section, Tailwind-shaped (CIP-3326)#38
coderdan merged 7 commits into
v2from
cip-3326-eql-v3-reference

Conversation

@coderdan

@coderdan coderdan commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Stacked on #37 (base: v2). Implements CIP-3326: the EQL reference rewritten against the eql_v3 branch, structured Tailwind-style — EQL is an abstraction over SQL as Tailwind is over CSS, and the docs follow the same arc: Install → Core concepts → type categories → Indexes → common queries, increasing in complexity.

Structure (11 pages, flat URLs, sidebar-grouped)

Page Covers
/docs/reference/eql Install: single SQL script, dbdev, Docker, permissions split, managed-PG
…/core-concepts The canonical mechanics page: variant model, payload anatomy (v/i/c + hm/ob/bf, absorbs CipherCell), typed-operand rule, fail-loud blockers, ORE-equality on _ord, term leakage
Types
…/numbers int2–int8, float4/8, numeric: variants, ob payload, operators + functions, range/min-max examples; owns no-SUM/AVG
…/dates-and-times date, timestamp: same traits, temporal semantics — time windows, newest-first, retention cutoffs
…/text All six text variants; owns the no-LIKE treatment (@> ngram-bloom containment); hm+ob+bf payload
…/json ste_vec model + sv payload shape (hm XOR oc), containment + GIN, field access, path queries, blocked jsonb ops
…/booleans "Every type has a storage-only variant — for bool it's the only one"; cardinality rationale
Indexes
…/indexes Functional indexes on extractors, engagement requirements, EXPLAIN, large-table builds
Queries
…/filtering =, IN, ranges/BETWEEN, token match, JSON containment, mixed encrypted+plaintext predicates
…/sorting ORDER BY: bare form vs extractor sort-key form, pagination, the ::jsonb projection trap
…/grouping-and-aggregates GROUP BY/DISTINCT on extractors, COUNT, min/max, no SUM/AVG
…/joins Equijoins; the same-keyset constraint headline + zero-rows diagnosis

Anti-drift rule (recorded in IA.md): shared mechanics live only in core-concepts; category and query pages link, never restate. Drift-management strategy for this section (test SQL blocks against the postgres-eql Docker image per verifiedAgainst; capability matrix as generated data) is on CIP-3337.

Accuracy notes (verified against shipped SQL, not just repo docs)

  • Equality on _ord variants compares ORE terms — _ord payloads carry ob only, no hm
  • Bare ORDER BY col is correct but adds a Sort node; ORDER BY eql_v3.ord_term(col) streams from the btree
  • sv entries carry hm XOR oc (post-consolidation), not the stale ocf/ocv split in sql-support.md

Release-gated claims (verify at EQL 3.0.0 release)

  • Payload v: 3 — documented as the EQL version per team decision (2026-07-02); the eql_v3 branch CHECKs still assert v = '2', so the upstream change must land before release
  • OPE SEM specifier — documented as arriving with the v3 release for all orderable types (incl. text); not yet in the branch
  • Docker pin example :17-3.0.0 (registry has 17-3.0.0-alpha.1; final tag pending)
  • eql_v3.version() output shown as '3.0.0'
  • Upstream nits: sql-support.md ocf/ocv table; CHANGELOG 3.0.0 under [Unreleased]

Smoke-tested: all 11 pages + .mdx mirrors 200; typecheck + redirect gate pass; legacy redirects retargeted (encryption/queries → filtering, cipher-cell → core-concepts).

https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P

Seven pages replacing the v2-era EQL reference, written against the
eql_v3 branch of cipherstash/encrypt-query-language (3.0.0):

- index: what EQL is, the v3 domain-variant model, install (single SQL
  script, idempotent), dbdev, Docker, migration/runtime permission
  split, managed-Postgres rationale
- types: 10 scalar families × variants matrix; bool storage-only;
  _ord/_ord_ore twins; index terms per variant
- operators: per-variant support matrix, typed-operand rule, no-LIKE,
  fail-loud blockers, query shapes, function-form equivalents
- indexes: functional indexes on term extractors, engagement
  requirements, sort-key form for index-streamed ORDER BY, EXPLAIN
  checklist, large-table build guidance
- json: ste_vec model, per-node-type terms (hm XOR oc), containment +
  GIN, field access, path queries, blocked native jsonb operators
- functions: comparisons, extractors, min/max only (no SUM/AVG),
  version()
- payload-format: v/i/c envelope (wire version still v:2), hm/ob/bf
  term keys, sv document shape, annotated examples (absorbs the legacy
  CipherCell page)

Cross-page consistency verified against the shipped SQL: equality on
_ord variants compares ORE terms (no hm in _ord payloads), and bare
ORDER BY is correct but extractor-form sort keys stream from the index.

Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
public-docs Ready Ready Preview, Comment Jul 2, 2026 12:12pm

Request Review

EQL is an abstraction over SQL the way Tailwind is over CSS — the docs
now follow the same shape: Install → Core concepts → type categories →
Indexes → query patterns, increasing in complexity. Each type-category
page is the complete reference for its types (variants, payload shape,
operators/functions, example queries on one page).

- index: trimmed to the Install page
- core-concepts (new): the canonical home for shared mechanics —
  variant model, payload anatomy (v/i/c envelope + hm/ob/bf terms,
  absorbs payload-format/CipherCell), typed-operand rule, fail-loud
  blockers, ORE-equality on _ord, term-leakage pointer
- numbers-and-dates, text, booleans (new) + json (reworked): category
  pages; text owns the no-LIKE treatment; json absorbs the sv payload
  shape; booleans framed as "every type has a storage-only variant —
  for bool it's the only one"
- filtering, sorting, grouping-and-aggregates, joins (new): cross-type
  query patterns; joins headlines the same-keyset constraint
- deleted: types.mdx, operators.mdx, functions.mdx, payload-format.mdx
  (content redistributed; URLs never shipped publicly, no redirect debt)
- Anti-drift rule recorded in IA.md: mechanics live ONLY in
  core-concepts; category/query pages link, never restate
- meta.json: flat URLs with ---Types---/---Indexes---/---Queries---
  sidebar separators; legacy redirect map retargeted (queries →
  filtering, cipher-cell → core-concepts)

Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
@coderdan coderdan changed the title Docs V2: EQL v3 reference section (CIP-3326) Docs V2: EQL v3 reference section, Tailwind-shaped (CIP-3326) Jul 2, 2026
…load v:3

Review feedback on the EQL section:

- Variant tables: generic form first, then full enumeration of every
  concrete domain name (Tailwind-style); capability column made
  concise; "index term carried" column dropped — term internals live
  in core-concepts' payload anatomy
- SEM specifiers documented as a concept in core-concepts: a trailing
  mechanism suffix (_ord_ore) pins WHICH searchable-encryption
  mechanism implements a capability; _ord tracks the default
  (currently ORE). Replaces the "twins" framing. Each orderable type
  page lists its specifiers under an "SEM specifiers" heading, noting
  the OPE specifier arriving for all orderable types (incl. text) in
  the v3 release
- Payload `v` field documented as the EQL version (3) per team
  decision 2026-07-02; all payload examples updated from v:2

Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
…perators and Functions

Review feedback:
- Dates & times split out of Numbers — same traits, distinct semantics;
  each page's examples now match its domain (payroll vs audit-event
  time windows / retention cutoffs / newest-first)
- CREATE TABLE examples get an explicit "Example" sub-heading + lead-in
- Operators and Functions are separate sections on every type page —
  operators as the per-variant support matrix, functions as the
  form-equivalents table (+ MIN/MAX, which only exist as functions)
- IA.md: split reflected; query-performance follow-up added (CIP-3351 —
  the v3 branch already folded the v2 perf guide into
  database-indexes.md, which our indexes page absorbed)

Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Docs V2 EQL v3 reference section under /reference/eql, restructuring the content into a “Tailwind-shaped” learning arc (install → core concepts → type categories → indexes → query patterns) and retargeting relevant legacy redirects to the new canonical pages.

Changes:

  • Replaces the EQL reference stub with a full set of new v3 reference pages (core concepts, types, indexes, and query patterns).
  • Defines EQL sidebar ordering/grouping via content/docs/reference/eql/meta.json.
  • Updates legacy→v2 redirect destinations to point at the new EQL pages, and updates IA tracking/checklists accordingly.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
v2-redirects.mjs Retargets legacy EQL-related redirects to new v2 EQL pages.
IA.md Updates the IA checklist to reflect the new EQL v3 page set and anti-drift rule.
content/docs/reference/eql/index.mdx Replaces the EQL section stub with an install/overview landing page.
content/docs/reference/eql/core-concepts.mdx Introduces the canonical mechanics page (variants, payload envelope, typed operands, fail-loud blockers).
content/docs/reference/eql/numbers.mdx Adds the numeric types reference (variants, payload, operators, functions, examples).
content/docs/reference/eql/dates-and-times.mdx Adds the date/timestamp reference with temporal query examples.
content/docs/reference/eql/text.mdx Adds the text types reference including no-LIKE guidance and token containment.
content/docs/reference/eql/json.mdx Adds encrypted JSON (ste_vec) reference including containment/path-query mechanics.
content/docs/reference/eql/booleans.mdx Documents booleans as storage-only by design.
content/docs/reference/eql/indexes.mdx Adds index recipes and engagement requirements for encrypted query patterns.
content/docs/reference/eql/filtering.mdx Adds WHERE-clause patterns across equality/range/text containment/JSON predicates.
content/docs/reference/eql/sorting.mdx Adds ORDER BY guidance including extractor-form sort keys and pagination patterns.
content/docs/reference/eql/grouping-and-aggregates.mdx Adds GROUP BY/DISTINCT/COUNT and min/max guidance, with no SUM/AVG rationale.
content/docs/reference/eql/joins.mdx Adds equijoin guidance including the same-keyset constraint and diagnosis steps.
content/docs/reference/eql/meta.json Defines page ordering and sidebar group separators for the EQL section.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


## What the terms reveal

Every index term a value carries is extra material stored in the database, and each term class reveals defined structure to an observer who can read the stored payloads: equality terms reveal *value repetition* (which rows share a value), ORE terms reveal *ordering* (which of two values is larger), and bloom terms reveal *probabilistic token overlap*. None of them reveal the plaintext — but you should only carry the terms you actually query on. The full analysis of what each term does and doesn't leak is in [Searchable encryption](/concepts/searchable-encryption).
| `float8` | `eql_v3.float8` · `eql_v3.float8_eq` · `eql_v3.float8_ord` · `eql_v3.float8_ord_ore` |
| `numeric` | `eql_v3.numeric` · `eql_v3.numeric_eq` · `eql_v3.numeric_ord` · `eql_v3.numeric_ord_ore` |

Declare only the capability you query on — each capability stores extra searchable material with defined leakage (see [Searchable encryption](/concepts/searchable-encryption)), and the variant model itself is covered in [Core concepts](/reference/eql/core-concepts).
| `date` | `eql_v3.date` · `eql_v3.date_eq` · `eql_v3.date_ord` · `eql_v3.date_ord_ore` |
| `timestamp` | `eql_v3.timestamp` · `eql_v3.timestamp_eq` · `eql_v3.timestamp_ord` · `eql_v3.timestamp_ord_ore` |

Time columns are nearly always ranged and sorted, so `_ord` is the usual choice. Declare only the capability you query on — each capability stores extra searchable material with defined leakage (see [Searchable encryption](/concepts/searchable-encryption)), and the variant model itself is covered in [Core concepts](/reference/eql/core-concepts).
| `eql_v3.text_match` | Free-text token containment: `@>` / `<@`. |
| `eql_v3.text_search` | Equality + ordering + token containment. |

Declare only the capabilities you query on — each capability stores extra searchable material with defined leakage (see [Searchable encryption](/concepts/searchable-encryption)).

## Why there are no query variants

A two-value column has too little cardinality for any searchable index to be safe. An equality term over `true` / `false` would partition the table into two visible buckets — leaking the value distribution (and, with any outside knowledge, the values themselves) outright. Rather than ship an index term that can't keep its promise, EQL omits the query variants entirely. See [Searchable encryption](/concepts/searchable-encryption) for the general analysis of what index terms reveal.
Comment thread content/docs/reference/eql/indexes.mdx Outdated
Comment thread content/docs/reference/eql/indexes.mdx Outdated
Comment thread content/docs/reference/eql/numbers.mdx Outdated
| `ORDER BY` | ❌ | ❌ | ✅ |
| `IS NULL` / `IS NOT NULL` | ✅ | ✅ | ✅ |

Blocked cells raise an `operator … is not supported` exception — they never silently return wrong rows. Operands must be typed (`$1::eql_v3.int8_ord`), or PostgreSQL resolves the native `jsonb` operator instead of the encrypted one. Both rules are covered in [Core concepts](/reference/eql/core-concepts).
| `ORDER BY` | ❌ | ❌ | ✅ |
| `IS NULL` / `IS NOT NULL` | ✅ | ✅ | ✅ |

Blocked cells raise an `operator … is not supported` exception — they never silently return wrong rows. Operands must be typed (`$1::eql_v3.timestamp_ord`), or PostgreSQL resolves the native `jsonb` operator instead of the encrypted one. Both rules are covered in [Core concepts](/reference/eql/core-concepts).
Comment thread content/docs/reference/eql/text.mdx Outdated
| `ORDER BY` | ❌ | ❌ | ✅ | ❌ | ✅ |
| `IS NULL` / `IS NOT NULL` | ✅ | ✅ | ✅ | ✅ | ✅ |

Blocked cells raise an `operator … is not supported` exception — they never silently return wrong rows. Operands must be typed (`$1::eql_v3.text_eq`), or PostgreSQL resolves the native `jsonb` operator instead of the encrypted one. Both rules are covered in [Core concepts](/reference/eql/core-concepts).
coderdan added 2 commits July 2, 2026 22:07
- indexes.mdx: cast query-shape example params to their EQL domain
  types, consistent with the typed-operand rule
- numbers/dates-and-times/text: the fail-loud note now scopes to
  operators — ORDER BY on a variant without an ordering term doesn't
  raise, it silently returns a meaningless order (links Sorting)
@coderdan

coderdan commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Copilot's comments addressed:

  • Dead links (/concepts/searchable-encryption ×6, /guides/troubleshooting/query-performance): rather than retargeting the canonical URLs, placeholder pages now exist on v2 (d0ccd7e, merged into this branch) — each links to the legacy page / interim references and its rewrite ticket (CIP-3333, CIP-3351).
  • Untyped $1 in indexes.mdx query shapes (×3): now cast to their EQL domain types, consistent with the typed-operand rule (896eae5).
  • ORDER BY in the fail-loud note (numbers, dates-and-times, text): the note now scopes raising to blocked operators, and calls out that ORDER BY on a variant without an ordering term runs silently with a meaningless order, linking to Sorting (896eae5).

@coderdan coderdan merged commit 19a132b into v2 Jul 2, 2026
2 checks passed
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