fix(capabilities): stop advertising a share-scoped FHIR API that is not wired

The capabilities share descriptor exposed scopeable FHIR resourceTypes, but no
/api/fhir/* route honours a share token — those routes require an authenticated
fhir:read Bearer. The share serves the rendered record view only. Drop the
unrouted resourceTypes from the advertised share scope and add an explicit
fhirApi:false flag so an integrator knows the share to FHIR face is not live.
This commit is contained in:
Marc-André Bombeck committed 2026-06-04 04:10:16 +02:00
1 parent cd3982a35c
commit 47ba474569
2 files changed
+11 -16

No files matched your search

@@ -58,10 +58,7 @@ import {
FHIR_EVERYTHING_OPERATION,
FHIR_SEARCH_PARAMS,
} from "@/lib/fhir/rest";
import {
SHARE_LINK_MAX_DAYS,
SHARE_LINK_RESOURCE_TYPES,
} from "@/lib/validations/clinician-share-link";
import { SHARE_LINK_MAX_DAYS } from "@/lib/validations/clinician-share-link";
import { exportSectionsSchema } from "@/lib/validations/health-record-export";
const SESSION_OK = {
@@ -95,7 +92,7 @@ type CapabilitiesBody = {
share: {
supported: boolean;
maxDays: number;
resourceTypes: string[];
fhirApi: boolean;
sections: string[];
};
};
@@ -178,11 +175,9 @@ describe("GET /api/meta/capabilities — drift guards", () => {
const body = (await res.json()) as CapabilitiesBody;
expect(body.data.share.supported).toBe(true);
expect(body.data.share.maxDays).toBe(SHARE_LINK_MAX_DAYS);
// The shareable resource types are exactly the REST catalogue, by
// construction — the share can never scope to an unrouted type.
expect(body.data.share.resourceTypes).toEqual([
...SHARE_LINK_RESOURCE_TYPES,
]);
// The share serves the rendered record view only; no `/api/fhir/*` route
// honours a share token yet, so the share→FHIR face is advertised off.
expect(body.data.share.fhirApi).toBe(false);
expect([...body.data.share.sections].sort()).toEqual(
Object.keys(exportSectionsSchema.shape).sort(),
);
+6 -6
View File
@@ -46,10 +46,7 @@ import {
FHIR_EVERYTHING_OPERATION,
FHIR_SEARCH_PARAMS,
} from "@/lib/fhir/rest";
import {
SHARE_LINK_MAX_DAYS,
SHARE_LINK_RESOURCE_TYPES,
} from "@/lib/validations/clinician-share-link";
import { SHARE_LINK_MAX_DAYS } from "@/lib/validations/clinician-share-link";
import { exportSectionsSchema } from "@/lib/validations/health-record-export";
export const dynamic = "force-dynamic";
@@ -118,11 +115,14 @@ export const GET = apiHandler(async () => {
},
// Clinician share-link surface (v1.11): a scoped, time-boxed, revocable
// read-only link to the owner's record. Descriptor sourced from the
// canonical share validation + export-section constants.
// canonical share validation + export-section constants. The share serves
// the rendered record view only; no `/api/fhir/*` route honours a share
// token yet (they require an authenticated `fhir:read` Bearer), so the
// share→FHIR face is not advertised as live.
share: {
supported: true,
maxDays: SHARE_LINK_MAX_DAYS,
resourceTypes: SHARE_LINK_RESOURCE_TYPES,
fhirApi: false,
sections: Object.keys(exportSectionsSchema.shape),
},
});