Commit graph

23 commits

Author SHA1 Message Date
bf2b9427aa refactor(config): rename VITE_LAMASSU_* machine-config env vars to VITE_BITSPIRE_*
MACHINE_MODEL, FIAT_CODE, VALIDATOR_DEVICE, DISPENSER_DEVICE and CASSETTES
carried the old brand in their names. Renamed everywhere they are read
(device.ts, electron/main.ts), written (flake.nix, mkAtmApp.nix, live.nix,
provision-atm.sh, factory-reset-atm.sh) and documented (.env.example,
docs/device-configuration.md). No compatibility fallback in code: the
machine reads VITE_BITSPIRE_* and nothing else.

The deployed .env files are the one place the old names persist — sintra's
/var/lib/bitspire/.env holds all three keys today — and the machine reads
MACHINE_MODEL / FIAT_CODE / CASSETTES from that file on every boot. Renaming
the keys in code alone would boot a live machine on preset defaults (wrong
bays, wrong fiat) at the next nightly pull. So configuration.nix gains an
activation script, beside the existing lamassu→bitspire user migration,
that rewrites VITE_LAMASSU_* → VITE_BITSPIRE_* in that file. Idempotent;
runs before bitspire.service starts.
2026-10-09 21:57:38 +02:00
425f00a71d perf(deploy): make Electron's GPU flags tunable without a rebuild
The kiosk has launched with --disable-gpu AND
--disable-software-rasterizer since the first ISO commit (19d43c2).
Together those turn off GPU compositing and the SwiftShader fallback,
which leaves Chromium rasterizing every pixel on the CPU. On a Bay Trail
Atom that is expensive, and it is very likely the largest single
contributor to a sluggish UI.

Nothing in git ever justified the pair. There is no comment, no issue and
no commit message about it; the flags arrived with the original hardware
bring-up and were carried through every refactor since. The descriptive
config at /etc/bitspire/config.env has even claimed
ELECTRON_DISABLE_GPU=false this whole time, contradicting the actual
command line. So this looks like bring-up scaffolding rather than a
diagnosed workaround, and it is worth re-testing now that the Mesa work
gives known-good crocus and iris drivers for all three GPU generations in
the fleet.

Testing it by rebuilding is the wrong loop. These are remote machines
with no one at the screen, a wrong flag is a black display, and each
attempt is a large closure copy over WireGuard. So the GPU flags move out
of ExecStart into a shell variable read from /var/lib/bitspire/.env: set
BITSPIRE_ELECTRON_GPU_FLAGS, restart the unit, look at the panel. A bad
value is one edit and a restart away from being undone.

Behaviour is unchanged by default. The variable uses ${VAR-default}, not
${VAR:-default}, so an absent line means today's flags while an
explicitly empty value means no GPU flags at all, i.e. full acceleration.
That distinction is the whole point and is why the .env template ships
the line commented out rather than set: a present-but-empty value would
silently enable the GPU on every machine that regenerates its .env.

The live ISO takes the same launcher via specialArgs, so the ISO and the
installed image cannot drift apart on this.

Closure is unchanged at 4604MB.
2026-09-24 19:13:06 +02:00
46e52f6598 chore: scrub "Lamassu" from shipped labels
The kiosk's <title> still read "Lamassu ATM" — visible as the browser tab
on the public demo, and inherited by the Electron window. The product has
been bitSpire since the rename; Lamassu belongs in the provenance credits
(README, the c0b69d1 boundary note), not on the artifact.

Rename the user-facing labels that ship: the page title, the flake
description (surfaces in `nix flake metadata`), the ISO build banner, the
header comments on the live-USB config / udev rules / app derivation that
land on the machine image, and the workspace packages' descriptions.

Deliberately NOT touched, because they are identifiers rather than labels
and renaming them has deployed-machine consequences:
- VITE_LAMASSU_MACHINE_MODEL / VITE_LAMASSU_FIAT_CODE (provisioned .env)
- LamassuEventKind (exported enum)
- localStorage keys lamassu-theme / lamassu-color-mode (would reset
  every machine's stored theme)
- docker container names + devenv scripts (dev-only)
- the packages/hal Cargo crate name
Hardware names in HAL driver comments ("Lamassu Sintra", "Douro", "Tejo")
stay: those are the physical machines' real names — that IS the credit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013A6683cCHnQxFUosx1krY4
2026-09-19 09:58:42 +02:00
42c0d3e9ca chore(deploy): seed a minimal .env — stop pre-seeding maskable vars (#70)
The bitspire-env activation seeds .env only when ABSENT (never refreshes on
redeploy), and env WINS over the pairing seed — so any value written at first
boot is frozen for the disk's life and silently masks the seed's source. That's
how a dead relay.aiolabs.dev and a provisioned VITE_OPERATOR_PUBKEYS made stale
installs "work" while a fresh machine broke.

Seed ONLY image-baked, non-maskable values (model, fiat, ELECTRON_FORCE_PROD,
DISPLAY, empty VITE_SPIRE_SEED placeholder). Relay + server pubkey come from the
seed; operator pubkey + fee config come from LNbits over the transport — so those
keys are no longer pre-seeded at all. VITE_RELAY_URL / VITE_LNBITS_SERVER_PUBKEY
are emitted only when the operator deliberately pins them via the Nix options (an
explicit override). Also drops the inert RELAY_URL/LNBITS_SERVER_PUBKEY lines from
/etc/bitspire/config.env (never loaded — EnvironmentFile is forced to .env).

Verified: built sintra-installed .env template is 5 lines, 0 maskable vars.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 21:53:51 +00:00
7e90719508 refactor(deploy): share UP Board serial hardware between installed + live ISO
The sintra live ISO (live.nix) had no serial support — ftdi_sio and the
ttyJ5/ttyJ7 udev symlinks were only in hardware/upboard.nix (installed), so
booting iso-sintra on real hardware failed on the validator + F56 dispenser
while the disk image worked. The two definitions had already drifted (live's
tejo block lacked ttyS4).

Extract the UP Board serial peripherals (usbserial/ftdi_sio/cp210x, the
ttyJ4/ttyJ5/ttyJ7 udev symlinks + permissions, console=tty0) into
hardware/upboard-serial.nix and import it from both upboard.nix (installed
tejo + sintra) and live.nix (sintra only). Single source of truth — the two
artifacts can't drift again. Named upboard-serial (not sintra-serial) since
upboard.nix serves both tejo-installed and sintra-installed.

Camera + LED/SPI rules stay inline in upboard.nix (installed-specific; the
pairing camera works via getUserMedia without the scanner symlink). Verified
by eval: live sintra now carries ftdi_sio + console=tty0 + ttyJ7; installed
sintra/tejo unchanged (serial present, camera present, no console dupe).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 21:31:36 +02:00
b2099c7d48 fix(deploy): make the live ISO boot cleanly
Fresh live boots hit a cascade of activation/unit failures because live.nix
shared installed-system config that assumes persistent state:

- bitspire-env chowned /var/lib/bitspire/.env to bitspire:bitspire in the
  default activation order, before `users` runs, so on a fresh boot (no .env
  yet) it failed with 'invalid user'. Move to the attrset form with
  deps=["users"]. (Installed systems skip the block since .env exists.)
- swapDevices=/var/swapfile lives in the live tmpfs and fails to init —
  replace with zramSwap for the low-RAM models' OOM cushion.
- wg0 needs a provisioned key the live boot lacks; it failed and dragged
  network-setup down. Drop the interface on live.
- display-reset runs `xrandr --output eDP-1`, but the Sintra drives HDMI-1
  (no eDP-1) — gate the service off for sintra.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 23:47:31 +02:00
482e0549b9 fix(deploy): make live ISOs USB-bootable (isoImage.makeUsbBootable)
The live ISO config set makeEfiBootable + makeBiosBootable but omitted
makeUsbBootable, so the image got BIOS+UEFI El Torito boot catalogs but
no isohybrid MBR/GPT — i.e. no partition table. dd'd to a USB stick it
shows iso9660 on the whole device with no ESP, and picky firmware (the
Sintra's Aaeon UP Board) won't recognise it as bootable, falling back to
its android-ia entry. Enabling makeUsbBootable applies the isohybrid MBR
(isohdpfx.bin) + GPT/ESP. Fixes USB boot for every model's live ISO.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 22:12:28 +02:00
8a02d72bd1 feat(deploy): provision VITE_SPIRE_SEED for bunker pairing (Phase E)
provision-atm.sh now writes VITE_SPIRE_SEED (the spire-seed:v1: pairing seed
from spirekeeper) as the production identity, validating the scheme prefix;
the generated nsec path is kept only as a dev fallback when SPIRE_SEED is
unset. Relay default moved to the LNbits bundled nostrrelay
(ws://$HOST_IP:5001/nostrrelay/test). .env templates (live.nix + the flake's
installed-default) swap VITE_ATM_PRIVATE_KEY → VITE_SPIRE_SEED and drop the
dead LP-era vars. README notes state.db now also holds the bunker binding
(keep it or re-pair).

Part of Phase E, aiolabs/bitspire#52. Unblocks the Sintra live-pairing smoke.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 12:49:30 +02:00
3128975224 chore(nix): bump nixpkgs 25.05 → 25.11
isoImage.isoName was renamed to image.fileName in 25.11 (unified
image module). Split the rename out — the rest of isoImage.* stays
put (makeEfiBootable, makeBiosBootable, squashfsCompression).

All 8 nixosConfigurations evaluate clean on 25.11 with zero
deprecation warnings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:12:11 +02:00
7c1011d382 chore(nix): bump nixpkgs 24.05 → 24.11
Three breakages handled:

- hardware.opengl → hardware.graphics (renamed in 24.11). Touches
  upboard.nix, douro.nix, batm3.nix, live.nix.
- vaapiIntel dropped — legacy pre-Broadwell driver, removed in
  nixpkgs. UP Board (Cherry Trail) and OptiPlex 9030 (Haswell) both
  use intel-media-driver, which stays.
- vaapiVdpau renamed → libva-vdpau-driver.

system.stateVersion stays 24.05 — convention is to never bump after
install. Existing Sintra and fresh flashes keep the 24.05 state
semantics; that's correct.

All 8 nixosConfigurations (4 models × {live,installed}) evaluate
clean with zero deprecation warnings on 24.11.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:12:11 +02:00
264cc47e0c refactor(deploy): rename system user lamassu → bitspire
System-level half of the lamassu → bitspire rebrand the rest of dev
already did at the path / service / package layers. Touches user/group
declarations, every systemd `User=` block, the udev rules filename, all
chown calls in flake.nix + live.nix, the displayManager autoLogin user,
the trusted-users nix entry, provision-atm.sh's ATM_USER, plus README +
CLAUDE.md doc references.

In-place migration for the Sintra dev unit (which auto-pulls dev at
04:00) lives in `system.activationScripts.bitspire-user-migration` and:
- copies `/home/lamassu/.ssh/authorized_keys` → `/home/bitspire/` once,
  so SSH access survives the rename
- recursively chowns `/var/lib/bitspire` to the new bitspire UID on
  every boot — cheap no-op once done, but covers the case where the
  data dir was written by the now-removed lamassu UID
- leaves `/home/lamassu/` in place as evidence; operator can `rm -rf`
  after confirming bitspire login works

Recovery path if the migration breaks SSH access: root key is still in
configuration.nix:142-144 (padreug@gizmo), so ssh root@<host> works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:11:32 +02:00
28a35ca479 refactor(rename): NixOS module + service + paths → bitspire
Five-file coordinated rename to give the dev-branch deploy a clean
`bitspire` namespace at the NixOS level:

  deploy/nixos/lamassu-atm.nix → deploy/nixos/bitspire-atm.nix
    - `services.lamassu-atm`           → `services.bitspire`
    - `systemd.services.lamassu-atm`   → `systemd.services.bitspire`
    - `/var/lib/lamassu-atm`           → `/var/lib/bitspire`
    - `/opt/lamassu-atm`               → `/opt/bitspire`
    - `/etc/lamassu-atm/config.env`    → `/etc/bitspire/config.env`

  flake.nix
    - module import path updated
    - `nixosModules.lamassu-atm` → `nixosModules.bitspire`
    - `system.activationScripts.lamassu-env` → `bitspire-env`
    - all activation-script paths point at /var/lib/bitspire

  deploy/nixos/configuration.nix
    - `networking.hostName = "lamassu-atm"` → `"bitspire"`

  deploy/nixos/live.nix
    - module import path updated
    - ISO name template: `lamassu-atm-<model>-live.iso` → `bitspire-<model>-live.iso`
    - activation-script name updated

  deploy/nixos/provision-atm.sh
    - data-dir paths: /var/lib/lamassu-atm → /var/lib/bitspire
    - systemctl + journalctl unit names updated

DELIBERATELY kept as `lamassu` (for now):
  - The `lamassu` UNIX user and group account. Renaming would
    require file-ownership migration scripts; the Sintra is a
    fresh flash so no existing data, but the internal user
    namespace inconsistency is acceptable.
  - LP-specific bits in provision-atm.sh (admin token, the
    `docker logs lamassu-lightning-pub` extractor) — those
    get ripped out in 3c when the script switches to LNbits.

NO migration activation script added — the Sintra flash is fresh,
production batm3/douro stay on `main` and never see this branch.
A future dev→main cutover will need a separate migration story
(rename UNIX user, move /var/lib/lamassu-atm → /var/lib/bitspire,
SSH key relocation, etc.).

Verified:
  nix eval .#nixosConfigurations.batm3-installed.config.systemd.services.bitspire.enable
    → true
  nix eval .#nixosConfigurations.bitSpire-live-sintra.config.networking.hostName
    → "bitspire"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:08:03 +02:00
Patrick Mulligan
ac9f169366 fix(deploy): disable SSH password authentication on production machines
Removes the mkForce override that enabled password auth for initial
setup. Machines are now provisioned with SSH keys, so the base
config's PasswordAuthentication=false takes effect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:04:37 -04:00
Patrick Mulligan
dc5f4f8aa6 feat(deploy): add batm3 ISO build target
Add batm3 to flake.nix NixOS configs, live.nix (CDC ACM kernel modules,
MEI udev rules), and build-iso.sh. Default fiat: USD.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 03:20:46 -04:00
Patrick Mulligan
143ae9ff0b feat(nix): add tejo hardware support and per-model auto-upgrade
- Add tejo-specific udev rules for both UP Board and UP4000 variants
  (serial symlinks ttyJ4/J5/J7, camera, LED SPI, I2C, USB autosuspend)
- Add USB serial kernel modules (usbserial, ftdi_sio, cp210x) for tejo
- Add tejo serial console kernel params (ttyS4 debug UART)
- Fix upboard.nix: hardware.graphics → hardware.opengl (NixOS 24.05)
- Add tejo-installed nixosConfiguration with model-specific auto-upgrade
- Parameterize auto-upgrade flake URL per machine model

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 08:54:50 -05:00
Patrick Mulligan
8a3b40184b fix: prevent ATM freeze on memory-constrained machines
- Add --disable-software-rasterizer to kill SwiftShader GPU process
- Restore MemoryMax=1G so systemd OOM-kills Electron before system locks
- Add 1GB swap file so kernel can page out under pressure
- Clean /tmp on boot to prevent stale build artifacts filling disk

Douro (1.8GB RAM, 15GB disk) was freezing from memory exhaustion with
no swap and no memory limit on the Electron process.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:04:29 -05:00
Patrick Mulligan
625cebed25 refactor(nix): consolidate deploy flake into root flake with pure ISO builds
Move deploy/nixos/flake.nix into the root flake.nix, adding mkAtmApp
for pure Nix builds of the Electron app (no local pnpm needed). Simplify
build-iso.sh to a thin wrapper around `nix build .#iso-<model>`. Add
douro hardware configuration. Streamline live.nix to consume the
Nix-built app package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 10:58:43 -05:00
Patrick Mulligan
4105f750de fix(deploy): complete ISO build with serialport parsers, device policy, and sintra model
- Add all 10 @serialport/parser-* packages to live.nix atm-app derivation
  (serialport@12 barrel import eagerly requires all of them)
- Add DevicePolicy=auto + DeviceAllow=char-* rw for serial port access
- Make envTemplate model-aware (machineModel + fiatCodeForModel)
- Add sintra model (EUR) to flake.nix and build-iso.sh
- Fix tejo fiat code from USD to GTQ

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 18:42:59 -05:00
Patrick Mulligan
c874d9e2e3 fix(deploy): multi-model ISO builds and HAL packaging
- Parameterize live.nix by machineModel (douro/tejo) passed via specialArgs
- Douro: kernel 5.15 LTS for Bay Trail i915 eDP fix, vt.handoff=7
- Fix HAL packaging: copy dist/ into subdirectory (not flattened)
- Add display-reset systemd service for kexec GPU reinitialization
- Add --disable-gpu flag for Electron on headless/GPU-less boots
- flake.nix: mkLiveConfig helper, per-model ISO outputs (iso-douro/iso-tejo)
- build-iso.sh: require model param, write model-specific .env for Vite
- flash-douro-usb.sh: GPT+FAT32 ESP layout for Bay Trail UEFI boot

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:02:28 -05:00
Patrick Mulligan
94a9f03e2e fix(hal): simplify Puloon error handling to match lamassu-machine
Align dispenser error handling with lamassu-machine's proven approach:
close port on error, set error name, let caller decide when to re-init.
Also configure live ISO for Douro/GTQ with serialport native modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:22:34 -05:00
Patrick Mulligan
658c3c2b4d fix(machine): live USB ISO with native modules and debug mode
Enable debugMode by default (simulated bill buttons) until real
hardware validator is connected. Fix live.nix to include native
node_modules (better-sqlite3, bindings) from pnpm virtual store,
add LD_LIBRARY_PATH for NixOS, bake aiolabs.dev endpoints into
env template, and enable Electron renderer logging in journalctl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:14:35 -05:00
Patrick Mulligan
722635a5a6 feat(machine): landscape layout and fullscreen mode
- Switch Electron window to landscape (1920x1080) with fullscreen fallback
- Rearrange IdleView for horizontal layout (logo+badges left, action cards right)
- Fix hostname command in provision/build scripts (use ip route instead of hostname -I)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 20:43:49 -05:00
Patrick Mulligan
19d43c2939 feat(deploy): add NixOS live USB ISO for ATM hardware testing
Add NixOS configuration to build a bootable live USB ISO that runs the
ATM Electron app in kiosk mode on physical hardware (UpBoard). The ISO
boots from squashfs, auto-starts X11/openbox, and launches Electron in
production mode.

Key changes:
- deploy/nixos/live.nix: Live USB module (squashfs+tmpfs, no disk install)
- deploy/nixos/flake.nix: Nix flake with ISO build output
- deploy/nixos/provision-atm.sh: Auto-provision LP credentials via API
- deploy/nixos/build-iso.sh: End-to-end build workflow script
- apps/machine: Fix Electron production mode (ELECTRON_FORCE_PROD),
  Vue Router hash mode for file:// protocol, relative asset paths

Build: cd deploy/nixos && bash build-iso.sh
Test:  qemu-system-x86_64 -enable-kvm -m 2G -cdrom result/iso/*.iso

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 20:11:23 -05:00