upleb.uk

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

summaryrefslogtreecommitdiff
path: root/PLAN.md
diff options
context:
space:
mode:
Diffstat (limited to 'PLAN.md')
-rw-r--r--PLAN.md99
1 files changed, 99 insertions, 0 deletions
diff --git a/PLAN.md b/PLAN.md
new file mode 100644
index 0000000..c4373fb
--- /dev/null
+++ b/PLAN.md
@@ -0,0 +1,99 @@
1# TollGate ESP32 — Test-Driven Development Plan
2
3## Overview
4
5Build a TollGate firmware for two ESP32 devices, following the [TollGate protocol spec](https://github.com/OpenTollGate/tollgate) (TIP-01, TIP-02, HTTP-01/02/03). The implementation uses ESP-IDF (C/C++) and integrates the nucula Cashu wallet.
6
7## Architecture Decision: C/C++ (ESP-IDF)
8
9- Existing working captive portal is in C (ESP-IDF)
10- Nucula Cashu wallet is in C/C++ (ESP-IDF)
11- ESP-IDF is already installed at `~/esp/esp-idf`
12- No Rust/ESP32 toolchain installed
13
14## Technology Stack
15
16| Layer | Technology |
17|-------|-----------|
18| Framework | ESP-IDF v5.4.1 (C/C++) |
19| Cashu wallet | nucula `Wallet` class (Phase 3) |
20| HTTP server | `esp_http_server` (port 80 captive portal, port 2121 TollGate API) |
21| DNS | Custom UDP task (hijack unauthenticated, forward authenticated) |
22| NAT | lwIP NAPT |
23| Testing | Playwright + curl + pyserial |
24| Build | Makefile |
25
26## Three-Phase Plan
27
28### Phase 1: Captive Portal + Firewall (No Payments)
29
30**Goal:** WiFi repeater with captive portal that gates internet access. Validates DNS hijack, NAT, DHCP, firewall.
31
32**Endpoints:**
33- `GET /whoami` — returns client MAC
34- `GET /usage` — returns `-1/-1`
35- Captive portal HTML on port 80
36
37**14 Test Cases:**
38| # | Test | Method | Pass Criteria |
39|---|------|--------|---------------|
40| 1 | Boot and AP appears | Serial + nmcli | SSID visible in scan |
41| 2 | DHCP lease | nmcli connect | Gets IP in 192.168.4.0/24 |
42| 3 | Captive portal serves HTML | GET / | 200, contains "TollGate" |
43| 4 | Captive detection URIs work | GET /generate_204 etc. | All return portal HTML |
44| 5 | DNS hijack before auth | nslookup google.com | Resolves to 192.168.4.1 |
45| 6 | No internet before auth | ping 8.8.8.8 | Fails |
46| 7 | /whoami returns MAC | GET /whoami | Returns mac=XX:XX:... |
47| 8 | /usage returns no session | GET /usage | Returns -1/-1 |
48| 9 | Grant access via API | GET /grant_access | 200, status granted |
49| 10 | DNS forward after auth | nslookup google.com | Resolves to real IP |
50| 11 | Internet after auth | ping 8.8.8.8 | Succeeds |
51| 12 | HTTP browsing works | Playwright | Page loads |
52| 13 | Reset auth | GET /reset_authentication | 200 |
53| 14 | Internet blocked after reset | ping 8.8.8.8 | Fails |
54
55### Phase 2: E-Cash Payments (Simple Melt-to-LNURL)
56
57**Goal:** Replace free access with Cashu payment. ESP32 parses token, melts via mint API to operator's LNURL.
58
59**New Endpoints:**
60- `GET /` on :2121 — TollGate advertisement (kind=10021)
61- `POST /` on :2121 — Accept Cashu token, melt, return session (kind=1022) or notice (kind=21023)
62
63**13 Additional Test Cases:**
64| # | Test | Method | Pass Criteria |
65|---|------|--------|---------------|
66| 15 | Advertisement valid | GET :2121/ | kind=10021 with price_per_step |
67| 16 | Valid payment | POST :2121/ with token | kind=1022 session |
68| 17 | Usage tracking | GET :2121/usage | 0/allotment |
69| 18 | Internet after payment | ping | Succeeds |
70| 19 | Invalid token | POST :2121/ garbage | kind=21023 error |
71| 20 | Spent token | Reuse token | kind=21023 spent error |
72| 21 | Wrong mint | Token from unaccepted mint | kind=21023 mint error |
73| 22 | Session expiry | Wait for allotment | Internet blocked |
74| 23 | Session renewal | Second payment | Allotment extended |
75| 24 | Portal payment form | Playwright paste token | Checkmark shown |
76| 25 | Two clients pay independently | Two POSTs | Both authenticated |
77| 26 | Client isolation | Only payer gets internet | Non-payer blocked |
78| 27 | Full e2e: portal→pay→browse | Playwright | Complete flow |
79
80### Phase 3: nucula Wallet Integration + Reseller
81
82**Goal:** Integrate nucula's full Cashu wallet. ESP32 holds balance, can be a reseller.
83
84**11 Additional Test Cases:**
85| # | Test | Method | Pass Criteria |
86|---|------|--------|---------------|
87| 28 | Wallet boot | Serial | Keysets loaded |
88| 29 | Receive via wallet | POST :2121/ | Balance incremented |
89| 30 | Balance persists | Reboot | Same balance |
90| 31 | Payout routine | Wait + serial | Tokens melted to LN |
91| 32 | Reseller discover | Serial | Upstream TollGate found |
92| 33 | Reseller pay | Serial + API | Token POSTed upstream |
93| 34 | Multi-hop internet | Ping from laptop | laptop→A→B→internet |
94| 35 | P2PK receive | Post P2PK token | Auto-signed, accepted |
95| 36 | DLEQ verified | Post token with DLEQ | Verified, accepted |
96| 37 | 5 consecutive payments | Loop | All authenticated |
97| 38 | Stress: rapid pay/expire | Loop with short sessions | No crash/leak |
98
99## Total: 38 Tests across 3 phases