feat(api): add emergency profile read and write route

GET/PATCH /api/anamnesis/emergency, wrapped in apiHandler. The PATCH
validates a partial body with per-field length caps, builds the Prisma
data field-by-field from the parsed input (never a spread), narrows the
user from requireAuth rather than the body, encrypts the free text on
write, and audits the change. The GET decrypts fail-soft for the form
prefill. Registers the OpenAPI operations and schema. An integration
test reads the row back to prove the write lands.
This commit is contained in:
Marc-André Bombeck committed 2026-08-10 05:32:59 +02:00
1 parent 772da42348
commit 6770bf3b7f
7 files changed
+788 -3

No files matched your search

+244 -3
View File
@@ -932,7 +932,7 @@ paths:
type: number
const: 2
leaves:
maxItems: 93
maxItems: 94
type: array
items:
type: string
@@ -1037,7 +1037,7 @@ paths:
type: number
const: 2
leaves:
maxItems: 93
maxItems: 94
type: array
items:
type: string
@@ -6842,6 +6842,93 @@ paths:
$ref: "#/components/schemas/ErrorEnvelope"
"422": *a3
"429": *a4
/api/anamnesis/emergency:
get:
tags:
- Insights
summary: Read the emergency profile
description: "Returns the caller's emergency (Notfalldaten) profile: blood type, organ-donor and advance-directive
declarations, and the decrypted emergency contacts, implants/devices and ICE note. Free text decrypts
fail-soft."
responses:
"200":
description: The emergency profile (fields null when unset).
content:
application/json:
schema:
$ref: "#/components/schemas/GetEmergencyProfileResponse"
"401": *a1
"422": *a3
"429": *a4
patch:
tags:
- Insights
summary: Update the emergency profile
description: Partial edit of the emergency profile on the caller's own record. Free-text fields are AES-256-GCM
encrypted before persistence. Audits as `anamnesis.emergency.update`.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
bloodType:
anyOf:
- type: string
enum:
- A_POS
- A_NEG
- B_POS
- B_NEG
- AB_POS
- AB_NEG
- O_POS
- O_NEG
- UNKNOWN
- type: "null"
organDonor:
anyOf:
- type: string
enum:
- YES
- NO
- UNKNOWN
- type: "null"
advanceDirective:
anyOf:
- type: string
enum:
- EXISTS
- NONE
- UNKNOWN
- type: "null"
contacts:
anyOf:
- type: string
maxLength: 2000
- type: "null"
implants:
anyOf:
- type: string
maxLength: 1000
- type: "null"
note:
anyOf:
- type: string
maxLength: 2000
- type: "null"
additionalProperties: false
responses:
"200":
description: The updated emergency profile.
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateEmergencyProfileResponse"
"401": *a1
"422": *a3
"429": *a4
/api/coach/about-me/questions:
get:
tags:
@@ -16157,7 +16244,7 @@ components:
type: number
const: 2
leaves:
maxItems: 93
maxItems: 94
type: array
items:
type: string
@@ -29624,6 +29711,160 @@ components:
- data
- error
additionalProperties: false
GetEmergencyProfileResponse:
type: object
properties:
data:
type: object
properties:
bloodType:
anyOf:
- type: string
enum:
- A_POS
- A_NEG
- B_POS
- B_NEG
- AB_POS
- AB_NEG
- O_POS
- O_NEG
- UNKNOWN
- type: "null"
organDonor:
anyOf:
- type: string
enum:
- YES
- NO
- UNKNOWN
- type: "null"
advanceDirective:
anyOf:
- type: string
enum:
- EXISTS
- NONE
- UNKNOWN
- type: "null"
contacts:
anyOf:
- type: string
- type: "null"
contactsUnreadable:
type: boolean
implants:
anyOf:
- type: string
- type: "null"
implantsUnreadable:
type: boolean
note:
anyOf:
- type: string
- type: "null"
noteUnreadable:
type: boolean
required:
- bloodType
- organDonor
- advanceDirective
- contacts
- contactsUnreadable
- implants
- implantsUnreadable
- note
- noteUnreadable
additionalProperties: false
error:
type: "null"
meta:
type: object
properties:
requestId:
type: string
additionalProperties: false
required:
- data
- error
additionalProperties: false
UpdateEmergencyProfileResponse:
type: object
properties:
data:
type: object
properties:
bloodType:
anyOf:
- type: string
enum:
- A_POS
- A_NEG
- B_POS
- B_NEG
- AB_POS
- AB_NEG
- O_POS
- O_NEG
- UNKNOWN
- type: "null"
organDonor:
anyOf:
- type: string
enum:
- YES
- NO
- UNKNOWN
- type: "null"
advanceDirective:
anyOf:
- type: string
enum:
- EXISTS
- NONE
- UNKNOWN
- type: "null"
contacts:
anyOf:
- type: string
- type: "null"
contactsUnreadable:
type: boolean
implants:
anyOf:
- type: string
- type: "null"
implantsUnreadable:
type: boolean
note:
anyOf:
- type: string
- type: "null"
noteUnreadable:
type: boolean
required:
- bloodType
- organDonor
- advanceDirective
- contacts
- contactsUnreadable
- implants
- implantsUnreadable
- note
- noteUnreadable
additionalProperties: false
error:
type: "null"
meta:
type: object
properties:
requestId:
type: string
additionalProperties: false
required:
- data
- error
additionalProperties: false
GetCoachAboutMeQuestionsResponse:
type: object
properties: