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

200
.claude/skills/hal-check.md Normal file
View file

@ -0,0 +1,200 @@
# /hal-check - Hardware Abstraction Layer Agent
## Purpose
Validate HAL driver implementations against existing lamassu-machine drivers and hardware specifications.
## Invocation
```
/hal-check [command] [driver]
```
Commands:
- `port` - Validate porting from lamassu-machine
- `protocol` - Check protocol implementation
- `safety` - Rust safety review
- `mock` - Validate mock implementation
Drivers:
- `id003`, `ccnet`, `cashflow`, `bnr`, `genmega`, `hcm2`, `gsr50` (validators)
- `puloon`, `f56`, `genmega`, `hcm2`, `gsr50` (dispensers)
- `nippon`, `zebra`, `genmega` (printers)
## Porting Validation
### Source Reference
Each Rust driver should map 1:1 with lamassu-machine JavaScript:
| Rust File | JavaScript Source |
|-----------|-------------------|
| `validators/id003.rs` | `lib/id003/*.js` |
| `validators/ccnet.rs` | `lib/ccnet/*.js` |
| `dispensers/puloon.rs` | `lib/puloon/*.js` |
| `dispensers/f56.rs` | `lib/f56/*.js` |
### Porting Checklist
```
/hal-check port id003
```
Validates:
- [ ] All protocol commands implemented
- [ ] State machine matches JS FSM
- [ ] CRC/checksum calculation identical
- [ ] Timeout values match
- [ ] Error codes mapped correctly
- [ ] Denomination tables match
### Protocol Commands
#### ID003 (JCM)
| Command | Code | JS Reference |
|---------|------|--------------|
| RESET | 0x40 | id003.js:reset() |
| ENABLE | 0x13 | id003fsm.js:enable |
| DISABLE | 0x14 | id003fsm.js:disable |
| STACK | 0x15 | id003fsm.js:stack |
| RETURN | 0x16 | id003fsm.js:return |
| STATUS | 0x10 | id003fsm.js:poll |
#### Puloon
| Command | Code | JS Reference |
|---------|------|--------------|
| RESET | 0x44 | puloonrs232.js |
| DISPENSE | 0x45 | puloonrs232.js |
| STATUS | 0x46 | puloonrs232.js |
## Safety Review (Rust-specific)
### Memory Safety
- [ ] No `unsafe` without justification comment
- [ ] Buffer sizes validated before read/write
- [ ] No panic paths in production code
- [ ] Proper error propagation with Result
### Concurrency Safety
- [ ] Serial port access properly synchronized
- [ ] Event channels bounded
- [ ] No deadlock potential
- [ ] Timeout on all blocking operations
### Hardware Safety
- [ ] Dispenser amounts validated (prevent over-dispense)
- [ ] Bill count cross-checked
- [ ] Error states trigger hardware reset
- [ ] Graceful degradation on hardware failure
## Mock Validation
### Mock Requirements
Mocks must simulate:
1. Normal operation flow
2. Error conditions
3. Timing (realistic delays)
4. State persistence
### Mock Test Coverage
```
/hal-check mock puloon
```
Validates mock implements:
- [ ] `connect()` - Success and failure paths
- [ ] `dispense()` - Full and partial dispense
- [ ] `reset()` - Error recovery
- [ ] Event emission timing
- [ ] Cassette state tracking
## Protocol Analysis
### Packet Structure Validation
```
/hal-check protocol id003
```
Compares Rust packet building with JS:
```rust
// Rust implementation
fn build_packet(&self, data: &[u8]) -> Vec<u8> {
let mut packet = vec![0x02]; // SYNC
packet.push(data.len() as u8 + 4);
packet.extend_from_slice(data);
let crc = self.calculate_crc(&packet);
packet.push((crc & 0xFF) as u8);
packet.push((crc >> 8) as u8);
packet
}
```
Against JavaScript:
```javascript
// lamassu-machine/lib/id003/id003rs232.js
function buildPacket(data) {
const buf = Buffer.alloc(data.length + 4)
buf[0] = 0x02 // SYNC
buf[1] = data.length + 4
data.copy(buf, 2)
const crc = calculateCrc(buf.slice(0, -2))
buf.writeUInt16LE(crc, buf.length - 2)
return buf
}
```
## Output Format
### Port Validation
```markdown
## HAL Port Validation: id003
### Command Coverage
| Command | JS | Rust | Match |
|---------|-------|------|-------|
| RESET | ✅ | ✅ | ✅ |
| ENABLE | ✅ | ✅ | ✅ |
| STATUS | ✅ | ⚠️ | Partial |
### Protocol Differences
- [ ] `id003.rs:78` - CRC uses different polynomial than JS
### Missing Implementations
- [ ] `HOLD` command not implemented (used in id003fsm.js:holdBill)
### Recommendations
1. Verify CRC calculation against test vectors from JS
2. Add HOLD command for escrow mode
```
### Safety Review
```markdown
## HAL Safety Review: puloon
### Memory Safety
- [x] No unsafe blocks
- [x] Buffer bounds checked
- [ ] `dispense()` at line 145 - unwrap() could panic
### Concurrency Safety
- [x] Serial port mutex protected
- [x] Event channel bounded (16)
### Hardware Safety
- [x] Amount validation in dispense()
- [ ] No cassette empty check before dispense
### Critical Issues
1. `puloon.rs:145` - Replace unwrap() with proper error handling
2. `puloon.rs:178` - Add cassette level check before dispensing
```
## Example Usage
```
/hal-check port id003
```
```
/hal-check safety packages/hal/src/dispensers/
```
```
/hal-check mock --all
```