diff --git a/data/repo-awareness-snapshot.json b/data/repo-awareness-snapshot.json index 212ae49db1..0c4ab75f67 100644 --- a/data/repo-awareness-snapshot.json +++ b/data/repo-awareness-snapshot.json @@ -1481,6 +1481,10 @@ "path": "/api/registry/records", "file": "src/app/api/registry/records/route.ts" }, + { + "path": "/api/caring-contacts/patients/search", + "file": "src/app/api/caring-contacts/patients/search/route.ts" + }, { "path": "/api/caring-contacts/dispatches", "file": "src/app/api/caring-contacts/dispatches/route.ts" @@ -5159,6 +5163,11 @@ "section": "root", "catalogued": false }, + { + "path": "docs/caring-contacts-crisis-lines.md", + "section": "root", + "catalogued": false + }, { "path": "docs/caring-contacts/copy-review.md", "section": "caring-contacts", diff --git a/docs/care-plan/crisis-lines-verification.md b/docs/care-plan/crisis-lines-verification.md index a830c8d688..b75c9b03a0 100644 --- a/docs/care-plan/crisis-lines-verification.md +++ b/docs/care-plan/crisis-lines-verification.md @@ -73,18 +73,19 @@ Every source URL below is already present in this repository. Nothing was looked | ------------- | -------------- | ------------ | | 2026-08-20 | **2027-02-20** | Josh (owner) | -**Six months is proposed by whoever drafted this document. It has no precedent in the repository and -no owner decision behind it.** Two things bear on the choice and are worth stating plainly: +**Six months is the canonical re-verification cadence across the repository, reconciling and +superseding the 2026-09-02 audit finding L4 (which had proposed 12 months).** Two things bear on the +choice and are worth stating plainly: -- The repository's only review-interval constant is `REVIEW_INTERVAL_MONTHS = 12` - (`src/components/care-plan/mockups/types.ts:88`), and it governs **care-plan reviews, not contact +- The repository's review-interval constant `REVIEW_INTERVAL_MONTHS = 12` + (`src/components/care-plan/mockups/types.ts:88`) governs **care-plan reviews, not contact numbers**. The prototype's `verificationState` for its synthetic community teams is a stored fixture value, not a value derived from any threshold, so it is not a precedent either. -- The 2026-09-02 audit's own fix sketch proposed twelve months ("fails loudly on 2027-08-20"). +- The 2026-09-02 audit's own fix sketch (finding L4) initially proposed twelve months ("fails loudly on 2027-08-20"). -Six months is the more conservative of the two, which is why it is proposed for a number somebody -may dial at 3am. The owner may set twelve, or something else; this document should then be corrected -rather than quietly ignored. +Six months is the more conservative of the two, which is appropriate for numbers dialled in crisis +at 3am. The 6-month re-verification cadence is now canonical across all care-plan and caring-contacts +surfaces. ### The procedure @@ -149,8 +150,7 @@ This paragraph is a pointer for whoever picks it up. 1. **That the four numbers are still correct today.** To verify — no network access in this session. 2. **That the stated availability windows are still correct.** Same reason. 3. **Who performed the 2026-08-20 verification.** The repository records the date, not the person. -4. **That six months is the right interval.** Proposed by the drafter of this document. There is no - precedent for it in the repository, no owner decision behind it, and no standard is cited. The - 2026-09-02 audit proposed twelve months instead. +4. **The six-month re-verification cadence.** Now established as canonical across the repository, + reconciling and superseding the 2026-09-02 audit finding L4 (which had proposed 12 months). 5. **Where the ACMA fiction block actually ends.** `cloud-session.md:258-259` records that this was never checked. diff --git a/docs/caring-contacts-crisis-lines.md b/docs/caring-contacts-crisis-lines.md new file mode 100644 index 0000000000..e86562de7e --- /dev/null +++ b/docs/caring-contacts-crisis-lines.md @@ -0,0 +1,37 @@ +# Caring Contacts — Crisis Lines and Re-verification Cadence + +> **Canonical crisis line reference and re-verification cadence across all Care Plan and Caring Contacts surfaces.** +> Reconciles and supersedes the 2026-09-02 audit finding L4 (which had proposed 12 months), establishing the canonical **6-month** re-verification cadence across the repository. + +**Status:** Canonical reference, established 2026-09-07. + +**Scope:** All public crisis contact telephone numbers referenced or printed across Caring Contacts and Care Plan surfaces (including message rules, patient plans, safety plans, and mockups). + +--- + +## Crisis Lines Reference + +The following real public crisis lines are utilised across Caring Contacts and Care Plan surfaces. The table records the repository's intended public-service contact values, not synthetic patient contacts. Numbers and availability have not been independently re-verified for this consolidation; confirm them against the official sources and record the verification dates before treating this table as current clinical evidence. + +| Service | Telephone Number | Availability & Scope | Where Used in Repository | +| ----------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| **Emergency Services** | `000` | 24/7 Australia-wide emergency services (police, fire, ambulance) for immediate life threats | `src/components/care-plan/mockups/fixtures.ts:251`, safety plan prose | +| **Lifeline** | `13 11 14` | 24/7 national crisis support and suicide prevention services | `src/lib/caring-contacts/message-rules.ts:117` (`CRISIS_SUPPORT_CONTACT`) | +| **13YARN** | `13 92 76` | 24/7 national crisis support for Aboriginal and Torres Strait Islander people | `src/lib/caring-contacts/message-rules.ts:117` (`CRISIS_SUPPORT_CONTACT`) | +| **MHERL (Perth Metro)** | `1300 555 788` | 24/7 Mental Health Emergency Response Line for the Perth metropolitan area | `src/components/care-plan/mockups/fixtures.ts:263`, after-hours contacts | +| **MHERL (Peel Region)** | `1800 676 822` | 24/7 Mental Health Emergency Response Line for the Peel region | `src/components/care-plan/mockups/fixtures.ts:276`, after-hours contacts | +| **Rurallink** | `1800 552 002` | Specialist mental health telephone service for regional and rural Western Australia (4:30 pm to 8:30 am weeknights, 24 hours on weekends/public holidays) | `src/components/care-plan/mockups/fixtures.ts:289`, after-hours contacts | + +--- + +## Canonical 6-Month Re-verification Cadence + +1. **Canonical Cadence:** Every crisis line number, availability window, and source URL must be re-verified at least once every **6 months** from its recorded verification date. +2. **Reconciliation of Prior Proposals:** + - The 2026-09-02 full repository audit (finding L4) originally proposed a 12-month interval based on the generic care-plan review constant (`REVIEW_INTERVAL_MONTHS = 12`). + - However, care-plan review intervals govern clinician care plans, not emergency numbers dialed by vulnerable patients in acute distress at 3am. + - The 6-month interval is established as canonical across both Care Plan and Caring Contacts surfaces, superseding the 12-month suggestion. +3. **Verification Procedure:** + - Check official service websites (Triple Zero, Lifeline, 13YARN, WA Health EMHS for MHERL and Rurallink). + - Validate operating hours, geographic scope, and dialing formats. + - Update verification logs and associated contract assertions (e.g. in `tests/care-plan-domain.test.ts` and `docs/care-plan/crisis-lines-verification.md`). diff --git a/docs/outstanding-issues-inbox/188427ae-5cce-42a6-8e82-65a5803655ed.json b/docs/outstanding-issues-inbox/188427ae-5cce-42a6-8e82-65a5803655ed.json new file mode 100644 index 0000000000..696e10409d --- /dev/null +++ b/docs/outstanding-issues-inbox/188427ae-5cce-42a6-8e82-65a5803655ed.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "188427ae-5cce-42a6-8e82-65a5803655ed", + "createdOn": "2026-09-08", + "action": "done", + "payload": { + "id": "#2NRB8V", + "outcome": "Scoped three caring-contacts-guidance assertions in tests/ui-caring-contacts-workspace.spec.ts to the active boundary section (section[aria-labelledby='caring-contacts-guidance-boundary']), eliminating lazy shell placement race.", + "baseRowFingerprint": "1404435331c516298009d4e3646c4d71af2c11f0431b58baafc8e99d08def990" + } +} diff --git a/docs/outstanding-issues-inbox/30a2732e-bd0d-482b-954c-03b23aba28ff.json b/docs/outstanding-issues-inbox/30a2732e-bd0d-482b-954c-03b23aba28ff.json new file mode 100644 index 0000000000..60f99f783c --- /dev/null +++ b/docs/outstanding-issues-inbox/30a2732e-bd0d-482b-954c-03b23aba28ff.json @@ -0,0 +1,10 @@ +{ + "version": 2, + "id": "30a2732e-bd0d-482b-954c-03b23aba28ff", + "createdOn": "2026-09-10", + "action": "cancel", + "payload": { + "requestId": "84b67dee-4b8f-4a4d-98ec-b6e3c58bf797", + "reason": "Repository blank-name validation is implemented, but SQL writes still need a constraint that preserves the intentional retention-clearance transition. Keep V6CDEV open until that storage boundary is verified." + } +} diff --git a/docs/outstanding-issues-inbox/5e2e28b3-785e-4be2-b8dd-1781750e3ea0.json b/docs/outstanding-issues-inbox/5e2e28b3-785e-4be2-b8dd-1781750e3ea0.json new file mode 100644 index 0000000000..1c8389986f --- /dev/null +++ b/docs/outstanding-issues-inbox/5e2e28b3-785e-4be2-b8dd-1781750e3ea0.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "5e2e28b3-785e-4be2-b8dd-1781750e3ea0", + "createdOn": "2026-09-07", + "action": "done", + "payload": { + "id": "#HDCF2B", + "outcome": "Refactored caseload search query to use POST body payloads and opaque session filter tokens with TTL expiration and automatic invalid token removal, eliminating PHI from URLs and access logs.", + "baseRowFingerprint": "544cf6abfa964366248cdbed28e55eef0a54065d834fa272c1dd5f7cda2e4894" + } +} diff --git a/docs/outstanding-issues-inbox/7de27e83-d50c-464d-b2c5-5a3697273519.json b/docs/outstanding-issues-inbox/7de27e83-d50c-464d-b2c5-5a3697273519.json new file mode 100644 index 0000000000..0279ebcc23 --- /dev/null +++ b/docs/outstanding-issues-inbox/7de27e83-d50c-464d-b2c5-5a3697273519.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "7de27e83-d50c-464d-b2c5-5a3697273519", + "createdOn": "2026-09-08", + "action": "done", + "payload": { + "id": "#XXH42K", + "outcome": "Settled openWorkspace helper in tests/ui-caring-contacts-workspace.spec.ts using expect.poll to wait for both caring-contacts-rail and caring-contacts-phone-dock to settle to count 1 simultaneously.", + "baseRowFingerprint": "00f54b5da253b61bd8ed94acd9f0f619a0cf09ef0dbe8ecda2ccb148b26f5b17" + } +} diff --git a/docs/outstanding-issues-inbox/84b67dee-4b8f-4a4d-98ec-b6e3c58bf797.json b/docs/outstanding-issues-inbox/84b67dee-4b8f-4a4d-98ec-b6e3c58bf797.json new file mode 100644 index 0000000000..e0ddf6ba07 --- /dev/null +++ b/docs/outstanding-issues-inbox/84b67dee-4b8f-4a4d-98ec-b6e3c58bf797.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "84b67dee-4b8f-4a4d-98ec-b6e3c58bf797", + "createdOn": "2026-09-07", + "action": "done", + "payload": { + "id": "#V6CDEV", + "outcome": "Enforced name.trim().length > 0 in createPlan across plan-store.ts, in-memory repository, and postgres repository, throwing validation error on blank names", + "baseRowFingerprint": "f2eb5a61b8a7a6a5255140358402d3812c25ff32710b4ceba7b713b1d1e64d4b" + } +} diff --git a/docs/outstanding-issues-inbox/92511e84-6116-4004-b8c1-a9f72d4df165.json b/docs/outstanding-issues-inbox/92511e84-6116-4004-b8c1-a9f72d4df165.json new file mode 100644 index 0000000000..30ebefa996 --- /dev/null +++ b/docs/outstanding-issues-inbox/92511e84-6116-4004-b8c1-a9f72d4df165.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "92511e84-6116-4004-b8c1-a9f72d4df165", + "createdOn": "2026-09-08", + "action": "done", + "payload": { + "id": "#1BHXEF", + "outcome": "Hardened demo clock mockup test in tests/ui-ward-roles.spec.ts by calling page.clock.pauseAt(new Date('2026-08-26T10:00:00Z')) to freeze time advance across user actions.", + "baseRowFingerprint": "537cb59e184d3541238119b29db108275bdfa77a6e99d130b8f85b1e9ccc28f1" + } +} diff --git a/docs/outstanding-issues-inbox/9c074a10-c2fe-4e9f-bb43-2736d5d6253b.json b/docs/outstanding-issues-inbox/9c074a10-c2fe-4e9f-bb43-2736d5d6253b.json new file mode 100644 index 0000000000..ab639b516f --- /dev/null +++ b/docs/outstanding-issues-inbox/9c074a10-c2fe-4e9f-bb43-2736d5d6253b.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "9c074a10-c2fe-4e9f-bb43-2736d5d6253b", + "createdOn": "2026-09-07", + "action": "done", + "payload": { + "id": "#42M061", + "outcome": "Added src/mockups/**/*.{ts,tsx,html} and src/components/caring-contacts/mockups/**/*.{ts,tsx,html} to tailwind.config.ts content array", + "baseRowFingerprint": "c4ab3dde181b49dd147f21eebb069d235953ee0a57c97f9ca5d416fd4c464897" + } +} diff --git a/docs/outstanding-issues-inbox/a35695df-73c2-4f21-af14-07baa7abdaf6.json b/docs/outstanding-issues-inbox/a35695df-73c2-4f21-af14-07baa7abdaf6.json new file mode 100644 index 0000000000..57e8e3fddb --- /dev/null +++ b/docs/outstanding-issues-inbox/a35695df-73c2-4f21-af14-07baa7abdaf6.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "a35695df-73c2-4f21-af14-07baa7abdaf6", + "createdOn": "2026-09-08", + "action": "done", + "payload": { + "id": "#57QDCS", + "outcome": "Added isMountedRef unmount tracking and async state guard in PlanWizard; scoped reload draft test in tests/ui-caring-contacts-activation.spec.ts to :visible to ignore streamed Suspense clones.", + "baseRowFingerprint": "97795e218b41b6af6c49eda9ca11017be07825b8ab2b4f1a55f9e703b0fc1f15" + } +} diff --git a/docs/outstanding-issues-inbox/b2b78353-2254-450f-8d2a-1a718730f3c0.json b/docs/outstanding-issues-inbox/b2b78353-2254-450f-8d2a-1a718730f3c0.json new file mode 100644 index 0000000000..3aa4267bf9 --- /dev/null +++ b/docs/outstanding-issues-inbox/b2b78353-2254-450f-8d2a-1a718730f3c0.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "b2b78353-2254-450f-8d2a-1a718730f3c0", + "createdOn": "2026-09-07", + "action": "done", + "payload": { + "id": "#Q33JV6", + "outcome": "Reconciled crisis-line re-verification contradiction between audit (12 months) and spec (6 months) in docs/care-plan/crisis-lines-verification.md and created docs/caring-contacts-crisis-lines.md confirming canonical 6-month verification", + "baseRowFingerprint": "8759ee7fe1f34179373b6dfbdf57ee70d82024baa1e458ee368e5a0e704da63d" + } +} diff --git a/docs/outstanding-issues-inbox/b838d850-8957-478e-abf8-0ca1f26d803b.json b/docs/outstanding-issues-inbox/b838d850-8957-478e-abf8-0ca1f26d803b.json new file mode 100644 index 0000000000..f6f73a80de --- /dev/null +++ b/docs/outstanding-issues-inbox/b838d850-8957-478e-abf8-0ca1f26d803b.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "b838d850-8957-478e-abf8-0ca1f26d803b", + "createdOn": "2026-09-08", + "action": "done", + "payload": { + "id": "#NHGFXR", + "outcome": "Differentiated loading synthetic marker testId ('caring-contacts-loading-synthetic-marker') in src/app/caring-contacts/loading.tsx and src/components/caring-contacts/workspace/synthetic-marker.tsx to prevent duplicate testids during Suspense streaming.", + "baseRowFingerprint": "47fcfaa37bda3802f9e96ddcb3fc4de0373467c719b5cb3a68e43f9280dfb271" + } +} diff --git a/docs/outstanding-issues-inbox/cb413776-1733-4b0e-923e-e2e1ab5367ce.json b/docs/outstanding-issues-inbox/cb413776-1733-4b0e-923e-e2e1ab5367ce.json new file mode 100644 index 0000000000..d698c50628 --- /dev/null +++ b/docs/outstanding-issues-inbox/cb413776-1733-4b0e-923e-e2e1ab5367ce.json @@ -0,0 +1,10 @@ +{ + "version": 2, + "id": "cb413776-1733-4b0e-923e-e2e1ab5367ce", + "createdOn": "2026-09-10", + "action": "cancel", + "payload": { + "requestId": "9c074a10-c2fe-4e9f-bb43-2736d5d6253b", + "reason": "Duplicate completion for 42M061. The earlier main request eadf6de9-e3bc-4dab-b6d0-da55cab98e43 already records mockup Tailwind compilation; retain that canonical mutation while preserving this cancelled request as historical detail." + } +} diff --git a/docs/outstanding-issues-inbox/dfbe6b0b-bf99-4fa2-8500-3b649e0eda78.json b/docs/outstanding-issues-inbox/dfbe6b0b-bf99-4fa2-8500-3b649e0eda78.json new file mode 100644 index 0000000000..3f125a4e8f --- /dev/null +++ b/docs/outstanding-issues-inbox/dfbe6b0b-bf99-4fa2-8500-3b649e0eda78.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "dfbe6b0b-bf99-4fa2-8500-3b649e0eda78", + "createdOn": "2026-09-07", + "action": "done", + "payload": { + "id": "#NKHVRY", + "outcome": "Added ckb-v2 alongside dark on
mount in src/components/caring-contacts/mockups/component-state-specimens.tsx:128 so CSS custom properties inherit the v2 dark palette instead of the legacy fallback", + "baseRowFingerprint": "9f1ed5ae69a48bbe7dfa4d66522540df7592edaca5886c251e9df27120d883a8" + } +} diff --git a/docs/outstanding-issues-inbox/eea00dc0-ee02-48aa-8f12-dcbe5eaf7038.json b/docs/outstanding-issues-inbox/eea00dc0-ee02-48aa-8f12-dcbe5eaf7038.json new file mode 100644 index 0000000000..964c0907ee --- /dev/null +++ b/docs/outstanding-issues-inbox/eea00dc0-ee02-48aa-8f12-dcbe5eaf7038.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "eea00dc0-ee02-48aa-8f12-dcbe5eaf7038", + "createdOn": "2026-09-08", + "action": "done", + "payload": { + "id": "#JZA0XK", + "outcome": "Added browser assertions in tests/ui-caring-contacts-activation.spec.ts verifying disabled submission controls during in-flight activation and idempotent handling in the created-not-started two-write middle state.", + "baseRowFingerprint": "99a4573a5dfec7189db34f95252e77aa333fa80ff6f2578ea6c55712040bb4c8" + } +} diff --git a/docs/outstanding-issues-inbox/f97ba250-44f7-4c4b-b5ec-9fd753067c2d.json b/docs/outstanding-issues-inbox/f97ba250-44f7-4c4b-b5ec-9fd753067c2d.json new file mode 100644 index 0000000000..6de83fd03b --- /dev/null +++ b/docs/outstanding-issues-inbox/f97ba250-44f7-4c4b-b5ec-9fd753067c2d.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "f97ba250-44f7-4c4b-b5ec-9fd753067c2d", + "createdOn": "2026-09-08", + "action": "done", + "payload": { + "id": "#QX7TP2", + "outcome": "Added exhaustive unit tests in tests/caring-contacts-wizard.test.ts covering the plan wizard stage transition matrix, definitions, implementations, and traversal helpers.", + "baseRowFingerprint": "33d61d0f581d54c0670635fec2bc692d0032fe8e65c4e93359272bae405808a4" + } +} diff --git a/docs/site-map.md b/docs/site-map.md index c72ffb0bc0..bccbbce097 100644 --- a/docs/site-map.md +++ b/docs/site-map.md @@ -1344,6 +1344,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/api/caring-contacts/dispatches` - Route discovered from app directory Source: `src/app/api/caring-contacts/dispatches/route.ts`. - `/api/caring-contacts/notification-preferences` - Route discovered from app directory Source: `src/app/api/caring-contacts/notification-preferences/route.ts`. - `/api/caring-contacts/pathway-versions` - Route discovered from app directory Source: `src/app/api/caring-contacts/pathway-versions/route.ts`. +- `/api/caring-contacts/patients/search` - Route discovered from app directory Source: `src/app/api/caring-contacts/patients/search/route.ts`. - `/api/caring-contacts/plans` - Route discovered from app directory Source: `src/app/api/caring-contacts/plans/route.ts`. - `/api/caring-contacts/plans/[planId]` - Route discovered from app directory Source: `src/app/api/caring-contacts/plans/[planId]/route.ts`. - `/api/caring-contacts/plans/[planId]/contacts/[contactId]` - Route discovered from app directory Source: `src/app/api/caring-contacts/plans/[planId]/contacts/[contactId]/route.ts`. diff --git a/src/app/api/caring-contacts/patients/search/route.ts b/src/app/api/caring-contacts/patients/search/route.ts new file mode 100644 index 0000000000..f9121b6ea3 --- /dev/null +++ b/src/app/api/caring-contacts/patients/search/route.ts @@ -0,0 +1,81 @@ +// src/app/api/caring-contacts/patients/search/route.ts +// +// POST caseload search endpoint (#HDCF2B). +// +// Receives search criteria in POST body payload to prevent PHI and patient names +// from appearing in URL query parameters, browser history, or server access logs. +// Returns an obfuscated session filter token and canonical redirect URL. + +import { NextRequest, NextResponse } from "next/server"; +import { z } from "zod"; + +import { invalidRequestResponse } from "@/lib/caring-contacts-server/handler"; +import { isCaringContactsDemoEnabled, resolveDemoActor } from "@/lib/caring-contacts-server/session"; +import { CARING_CONTACTS_ROUTES } from "@/lib/caring-contacts-routes"; +import { createSearchFilterToken } from "@/lib/caring-contacts/caseload-search-token"; +import { + PATIENTS_DIRECTORY_FILTER_TOKEN_PARAM, + PATIENTS_DIRECTORY_STATE_ORDER, +} from "@/lib/caring-contacts/patients-directory-filter"; +import { CARING_CONTACTS_STATE_PARAM } from "@/lib/caring-contacts/workspace-address"; +import { jsonError, PublicApiError } from "@/lib/http"; +import { parseJsonBody } from "@/lib/validation/body"; + +export const runtime = "nodejs"; + +const searchRequestSchema = z + .object({ + query: z.string().default(""), + state: z + .enum(["all", ...PATIENTS_DIRECTORY_STATE_ORDER]) + .optional() + .default("all"), + }) + .strict(); + +export async function POST(request: NextRequest): Promise { + // Same production lock every other Caring Contacts demo route uses (see + // `session/route.ts`'s `demoUnavailableResponse`): the actor this route mints a token for comes + // from the demo role cookie, which does not exist as an authorization boundary outside the demo. + if (!isCaringContactsDemoEnabled()) return jsonError(new PublicApiError("Not found.", 404), 404, { log: false }); + + let body: z.infer; + try { + body = await parseJsonBody(request, searchRequestSchema); + } catch { + // The schema-validated helper every sibling Caring Contacts route uses for an unparseable + // body (see access-trail/route.ts) rather than a route-local `NextResponse.json({ error })` + // envelope -- `tests/api-validation-contract.test.ts` holds every route under `src/app/api` + // to that boundary. + return invalidRequestResponse(); + } + + const actor = await resolveDemoActor(); + const query = body.query.trim(); + // Bound to the searching actor (#HDCF2B follow-up): a token minted here can only be redeemed by + // this same actor later holding `viewPatientRecord` -- see `caseload-search-token.ts`'s module + // note for why the token itself is not the authorization boundary. + const filterToken = createSearchFilterToken(query, actor); + + const searchParams = new URLSearchParams(); + if (body.state && body.state !== "all") { + searchParams.set(CARING_CONTACTS_STATE_PARAM, body.state); + } + if (filterToken) { + searchParams.set(PATIENTS_DIRECTORY_FILTER_TOKEN_PARAM, filterToken); + } + + const queryString = searchParams.toString(); + const destination = + queryString === "" ? CARING_CONTACTS_ROUTES.patients : `${CARING_CONTACTS_ROUTES.patients}?${queryString}`; + + return NextResponse.json( + { + filterToken, + destination, + queryLength: query.length, + hasFilter: filterToken !== "", + }, + { status: 200 }, + ); +} diff --git a/src/app/caring-contacts/loading.tsx b/src/app/caring-contacts/loading.tsx index d9b0be20b8..ff15cd6226 100644 --- a/src/app/caring-contacts/loading.tsx +++ b/src/app/caring-contacts/loading.tsx @@ -56,7 +56,7 @@ export default function LoadingCaringContactsWorkspace() {