docs(openapi): list every OIDC error reason the native leg can receive

The login route's description named only the four reasons the login step
itself sends. The callback, which the identity provider drives and so has
no OpenAPI entry, ends the native leg at healthlog://oidc-callback with
eight more, and nothing written listed them. An app build matched against
hyphenated shorthand (identity-conflict) while the server has always sent
oidc_identity_conflict, so every SSO error fell through to the generic
message. The values do not change; the description now names the full
set, and a structural test binds it to the literals the two routes pass
to their redirect helpers in both directions.

Regenerates docs/api/openapi.yaml, including the CSV import description
from the previous commit.
This commit is contained in:
Marc-André Bombeck committed 2026-09-26 19:59:11 +02:00
1 parent 24050d84c7
commit 5a054d636e
3 files changed
+93 -6

No files matched your search

+21 -5
View File
@@ -3283,7 +3283,13 @@ paths:
"302":
description: Always a redirect. To the provider on success. On failure to `/auth/login?error=<reason>` (browser) or
`healthlog://oidc-callback?error=<reason>` (native), where reason is one of `oidc_disabled`,
`oidc_rate_limited`, `oidc_invalid_request`, `oidc_failed`.
`oidc_rate_limited`, `oidc_invalid_request`, `oidc_failed`. The provider then returns to the callback (not
listed here, because the identity provider drives it rather than a client), which ends the native leg at
`healthlog://oidc-callback` with `code=<hlh_…>`, with `mfa_ticket=<ticket>&methods=<list>`, or with
`error=<reason>`, where reason is one of `oidc_disabled`, `oidc_rate_limited`, `oidc_denied`,
`oidc_no_email`, `oidc_email_unverified`, `oidc_identity_conflict`, `oidc_registration_disabled`,
`oidc_failed`. The reasons are this exact snake_case vocabulary on both legs; a client maps a value it does
not know to a generic sign-in failure.
/api/auth/passkey/register-options:
post:
tags:
@@ -13063,9 +13069,12 @@ paths:
before 1900). Glucose accepts `mmol/L` (converted to canonical `mg/dL`); weight accepts `lb` (converted to
`kg`). `glucoseContext` is optional on a `BLOOD_GLUCOSE` row — a blank cell stores no context, which is the
normal shape of a continuous-sensor export; a non-empty value is still checked against the enum, and the column
is refused on any other type. An `externalId` column makes re-upload idempotent (upsert on `(userId, type,
source=IMPORT, externalId)`); without it a re-upload duplicates. `?dryRun=1` validates + previews without
writing. Shares the 5/hour `import:` rate bucket."
is refused on any other type. Re-uploading a file is idempotent. With an `externalId` column a row upserts on
`(userId, type, source=IMPORT, externalId)`: a changed row is `updated`, an unchanged one is `skipped` with
reason `duplicate` and not written. Without it a row is deduplicated on `(type, measuredAt)` and a repeat is
`skipped` / `duplicate`. Writes commit in chunks rather than as one transaction; a failure part-way leaves
earlier chunks written, and re-uploading the same file completes the rest. `?dryRun=1` validates + previews
without writing. Shares the 5/hour `import:` rate bucket."
parameters:
- name: dryRun
in: query
@@ -35818,6 +35827,11 @@ components:
anyOf:
- type: string
- type: "null"
noteEncrypted:
anyOf:
- type: string
minLength: 1
- type: "null"
createdAt:
type: string
minLength: 1
@@ -36495,6 +36509,9 @@ components:
minLength: 1
title:
type: string
titleEncrypted:
type: string
minLength: 1
documentScoped:
type: boolean
summaryEncrypted:
@@ -36586,7 +36603,6 @@ components:
additionalProperties: {}
required:
- id
- title
- documentScoped
- createdAt
- updatedAt