upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/CHECKLIST.md
diff options
context:
space:
mode:
Diffstat (limited to 'CHECKLIST.md')
-rw-r--r--CHECKLIST.md191
1 files changed, 74 insertions, 117 deletions
diff --git a/CHECKLIST.md b/CHECKLIST.md
index b71bd14..c5dfbe4 100644
--- a/CHECKLIST.md
+++ b/CHECKLIST.md
@@ -22,158 +22,115 @@
22- [x] Tests 1-14: ALL PASSING 22- [x] Tests 1-14: ALL PASSING
23 23
24## Phase 2: E-Cash Payments — COMPLETE 24## Phase 2: E-Cash Payments — COMPLETE
25### Code Written 25- [x] Implement cashu.c/h, session.c/h, tollgate_api.c/h
26- [x] Implement cashu.c/h (Cashu token parse, base64url, checkstate, mint validation) 26- [x] Update captive portal HTML with payment form
27- [x] Implement session.c/h (time-based allotment, expiry, secret tracking, MAC tracking) 27- [x] Wire into tollgate_main.c
28- [x] Implement tollgate_api.c/h (:2121 server, GET/POST /, /usage, /whoami) 28- [x] Per-MAC access tracking, two httpd instances
29- [x] Update captive portal HTML with payment form (Cashu token textarea + "Pay & Connect") 29- [x] Bug fixes: stack overflow, heap allocations, TLS, token decode
30- [x] Wire into tollgate_main.c (session_init, api_start, session_tick loop)
31- [x] Per-MAC access tracking: `firewall_get_mac_for_ip()` using `esp_wifi_ap_get_sta_list_with_ip()` + ARP fallback
32- [x] Two httpd instances: port 80 (captive portal) and port 2121 (TollGate API)
33
34### Bug Fixes
35- [x] Stack overflow: httpd stack_size increased to 32768 (TLS+mbedTLS needs ~20KB)
36- [x] Heap allocations: cashu_token_t, cashu_proof_state_t, json_buf, post_body all heap-allocated
37- [x] TLS to mint: `esp_crt_bundle_attach` + `esp-tls` in CMakeLists.txt REQUIRES
38- [x] HTTP client: `open/write/fetch_headers/read` pattern (not `perform`)
39- [x] Token decode: dynamic `json_buf` sizing `malloc((b64_len * 3) / 4 + 4)`, strip trailing `\n`/`\r`
40- [x] POST body recv: loop `httpd_req_recv` until all `content_len` bytes read
41- [x] `secret_count` bug: capped at `MIN(proof_count, 5)` before `session_create`
42- [x] `config.c` default mint URL fixed to `testnut.cashu.space`
43- [x] Makefile: nutshell wallet targets (wallet-setup, wallet-info, mint-token, send-token)
44- [x] `tests/phase2.mjs`: `/whoami` test checks `includes('mac=')`
45
46### Tests Passing
47- [x] Tests 15-24: ALL PASSING 30- [x] Tests 15-24: ALL PASSING
48 31
49## Phase 3: On-Device Wallet + Nostr Identity + Wifistr — COMPLETE 32## Phase 3: On-Device Wallet + Nostr Identity + Wifistr — COMPLETE
50### nucula Wallet Integration 33- [x] nucula wallet integration (git submodule, C++ bridge, C API)
51- [x] Add nucula as git submodule (`nucula_src/`) 34- [x] Nostr identity derivation (HMAC-SHA512, MAC/SSID/IP)
52- [x] Create `components/secp256k1/` (symlink to nucula's libsecp256k1) 35- [x] Nostr event signing (NIP-01, Schnorr)
53- [x] Create `components/nucula_lib/` (C++ bridge + C API) 36- [x] Geohash encoding
54- [x] C bridge: `nucula_wallet.h` (init, receive, send, swap_all, balance, proofs_json) 37- [x] Wifistr service discovery (kind 38787)
55- [x] All wallet operations tested on Board A: pay, swap, send, persistence 38- [x] 58 unit tests passing
56
57### Nostr Identity Derivation (identity.c/h)
58- [x] HMAC-SHA512 derivation via mbedtls, npub via secp256k1
59- [x] Derive STA/AP MAC, SSID, AP IP from nsec
60- [x] Set MACs via `esp_wifi_set_mac()` in boot sequence
61- [x] 24/24 unit tests passing
62
63### Nostr Event Signing (nostr_event.c/h)
64- [x] NIP-01 canonical JSON, SHA-256 ID, Schnorr signature
65- [x] 23/23 unit tests passing
66
67### Geohash Encoding (geohash.c/h)
68- [x] Standard base-32 geohash encoding
69- [x] 11/11 unit tests passing
70
71### Wifistr Service Discovery (wifistr.c/h)
72- [x] kind 38787 event builder + WebSocket relay publish
73- [x] Publish on boot + periodic timer (6h default)
74- [x] Verified published to relay.damus.io and nos.lol
75 39
76## Phase 4: ESP32 TollGate Client Detection + Auto-Payment — COMPLETE (commit `78dd599`) 40## Phase 4: ESP32 TollGate Client Detection + Auto-Payment — COMPLETE (commit `78dd599`)
77- [x] tollgate_client.c/h — detection, payment, monitoring, state machine 41- [x] tollgate_client.c/h — detection, payment, monitoring, state machine
78- [x] Config fields: client_enabled, client_steps_to_buy, etc.
79- [x] Integration into tollgate_main.c
80- [x] 30/30 unit tests passing 42- [x] 30/30 unit tests passing
81 43
82## Phase 5: Lightning Auto-Payout — COMPLETE (commit `cb4bd7d`) 44## Phase 5: Lightning Auto-Payout — COMPLETE (commit `cb4bd7d`)
83- [x] lnurl_pay.c/h — LNURL-pay HTTP flow 45- [x] lnurl_pay.c/h, lightning_payout.c/h, nucula_wallet_melt()
84- [x] lightning_payout.c/h — periodic balance check, threshold, multi-recipient split, melt 46- [x] 18 unit tests passing
85- [x] nucula_wallet_melt() bridge for NUT-05
86- [x] Config: payout.enabled, recipients, mints, fee_tolerance, etc.
87- [x] 7/7 lnurl_pay + 11/11 lightning_payout = 18 unit tests passing
88 47
89## Phase 6: Bytes-Based Billing — COMPLETE (commit `edd125d`) 48## Phase 6: Bytes-Based Billing — COMPLETE (commit `edd125d`)
90- [x] Dual-metric session support (milliseconds + bytes) 49- [x] Dual-metric session support (milliseconds + bytes)
91- [x] session_create_bytes(), session_add_bytes()
92- [x] Config: metric, step_size_bytes
93- [x] Discovery endpoint advertises correct metric
94- [x] Unit tests: bytes session lifecycle, mixed metrics
95 50
96## Phase 7: MCP Handler + NIP-04 + CVM Server — COMPLETE (commit `fdf662f`) 51## Phase 7: MCP Handler + NIP-04 + CVM Server — COMPLETE (commit `fdf662f`)
97- [x] mcp_handler.c/h — 4 tools (get_config, set_config, get_balance, wallet_send), 25 unit tests 52- [x] mcp_handler.c/h (4 tools, 25 unit tests)
98- [x] nip04.c/h — AES-256-CBC + ECDH with 0x02 compressed pubkey prefix, 15 unit tests 53- [x] nip04.c/h (AES-256-CBC + ECDH, 15 unit tests)
99- [x] cvm_server.c/h — Nostr DM listener skeleton with FreeRTOS task 54- [x] cvm_server.c/h (Nostr DM listener)
100- [x] Fixed NIP-04 IV bug: mbedtls_aes_crypt_cbc modifies IV in-place
101- [x] Fixed missing esp_random.h include in nip04.c
102- [x] 156 total unit tests passing across 10 test binaries
103 55
104## Bug Fixes — COMPLETE (commit `3342c8e`) 56## Bug Fixes — COMPLETE (commit `3342c8e`)
105- [x] reset_auth_handler now calls session_revoke_all() before firewall_revoke_all() 57- [x] reset_auth, /usage, metric default, sys_evt stack overflow fixes
106- [x] Port 80 /usage shows real session data (remaining/total) instead of "0/0"
107- [x] Config metric defaults to "milliseconds" (ESP32 can't track per-client bytes from NAT)
108- [x] Fixed sys_evt stack overflow: deferred start_services() to dedicated 32KB task
109 58
110## Playwright Interop Tests — COMPLETE (commit `4fb44e7`) 59## Playwright Interop Tests — COMPLETE (commit `4fb44e7`)
111- [x] 18/18 tests passing (11 ESP32 + 7 ESP32↔OpenWRT interop) 60- [x] 18/18 tests passing (11 ESP32 + 7 ESP32↔OpenWRT interop)
112- [x] 7 screenshots generated 61
113- [x] Double-spend rejection verified on live hardware 62## Per-Client NAT Filtering — COMPLETE (commit `0c2c67b`)
63- [x] Create `main/lwip_tollgate_hooks.h` — LWIP_HOOK_IP4_CANFORWARD definition
64- [x] Update `CMakeLists.txt` — inject hook header into lwIP compilation
65- [x] Add `tollgate_ip4_canforward_filter()` to `firewall.c` — filter by source IP, network byte order
66- [x] NAT always ON, per-client filter in lwIP forwarding path
67- [x] Remove `update_nat()`, `firewall_enable_nat()`, `firewall_disable_nat()`
68- [x] Subnet-aware: only filter AP subnet packets, allow internet responses
69- [x] Fix byte order bug: firewall stores IPs in network byte order
70- [x] Reduce API server stack 32KB→16KB (fixes ESP_ERR_HTTPD_TASK)
71- [x] E2E verified: block→pay→allow→revoke→block on live hardware
72
73## Spent-Secret Cleanup — COMPLETE (commit `0c2c67b`)
74- [x] Remove `s_spent_secrets[]`, `session_is_secret_spent()` from session.c
75- [x] Remove `spent_secrets`/`spent_secret_count` from `session_t`
76- [x] Remove spent-secret params from `session_create()`/`session_create_bytes()`
77- [x] Remove local spent-secret check in `tollgate_api.c`
78- [x] Update `tests/unit/test_session.c`
79- [x] 186 unit tests passing
114 80
115--- 81---
116 82
117## TODO — In Progress 83## TODO — Remaining
118
119### Per-Client NAT Filtering (Multi-Client Fix)
120- [ ] Create `main/lwip_tollgate_hooks.h` — LWIP_HOOK_IP4_CANFORWARD definition
121- [ ] Update `CMakeLists.txt` — inject hook header into lwIP compilation
122- [ ] Add `tollgate_ip4_canforward_filter()` to `firewall.c` — filter forwarded packets by source IP
123- [ ] Change firewall strategy: NAT always ON, per-client filter in lwIP forwarding path
124- [ ] Remove `update_nat()`, `firewall_enable_nat()`, `firewall_disable_nat()` from firewall.c
125- [ ] Update `stop_services()` in tollgate_main.c — remove `firewall_disable_nat()` call
126- [ ] Add unit test for filter function
127- [ ] Build, flash, test on Board A
128- [ ] Verify multi-client isolation: expire one client while other is active
129
130### Spent-Secret Cleanup
131- [ ] Remove `s_spent_secrets[]` and `session_is_secret_spent()` from `session.c`
132- [ ] Remove `spent_secrets` field from `session_t` struct in `session.h`
133- [ ] Remove `spent_secrets` params from `session_create()` and `session_create_bytes()`
134- [ ] Remove local spent-secret check in `tollgate_api.c` (lines 227-239)
135- [ ] Remove `secrets[]` array construction in `tollgate_api.c`
136- [ ] Update `tests/unit/test_session.c` — remove secret-tracking tests
137- [ ] Run `make test-unit` — all tests pass
138
139### Integration Tests (tests/integration/)
140- [ ] Create `tests/integration/` directory
141- [ ] Move existing tests (api.mjs, network.mjs, smoke.mjs, phase2.mjs) into integration/
142- [ ] Write `test-reset-auth.mjs` — verify sessions cleared after reset
143- [ ] Write `test-session-lifecycle.mjs` — pay → verify usage → wait expiry → verify blocked (65s)
144- [ ] Write `test-dns-firewall.mjs` — DNS hijack before auth, forward after auth
145- [ ] Update Makefile targets for new paths
146- [ ] All integration tests passing
147 84
148### Test Reorganization 85### Test Reorganization
149- [ ] Fix all hardcoded IPs → `process.env.TOLLGATE_IP` 86- [ ] Fix hardcoded IP fallbacks: `192.168.4.1` → `10.192.45.1` in test files
150- [ ] Move `tests/captive-portal.spec.mjs` → `tests/e2e/` 87- [ ] Create `tests/integration/` and `tests/e2e/` directories
151- [ ] Move `tests/interop-happy-path.spec.mjs` → `tests/e2e/` or `tests/integration/` 88- [ ] Move `api.mjs`, `network.mjs`, `phase2.mjs`, `smoke.mjs` → `tests/integration/`
152- [ ] Move `tests/playwright.config.mjs` → `tests/e2e/` 89- [ ] Move `captive-portal.spec.mjs`, `interop-happy-path.spec.mjs` → `tests/e2e/`
90- [ ] Move `playwright.config.mjs` → `tests/e2e/`
91
92### New Integration Tests
93- [ ] Write `tests/integration/test-reset-auth.mjs` — reset → verify blocked → pay → verify allowed → reset → verify blocked
94- [ ] Write `tests/integration/test-session-expiry.mjs` — pay → wait 65s → verify blocked (slow test)
95- [ ] Write `tests/integration/test-dns-firewall.mjs` — DNS hijack before auth, forward after auth, per-client NAT filter
96
97### Makefile & Package Updates
98- [ ] Add `test-unit`, `test-integration`, `test-e2e`, `test-all`, `test-session-expiry` targets
99- [ ] Update `package.json` scripts for new paths
100- [ ] Update existing targets to new paths
153 101
154### Playwright Video Recording Fix 102### Playwright Video Recording Fix
155- [ ] Per-test context isolation (not shared serial context) 103- [ ] Per-test context isolation in playwright.config.mjs
156- [ ] Verify `.webm` files generated in test-results/ 104- [ ] Verify `.webm` files generated in `tests/e2e/test-results/`
157 105
158### OpenWRT Interop 106### AGENTS.md Update
159- [ ] Investigate `nofee.testnut.cashu.space` API compatibility issues 107- [ ] Update firewall description: "per-client NAT filter via LWIP_HOOK_IP4_CANFORWARD"
160- [ ] Fix cashu CLI v0.19.2 Pydantic validation failures with missing `active` field 108- [ ] Update session.c description: remove "spent-secret tracking"
161 109
162### Board B 110### OpenWRT Interop
163- [ ] Flash Board B with current firmware (different nsec) 111- [ ] SSH to `root@10.47.41.1`, verify `tollgate-wrt` still running
164- [ ] Cross-board payment test: Board B → Board A 112- [ ] Test `curl http://10.47.41.1:2121/` — kind=10021 response
165- [ ] ESP32→ESP32 auto-payment (Scenario 5) 113- [ ] Investigate `nofee.testnut.cashu.space` API compatibility
114- [ ] Document findings
115
116### Board B — Flash + Cross-Board Test
117- [x] Generate nsec for Board B: `9af47906b45aca5e238390f3d03c8274e154198e81aa2095065627d1e61ca968`
118- [x] Derived identity: SSID `TollGate-b96d80`, AP IP `10.185.47.1`, AP MAC `fe:08:f7:b9:6d:80`
119- [ ] Create Board B config.json with new nsec
120- [ ] Flash Board B at `/dev/ttyACM1`
121- [ ] Verify Board B boots with different SSID/IP
122- [ ] Cross-board payment test: Board B pays Board A (Scenario 5)
166 123
167--- 124---
168 125
169## Reminders 126## Reminders
170- **Commit + push every time a test passes that previously didn't pass** 127- **Commit + push every time a test passes that previously didn't pass**
171- Board A: `/dev/ttyACM0`, MAC `94:a9:90:2e:37:7c`, SSID `TollGate-C0E9CA`, AP IP `10.192.45.1` 128- Board A: `/dev/ttyACM0`, SSID `TollGate-C0E9CA`, AP IP `10.192.45.1`
172- Board B: `/dev/ttyACM1`, MAC `fc:01:2c:c5:50:50` 129- Board B: `/dev/ttyACM1`, SSID `TollGate-b96d80`, AP IP `10.185.47.1`, nsec `9af47906...`
173- OpenWRT Router: SSH `root@10.47.41.1`, port 2121 130- OpenWRT Router: SSH `root@10.47.41.1`, port 2121
174- `source ~/esp/esp-idf/export.sh` before `idf.py` 131- `source ~/esp/esp-idf/export.sh` before `idf.py`
175- Latest commit: `3342c8e` 132- Latest commit: `0c2c67b`
176- 156 unit tests + 18 Playwright tests — all passing 133- 186 unit tests + 18 Playwright tests — all passing
177- sudo password: `c03rad0r123` 134- sudo password: `c03rad0r123`
178- Token generation: `cashu -h https://testnut.cashu.space send --legacy 21` 135- Token generation: `cashu -h https://testnut.cashu.space send --legacy 21`
179- See `AGENTS.md` for full testing rules 136- See `AGENTS.md` for full testing rules