feat(migrations): reconcile collections columns missed by initial-schema backfill (B2) #150

Merged
varutasu merged 1 commit from convoy/reconcile-b2-collections-columns into main 2026-06-14 09:18:05 -04:00
varutasu commented 2026-06-14 09:04:27 -04:00 (Migrated from github.com)

Summary

Brief 2 of the reconcile-historical-add-scripts convoy. Captures the
collections-table DDL that historical scripts added to prod but
migrations/1779853647564_initial-schema.js never captured.

Column / object Source script Reference
collections.visibility VARCHAR(20) DEFAULT 'private' scripts/add-collaboration-features.js (collections half) lines 15-21
collections.tcg VARCHAR(50) DEFAULT 'MTG' scripts/add-collaboration-features.js (collections half) lines 15-21
collections.tags TEXT scripts/add-collaboration-features.js (collections half) lines 15-21
collections.slug VARCHAR(100) UNIQUE scripts/add-collection-slugs.js lines 17-20
idx_collections_slug UNIQUE INDEX scripts/add-collection-slugs.js line 79
check_slug_format CHECK constraint scripts/add-collection-slugs.js line 91
collections.image TEXT scripts/add-image-column.js lines 14-17

Out of scope

  • collection_permissions, collection_activity, users.is_pending,
    idx_collections_visibility, idx_collection_permissions_*,
    idx_collection_activity_collection_id — owned by B3
    (reconcile-collaboration-tables) per architect plan.
  • is_system_collection — already captured by
    migrations/1780378340194_system-collection-description.js.
  • Per-row slug backfill DML (script lines 41-74) — deferred per architect
    plan (Defer slug backfill DML — generating slugs on a fresh env is moot.). Long-lived envs already ran the backfill historically.

Idempotency (D2)

Every statement is IF NOT EXISTS-guarded:

  • ADD COLUMN IF NOT EXISTS for the 5 columns. The inline UNIQUE clause
    on slug is silently ignored when the column already exists, so prod
    (already has the autogen collections_slug_key) and fresh envs both
    converge.
  • CREATE UNIQUE INDEX IF NOT EXISTS for idx_collections_slug.
  • A DO $$ ... END $$ block guarded by pg_constraint-existence check
    for check_slug_format (Postgres has no native IF NOT EXISTS clause
    for named constraints).

Static idempotency grep confirms each B2 column/constraint is the sole
owner across all 8 migrations. The image_url/stock_image_url
references in 1779853647564_initial-schema.js are on the cards
table, not collections. The tags table created in
1781440721350_add-tagger-tables.js is a separate table from this
migration's collections.tags column.

Down-migration

Hard stub. Throws with a descriptive error matching the initial-schema
style. Rolling back would erase visibility / tcg / tags / slug / image
data on every collections row.

Files changed

  • migrations/1781000000002_reconcile-collections-columns.js (new, 114 lines)

Acceptance criteria

  • Pre-assigned timestamp 1781000000002 honored
  • All scope columns from architect inventory captured (visibility,
    tcg, tags, slug, idx_collections_slug, check_slug_format,
    image)
  • No out-of-scope columns added (collaboration tables, indexes
    reserved for B3, is_system_collection left to existing migration)
  • Slug backfill DML deferred per architect plan
  • Idempotent against fresh, prod, and re-apply
  • down() hard-stub throw matching initial-schema style
  • No edits to historical scripts/add-* / fix-* / seed-* files
    (no-go-zones rule)
  • No edits to architect convoy file (B7 owns as-shipped sweep)
  • No edits to lib/slug-utils.js (runtime context only)

Test plan

  • node --check migrations/1781000000002_reconcile-collections-columns.js → exit 0
  • npm run lint → 0 errors (1 pre-existing unrelated warning in components/CollectionsPageView.js)
  • npm run test:run → 131/131 passing
  • Static idempotency proof via grep — each B2 column/constraint is the
    sole owner across migrations/*.js
  • Live Neon-branch test deferred to operator runbook (D5 of convoy
    plan); to verify, the operator runs npm run migrate up against a
    fresh Neon branch and a long-lived env (both should succeed; both
    should be no-ops on pgmigrations-row insert plus the DDL-
    idempotent statements).

Notes for reviewer

  • The slug VARCHAR(100) UNIQUE inline clause and the explicit
    idx_collections_slug index both exist in the historical script; both
    are replicated here to match prod state byte-equivalently. Postgres
    ends up with the autogen collections_slug_key unique constraint
    (from the inline clause) AND the named idx_collections_slug unique
    index — same as prod. This double-uniqueness is benign at the SQL
    level.
  • B2 deliberately does NOT add idx_collections_visibility even though
    the visibility column lands here — that index is in the
    collaboration-half indexes that B3 owns.
  • 5 sibling implementer briefs (B1, B3, B4, B5, B6) are running in
    parallel against disjoint migration files and disjoint pre-assigned
    timestamps. No file-level conflicts expected.

Made with Cursor

<!-- pipeline: convoy=reconcile-historical-add-scripts brief=2 --> ## Summary Brief 2 of the `reconcile-historical-add-scripts` convoy. Captures the `collections`-table DDL that historical scripts added to prod but `migrations/1779853647564_initial-schema.js` never captured. | Column / object | Source script | Reference | | --- | --- | --- | | `collections.visibility VARCHAR(20) DEFAULT 'private'` | `scripts/add-collaboration-features.js` (collections half) | lines 15-21 | | `collections.tcg VARCHAR(50) DEFAULT 'MTG'` | `scripts/add-collaboration-features.js` (collections half) | lines 15-21 | | `collections.tags TEXT` | `scripts/add-collaboration-features.js` (collections half) | lines 15-21 | | `collections.slug VARCHAR(100) UNIQUE` | `scripts/add-collection-slugs.js` | lines 17-20 | | `idx_collections_slug` UNIQUE INDEX | `scripts/add-collection-slugs.js` | line 79 | | `check_slug_format` CHECK constraint | `scripts/add-collection-slugs.js` | line 91 | | `collections.image TEXT` | `scripts/add-image-column.js` | lines 14-17 | ### Out of scope - `collection_permissions`, `collection_activity`, `users.is_pending`, `idx_collections_visibility`, `idx_collection_permissions_*`, `idx_collection_activity_collection_id` — owned by **B3** (`reconcile-collaboration-tables`) per architect plan. - `is_system_collection` — already captured by `migrations/1780378340194_system-collection-description.js`. - Per-row slug backfill DML (script lines 41-74) — deferred per architect plan (`Defer slug backfill DML — generating slugs on a fresh env is moot.`). Long-lived envs already ran the backfill historically. ## Idempotency (D2) Every statement is `IF NOT EXISTS`-guarded: - `ADD COLUMN IF NOT EXISTS` for the 5 columns. The inline `UNIQUE` clause on `slug` is silently ignored when the column already exists, so prod (already has the autogen `collections_slug_key`) and fresh envs both converge. - `CREATE UNIQUE INDEX IF NOT EXISTS` for `idx_collections_slug`. - A `DO $$ ... END $$` block guarded by `pg_constraint`-existence check for `check_slug_format` (Postgres has no native `IF NOT EXISTS` clause for named constraints). Static idempotency grep confirms each B2 column/constraint is the sole owner across all 8 migrations. The `image_url`/`stock_image_url` references in `1779853647564_initial-schema.js` are on the `cards` table, not `collections`. The `tags` table created in `1781440721350_add-tagger-tables.js` is a separate table from this migration's `collections.tags` column. ## Down-migration Hard stub. Throws with a descriptive error matching the initial-schema style. Rolling back would erase visibility / tcg / tags / slug / image data on every collections row. ## Files changed - `migrations/1781000000002_reconcile-collections-columns.js` (new, 114 lines) ## Acceptance criteria - [x] Pre-assigned timestamp `1781000000002` honored - [x] All scope columns from architect inventory captured (`visibility`, `tcg`, `tags`, `slug`, `idx_collections_slug`, `check_slug_format`, `image`) - [x] No out-of-scope columns added (collaboration tables, indexes reserved for B3, `is_system_collection` left to existing migration) - [x] Slug backfill DML deferred per architect plan - [x] Idempotent against fresh, prod, and re-apply - [x] `down()` hard-stub throw matching initial-schema style - [x] No edits to historical `scripts/add-*` / `fix-*` / `seed-*` files (no-go-zones rule) - [x] No edits to architect convoy file (B7 owns as-shipped sweep) - [x] No edits to `lib/slug-utils.js` (runtime context only) ## Test plan - [x] `node --check migrations/1781000000002_reconcile-collections-columns.js` → exit 0 - [x] `npm run lint` → 0 errors (1 pre-existing unrelated warning in `components/CollectionsPageView.js`) - [x] `npm run test:run` → 131/131 passing - [x] Static idempotency proof via grep — each B2 column/constraint is the sole owner across `migrations/*.js` - [ ] Live Neon-branch test deferred to operator runbook (D5 of convoy plan); to verify, the operator runs `npm run migrate up` against a fresh Neon branch and a long-lived env (both should succeed; both should be no-ops on `pgmigrations`-row insert plus the DDL- idempotent statements). ## Notes for reviewer - The `slug VARCHAR(100) UNIQUE` inline clause and the explicit `idx_collections_slug` index both exist in the historical script; both are replicated here to match prod state byte-equivalently. Postgres ends up with the autogen `collections_slug_key` unique constraint (from the inline clause) AND the named `idx_collections_slug` unique index — same as prod. This double-uniqueness is benign at the SQL level. - B2 deliberately does NOT add `idx_collections_visibility` even though the `visibility` column lands here — that index is in the collaboration-half indexes that B3 owns. - 5 sibling implementer briefs (B1, B3, B4, B5, B6) are running in parallel against disjoint migration files and disjoint pre-assigned timestamps. No file-level conflicts expected. Made with [Cursor](https://cursor.com)
vercel[bot] commented 2026-06-14 09:04:34 -04:00 (Migrated from github.com)

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tcg-vault Ready Ready Preview, Comment Jun 14, 2026 1:04pm

Request Review

[vc]: #JFBjYuYkd179ILBjyZL90eyiaaYsrBpg/H3yGRBvi0Q=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJ0Y2ctdmF1bHQiLCJwcm9qZWN0SWQiOiJwcmpfRjZXOEVvRkd3Y0g3aWVGcnRvRlNlOXdVVkFhNSIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJ0Y2ctdmF1bHQtZ2l0LWNvbnZveS1yZWNvbmNpLTIwZjYwNy1yYW5kYWxsLXN0aWxsd2VsbHMtcHJvamVjdHMudmVyY2VsLmFwcCJ9LCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vcmFuZGFsbC1zdGlsbHdlbGxzLXByb2plY3RzL3RjZy12YXVsdC9DRVJvWU1veVR4YzJrRkhNVmVuOW5WVEo5MUVuIiwicHJldmlld1VybCI6InRjZy12YXVsdC1naXQtY29udm95LXJlY29uY2ktMjBmNjA3LXJhbmRhbGwtc3RpbGx3ZWxscy1wcm9qZWN0cy52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIn1dLCJyZXF1ZXN0UmV2aWV3VXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3ZlcmNlbC1hZ2VudC9yZXF1ZXN0LXJldmlldz9vd25lcj1zdHdsLWxhYnMmcmVwbz10Y2ctdmF1bHQmcHI9MTUwIn0= The latest updates on your projects. Learn more about [Vercel for GitHub](https://vercel.link/github-learn-more). | Project | Deployment | Actions | Updated (UTC) | | :--- | :----- | :------ | :------ | | [tcg-vault](https://vercel.com/randall-stillwells-projects/tcg-vault) | ![Ready](https://vercel.com/static/status/ready.svg) [Ready](https://vercel.com/randall-stillwells-projects/tcg-vault/CERoYMoyTxc2kFHMVen9nVTJ91En) | [Preview](https://tcg-vault-git-convoy-reconci-20f607-randall-stillwells-projects.vercel.app), [Comment](https://vercel.live/open-feedback/tcg-vault-git-convoy-reconci-20f607-randall-stillwells-projects.vercel.app?via=pr-comment-feedback-link) | Jun 14, 2026 1:04pm | <a href="https://vercel.com/vercel-agent/request-review?owner=stwl-labs&repo=tcg-vault&pr=150" rel="noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://agents-vade-review.vercel.sh/request-review-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://agents-vade-review.vercel.sh/request-review-light.svg"><img src="https://agents-vade-review.vercel.sh/request-review-light.svg" alt="Request Review"></picture></a>
github-actions[bot] commented 2026-06-14 09:05:45 -04:00 (Migrated from github.com)

Pipeline Health

Build + CI gates

Gate Status
Vercel build (Preview) pass
CI: Lint in progress
CI: Schema map fresh skipped
Preview smoke ⏭ skipped or pending
Visual diff ⏭ skipped or pending

Build runs on Vercel; this CI runs lint and schema-map drift only (no duplicate build).

Role reports

Role Status
Reviewer report pending
A11y audit pending
Design system audit pending

See individual comments above for details. This rollup updates automatically.

<!-- pipeline-rollup --> ## Pipeline Health ### Build + CI gates | Gate | Status | | --- | --- | | Vercel build (Preview) | ✅ pass | | CI: Lint | ⏳ in progress | | CI: Schema map fresh | ❌ skipped | | Preview smoke | ⏭ skipped or pending | | Visual diff | ⏭ skipped or pending | _Build runs on Vercel; this CI runs lint and schema-map drift only (no duplicate build)._ ### Role reports | Role | Status | | --- | --- | | Reviewer report | ⏳ pending | | A11y audit | ⏳ pending | | Design system audit | ⏳ pending | See individual comments above for details. This rollup updates automatically.
Sign in to join this conversation.
No description provided.