feat: route wallet traffic through the Temetro Network relay (v0.7.0)

Devices no longer connect to the backend directly. The /wallet Socket.io
namespace is removed from realtime.ts; a new services/relay-client.ts connects
to the standalone Temetro Network relay's /hub namespace (RELAY_TOKEN-auth),
emitToWallet delegates to its sendToWallet, and device responses + wallet:online
replay are handled there via the same wallet-share/wallet-updates services.

- Add RELAY_URL + RELAY_TOKEN env (env.ts, .env.example, docker-compose.yml);
  the wallet-import QR (resolveRelayUrl) now points at RELAY_URL.
- Add socket.io-client dependency.
- Document the Temetro Network folder/service in root + backend CLAUDE.md.
- Bump root/backend/frontend to 0.7.0; CHANGELOG entry.

The relay service itself lives in github.com/temetro/temetro-network.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalid Abdi
2026-07-05 03:04:23 +03:00
parent d79f7f7c06
commit ef76afc3ca
14 changed files with 305 additions and 175 deletions
+7 -1
View File
@@ -36,6 +36,7 @@ import { staffRouter } from "./routes/staff.js";
import { networkRouter } from "./routes/network.js";
import { tasksRouter } from "./routes/tasks.js";
import { versionRouter } from "./routes/version.js";
import { initRelayClient } from "./services/relay-client.js";
import { beginQuickTunnelDiscovery } from "./services/relay-url.js";
import { sweepExpiredShares } from "./services/wallet-share.js";
@@ -123,6 +124,11 @@ app.use(errorHandler);
const server = createServer(app);
initRealtime(server);
// Connect to the Temetro Network relay (the device-facing hub). Patient phones
// no longer connect to this backend directly — they connect to the relay, and
// we push to / receive from them over its /hub namespace.
initRelayClient();
// Sweep expired temporary patient-wallet shares (auto-delete) every 5 minutes.
const SHARE_SWEEP_INTERVAL = 5 * 60 * 1000;
setInterval(() => {
@@ -154,7 +160,7 @@ server.listen(env.PORT, () => {
console.log(` • portal: /api/portal (public clinic kiosk)`);
console.log(` • fhir: /fhir (read-only FHIR R4 server, API-key auth)`);
console.log(` • signing: /api/signing (Ed25519 clinic key)`);
console.log(` • wallet: /api/patients/wallet (+ /wallet socket relay)`);
console.log(` • wallet: /api/patients/wallet (via Temetro Network relay: ${env.RELAY_URL})`);
});
// Dockerized off-network testing: learn our public Cloudflare quick-tunnel URL