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:
parent
30a2eb2199
commit
c98f126ba7
180 changed files with 2695 additions and 9587 deletions
218
.claude/skills/docs.md
Normal file
218
.claude/skills/docs.md
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
# /docs - Documentation Agent
|
||||
|
||||
## Purpose
|
||||
Keep documentation synchronized with code, generate API docs, and maintain architecture diagrams.
|
||||
|
||||
## Invocation
|
||||
```
|
||||
/docs [command] [target]
|
||||
```
|
||||
|
||||
Commands:
|
||||
- `sync` - Sync docs with code changes
|
||||
- `api` - Generate API documentation
|
||||
- `diagram` - Update architecture diagrams
|
||||
- `readme` - Update package README
|
||||
- `changelog` - Generate changelog entry
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
```
|
||||
docs/
|
||||
├── architecture/
|
||||
│ ├── overview.md # High-level architecture
|
||||
│ ├── nostr-protocol.md # Nostr integration details
|
||||
│ ├── lightning-flow.md # Payment flows
|
||||
│ └── hardware-hal.md # HAL documentation
|
||||
├── api/
|
||||
│ ├── nostr-client.md # @lamassu/nostr-client API
|
||||
│ ├── clink.md # @lamassu/clink API
|
||||
│ ├── state-machine.md # @lamassu/state-machine API
|
||||
│ └── hal.md # @lamassu/hal API
|
||||
├── guides/
|
||||
│ ├── development.md # Dev setup guide
|
||||
│ ├── hardware-testing.md # Testing with real hardware
|
||||
│ └── deployment.md # NixOS deployment guide
|
||||
└── adrs/ # Architecture Decision Records
|
||||
├── 001-nostr-backbone.md
|
||||
├── 002-clink-over-bolt12.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Sync Tasks
|
||||
|
||||
### Code → Docs Sync
|
||||
When code changes:
|
||||
1. Detect modified files
|
||||
2. Check if related docs exist
|
||||
3. Flag outdated documentation
|
||||
4. Suggest updates
|
||||
|
||||
### Doc → Code Validation
|
||||
Ensure docs reference actual code:
|
||||
- [ ] Function names match
|
||||
- [ ] Parameter types correct
|
||||
- [ ] Return types accurate
|
||||
- [ ] Examples compile/run
|
||||
|
||||
## API Documentation
|
||||
|
||||
### TypeScript Packages
|
||||
Generate from TSDoc comments:
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Create a CLINK offer for receiving payments
|
||||
*
|
||||
* @param identity - Machine identity (nsec/npub)
|
||||
* @param relays - Relay URLs to include in offer
|
||||
* @param priceType - 'fixed' | 'variable' | 'spontaneous'
|
||||
* @param amount - Amount in sats (required for fixed)
|
||||
* @returns Encoded noffer string
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const offer = createOffer(identity, ['wss://relay.example'], 'fixed', 10000)
|
||||
* // Returns: noffer1...
|
||||
* ```
|
||||
*/
|
||||
export function createOffer(...): string
|
||||
```
|
||||
|
||||
### Rust Crate (HAL)
|
||||
Generate from rustdoc comments:
|
||||
|
||||
```rust
|
||||
/// Connect to a bill validator
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `port` - Serial port path (e.g., "/dev/ttyUSB0")
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns `ValidatorError::ConnectionFailed` if port unavailable
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// let mut validator = Id003Validator::new("/dev/ttyUSB0", "USD");
|
||||
/// validator.connect().await?;
|
||||
/// ```
|
||||
pub async fn connect(&mut self) -> Result<(), ValidatorError>
|
||||
```
|
||||
|
||||
## Diagram Updates
|
||||
|
||||
### Mermaid Diagrams
|
||||
Keep architecture diagrams current:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant A as ATM
|
||||
participant R as Relay
|
||||
participant L as Lightning.Pub
|
||||
|
||||
U->>A: Insert $20 bill
|
||||
A->>A: Validate bill
|
||||
A->>R: Publish CLINK offer
|
||||
U->>R: Send payment request
|
||||
R->>A: Forward request
|
||||
A->>L: Generate invoice
|
||||
L->>A: Return invoice
|
||||
A->>R: Send invoice to user
|
||||
U->>L: Pay invoice
|
||||
L->>A: Payment confirmed
|
||||
A->>U: Display success
|
||||
```
|
||||
|
||||
### Auto-update triggers
|
||||
- New event kinds added → Update protocol diagram
|
||||
- State machine changes → Update flow diagram
|
||||
- New hardware driver → Update HAL diagram
|
||||
|
||||
## Changelog Generation
|
||||
|
||||
### Format (Keep a Changelog)
|
||||
```markdown
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- CLINK offer support for cash-in flow
|
||||
- Puloon dispenser driver
|
||||
|
||||
### Changed
|
||||
- Upgraded to XState v5 actor model
|
||||
|
||||
### Fixed
|
||||
- Race condition in bill acceptance
|
||||
|
||||
### Security
|
||||
- Added NIP-44 encryption for receipts
|
||||
```
|
||||
|
||||
### Auto-detection
|
||||
From git commits since last release:
|
||||
- `feat:` → Added
|
||||
- `fix:` → Fixed
|
||||
- `refactor:` → Changed
|
||||
- `security:` → Security
|
||||
- `BREAKING:` → Breaking Changes
|
||||
|
||||
## Output Format
|
||||
|
||||
### Sync Report
|
||||
```markdown
|
||||
## Documentation Sync: [target]
|
||||
|
||||
### Outdated Docs
|
||||
| Doc | Code Change | Status |
|
||||
|-----|-------------|--------|
|
||||
| api/clink.md | createOffer params | ⚠️ Outdated |
|
||||
| guides/development.md | New env var | ⚠️ Missing |
|
||||
|
||||
### Suggested Updates
|
||||
1. `api/clink.md:45` - Add `timeout` parameter to createOffer
|
||||
2. `guides/development.md` - Add LIGHTNING_PUB_URL env var
|
||||
|
||||
### Missing Documentation
|
||||
- `packages/cashu/src/wallet.ts` - No API docs
|
||||
```
|
||||
|
||||
### Generated Docs
|
||||
```markdown
|
||||
## Generated: [file]
|
||||
|
||||
### API Reference
|
||||
|
||||
#### `createOffer(identity, relays, priceType, amount?)`
|
||||
|
||||
Creates a CLINK offer for receiving Lightning payments.
|
||||
|
||||
**Parameters:**
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| identity | MachineIdentity | Machine nsec/npub |
|
||||
| relays | string[] | Relay URLs |
|
||||
| priceType | 'fixed' \| 'variable' | Pricing model |
|
||||
| amount | number? | Amount in sats |
|
||||
|
||||
**Returns:** `string` - Encoded noffer
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
const offer = createOffer(identity, ['wss://relay'], 'fixed', 10000)
|
||||
```
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
/docs sync packages/clink/
|
||||
```
|
||||
|
||||
```
|
||||
/docs api packages/nostr-client/src/
|
||||
```
|
||||
|
||||
```
|
||||
/docs changelog --since v0.1.0
|
||||
```
|
||||
200
.claude/skills/hal-check.md
Normal file
200
.claude/skills/hal-check.md
Normal 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
|
||||
```
|
||||
168
.claude/skills/lightning-check.md
Normal file
168
.claude/skills/lightning-check.md
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
# /lightning-check - Lightning.Pub Conformity Agent
|
||||
|
||||
## Purpose
|
||||
Validate Lightning.Pub integration and CLINK protocol conformity.
|
||||
|
||||
## Invocation
|
||||
```
|
||||
/lightning-check [target] [--clink] [--wallet]
|
||||
```
|
||||
|
||||
Where:
|
||||
- `target` - File or directory to check
|
||||
- `--clink` - Focus on CLINK offer/debit flow
|
||||
- `--wallet` - Focus on wallet operations
|
||||
|
||||
## Lightning.Pub Integration
|
||||
|
||||
### Connection
|
||||
Lightning.Pub uses Nostr for all communication:
|
||||
|
||||
```typescript
|
||||
// Connection via nprofile
|
||||
const nprofile = 'nprofile1...' // Contains pubkey + relay hints
|
||||
|
||||
// All operations are Nostr events to Lightning.Pub's pubkey
|
||||
await relay.publish({
|
||||
kind: 21002, // CLINK debit
|
||||
content: encrypted_request,
|
||||
tags: [['p', lightningPubPubkey]],
|
||||
})
|
||||
```
|
||||
|
||||
### Required Checks
|
||||
- [ ] Using correct event kinds (21001, 21002, 21003)
|
||||
- [ ] Proper NIP-44 encryption for requests
|
||||
- [ ] Handling async responses via subscription
|
||||
- [ ] Proper error handling for payment failures
|
||||
|
||||
## CLINK Protocol
|
||||
|
||||
### Offer Flow (Kind 21001)
|
||||
```
|
||||
User scans noffer → Wallet sends 21002 → ATM responds with invoice → User pays
|
||||
```
|
||||
|
||||
Validation:
|
||||
- [ ] noffer encoding is valid
|
||||
- [ ] Relays included in offer
|
||||
- [ ] Price type correctly specified (fixed/variable/spontaneous)
|
||||
- [ ] Amount bounds validated
|
||||
|
||||
### Debit Flow (Kind 21002)
|
||||
Request structure:
|
||||
```json
|
||||
{
|
||||
"method": "pay_invoice",
|
||||
"params": {
|
||||
"invoice": "lnbc...",
|
||||
"amount_msat": 100000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Response structure:
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"preimage": "...",
|
||||
"fee_msat": 1000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Validation:
|
||||
- [ ] Invoice format valid (BOLT11)
|
||||
- [ ] Amount matches invoice
|
||||
- [ ] Preimage verified against payment hash
|
||||
- [ ] Fee within acceptable bounds
|
||||
- [ ] Timeout handling
|
||||
|
||||
### Manage Flow (Kind 21003)
|
||||
For operator commands:
|
||||
```json
|
||||
{
|
||||
"method": "get_balance",
|
||||
"params": {}
|
||||
}
|
||||
```
|
||||
|
||||
Validation:
|
||||
- [ ] Only authorized operators can send
|
||||
- [ ] Commands are properly authenticated
|
||||
- [ ] Responses handled securely
|
||||
|
||||
## Invoice Validation
|
||||
|
||||
### BOLT11 Checks
|
||||
- [ ] Valid bech32 encoding
|
||||
- [ ] Expiry not passed
|
||||
- [ ] Amount matches expected
|
||||
- [ ] Description hash valid (if used)
|
||||
- [ ] Payment hash extractable
|
||||
|
||||
### Security Checks
|
||||
- [ ] Never pay same invoice twice
|
||||
- [ ] Amount limits enforced
|
||||
- [ ] Rate limiting on payments
|
||||
- [ ] Proper logging (no sensitive data)
|
||||
|
||||
## Wallet Operations
|
||||
|
||||
### Balance Queries
|
||||
- [ ] Cached appropriately (not every render)
|
||||
- [ ] Error handling for offline
|
||||
- [ ] Display in correct units (sats, not msat)
|
||||
|
||||
### Invoice Generation
|
||||
- [ ] Unique payment hashes
|
||||
- [ ] Reasonable expiry times
|
||||
- [ ] Description for record-keeping
|
||||
- [ ] Amount in correct units
|
||||
|
||||
## Output Format
|
||||
|
||||
```markdown
|
||||
## Lightning.Pub Conformity: [target]
|
||||
|
||||
### CLINK Protocol
|
||||
| Flow | Status | Notes |
|
||||
|------|--------|-------|
|
||||
| Offer (21001) | ✅ | |
|
||||
| Debit (21002) | ⚠️ | Missing timeout |
|
||||
| Manage (21003) | ✅ | |
|
||||
|
||||
### Invoice Handling
|
||||
- [ ] `file:line` - Issue description
|
||||
|
||||
### Integration Issues
|
||||
- [ ] Description with fix suggestion
|
||||
|
||||
### Recommendations
|
||||
- [ ] Performance/UX improvements
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
/lightning-check packages/lightning/src/ --clink
|
||||
```
|
||||
|
||||
Output:
|
||||
```markdown
|
||||
## Lightning.Pub Conformity: packages/lightning/src/
|
||||
|
||||
### CLINK Protocol
|
||||
| Flow | Status | Notes |
|
||||
|------|--------|-------|
|
||||
| Offer (21001) | ✅ | Properly encoded |
|
||||
| Debit (21002) | ⚠️ | No timeout handling |
|
||||
|
||||
### Issues Found
|
||||
- [ ] `client.ts:89` - Debit request has no timeout, could hang indefinitely
|
||||
- [ ] `client.ts:112` - Payment hash not verified against preimage
|
||||
|
||||
### Recommendations
|
||||
- Add 30-second timeout for CLINK debit requests
|
||||
- Implement invoice deduplication to prevent double-pay
|
||||
```
|
||||
125
.claude/skills/nostr-check.md
Normal file
125
.claude/skills/nostr-check.md
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
# /nostr-check - Nostr Conformity Agent
|
||||
|
||||
## Purpose
|
||||
Validate Nostr Implementation Proposals (NIP) conformity and optimize Nostr-related code.
|
||||
|
||||
## Invocation
|
||||
```
|
||||
/nostr-check [target] [--nips NIP1,NIP2,...]
|
||||
```
|
||||
|
||||
Where `target` can be:
|
||||
- A file path
|
||||
- A directory
|
||||
- `--events` to validate event structures
|
||||
- `--relay` to check relay configuration
|
||||
|
||||
## Relevant NIPs for Lamassu ATM
|
||||
|
||||
### Core NIPs (Must Implement)
|
||||
| NIP | Description | Usage in Lamassu |
|
||||
|-----|-------------|------------------|
|
||||
| NIP-01 | Basic protocol | Event structure, relay communication |
|
||||
| NIP-19 | bech32 entities | npub, nsec, nprofile encoding |
|
||||
| NIP-42 | Auth | Private relay authentication |
|
||||
| NIP-44 | Encrypted payloads | Secure DMs, receipts |
|
||||
| NIP-59 | Gift wrapping | Anonymous message delivery |
|
||||
|
||||
### Application NIPs
|
||||
| NIP | Description | Usage in Lamassu |
|
||||
|-----|-------------|------------------|
|
||||
| NIP-17 | Private DMs | Receipt delivery |
|
||||
| NIP-47 | Nostr Wallet Connect | Potential wallet integration |
|
||||
| NIP-57 | Lightning Zaps | Optional tipping |
|
||||
|
||||
### Custom Event Kinds
|
||||
| Kind | Description | Structure |
|
||||
|------|-------------|-----------|
|
||||
| 21001 | CLINK Offer | `{ pubkey, relays, priceType, amount? }` |
|
||||
| 21002 | CLINK Debit | Payment request/response |
|
||||
| 21003 | CLINK Manage | Operator commands |
|
||||
| 30078 | Machine Status | Replaceable, `d` tag = "status" |
|
||||
| 30079 | Transaction Record | Replaceable, `d` tag = "tx:{txid}" |
|
||||
|
||||
## Validation Checks
|
||||
|
||||
### Event Structure (NIP-01)
|
||||
```typescript
|
||||
interface Event {
|
||||
id: string // 32-byte hex
|
||||
pubkey: string // 32-byte hex
|
||||
created_at: number // Unix timestamp
|
||||
kind: number // Event kind
|
||||
tags: string[][] // Array of tag arrays
|
||||
content: string // Arbitrary string
|
||||
sig: string // 64-byte hex signature
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] `id` is valid SHA256 of serialized event
|
||||
- [ ] `pubkey` is valid 32-byte hex
|
||||
- [ ] `created_at` is reasonable (not far future/past)
|
||||
- [ ] `kind` is valid for application
|
||||
- [ ] `tags` are properly formatted
|
||||
- [ ] `sig` is valid Schnorr signature
|
||||
|
||||
### bech32 Encoding (NIP-19)
|
||||
- [ ] npub/nsec properly encoded
|
||||
- [ ] nprofile includes relay hints
|
||||
- [ ] nevent includes author pubkey
|
||||
- [ ] No confusion between hex and bech32
|
||||
|
||||
### Encryption (NIP-44)
|
||||
- [ ] Using NIP-44 (not deprecated NIP-04)
|
||||
- [ ] Proper key derivation
|
||||
- [ ] Random nonce for each message
|
||||
- [ ] MAC verification before decryption
|
||||
|
||||
### Auth (NIP-42)
|
||||
- [ ] Challenge-response implemented
|
||||
- [ ] Auth events have proper `relay` tag
|
||||
- [ ] Auth events signed correctly
|
||||
- [ ] Timeout handling for auth flow
|
||||
|
||||
## Optimization Suggestions
|
||||
|
||||
### Relay Communication
|
||||
- Use connection pooling
|
||||
- Implement proper reconnection with backoff
|
||||
- Batch event publishing when possible
|
||||
- Use REQ filters efficiently
|
||||
|
||||
### Event Handling
|
||||
- Verify signatures before processing
|
||||
- Cache verified events
|
||||
- Use proper indexing for event lookups
|
||||
- Implement proper subscription management
|
||||
|
||||
## Output Format
|
||||
|
||||
```markdown
|
||||
## Nostr Conformity: [target]
|
||||
|
||||
### NIP Compliance
|
||||
| NIP | Status | Notes |
|
||||
|-----|--------|-------|
|
||||
| NIP-01 | ✅ Pass | |
|
||||
| NIP-19 | ⚠️ Issue | See below |
|
||||
|
||||
### Issues Found
|
||||
- [ ] `file:line` - Description
|
||||
|
||||
### Optimization Opportunities
|
||||
- [ ] Description with rationale
|
||||
|
||||
### Custom Event Validation
|
||||
| Kind | Valid | Notes |
|
||||
|------|-------|-------|
|
||||
| 30078 | ✅ | Machine status properly formatted |
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
/nostr-check packages/nostr-client/src/events.ts --nips NIP-01,NIP-19
|
||||
```
|
||||
105
.claude/skills/security.md
Normal file
105
.claude/skills/security.md
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# /security - Security Review Agent
|
||||
|
||||
## Purpose
|
||||
Perform security audits on code changes, focusing on Bitcoin/Lightning ATM-specific vulnerabilities.
|
||||
|
||||
## Invocation
|
||||
```
|
||||
/security [target]
|
||||
```
|
||||
|
||||
Where `target` can be:
|
||||
- A file path (e.g., `packages/lightning/src/client.ts`)
|
||||
- A directory (e.g., `packages/hal/`)
|
||||
- `--staged` for staged git changes
|
||||
- `--all` for full codebase scan
|
||||
|
||||
## Review Checklist
|
||||
|
||||
### 1. Bitcoin/Lightning Security
|
||||
- [ ] Private keys never logged or exposed
|
||||
- [ ] nsec (Nostr secret keys) protected with proper permissions (0600)
|
||||
- [ ] Invoice amounts validated before payment
|
||||
- [ ] Payment preimages handled securely
|
||||
- [ ] No hardcoded mnemonics, seeds, or keys
|
||||
- [ ] Proper BOLT11/BOLT12 invoice validation
|
||||
|
||||
### 2. Hardware Security (ATM-specific)
|
||||
- [ ] Bill validator amounts cross-checked
|
||||
- [ ] Dispenser commands validated (prevent over-dispensing)
|
||||
- [ ] Hardware error states handled gracefully
|
||||
- [ ] No race conditions in cash handling
|
||||
- [ ] Timeout handling for hardware operations
|
||||
|
||||
### 3. Nostr Security
|
||||
- [ ] NIP-44 encryption used for sensitive messages
|
||||
- [ ] Event signatures verified before processing
|
||||
- [ ] Relay URLs validated (no injection)
|
||||
- [ ] NIP-42 auth implemented for private relay
|
||||
- [ ] No pubkey/npub confusion (proper type safety)
|
||||
|
||||
### 4. General Security
|
||||
- [ ] Input validation on all external data
|
||||
- [ ] SQL injection prevention (parameterized queries)
|
||||
- [ ] No command injection in Bash/shell calls
|
||||
- [ ] Proper error handling (no sensitive data in errors)
|
||||
- [ ] Rate limiting on API endpoints
|
||||
- [ ] HTTPS/WSS enforced in production
|
||||
|
||||
### 5. Rust-specific (HAL)
|
||||
- [ ] No `unsafe` blocks without justification
|
||||
- [ ] Error handling with Result, no unwrap() in production
|
||||
- [ ] Buffer bounds checking for serial communication
|
||||
- [ ] Proper lifetime management
|
||||
|
||||
### 6. TypeScript-specific
|
||||
- [ ] Strict null checks honored
|
||||
- [ ] No `any` types
|
||||
- [ ] Zod validation on external data
|
||||
- [ ] No eval() or dynamic code execution
|
||||
|
||||
## Output Format
|
||||
|
||||
```markdown
|
||||
## Security Review: [target]
|
||||
|
||||
### Critical Issues
|
||||
- [ ] Issue description with file:line reference
|
||||
|
||||
### High Priority
|
||||
- [ ] Issue description with file:line reference
|
||||
|
||||
### Medium Priority
|
||||
- [ ] Issue description with file:line reference
|
||||
|
||||
### Low Priority / Suggestions
|
||||
- [ ] Suggestion with rationale
|
||||
|
||||
### Passed Checks
|
||||
- [x] Check that passed
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
/security packages/lightning/src/client.ts
|
||||
```
|
||||
|
||||
Output:
|
||||
```markdown
|
||||
## Security Review: packages/lightning/src/client.ts
|
||||
|
||||
### Critical Issues
|
||||
None found.
|
||||
|
||||
### High Priority
|
||||
- [ ] `client.ts:45` - Invoice amount not validated before `payInvoice()` call
|
||||
|
||||
### Medium Priority
|
||||
- [ ] `client.ts:78` - Error message includes full stack trace, may leak internal paths
|
||||
|
||||
### Passed Checks
|
||||
- [x] Private keys not exposed in logs
|
||||
- [x] NIP-44 encryption used for DMs
|
||||
- [x] Proper TypeScript strict mode
|
||||
```
|
||||
201
.claude/skills/test.md
Normal file
201
.claude/skills/test.md
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
# /test - Testing Agent
|
||||
|
||||
## Purpose
|
||||
Run tests, analyze coverage, generate test cases, and validate ATM transaction flows.
|
||||
|
||||
## Invocation
|
||||
```
|
||||
/test [command] [target]
|
||||
```
|
||||
|
||||
Commands:
|
||||
- `run` - Run tests (default)
|
||||
- `coverage` - Run with coverage report
|
||||
- `generate` - Generate test cases for a file
|
||||
- `flow` - Validate transaction flow
|
||||
- `hardware` - Run hardware mock tests
|
||||
|
||||
## Test Categories
|
||||
|
||||
### 1. Unit Tests
|
||||
Location: `*.test.ts` or `*.spec.ts` alongside source files
|
||||
|
||||
```bash
|
||||
pnpm test # All tests
|
||||
pnpm test --filter @lamassu/nostr-client # Specific package
|
||||
```
|
||||
|
||||
### 2. Integration Tests
|
||||
Location: `tests/integration/`
|
||||
|
||||
Tests cross-package interactions:
|
||||
- Nostr client + CLINK
|
||||
- State machine + Hardware mocks
|
||||
- Lightning client + Invoice handling
|
||||
|
||||
### 3. E2E Tests (Playwright)
|
||||
Location: `tests/e2e/`
|
||||
|
||||
Full transaction flows:
|
||||
- Cash-in flow (bill insert → Lightning payment)
|
||||
- Cash-out flow (Lightning receive → dispense)
|
||||
- Error recovery flows
|
||||
|
||||
### 4. Hardware Mock Tests
|
||||
Test against mock hardware:
|
||||
|
||||
```bash
|
||||
pnpm test:hardware # With mock validator/dispenser
|
||||
REAL_HARDWARE=true pnpm test:hardware # With real hardware (CI skip)
|
||||
```
|
||||
|
||||
## Test Generation
|
||||
|
||||
### For a new file:
|
||||
```
|
||||
/test generate packages/lightning/src/client.ts
|
||||
```
|
||||
|
||||
Generates test skeleton:
|
||||
```typescript
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { LightningPubClient } from './client'
|
||||
|
||||
describe('LightningPubClient', () => {
|
||||
describe('createInvoice', () => {
|
||||
it('should create valid BOLT11 invoice', async () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it('should handle network errors', async () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it('should validate amount bounds', async () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Test Case Suggestions
|
||||
Based on code analysis, suggest test cases for:
|
||||
- Happy path
|
||||
- Edge cases (null, empty, max values)
|
||||
- Error conditions
|
||||
- Timeout scenarios
|
||||
- Concurrent operations
|
||||
|
||||
## Transaction Flow Validation
|
||||
|
||||
### Cash-In Flow
|
||||
```
|
||||
/test flow cash-in
|
||||
```
|
||||
|
||||
Validates:
|
||||
1. Idle → Select Cash-In
|
||||
2. Bill insertion events received
|
||||
3. Amount calculation correct
|
||||
4. CLINK offer generated
|
||||
5. Payment received event
|
||||
6. Receipt sent (optional)
|
||||
7. Return to Idle
|
||||
|
||||
### Cash-Out Flow
|
||||
```
|
||||
/test flow cash-out
|
||||
```
|
||||
|
||||
Validates:
|
||||
1. Idle → Select Cash-Out
|
||||
2. Amount selection
|
||||
3. Invoice generated
|
||||
4. Payment received
|
||||
5. Cash dispensed
|
||||
6. Bills removed detection (F56)
|
||||
7. Return to Idle
|
||||
|
||||
### Error Flows
|
||||
```
|
||||
/test flow errors
|
||||
```
|
||||
|
||||
Validates:
|
||||
- Hardware timeout recovery
|
||||
- Payment failure handling
|
||||
- Network disconnection
|
||||
- Partial dispense handling
|
||||
|
||||
## Coverage Requirements
|
||||
|
||||
### Minimum Coverage Targets
|
||||
| Package | Statements | Branches | Functions |
|
||||
|---------|------------|----------|-----------|
|
||||
| nostr-client | 80% | 75% | 80% |
|
||||
| clink | 80% | 75% | 80% |
|
||||
| state-machine | 90% | 85% | 90% |
|
||||
| lightning | 80% | 75% | 80% |
|
||||
| hal (mocks) | 70% | 65% | 70% |
|
||||
|
||||
### Critical Paths (100% coverage required)
|
||||
- Payment processing
|
||||
- Cash dispensing logic
|
||||
- Key handling
|
||||
- Amount calculations
|
||||
|
||||
## Output Format
|
||||
|
||||
### Test Run
|
||||
```markdown
|
||||
## Test Results: [target]
|
||||
|
||||
### Summary
|
||||
- Total: 42
|
||||
- Passed: 40
|
||||
- Failed: 2
|
||||
- Skipped: 0
|
||||
|
||||
### Failed Tests
|
||||
1. `client.test.ts` > createInvoice > should validate amount
|
||||
- Expected: Error thrown
|
||||
- Received: Invoice created with negative amount
|
||||
|
||||
### Coverage
|
||||
| File | Statements | Branches | Functions |
|
||||
|------|------------|----------|-----------|
|
||||
| client.ts | 85% | 78% | 90% |
|
||||
```
|
||||
|
||||
### Test Generation
|
||||
```markdown
|
||||
## Generated Tests: [file]
|
||||
|
||||
### Test File
|
||||
`packages/lightning/src/client.test.ts`
|
||||
|
||||
### Suggested Test Cases
|
||||
1. **createInvoice**
|
||||
- ✅ Valid amount creates invoice
|
||||
- ✅ Zero amount rejected
|
||||
- ✅ Negative amount rejected
|
||||
- ✅ Network error handled
|
||||
|
||||
### Missing Coverage
|
||||
- `payInvoice` has no tests
|
||||
- Error handling branch at line 45 untested
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
/test coverage packages/state-machine/
|
||||
```
|
||||
|
||||
```
|
||||
/test generate packages/clink/src/offer.ts
|
||||
```
|
||||
|
||||
```
|
||||
/test flow cash-out
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue