Skip to content

Overnight sweep: small security, privacy and correctness fixes from the audits - #3849

Merged
BigSimmo merged 4 commits into
mainfrom
claude/project-thread-wy6h7x
Oct 26, 2026
Merged

BigSimmo merged 4 commits into
mainfrom
claude/project-thread-wy6h7x

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Requested by Josh · project thread

Summary

Ordinary code fixes for open audit rows that were still present on main (checked against 4705d27a7). No database migration, no protected retrieval file, no clinical wording, no CI workflow file.

  • Admin Requests: a request flagged as holding a patient detail no longer puts its message into the Email draft href (only onClick guarded it, so middle click or copy link skipped the check). Security test row.
  • Teaching: a supervisor's direct EPA record refuses a note that looks like a patient detail or is too long, matching the request path. Security test row, new test.
  • scripts/classify-documents.ts keeps a reviewer's hidden / label_review_status on regenerated labels and pages the existing-label read. Whole-codebase row.
  • scripts/embed-registry-records.ts pages each record loader past the 1000-row cap. Whole-codebase row.
  • scripts/sql/operator-export-site-content-population.sql no longer emits one all-null record when the active release is empty (operator read-only query, not a migration). Whole-codebase row.
  • scripts/compare-retrieval-eval.ts --fail-on-regression fails on a doc or content recall drop or recall below the pinned 1.0. Security test row, new tests.
  • scripts/eval-rag.ts refuses unknown or mistyped flags, and --fail-on-threshold fails when no case was selected. Security test row.
  • On Call editor: the clearWhenEmpty comment now matches what handleSave does (every emptied optional field clears). Whole-codebase row, comment only.
  • /?mode=medications and /?mode=medication now open Medication mode instead of silently falling back to Answer (design audit D26-52, a11y A11Y-13 wrong title). New tests.
  • issues:reconcile repairs the mojibake arrow in the ledger preamble (#WWTRM5). A batch with no requests stays byte for byte, so check:ledger-write-discipline still matches every other PR. New tests.
  • DSM search, Therapy search and Therapy recommend: result titles no longer skip a heading level (A11Y-12, D26-43). Recommend's "Ranked clinical matches" label becomes the h2 it already looks like; the two search pages get a visually hidden h2. No visual change.

Already fixed on main, no change needed: changed-file names injecting CI scope outputs (ci-change-scope.mjs refuses control characters), canary case summary "all passed" for a missing section, bulk reindex refresh after a failed batch (the active use-dashboard-bulk-actions hook does it), disallowed ARIA listitem on article (fixed in cf4a754), /api/local-project-id on the deployed site (LS-14, returns 404).

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

RAG impact: no retrieval behaviour change — no ranking-protected file changed. The eval scripts touched only fail more strictly.

Verification

  • Checks run: npm run typecheck pass; eslint and prettier clean on changed files; full npm run test twice (before and after the heading commit): Test Files 2 failed | 2120 passed, the only failures are cloud-platform-smoke (wants npm 11.17.0) and rag-plan-package-parity (wants origin/main), both known container-environment failures, unrelated to this diff.

Risk and rollout

  • Risk: low. The two operator scripts and the eval scripts only run by hand. The Requests change only affects requests already blocked.
  • Rollback: revert the merge commit.
  • Provider or production effects: None. Nothing was run against live services.

Clinical Governance Preflight

  • 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

Evidence / not applicable / unresolved:

  • Two changes tighten patient-detail checks. No clinical content changed.

Notes

  • Josh gave a blanket go-ahead for the overnight sweep and asked for PRs to merge when able.

🤖 Generated with Claude Code

https://claude.ai/code/session_01A3iqZF1bkjWhCnrvYZPYJo

Summary by CodeRabbit

  • Bug Fixes
    • Legacy medication mode links now redirect to prescribing while preserving other query parameters.
    • Draft requests with patient-related problems no longer expose a mail link.
    • Corrected damaged arrow characters in nonempty ledger updates.
    • Empty evaluation runs now fail when threshold checks are required.
  • Accessibility
    • Added heading structure to diagnosis and therapy results, and promoted ranked clinical matches to a heading.
  • Validation
    • Direct EPA notes that contain patient details or exceed the length limit are rejected.

- Admin Requests: a request flagged as holding a patient detail no longer
  puts its message into an Email draft link (only onClick guarded it).
- Teaching: a supervisor's direct EPA record now refuses a note that looks
  like a patient detail or is too long, matching the request path.
- classify-documents keeps a reviewer's hidden label hidden and pages the
  existing-label read so no label loses its review state.
- embed-registry-records pages every record loader past the 1000-row cap.
- Operator export SQL no longer emits one all-null record for an empty release.
- compare-retrieval-eval --fail-on-regression now fails on a doc or content
  recall drop or recall below the pinned 1.0.
- eval-rag refuses unknown or mistyped flags, and --fail-on-threshold fails
  when no case was selected.
- On Call editor: correct the clearWhenEmpty comment to match handleSave.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A3iqZF1bkjWhCnrvYZPYJo
…n reconcile

- /?mode=medications and /?mode=medication now open Medication mode instead of
  silently falling back to Answer (design audit D26-52, a11y A11Y-13 title).
- issues:reconcile repairs the mojibake arrow in the ledger preamble (#WWTRM5).
  A batch with no requests stays byte for byte, so other PRs still match.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A3iqZF1bkjWhCnrvYZPYJo
@supabase

supabase Bot commented Oct 26, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@BigSimmo BigSimmo self-assigned this Oct 26, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T18:20:04.616516Z b7707fb PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 85003d2 and 26a9e22.

Files selected for processing: 17
  • scripts/classify-documents.ts
  • scripts/compare-retrieval-eval.ts
  • scripts/embed-registry-records.ts
  • scripts/eval-rag.ts
  • scripts/ledger-inbox.mjs
  • scripts/sql/operator-export-site-content-population.sql
  • src/components/dsm/dsm-search-page.tsx
  • src/components/on-call/on-call-entry-editor.tsx
  • src/components/therapy-compass/screens/recommend-screen.tsx
  • src/components/therapy-compass/screens/search-screen.tsx
  • src/components/work-screens/admin/requests-page.tsx
  • src/lib/legacy-home-redirect.ts
  • src/lib/teaching/assessments/model.ts
  • tests/compare-retrieval-eval.test.ts
  • tests/ledger-inbox.test.ts
  • tests/own-page-mode-home.test.ts
  • tests/teaching-assessments-model.test.ts

Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Walkthrough

This pull request updates data pagination and metadata handling, evaluation checks, ledger repair, export aggregation, accessibility headings, request actions, legacy mode redirects, and direct EPA note validation. It also updates an on-call editor comment to describe existing save behavior.

Changes: Generated label classification

Layer / File(s) Summary
Page generated labels and preserve metadata
scripts/classify-documents.ts
Generated labels are loaded in ordered pages. Upserts retain label_review_status and hidden from existing metadata.

Registry record pagination

Layer / File(s) Summary
Add shared paging to record loaders
scripts/embed-registry-records.ts
Registry, medication, and differential loaders use a shared paging helper and add id as the final sort key.

Retrieval recall gate

Layer / File(s) Summary
Check recall and gate the command
scripts/compare-retrieval-eval.ts, tests/compare-retrieval-eval.test.ts
The script reports document and content recall failures and sets a failing exit status when the regression flag is enabled. Tests cover the recall conditions.

RAG evaluation argument checks

Layer / File(s) Summary
Validate arguments and selected cases
scripts/eval-rag.ts
Argument parsing rejects positional and unknown flags. Threshold checking fails when no cases are selected.

Ledger encoding repair

Layer / File(s) Summary
Repair markdown before applying requests
scripts/ledger-inbox.mjs, tests/ledger-inbox.test.ts
Nonempty request batches repair the known corrupted arrow sequence. Tests also verify that an empty batch leaves the input unchanged.

Population export aggregation

Layer / File(s) Summary
Filter null release rows
scripts/sql/operator-export-site-content-population.sql
The JSON aggregate excludes rows with a null release_id.

Search heading hierarchy

Layer / File(s) Summary
Add headings to search and recommendation content
src/components/dsm/dsm-search-page.tsx, src/components/therapy-compass/screens/search-screen.tsx, src/components/therapy-compass/screens/recommend-screen.tsx
The diagnosis and therapy search screens add level-two headings. The recommendation screen uses an h2 for “Ranked clinical matches.”

On-call editor save behavior comment

Layer / File(s) Summary
Update the save behavior description
src/components/on-call/on-call-entry-editor.tsx
The comment now describes how empty optional fields and list and escalation-step fields are saved.

Draft request email action

Layer / File(s) Summary
Select the email action for blocked requests
src/components/work-screens/admin/requests-page.tsx
Draft requests with a patient-related problem use a button instead of a mailto link.

Legacy home mode redirects

Layer / File(s) Summary
Redirect legacy medication modes
src/lib/legacy-home-redirect.ts, tests/own-page-mode-home.test.ts
The medication and medications mode values redirect to prescribing. Tests verify query preservation.

Direct EPA note validation

Layer / File(s) Summary
Validate notes before recording
src/lib/teaching/assessments/model.ts, tests/teaching-assessments-model.test.ts
Direct EPA recording rejects notes that fail text validation. Tests cover patient-identifying and overlong notes.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Possibly related PRs

  • BigSimmo/PsychSift#3790: Adds review carry-forward and generation snapshots for generated indexing data; this pull request also preserves review metadata during label updates.
  • BigSimmo/PsychSift#3781: Adds protected retrieval evaluation requirements; this pull request adds a recall gate to the comparison script.
  • BigSimmo/PsychSift#3780: Records the ledger arrow encoding issue; this pull request implements the corresponding repair.

Suggested labels: 🕐 40+ Minutes

Suggested reviewers: claude

Merge Risk: Minimal · up to 26a9e

This change contains small security, privacy and correctness fixes with no identified merge-blocking issue. Normal checks apply, including confirming that the two reported test failures are environmental.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 16 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly summarizes the pull request as a set of security, privacy, and correctness fixes from audits. It is concise and related to the broad changeset.
Description check Passed The description includes the required Summary, Verification, Risk and rollout, Clinical Governance Preflight, and Notes sections. It documents the changed areas, test results including known unrelated…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description includes the required Summary, Verification, Risk and rollout, Clinical Governance Preflight, and Notes sections. It documents the changed areas, test results including known unrelated failures, risks, rollback, production effects, and governance evidence.

Full details: Docstring Coverage

Explanation

Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 16 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.

Comment @coderabbitai help to get the list of available commands.

@gitar-bot

gitar-bot Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Gitar is working

Verification

Rules No rules evaluated

Functional validation Not enabled

Set up

Auto-approval Not enabled

Set up

Gitar

@claude

claude Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Claude encountered an error after 2s —— View job


I'll analyze this and get back to you.

…11Y-12, D26-43)

Recommend's 'Ranked clinical matches' label becomes the h2 it looks like, and
Therapy search and DSM search results get a visually hidden h2 above the h3
result titles. No visual change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A3iqZF1bkjWhCnrvYZPYJo
@BigSimmo
BigSimmo enabled auto-merge October 26, 2026 18:53

Copy link
Copy Markdown
Owner Author

Lighthouse budget failed on 26a9e22. This looks like runner noise, not this PR.

  • The only breach is desktop /documents/search: total blocking time was 93 ms against a 43 ms baseline. Every other page and metric stayed within tolerance.
  • The confirmation runs that should settle a breach did not run. Lighthouse crashed with NO_NAVSTART (a trace recording error), so the breach was never confirmed.
  • This PR does not touch the document search page or anything it loads. The UI changes are heading tags on the DSM and Therapy pages, plus one redirect rule.

The workflow run is still in progress, so the failed job can't be re-run yet. I'll re-run it once when the run finishes.


Generated by Claude Code

@BigSimmo
BigSimmo merged commit 2c5c50d into main Oct 26, 2026
55 of 58 checks passed
@BigSimmo
BigSimmo deleted the claude/project-thread-wy6h7x branch October 26, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants