feat: publish maintenance beacon when ATM is under service

In maintenance mode, establish a minimal Nostr connection (no
Lightning.Pub) and publish Kind 30078 heartbeat with
maintenance: true. Monitors show yellow dot + "under service"
instead of appearing offline.

Only the Nostr client is initialized — no payment infrastructure.
Same one-shot private key security model as normal operation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-03-30 18:18:06 -04:00
commit 54c3f7bd8d

View file

@ -43,6 +43,40 @@ onMounted(async () => {
if (maintenanceMode) { if (maintenanceMode) {
atmStore.initError = 'maintenance' atmStore.initError = 'maintenance'
// Publish maintenance beacon — minimal Nostr connection only (no Lightning.Pub)
try {
const { NostrClient, loadIdentityFromHex, createSignedEvent } = await import(
'@lamassu/nostr-client'
)
const secrets = isElectron ? await window.electronAPI?.getAtmSecrets() : null
const privKey = secrets?.atmPrivateKey || import.meta.env.VITE_ATM_PRIVATE_KEY
const relayUrl = config?.relayUrl || import.meta.env.VITE_RELAY_URL
if (privKey && relayUrl) {
const identity = loadIdentityFromHex(privKey)
const client = new NostrClient({ relays: [{ url: relayUrl }], identity })
await client.connect()
const publishBeacon = () => {
const event = createSignedEvent(identity, {
kind: 30078,
created_at: Math.floor(Date.now() / 1000),
tags: [['d', 'atm-availability']],
content: JSON.stringify({
cash_in: false,
cash_out: false,
cash_level: 'none',
maintenance: true,
fiat: config?.fiatCode || 'USD',
model: config?.machineModel || 'atm',
}),
})
client.publish(event).catch(() => {})
}
publishBeacon()
setInterval(publishBeacon, 5 * 60 * 1000)
}
} catch (e) {
console.warn('[App] Failed to start maintenance beacon:', e)
}
return return
} }