brand
無料Apply this site's visual identity — colours, type, logo files and fixed brand strings. Use for any page, component, social asset or document that should look like the site.
日本語の概要は準備中です。原文の説明を表示しています。
Use when a new feature needs a table, column or capability — evolving the schema so the new thing joins the permission, audit and RLS contract instead of sitting outside it. Covers the DDL/DML split, the resource/capability wiring, and the self-verifying migration.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
The schema here is not a set of tables. It is a contract: every resource has a key, every key has capabilities, every write is authorized and audited in the same atomic step, and every table is reachable only through a policy. A new table that does not join that contract is not "a table without permissions yet" — it is a hole, and it will be found by someone who is not you.
This skill exists because joining the contract is mechanical, easy to half-do, and invisible
when you get it wrong. A table with RLS enabled and no policy silently returns zero rows. A
table with a policy and no resource_key cannot be granted to anyone. Both look fine until
they do not.
node scripts/sql-classify.mjs # what tier does each migration sit in
ls supabase/migrations | tail -3 # the next number is the last + 1
Migrations are append-only and applied by hand, in order. Never edit an applied one — it already ran, so editing it changes nothing on any existing database and diverges you from every deployment that has it. If something is wrong, the fix is the next number.
Work through these in order. Each one is a question with a wrong answer that compiles.
1. Does it need to be a table at all? A setting is app_config. A secret is app_secrets
(encrypted). A flag is feature_flags. Reach for a new table when you have rows that belong to
someone and change over time.
2. What is its resource key? One short noun — blog, crm, payments. Add it to
RESOURCE_KEYS in src/types/schema.ts in the same change, or the admin capability grid has
a resource nobody can grant.
3. Which capabilities apply? view / create / edit / delete, plus publish when
there is a published state. view is a floor — migration 075 made an acting capability
require the view it depends on, so granting create without view now grants nothing. Seed
grants for every existing role, including the ones that should get nothing: an absent row and
an explicit allowed=false read differently to an operator looking at the grid.
4. RLS: enable it AND write policies. Enabling without a policy denies everything;
Postgres will not warn you. Write USING for reads and WITH CHECK for writes — a USING-only
policy lets a caller write a row they then cannot see.
5. Route writes through perform_action(). It authorizes and audits atomically, so no
write path can produce a permission decision without also producing an audit row. A direct
INSERT from application code bypasses both.
6. Split DDL from DML. The migration carries schema and any idempotent backfill it needs.
Rows that make the system work go to seed/01_required.sql; starting values an admin will edit
go to seed/02_defaults.sql. Company, product or content data goes in neither — it comes
from the admin UI or the site-bootstrap skill. Run node scripts/sql-classify.mjs afterwards
and confirm your migration lands in the tier you intended.
7. Verify inside the migration. End with a DO $verify$ block that asserts the thing you
just claimed, and RAISE EXCEPTION if it is not true. Migration 075 checks that its own
disclosure fix holds and that the private lookup is not reachable by authenticated. A
migration that cannot fail at apply time is a migration you will trust for the wrong reasons.
Every migration here opens by explaining the finding it closes, not what it does — the SQL
already says what it does. Read 007_publish_capability_enforcement.sql for the shape. If you
cannot articulate what was wrong before, the migration is not ready; you are guessing at a
design rather than closing a gap.
Include what you checked and chose not to change. 075 records that every seeded role holding
crm:create also holds crm:view, which is the fact that made a breaking change safe. Without
it the next person has to rediscover it before they dare touch the policy.
# never against production first
createdb scratch_test
for f in supabase/migrations/*.sql; do psql -v ON_ERROR_STOP=1 -d scratch_test -f "$f"; done
pnpm test:db # permissions, RLS, PII
pnpm gen:e2e # the permission-matrix invariants regenerate from the DB
pnpm test:db is not optional after a schema change. It is the only thing standing between a
policy typo and a table that quietly returns everything to everyone.
A schema change is not finished when it applies. It is finished when:
pnpm test:db is green and you added a case that fails without your changepublic_template_sync as
ship-when-UI-existsdocs/PUBLIC_TEMPLATE.md says whether this crosses to the public templatework-units/session-state.json records itThen use feature-testing to cover the surface you built on top.
view.perform_action().まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Apply this site's visual identity — colours, type, logo files and fixed brand strings. Use for any page, component, social asset or document that should look like the site.
日本語の概要は準備中です。原文の説明を表示しています。
Use FIRST when someone asks for a new feature or a change to an existing one — before any schema, code or test. Works out what is actually being asked for, whether to build it or integrate a third party (Trustpilot, Stripe, Calendly and the like), where the data lives, who may do what, and what happens when the vendor is down. Produces a decision, then hands to feature-schema.
日本語の概要は準備中です。原文の説明を表示しています。
Use after building a feature — explore it in a real browser to find what nobody predicted, then turn each finding into a deterministic test that guards it forever. Covers the agentic pass, what to generate vs hand-write, and how to skip honestly when a capability is missing.
日本語の概要は準備中です。原文の説明を表示しています。
Publishing content or deploying site-os — what caches exist, what refreshes them, and how to prove a change is actually live. Use when publishing a post or product, launching a page, deploying, or when someone says a change "isn't showing".
日本語の概要は準備中です。原文の説明を表示しています。
Handling secrets, keys and credentials for site-os — reading vigyan-secrets.md safely, moving keys into app_secrets, rotating, and responding to an exposure. Use whenever a task touches a key, token, password, .env file, app_secrets, encryption, or the secrets document.
日本語の概要は準備中です。原文の説明を表示しています。
Audit a page or the whole yoursite site (or a new site) for indexing readiness — cache headers, sitemap, robots, canonical, JSON-LD, internal links — and check the publish pipeline (Cloudflare purge/warm, IndexNow, GSC, Bing). Use before/after publishing content or launching a site.
日本語の概要は準備中です。原文の説明を表示しています。