Merge remote-tracking branch 'origin/main' into wip/v140-E

This commit is contained in:
Marc-André Bombeck committed 2026-10-03 18:56:39 +02:00
commit f3ccc809a8
28 files changed
+891 -38

No files matched your search

+1
View File
@@ -213,6 +213,7 @@ export const ERROR_CODE_CATALOGUE: Readonly<Record<string, readonly string[]>> =
"labs.ocr.rateLimited",
"labs.restore.invalid",
"labs.result.notFound",
"labs.unit.mismatch",
"labs.update.invalid",
"labs.update.linkedFieldsImmutable",
"labs.update.numericExpected",
+5
View File
@@ -162,6 +162,11 @@ export const labsPaths: NonNullable<ZodOpenApiObject["paths"]> = {
},
},
...stdResponses,
"422": {
description:
"Nothing was written. `meta.errorCode` = `labs.create.invalid` when the body failed validation (every issue under `details.issues`), or `labs.unit.mismatch` when a numeric reading states a `unit` other than the one its marker is tracked in (`meta.markerUnit`, `meta.readingUnit`). A unit is compared only when one is sent; with a `biomarkerId` it may be omitted and the marker's unit is then the stated one. Spelling is forgiven (`mmol/l`, `ug/L` for `µg/L`); a different unit is refused, never relabelled.",
content: { "application/json": { schema: errorEnvelope } },
},
...recordWriteRateLimitResponse,
},
},
+10 -3
View File
@@ -72,6 +72,10 @@ const extractedRow = z
takenAt: z.string().nullable(),
confidence: extractConfidence,
biomarkerMatch: z.enum(["new", "existing"]),
markerUnit: z.string().nullable().meta({
description:
"The unit the matched marker is tracked in, or null when the marker does not exist yet (it will adopt this row's unit). A row whose `unit` differs from it cannot be committed: the commit skips it with `reason: unit_mismatch`, and the review screen marks it before Save.",
}),
duplicateOf: z.string().nullable(),
})
.meta({
@@ -138,7 +142,10 @@ const commitResponse = z
skipped: z.array(
z.object({
analyte: z.string(),
reason: z.literal("duplicate"),
reason: z.enum(["duplicate", "unit_mismatch"]).meta({
description:
"`duplicate`: the row matched a live reading at commit time. `unit_mismatch`: the row states a unit other than the one its marker is tracked in, so it was not written.",
}),
}),
),
outcome: z.enum(["empty", "failed", "partial", "success"]).meta({
@@ -149,7 +156,7 @@ const commitResponse = z
.meta({
id: "OcrCommitResponse",
description:
'The rows written (`source: "OCR"`), those skipped as commit-time duplicates, and the resolved outcome.',
'The rows written (`source: "OCR"`), those skipped (commit-time duplicates, or a unit that differs from that of the marker), and the resolved outcome.',
});
export const ocrPaths: NonNullable<ZodOpenApiObject["paths"]> = {
@@ -223,7 +230,7 @@ export const ocrPaths: NonNullable<ZodOpenApiObject["paths"]> = {
tags: ["Labs"],
summary: "Commit confirmed Lab-OCR rows",
description:
'Writes ONLY the rows the human confirmed on the review screen. Each row resolves-or-mints a user-scoped biomarker and creates a `LabResult` with `source: "OCR"`; a row that duplicates a live reading is skipped. Idempotent (Idempotency-Key). Audits as `labs.ocr.commit`. `userId` is narrowed from the session, never a body field.',
'Writes ONLY the rows the human confirmed on the review screen. Each row resolves-or-mints a user-scoped biomarker and creates a `LabResult` with `source: "OCR"`; a row that duplicates a live reading, or states a unit other than that of its marker, is skipped (`skipped[].reason`). Idempotent (Idempotency-Key). Audits as `labs.ocr.commit`. `userId` is narrowed from the session, never a body field.',
requestBody: {
required: true,
content: { "application/json": { schema: ocrCommitRequest } },