mirror of
https://github.com/temetro/temetro.git
synced 2026-07-26 11:58:14 +00:00
bb536ba6da
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>
48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
// Client for the clinic→wallet record-update push. When a clinician edits a
|
|
// wallet-linked patient, they can push the updated record to the patient's app;
|
|
// it stays pending until the patient approves it on their phone.
|
|
|
|
import { apiFetch } from "@/lib/api-client";
|
|
|
|
export type WalletUpdateStatus = "pending" | "delivered" | "approved" | "denied";
|
|
|
|
export type WalletUpdate = {
|
|
id: string;
|
|
fileNumber: string;
|
|
walletNumber: string;
|
|
status: WalletUpdateStatus;
|
|
changes: string[];
|
|
createdAt: string;
|
|
deliveredAt: string | null;
|
|
resolvedAt: string | null;
|
|
};
|
|
|
|
// Resolve the wallet a patient is linked to. Rejects (404) when not wallet-backed.
|
|
export function getWalletLink(
|
|
fileNumber: string,
|
|
): Promise<{ walletNumber: string }> {
|
|
return apiFetch<{ walletNumber: string }>(
|
|
`/api/patients/wallet/link/${encodeURIComponent(fileNumber)}`,
|
|
);
|
|
}
|
|
|
|
export function pushWalletUpdate(input: {
|
|
fileNumber: string;
|
|
changes: string[];
|
|
}): Promise<WalletUpdate> {
|
|
return apiFetch<WalletUpdate>("/api/patients/wallet/push", {
|
|
method: "POST",
|
|
body: JSON.stringify(input),
|
|
});
|
|
}
|
|
|
|
export function listWalletUpdates(): Promise<WalletUpdate[]> {
|
|
return apiFetch<WalletUpdate[]>("/api/patients/wallet/updates");
|
|
}
|
|
|
|
export function getWalletUpdate(id: string): Promise<WalletUpdate> {
|
|
return apiFetch<WalletUpdate>(
|
|
`/api/patients/wallet/updates/${encodeURIComponent(id)}`,
|
|
);
|
|
}
|