Commit Graph
7 Commits
Author SHA1 Message Date
Marc-André Bombeck fb1cb4e3ed feat: gate a switched browser on the record's modules, not the actor's
Turning a module off for a profile you look after wrote a column nothing
on screen was reading. GET /api/auth/me published the ACTOR's module map
while switched, and the navigation, the dashboard tiles and the insights
sections all gate on it — so a guardian who turned Cycle off for the child
kept seeing a Cycle destination inside the child's record, and a guardian
who tracks it saw one there whether or not the child did (#939).

The map and the resolved cycle flag now answer for the record the session
is inside. They are not display preferences: every surface they gate shows
the record's data, so the record is what decides. Locale, theme and layout
stay the actor's. The record is taken from the grant-validated active
entry rather than the session's own selector, so a revoked switch cannot
publish somebody's configuration, and with no switch the payload is what
it was.

Cycle also gets a row on the guardian's Modules surface, which it never
had. It is a delegated module, so its state is the record's own cycle
profile and modulePreferences.cycle is refused — which left a guardian no
way to turn it off for a record whose sex says it should be on. The family
names the real column instead of a blob entry the gate ignores.

Refs #939
2026-09-10 00:02:03 +02:00
aucun6352 f7cc47850a fix(i18n): make the Korean locale actually work end to end
Registering `ko` in the `Locale` union left seven locale-keyed tables
without an entry, so the build could not type-check and the safety
screens, the citation-coverage grader and the reference-range parser
read nothing at all for a Korean reader.

Three failures were not missing keys but wrong assumptions:

- The shared fold decomposes with NFD and strips U+0300-U+036F. Latin
  accents become plain letters, but Hangul decomposes into jamo, which
  are not in that range and survived — so folded Korean text was a jamo
  sequence no precomposed table entry could ever match. It recomposes to
  NFC now; every Latin, Polish and German fold is byte-identical.
- `normaliseLabKey` kept `[a-z0-9]`, which reduced every Korean analyte
  name to the empty string, so the derived index held none of them and a
  Korean cholesterol result reached a FHIR export uncoded.
- The reference-range parser had the hyphen and the dashes but not the
  tilde a Korean lab actually prints (`3.5~5.0`).

The Korean safety banks carry no `\b` next to a Hangul token — `\b` is
an ASCII `\w` boundary and Hangul is not `\w`, so `/\b증량/` matches
nothing — and the clause order is the mirror of the Latin banks, since
Korean closes with the verb. The dose patterns require a target-marking
particle for the same reason the Latin banks require "to"/"by": without
it the permitted restatement "7.5mg을 복용 중이고, 체중은 내려가고
있어요" tripped the lowering pattern.

The Coach and Insights prompts route `ko` down the reviewed English body
plus a Korean reply directive; there is no `safety-contracts.ko.yaml`, so
the native builder has no Korean ground rules to compose from.
2026-08-26 20:00:44 +09:00
aucun6352 f1b0420479 feat(i18n): add Korean as a seventh end-to-end locale
Register `ko` in the locale list, language names, and labels, and ship
messages/ko.json so the whole UI — dashboard, settings, share views,
clinician PDF, notifications, and AI prompts — renders in Korean.

Extend the locale-parity, English-leak, plural-completeness, and copy
guard tests to cover the new locale, and update README/CONTRIBUTING to
list Korean among the supported languages.
2026-08-26 16:42:45 +09:00
Marc-André Bombeck 7f67c24ecc Describe the rest of the integration surface in the contract
Thirty-seven more paths the clients already call and the published spec did not
describe: the six OAuth providers' credential, status, disconnect, sync and
probe endpoints, the cross-provider surfaces under `/api/integrations/*`, the
managed record's configuration tree, and the native device-revoke path.

Where providers share a verb name they do not always share a contract, and the
descriptions say so instead of averaging it out. Three divergences are stated
per path. A disconnect refuses a repeat with 404 on six providers and answers an
idempotent 200 on two. `/api/<provider>/test` answers a bare probe result while
the same-named `/api/integrations/<provider>/test` adds the connection's last
sync, and the Google Health one accepts a body that replaces the response shape
outright. `GET /api/withings/status` refreshes and re-persists the OAuth token
while it reads; the other six status endpoints write nothing, and each now says
which it is.

Two further facts a client cannot infer. The Withings credential DELETE writes
no audit row and leaves the ledger at its last state, unlike every sibling, so
its `state` is not proof of a live connection afterwards. The WHOOP connect
ticket is a credential in a response body, returned once and stored only as a
hash.

The Google Health credential schema moves to the validations module; the managed
record's six strict patch schemas are exported from where they already lived, so
the contract publishes the objects the handler parses rather than a restatement.
2026-08-22 12:44:36 +02:00
Marc-André Bombeck a45dde2039 Retire the guardian toggle over a pref nothing reads
The evidence disclosure stopped honouring showEvidenceByDefault in
v1.4.27 and the owner surface retired the control with it — but the
managed-record coach form still offered the switch, silently governing
nothing. Remove the control, the managed-schema pick, the response
field, and the label in all six locales; the strict schema now refuses
the key outright.
2026-08-14 01:56:25 +02:00
Marc-André Bombeck 247ac8494c fix: complete managed record settings
- Expose canonical defaults and reject invalid settings families\n- Localize Guardian controls and refresh dependent caches
2026-08-06 03:40:13 +02:00
Marc-André Bombeck e788675b82 feat: configure managed record settings
- Scope writable settings to the selected managed record\n- Render typed Guardian controls with separated audit attribution
2026-08-06 03:21:02 +02:00