Skip to content

skills: document the managed AI platform path (Lovable, v0, Bolt, Replit) - #909

Open
coderdan wants to merge 1 commit into
dan/skills-type-capability-matrixfrom
dan/skills-managed-platforms
Open

skills: document the managed AI platform path (Lovable, v0, Bolt, Replit)#909
coderdan wants to merge 1 commit into
dan/skills-type-capability-matrixfrom
dan/skills-managed-platforms

Conversation

@coderdan

Copy link
Copy Markdown
Contributor

Fixes #893. Stacked on #908 (→ #907#906) — this PR's diff is the last commit only.

The gap

A Lovable agent implemented CipherStash end-to-end and reported what it had to work out for itself. Most of it applies to every managed AI app platform — Lovable, v0, Bolt, Replit — because they share a shape: no shell the developer controls, an edge/Workers runtime, a database role that is not postgres, and schema changes only through the platform's own migration tool. Each of those changes the setup, and nothing in the skills covered the combination.

Its most expensive discovery, in its own words:

I spent a full turn concluding CipherStash was impossible here before learning stash existed.

It found @cipherstash/protect, inferred "native Rust addon, won't run on Workers" from the -ffi dependency name, and concluded the product was unusable. That is a wrong conclusion drawn from the wrong package — and a near-miss we should not rely on the next agent surviving.

New skill: stash-managed-platforms

That correction is the first thing on the page, before any setup content, because it decides whether anyone gets further: use @cipherstash/stack with the @cipherstash/stack/wasm-inline entry; @cipherstash/protect is the deprecated predecessor and its native module will not load there.

The rest, in the order an implementer needs it:

  • Headless auth works. stash auth login --json --region <slug> runs the device flow with the verification URL as the first NDJSON event, opens no browser, and writes to ~/.cipherstash — which exists fine in an ephemeral sandbox. The reporter did not know this and reached for a raw EQL .sql release asset on the assumption the CLI could not authenticate; once it confirmed --json worked, the CLI was the better path throughout. Written with the three things that actually bite: --region is required in a non-TTY, the command blocks while polling (~900 s — run it backgrounded, it is not hung), and you must authenticate before stash init.
  • Credentials. stash env --name <x> --write--name required non-interactively, mode 0600, existing file refused rather than overwritten, secrets shown once. The reporter called this part "flawless and worth codifying"; recording it matters because we had it flagged internally as a suspected blocker and it is not one.
  • The database role is not postgres. The install completes; only three optional owner-scoped statements are skipped. stash eql preflight --json before touching anything, and two of its answers change what you write next — ORE operator class: not creatable means types.*Ord not *OrdOre (eql: detect the ORE-unavailable case at install time, and name a remedy that exists #907), and a relocated pgcrypto aborts the bundle for any role.
  • Getting SQL applied through the platform's migration toolstash eql migration --supabase / --drizzle, which on a Supabase-backed platform is the only durable option since supabase db reset discards a direct install. The generated migration's pg_has_role guard is what makes it apply cleanly under whatever role the platform's runner uses.
  • What survives PostgREST, as a table, because agents guess wrong in both directions.
  • encryptedSupabase cannot be constructed in a Worker (Supabase v3: encryptedSupabaseV3 requires a Postgres connection, so it cannot run in Workers or the browser #708) — it introspects the database, so it needs a Postgres connection. Stated as a property of the wrapper, with the two supported shapes, so nobody debugs it as a config mistake.

Plus an "order of operations" list, since the constraint that actually hurts on these platforms is sequencing rather than any individual step.

Changes to existing skills

  • stash-edge gains the @cipherstash/protect correction directly under its runtime-entry table — that table is where an agent goes to decide "what do I import here", so it is where the wrong inference gets made. (Agent-verified: the deprecated-predecessor language existed only in stash-drizzle, about a different package.)
  • stash-supabase gains two above-the-fold callouts: a pointer to the new skill, and a one-line summary of what does and does not survive PostgREST. The existing treatment is correct but ~500 lines down, which is not where a time-pressured agent finds it — the issue's point 5.

Registration

A new skill directory ships automatically (tsup copies skills/ recursively) but is not installed anywhere until it is named in the maps. All four sites:

  • packages/cli/src/commands/init/lib/install-skills.tsSKILL_MAP.supabase and .postgresql
  • packages/wizard/src/lib/install-skills.ts — the mirrored map (supabase, generic)
  • packages/cli/src/commands/init/lib/setup-prompt.tsSKILL_PURPOSES, else it renders as "(no description)"
  • AGENTS.md — the skills/* inventory and the package→skill routing table

Those two integrations because the hosted AI builders are either Supabase-backed (Lovable) or reach a plain Postgres (v0, Bolt, Replit); Drizzle and Prisma Next projects are not built this way.

Worth knowing while reviewing: nothing enforces the converse — stash-dynamodb and stash-supply-chain-security sit in skills/ registered in no SKILL_MAP at all, and no test notices. I have not added a guard, because I would be encoding a guess about whether those two are deliberate. Flagging it rather than fixing it silently.

Verification

stash (1334), @cipherstash/wizard (366) and @cipherstash/stack (1050) suites green; Biome clean. Built the CLI and confirmed dist/skills/stash-managed-platforms/SKILL.md ships — and the existing SKILL_MAP test (every listed skill must resolve to a bundled SKILL.md) now covers the new entry on both integrations, so a rename that missed the maps fails.

https://claude.ai/code/session_01AwM5Cm5ddasXozb6stxPR1

Lovable, v0, Bolt and Replit share a shape -- no shell the developer
controls, an edge/Workers runtime, a database role that is not `postgres`,
and schema changes only through the platform's own migration tool -- and each
of those changes the setup. Nothing covered it.

The costly fact goes first, because it decides whether anyone gets further:
use `@cipherstash/stack` with the `wasm-inline` entry. `@cipherstash/protect`
is the deprecated predecessor, and reasoning from its `-ffi` dependency to
"CipherStash cannot run on an edge runtime" is a wrong conclusion drawn from
the wrong package -- it cost an agent a full turn on a real project before it
found `stash`. The same correction now sits in `stash-edge`'s entry table,
where an agent comparing runtimes will hit it.

The rest: headless `auth login --json` in an ephemeral sandbox (the CLI can
authenticate there, which the reporter did not know and worked around by
fetching a raw .sql release asset), minting `CS_*` with `stash env`,
installing EQL as a non-`postgres` role or generating a migration instead,
which predicates survive PostgREST, and why `encryptedSupabase` cannot be
constructed in a Worker.

Two things lifted above the fold in `stash-supabase`: a pointer to the new
skill, and a one-line PostgREST summary. The full treatment was correct but
~500 lines down, which is not where a time-pressured agent finds it.

Registered for `supabase` and `postgresql` in both the CLI and wizard skill
maps, in SKILL_PURPOSES, and in the AGENTS.md inventory and routing table.

Claude-Session: https://claude.ai/code/session_01AwM5Cm5ddasXozb6stxPR1
@coderdan
coderdan requested a review from a team as a code owner August 18, 2026 12:40
@changeset-bot

changeset-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4a4b7bd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
stash Patch
@cipherstash/basic-example Patch
@cipherstash/e2e Patch
@cipherstash/stack Patch
@cipherstash/stack-drizzle Patch
@cipherstash/stack-supabase Patch
@cipherstash/stack-prisma Patch
@cipherstash/wizard Patch
@cipherstash/bench Patch
@cipherstash/test-kit Patch
@cipherstash/prisma-example Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@freshtonic freshtonic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approve. The skill earns its place: the four-property platform shape is a real category the existing skills didn't cover as a combination, and leading with the @cipherstash/protect correction — the inference that cost an agent a full turn — is the right editorial call. CI green.

What I verified:

  • Every CLI fact the skill states resolves against the registry on this branch: stash impl --target lovable (the target list includes lovable), stash auth regions --json, stash eql verify, the authorization_required first-event and region_required non-TTY exit for auth login --json, and STASH_REGION as the flag fallback — all present and matching the tests that pin them. That matters more than usual here because this file ships into customer repos and describes behaviour, not code the reader can check.
  • All four registration sites are in the diff (CLI SKILL_MAP supabase + postgresql, wizard's mirrored map, SKILL_PURPOSES, and both AGENTS.md tables), and the existing SKILL_MAP resolution test now covers the new entry on both integrations, so a rename that misses a map fails CI.
  • The skill is a single self-sufficient SKILL.md with no sibling files — correct for the readBundledSkill inlining path, where split content is silently dropped.
  • Content is consistent with the stack it sits on: the "Optional SQL — requires postgres" framing and heal-on-rerun match #902's final shape, the ORE operator class: not creatable → types.*Ord guidance matches #907, the capability-matrix pointer matches #908, and the PostgREST table agrees with the stash-supabase above-the-fold summary added in the same PR. The pg_has_role guard claim about generated migrations is accurate.
  • Changeset present (stash patch); the AGENTS.md skills inventory and routing table are updated per the repo's keep-the-meta-files-honest rule.

On the flagged-not-fixed item — stash-dynamodb and stash-supply-chain-security sitting in no SKILL_MAP with no test noticing — I agree with flagging rather than guessing. For what it's worth, both look deliberate (stash-dynamodb's integration isn't an init path, and supply-chain is a repo-internal guide), so if a guard is added later it probably wants an explicit allowlist of unmapped skills rather than a blanket converse rule.

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