docs(insights): document english tile-id contract + naming ADR

Regenerate `docs/api/openapi.yaml` so the `InsightsLayoutBody` enum
carries the canonical English tile ids first, then the
accepted-but-deprecated legacy German ids, with the normalisation +
deprecation spelled out in the schema description. Add ADR 0001 fixing
the convention — localised UI copy, English internal identifiers — and
the non-breaking alias strategy. Add an iOS coordination note covering
the new canonical ids, the continued acceptance of the legacy ids, and
the recommended migration path.
This commit is contained in:
Marc-André Bombeck committed 2026-05-31 22:12:25 +02:00
1 parent 607dd9e5df
commit 262a3ad70a
4 files changed
+214 -12

No files matched your search

+16 -4
View File
@@ -44,7 +44,7 @@ import {
MEDICATION_TREATMENT_CLASS_VALUES,
} from "@/lib/validations/medication";
import { medicationExtractionSchema } from "@/lib/ai/coach/medication-extract-prompt";
import { INSIGHTS_TILE_IDS } from "@/lib/insights-layout";
import { ACCEPTED_INSIGHTS_TILE_IDS } from "@/lib/insights-layout";
import { exportSelectionSchema } from "@/lib/validations/health-record-export";
/**
@@ -1121,14 +1121,26 @@ medicationExtractionSchema.meta({
// Insights tile layout — mirrors the Zod schema in
// `src/app/api/insights/layout/route.ts`. The tile-id enum is derived
// from the same `INSIGHTS_TILE_IDS` source so the contract cannot drift.
// from the same `ACCEPTED_INSIGHTS_TILE_IDS` source so the contract
// cannot drift.
//
// v1.8.0 — the canonical ids are English (`blood-pressure`, `pulse`,
// `oxygen`, `body-temperature`, `weight`, `active-energy`, `sleep`,
// `resting-pulse`, `mood`, `medications`). The endpoint still ACCEPTS
// the legacy German ids (`blutdruck`, `puls`, `sauerstoff`,
// `koerpertemperatur`, `gewicht`, `aktive-energie`, `schlaf`,
// `ruhepuls`, `stimmung`, `medikamente`) on input so existing iOS
// layouts keep validating; the server normalises them to the canonical
// English id before persisting, and GET always returns canonical ids.
// The legacy ids are accepted-but-deprecated and will be dropped from
// the accepted set in a future major.
const insightsLayoutSchema = z
.object({
version: z.literal(1),
tiles: z
.array(
z.object({
id: z.enum(INSIGHTS_TILE_IDS),
id: z.enum(ACCEPTED_INSIGHTS_TILE_IDS),
visible: z.boolean(),
order: z.number().int().min(0).max(99),
}),
@@ -1139,7 +1151,7 @@ const insightsLayoutSchema = z
.meta({
id: "InsightsLayoutBody",
description:
"Per-user Insights tile layout: an ordered list of tiles with a visibility flag. `version` is the layout schema version; tile ids are a closed enum derived from the server's tile registry.",
"Per-user Insights tile layout: an ordered list of tiles with a visibility flag. `version` is the layout schema version. Tile ids are a closed enum: the canonical ids are English (matching the routed `/insights/<slug>` sub-pages). The legacy German ids (blutdruck, puls, sauerstoff, koerpertemperatur, gewicht, aktive-energie, schlaf, ruhepuls, stimmung, medikamente) remain accepted on input for backward compatibility and are normalised to their English equivalents before persisting; GET responses always carry the canonical English ids. The legacy ids are deprecated and will be removed in a future major version.",
});
// v1.7.0 — health-record export selection. Strict shape: unknown keys