authoring-e2ee-featurelisted
Install: claude install-skill BhodiSea/next-expo-supabase-agent-harness
# Authoring an E2EE feature
Encryption sits ON TOP of the authorization boundary, never in place of it: RLS keyed on
`auth.uid()` still decides which rows a caller may read, and `@app/crypto` decides whether
the bytes mean anything once read. Everything in the `authoring-vertical-slice` recipe still
applies — migration, RLS, `./client` read, procedure, both screens, tests, provenance, green
gate. This recipe is what that slice gains when a column must be unreadable to the server,
and what it LOSES in exchange.
Build in this strict order. Steps 1, 5, 6 and 7 are irreversible-ish in different ways: a
column encrypted for a month cannot be retroactively indexed, and a user who loses the device
AND the recovery code cannot be given their data back.
## Step 0 — preconditions, all three
Do not start until all of these are true:
1. **The module is enabled** — `packages/platform/crypto/` exists (`@app/crypto`). If it does
not, the module is opt-in and enabling it is a separate, reviewed act: read
`docs/modules/e2ee/README.md` first, in particular "What this deliberately does NOT solve".
2. **Host adapters are wired.** `createWebCryptoProvider()` (and, if the feature shares,
`createWebCryptoX25519Provider()`) cover web and Node and return `null` where there is no
Web Crypto. The MOBILE `CryptoProvider` / `X25519Provider` and BOTH surfaces'
`KeystoreAdapter` are consumer code — `docs/modules/e2ee/mobile-provider.patch.md` is the
recipe. Hermes ships no Web Crypto