Fix the audit's code-only "fix now" findings (search patient check, admin MFA, alerts)

Merged
BI
25d ago
+510-2196

Requested by Josh Β· project thread

Summary

Code-only fixes from the 19 October 2026 repository audit ("fix now" group). No database change, no protected search or ranking file, no sw.js, no paid call.

Before: typing a patient detail into Documents or Differentials search sent it to the overseas AI service for embedding, because only Answer screened for it. An expired session during an answer showed "Search request was not authorized by the server" with a Retry button. A stolen administrator session without recent MFA could delete documents or publish site content. A prototype referral board page was publicly served, work-area pages were indexable, the ops digest could miss a page when a scheduled run fired late, Sentry dropped bot-triggered 5xx errors, and two worker completion paths skipped the health heartbeat.

After: Documents and Differentials search are screened in the browser and refused by /api/search (400 patient_detail_in_question) before retrieval. The error panel maps a session-expired error to "Sign in again" without Retry. Permanent document delete and site-content publish through the app routes require a multi-factor sign-in from the last 15 minutes, the same check upload already uses. The prototype page is gone, work areas carry noindex, the digest tolerates a late run, bot 5xx errors reach Sentry, and the heartbeat covers every completion path. The four 19 October owner decisions are recorded under docs/decisions/.

How: the search route reuses rejectPatientDetailQuestion; the dashboard widens its existing check to the modes that call /api/search. A new requireRecentAdministratorAssurance reads claims from the token the request presented and reuses assertTrustedAdministratorAssurance. Work-area layouts export PRIVATE_APP_ROBOTS_METADATA.

FindingChange
F-01Patient-detail check on document and differentials search, server and client
F-15Session-expired errors map to a "Sign in again" panel, no Retry
F-12Recent MFA for document DELETE and site-content publications POST (route level)
F-14Delete public/referral-board-mockup.html
F-30noindex for roster, my-day, admin, on-call, cme, teaching, open-shifts
F-18Ops digest joins samples up to two schedule intervals apart; docs say six-hourly
F-19Sentry keeps bot-agent server errors (5xx, unhandled, error/fatal)
F-33Worker heartbeat on managed-generation and strict-enrichment completion

Held back: F-25 (On Call example rows in shared view). The owner decided on 19 October to leave it as is; see docs/decisions/2026-10-19-on-call-example-rows-stay-shared.md.

Areas touched: App experience, Data platform and access, Clinical reference content, Source intake and indexing, Answer engine, Personal practice, Knowledge and records, Prototypes

RAG impact: no retrieval behaviour change β€” the search route refuses patient-detail queries before retrieval runs; no ranking, selection or retrieval file changed.

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains PsychSift Production (sjrfecxgysukkwxsowpy)
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

Verification

  • Checks run:
    • Focused route and component tests (search route, error panel, search utils, crawler policy, private access routes, site-content publication route, ops digest, operational alerts, Sentry filter, worker health): all passed.
    • npm run verify:cheap: exit 0. Lint and typecheck passed, then "Test Files 2011 passed (2011)", "Tests 32661 passed | 2 skipped (32663)"
    • Remaining Static PR check steps run locally after the snapshot fix (clinical hazard controls, production readiness CI, function grants, owner scope and others): all exit 0.

Not run locally: browser suites (CI selects them by scope), SQL tests (no database change).

Risk and rollout

  • Risk: administrators must have signed in with MFA in the last 15 minutes to delete a document or publish site content, otherwise they get a 403 and need to sign in again. The patient-detail check may occasionally refuse a search that only looks like a patient detail; the message says what to remove.
  • Known gap (F-15, found after review): on the dashboard, a 401 marks the session expired, which invalidates the request before the error is shown, so the dashboard's current-request guard drops the error and the new "Sign in again" panel is not reached from that path yet. This is unchanged from before this PR (the old message was dropped the same way). The same guard also drops the answer timeout error; the Design and UX audit thread fixes both in one follow-up change.
  • Known gap (review finding): the site-content publish, retire and reconciliation-plan database functions are still callable directly by an authenticated administrator token, and they check the administrator role but not recent MFA. So the 15-minute check covers the route, not a direct database call. The database fix is drafted in #3677 for owner approval.
  • Rollback: revert this PR. No data or schema change.
  • Provider or production effects: None

Notes

  • Audit report: /mnt/project-files/reviews/2026-10-19-repository-audit.md (project files).

πŸ€– Generated with Claude Code

https://claude.ai/code/session_01XpAQzPLSw4ncZyrFjoWBA3