feat(docker): add dev.sh with auto-funding and ATM app setup

- Add dev.sh script for managing regtest development environment
- Implement cmd_fund to fund ATM app owner via Lightning.Pub API
- Add --fund flag to cmd_up for automatic funding on startup
- Update setup_atm_app to write VITE_APP_ID to machine .env
- Fix Electron IPC to pass appId and extensionApiUrl to renderer
- Restructure repo from nested lamassu-next/ to root

The dev.sh script now supports:
- ./dev.sh up --fund  # Start regtest and auto-fund ATM
- ./dev.sh fund       # Fund existing ATM app
- ./dev.sh status     # Show environment status
- ./dev.sh reset      # Clean restart

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-15 14:19:16 -05:00
commit c98f126ba7
180 changed files with 2695 additions and 9587 deletions

View file

@ -0,0 +1,140 @@
# ADR-001: Hardware Abstraction Layer Architecture
**Status:** Accepted
**Date:** 2026-01-26
**Context:** Lamassu Next ATM proof of concept
## Decision
We will use **TypeScript HAL drivers extracted from lamassu-machine** rather than rewriting in Rust, and use **Electron instead of Tauri** for the kiosk application.
## Context
The Lamassu Next project needs to control ATM hardware (bill validators, dispensers) on Lamassu Sintra machines. Initial plans considered:
1. Rust HAL with Tauri backend
2. TypeScript HAL with Tauri (IPC bridge)
3. TypeScript HAL with Electron (direct integration)
### Hardware Target: Lamassu Sintra
- **Platform:** Aaeon UP Board (Intel Atom x5-Z8350, x86 Linux)
- **Bill Validator:** JCM iVIZION using ID003 protocol
- **Bill Dispenser:** Fujitsu F53/F56
- **Serial:** `/dev/ttyJ5` (validator), `/dev/ttyJ7` (dispenser)
- **Protocol:** RS-232, 9600 baud, 8 data bits, even parity, 1 stop bit
## Options Considered
### Option 1: Rust HAL + Tauri
**Pros:**
- Native Tauri integration
- Memory safety guarantees
- Single backend language
**Cons:**
- Requires full protocol reimplementation
- Two debugging environments (Rust + TypeScript)
- Serial at 9600 baud doesn't benefit from Rust performance
- Significant time investment with uncertain payoff
### Option 2: TypeScript HAL + Tauri
**Pros:**
- Reuse battle-tested lamassu-machine drivers
- TypeScript throughout application code
**Cons:**
- IPC boundary between Tauri (Rust) and HAL (Node.js)
- Serialization overhead and complexity
- Two processes to manage and debug
### Option 3: TypeScript HAL + Electron (Selected)
**Pros:**
- Direct `serialport` npm access in main process
- Single debugging environment (Chrome DevTools)
- All packages run natively (state-machine, HAL, lightning, clink)
- Mature ecosystem, well-documented edge cases
- Fastest path to working proof of concept
**Cons:**
- Larger binary size (~150MB vs ~10MB)
- Higher memory usage than Tauri
- Bundles Chromium
## Decision Rationale
### Why not Rust?
The JavaScript drivers in lamassu-machine have run in production for years. The complexity is in the protocol state machines (ID003 FSM, F56 DLE/STX framing), not raw performance. Serial communication at 9600 baud is trivial - Rust's performance benefits are irrelevant here.
Adding Rust creates a language boundary that requires:
- IPC serialization/deserialization
- Two build systems
- Two debugging environments
- Potential for bugs at the boundary
For a proof of concept, minimizing unknowns is critical.
### Why Electron over Tauri?
Tauri's benefits (small binary, low RAM) optimize for end-user desktop apps where download size matters. An ATM is a single-purpose kiosk:
- Binary size irrelevant - installed once on dedicated hardware
- RAM sufficient - Sintra has 2-4GB, not competing with other apps
- Development speed critical - proof of concept needs fast iteration
Electron allows the Vue UI, state machine, HAL, and Lightning packages to all run in the same Node.js environment with unified debugging.
## Implementation Status
### Completed
- `@lamassu/hal` package created with:
- ID003 bill validator driver (JCM iVIZION)
- F56 bill dispenser driver (Fujitsu F53/F56)
- TypeScript types for all interfaces
- Extracted from lamassu-machine, fully typed
### Remaining Work
1. Convert `apps/machine` from Tauri to Electron
2. Wire HAL to state machine services:
- `dispenseCash` → F56Dispenser.dispense()
- Bill events → state machine events
3. Add device configuration (serial port paths)
4. Test on physical Sintra hardware
## Consequences
### Positive
- Faster proof of concept development
- Easier debugging during hardware integration
- Reuse of proven driver code
- Single language throughout
### Negative
- Larger deployment size (acceptable for kiosk)
- Cannot leverage Rust safety guarantees (mitigated by mature JS drivers)
### Future Considerations
If a compelling reason for Rust emerges (it likely won't), the HAL interface is abstracted - drivers could be reimplemented without changing the state machine integration. The Vue UI works with either Electron or Tauri.
## References
- `packages/hal/` - TypeScript HAL implementation
- `packages/state-machine/src/types.ts` - ATMServices interface
- `hardware/codebase/upboard/sintra/device_config.json` - Sintra device paths
- lamassu-machine `lib/id003/`, `lib/f56/` - Original JS drivers