fix: remediate 2026-07 repo audit findings (clinical answer path, data integrity, privacy) - #123
Merged
Merged
Conversation
…trieval, and ingestion paths Full multi-agent audit (docs/audit/repo-audit-2026-07-01.md): 42 verified findings fixed or explicitly dispositioned, then hardened by an adversarial review of the fix diff itself (R1-R13). Highlights: - Answer path: numeric-verification corpus now covers retrieval synopses, image table text, and table-fact metadata snippets (H1); sanitizer no longer deletes clinical threshold sentences (H2); copied ward-note tables share the on-screen conservative normalization + low-confidence caveat, with no duplicated markdown header or ragged-row misalignment (H4/M8/M16, and AccessibleTable parity). - Retrieval: deriveConfidence scoped to cited chunks (M1); word-boundary intent signals with digit-attached dose support (M2/M3); retrieval-selection aligned verbatim with PR #118 relevance-first contract (H3/L4 superseded). - Data integrity: DELETE blocks pending reindex jobs (M9); deep-memory builds embeddings before deleting old memory and fails closed on generation-lookup errors (M11/L8); perceptual hash 16-bit -> 192-bit ph2 (M12); new migration 20260702000000 preserves legacy NULL-generation artifacts unless replaced, mirrored in the worker fallback (M13); chunking forward-progress guard and whole-line page-noise anchoring (M14/M17). - Privacy/security: optional HMAC-keyed query hashing via RAG_QUERY_HASH_SECRET (M15); non-string log fields serialized before redaction (L12); timing-safe edge-function secret compare and fail-fast 4xx (L20/L7); stale-search guard incl. progress updates in ClinicalDashboard (M10/R9). - Scripts/config: strict CLI arg validation (L1/L2/R13), classification fixes (M4-M7/R10), dead-code removal (L15-L17), CSP host dedup (L13). Verification: tsc clean; vitest 701 passed / 2 skipped (incl. ~13 new regression tests); Deno edge-function typecheck clean. Lint not run locally (eslint missing from worktree node_modules; pre-existing lockfile drift). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # src/app/api/search/route.ts # src/components/ClinicalDashboard.tsx
format:check now passes repo-wide (CI does not gate on it, so drift had accumulated on main as well; includes the audit report and merge-touched sources). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Remediates a broad set of clinical-safety, data-integrity, and privacy/security findings across the RAG answer path, ingestion/indexing pipeline, Supabase schema/RPCs, and supporting UI/scripts, with regression tests and a new migration to preserve legacy artifacts safely during reindex commits.
Changes:
- Expands numeric/quote verification and table-handling so the verification corpus and clipboard/table outputs match the model-visible/cited corpus (synopsis, image table text, table-fact metadata), and preserves low-confidence caveats.
- Hardens indexing/data-integrity paths (generation commit preservation rules, deep-memory rebuild ordering, delete guards, chunking forward-progress, perceptual hash upgrade).
- Improves privacy/security/ops robustness (optional HMAC query hashing, safer log redaction for non-strings, timing-safe edge secret compare, fail-fast on non-retryable OpenAI 4xx, stricter CLI arg parsing).
Reviewed changes
Copilot reviewed 51 out of 51 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| worker/main.ts | Mirrors the new “preserve legacy artifacts unless replaced” rule in the worker fallback deletion logic; documents image I/O trade-off. |
| tests/ward-output.test.ts | Adds regression coverage for clipboard/ward-note table normalization and caveat parity. |
| tests/supabase-schema.test.ts | Reformats assertions for schema/migration hybrid function ordering checks. |
| tests/source-text-sanitizer.test.ts | Adds regression coverage for keeping threshold sentences while still dropping title-noise fragments. |
| tests/retrieval-selection.test.ts | Adds coverage for clamping annotated hybrid_score and documents audit disposition context. |
| tests/rag-provider.test.ts | Minor formatting update around rate-limit classification test. |
| tests/rag-content-accuracy.test.ts | Minor formatting update for unbolding verified figures test. |
| tests/private-access-routes.test.ts | Extends DELETE guard test to cover both pending and processing ingestion jobs. |
| tests/openai-error-mapping.test.ts | Minor formatting update for quota-message classification test. |
| tests/image-filtering.test.ts | Updates tests to assert the new ph2 perceptual-hash format. |
| tests/document-organization.test.ts | Adds regression tests for title-only site detection and BMJ false-attribution avoidance. |
| tests/deep-memory.test.ts | Updates behavior expectation to fail-closed when committed-generation lookup fails. |
| tests/clinical-search.test.ts | Adds regression coverage for word-boundary intent signals and dose/visual focus detection. |
| tests/chunking.test.ts | Adds regression tests for overlap>=chunkSize termination and inline page-reference preservation. |
| tests/answer-verification.test.ts | Adds regression tests covering synopsis-only and image-table-text-only numeric verification. |
| tests/answer-prose-runons.test.ts | Minor formatting update for run-on sentence polishing test. |
| supabase/schema.sql | Updates commit_document_index_generation semantics in the schema snapshot to preserve legacy artifacts unless replaced. |
| supabase/migrations/20260702000000_commit_generation_preserve_legacy_artifacts.sql | Introduces migration redefining commit_document_index_generation to avoid destroying legacy NULL-generation artifacts unless replacements exist. |
| supabase/functions/indexing-v3-agent/index.ts | Adds timing-safe secret compare and fail-fast behavior for non-retryable OpenAI 4xx in embedding fetches; updates auth call site to await. |
| src/lib/ward-output.ts | Normalizes copied tables via normalizeAccessibleTable, preserves low-confidence caveat, avoids header duplication and column shifts; avoids dangling headings. |
| src/lib/visual-intelligence.ts | Derives medications from clinical vocabulary category matches instead of a hardcoded allowlist. |
| src/lib/validation/form-data.ts | Clarifies preprocess behavior so non-string multipart values are rejected (not silently coerced). |
| src/lib/source-text-sanitizer.ts | Adds threshold-signal detection to prevent dropping threshold-bearing fragments; adjusts provenance scoring to avoid gating regressions. |
| src/lib/rag.ts | Scopes confidence derivation to cited chunks; expands table-fact quote corpus to include prompt-visible metadata snippet fields. |
| src/lib/rag-provider.ts | Type formatting cleanup for ProviderFailureKind union. |
| src/lib/query-privacy.ts | Adds optional HMAC-SHA256 query hashing keyed by RAG_QUERY_HASH_SECRET (falls back to legacy SHA-256 when unset). |
| src/lib/privacy.ts | Serializes non-string log fields before redaction to avoid leaking URLs/emails/secrets in structured fields. |
| src/lib/ingestion.ts | Simplifies retryable-ingestion error logic and documents duplicate-key/manual-recovery path. |
| src/lib/image-filtering.ts | Upgrades lightweight perceptual hash from ph1 (16-bit) to ph2 (192-bit) to reduce collisions. |
| src/lib/evidence.ts | Allows callers to pass precomputed relevance/visualEvidence into buildSmartPanel to avoid recomputation. |
| src/lib/evidence-relevance.ts | Fixes unreachable “none” verdict; uses matched terms and score to avoid overstating evidence. |
| src/lib/env.ts | Adds optional RAG_QUERY_HASH_SECRET env var with minimum length constraint. |
| src/lib/document-tags.ts | Removes misleading dead branches and clarifies label-noise behavior. |
| src/lib/document-organization.ts | Fixes BMJ attribution rule, expands evidence text to include title/filename with bracket stripping, and corrects fallback gating on confirmed candidates. |
| src/lib/document-index-units.ts | Prevents “yes/no” from classifying table-like images as flowcharts unless structurally non-table. |
| src/lib/deep-memory.ts | Computes embeddings before deleting existing rows; fails closed on committed-generation lookup errors. |
| src/lib/cross-document-synthesis.ts | Removes dead ternary and simplifies maxPerDocument assignment. |
| src/lib/clinical-search.ts | Makes intent-signal matching word-boundary aware (with digit-adjacent doses) and preserves explicit dose signals despite escalation terms. |
| src/lib/chunking.ts | Anchors page-noise stripping to whole lines and enforces forward progress when overlap>=chunkSize. |
| src/lib/answer-verification.ts | Extends verification corpus to include retrieval_synopsis, image table text, and table-fact metadata snippet fields. |
| src/lib/answer-ranking.ts | Fixes bold-segment capping to count per-occurrence “free passes” rather than Set-based bypass. |
| src/components/ClinicalDashboard.tsx | Adds request sequencing guard so only the latest in-flight search updates UI state and progress. |
| src/components/AccessibleTable.tsx | Ensures markdown-parsed tables don’t incorrectly re-emit headers as data rows; keeps parity with clipboard normalization. |
| src/app/api/search/route.ts | Avoids recomputing relevance/visual evidence by caching and passing precomputed values through to smart panel and payload. |
| src/app/api/documents/[id]/route.ts | Blocks permanent delete when ingestion_jobs are pending or processing; improves the conflict message. |
| scripts/recover-ingestion-queue.ts | Replaces permissive arg parsing with strict validation (unknown flags/missing values/invalid ints fail). |
| scripts/purge-query-logs.ts | Makes CLI parsing fail loudly on unknown flags. |
| next.config.ts | Deduplicates CSP connect-src Supabase host entry (keeps wildcard). |
| docs/rag-hybrid-findings-and-todo.md | Markdown formatting tweaks (indentation/italics changes); note: current diff introduces broken indentation in one section. |
| docs/audit/repo-audit-2026-07-01.md | Adds the audit report documenting findings, fixes, verification, and dispositions. |
| .env.example | Documents the new optional RAG_QUERY_HASH_SECRET env var and its implications. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
78
to
+79
| fires for document_lookup/broad_summary (`shouldUseSecondStageRerank` needs `topScoresClose && | ||
| hasVisualEvidence`, `rag.ts:548`). Widening it (RC10) could restore discrimination among the | ||
| hasVisualEvidence`, `rag.ts:548`). Widening it (RC10) could restore discrimination among the |
Comment on lines
+83
to
+84
| hnsw.ef_search='100'` on the three sql functions; **hosted Supabase denies it (`42501 permission | ||
| denied to set parameter`)** — the RC11 blocker. The only method hosted allows is the plpgsql-wrapper |
13 tasks
BigSimmo
added a commit
that referenced
this pull request
Jul 30, 2026
The open-items table was restored by hand after a #1415 conflict merge wiped it, which left it off Prettier's formatting. verify:pr-local's format:changed gate caught it. Table integrity re-verified: 59 open rows, my two rows intact as #123 and #124, no duplicate IDs, ledger guard passing at 1287 records. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/audit/repo-audit-2026-07-01.md), hardened by an adversarial review of the fix diff itself (R1–R13, all resolved).20260702000000_commit_generation_preserve_legacy_artifacts.sql(not yet applied to the live DB — apply via normal flow, thenreindex:health+check:indexing), mirrored in the worker fallback; chunking forward-progress guard + whole-line page-noise anchoring.RAG_QUERY_HASH_SECRET(recommend setting wherever real queries are logged); non-string log fields serialized before redaction; timing-safe edge-function secret compare; fail-fast on non-retryable OpenAI 4xx.retrieval-selection.ts+ its governance contract test are aligned verbatim with PR RAG optimisation: answer quality (P1-P10), v17 numeric grounding, offline fallback, hybrid RPC hardening + golden-recall regression fix #118's relevance-first design (audit H3/L4 superseded by the measured golden-eval contract; no metadata weighting reintroduced).origin/main(through PR Merge codex/RAG_FIX modes (Differentials/Services/Forms/Favourites) restyled to Clinical White theme #120) into the branch; conflicts insearch/route.tsandClinicalDashboard.tsxresolved onto main's source-library/differentials refactor.Verification
npm run verify:cheap— pass on the merged tree after cleannpm ci(lint ✅, typecheck ✅, vitest 785 passed / 2 skipped across 98 files)npm run verify:ui— not run locally; CI's chromium e2e gate covers the UI changes (ClinicalDashboard request guard, AccessibleTable header-source parity)npm run verify:release— not run (no release claim)npm run format:check— pass (drifted files on both branch and main formatted)npm run check:production-readiness— not run locally (no.envin this worktree);check:production-readiness:ciruns in CI. Post-merge: apply the new migration, then runcheck:production-readiness+reindex:health+check:indexingnpm run check:deployment-readiness— covered by CIAlso run locally:
npm run check:edge:functions(Deno) — pass.Clinical Governance Preflight
Clinical KB Database(sjrfecxgysukkwxsowpy)RAG_QUERY_HASH_SECRETis server-only (notNEXT_PUBLIC_*); reviewer-verified no client-bundle leakdocs/clinical-governance.mdare unchanged by this PRNotes
docs/audit/repo-audit-2026-07-01.md.retrieval-selection.tsmatches origin/main byte-for-byte, so the 23/23 contract is unchanged.🤖 Generated with Claude Code