diff options
| author | Your Name <you@example.com> | 2026-05-15 13:06:25 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-15 13:06:25 +0530 |
| commit | 8a2307a5ced6da94cc674602219d5a68a1246264 (patch) | |
| tree | fe622a9960434fc3a42d3d1aa2ba748d804118fa /PLAN.md | |
initiall commit
Diffstat (limited to 'PLAN.md')
| -rw-r--r-- | PLAN.md | 99 |
1 files changed, 99 insertions, 0 deletions
| @@ -0,0 +1,99 @@ | |||
| 1 | # TollGate ESP32 — Test-Driven Development Plan | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | |||
| 5 | Build 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 | ||