mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
docs(openapi): add GET/PUT /api/auth/me/report-selection
Documents the saved doctor-report scope endpoint, reusing the real savedReportProfileSchema so the spec's leaf cap and version literal stay tied to the source of truth.
This commit is contained in:
1 parent
ec2c8a9e71
commit
b7074e04b8
2 files changed
+205
No files matched your search
@@ -5699,6 +5699,48 @@ paths:
|
||||
$ref: "#/components/schemas/ErrorEnvelope"
|
||||
"422": *a3
|
||||
"429": *a4
|
||||
/api/auth/me/report-selection:
|
||||
get:
|
||||
tags:
|
||||
- Auth
|
||||
summary: Read the owner's saved doctor-report selection
|
||||
description: "Returns the saved report-scope profile, or `profile: null` when the account has never saved one (or the
|
||||
stored blob no longer parses against the current leaf catalogue). Replaces the retired `GET
|
||||
/api/auth/me/doctor-report-prefs`. Auth via cookie or Bearer."
|
||||
responses:
|
||||
"200":
|
||||
description: The saved profile, or null.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GetReportSelectionResponseEnvelope"
|
||||
"401": *a1
|
||||
"422": *a3
|
||||
"429": *a4
|
||||
put:
|
||||
tags:
|
||||
- Auth
|
||||
summary: Replace the owner's saved doctor-report selection
|
||||
description: Replace, not merge — the body states the whole scope or it is not a scope; a leaf omitted from the body is
|
||||
a leaf removed from the saved profile. An unknown leaf id is refused with a 422 that names it. The saved
|
||||
selection is also what the FHIR REST face and the MCP doctor-visit surfaces replay for a caller that cannot ask
|
||||
a human, so every write is audit-logged. Auth via cookie or Bearer.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SavedReportProfile"
|
||||
responses:
|
||||
"200":
|
||||
description: The saved profile, echoed back.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/PutReportSelectionResponseEnvelope"
|
||||
"401": *a1
|
||||
"422": *a3
|
||||
"429": *a4
|
||||
/api/insights/chat:
|
||||
get:
|
||||
tags:
|
||||
@@ -13691,6 +13733,40 @@ components:
|
||||
`null` switches the alert off. `baseUpdatedAt` is the optional optimistic-concurrency token: echo it to have the
|
||||
server refuse (409) a write that would silently revert a category another writer set from a fresher read (e.g.
|
||||
iOS `medication.clientManaged`). Omit it for the legacy unconditional write."
|
||||
SavedReportProfile:
|
||||
type: object
|
||||
properties:
|
||||
v:
|
||||
type: number
|
||||
const: 2
|
||||
leaves:
|
||||
maxItems: 91
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 64
|
||||
format:
|
||||
type: string
|
||||
enum:
|
||||
- pdf
|
||||
- fhir
|
||||
- package
|
||||
rangeDays:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 365
|
||||
includeCharts:
|
||||
type: boolean
|
||||
required:
|
||||
- v
|
||||
- leaves
|
||||
- format
|
||||
- rangeDays
|
||||
- includeCharts
|
||||
additionalProperties: false
|
||||
description: "A saved doctor-report scope: which leaves are included plus the export format, trailing window and chart
|
||||
toggle. Replace-only — there is no partial-merge write."
|
||||
FencedCoachChatRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -24686,6 +24762,61 @@ components:
|
||||
- data
|
||||
- error
|
||||
additionalProperties: false
|
||||
GetReportSelectionResponseEnvelope:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: "#/components/schemas/GetReportSelectionResponse"
|
||||
error:
|
||||
type: "null"
|
||||
meta:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
additionalProperties: false
|
||||
required:
|
||||
- data
|
||||
- error
|
||||
additionalProperties: false
|
||||
GetReportSelectionResponse:
|
||||
type: object
|
||||
properties:
|
||||
profile:
|
||||
anyOf:
|
||||
- $ref: "#/components/schemas/SavedReportProfile"
|
||||
- type: "null"
|
||||
description: The saved profile, or null when the account has never saved one, or when the stored blob no longer parses
|
||||
against the current leaf catalogue. Null is never resolved to a default scope server-side — the client
|
||||
applies its own named template and shows that as a visible choice.
|
||||
required:
|
||||
- profile
|
||||
additionalProperties: false
|
||||
PutReportSelectionResponseEnvelope:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: "#/components/schemas/PutReportSelectionResponse"
|
||||
error:
|
||||
type: "null"
|
||||
meta:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
additionalProperties: false
|
||||
required:
|
||||
- data
|
||||
- error
|
||||
additionalProperties: false
|
||||
PutReportSelectionResponse:
|
||||
type: object
|
||||
properties:
|
||||
profile:
|
||||
$ref: "#/components/schemas/SavedReportProfile"
|
||||
required:
|
||||
- profile
|
||||
additionalProperties: false
|
||||
CoachConversationsPageResponse:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -12,6 +12,7 @@ import { notificationPrefsSchema } from "@/lib/validations/notification-prefs";
|
||||
import { sourcePrioritySchema } from "@/lib/validations/source-priority";
|
||||
import { modulePrefsPatchSchema } from "@/lib/validations/modules";
|
||||
import { MODULE_KEYS } from "@/lib/modules/registry";
|
||||
import { savedReportProfileSchema } from "@/lib/report-selection/profile-shape";
|
||||
import {
|
||||
dataEnvelope,
|
||||
errorEnvelope,
|
||||
@@ -199,6 +200,33 @@ const coachPrefsPutRequest = coachPrefsSchema
|
||||
"Coach prompt-tuning preferences to persist, plus the optional optimistic-concurrency `baseUpdatedAt` token. The guarded write covers both `coachPrefsJson` and the mirrored `insightsExcludeMetrics` column atomically. Omit the token for the legacy unconditional write.",
|
||||
});
|
||||
|
||||
// v1.28-era — the owner's saved doctor-report selection (leaf list plus the
|
||||
// render choices the export panel restores). `v` is the report-selection
|
||||
// schema version (currently locked at 2); `leaves` is a closed catalogue of
|
||||
// section/field ids, canonicalised to a fixed order server-side so two
|
||||
// clients that chose the same scope persist the same bytes. This is the ONLY
|
||||
// request body for the PUT — it replaces the stored profile whole, it never
|
||||
// merges.
|
||||
const savedReportProfile = savedReportProfileSchema.meta({
|
||||
id: "SavedReportProfile",
|
||||
description:
|
||||
"A saved doctor-report scope: which leaves are included plus the export format, trailing window and chart toggle. Replace-only — there is no partial-merge write.",
|
||||
});
|
||||
|
||||
const reportSelectionGetResponse = z
|
||||
.object({
|
||||
profile: savedReportProfile
|
||||
.nullable()
|
||||
.describe(
|
||||
"The saved profile, or null when the account has never saved one, or when the stored blob no longer parses against the current leaf catalogue. Null is never resolved to a default scope server-side — the client applies its own named template and shows that as a visible choice.",
|
||||
),
|
||||
})
|
||||
.meta({ id: "GetReportSelectionResponse" });
|
||||
|
||||
const reportSelectionPutResponse = z
|
||||
.object({ profile: savedReportProfile })
|
||||
.meta({ id: "PutReportSelectionResponse" });
|
||||
|
||||
// v1.8.6 — profile read/write surface for the native client. The
|
||||
// runtime validation lives in `src/lib/validations/auth.ts`
|
||||
// (`profileSchema`, whose transforms normalise empty → null and run the
|
||||
@@ -850,4 +878,50 @@ export const profilePaths: NonNullable<ZodOpenApiObject["paths"]> = {
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/auth/me/report-selection": {
|
||||
get: {
|
||||
tags: ["Auth"],
|
||||
summary: "Read the owner's saved doctor-report selection",
|
||||
description:
|
||||
"Returns the saved report-scope profile, or `profile: null` when the account has never saved one (or the stored blob no longer parses against the current leaf catalogue). Replaces the retired `GET /api/auth/me/doctor-report-prefs`. Auth via cookie or Bearer.",
|
||||
responses: {
|
||||
"200": {
|
||||
description: "The saved profile, or null.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: dataEnvelope(
|
||||
reportSelectionGetResponse,
|
||||
"GetReportSelectionResponseEnvelope",
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
...stdResponses,
|
||||
},
|
||||
},
|
||||
put: {
|
||||
tags: ["Auth"],
|
||||
summary: "Replace the owner's saved doctor-report selection",
|
||||
description:
|
||||
"Replace, not merge — the body states the whole scope or it is not a scope; a leaf omitted from the body is a leaf removed from the saved profile. An unknown leaf id is refused with a 422 that names it. The saved selection is also what the FHIR REST face and the MCP doctor-visit surfaces replay for a caller that cannot ask a human, so every write is audit-logged. Auth via cookie or Bearer.",
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: { "application/json": { schema: savedReportProfile } },
|
||||
},
|
||||
responses: {
|
||||
"200": {
|
||||
description: "The saved profile, echoed back.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: dataEnvelope(
|
||||
reportSelectionPutResponse,
|
||||
"PutReportSelectionResponseEnvelope",
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
...stdResponses,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in new issue
Block a user