From 5e21363e0f2c4785f610125f171ce972148bad29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 1 Oct 2026 10:06:39 +0200 Subject: [PATCH] docs(comments): correct four comments that describe gates and mints that no longer exist - /api/auth/me and the AuthUser type described disableCoach as the gate every Coach surface checks below a flags.coach short-circuit. Neither has been true since the AI capability resolution: it is the account's stored opt-out, and surfaces read ai.capabilities.coach or modules.coach. - /api/mcp/tokens claimed /api/tokens mints medication:ingest; that mint was removed, and the medication pair now comes from the per-medication endpoint toggle. - /api/meta/capabilities listed the token kinds as wildcard, medication ingest or MCP, missing measurements:write, workouts:write and documents:write. Comment only: the served scopeMintable answer for the FHIR face is unchanged and still right. --- src/app/api/auth/me/route.ts | 11 ++++++----- src/app/api/mcp/tokens/route.ts | 4 +++- src/app/api/meta/capabilities/route.ts | 12 +++++++----- src/hooks/use-auth.ts | 15 ++++++++------- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/app/api/auth/me/route.ts b/src/app/api/auth/me/route.ts index 2dfa2bc58..e150408eb 100644 --- a/src/app/api/auth/me/route.ts +++ b/src/app/api/auth/me/route.ts @@ -346,11 +346,12 @@ export const GET = apiHandler(async () => { // defaults rather than to `undefined`, so the switch is what renders. // No extra query — the session already loads the row this column is on. notificationPrefs: parseNotificationPrefs(user.notificationPrefs ?? null), - // v1.4.47 W3 — per-user Coach opt-out. Default `false` if the - // column is absent (partial-deploy rollback safety, see migration - // 0078 commentary). Every Coach mount point on the client checks - // `user.disableCoach` BELOW the operator-level `flags.coach` - // short-circuit; both gates must agree to paint the affordance. + // v1.4.47 W3 — the caller's own stored Coach opt-out, published for the + // switch that edits it. Default `false` if the column is absent + // (partial-deploy rollback safety, see migration 0078 commentary). It is + // not a gate: whether the Coach shows for the record on screen is the + // resolved `ai.capabilities.coach` and `modules.coach` below, which fold + // in the record's own opt-out, the operator's switches and the grant. disableCoach: user.disableCoach ?? false, // v1.7.0 — health-record export identity fields. All optional. fullName: user.fullName ?? null, diff --git a/src/app/api/mcp/tokens/route.ts b/src/app/api/mcp/tokens/route.ts index 14ccdb37e..e79f93e6c 100644 --- a/src/app/api/mcp/tokens/route.ts +++ b/src/app/api/mcp/tokens/route.ts @@ -2,7 +2,9 @@ * MCP connector tokens — list + mint. * * The MCP settings card mints a DEDICATED `health:read`-scoped Bearer here (NOT - * the `medication:ingest` scope the generic `/api/tokens` mints, and NEVER the + * one of the write scopes the other token surfaces mint — the per-medication + * ingest pair `medication:ingest` + `medication::ingest`, + * `measurements:write`, `workouts:write`, `documents:write` — and NEVER the * `["*"]` wildcard). The raw `hlk_` value is shown once. This is the manual / * stdio / power-user path; the OAuth bridge (`/api/mcp/oauth/*`) mints the same * `health:read` scope automatically for cloud connectors. Both surface here so diff --git a/src/app/api/meta/capabilities/route.ts b/src/app/api/meta/capabilities/route.ts index f698a3a84..5b442dc17 100644 --- a/src/app/api/meta/capabilities/route.ts +++ b/src/app/api/meta/capabilities/route.ts @@ -109,11 +109,13 @@ export const GET = apiHandler(async () => { // Bearer scope. All sourced from the canonical `rest.ts` constants. restBaseUrl: "/api/fhir", // The face checks a narrow `fhir:read` scope, and NO code path mints a - // token carrying it — every mint grants a wildcard, the medication - // ingest scope, or an MCP scope. So the face is reachable by the owner's - // cookie session or a wildcard device token, and by nothing else. It is - // reported that way rather than advertising a credential a client cannot - // obtain. + // token carrying it — every mint grants a wildcard (login, passkey, + // refresh), the per-medication ingest pair (`medication:ingest` + + // `medication::ingest`), `measurements:write`, `workouts:write`, + // `documents:write`, or an MCP scope (`health:read`, `health:write`). + // So the face is reachable by the owner's cookie session or a wildcard + // device token, and by nothing else. It is reported that way rather than advertising a credential a + // client cannot obtain. scopeMintable: false, resourceTypes: FHIR_REST_RESOURCE_TYPES, operations: [FHIR_EVERYTHING_OPERATION], diff --git a/src/hooks/use-auth.ts b/src/hooks/use-auth.ts index 65096bd96..dae619122 100644 --- a/src/hooks/use-auth.ts +++ b/src/hooks/use-auth.ts @@ -144,13 +144,14 @@ export interface AuthUser { */ dateFormat: DateFormatPreference; /** - * v1.4.47 W3 — per-user Coach opt-out. When `true`, every Coach - * mount point (``, ``, the - * inline `` pill, the `/targets` page CTA) - * renders nothing. The gate sits BELOW the operator-level - * `flags.coach` short-circuit — both must agree to render the - * affordance. Defaults to `false` when the field is absent (e.g. - * stale /me payload from a partial-deploy rollback). + * v1.4.47 W3 — the signed-in person's own stored Coach opt-out. It is + * the value the Activate-Coach switch and the module toggle edit, and + * nothing else should read it: it belongs to the account, not to the + * record on screen, and it is only one of the layers that decide whether + * the Coach is there. Every Coach surface gates on the resolved answers + * instead — `ai.capabilities.coach` (`useAiCapability("coach")`) for + * the affordances, `modules.coach` for the Coach's settings and tuning. + * Defaults to `false` when the field is absent (a stale /me payload). */ disableCoach: boolean; /**