Skip to content

stash-supabase skill and README tell customers Workers are impossible — supported since #912 #950

Description

@tobyhede

Background

CipherStash Stack encrypts individual database columns. @cipherstash/stack-supabase is the Supabase integration: you wrap a Supabase client, and the wrapper encrypts values on the way in and decrypts them on the way out.

The package has two entry points:

Entry point How it learns your columns Where it runs
@cipherstash/stack-supabase Introspection — it opens a direct Postgres connection and reads the column types Node.js only
@cipherstash/stack-supabase/wasm-inline You declare the tables yourself, in a schemas argument Edge runtimes: Deno, Supabase Edge Functions, Cloudflare Workers

The second entry point exists because a Worker cannot open a raw Postgres socket, and cannot load a native module either. Declaring your tables is what removes the need to introspect; a WASM build of the encryption engine is what removes the native module.

We also ship Agent Skills. These are Markdown guides that travel inside the stash npm package. stash init copies them into the customer's own repository, under .claude/skills/ or .codex/skills/. The customer's coding agent then reads them as instructions. A wrong sentence in a skill becomes wrong guidance inside someone else's codebase.

Problem

The documentation still says the Worker entry point does not exist.

Before #912, there was one entry point, it always introspected, and it genuinely could not run in a Worker. The documentation said so, correctly.

#912 merged on 2026-08-19 and added the second entry point. The documentation was not updated. Three files still tell the reader that a Worker is impossible:

  1. skills/stash-supabase/SKILL.md:269 — "so the factory cannot run in a Worker or the browser."
  2. packages/stack-supabase/README.md:91 — "the factory cannot run in an edge Worker or the browser — construct it in your server-side code."
  3. docs/reference/supabase-sdk.md:33-34 — the same sentence. Line 7 of that file also says "One entry point, EQL v3 only". There are two.

The skill contradicts itself. Line 29 of the same file says the opposite, and is correct:

encryptedSupabase can be constructed inside a Worker, but only from the @cipherstash/stack-supabase/wasm-inline entry and only with declared schemas.

Line 29 is the only mention of the wasm-inline entry in the entire skill. The setup section, which contains line 269, imports the package root and never points anywhere else. A reader who follows the setup steps never learns the second entry exists.

The README is worse: it contains zero occurrences of the word "wasm" in 134 lines. It documents one entry point for a package that ships two.

Who this hurts, and how

The skill ships to customers twice — inside the stash package and inside @cipherstash/wizard — and is then copied into the customer's repository. Their agent reads it as instruction, not as prose.

The population most affected is the one we least want to lose. Managed AI platforms — Lovable, v0, Bolt, Replit — run server code on an edge runtime. That is exactly the case the wasm-inline entry was built for, and exactly the case the skill tells an agent is impossible. We have a separate skill, stash-managed-platforms, whose whole job is to unblock those platforms.

The failure is quiet and total. An agent that reads "cannot run in a Worker" does not file a bug. It concludes the product does not support the platform and stops. Nobody hears about it.

The wrong sentence is already built

The stale line is compiled into the build output on disk:

  • packages/cli/dist/skills/stash-supabase/SKILL.md:269
  • packages/wizard/dist/skills/stash-supabase/SKILL.md:269

An npm pack from an un-rebuilt tree ships it.

Why nothing catches this

Nothing checks that the documentation agrees with the export map. Skills are Markdown — no type checker reads them, no test asserts their claims, and CI has no step that compares a runtime claim against package.json. The only signal is a human noticing that two paragraphs in one file disagree.

Proposal

  1. Fix skills/stash-supabase/SKILL.md. Scope the sentence at line 269 to the package root entry. Say that introspection and the native module are what need Node, and that the wasm-inline entry has neither. Add the edge entry to the setup section, not only to the callout at line 29.
  2. Fix packages/stack-supabase/README.md. Same correction, plus a section documenting the wasm-inline entry, because the README does not mention it at all today. This file renders on the npm package page.
  3. Fix docs/reference/supabase-sdk.md, line 7 ("One entry point") and lines 33-34.
  4. Rebuild so packages/cli/dist/skills/ and packages/wizard/dist/skills/ no longer carry the stale text.
  5. Add changesets: a stash patch, because skills ship inside that package, and a @cipherstash/stack-supabase patch for the README.
  6. Optional, and cheap: add a test that fails when a shipping document claims a runtime the export map does not offer. This class of drift has now happened once and nothing would catch the second time.

Keep the browser half of every sentence. Only the Worker half is wrong. The browser claim is correct and is tracked by #804 — a workspace client key is required on every authentication path, so a browser build is not constructible today.

Do not edit the CHANGELOG files. packages/stack/CHANGELOG.md and packages/stack-supabase/CHANGELOG.md contain the same sentence, as does docs/superpowers/specs/2026-07-09-supabase-v3-introspection-design.md. They are historical records and were accurate when written. A search-and-replace must not sweep them up.

Verification

All line numbers checked against 0854bda0, the current tip of main.

$ git show origin/main:packages/stack-supabase/README.md | grep -c -i wasm
0

$ git grep -n "cannot run in a Worker" origin/main -- skills/
origin/main:skills/stash-supabase/SKILL.md:269:`DATABASE_URL`), so the factory cannot run in a Worker or the browser.

$ grep -n "cannot run in a Worker" packages/cli/dist/skills/stash-supabase/SKILL.md
269:`DATABASE_URL`), so the factory cannot run in a Worker or the browser.

$ grep -n "cannot run in a Worker" packages/wizard/dist/skills/stash-supabase/SKILL.md
269:`DATABASE_URL`), so the factory cannot run in a Worker or the browser.

The wasm-inline entry's own source comment already states the correct position, and that comment ships compiled into packages/stack-supabase/dist/wasm-inline.d.ts:

packages/stack-supabase/src/wasm-inline.ts:59-68 — "This entry cannot introspect at all, so schemas is required rather than optional. … This entry is ESM-only … and is server-side: it is not browser-safe (#804)."

So the source and the documentation disagree, and the source is right.

Relationship to other work

Metadata

Metadata

Assignees

No one assigned

    Labels

    SDKdocumentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions