Skip to content

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

Draft
BigSimmo wants to merge 1 commit into
mainfrom
claude/dev-section-passwordless-link
Draft

Open the developer area with a bookmarked link instead of a sign-in#2742
BigSimmo wants to merge 1 commit into
mainfrom
claude/dev-section-passwordless-link

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Replaces #2741, which carried the same change but could not be made scanner-clean: Gitleaks reads every commit in a PR's range, and that branch's first commit contained 32-character hex test fixtures assigned to names like KEY. The fixtures are fixed here, and this branch is a single commit that never contained them. Owner approved the replacement after a history rewrite on the original branch proved impossible from this session.

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 this commit — the check now reports [repo-awareness] in step with data/repo-awareness-snapshot.json (224 pages, 906 documents, 2718 reviews).
  • npm run typecheck[gate-receipts] recorded a pass for "typecheck:internal" (7464 input files), re-run after the fixture change.
  • npm run lint[gate-receipts] recorded a pass for "lint:internal" (7464 input files), re-run after the fixture change.
  • npx prettier --check .All matched files use Prettier code style! (whole tree)
  • Affected suites green: tests/developer-area-link-access.test.ts (12 new), tests/proxy.test.ts, tests/developer-area-access.test.ts, tests/developer-area-gate.dom.test.tsx, tests/production-readiness-offline.test.ts — 76 tests across the five files.
  • Gitleaks, using the pinned 8.24.3 the workflow installs and the same range the check scans: the original branch reproduces (leaks found: 5), this branch reports no leaks found.
  • 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.
  • The Gitleaks findings on Open the developer area with a bookmarked link instead of a sign-in #2741 were true positives for the rule — a random-looking high-entropy string assigned to KEY is the shape it exists to catch — so the fixtures changed rather than the allowlist. No .gitleaksignore entry was added.
  • 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, inside the ~400-day ceiling browsers clamp Set-Cookie to, 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, expired, 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. docs/developer-area-access.md covers setup, per-device use,
what the link does not grant, and revocation.

Test fixtures are built from readable words with padEnd(32, "-") rather than
written as 32-character hex literals. The first version of this branch failed
Gitleaks with five generic-api-key findings on exactly those literals, which is
a true positive for the rule: a random-looking high-entropy string assigned to
a name like KEY is the shape it exists to catch. Nothing in the tests depended
on the values looking random, so the fixtures changed rather than the
allowlist. Squashed to one commit for the same reason -- a range scan reads
every commit's diff, so the offending blob had to leave the branch's history,
not just its tip.

Verified: verify:cheap exit 0; lint and typecheck pass (7464 input files each);
prettier --check . clean whole-tree; the five affected suites green (76 tests);
pinned Gitleaks 8.24.3 reproduces the original failure (leaks found: 5) and
reports none over this branch's range.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K8kRjars99uHE46MRH28rg
@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.

@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 ↗︎.

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