Repository navigation
Issue #71, 72, 73 and 74 resolved - #147
Conversation
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
|
@Jayking40 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
The merge of upstream main resolved the models.ts conflict by truncating the Phase W6 stuck-referrals section mid-interface, dropping Referral's closing fields and the StuckReferral/DoctorAvailability/reassign/cancel types, which broke typecheck in CI. Both sides only appended sections after the same shared prefix, so keep both: upstream's Phase W4 sections followed by the Phase W6 ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
afeezorobsco-cyber
left a comment
There was a problem hiding this comment.
Reviewed: all four admin pages sit behind RequireAuth allowedRoles={['admin']}, ids in paths are encodeURIComponent-ed, there's no raw HTML rendering, and every endpoint core doesn't serve yet becomes a neutral "not served yet" on 404 instead of an error. The assumed shapes are well documented in ARCHITECTURE_ESSENTIALS. CI green. LGTM.
Follow-up (non-blocking): the assumed AccessLog shape here ({id, actorUserId, actorRole, entityType, entityId, route, createdAt}, paged as CursorPage) doesn't match what docforum-core#149 currently returns ({items: [...]} with accessedBy / accessedByUser.role / accessedAt, entityType required, take limit, no cursor). One side will need to change when #149 lands.
feat(admin): audit and access log viewer (Phase W6)
Summary
PRD §7 requires every state change to be attributable, and docforum-core now records audit events (docforum-core#43) and will record who viewed which clinical record (docforum-core#45). Those records only matter if an admin can search them. This PR adds an admin-only viewer at
/admin/auditthat answers questions like "who released this payment?", "who verified this doctor?" and "who viewed this patient's record?".It starts Phase W6 — Admin console in
ROADMAP.md. This is PRD §7 (auditability), not one of the PRD §4 core flows.All data comes from docforum-core's API. Nothing here calls Stellar or the escrow service.
Changes
/admin/auditpage with two tabsGET /admin/audit-events. Each row shows the time, action code, entity, from → to state, who did it (with their role), the request ID and the extra details.GET /admin/access-logs(docforum-core#45 isn't merged yet). If that endpoint returns 404, the tab says the logs aren't available yet instead of showing an error./admin?intent=<id>. Entity types with no admin screen yet show their ID as plain text.ROADMAP.mdhas a new Phase W6 section and changelog entry. The "Known assumptions — Phase W6" section ofARCHITECTURE_ESSENTIALS.mddocuments the real audit-events contract, the assumed access-log contract, and the missing action filter.API gap to file in docforum-core
GET /admin/audit-eventshas noactionfilter and rejects unknown parameters with a400. For now the action filter only searches the page that's loaded, and the UI says so. Adding a server-sideactionfilter would let the viewer search every page.Testing
action, and how action matching works.constructorand__proto__don't produce a link.$ npm run typecheck
tsc -b --noEmit
$ npm test
Test Files 27 passed (27)
Tests 153 passed (153)
$ npm run build
✓ built in 3.24s
The >500 kB chunk-size warning from
npm run buildalready appears onmain(518 kB there; this branch adds about 6 kB gzipped).Screenshots
Taken with fake API responses, since the preview backend has no audit data. The fake events endpoint rejects
actionthe same way the real one does, so the filtered screenshot also shows the parameter is never sent.screenshots/admin-audit-events-desktop.pngscreenshots/admin-audit-events-mobile.pngscreenshots/admin-audit-events-filtered-desktop.pngscreenshots/admin-audit-access-desktop.pngscreenshots/admin-audit-access-mobile.pngCloses #71
feat(admin): Stuck referrals console — reassign or cancel with a reason
Summary
Referrals that sit pending for days leave patients stuck between doctors. This is the failure DocForum exists to prevent. This PR adds an admin console at
/admin/referralsthat lists stuck referrals by age, with their target specialty and the reason they're stuck (no doctor, doctor inactive, loop flagged). Each one can be reassigned to an eligible doctor or cancelled, and both actions need a reason, which docforum-core records in the audit trail.PRD flow: §4 core flow, the referral step (booking → referral → order → fulfillment). This screen is the admin fallback when routing fails.
Depends on: DocForum/docforum-core#68 (admin referral operations) and #65 (loop detection / referral chain). Neither has landed, so the API shapes are documented assumptions (see "Known assumptions — Phase W6" in
ARCHITECTURE_ESSENTIALS.md).Changes
verified, list the referral's target specialty, and are neither the doctor it's stuck with nor the referring doctor can be selected. Anything else is hidden, and the picker says how many were hidden.expectedUpdatedAt).409/404(someone else acted first): the dialog closes, a notice explains what happened, and the queue refreshes.400/422: the dialog stays open with the server's message;422also reloads the doctor list.ReferralStatusandSpecialty, and theReferralfields from itsARCHITECTURE.md§4.4. The encryptedsnapshotNotesfield is deliberately left out, and no patient-identifying data is shown.ROADMAP.mdhas the Phase W6 item and a changelog line.ARCHITECTURE_ESSENTIALS.mddocuments every assumed endpoint and shape.Testing
409conflict,422refusal, no eligible doctors404conflict, network failure then safe retrynpm run typecheck ✓ no errors
npm test Test Files 30 passed (30)
Tests 207 passed (207)
npm run build ✓ built
Screenshots
Closes #72
feat(admin): system health page — readiness, background jobs and recent failures
Summary
When the backend misbehaves (a cold start on the preview, a stalled expiry job, a Stellar RPC outage), admins currently have no way to see what's wrong. This adds an admin-only System health page at
/admin/systemthat answers "is it broken?" at a glance and shows the detail underneath.The three backend dependencies (docforum-core#100 job runner, #104 readiness checks, #94 outbox) haven't landed yet, so the page is built against assumed API shapes, written up in
ARCHITECTURE_ESSENTIALS.mdunder "Known assumptions — Phase W6". Until those land, each section shows "not served yet" or "not exposed" instead of an error.PRD flow: this isn't one of the PRD §4 core flows. It's admin operations tooling (Phase W6, admin console).
Changes
409), job not found (404), or couldn't confirm (network failure; safe to retry because jobs are idempotent).ROADMAP.md(W6 item and changelog line) andARCHITECTURE_ESSENTIALS.md(assumed shapes for/health/ready,/admin/jobs,/admin/jobs/:name/run,/admin/outbox).Testing
npm run typecheck: cleannpm test: 33 files, 267/267 passing (60 new)npm run build: green (the >500 kB chunk warning was already there onmain)New tests cover:
409already running, network failure, and that the dialog can't be closed mid-request./health/ready's503body is unwrapped only when it's a real readiness report; job names are URL-encoded.Screenshots
Captured against stubbed API responses, since the endpoints don't exist yet.
screenshots/admin-system-desktop.pngscreenshots/admin-system-mobile.pngscreenshots/admin-system-run-confirm-desktop.pngscreenshots/admin-system-run-confirm-mobile.pngscreenshots/admin-system-run-result-desktop.pngscreenshots/admin-system-run-result-mobile.pngUnrelated issue found
On
main, the homepage's GSAP animation callsgetTotalLength()on an SVG that isdisplay: noneat mobile widths. Chromium throws and the whole app goes blank, which affects anyone logging in on a phone. It's out of scope here; I'll open a separate issue.Closes #73
feat(admin): feature flags console
Summary
Staged rollouts (wallet payments, 2FA enforcement, new notification channels) are controlled by docforum-core feature flags. Until now, changing one meant editing the database, with no audit trail the team could see. This PR adds an admin console at
/admin/flags. Admins can review flags, search and filter them, and change them through a confirmation step that shows who changed each flag last and when.docforum-core#132 hasn't landed, so the flag API shape is assumed. It is documented in
ARCHITECTURE_ESSENTIALS.md→ "Known assumptions — Phase W6". The "last changed" data uses the real audit-events endpoint (docforum-core#43).This is Phase W6 (admin console) work, not one of the PRD §4 core flows.
Changes
updatedAtthe admin saw, so concurrent edits come back as409and are explained. A flag that no longer exists (404) is reported too. An open dialog notices when the flag changes underneath it, blocks confirming, and offers to start again from the latest values.Testing
npm run typecheck # clean
npm test # Test Files 37 passed (37) · Tests 335 passed (335)
npm run build # ✓ built (the >500 kB chunk warning was already there on main)
Screenshots
Captured against a mocked API, at desktop (1280px) and mobile (390px) widths:
screenshots/admin-flags-list-desktop.pngscreenshots/admin-flags-list-mobile.pngscreenshots/admin-flags-filtered-desktop.pngscreenshots/admin-flags-filtered-mobile.pngscreenshots/admin-flags-edit-desktop.pngscreenshots/admin-flags-edit-mobile.pngscreenshots/admin-flags-confirm-desktop.pngscreenshots/admin-flags-confirm-mobile.pngscreenshots/admin-flags-toggle-confirm-desktop.pngscreenshots/admin-flags-toggle-confirm-mobile.pngscreenshots/admin-flags-rollback-desktop.pngscreenshots/admin-flags-rollback-mobile.pngCloses #74