diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index 045e4c31f..d279cbdd8 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -16615,12 +16615,6 @@ components: type: boolean needsReselection: type: boolean - allowFhirApi: - type: boolean - resourceTypes: - type: array - items: - type: string expiresAt: type: string createdAt: @@ -16659,8 +16653,6 @@ components: - documentCount - documentOnly - needsReselection - - allowFhirApi - - resourceTypes - expiresAt - createdAt - revokedAt @@ -16713,12 +16705,6 @@ components: type: boolean needsReselection: type: boolean - allowFhirApi: - type: boolean - resourceTypes: - type: array - items: - type: string expiresAt: type: string createdAt: @@ -16744,8 +16730,6 @@ components: - documentCount - documentOnly - needsReselection - - allowFhirApi - - resourceTypes - expiresAt - createdAt - revokedAt diff --git a/src/app/api/share-links/__tests__/route.test.ts b/src/app/api/share-links/__tests__/route.test.ts index c38b61431..2de2d538a 100644 --- a/src/app/api/share-links/__tests__/route.test.ts +++ b/src/app/api/share-links/__tests__/route.test.ts @@ -374,8 +374,6 @@ describe("DELETE /api/share-links/[id] — revoke", () => { * Mutation checks: * - drop the `SHARE_LINK_FORBIDDEN_LEAVES` check in the route → "refuses the * insurance leaf by name" goes red. - * - drop `RETIRED_FHIR_SCOPE_FIELDS` from the create response → "keeps the - * retired scope fields on the response" goes red. * - make `needsReselection` always false → "flags a link whose frozen scope * predates the selection model" goes red. */ @@ -433,21 +431,17 @@ describe("POST /api/share-links — the frozen scope", () => { expect(createArg.data.sectionsJson).toEqual({ v: 2, leaves: [] }); }); - it("keeps the retired scope fields on the response", async () => { - // Response-only, serving constants. The request refuses them and the - // columns are gone; they stay here until the native client confirms it - // does not decode them. + it("the retired FHIR scope fields are gone from the create response", async () => { + // #70 — the native client confirmed removal breaks no shipped decoder. vi.mocked(prisma.clinicianShareLink.create).mockResolvedValue( storedRow() as never, ); const res = await POST( postReq(validBody({ selection: { v: 2, leaves: ["WEIGHT"] } })), ); - const body = (await res.json()) as { - data: { allowFhirApi: boolean; resourceTypes: string[] }; - }; - expect(body.data.allowFhirApi).toBe(false); - expect(body.data.resourceTypes).toEqual([]); + const body = (await res.json()) as { data: Record }; + expect(body.data).not.toHaveProperty("allowFhirApi"); + expect(body.data).not.toHaveProperty("resourceTypes"); }); }); @@ -465,12 +459,9 @@ describe("GET /api/share-links — the pick-again state", () => { const res = await GET(); const body = (await res.json()) as { data: { - shareLinks: Array<{ - id: string; - needsReselection: boolean; - allowFhirApi: boolean; - resourceTypes: string[]; - }>; + shareLinks: Array< + { id: string; needsReselection: boolean } & Record + >; }; }; const byId = new Map(body.data.shareLinks.map((l) => [l.id, l])); @@ -479,8 +470,8 @@ describe("GET /api/share-links — the pick-again state", () => { // A documents-only link carried no report scope to begin with, so it was // never revoked and is not asked to pick again. expect(byId.get("docs")!.needsReselection).toBe(false); - // The retired fields ride the list response too. - expect(byId.get("current")!.allowFhirApi).toBe(false); - expect(byId.get("current")!.resourceTypes).toEqual([]); + // The retired FHIR scope fields are gone from the list response too. + expect(byId.get("current")).not.toHaveProperty("allowFhirApi"); + expect(byId.get("current")).not.toHaveProperty("resourceTypes"); }); }); diff --git a/src/app/api/share-links/route.ts b/src/app/api/share-links/route.ts index a98fd2fc8..045056b99 100644 --- a/src/app/api/share-links/route.ts +++ b/src/app/api/share-links/route.ts @@ -87,22 +87,6 @@ const shareLinkSummarySelect = { _count: { select: { documents: true } }, } as const; -/** - * RETIRED, kept on the response only. - * - * These two fields described a scoped FHIR face for a share link that was - * never built. The request schema refuses them — sending either is a 422 — - * their columns are dropped, and nothing reads or honours them. They stay in - * the create and list responses, serving the constant `false` and `[]`, - * because the native client was given this response shape and a missing - * non-optional key fails a whole Swift decode. They come out once #70 in the - * native repository confirms the client does not decode them. - */ -const RETIRED_FHIR_SCOPE_FIELDS = { - allowFhirApi: false, - resourceTypes: [] as string[], -} as const; - /** Project a stored row to the safe owner-facing shape (never the token). */ function toSummary(row: { id: string; @@ -279,7 +263,6 @@ export const POST = apiHandler(async (request: NextRequest) => { return apiSuccess( { ...toSummary(created), - ...RETIRED_FHIR_SCOPE_FIELDS, token: rawToken, passphrase: rawPassphrase, shareUrl, @@ -300,9 +283,6 @@ export const GET = apiHandler(async () => { }); return apiSuccess({ - shareLinks: rows.map((row) => ({ - ...toSummary(row), - ...RETIRED_FHIR_SCOPE_FIELDS, - })), + shareLinks: rows.map((row) => toSummary(row)), }); }); diff --git a/src/components/settings/share-link-create-form.tsx b/src/components/settings/share-link-create-form.tsx index 9a6432828..a5974c185 100644 --- a/src/components/settings/share-link-create-form.tsx +++ b/src/components/settings/share-link-create-form.tsx @@ -83,14 +83,6 @@ export interface ShareLinkSummary { * hashes). `qrUrl` carries the passphrase in the URL fragment (`#k=`). */ export interface ShareLinkCreated extends ShareLinkSummary { - /** - * RETIRED, response-only. They configured a FHIR face that was never built; - * the request refuses them and the columns are gone. They stay here because - * the native client was given this shape and a missing non-optional key - * fails a whole Swift decode — see #70 in the native repository. - */ - allowFhirApi: boolean; - resourceTypes: string[]; token: string; passphrase: string; shareUrl: string; diff --git a/src/lib/openapi/routes/health-record.ts b/src/lib/openapi/routes/health-record.ts index 6d60b96dc..8a5d566f0 100644 --- a/src/lib/openapi/routes/health-record.ts +++ b/src/lib/openapi/routes/health-record.ts @@ -36,12 +36,6 @@ const shareLinkSummary = z.object({ // link was revoked on upgrade; the sharing list surfaces this so the owner // knows to re-mint rather than wondering why a working link stopped. needsReselection: z.boolean(), - // RETIRED, response-only, serving the constants `false` and `[]`. They - // configured a FHIR face that was never built; the request refuses them and - // their columns are gone. They stay on the response until the native client - // confirms it does not decode them. - allowFhirApi: z.boolean(), - resourceTypes: z.array(z.string()), expiresAt: z.string(), createdAt: z.string(), revokedAt: z.string().nullable(),