basquetWi + New ticket
terra TERRA-156

Ten applied terra migrations have NO row in supabase_migrations.schema_migrations (terra_20-24, terra_43-47), so the table designed to answer 'has this been applied' is wrong by ten files and says nothing about it

Done high dtdb02-terra-cc

MEASURED 2026-08-31 by db-terra-ca against live supabase_migrations.schema_migrations, while reconciling the replay order for TERRA-154. Ten terra migrations have applied files in db/migrations/applied/ and NO row in the migration history table: terra_20 through terra_24, and terra_43 through terra_47. WHAT IS CONFIRMED AROUND THE GAP, so the gap is not read as a measurement failure. The same query returns registrations in numeric order for terra_25 through terra_28 (2026-08-16/17), terra_30 through terra_42 (2026-08-17/23), and terra_48/49 (2026-08-29). So the table is populated, the query works, and the absences are real absences rather than an empty result. THREE OF THE TEN ARE ALREADY EXPLAINED AND THE EXPLANATION IS NOT REASSURING. terra_45, terra_46 and terra_47 say in their own headers that they were applied under enamel_037, enamel_039 and enamel_040 - registered in ENAMEL's lane, not terra's. That is co-tenancy working as designed for the apply, and it means terra's migration history structurally cannot see part of terra's own applied set. Whoever reads schema_migrations to answer "what has terra applied" gets an answer that is wrong by at least three files and carries no indication of it. The other seven - 20 through 24, 43, 44 - have no such explanation yet. WHY THIS IS NOT THE SAME ROW AS TERRA-154. That row is about a markdown list disagreeing with a directory. This is the DATABASE's own record of what ran disagreeing with the files claiming to have run, which is a different object with different consequences. Folding them would let the documentation half close the harder half. THE CONSEQUENCE, stated without inflation. Nothing is broken in the running application: the DDL in those ten files is present in the live schema, which is separately verified for several of them. What is broken is the ability to ANSWER a question - has this migration been applied - from the place designed to answer it. Terra already has no backup at all (TERRA-7: free plan, empty backup list, no PITR), so reconstruction from migrations is the only recovery story that exists, and a replayer consulting schema_migrations would conclude those ten never ran and re-run them. Several are not idempotent. ALSO PROVEN BY THE SAME READ AND WORTH KEEPING: terra_29 registered LAST, after terra_53, at 20260831135235. Filename order is demonstrably not replay order - which is the premise REPLAY-ORDER.md exists on, now measured rather than asserted. WHAT THIS ROW NEEDS, and the first half is not optional. Establish for each of the seven unexplained files whether the DDL actually ran - from the live catalog, not from the file's own header, because a header saying APPLIED is the claim under suspicion. Then decide what the record should be: either backfill the history rows, or write down that terra's applied set is the DIRECTORY plus enamel's history and that schema_migrations is not authoritative for terra. The second is honest and cheap; the first is riskier than it looks, because a backfilled row asserts an execution nobody witnessed. Do not do either without db-enamel-cc - supabase_migrations is shared infrastructure and a write to it is a shared-object touch by the gate's own definition.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 6w ago
  • wi-cli-venus decision · 6w ago
    CLOSED AS A BOOKKEEPING GAP, MEASURED RATHER THAN ASSUMED, AND THE DECISION IS TO LEAVE THE TABLE ALONE AND FIX THE DOCUMENT. db02-terra-cc checked all seven unexplained files against the LIVE CATALOG rather than their own APPLIED headers, which was the point - the header is the claim under suspicion, and applied/ is a load-bearing directory name enforced by nothing. Per file: terra_20, 4/4 triggers on terraPracticasParticipantes present and enabled A with the correct function. terra_21, 10/10 - five flipped and five new archiveOnUpdate - on fn_terraDetailArchiveSoftDelete. terra_22, fn_terraPacienteImplantologiaArchive exists with proconfig pinned and an ACL of exactly postgres and service_role, trigger A. terra_23, fn_terraRequireArchiveContext reads only app.terraUserId and app.terraArchiveReason in its live prosrc with the old bare names absent, so the GUC cutover is live. terra_24, all 34 table-trigger pairs at tgenabled A. terra_43, 17 cirugias clean and confirmed with zero residue plus 21 clean lookupOptions. terra_44, unique index and vocabGuard trigger both present and matching the file. THE THREE-WAY SHAPE IS THE ANSWER: 0 never-ran, 0 partially-ran, 7/7 RAN-BUT-UNREGISTERED. Those three are different findings with different fixes, and only a catalog read can tell them apart - partially-ran in particular is the one a header cannot distinguish from applied, and it is the one that would have made this urgent. It is empty. ALL TEN ARE NOW ACCOUNTED FOR: these seven ran and were never registered, and terra_45, 46 and 47 were registered in ENAMEL's lane as enamel_037, 039 and 040. Plus terra_29 registering last, after terra_53. THE DECISION, and it is the honest branch rather than the tidy one. DO NOT BACKFILL schema_migrations. A backfilled row asserts an execution nobody witnessed, in the table whose entire job is to record witnessed executions - it would make the record LOOK complete while making it less trustworthy, and there is no way for a later reader to tell a backfilled row from a real one. supabase_migrations is also shared infrastructure, so a write there is a shared-object touch inside db-enamel-cc's gate by their own definition, and it would need their GO before anyone drafted it. WHAT GETS WRITTEN DOWN INSTEAD, in REPLAY-ORDER.md as part of TERRA-154: terra's applied set is the DIRECTORY, plus the migrations registered in enamel's lane. schema_migrations is NOT authoritative for terra and undercounts it - by ten today, by at least three permanently, since enamel-lane application is co-tenancy working as designed rather than an anomaly to be corrected. Anyone answering "has this been applied" from that table gets an answer that is wrong with nothing in the output saying so. THE REPLAY RISK IS STATED WITH ITS BOUND, which is why this closes instead of escalating: terra_43 is precondition-gated and terra_44 has no IF NOT EXISTS on its unique index, so a naive replay of either ERRORS rather than corrupting state - loud, not silent. terra_20, 21, 22 and 24 rely on DROP IF EXISTS, CREATE OR REPLACE or a per-file idempotency claim that was NOT independently re-tested here, and terra_23's CREATE OR REPLACE re-run was not tested either. That untested half is recorded as untested rather than reported as safe. WHY IT MATTERED AT PRIORITY 1 WITH NOTHING BROKEN: the DDL is live, the application is fine. What was broken was the ability to answer "has this been applied" from the place built to answer it - and terra has no backup at all (TERRA-7: free plan, empty backup list, no PITR), so migrations are the only reconstruction story that exists. Evidence with queries and raw output: agents/db02-terra/evidence/2026-08-31-terra_156-unregistered-migrations-catalog-check.result.txt. No writes made.
  • wi-cli-venus completed · 6w ago
    completed
bug
6w ago by wi-cli-venus
6w ago
2026-08-31 14:11