mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
fix(fhir): stop advertising a credential no client can obtain
The capability descriptor named `fhir:read` as the scope a narrow token needs for the REST face. No code path mints a token carrying it — every mint grants a wildcard, the medication ingest scope, or an MCP scope — so the face is reachable by the owner's cookie session or a wildcard device token and by nothing else. Advertising an unobtainable credential invites a client to go looking for one. The constant stays where it belongs, as the fail-closed check each route makes; the descriptor now reports the fact instead. End-to-end coverage for the scope picker: the first run opens it expanded with the fenced tier rendered and no group control over it, a group row clears the 44 px floor at 390 px, and a leaf grid opens from its chevron. All on stable test ids rather than text a breakpoint can hide.
This commit is contained in:
1 parent
f12290532f
commit
ffe99caccd
5 files changed
+72
-12
No files matched your search
@@ -53,7 +53,6 @@ import {
|
||||
GERMAN_ATC_DEFAULT_LOCALES,
|
||||
} from "@/lib/fhir/build-bundle";
|
||||
import {
|
||||
FHIR_READ_SCOPE,
|
||||
FHIR_REST_RESOURCE_TYPES,
|
||||
FHIR_EVERYTHING_OPERATION,
|
||||
FHIR_SEARCH_PARAMS,
|
||||
@@ -87,7 +86,7 @@ type CapabilitiesBody = {
|
||||
snomedRoute: string;
|
||||
germanAtcDefaultLocales: string[];
|
||||
restBaseUrl: string;
|
||||
readScope: string;
|
||||
scopeMintable: boolean;
|
||||
resourceTypes: string[];
|
||||
operations: string[];
|
||||
searchParams: string[];
|
||||
@@ -169,7 +168,10 @@ describe("GET /api/meta/capabilities — drift guards", () => {
|
||||
const res = await call();
|
||||
const body = (await res.json()) as CapabilitiesBody;
|
||||
expect(body.data.fhir.restBaseUrl).toBe("/api/fhir");
|
||||
expect(body.data.fhir.readScope).toBe(FHIR_READ_SCOPE);
|
||||
// The face checks `fhir:read`, but nothing mints a token carrying it, so
|
||||
// advertising it as an obtainable credential would be a claim the code
|
||||
// cannot support.
|
||||
expect(body.data.fhir.scopeMintable).toBe(false);
|
||||
expect(body.data.fhir.resourceTypes).toEqual([...FHIR_REST_RESOURCE_TYPES]);
|
||||
expect(body.data.fhir.operations).toEqual([FHIR_EVERYTHING_OPERATION]);
|
||||
expect(body.data.fhir.searchParams).toEqual([...FHIR_SEARCH_PARAMS]);
|
||||
|
||||
@@ -41,7 +41,6 @@ import {
|
||||
GERMAN_ATC_DEFAULT_LOCALES,
|
||||
} from "@/lib/fhir/build-bundle";
|
||||
import {
|
||||
FHIR_READ_SCOPE,
|
||||
FHIR_REST_RESOURCE_TYPES,
|
||||
FHIR_EVERYTHING_OPERATION,
|
||||
FHIR_SEARCH_PARAMS,
|
||||
@@ -111,7 +110,13 @@ export const GET = apiHandler(async () => {
|
||||
// whole-record operation, the honoured search params and the narrow
|
||||
// Bearer scope. All sourced from the canonical `rest.ts` constants.
|
||||
restBaseUrl: "/api/fhir",
|
||||
readScope: FHIR_READ_SCOPE,
|
||||
// The face checks a narrow `fhir:read` scope, and NO code path mints a
|
||||
// token carrying it — every mint grants a wildcard, the medication
|
||||
// ingest scope, or an MCP scope. So the face is reachable by the owner's
|
||||
// cookie session or a wildcard device token, and by nothing else. It is
|
||||
// reported that way rather than advertising a credential a client cannot
|
||||
// obtain.
|
||||
scopeMintable: false,
|
||||
resourceTypes: FHIR_REST_RESOURCE_TYPES,
|
||||
operations: [FHIR_EVERYTHING_OPERATION],
|
||||
searchParams: FHIR_SEARCH_PARAMS,
|
||||
|
||||
Reference in new issue
Block a user