- services/portal.ts: clinic-scoped portal actions (clinic info, doctors,
availability, linkWallet, conflict-checked booking, results, downloadable lab
files) plus handlePortalRequest to dispatch a relayed portal:request.
- relay-client.ts: handle portal:request on the hub and ack the result back down
the relay (device path identifies the patient by verified wallet number).
- patients: new nullable wallet_number column (+ migration); linking stores it,
and walletNumberForPatient now resolves via it so pushes work after a portal
link, not only after a permanent share.
- routes/portal.ts: GET /:clinic/link returns the relay-based pairing descriptor
(clinic signing key + relay URL) for the QR — no more localhost-baked API URL.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>