From 1c5e71eb39038ccfd60eb877fc64d248b32ea1c4 Mon Sep 17 00:00:00 2001 From: Khalid Abdi Date: Wed, 8 Jul 2026 19:34:27 +0300 Subject: [PATCH] backend: include appointments & invoices in the wallet push bundle Appointments and invoices live in their own tables, not on the Patient snapshot, so a clinic->wallet push previously sealed only the patient record and the patient's appointments/invoices never reached the wallet app. Load and attach them to the sealed bundle ({ patient, appointments, invoices, changes }). Co-Authored-By: Claude Opus 4.8 --- backend/src/services/wallet-updates.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/backend/src/services/wallet-updates.ts b/backend/src/services/wallet-updates.ts index ca995f4..1a7db32 100644 --- a/backend/src/services/wallet-updates.ts +++ b/backend/src/services/wallet-updates.ts @@ -13,6 +13,8 @@ import { verifySignature, } from "../lib/wallet-crypto.js"; import { ed25519PubToX25519Hex } from "../lib/wallet-x25519.js"; +import { listAppointments } from "./appointments.js"; +import { listInvoices } from "./invoices.js"; import { getPatient } from "./patients.js"; import { signWithClinicKey } from "./signing.js"; @@ -100,9 +102,23 @@ export async function createRecordUpdate( const patient = await getPatient(orgId, fileNumber); if (!patient) throw new HttpError(404, "Patient not found."); + // Appointments and invoices live in their own tables (not on the Patient + // snapshot), so pull the ones for this patient and ship them alongside — the + // wallet has no other way to see them and they'd otherwise silently vanish. + const [orgAppointments, orgInvoices] = await Promise.all([ + listAppointments(orgId), + listInvoices(orgId), + ]); + const appointments = orgAppointments.filter( + (a) => a.fileNumber === fileNumber, + ); + const invoices = orgInvoices.filter((i) => i.fileNumber === fileNumber); + // The wallet opens this, verifies the signature over the same bytes, then - // replaces its on-device record with `patient`. - const bundle = utf8ToBytes(JSON.stringify({ patient, changes })); + // replaces its on-device record with `patient` (+ appointments/invoices). + const bundle = utf8ToBytes( + JSON.stringify({ patient, appointments, invoices, changes }), + ); const { signature, publicKey } = await signWithClinicKey(orgId, bundle); const x25519Hex = ed25519PubToX25519Hex(decodeWalletNumber(walletNumber)); const sealed = seal(x25519Hex, bundle);