mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
chore(openapi): document date-time fields as offset-bearing ISO-8601
v1.4.25 W7 phase 3.4 — proposal §3 symptom 10.
The schema patterns on every 'format: date-time' field already
accept both 'Z' and '±HH:MM' suffixes (the Zod sources use
{ offset: true }), so the wire contract is technically correct. The
discoverability problem is that consumers reading the spec assume
'date-time' implies UTC.
Adds an explicit 'Date-time contract' paragraph to the API
description naming the convention: server responses emit the
requesting user's offset when a user context is present (exports,
doctor-report PDF), background-job-authored payloads emit 'Z',
clients must accept both.
Regenerated docs/api/openapi.yaml via pnpm openapi:generate; check
passes.
This commit is contained in:
1 parent
ce6d6be95a
commit
beb61b78bf
3 files changed
+32
-23
No files matched your search
+22
-21
@@ -210,8 +210,7 @@ components:
|
||||
- error
|
||||
type: object
|
||||
DeviceRegisterRequest:
|
||||
description:
|
||||
Native device registration. Re-registering an APNs token belonging to another user returns 409
|
||||
description: Native device registration. Re-registering an APNs token belonging to another user returns 409
|
||||
(cross-user-hijack guard).
|
||||
properties:
|
||||
apnsEnvironment:
|
||||
@@ -354,8 +353,7 @@ components:
|
||||
type: object
|
||||
InsightsComprehensiveResponse:
|
||||
additionalProperties: false
|
||||
description:
|
||||
AI-generated insights bundle. Strict-schema validated server-side; Coach-routed when the insight surface
|
||||
description: AI-generated insights bundle. Strict-schema validated server-side; Coach-routed when the insight surface
|
||||
needs day-level grounding.
|
||||
properties:
|
||||
citations:
|
||||
@@ -699,7 +697,18 @@ info:
|
||||
contact:
|
||||
name: HealthLog
|
||||
url: https://healthlog.dev
|
||||
description: Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest.
|
||||
description: >-
|
||||
Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest.
|
||||
|
||||
|
||||
## Date-time contract
|
||||
|
||||
|
||||
Every field marked `format: date-time` is an ISO-8601 instant. The schema pattern accepts both `Z` (UTC) and
|
||||
`±HH:MM` (offset) suffixes; clients must accept either. Server responses since v1.4.25 emit timestamps with the
|
||||
requesting user's display-timezone offset when a user context exists (exports, doctor-report PDF).
|
||||
Background-job-authored payloads (backups, admin tools) emit `Z`. Native iOS clients should always parse via a
|
||||
Foundation ISO-8601 formatter with the `withInternetDateTime` + `withTimeZone` options enabled.
|
||||
license:
|
||||
name: AGPL-3.0
|
||||
url: https://github.com/MBombeck/HealthLog/blob/main/LICENSE
|
||||
@@ -709,8 +718,7 @@ openapi: 3.1.0
|
||||
paths:
|
||||
/api/auth/login:
|
||||
post:
|
||||
description:
|
||||
"Browser callers receive a session cookie. Native callers (X-Client-Type: native or HealthLog-iOS UA
|
||||
description: "Browser callers receive a session cookie. Native callers (X-Client-Type: native or HealthLog-iOS UA
|
||||
prefix) additionally receive a paired access + refresh token."
|
||||
requestBody:
|
||||
content:
|
||||
@@ -758,8 +766,7 @@ paths:
|
||||
- Auth
|
||||
/api/auth/me/coach-prefs:
|
||||
get:
|
||||
description:
|
||||
Returns the persisted preferences with defaults filled in. Null persisted state resolves to the legacy
|
||||
description: Returns the persisted preferences with defaults filled in. Null persisted state resolves to the legacy
|
||||
v1.4.22 defaults.
|
||||
responses:
|
||||
"200":
|
||||
@@ -775,8 +782,7 @@ paths:
|
||||
tags:
|
||||
- Auth
|
||||
put:
|
||||
description:
|
||||
Persists the supplied prefs. Body is validated against `CoachPrefs`; missing keys fall back to the
|
||||
description: Persists the supplied prefs. Body is validated against `CoachPrefs`; missing keys fall back to the
|
||||
documented defaults.
|
||||
requestBody:
|
||||
content:
|
||||
@@ -854,8 +860,7 @@ paths:
|
||||
- Auth
|
||||
/api/auth/refresh:
|
||||
post:
|
||||
description:
|
||||
Reuse of a consumed refresh token revokes every refresh token still active for the originating device
|
||||
description: Reuse of a consumed refresh token revokes every refresh token still active for the originating device
|
||||
(per-device blast radius from v1.4.23). Legacy tokens issued before v1.4.23 with a null deviceId fall back to
|
||||
revoke-all-for-user.
|
||||
requestBody:
|
||||
@@ -879,8 +884,7 @@ paths:
|
||||
- Auth
|
||||
/api/devices:
|
||||
post:
|
||||
description:
|
||||
Idempotent upsert by `token`. APNs token + environment are paired — supplying one without the other returns
|
||||
description: Idempotent upsert by `token`. APNs token + environment are paired — supplying one without the other returns
|
||||
422. Cross-user re-registration of either identifier returns 409.
|
||||
requestBody:
|
||||
content:
|
||||
@@ -909,8 +913,7 @@ paths:
|
||||
- Devices
|
||||
/api/insights/chat/messages/{id}/feedback:
|
||||
post:
|
||||
description:
|
||||
Persists a helpful/unhelpful rating for a single Coach reply. Reuses the v1.4.16 RecommendationFeedback
|
||||
description: Persists a helpful/unhelpful rating for a single Coach reply. Reuses the v1.4.16 RecommendationFeedback
|
||||
table via the polymorphic `targetType` column. The aggregator buckets ratings by (promptVersion, tone,
|
||||
verbosity).
|
||||
requestBody:
|
||||
@@ -946,8 +949,7 @@ paths:
|
||||
- Insights
|
||||
/api/insights/comprehensive:
|
||||
get:
|
||||
description:
|
||||
Full Insights surface — daily briefing, recommendations with rationale, optional weekly report + storyboard
|
||||
description: Full Insights surface — daily briefing, recommendations with rationale, optional weekly report + storyboard
|
||||
annotations. Strict-schema validated server-side.
|
||||
responses:
|
||||
"200":
|
||||
@@ -1119,8 +1121,7 @@ paths:
|
||||
- Measurements
|
||||
/api/measurements/batch:
|
||||
post:
|
||||
description:
|
||||
Up to 500 HealthKit entries per call. Idempotent via the `Idempotency-Key` header (replay window 24h).
|
||||
description: Up to 500 HealthKit entries per call. Idempotent via the `Idempotency-Key` header (replay window 24h).
|
||||
Per-entry status lets the iOS client advance its sync cursor accurately.
|
||||
requestBody:
|
||||
content:
|
||||
|
||||
@@ -1015,6 +1015,7 @@ export default function InsightsPage() {
|
||||
</div>
|
||||
|
||||
<HealthChart
|
||||
chartKey="bp"
|
||||
types={["BLOOD_PRESSURE_SYS", "BLOOD_PRESSURE_DIA"]}
|
||||
title={t("charts.bloodPressure")}
|
||||
colors={["#ff79c6", "#8be9fd"]}
|
||||
@@ -1227,6 +1228,7 @@ export default function InsightsPage() {
|
||||
</div>
|
||||
|
||||
<HealthChart
|
||||
chartKey="weight"
|
||||
types={["WEIGHT"]}
|
||||
title={t("charts.weight")}
|
||||
colors={["#bd93f9"]}
|
||||
@@ -1397,6 +1399,7 @@ export default function InsightsPage() {
|
||||
</div>
|
||||
|
||||
<HealthChart
|
||||
chartKey="pulse"
|
||||
types={["PULSE"]}
|
||||
title={t("charts.pulse")}
|
||||
colors={["#50fa7b"]}
|
||||
@@ -1431,7 +1434,7 @@ export default function InsightsPage() {
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<MoodChart compareBaseline={compareBaseline} />
|
||||
<MoodChart chartKey="mood" compareBaseline={compareBaseline} />
|
||||
|
||||
<InsightStatusCard
|
||||
title={t("insights.assessmentTitle")}
|
||||
@@ -1562,6 +1565,7 @@ export default function InsightsPage() {
|
||||
|
||||
{user?.heightCm ? (
|
||||
<HealthChart
|
||||
chartKey="bmi"
|
||||
types={["WEIGHT"]}
|
||||
title={t("targets.bmi")}
|
||||
colors={["#f1fa8c"]}
|
||||
|
||||
@@ -35,7 +35,11 @@ export const openApiBase: Pick<
|
||||
title: "HealthLog API",
|
||||
version: "1.4.23",
|
||||
description:
|
||||
"Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest.",
|
||||
"Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest.\n\n" +
|
||||
"## Date-time contract\n\n" +
|
||||
"Every field marked `format: date-time` is an ISO-8601 instant. The schema pattern accepts both `Z` (UTC) and `±HH:MM` (offset) suffixes; clients must accept either. " +
|
||||
"Server responses since v1.4.25 emit timestamps with the requesting user's display-timezone offset when a user context exists (exports, doctor-report PDF). Background-job-authored payloads (backups, admin tools) emit `Z`. " +
|
||||
"Native iOS clients should always parse via a Foundation ISO-8601 formatter with the `withInternetDateTime` + `withTimeZone` options enabled.",
|
||||
license: {
|
||||
name: "AGPL-3.0",
|
||||
url: "https://github.com/MBombeck/HealthLog/blob/main/LICENSE",
|
||||
|
||||
Reference in new issue
Block a user