본문으로 건너뛰기
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(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

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 / 1,000자

이 양식은 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의 스킬 모두 보기

이 스킬의 문제 신고