diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index 9255e81e3..aa48c04d7 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -82136,7 +82136,7 @@ components: - type: "null" syncHealth: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Present on the GET read; omitted from the PATCH echo." + description: "Deprecated, still served: read `health`. Present on the GET read; omitted from the PATCH echo." $ref: "#/components/schemas/SyncHealth" metricFreshness: description: Per-metric-type freshness for the `APPLE_HEALTH` source, with the per-type arrival facts. Present on the @@ -82814,7 +82814,7 @@ components: type: boolean state: deprecated: true - description: "Deprecated: removed in v1.44, read `health`." + description: "Deprecated, still served: read `health`." type: string enum: - connected @@ -82837,14 +82837,14 @@ components: - type: "null" lastError: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Last recorded failure message, decrypted from the ledger. - Null when the last attempt succeeded or none has run." + description: "Deprecated, still served: read `health`. Last recorded failure message, decrypted from the ledger. Null + when the last attempt succeeded or none has run." type: - string - "null" syncHealth: deprecated: true - description: "Deprecated: removed in v1.44, read `health`." + description: "Deprecated, still served: read `health`." $ref: "#/components/schemas/SyncHealth" health: description: The unified connection state. Present whenever the connection exists; null in the rare case it resolved to @@ -83033,9 +83033,9 @@ components: pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ tokenExpired: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. The stored access token's expiry is in the past. Read - straight off the row — unlike the Withings status read, this endpoint does not refresh; the sync path - refreshes lazily instead." + description: "Deprecated, still served: read `health`. The stored access token's expiry is in the past. Read straight + off the row — unlike the Withings status read, this endpoint does not refresh; the sync path refreshes + lazily instead." type: boolean tokenExpiresAt: type: string @@ -83124,8 +83124,7 @@ components: pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ tokenExpired: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. True after a refresh attempt that did not produce a live - token." + description: "Deprecated, still served: read `health`. True after a refresh attempt that did not produce a live token." type: boolean tokenRefreshFailed: description: The read tried to refresh an expired token and could not — either the per-user credentials are gone or @@ -83145,8 +83144,8 @@ components: - "null" hasActivityScope: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Pre-computed convenience flag the reconnect banner reads. A - null `scope` counts as missing activity." + description: "Deprecated, still served: read `health`. Pre-computed convenience flag the reconnect banner reads. A null + `scope` counts as missing activity." type: boolean health: description: The unified connection state. Present whenever the connection exists; null in the rare case it resolved to @@ -83455,8 +83454,8 @@ components: pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ tokenExpired: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Read straight off the row — this endpoint does not refresh; - the sync path refreshes lazily." + description: "Deprecated, still served: read `health`. Read straight off the row — this endpoint does not refresh; the + sync path refreshes lazily." type: boolean tokenExpiresAt: type: string @@ -83626,8 +83625,8 @@ components: pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ tokenExpired: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Read straight off the row — this endpoint does not refresh; - the sync path refreshes lazily." + description: "Deprecated, still served: read `health`. Read straight off the row — this endpoint does not refresh; the + sync path refreshes lazily." type: boolean tokenExpiresAt: type: string @@ -83677,7 +83676,7 @@ components: when every type was read to its start. Kept after the backfill completes; cleared on reconnect. needsReauth: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. The stored refresh token was rejected with `invalid_grant` — + description: "Deprecated, still served: read `health`. The stored refresh token was rejected with `invalid_grant` — Google expires it after 7 days while the OAuth client is in Testing publishing mode, and a user-revoked grant lands here too. Distinct from `parked` and from `disconnected`: the connection still exists, it just cannot mint a token until the user reconnects. Only Google Health has this field." @@ -83881,7 +83880,7 @@ components: description: The user has stored their own BYO client id and secret. state: deprecated: true - description: "Deprecated: removed in v1.44, read `health`." + description: "Deprecated, still served: read `health`." type: string enum: - connected @@ -83904,13 +83903,13 @@ components: - type: "null" lastError: deprecated: true - description: "Deprecated: removed in v1.44, read `health`." + description: "Deprecated, still served: read `health`." type: - string - "null" syncHealth: deprecated: true - description: "Deprecated: removed in v1.44, read `health`." + description: "Deprecated, still served: read `health`." $ref: "#/components/schemas/SyncHealth" health: description: The unified connection state. Present whenever the connection exists; null in the rare case it resolved to @@ -84305,7 +84304,7 @@ components: - disconnected - parked - unknown - description: "Deprecated: removed in v1.44, read `health`." + description: "Deprecated, still served: read `health`." deprecated: true lastSuccessAt: anyOf: @@ -84321,7 +84320,7 @@ components: - type: "null" lastError: deprecated: true - description: "Deprecated: removed in v1.44, read `health`." + description: "Deprecated, still served: read `health`." type: - string - "null" @@ -84348,11 +84347,11 @@ components: additionalProperties: false - type: "null" deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Per-kind consecutive-failure counters, or null when the row - has never written a bucket payload. Compare against the top-level `threshold` to know how close the provider - is to the operator alert." + description: "Deprecated, still served: read `health`. Per-kind consecutive-failure counters, or null when the row has + never written a bucket payload. Compare against the top-level `threshold` to know how close the provider is + to the operator alert." syncHealth: - description: "Deprecated: removed in v1.44, read `health`." + description: "Deprecated, still served: read `health`." deprecated: true $ref: "#/components/schemas/SyncHealth" metricFreshness: @@ -84389,7 +84388,7 @@ components: - type: "null" tokenExpired: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Null — not false — when there is no connection to judge." + description: "Deprecated, still served: read `health`. Null — not false — when there is no connection to judge." type: - boolean - "null" @@ -84432,14 +84431,14 @@ components: - "null" hasActivityScope: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Withings only." + description: "Deprecated, still served: read `health`. Withings only." type: boolean planUnavailable: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Withings only. The readings this connection's Withings API - plan withholds (status 277 since the 2026-10-12 plan split), deduplicated and in display order. Empty when - the plan refuses nothing. The sync skips these and keeps importing everything else; the list refreshes when - the weekly re-probe asks again." + description: "Deprecated, still served: read `health`. Withings only. The readings this connection's Withings API plan + withholds (status 277 since the 2026-10-12 plan split), deduplicated and in display order. Empty when the + plan refuses nothing. The sync skips these and keeps importing everything else; the list refreshes when the + weekly re-probe asks again." type: array items: type: string @@ -84468,7 +84467,7 @@ components: - weight needsReauth: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Google Health only." + description: "Deprecated, still served: read `health`. Google Health only." type: boolean available: description: Oura / Polar / Strava only. @@ -84478,7 +84477,7 @@ components: type: boolean scopeReconnect: deprecated: true - description: "Deprecated: removed in v1.44, read `health`. Oura only. Collections the stored grant does not cover: Oura + description: "Deprecated, still served: read `health`. Oura only. Collections the stored grant does not cover: Oura refused them for a missing scope (named in its 401, or inferred when sibling collections succeeded with the same token), or the scopes Oura reported at connect leave theirs out. Not a failure and not counted toward the reconnect threshold; one reconnect asks for the missing scopes. Empty when the grant covers everything @@ -84534,7 +84533,7 @@ components: description: The unified connection state, null when the provider is not connected (and for Fitbit once `retirement.ended`). It supersedes `state`, `lastError`, `consecutiveFailuresByKind`, `syncHealth`, `tokenExpired`, `needsReauth`, `hasActivityScope`, `planUnavailable` and `scopeReconnect` on this entry; - those nine are deprecated and removed in v1.44. + those nine are deprecated and still served for clients that predate `health`. required: - integration - state diff --git a/src/__tests__/baselines/version-stamp-comments.json b/src/__tests__/baselines/version-stamp-comments.json index 5a3506c2e..95b97061a 100644 --- a/src/__tests__/baselines/version-stamp-comments.json +++ b/src/__tests__/baselines/version-stamp-comments.json @@ -1,7 +1,7 @@ { "$comment": "Comment lines that open with a release version, per file under src/. Maintained by src/__tests__/version-stamp-ratchet.test.ts.", "count": 2897, - "total": 9247, + "total": 9246, "entries": { "__tests__/account-payload-consumer-guard.test.ts": 2, "__tests__/acting-account-boundary-guard.test.ts": 7, @@ -360,7 +360,7 @@ "app/api/integrations/healthkit/__tests__/route.test.ts": 4, "app/api/integrations/healthkit/route.ts": 3, "app/api/integrations/status/__tests__/route.test.ts": 2, - "app/api/integrations/status/route.ts": 7, + "app/api/integrations/status/route.ts": 6, "app/api/integrations/withings/resume/__tests__/route.test.ts": 1, "app/api/integrations/withings/resume/route.ts": 1, "app/api/internal/deploy-webhook/__tests__/route.test.ts": 2, diff --git a/src/app/api/integrations/status/route.ts b/src/app/api/integrations/status/route.ts index 417037307..56539ee6e 100644 --- a/src/app/api/integrations/status/route.ts +++ b/src/app/api/integrations/status/route.ts @@ -502,8 +502,8 @@ export const GET = apiHandler(async () => { } satisfies IntegrationViewModel & NightscoutExtras, { ...publish(dawarichStatus), - // v1.43 — Dawarich, read by the card through `health`. The ledger core - // rides along like on every entry, and goes with the rest in v1.44. + // Dawarich, read by the card through `health`. The ledger core rides + // along like on every entry. connected: dawarichConfigured, configured: dawarichConfigured, health: health["dawarich"], @@ -524,8 +524,9 @@ interface IntegrationViewModel { * health-shaped field on this entry (`state`, `lastError`, * `consecutiveFailuresByKind`, `syncHealth`, `tokenExpired`, `needsReauth`, * `hasActivityScope`, `planUnavailable`, `scopeReconnect`) is folded into - * it and goes once the settings cards render `health`; no other client - * reads this envelope. + * it. Those stay on the wire, deprecated in the published document; the + * cards render `health`, and only their copied diagnostics still read + * `consecutiveFailuresByKind`. No native client reads this envelope. */ health: ConnectionHealth | null; state: string; diff --git a/src/lib/openapi/routes/integrations.ts b/src/lib/openapi/routes/integrations.ts index c2acc5677..a50b645d7 100644 --- a/src/lib/openapi/routes/integrations.ts +++ b/src/lib/openapi/routes/integrations.ts @@ -75,10 +75,12 @@ const healthKitEntry = z "One resolved HealthKit metric mapping (defaults merged with the user's stored overrides).", }); -// The health-shaped fields that predate `health` (v1.42.4). They stay on the -// wire through v1.43 so App 1.2.0 keeps decoding, are marked deprecated in the -// document, and go in v1.44. -const LEGACY_HEALTH_FIELD = "Deprecated: removed in v1.44, read `health`."; +// The health-shaped fields that predate `health`. They are marked deprecated +// in the document and stay on the wire: native builds from before `health` +// still decode them, the current one falls back to them only against a server +// that sends no `health`, and the web card's copied diagnostics read the +// failure streak. No removal release is set. +const LEGACY_HEALTH_FIELD = "Deprecated, still served: read `health`."; function legacy(text?: string): { deprecated: true; description: string } { return { @@ -1184,7 +1186,7 @@ const integrationEnvelopeEntry = z health: connectionHealth .nullable() .describe( - "The unified connection state, null when the provider is not connected (and for Fitbit once `retirement.ended`). It supersedes `state`, `lastError`, `consecutiveFailuresByKind`, `syncHealth`, `tokenExpired`, `needsReauth`, `hasActivityScope`, `planUnavailable` and `scopeReconnect` on this entry; those nine are deprecated and removed in v1.44.", + "The unified connection state, null when the provider is not connected (and for Fitbit once `retirement.ended`). It supersedes `state`, `lastError`, `consecutiveFailuresByKind`, `syncHealth`, `tokenExpired`, `needsReauth`, `hasActivityScope`, `planUnavailable` and `scopeReconnect` on this entry; those nine are deprecated and still served for clients that predate `health`.", ), }) .meta({