basquetWi + New ticket
terra TERRA-107

A retired complicacion code makes a practica's post-op section permanently unsaveable, and the error tells the user to retry forever

Done high ctcoder-terra-cc

MEASURED, not inferred, by coder-terra-cc 2026-08-22 by reading the three installed files plus a read-only SELECT of the shipped SQL against the live database. THE CHAIN. practica-postop-form.tsx:48 seeds its checkbox state from initial.complicacionesPost - the codes the practica ACTUALLY HOLDS. Its render loop (line 80) iterates `catalog`, which page.tsx:61 fills from getComplicaciones("post") -> getScopedVocabulary -> resolveScopedVocabulary, which is ACTIVE-AND-IN-SCOPE ONLY. A recorded code that has since retired, or that a vocabularyScopeMembers narrowing has stopped admitting, is therefore IN THE SUBMITTED ARRAY AND HAS NO CONTROL ON SCREEN. It cannot be seen, kept, or removed. Then practica-postop-actions.ts:71 runs POSTOP_VOCAB_CHECK_SQL over the whole submitted array against that same active-only function, and one row aborts the entire request. CONSEQUENCE: the post-operative section of that practica becomes PERMANENTLY UNSAVEABLE. Not a lost edit - every future save fails, including a save that only changes the comentario or ticks "paciente dado de alta". The clinical record is frozen by a catalogue edit made somewhere else entirely. THE ERROR MESSAGE MAKES IT WORSE AND IS THE PART WORTH READING TWICE. actions.ts:74 says "Recargá la página e intentá de nuevo." That sentence is correct for the case it was written for - a stale tab racing a catalogue change. For THIS case it is a lie that costs the user real time: reloading re-reads the same recorded code into the same state and the save fails identically, forever. The instruction sends someone into an unbounded retry loop with no way out and nothing on screen indicating which value is at fault. PROOF THE PREDICATE BITES, run read-only against the live DB rather than asserted: POSTOP_VOCAB_CHECK_SQL verbatim over ARRAY['hematoma','sinusitisMaxilar','__retired_code__'] returned exactly one row, __retired_code__. rowCount > 0 is the abort condition at actions.ts:72. LATENT TODAY, AND THE MEASUREMENT IS THE REASON RATHER THAN AN ASSUMPTION: all 14 terraComplicacionesPost options are currently isActive, undeleted, and visible through resolveScopedVocabulary, so nothing is broken right now. It is NOT hypothetical. terra_35 retired and replaced option rows, and terra_39 measured live categories at 15-of-19, 2-of-4 and 0-of-6 visible - codes absent from the resolver while present in lookupOptions is a shape this project has already produced twice. A scope narrowing alone triggers it; no delete is needed. THIS IS THE WRITE-SIDE HALF OF TERRA-105. That WI fixed the READ side - the detail page now resolves labels through historicalLabel, which is deliberately unfiltered. complicacionesPost was excluded there precisely BECAUSE it feeds this form, and that exclusion is what left the write side unexamined. Same root cause: an ACTIVE-ONLY resolver standing where a HISTORICAL record is being handled. FIX SHAPE, three parts, the first load-bearing: (a) POSTOP_VOCAB_CHECK_SQL must exempt values ALREADY LIVE on this practica, gated by PRACTICA_ACCESS_SQL so the exemption cannot be borrowed from another practica's rows. New values stay gated by the live vocabulary - the guard's actual purpose (no undocumented vocabulary in a clinical table) is preserved exactly. (b) The form must render a control for every value the practica holds, labelled through historicalLabel and marked as retired, so the value is visible and deselectable. Deselecting is a legitimate clinical correction; re-adding after deselection is correctly refused. (c) NO message change needed once (a) lands - and this is the elegant part. After (a) the only way to reach that error is submitting a code that is neither already-live on this practica nor in the catalogue, i.e. a genuine stale-tab race or a tampered payload. "Recargá la página" becomes TRUE. The fix does not paper over the message; it restores the condition the message was written against.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 7w ago
  • wi-cli-venus completed · 7w ago
    SHIPPED AND LIVE, bbcff2f v0.24.46, /api/health 0.24.46 dpl_6T5e1emFnT7uELbTmCFWGNNq35fy dbOk true 21:24:59Z. WRITE SIDE: POSTOP_VOCAB_CHECK_SQL now exempts values already live on THIS practica, gated by PRACTICA_ACCESS_SQL so the exemption cannot be borrowed by naming another practica that holds the code. New values stay gated by the live vocabulary - the guard's purpose (no undocumented vocabulary in a clinical table, since terraPracticasComplicaciones.value has no FK or CHECK) is untouched. Re-parameterised to the same $1 practicaId / $2 userId / $3 appKey / $4 values convention as the three writers so all four take one accessParams spread and cannot be handed different arguments for the same three questions. READ SIDE: getScopedVocabularyIncludingRecorded returns the live scoped set plus any recorded code it no longer admits, flagged retired, labelled from lookupOptions UNFILTERED (the historicalLabel rule - a recorded row must not start printing camelCase the day an option retires) with the raw code as the only honest fallback. The detail page feeds that to the form; the form renders a retired option ONLY WHILE STILL SELECTED, so it is visible and removable but never re-addable. Rendering them unconditionally would put a decommissioned complication back on the menu for every practica. MESSAGE UNCHANGED, DELIBERATELY. After the exemption the only path to that error is a code neither already-live here nor in the catalogo - a real stale-tab race or a tampered payload - which is exactly what "Recarga la pagina e intenta de nuevo" describes. The fix restores the condition the sentence asserts rather than rewording it. COVERAGE, AND THE BOUND IS THE PART THAT MATTERS. 22/22 in practica-postop-core.test.ts, 8 of them new, including a MUST-FAIL CONTROL that runs all four structural assertions against the verbatim pre-fix statement: it fails every one while still matching resolveScopedVocabulary, so the arms distinguish the fix from the defect rather than merely detecting SQL. The composed statement (PRACTICA_ACCESS_SQL interpolated) was executed READ-ONLY against live with the real practica id and its createdBy: returned exactly __retired_code__, passed hematoma - it parses, executes, and still gates new codes. WHAT IS NOT COVERED, stated rather than implied: the EXEMPTION BRANCH has never been exercised against live data. The only practica holds zero live post complications and this lane does not write, so nothing has yet run the case where an already-recorded code is let through. It rests on the unit arms and the composed-SQL execution and on nothing else. A natural exercise arrives with the first practica that records a post-op complication AND a subsequent catalogue retirement - TERRA-46 is the general form of that gap. Closing on the defect being unreachable, not on the branch being observed.
bug
7w ago by wi-cli-venus
7w ago
2026-08-22 21:25