跳到正文
cccskills
免费在 GitHub 公开

db-move-table-schema

Relocating a live, still-used table to another Postgres schema with every reference intact. Use when asked to move or rehome a table into a schema, or to pull a table out of public into a domain schema. NOT for retiring a table (use db-deprecate-table).

中文简介正在准备中。当前显示原文说明。

集成工具SupabasePostgreSQL
查看安装方法

包含的文件(1)

  • SKILL.md9.9 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Move a table to a new schema

<!-- rules:stamp -->

Rules from common-docs/policies/database-changeover-doctrine.md — edit there, never here (python3 common-docs/meta/scripts/one_home.py --write).

  1. Fix what is actually broken right now.
  2. While doing that, move the changeover forward a little — a few tables at a time, each one complete in every repo.
  3. Database counts mean nothing. There are zero users; all data is test data or his own, and a count only shows how much was tested. Never lead with a number, rank by volume, argue a name or design from row counts, or put counts in a brief as evidence; design for the live-week scale (100x today).
  4. There is no real data and there are no real users. Functionality first: primitive or store capability, then rendering, then editing, then a guard on the code path. Never spend a lane protecting, reconciling or carefully copying existing rows; the data copy is a plain mover step that can run again. Never open with a data census or a preservation gate. Data destruction still stops for confirmation; data fidelity does not.
  5. Never report on graveyard tables, and do not triage public until the canonical tables are right: graveyard is dead and known (deleting it may become an explicit task; until then it never appears in findings, summaries or "worth flagging" lists), public is a queue (canonical-first triage). When he repeats this hint to an agent, the fix is a missing pointer somewhere that agent read: find it and add it.
  6. Focus on what is right, not what is wrong. Learn how the canonical system works when correct (base entity, organization_id, access, associations), so that when a table is named the correct answer is already known. Mention a legacy item only when Arman names it or a task requires it; big dug-up findings are not the small critical fixes he has in mind.
<!-- rules:stamp-end -->

Moving an uncertified public table into its feature schema is the useful response to a database finding on it — not patching the finding in place: canonical-first triage.

Relocate public.<table> → <new>.<table> with references intact. Postgres moves most things for you; the misses are predictable. Read ../db-change/TOOLKIT.md + ../db-change/SKILL.md first. Project: brsgrqvjdzwihsvnfqkf. Retiring a dead table → db-deprecate-table; bringing a table onto the platform standard → db-canonicalize-table.

What ALTER TABLE … SET SCHEMA carries automatically

The table's columns, PK, indexes, CHECK/UNIQUE/FK constraints (its own and inbound FK constraints — cross-schema FKs keep working), RLS policies, triggers, and owned sequences all follow. You do not re-create these.

What does NOT follow: schema-level USAGE and the schema's default privileges — these belong to the schema, not the table. The moved table's grants come along but are dead without schema USAGE: every authenticated/anon access throws permission denied for schema <new>, which wrapper RPCs swallow into a silent null (the cx_canvas_upsert returned null class). Step 2 grants it; Step 3 verifies it.

What you MUST update by hand

  1. Registry rows — platform.entity_types.schema_name and platform.shareable_resource_registry.schema_name for this token.
  2. Hardcoded public.<table> references in functions/RPCs and views (unqualified refs follow search_path; schema-qualified ones break). Find them, CREATE OR REPLACE repointed.
  3. FE access = TWO separate doors. (a) PostgREST exposure + FE types — the target schema must be exposed to PostgREST and added to the pnpm db-types --schema list (TOOLKIT.md §0 trap), else the FE loses types and 404s. (b) Schema USAGE grant (Step 2) — SET SCHEMA does not grant it. A schema can be exposed yet USAGE-denied, which surfaces as a silent null, not a 404. Both are required. supabase-js calls change from .from('<table>') to .schema('<new>').from('<table>').
  4. aidream ORM — the target schema must be in db/matrx_orm.yaml additional_schemas with a generate block; the model regenerates into that schema's models_<schema>.py. If a sub-package consumes the table, update aidream/package_integration.py.

Step 1 — Pre-flight discovery

-- functions & views referencing the qualified name
select n.nspname, p.proname from pg_proc p join pg_namespace n on n.oid=p.pronamespace
where pg_get_functiondef(p.oid) ilike '%public.<table>%' or pg_get_functiondef(p.oid) ilike '%<table>%';
select schemaname, viewname from pg_views where definition ilike '%<table>%';
-- inbound FKs (will keep working, but note them)
select conrelid::regclass as referencing, conname from pg_constraint where confrelid='public.<table>'::regclass and contype='f';
-- current policies/triggers (confirm they follow after the move)
select polname from pg_policy where polrelid='public.<table>'::regclass;
select tgname from pg_trigger where tgrelid='public.<table>'::regclass and not tgisinternal;

Grep both repos for <table> usages (FE .from, Python models/managers, package wiring).

Step 2 — Ensure the target schema is ready (the EXPOSURE BLOCKER)

create schema if not exists <new>; then — always, even if the schema already existed (this is the step that gets skipped when the schema is pre-existing, and it's what broke canvas/code/legal/scraper) — GRANT USAGE ON SCHEMA <new> TO authenticated, anon, service_role; plus ALTER DEFAULT PRIVILEGES IN SCHEMA <new> GRANT … TO … for future tables · add it to the db-types --schema list · add to aidream matrx_orm.yaml.

⛔ You CANNOT expose a new schema via the MCP. Supabase's PostgREST exposed-schema list is platform config, not a role GUC (verified: nothing on authenticator.rolconfig), so no SQL you can run reaches it — not pnpm db:apply, not a read through the database tool. It must be added via the dashboard (Settings → API → Exposed schemas) or the management API (PATCH /v1/projects/{ref}/postgrest, preserving the existing list). A FE-read table moved into an unexposed schema 404s for every user the instant it moves. So: get the schema exposed FIRST (ask the user / use the mgmt API), confirm, then move. Don't blind-ALTER ROLE authenticator SET pgrst.db_schemas — you don't know the full current list and will silently un-expose other schemas.

Step 3 — Move + verify it followed

alter table public.<table> set schema <new>;
select count(*) from <new>.<table>;                                    -- unchanged
select polname from pg_policy where polrelid='<new>.<table>'::regclass; -- policies followed
select tgname  from pg_trigger where tgrelid='<new>.<table>'::regclass and not tgisinternal; -- triggers followed
select has_schema_privilege('authenticated','<new>','USAGE'),
       has_schema_privilege('anon','<new>','USAGE');                   -- MUST be true (Step 2); SET SCHEMA does NOT grant it

Repo-wide audit for this whole class — any schema with table grants but no USAGE (run after every move):

select n.nspname,
  count(*) filter (where has_table_privilege('authenticated', format('%I.%I',n.nspname,c.relname),'SELECT')) as granted_tables,
  has_schema_privilege('authenticated',n.nspname,'USAGE') as usage
from pg_namespace n join pg_class c on c.relnamespace=n.oid and c.relkind in ('r','p','v','m')
where n.nspname not like 'pg_%' and n.nspname<>'information_schema'
group by n.nspname
having not has_schema_privilege('authenticated',n.nspname,'USAGE')
   and count(*) filter (where has_table_privilege('authenticated', format('%I.%I',n.nspname,c.relname),'SELECT'))>0;
-- expected leftovers: cron, deprecated (internal/retired — correctly NO usage). Anything else FE-facing = bug.

Step 4 — Repoint the misses

Update the registry schema_name rows; CREATE OR REPLACE any function/view that named public.<table>; re-verify those RPCs run.

Step 5 — Cross-repo finalize

db-change SOP: pnpm db-types (schema added) → swap .from('<table>') → .schema('<new>').from('<table>') everywhere → pnpm sync-types (fix TS). aidream: python db/generate.py → update imports to the new model module + package_integration.py → python db/detect_applied.py → python run.py clean boot. Ledger the migration. Commit + push main on both repos.

Clean cut — no silent shim (SKILL db-change → THE CUT)

The move makes public.<t> vanish, so every stale ref errors — that's correct and desired; do NOT soften it. Register the move FIRST in scripts/dead-relations.json + platform.deprecated_relations, then repoint using pnpm check:dead-relations as your checklist until it's green (it catches the raw-SQL/comment/Python refs tsc can't). If a table genuinely can't move in the window, tripwire it (platform.deprecate_relation), never a passthrough view.

NEVER

  • Leave a compat VIEW at the old public.<t> name (the silent shim — the #1 disaster: reads/writes split silently across two tables). The old name must error or tripwire-RAISE, never pass through.
  • Move a FE-read table into a schema that isn't exposed + in the db-types list (silent 404s), or that lacks schema USAGE for authenticated/anon (silent null — SET SCHEMA does not grant it).
  • Forget the registry schema_name rows — verify_canonical/has_access resolve schema from entity_types, so a stale schema_name breaks RLS resolution.
  • Recreate policies/triggers/constraints by hand — they moved with the table; recreating them risks drift.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Admin debug system wiring for the floating AdminIndicator's live debug data and Copy Full Context. Use when adding debug visibility to a route or feature, wiring useDebugContext or the debug panel, capturing console errors, or enabling the copy-context workflow for a page.

中文简介正在准备中。当前显示原文说明。

armanisadeghi/ai-matrx32026年10月20日 更新

Compact two-icon Copy / Copy-for-AI controls (components/agent-copy). Use when adding copy buttons to a row, card, list, or record; merging duplicate Copy/JSON/AI controls; continuing the copy rollout; or writing a Copy-for-AI payload. NOT for markdown content actions (use rich-document-actions).

中文简介正在准备中。当前显示原文说明。

armanisadeghi/ai-matrx32026年10月20日 更新

Disclosing a surface's existing fixed AI jobs in the shell's top Agents menu. Use when a page, panel, overlay, or window already runs a mandate behind a button, assist, automatic action, or mode; when the agent-disclosure guard names a file; or during a surface check.

中文简介正在准备中。当前显示原文说明。

armanisadeghi/ai-matrx32026年10月20日 更新

The watch-fix-rerun method for making an existing platform agent or automated process efficient and correct: baseline its ledger, run one unit yourself, fix the class behind every wasted call, rerun, record. Use when asked to improve, optimize, watch, or 'make efficient' an agent, a sandbox session, a sync job, or any recurring automated process.

中文简介正在准备中。当前显示原文说明。

armanisadeghi/ai-matrx32026年10月20日 更新

Redux state for agent execution and firing agent shortcuts. Use when editing features/agents/redux/, building agent UI, creating a conversation, touching assembleRequest or NDJSON stream state, wiring agent-state selectors, adding a per-conversation capability, or triggering a shortcut from a button, menu, or code (useShortcutTrigger, launchAgentExecution).

中文简介正在准备中。当前显示原文说明。

armanisadeghi/ai-matrx32026年10月20日 更新

The provision for a call site: the exhaustive menu of values that place in the code can realistically produce. Use before creating or fixing a mandate or agent that reasons about more than its own input, when deciding whether an agent can answer at all with what it is sent, or when its output 'looks right' but nobody checked it could be. NOT for building the agent (use create-agent).

中文简介正在准备中。当前显示原文说明。

armanisadeghi/ai-matrx32026年10月20日 更新

查看 armanisadeghi 的全部技能

报告此技能的问题