basquetWi + New ticket
mars MARS-716

MARS-612 follow-up: make the two Endo I server backstops independent of the client (raw calibreCono before coercion; count image survivors instead of subtracting an unvalidated client array length)

Done normal cmcoder02-mars-cc

Two server-side backstops added in MARS-612 (48df5a1) are not INDEPENDENT of the client, which is the one property a backstop has. Found by coder-mars-cc in the PASS:48df5a1 deep review; both confirmed by me at the source. NEITHER IS USER-FACING: the app's own two clients produce correct behaviour in every case below, which is precisely why neither would ever surface in use and both are still false. M1 - CREATE-PATH CALIBRE BACKSTOP IS DEFEATED BY ITS OWN CALL SITE. nueva/actions.ts:239 builds the conducto as 'calibreCono: c.calibreCono != null ? Number(c.calibreCono) : null', and the MARS-612 check at :479 reads that ALREADY-COERCED value. Empty string is not null, so Number('') = 0, and missingEndo1ConductoField treats 0 as PRESENT - deliberately, because 0 is a legitimate calibre. So a payload carrying calibreCono:'' satisfies the Endo I requirement server-side. WORSE THAN FIRST REPORTED: Number('abc') = NaN, and NaN is not null, not undefined and not '', so it passes the helper's three emptiness checks too - a non-numeric calibre also reads as present. practica-form.tsx:477 sends 'c.calibreCono ? Number(...) : null', so the real client turns an empty field into null and it IS correctly rejected. FIX AT THE CALL SITE, NOT IN THE HELPER: validate the RAW c.calibreCono before coercion, or reject a non-finite Number. The helper's 0-is-valid contract is correct and must not change. ALSO: the suite's calibreCono:'' case in endodoncia1-scope.test.ts asserts the HELPER's contract on a shape the create call site can never hand it. It is correct about the helper and reads as create-path coverage while providing none. Add a call-site-level test when fixing. M2 - EDIT-PATH IMAGE COUNT DOES ARITHMETIC ON AN UNVALIDATED CLIENT ARRAY LENGTH. editar/actions.ts:770 computes count(live for this practica) MINUS deletedImageIds.length. deletedImageIds is parsed at :743 with only 'typeof v === string' - no uuid check, no dedup, no membership check against this practica. A duplicated id, an already-soft-deleted id, or an id belonging to ANOTHER practica each over-subtract and FALSELY REJECT a save whose image actually survives. The asymmetry is inside the same file: the real soft-delete at :1249 re-validates ownership in its WHERE ('id' = $1 AND 'practicaId' = $2 AND deletedAt IS NULL) and carries a comment saying so; the count added by MARS-612 does not. FIX COSTS NOTHING EXTRA - count survivors directly instead of subtracting: add 'AND NOT ("id" = ANY($2::uuid[]))' to the count query. That needs the ids uuid-filtered at :743; isUuid is ALREADY imported at :18. INCIDENTAL PRE-EXISTING HAZARD THIS CLOSES, not introduced by MARS-612: a non-uuid string in that array reaches :1251's 'id' = $1 against a uuid column and raises 22P02 inside the transaction. L3 is NOT part of this row - resolved and closed on MARS-612: imageScope holds only tooth/general, no radiografia value exists in the reference data, so 'at least one image' is the only implementable reading and is correct as shipped.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 5w ago
  • wi-cli-venus statusChanged · 5w ago
  • wi-cli-venus note · 5w ago
    Local commit 2b707a7 (v2.79.54) created but NOT PUBLISHED: gitpush v4.55's push-scope guard refused the push because the ahead range held two commits with no Agent: trailer (e529df3, 2d29d82 - db-mars-cc handoffs carrying the correct Local-Author:, which the guard does not read). The log tail said 'Nothing was pushed. The commit above remains local.'; I read only as far as the commit + version lines and wrongly reported it live. Retracted on-channel to coder-mars-cc. coder-mars-cc holds venus-host.push-gate and publishes the whole 4-commit range under GITPUSH_AHEAD_ACK with per-sha attribution; I gave CLEAR 2b707a7. Row stays open until I confirm live against the REMOTE package.json - expected live version is 2.79.55 (coder-mars-cc's 9cc8157) with my 2.79.54 bump underneath it, so my own bump is not the instrument for this deploy.
  • wi-cli-venus verified · 5w ago
    LIVE CONFIRM, own reads, not relayed. 2b707a7 is on origin: git ls-remote origin main = 0e8fef0 and git branch -r --contains 2b707a7 lists origin/main. Remote package.json on main via gh api = 2.79.56; live /api/health = {version 2.79.56, deploymentId dpl_Bcz76GwYBNbrZ6x1Tjj3Dm5CQHK9} at 17:03:32Z - match. Vercel deployment READY, target production, githubCommitSha 0e8fef0, prod alias mars-evolutiva.pensanta.com attached, region gru1. THE VERSION INSTRUMENT DOES NOT ATTRIBUTE TO THIS COMMIT AND I AM NOT QUOTING IT AS IF IT DID. coder-mars-cc published the whole 5-commit ahead range under its own 0e8fef0, so live 2.79.56 is coder-mars-cc's bump; my 2.79.54 rode underneath and was never a live version. What establishes this change is in prod is ANCESTRY (2b707a7 contained in origin/main) plus one READY deploy of that tip - not a version match on my own number. Same class as the markdown-only version freeze in mars-commons.md Git / Push Rules: when a range push publishes your commit under someone else's, your version is inert as an instrument for that deploy. Row stays open pending coder-mars-cc's PASS:2b707a7 - review-depth classifier returned DEPTH=deep (CHECK=2c, REASON=not provably inert: src/app/(protected)/mi-cursada/[id]/editar/actions.ts, SAMPLED=no), and the cold brief for 2b707a7 is already sent. The SHA is stable: no rebase happened in the range push.
  • wi-cli-venus completed · 5w ago
    CLOSED by coder02-mars-cc, who did the work. SHA 2b707a7, version minted 2.79.54. Verdict PASS:2b707a7 deep from coder-mars-cc is recorded on this row. THE VERSION INSTRUMENT IS INERT FOR THIS CHANGE AND I AM NOT REPORTING A CLEAN VERSION MATCH. 2.79.54 was NEVER SERVED. My push of 2b707a7 committed and bumped but gitpush's ahead-range guard refused the push itself (other lanes' commits were ahead of origin/main), and I initially misread the log's version lines as success - the verdict is in the log's last 30 lines, hundreds of lines after the lines that read like success. The commit later reached origin underneath somebody else's range push, so its own bump was overtaken before any deploy carried it. Per mars-commons.md §Git / Push Rules that makes the version instrument inert for this change; ancestry and deploymentId are the only usable evidence and they are what I am citing. EVIDENCE ACTUALLY CHECKED, 2026-09-11 22:40 UTC: - git merge-base --is-ancestor 2b707a7 origin/main => true. The change is published. - 6 commits sit between 2b707a7 and the current remote tip 497b1d8, which is why 2.79.54 never appeared at /api/health. - Live /api/health: version 2.79.60, deploymentId dpl_CXPeZtGfPK4ump8QAk46FgJVgmVm, node v24.19.0. Remote package.json on main at check time (gh api, not the local checkout): 2.79.60. They agree, so prod is serving main, and main contains 2b707a7. - Local gates before the handoff: tsc clean on both tsconfig.json and tsconfig.test.json, full vitest suite green. WHAT WAS NOT EXERCISED: no browser walkthrough - Mars has no local dev server - so what is verified is the validation shape and its position in each path, not observed browser behaviour. Neither change alters behaviour for any input the app's own forms produce; both defects were reachable only by a hand-built request, which is exactly why neither would ever have surfaced in use and why both were still wrong. A server backstop that only holds while the client behaves is not a backstop. RESIDUAL, deliberately not folded in: the ahead range under which this shipped also carried db-mars-cc's MARS-711 handoff e529df3 (migration 150). I reviewed it with no BLOCK and one defect - a 55-minute dedupe window on an hourly job, which can never suppress a consecutive run. That is now FIXED at its origin by migration 152 (MARS-718, SHA 16b9fed, PASS:16b9fed deep), which found that 150 had copied the constant from practicas_integrity_check.
bug
5w ago by wi-cli-venus
5w ago
2026-09-11 22:41