---
description: Require frontend changes and their DB/RPC/RLS/storage/secret dependencies to ship and be remotely verified together. Apply when implementing code that reads or writes backend state. Do not apply to plan-* or present-then-stop audits; production data mutation still requires confirmation.
alwaysApply: false
---

# Full-Stack Ship Discipline

A feature is **not done** when the UI compiles — it is done when the flow
works end-to-end against the **remote** backend the user actually hits. The
recurring failure this prevents: a migration file authored beside a feature
is never deployed, the live API 404s, and the bug masquerades as a UI issue.

1. **Inventory backend dependencies first.** Before editing components ask:
   does this read/write data, call an RPC, or depend on a table / column /
   function / policy / bucket / secret? Fix those in the same turn.
2. **Deploy schema, don't just author it.** Supabase: `apply_migration` /
   `execute_sql` on the confirmed `project_id`, then verify in the same turn
   — re-query `information_schema` / `pg_proc` / `pg_policies`, exercise the
   surface as `anon` / `authenticated`, check `get_logs` and `get_advisors`.
   Other stacks: run the real deploy command (`prisma migrate deploy`,
   `drizzle-kit push`, `rails db:migrate`, …) against the confirmed
   environment before the turn ends.
3. **Keep file and deploy in sync.** SQL applied via MCP also gets a matching
   versioned file in the repo's migrations folder. Do not `git push` unless
   the user asked in this turn.
4. **Edge functions, secrets, RLS, buckets, and cron jobs count as schema** —
   deploy and configure them with the UI change (`verify_jwt`, CORS, keys).
5. **Never re-ask before deploying schema the user asked to ship; always ask
   before mutating production data** (`DELETE` / `TRUNCATE` / `UPDATE` on
   real rows).
6. **Do not attach during a present-then-stop pass.** If the active skill is
   `plan-*` or a read-only `audit-*`, emit findings/plan only — do not
   `apply_migration` or deploy until the user approves a phase.

Done means: remote objects verified to exist, anon + authenticated paths
exercised, migration file on disk, and the frontend observed hitting a 200 —
not a stale 404.
