Reported by a Lovable agent implementing CipherStash in a Lovable-hosted project:
I burned real time discovering that types.Double doesn't mint ORE blocks and I needed types.DoubleOrdOre, and that ordered domains in public vs eql_v3 differ in which operators are exposed. A single table — type → supported predicates → required column domain → required SDK type — would remove most of that.
Why it lands
packages/stack/src/eql/v3/types.ts:113-191 exports around 40 factories. Every scalar has four variants following the same pattern — Integer, IntegerEq, IntegerOrd, IntegerOrdOre — plus the type-specific ones (TextMatch, TextSearch, Boolean, Json). The capability is fixed by the type; there are no chainable tuners. So picking the wrong factory is silent at authoring time and only shows up as a predicate that will not run.
The names do not carry the mapping on their own. types.Double is storage-only. types.DoubleOrd orders via OPE and indexes on any role. types.DoubleOrdOre orders via ORE and needs an operator class only a superuser can create — so on Supabase it is usable but unindexable (#759), which makes DoubleOrd the right pick there and DoubleOrdOre the trap. The reporter picked the trap.
The public vs eql_v3 confusion is the same gap from the SQL side: the domains live in public (public.eql_v3_double_ord), the operator functions live in eql_v3 (eql_v3.ord_term), and their internals in eql_v3_internal. Nothing states that plainly in one place.
Proposal
One table, high in skills/stash-encryption/SKILL.md, cross-linked from skills/stash-indexing and skills/stash-postgres, with a column per question an implementer actually has:
| SDK factory |
Postgres domain |
Predicates |
Index |
Managed Postgres |
types.Double(...) |
public.eql_v3_double |
none (storage only) |
— |
✅ |
types.DoubleEq(...) |
public.eql_v3_double_eq |
=, !=, IN |
HMAC btree |
✅ |
types.DoubleOrd(...) |
public.eql_v3_double_ord |
=, !=, <, <=, >, >=, ORDER BY |
OPE btree |
✅ |
types.DoubleOrdOre(...) |
public.eql_v3_double_ord_ore |
as above |
ORE opclass — superuser only |
⚠️ usable, not indexable |
types.TextMatch(...) |
public.eql_v3_text_match |
free-text matches |
bloom |
✅ |
| … |
|
|
|
|
Plus a short note on schema layout: domains in public, operator functions in eql_v3, internals in eql_v3_internal — and that the last of those is why the Supabase grants cover both schemas.
Generating the table from types.ts rather than hand-writing it would keep it honest, and is worth considering given the surface is 40 entries wide and mechanical.
The docs site (cipherstash.com/docs, separate repo) needs the same table — flagging that here rather than opening a second issue.
Related
Reported by a Lovable agent implementing CipherStash in a Lovable-hosted project:
Why it lands
packages/stack/src/eql/v3/types.ts:113-191exports around 40 factories. Every scalar has four variants following the same pattern —Integer,IntegerEq,IntegerOrd,IntegerOrdOre— plus the type-specific ones (TextMatch,TextSearch,Boolean,Json). The capability is fixed by the type; there are no chainable tuners. So picking the wrong factory is silent at authoring time and only shows up as a predicate that will not run.The names do not carry the mapping on their own.
types.Doubleis storage-only.types.DoubleOrdorders via OPE and indexes on any role.types.DoubleOrdOreorders via ORE and needs an operator class only a superuser can create — so on Supabase it is usable but unindexable (#759), which makesDoubleOrdthe right pick there andDoubleOrdOrethe trap. The reporter picked the trap.The
publicvseql_v3confusion is the same gap from the SQL side: the domains live inpublic(public.eql_v3_double_ord), the operator functions live ineql_v3(eql_v3.ord_term), and their internals ineql_v3_internal. Nothing states that plainly in one place.Proposal
One table, high in
skills/stash-encryption/SKILL.md, cross-linked fromskills/stash-indexingandskills/stash-postgres, with a column per question an implementer actually has:types.Double(...)public.eql_v3_doubletypes.DoubleEq(...)public.eql_v3_double_eq=,!=,INtypes.DoubleOrd(...)public.eql_v3_double_ord=,!=,<,<=,>,>=,ORDER BYtypes.DoubleOrdOre(...)public.eql_v3_double_ord_oretypes.TextMatch(...)public.eql_v3_text_matchmatchesPlus a short note on schema layout: domains in
public, operator functions ineql_v3, internals ineql_v3_internal— and that the last of those is why the Supabase grants cover both schemas.Generating the table from
types.tsrather than hand-writing it would keep it honest, and is worth considering given the surface is 40 entries wide and mechanical.The docs site (cipherstash.com/docs, separate repo) needs the same table — flagging that here rather than opening a second issue.
Related
stash-encryption: the_ord_oredomains are not disabled on managed Postgres — only the opclass is skipped #759 — theOrdvsOrdOrecallout the table depends on being correct.encryptQueryterm +::eql_v3.query_<domain>cast), the no-ORM half of the same mapping.CREATE INDEXguidance for encrypted columns; the "Index" column above is the same knowledge in summary form.