diff --git a/apps/machine/.env.example b/apps/machine/.env.example index 8124aa4..1bc2c2e 100644 --- a/apps/machine/.env.example +++ b/apps/machine/.env.example @@ -49,6 +49,13 @@ VITE_ATM_PRIVATE_KEY= # (manual dispense, remote management). Decoupled from Lightning.Pub identity. # VITE_OPERATOR_PUBKEYS=abcd1234...,ef567890... +# ============================================================================= +# Maintenance Mode +# ============================================================================= + +# Show "Under Service" screen and block all transactions +# VITE_MAINTENANCE_MODE=true + # ============================================================================= # Mock Fallback (Production Safety) # ============================================================================= diff --git a/apps/machine/electron/main.ts b/apps/machine/electron/main.ts index 04c61db..875cf73 100644 --- a/apps/machine/electron/main.ts +++ b/apps/machine/electron/main.ts @@ -187,6 +187,9 @@ ipcMain.handle('get-config', () => { // Operator identity (comma-separated hex pubkeys) operatorPubkeys: process.env.VITE_OPERATOR_PUBKEYS || '', + + // Maintenance mode — show "out of service" screen + maintenanceMode: process.env.VITE_MAINTENANCE_MODE === 'true', } }) diff --git a/apps/machine/electron/preload.ts b/apps/machine/electron/preload.ts index 952ede7..17f3ab4 100644 --- a/apps/machine/electron/preload.ts +++ b/apps/machine/electron/preload.ts @@ -26,6 +26,7 @@ export interface RuntimeConfig { cassettes?: string allowMockFallback: boolean operatorPubkeys: string + maintenanceMode: boolean } /** diff --git a/apps/machine/src/App.vue b/apps/machine/src/App.vue index 4d06d80..c0d0bb1 100644 --- a/apps/machine/src/App.vue +++ b/apps/machine/src/App.vue @@ -33,6 +33,16 @@ onMounted(async () => { }) } + // Check maintenance mode before initializing anything + const config = isElectron ? await window.electronAPI?.getConfig() : null + const maintenanceMode = + config?.maintenanceMode || import.meta.env.VITE_MAINTENANCE_MODE === 'true' + + if (maintenanceMode) { + atmStore.initError = 'maintenance' + return + } + try { if (isElectron) { await atmStore.initializeForProduction() @@ -88,11 +98,20 @@ function toggleLiveServices() { -

ATM Unavailable

+

+ {{ atmStore.initError === 'maintenance' ? 'Under Service' : 'ATM Unavailable' }} +

- This machine is temporarily out of service. Please try again later or use another machine. + {{ + atmStore.initError === 'maintenance' + ? 'This machine is currently being serviced. We will be back shortly.' + : 'This machine is temporarily out of service. Please try again later or use another machine.' + }}

-

+

{{ atmStore.initError }}

diff --git a/apps/machine/src/types/electron.d.ts b/apps/machine/src/types/electron.d.ts index bccb0e8..7e13fb7 100644 --- a/apps/machine/src/types/electron.d.ts +++ b/apps/machine/src/types/electron.d.ts @@ -15,6 +15,7 @@ export interface RuntimeConfig { cassettes?: string allowMockFallback: boolean operatorPubkeys: string + maintenanceMode: boolean } export interface AtmSecrets {