Skip to content

Open the developer area with a bookmarked link instead of a sign-in - #2741

Closed
BigSimmo wants to merge 2 commits into
mainfrom
claude/dev-section-password-removal-8y3slc
Closed

Open the developer area with a bookmarked link instead of a sign-in#2741
BigSimmo wants to merge 2 commits into
mainfrom
claude/dev-section-password-removal-8y3slc

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • The owner asked for a Developer Section that does not ask him to sign in. Deleting DeveloperAreaGate would have published the task ledger, the hazard notes and the Ward Flow / Care Plan / Caring Contact prototypes to anyone visiting psychiatry.tools — #L30 reintroduced on purpose — so this adds a third credential beside the administrator claim rather than removing it.
  • DEVELOPER_AREA_ACCESS_KEY (server-only, 32-character floor) is presented once per device as /mockups/development?devkey=…. src/proxy.ts verifies it, sets a signed cookie, and redirects the key out of the URL so it does not survive in the address bar, the shared history entry, or a Referer header sent onward.
  • The cookie carries v1.<issuedAt>.<HMAC-SHA256 over both, keyed by the secret> — not the key. A stolen cookie cannot be turned back into the secret, and cannot be re-dated to extend itself because the signature covers the issue time. The proxy re-issues it on every verified visit, inside the ~400-day ceiling browsers clamp Set-Cookie to, so a device used once a year never sees the sign-in screen again.
  • Additive and fails closed. Unset, under-strength, malformed, expired, or signed under a rotated key all fall through to the existing sign-in screen. NEXT_PUBLIC_MOCKUPS_ENABLED is untouched. Rotating the key in Railway revokes every device at once.
  • Reaching the page is all it grants. resolveHubEnvironmentFacts and the corpus-health reader still call isAdministratorUser themselves and degrade to "unavailable" for a link holder — the link is a convenience credential that can be forwarded in a message; the corpus is the clinical library. The code and docs/developer-area-access.md both say not to "simplify" that away.
  • check:production-readiness now fails a NEXT_PUBLIC_DEVELOPER_AREA_ACCESS_KEY (Next.js would inline the secret into the client bundle) and states an enabled key as a release-time fact.
  • New docs/developer-area-access.md covers setup, per-device use, what the link does not grant, and revocation.

Verification

  • npm run verify:cheap — exit 0. [diff-integrity] PASS — 5 changed test file(s), 52 -> 76 test case(s); [mockup-retirement] PASS — 82 mockup route(s) indexed; sitemap:check clean. Its one advisory (check:repo-awareness-snapshot behind, from the new document) is fixed in the second commit — the check now reports [repo-awareness] in step with data/repo-awareness-snapshot.json.
  • npm run typecheck[gate-receipts] recorded a pass for "typecheck:internal" (7464 input files)
  • npm run lint[gate-receipts] recorded a pass for "lint:internal" (7464 input files)
  • npx prettier --check .All matched files use Prettier code style! (whole tree, committed)
  • Four affected suites green: tests/developer-area-link-access.test.ts (12 new), tests/proxy.test.ts (33), tests/developer-area-access.test.ts, tests/developer-area-gate.dom.test.tsx, plus tests/production-readiness-offline.test.ts (14).
  • npm run verify:pr-localVerification not run: deferred to CI, which runs the same risk-routed selection on this diff.
  • npm run verify:uiUI verification not run: the only component change is one added branch in DeveloperAreaGate, a Server Component that renders existing children; no styling, routing chrome, or client behaviour changed. CI runs the browser suite on this diff.
  • npm run check:production-readinessVerification not run: provider-backed, needs explicit approval. The new developerAccessKeyProductionRisk predicate it calls is covered offline in tests/production-readiness-offline.test.ts.

Risk and rollout

  • Risk: a new credential for a subtree that reaches the live site. The failure mode that matters is failing open, so every unset/short/malformed/wrong-key/expired path is asserted to deny in tests/developer-area-link-access.test.ts, and tests/proxy.test.ts asserts no cookie is minted for a wrong key, for an unconfigured deployment, or on a look-alike path such as /mockups/care-plan-archive. The secondary risk is key leakage: the cookie is HttpOnly, scoped Path=/mockups so it is never sent on a clinical request, and the URL secret is stripped by redirect whether or not it verified.
  • Rollback: unset DEVELOPER_AREA_ACCESS_KEY. The feature is off and administrator sign-in is the only way in, with no code change and no deploy.
  • Provider or production effects: None. No provider call is added — the cookie path deliberately answers without a Supabase round trip. No migration, no schema change, no Railway mutation performed here; enabling the feature is an operator setting a variable.
  • RAG impact: none — no retrieval, ranking, selection, chunking, or answer-contract surface is touched.

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use — unchanged
  • No patient-identifiable document workflow was introduced or expanded; the gated prototypes remain synthetic
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy) — untouched
  • Service-role keys and private document access remain server-only; the new key is server-only by name and by a readiness check that fails a NEXT_PUBLIC_ copy
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behaviour remain conservative — a link holder without the administrator claim reads "unavailable", never a number nothing read
  • Deployment classification/TGA SaMD impact checked: no clinical decision-support behaviour changed

Notes

  • The Developer Section never used a password. The request was to remove the sign-in step; this removes it for the owner's own devices without making the area public.
  • There is no per-device revocation, by design for a single-operator deployment. Key rotation is the revocation, and docs/developer-area-access.md says so rather than leaving it to be rediscovered.

🤖 Generated with Claude Code

https://claude.ai/code/session_01K8kRjars99uHE46MRH28rg


Generated by Claude Code

The owner asked for a Developer Section that does not ask him to sign in.
Deleting DeveloperAreaGate would have published the task ledger, the hazard
notes and the Ward Flow / Care Plan / Caring Contact prototypes to anyone
visiting psychiatry.tools -- #L30 reintroduced on purpose -- so this adds a
third credential beside the administrator claim rather than removing it.

DEVELOPER_AREA_ACCESS_KEY (server-only, 32-character floor) is presented once
per device as `/mockups/development?devkey=...`. src/proxy.ts verifies it,
sets a signed cookie and redirects the key out of the URL so it does not
survive in the address bar, the shared history entry or a Referer header. The
cookie carries an HMAC over its own issue time, not the key, so it cannot be
re-dated or turned back into the secret; the proxy re-issues it on every
verified visit, so a device used once a year never sees the sign-in again.

The credential is additive and fails closed everywhere: unset, under-strength,
malformed, or signed under a rotated key all fall through to the existing
sign-in screen. Rotating the key in Railway is the revocation. Reaching the
page is all it grants -- environment-facts and corpus-health still check the
administrator claim themselves and degrade to "unavailable" for a link holder.

check:production-readiness now fails a NEXT_PUBLIC_ copy of the key (Next.js
would inline it into the client bundle) and states an enabled key as a
release-time fact.

Verified: lint, typecheck, prettier --check . and the four affected suites
(link-access, proxy, developer-area-access, developer-area-gate) green;
verify:cheap left to the next run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K8kRjars99uHE46MRH28rg
`check:repo-awareness-snapshot` reported the committed snapshot behind the
repository after docs/developer-area-access.md was added. Regenerated with
`npm run snapshot:repo-awareness`; the check now reports in step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K8kRjars99uHE46MRH28rg
@supabase

supabase Bot commented Sep 8, 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 ↗︎.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

BigSimmo commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #2742 and closing. Same change, scanner-clean.

Why a replacement rather than a fix here. Gitleaks failed this branch with five generic-api-key findings (run 34232733033) on the 32-character hex fixtures the new tests assigned to KEY and DEVELOPER_AREA_ACCESS_KEY. That is a true positive for the rule — a random-looking high-entropy string under one of those names is the shape it exists to catch — so the fixtures changed rather than the allowlist, and no .gitleaksignore entry was added.

The fix could not land on this branch. Gitleaks scans every commit in a PR's range, not just the tip, so the offending blob had to leave the branch's history; force-push and branch deletion are both barred from this session. The owner approved a replacement branch instead.

Verified with the pinned Gitleaks 8.24.3 the workflow installs, over the same range the check scans: this branch reproduces at leaks found: 5, #2742 reports no leaks found.

Nothing else differs. All local gates were re-run on the new branch after the fixture change — lint, typecheck, whole-tree prettier --check ., verify:cheap, and the five affected suites (76 tests).


Generated by Claude Code

@BigSimmo BigSimmo closed this Sep 8, 2026
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