Patient record:
- Add `bloodType` and `phone` to the patient model (schema, canonical types on
both backend + frontend, zod validation). `phone` is a demographic field
(reception can read/write); `bloodType` is clinical PHI, redacted for the
reception role. Surface both in the record sheet, chat summary card, and the
add/edit patient form. Migration 0033.
Clinic location:
- New org-scoped `clinic_settings` table (address/city/country + optional
lat/long), service, and routes: GET /api/clinic/settings (any clinician) and
PUT /api/clinic/location (owner/admin). Edited in Settings → Signing → Clinic
location. Consumed later by the wallet app. Migration 0034.
i18n:
- Translate all new keys into every shipped locale (en/de/fr/ar/so) and document
the "translate into every locale" rule in frontend/CLAUDE.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The relay is now multi-clinic. Each clinic authenticates to the /hub
namespace by signing a challenge with its own Ed25519 clinic signing key
(a per-clinic identity, not a shared RELAY_TOKEN), and the relay routes
every device response back to only the clinic that originated the request
(keyed by requestId) — so clinics never see each other's traffic.
Backend:
- clinic_signing_keys.network_enabled + GET/PUT /api/signing/network
(owner/admin) to join/leave the network.
- relay-client keeps one authenticated hub connection per network-enabled
org (connectOrg/disconnectOrg, hubs map keyed by orgId); emitToWallet/
sendToWallet take orgId; offline flush is org-scoped.
- Wallet import/push return 409 until a clinic joins.
- RELAY_TOKEN is now optional/legacy (open relay needs no shared secret).
Frontend:
- "Join Temetro Network" toggle in Settings → Signing, localized in all
five languages (en, fr, de, so, ar).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A clinician can push an updated record to a wallet-linked patient (permanent
share). The snapshot is signed with the clinic Ed25519 key and sealed to the
wallet's X25519 key — derived from its Ed25519 wallet number via the birational
map, verified byte-for-byte against the wallet's own derivation. Stored pending,
delivered over the /wallet relay live and on the wallet's next authenticated
connect (offline catch-up). The patient approves/denies in-app; the wallet signs
its decision, the backend verifies it, and the record is replaced only on
approval. Wallet pins the clinic key (TOFU) and warns on change.
Backend: walletRecordUpdates table + service, ed25519PubToX25519Hex helper,
POST /api/patients/wallet/push, GET .../link/:fileNumber|updates|updates/:id,
wallet:update-request / wallet:update-response relay events.
Frontend: "Push to wallet" dialog with live status, wallet-link gating on the
patient sheet, "Sent updates" list under Settings → Signing, walletPush /
walletUpdatesList locale namespaces across all five languages. Bumps to v0.5.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add three UI locales (so/ar/de) with full ~1,660-key translations alongside
en/fr, selectable in Settings → Profile. Arabic gets full right-to-left support:
- config.ts registers the locales and exports a `dirFor` helper; an inline
<head> script in layout.tsx sets <html dir/lang> before first paint (no RTL
flash), and i18n-provider keeps them in sync on language change.
- ~160 physical direction utilities converted to logical (ms/me/ps/pe/
start/end/text-start/text-end); directional chevrons/arrows get rtl:rotate-180;
chat-bubble align variants fixed to logical.
- IBM Plex Sans Arabic appended to the sans/heading font stacks for
per-character Arabic fallback.
- Language persists to the backend user_settings and re-applies on sign-in so it
roams across devices (localStorage stays the offline source of truth).
- New scripts/check-locales.mjs (npm run check-locales) enforces key/placeholder
parity and Arabic CLDR plural completeness.
Bump to 0.3.0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Records tab: data sources, import/export, retention (replaces placeholder)
- Developers tab: API base URL, access-tokens empty state, resources
- Signing tab: how-it-works steps + backup key entries
- Team member dialog: header band, per-resource permission rows with icons
and action chips, COSS Select for role change
- Care team: hint that clicking a member shows their permissions
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Finish the i18n pass: settings panels (profile/care-team/signing), the
chat heading + input, the patient cards / detail / create-edit form, and
the notes page + rich-text editor are all keyed in en/translation.json.
All 526 static t() keys resolve. Document the new backend resources +
Socket.io realtime (backend README/CLAUDE) and the i18n coverage
(frontend CLAUDE).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Patients: new /patients directory table (name, MRN, age·sex, status,
last seen, allergies) with search + Add patient; clicking a row opens
the record in the chat via /?patient=<#>. chat-panel reads that search
param (Suspense-wrapped) and runs the lookup once on arrival. Sidebar
"Patients" now links to /patients; lib/patients gains listPatients().
- Settings: re-themed to clinical tabs (Profile · Records · Signing ·
Care team · Developers) — clinician profile, patient notifications,
patient-owned-storage/signed-records features, and a Signing key panel.
Same layout/components, only content changed.
- Sidebar footer: Polar-style NavUser (avatar + name + chevron) opening a
menu upward — Settings · Docs & GitHub · Theme · Log out. Collapsed
("locked"): avatar only, name on hover (tooltip), menu opens to the
right. Placeholder identity (no auth yet).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>