Harden auth and ingestion privacy/reliability paths - #175
Merged
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The fake sb_secret_live_ fixture in tests/privacy.test.ts exists to prove safeErrorLogDetails redacts secrets; commit 92cd8ac in this branch's history trips the generic-api-key rule on every scan even though the tip was already rewritten to avoid it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BigSimmo
enabled auto-merge (squash)
July 2, 2026 12:03
Uh oh!
There was an error while loading. Please reload this page.
BigSimmo pushed a commit
that referenced
this pull request
Jul 31, 2026
Two small things, both about not hiding information. A zero-count facet used `disabled`, which drops it out of the tab order. A keyboard or screen-reader user then loses the row entirely and never learns why it went quiet — and a `title` on a disabled control is not reliably announced. It now uses `aria-disabled` with the click guarded, so the row stays focusable and carries an sr-only explanation via `aria-describedby`. That is the disabled-affordance pattern docs/wiring-conventions.md already describes. `#175` corrects `#171`, which is already on main. `#171` claims the documents source-type control duplicates the `Document type` facet group. It does not, and the claim was made from a shared word rather than from the code: `resultTypeTabs`/`filterMatchesByResultType` filter on artefact properties — tableCount, imageCount, a .pdf extension — while the `Document type` facet comes from `document_type` labels meaning policy, guideline, form. A guideline containing a table is both. They are complementary axes. The real duplication is the scope chip `tables` against the source-type `Tables` tab. The merge `#171` recommends is still worth doing, but source-type becomes its own group rather than being absorbed, and the scope chips are the part that folds away. `#171`'s separate claim that `Sources` is navigation stands. The correction is appended rather than edited in: the ledger is append-only, and `#158` is precedent for keeping a withdrawn finding on record so it is not re-filed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Akwz3Sdms8uJ5AkDt3CduY
BigSimmo added a commit
that referenced
this pull request
Jul 31, 2026
#179: the full catalogue silently went from a single minified line to 18,400 pretty-printed ones when the modality scrub routed it through syncTarget. Measured +123 KB raw but only +3.4 KB gzipped, so the real cost is ~37,000 lines of git churn per data revision — set against reviewable diffs on a 205-record clinical dataset, which is probably the better trade. Recorded so the format is a decision rather than a side effect. #180: that same change made the generator write its curated output back over the file it reads as source. It is stable only because curatedModality is a fixed point, and it matters because #175 asks someone to hand-curate modality values in exactly that file — an edit the next run could discard with no gate to catch it, since --check compares against what the generator would produce. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
11 tasks
BigSimmo added a commit
that referenced
this pull request
Aug 13, 2026
…#180) and serve aliases by rewrite (#177) (#1886) * fix(therapies): stop the catalogue generator consuming its own output build-therapies-index.mjs read public/therapy-compass-data/therapies.json as its source and also wrote that same path as legacyFullTarget. Source and target were one file, so every run consumed its own output. That was not merely untidy. curatedFull nulls every tag-echo modality (curatedModality), so the first run overwrote the author's raw modality values with the scrubbed ones, and every later run re-read the scrubbed copy. It survived only because the scrub happens to be idempotent — the raw input was still destroyed, recoverable from git history alone. Move the hand-edited catalogue to src/data/therapies-source.json, outside the directory this generator writes, and read only from there. The file in public/therapy-compass-data/ is now output, never input. Also add the new path to .prettierignore. At its old path it was covered by the public/therapy-compass-data/ entry; without an entry Prettier pretty-prints the compact single-line catalogue into ~17k lines, which is the churn #179 fixed on the generated side. Verified: regenerated output is byte-identical to the previous alias (hashed filenames unchanged), the source stays byte-identical to its original across two further re-runs, check:therapy-data-index passes, and the 28 therapy contract tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STG6AU5J4gxrFJagP4pRti * perf(therapies): serve catalogue aliases by rewrite instead of duplicating bytes public/therapy-compass-data/ shipped each catalogue twice: therapies.json, therapies-index.json and therapies-home.json were written byte-identical to their content-addressed twin. Git stores one blob per identical pair, so history was unaffected, but the working tree and every Docker image carried both — 2.81 MB, and 5.34 MB while the one-deploy grace generation is retained. The alias URLs themselves are load-bearing: useTherapyData falls back to them when a bundle older than the grace generation names a hashed file that no longer exists, so they cannot simply be dropped. Serve them from next.config.ts rewrites onto the current hashed filename instead, and stop writing the files. afterFiles rather than beforeFiles: no file exists at the alias paths now, so the rewrite is reached once the static handler finds nothing, and nothing legitimate is shadowed. build-therapies-index.mjs --check now fails if an alias file reappears, since a real file would win over an afterFiles rewrite and then go stale at the next regeneration. The generator writes content-addressed assets directly from the generated bytes rather than copying a just-written alias, so projectionBytes/fullCatalogueBytes are now the single definition of each payload's exact bytes. Verified against a running server: all three alias URLs return 200 with content byte-identical to their hashed asset; aliases keep Cache-Control max-age=0, must-revalidate while the hashed asset keeps max-age=31536000, immutable, so the alias does not inherit the destination's immutable policy; the retained grace generation still returns 200. Hashed filenames are unchanged by this refactor, proving the direct-write path is byte-identical. public/therapy-compass-data/ drops from 8.0M to 5.3M. npm run build succeeds and the stray-alias guard fires. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STG6AU5J4gxrFJagP4pRti * docs(issues): close#180 and #177, and correct the paths they moved Both rows are resolved by the two preceding commits. Also corrects three rows that cited the catalogue paths this work moved — docs:check-links caught them. #175 mattered most: it instructed a future reader to curate modality values in public/therapy-compass-data/therapies.json, which no longer exists. It now names src/data/therapies-source.json, the only hand-edited catalogue file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STG6AU5J4gxrFJagP4pRti * docs(ledger): record the review for this branch Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STG6AU5J4gxrFJagP4pRti * fix: ship generated therapy assets with app runner * test: cover every next config runner import * fix(docs): update therapy catalogue references * fix(ci): reconcile therapy docs with ledger inbox --------- Co-authored-by: Claude <noreply@anthropic.com>
BigSimmo added a commit
that referenced
this pull request
Aug 17, 2026
7 tasks
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 freeto 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
Verification
npm run verify:cheapnpm run verify:uiwhen UI, routing, styling, browser behavior, reduced-motion, or forced-colors behavior changednpm run verify:releasebefore release or handoff confidence claimsnpm run format:checknpm run check:production-readinesswhen clinical workflow, privacy, environment, Supabase, source governance, or deployment behavior changednpm run check:deployment-readinesswhen deployment startup, hosting, or rollout behavior changedClinical Governance Preflight
Complete this section when the change touches ingestion, answer generation, search/ranking, source rendering, document access, privacy, production env, or clinical output.
Clinical KB Database(sjrfecxgysukkwxsowpy)Notes
npm run verify:cheapremains blocked by existing repository-wide type-check debt outside this scoped security/reliability work..impeccable/,docs/superpowers/plans/) were intentionally left out of this PR.