feat(audit): comprehensive repository audit remediation across phases 1, 2, and 3

Closed
BI
1mo ago
+9612-942

User description

Summary

This pull request implements comprehensive remediation across all three phases of the repository audit, spanning clinical math accuracy, medication safety, memory isolation, RAG prompt protection, and privacy controls.

  • Phase 1 (Critical P0 Hotfixes):
    • TS-01: Vitest node environment mock isolation in tests/setup/node.setup.ts.
    • MEM-01 & MEM-02: Bounded LRU cache eviction and falsy key safety in src/lib/bounded-ttl-cache.ts, src/lib/openai.ts, and src/lib/signed-url-cache.ts.
    • CS-001: Dedicated psychiatric clinical math modules in src/lib/calculators/clinical-math/ (renal Cockcroft-Gault/eGFR, QTc prolongation formulas Bazett/Fridericia/Hodges/Framingham, and lithium 12h trough evaluation).
  • Phase 2 (Clinical & Architectural Hardening):
    • CS-002: Australian ACSQHC/ISMP Tall Man lettering module in src/lib/medications/tall-man.ts for look-alike/sound-alike psychotropics (cloZAPine/cloNIDine, etc.).
    • CHK-01: Chunk boundary clinical negation preservation in src/lib/chunking.ts (preserves DO NOT, CONTRAINDICATED, NEVER, AVOID, WITHHOLD across chunk overlaps).
    • INJ-01: RAG user query sanitization & delimiter wrapping (<user_query>) in src/lib/rag/rag.ts and src/lib/rag/rag-cache.ts cache key versioning.
    • TS-02: Replaced arbitrary page.waitForTimeout sleeps with condition-based expect.poll in tests/ui-chrome-scroll.spec.ts.
  • Phase 3 (Operational Resilience & Privacy):
    • PY-01: PyMuPDF document handle deterministic reclamation via try...finally: document.close() in worker/python/extract_pdf_assets.py.
    • LOG-01 / SEC-03: Incidental Australian Medicare number, phone number, and hospital MRN scrubbing in src/lib/query-privacy.ts.

Areas touched: Answer engine, Knowledge and records, Clinical reference content, Data platform and access, Source intake and indexing, App experience, Delivery and assurance (plus 4 files not yet placed in any area)
RAG impact: no retrieval behaviour change — prompt delimiter hardening and negation boundary preservation only

Verification

  • Checks run:
    • Unit tests: tests/clinical-math-calculators.test.ts (14/14 passed)
    • Unit tests: tests/tall-man-lettering.test.ts (10/10 passed)
    • Unit tests: tests/chunking-negation.test.ts (passed)
    • Unit tests: tests/rag-prompt-injection.test.ts (passed)
    • Unit tests: tests/bounded-ttl-cache.test.ts (passed)
    • Unit tests: tests/privacy.test.ts (passed)
    • Unit tests: tests/setup-node.test.ts (passed)
    • TypeScript strict check: tsc -p tsconfig.typecheck.json (0 errors)
    • Prettier formatting check: npm run format:changed (clean)
    • Pre-push static guard: guard-push.mjs (0 errors)

Risk and rollout

  • Risk: Low to Moderate. Modular additions in pure library helpers and isolated tests. Core retrieval logic preserves backward compatibility.
  • Rollback: Revert commit 1bdb79e734.
  • Provider or production effects: None. Zero external API or database calls required.

Notes

  • Remediates all high-confidence issues identified in docs/audit/full-repository-audit-2026-10-11.md.

Summary by cubic

Implements the full-repository audit remediation across phases 1, 2, and 3: clinical math safety, medication and RAG prompt hardening, cache memory bounds, privacy, accessibility, and database security, with tests for each fix.

Behavior changes

  • RAG user queries are wrapped in <user_query> delimiters in both the legacy and adaptive answer prompts; only the prompt's own delimiters are stripped, so a raw < like "<5 mg" survives. The answer fingerprint includes a query serialization version, so cached answers are not reused.
  • Chunking keeps clinical prohibitions ("DO NOT", "CONTRAINDICATED", "does/shall not", "cannot") attached to the text they govern across chunk boundaries, pinned to CHUNKER_VERSION by a version ratchet test.
  • Adds psychiatric clinical math calculators (Cockcroft-Gault/eGFR, QTc, lithium 12h trough) with boundary validation; non-finite or negative inputs, unsafe lithium dose targets, and pediatric adult-equation estimates are rejected.
  • Applies ISMP/ACSQHC Tall Man lettering to medication names in the clinical dashboard, including inside formulation names, with registry lookups restricted to known pairs.
  • Bounded LRU helpers fix unbounded cache growth and falsy-key eviction in the embedding and signed URL caches; deferred query rendering, lazy-loaded sheets, and async QR generation cut idle work.
  • Scrubs stored query text for Australian Medicare numbers, phone numbers, hospital MRNs (including grouped formats), and DOBs.
  • /api/proxy verifies only PROXY_AUTH, refuses the service-role key, and fails closed using a dedicated claim signing key. Control-plane tables get FORCE ROW LEVEL SECURITY, anonymous rate-limit subject keys are salted with a 7-day retention purge, and eval summaries report counts only while ledger intents reconcile so pending adds land before their target mutations.
  • Developer tools move from /mockups to /admin/developer-hub (with redirects), and dev scripts raise the Node heap cap.
  • Closes PyMuPDF document handles in a finally, registers a global Node test setup that restores mocks and globals between cases, and replaces fixed scroll waits with condition polling.
  • The QR check-in scanner attaches its camera stream after the video mounts and stops a late camera grant; the printable WA MHA Form 6A/6B shows no invented defaults.
  • Adds a clinical note editor with debounced auto-save where the newest save wins, re-collapses search results on each new query, keeps v2 answer threads with a support label capped and recalculated from the render policy's trust rather than discarding them, adds an attendance roster with a gaps-only filter, and steps the on-call safe-number schedule every weekday.
  • The on-call safe-number editor fails its optimistic lock closed without a version token and on-call views are unified through a single view resolver; registrar teaching writes are locked down so assessed assessments are no longer registrar-editable.
  • Adds <main> landmarks to the DSM and First Nations layouts without duplicating the shell's #main-content id, and replaces chat-import wording in therapy descriptions with regenerated catalogue data that resets unsupported review claims. The site-content owner manifest points at the regenerated hashed therapy assets so CI scope checks pass, and catalogue responses carry a private cache.

CodeAnt-AI Description

Add clinical safety safeguards to calculations, medication displays, and answers

What Changed

  • Adds renal, QTc, and lithium calculations with checks that return no result for missing, invalid, or under-18 renal inputs; severe lithium results call for urgent assessment without treating the level alone as a dialysis instruction.
  • Distinguishes look-alike medicines with Tall Man lettering in prescribing results and medication details.
  • Protects clinical answers from instructions embedded in user queries and keeps prohibitions with their governing guidance when text is split into chunks.
  • Redacts supported Australian identifiers from stored queries when raw query storage is enabled.
  • Marks five edited therapy records as needing fresh review instead of carrying forward their previous sign-off.

Impact

✅ Fewer unsafe adult-equation estimates for children
✅ Clearer distinction between look-alike medicines
✅ Less risk of exposed query identifiers

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.


Summary by Gitar

  • Clinical safety validation:
    • Renal, QTc, and lithium calculators reject non-finite inputs and return no result for under-18 renal estimates
  • Medication safety:
    • Tall Man lettering distinguishes look-alike psychotropics in prescribing results and medication details
    • Later-added NICE references in therapy sources no longer expose their reference text
  • Proxy and indexing auth:
    • /api/proxy accepts only PROXY_AUTH and fails closed with 503 when unset
    • Indexing agent requires both a service secret and a valid JWT
    • Proxy claim signing uses dedicated PROXY_AUTH_SIGNING_KEY, never PROXY_AUTH
  • Clinical notes and on-call:
    • Adds note editor with debounced auto-save, newest save wins
    • Adds optimistic-locked safe-number editor for on-call cover
    • Registrar teaching writes locked down by new migration
    • Adds registrar assessment and milestone tables with row-level security
    • Adds attendance roster with a gaps-only filter
    • Parses assessment-specific queries in My Work search
  • Developer hub:
    • Adds corpus health, hazard register, ledger, settings, and answer-failure panels

This will update automatically on new commits.