diff --git a/src/app/api/auth/me/route.ts b/src/app/api/auth/me/route.ts index 179658f3b..9d8868d1a 100644 --- a/src/app/api/auth/me/route.ts +++ b/src/app/api/auth/me/route.ts @@ -93,6 +93,21 @@ const SERVER_FEATURES = { lifeCircumstances: true, } as const; +/** + * v1.7.0 — patient-identity fields for the health-record export. The KVNR is + * stored encrypted; decrypt fail-soft so a key-rotation gap on one row never + * 500s the whole profile fetch (the field just reads null and the user + * re-enters it). + */ +function readInsuranceNumber(encrypted: string | null | undefined) { + if (!encrypted) return null; + try { + return decrypt(encrypted); + } catch { + return null; + } +} + export const GET = apiHandler(async () => { const auth = await requireActorAuth(); const { user } = auth; @@ -289,24 +304,13 @@ export const GET = apiHandler(async () => { sectionsOpen(sections, "cycle") && isCycleEnabled(record?.gender ?? null, cycleProfile); - // v1.7.0 — patient-identity fields for the health-record export. The - // KVNR is stored encrypted; decrypt fail-soft so a key-rotation gap on - // one row never 500s the whole profile fetch (the field just reads - // null and the user re-enters it). - let insuranceNumber: string | null = null; - if (identity?.insuranceNumberEncrypted) { - try { - insuranceNumber = decrypt(identity.insuranceNumberEncrypted); - } catch { - insuranceNumber = null; - } - } + const insuranceNumber = readInsuranceNumber( + identity?.insuranceNumberEncrypted, + ); return apiSuccess({ id: user.id, username: user.username, - // When the caller's account was created. The dashboard greeting says - // "welcome", not "welcome back", during an account's first day. createdAt: user.createdAt, email: user.email, role: user.role ?? "USER", diff --git a/src/components/insights/coach-panel/use-coach.ts b/src/components/insights/coach-panel/use-coach.ts index 9d453a7a9..0360bdea2 100644 --- a/src/components/insights/coach-panel/use-coach.ts +++ b/src/components/insights/coach-panel/use-coach.ts @@ -1,6 +1,5 @@ "use client"; -import type { Locale } from "@/lib/i18n/config"; import { useCallback, useEffect, @@ -896,7 +895,7 @@ export interface SendCoachMessageParams { conversationId?: string; message: string; prefill?: string; - locale?: Locale; + locale?: import("@/lib/i18n/config").Locale; /** * v1.4.20.1 — optional snapshot scope (per-source toggles + window) * driven by the sources-rail picker. When omitted the server falls diff --git a/src/lib/ai/coach/types.ts b/src/lib/ai/coach/types.ts index b09114597..322c72c89 100644 --- a/src/lib/ai/coach/types.ts +++ b/src/lib/ai/coach/types.ts @@ -7,7 +7,6 @@ * can pass messages through with minimal translation. */ import { z } from "zod/v4"; - import { locales } from "@/lib/i18n/config"; import { COACH_SCOPE_SOURCES } from "./scope-sources"; @@ -87,19 +86,14 @@ export const coachChatRequestSchema = z.object({ conversationId: z.string().min(1).max(64).optional(), message: z.string().min(1).max(4000), prefill: z.string().max(2000).optional(), - /** - * The reply language: any UI locale. Overrides the cookie and the account's - * stored language for this turn (`resolveServerLocale`). - */ locale: z.enum(locales).optional(), scope: coachScopeSchema.optional(), /** - * v1.16.6 — guided clarifying-questions flow: the pending question - * this message answers. The question bubble is client-side only - * (never persisted), so without this context the model would see a - * bare answer ("since 2019, with medication") and could not react - * to it. Rides the prompt as delimited user-provided context; the - * persisted user turn stays the answer alone. + * v1.16.6 — guided clarifying-questions flow: the pending question this + * message answers. The question bubble is client-side only (never persisted), + * so without this context the model would see a bare answer ("since 2019, + * with medication") and could not react to it. Rides the prompt as delimited + * user-provided context; the persisted user turn stays the answer alone. */ guidedQuestion: z.string().min(1).max(500).optional(), /** diff --git a/src/lib/validations/inbound-documents.ts b/src/lib/validations/inbound-documents.ts index 435646d73..a66239531 100644 --- a/src/lib/validations/inbound-documents.ts +++ b/src/lib/validations/inbound-documents.ts @@ -945,8 +945,7 @@ export const DOCUMENT_CHAT_MESSAGE_MAX = 4000; * Request body for `POST /api/documents/inbound/{id}/chat`. No `userId` and no * `documentId` field — the user is narrowed from the session and the document id * comes from the path. `conversationId` continues an existing thread scoped to - * this document; omitting it starts a new one. `locale` is the reply language, - * any UI locale, like the Coach's. + * this document; omitting it starts a new one. `locale` is the reply language. */ export const documentChatRequestSchema = z .object({