Docs V2: Supabase integration section + canonical encryptedSupabaseV3 reference#39
Docs V2: Supabase integration section + canonical encryptedSupabaseV3 reference#39coderdan wants to merge 15 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…reference (CIP-3328)
- /reference/stack/supabase: THE canonical encryptedSupabase page —
one signature ({encryptionClient, supabaseClient}, .from(table,
schema)), full query-builder surface, schema-capability → EQL-term
mapping, response/error shapes, deferred-execution model
- /integrations/supabase: flagship tutorial rewritten on EQL v3
(install script → eql_v3 typed columns → wrapper → queries incl.
ORDER BY on _ord; free-text as token containment, no LIKE)
- /integrations/supabase/{database,auth,dashboard-experience}:
migrations-vs-SQL-Editor install, grants, indexes, RLS composition;
Supabase Auth JWT → LockContext; Table Editor expectations + OAuth
integration flow
- placeholder pages for 6 forward-linked IA URLs (identity-aware-
encryption, schema-design, encrypt-existing-data, drizzle,
audit-logging, cts) so no internal link 404s
- IA.md: tick CIP-3328 items; add CIP-3355 SDK-alignment gate
(wrapper wire behaviour is still EQL v2 — blocks final merge)
9683c86 to
fd918a6
Compare
Reorganize /integrations/supabase from 4 pages into: Overview (front
door from the marketplace listing), Quickstart (the tutorial, OAuth
folded in as optional), Fundamentals (database.mdx + dashboard-
experience.mdx merged), Data layer (ORM/framework router), Auth
(rebuilt on OIDC federation), and Edge Functions (new).
- Auth: replace the deprecated LockContext.identify() flow with
OidcFederationStrategy as config.authStrategy, then
.withLockContext({ identityClaim }) — lock context now correctly
documented as requiring federation.
- Data layer: document the PostgREST vs direct-Postgres fork and
Supabase pooler/connection glue; link out to canonical ORM pages
rather than duplicating them.
- Edge Functions: written on the @cipherstash/stack/wasm-inline
surface; wrapper-on-edge question gated behind a callout.
- Add Prisma + Next.js integration placeholders so Data-layer links
resolve; fix stale /supabase/database link in the stack reference.
- Reorder meta.json; remove merged pages.
Addresses Vercel preview comment: the section folder and the index page were both labelled 'Supabase', so the sidebar read 'Supabase › Supabase'. Title the index page 'Overview' to remove the repeat.
Replace the "How it fits together" section on the Supabase overview with launch-article "How it works" copy. Fix EQL domain names against eql_v3 (int_ord -> integer_ord) and reframe text_search match as containment matching (like LIKE '%term%'), with a caveat callout. Add Table Editor screenshot.
- Remove em-dashes across the overview (AI "tell") - Backtick `base` in "EQL base types" - Convert the text_search note to a concise <Callout> - Collapse the RLS/stack/KMS/performance/security sections into one linked "Built for the Supabase stack" summary
Add a shared, product-wide FAQ component (src/components/faq) that renders an accordion and emits FAQPage JSON-LD. Generic answers (privacy, scaling, KMS, RLS-vs-encryption, free tier) live once in faq/shared and are composed with Supabase-specific questions inline on the overview. De-dupe the performance/privacy prose now covered by the FAQ.
Reuse the shared privacy/KMS/free-tier FAQ entries and add DynamoDB-specific questions (equality-only querying, keeping AWS SDK control, adoption). Omits the Postgres-oriented scaling/RLS entries, which do not apply.
# Conflicts: # src/mdx-components.tsx
…ains
The Supabase pages documented `encryptedSupabase`, the EQL v2 dialect.
Stack 1.0 ships `encryptedSupabaseV3` alongside it, and it is a different
shape. Verified against the adapter source on the release branch, not
against the PR descriptions, which have drifted.
- `await encryptedSupabaseV3(url, key, options?)` or `(client, options?)`.
It is async because it introspects the database at connect time, reads
the EQL domain of every column, and derives the encryption config from
it. There is no schema to declare and no `encryptedTable` to keep in
sync, so `.from()` takes only a table name.
- Introspection needs a direct Postgres connection: `DATABASE_URL`, or
`options.databaseUrl`. Documented in the quickstart env block.
- `schemas` is optional, and buys compile-time types plus startup
verification. Import from `@cipherstash/stack/eql/v3`.
- `select('*')` works, expanded from the introspected column list. On v2
it throws.
- `.like()` / `.ilike()` throw on encrypted columns. Free-text search is
`.contains()`. With the default match options the query term carries
the whole query string as a token, so a substring matches nothing;
called out where it will bite.
- Column types are the EQL 3.0.0 prefixed domains: `public.eql_v3_text_eq`,
not `eql_v3.text_eq`. The domains live in `public`; only the functions
and operators live in `eql_v3`.
- Supabase runs the installer as a non-superuser, so the ORE-backed
domains are disabled and raise on first write. Say so on the pages that
offer the choice, and point at `_ord` / `text_search`.
- The query builder's `.withLockContext()` takes a `LockContext`
instance, unlike the core client's, which takes a plain object. The
auth page passed the wrong one.
The v2 wrapper is unchanged and still documented, at the foot of the
reference page.
|
Pushed two commits: a Everything below was verified against the adapter source on
What changed
Two things worth a second opinion
Depends on
Checks
|
The operand is a storage payload, not a query term: PostgREST cannot cast a filter value to the narrow _query domain, and protect-ffi 0.28 rejects encryptQuery for the v3 scalars. So the needle's bloom carries the whole needle as an include_original token, which the haystack's bloom cannot contain unless the two are equal, or the needle is exactly one trigram long. Says it is a defect to be fixed in EQL rather than intended behaviour.
|
Correction to my note above on You're right about the storage side. What I missed is which payload the wrapper puts on the query side. It sends a full storage payload as the operand, not a narrow query term, and the source says why:
Confirmed at So the needle gets tokenized as if it were a stored value: It follows that The class doc reaches the same conclusion and calls it a defect:
The docs now describe it as a known defect with that precise rule, rather than as intended behaviour. I could not find the tracking issue in |
Drizzle and the Supabase wrapper share the defect but not the cause. The common blocker is that protect-ffi has no v3 scalar encryptQuery, so no client can build a narrow operand. Only Supabase is additionally blocked by PostgREST's inability to cast a filter value to the query domain; Drizzle emits its own SQL and can cast once a narrow term exists.
Not a protect-ffi gap: substring containment works at the ffi layer when include_original is off, which is the schema default. stack's shared match defaults force it on, inherited from the v2 builder, where QueryMode dropped the original token. Link the tracking issue.
Docs do not link GitHub issues. The callout had also accumulated two competing explanations across revisions; keep the one that is true.
…w link - Remove the `.contains()` substring callout from the reference page and the quickstart. Known defects belong in the issue tracker, not in the docs; the fix is imminent. - Remove the pre-publish redirect that sent /integrations/supabase to the legacy /stack/cipherstash/supabase page. It was placed on main so the future URL would resolve before v2 shipped, and its own comment says to remove it once v2 owns the URL. This branch is where v2 owns it, so the section's Overview nav item was landing on the old IA. - List Supabase first under Integrations.
The screenshot no longer reflects the product, and there is no replacement yet. It also illustrated adding EQL columns through the Table Editor, which Fundamentals already says is unreliable: the type picker does not surface custom domains. The copy now sends readers to SQL, which is the dependable path and what a migration needs anyway. Also drops the last two "Supabase Studio" mentions. It is the Supabase Dashboard.
Supabase integration section, plus the canonical
encryptedSupabaseV3reference. Targets thev2docs branch.Originally written against
encryptedSupabase(the EQL v2 dialect). Reworked ontoencryptedSupabaseV3and the EQL 3.0.0 domains, verified against the adapter source onfeat/eql-v3-text-search-schemaand against the EQL v3 domain SQL rather than the PR descriptions, which have drifted.Pages
/reference/stack/supabase— the canonical wrapper page.await encryptedSupabaseV3(url, key, options?)or(client, options?), connect-time introspection,.from(tableName), optionalschemasfor types and startup verification, the full builder surface, the domain-to-term table, response and error shapes, and the deferred-execution model. The v2 wrapper is documented at the foot./integrations/supabase— section overview./integrations/supabase/quickstart— empty project to encrypted, searchable table: install EQL, type the columns, wrap the client, query./integrations/supabase/fundamentals— migration vs SQL Editor install, role grants, functional indexes, RLS composition, pooler and introspection connections./integrations/supabase/auth— Supabase Auth session toOidcFederationStrategy, then.withLockContext()./integrations/supabase/orms— PostgREST path vs a direct Postgres connection./integrations/supabase/edge-functions— thewasm-inlinecore client on the Edge runtime.What the rework changed
encryptedTableto keep in sync, and.from()takes only a table name.DATABASE_URLoroptions.databaseUrl), a different credential from the anon key. Added to the quickstart env block.schemasis optional: compile-time types plus startup verification, imported from@cipherstash/stack/eql/v3. There is no@cipherstash/stack/schema/v3export.select('*')works on v3, expanded from the introspected column list. It throws on v2.public.eql_v3_text_eq, noteql_v3.text_eq. Domains live inpublic; functions and operators live ineql_v3..like()/.ilike()throw on encrypted columns. Free-text search is.contains()..withLockContext()takes aLockContextinstance; the core client's takes a plain{ identityClaim }object. The auth page was passing the core shape.Known defect, documented
.contains()cannot match substrings today:text_searchforcesinclude_original: true, so the needle's bloom carries the whole needle as an extra token that the haystack's bloom cannot contain. Tracked in cipherstash/stack#610. A warn callout describes the behaviour; remove it when the fix lands.Depends on
encryptedSupabaseV3rejects every EQL 3.0.0 table, becauseDOMAIN_REGISTRYis keyed on the old unprefixed names..in()on encrypted columns and.not(col, 'in', […]), both documented as working in the filter table.Notes for review
/reference/eql/*; these pages link rather than restate.edge-functions.mdxstill uses the v2 schema builders, because@cipherstash/stack/wasm-inlineexportsencryptedTable/encryptedColumnfrom@/schemaand does not export the v3types. Left alone; it already carries a "being confirmed" callout. Worth deciding whether the edge build should re-export the v3 surface.v2branch and are tracked separately; they must be stripped before anything reaches production.bun run buildpasses.validate-content,validate-links,validate-mermaidpass.