Mx Migration AuthorSAFE
AI-powered CMS core for personal blogs and creator websites, with AI summaries, translation, moderation, and writing workflows.
Overview
AI-powered CMS core for personal blogs and creator websites, with AI summaries, translation, moderation, and writing workflows.
81b3f9a4c850OBSERVED · 2026-10-14What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
--- name: mx-migration-author description: | Author and review Drizzle SQL migrations safely for rolling deploys. Triggers when editing apps/core/src/database/schema/*.ts or apps/core/src/database/migrations/*.sql, when the user runs drizzle-kit generate, when "lint-migrations" reports a violation, or on prompts like "迁移", "改 schema", "alter table", "add a column", "drop column", "migration safety". Enforces the expand-contract pattern because mx-core ships rolling deploys (Dokploy, 2 replicas) where new and old pods coexist for tens of seconds during cutover. argument-hint: [migration-file-path] --- # MX Migration Author Migrations run as a release-phase step (see `docs/superpowers/specs/2026-05-05-database-migration-release-phase-design.md`). Schema changes must be backwards-compatible with the previous release's code, because old replicas keep serving traffic until rolling deploy finishes. ## §A Invariants 1. mx-core ships rolling deploy. New and old pods run simultaneously during cutover. 2. Therefore: release `N`'s migration must work with release `N-1`'s code without errors. The contract-side change (drop / rename / type change) must wait one release after the expand-side change. 3. `mx-migrate` runs to completion before any `mx-core` pod starts. The app refuses to start if schema is behind. This means migration failures **block the deploy** rather than crash-loop replicas. 4. Drizzle migrations run inside a transaction by default. CONCURRENTLY index creation requires `--> statement-breakpoint` to break out. ## §B Decision tree ``` Is the change additive (table / nullable column / index / FK)? ├── yes → use §C.1 (one release) └── no → expand first, contract later — see §C.2 (multiple releases) ``` ## §C.1 Expand templates (single release) | Operation | Safe approach | |---|---| | Add table | `CREATE TABLE` (drizzle generates) — safe; old code has no reference. | | Add nullable column | `ADD COLUMN col TYPE` — safe. | | Add NOT NULL column | **Three releases.** Phase 1: add nullable + dual-write in code. Phase 2: backfill (separate SQL migration). Phase 3: `ALTER COLUMN col SET NOT NULL`. | | Add NOT NULL with DEFAULT | `ADD COLUMN col TYPE NOT NULL DEFAULT <expr>` — single release, but consider table size: a wide DEFAULT rewrites the table. | | Add index (small table) | `CREATE INDEX` is fine. | | Add index (large table, est. >1M rows) | `CREATE INDEX CONCURRENTLY`. Must be its own statement and **not** inside a drizzle transaction. Annotate the breakpoint and the lint allow. | | Add FK (large table) | Two releases: `ADD CONSTRAINT ... NOT VALID`, then `VALIDATE CONSTRAINT`. | ## §C.2 Mutate / contract templates (multiple releases) | Operation | Stages | |---|---| | Drop column | R1: stop reading/writing the column in code (deploy code only). R2: `ALTER TABLE ... DROP COLUMN`. | | Rename column | R1: add new column. R2: dual-write (read old preferentially, write both). R3: backfill, switch reads to new. R4: drop old column. | | Change column type | R1: add new column. R2: backfill + dual-write. R3: cut over readers/writers. R4: drop old. | | Drop NOT NULL | One release — relaxing constraint is safe. | | Add NOT NULL | See §C.1 row. | | Drop table | R1: stop all references in code. R2: `DROP TABLE IF EXISTS`. | | Drop index | One release — only loses performance; not a correctness break. | ## §D Working with the lint guard `pnpm -C apps/core run lint:migrations` flags dangerous patterns (`no-drop-column`, `no-drop-table`, `no-bare-not-null-add`, `no-rename-column`, `no-alter-type`, `no-bare-create-index`). The lint runs in CI on every PR. If the lint flags a statement and the change is genuinely safe in this context (e.g. baseline cutover with no existing consumers, large-batch rebuild on a known-cold table), add a per-statement annotation **above or on the same line** as the statement: ```sql -- migration-lint:allow=no-drop-column reason=baseline cutover, no consumers yet ALTER TABLE users DROP COLUMN email; ``` `reason=` is mandatory. Bare `migration-lint:allow=*` without `reason=` is itself a lint error. Reviewers must read the reason; do not slip allow annotations past review without justification. ## §E Self-checklist (run after generating each migration) ``` [ ] Is this migration backwards-compatible with the previous release's code? [ ] Does any DDL acquire AccessExclusive on a hot table? (DROP/RENAME/TYPE) [ ] Indexes on large tables are CONCURRENTLY (and broken out of drizzle's tx)? [ ] If a backfill is needed, is it staged so it does not block? [ ] Is a follow-up contract migration tracked (issue / next-release plan)? [ ] `pnpm -C apps/core run lint:migrations` passes locally? [ ] Migration applied cleanly against an ephemeral testcontainer? ``` ## §F Authoring workflow 1. Edit `apps/core/src/database/schema/*.ts`. 2. Run `pnpm -C apps/core exec drizzle-kit generate` to scaffold the SQL. 3. Read the generated SQL. Restructure if the change implies a contract operation — split into expand-now / contract-later migrations across releases. 4. `pnpm -C apps/core run lint:migrations`. Fix or annotate. 5. Apply locally: `pnpm -C apps/core run migrate`. 6. Add tests covering the schema change (repository spec, e2e where user-facing). For NOT NULL adds with default, also write a test that reads existing rows. 7. Commit. PR title prefix: `migration:` or `db:`. PR body must include the expand-contract phase plan. ## §G What this skill must not do - Decide unilaterally to add `migration-lint:allow=` — that's a human judgment call. Suggest the annotation and the reason, surface the trade-off, but require explicit user confirmation. - Combine expand and contract into one migration, except for the baseline (idx ≤ 0003). - Suggest schema changes without first reading `apps/core/src/database/schema/` to understand current shape. - Use `applyMigrations` or any boot-time mutation. Migration is a release-phase step
Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | NA |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (1)
apps/core/.env
Gates applied: no_behavioural_pass.
81b3f9a4c850full audit observations/trust-audit/skill/mx-space__mx-migration-author.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-14 | 81b3f9a4c850 | SAFE | B | 89 | first audit |
Questions
What does the Mx Migration Author skill do?
AI-powered CMS core for personal blogs and creator websites, with AI summaries, translation, moderation, and writing workflows.
Is Mx Migration Author safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Mx Migration Author access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
How current is this page?
The grade is for one exact copy of the source (81b3f9a4c850), read on 2026-10-14. The repository is watched, and a new audit runs when it changes — this is the first audit.