diff options
| author | Your Name <you@example.com> | 2026-05-20 04:09:47 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-20 04:09:47 +0530 |
| commit | 0ba9e591a5ffe9b7e5833341821bd72095b6acb7 (patch) | |
| tree | a01a06ca4d141804dd624759321c0892e17a2020 | |
| parent | bb157fcb839d66b98ca375ab0ea657a08b5a21b4 (diff) | |
docs: test coverage + phase 4/5 + interop plan with checklist
| -rw-r--r-- | TEST_COVERAGE_PLAN.md | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/TEST_COVERAGE_PLAN.md b/TEST_COVERAGE_PLAN.md new file mode 100644 index 0000000..887b578 --- /dev/null +++ b/TEST_COVERAGE_PLAN.md | |||
| @@ -0,0 +1,262 @@ | |||
| 1 | # Test Coverage + Phase 4/5 + Interop Plan | ||
| 2 | |||
| 3 | Ensure full hardware + Playwright test coverage at all times. Restructure main/ to delegate | ||
| 4 | to tollgate_core. Fix NerdQAxePlus symlink. Add ESP32 ↔ OpenWRT interop tests. | ||
| 5 | |||
| 6 | ## End State | ||
| 7 | |||
| 8 | ``` | ||
| 9 | esp32-tollgate (master) | ||
| 10 | main/ = thin shell calling tollgate_core API | ||
| 11 | components/tollgate_core/ = THE reusable core (cashu, dns, firewall, session, mining, stratum) | ||
| 12 | .env = board nsecs + upstream WiFi secrets (gitignored) | ||
| 13 | |||
| 14 | esp-miner-nerdqaxeplus (develop) | ||
| 15 | components/tollgate_core/ = IDF Component Manager override_path → esp32-tollgate | ||
| 16 | |||
| 17 | physical-router-test-automation/ | ||
| 18 | esp32/Makefile = ESP32 board tests (lock-protected) | ||
| 19 | esp32/boards.env = all 3 boards with derived SSID/IP/MAC | ||
| 20 | mint-health/ = OpenWRT router tests (lock-protected) | ||
| 21 | Interop targets = ESP32 ↔ Go router bidirectional payment tests | ||
| 22 | ``` | ||
| 23 | |||
| 24 | ## Mutex Rules (MANDATORY) | ||
| 25 | |||
| 26 | | Target type | Lock mechanism | Required locks | | ||
| 27 | |-------------|---------------|----------------| | ||
| 28 | | ESP32 flash/test | `make -C esp32 lock-{a,b,c}` | Per-board lock file in locks/ | | ||
| 29 | | OpenWRT router test | `make lock` | hardware.lock | | ||
| 30 | | Interop (ESP32+router) | Both | Board lock AND hardware.lock | | ||
| 31 | | Unit tests | None | None (no hardware) | | ||
| 32 | | Build | None | None (no hardware) | | ||
| 33 | |||
| 34 | All hardware access MUST go through lock-protected Makefile targets. | ||
| 35 | No direct esptool.py, curl, or nmcli against hardware without locks. | ||
| 36 | |||
| 37 | ## Mints | ||
| 38 | |||
| 39 | | Mint | URL | Purpose | | ||
| 40 | |------|-----|---------| | ||
| 41 | | Testnut | `https://testnut.cashu.space` | ESP32 boards, auto-pays invoices | | ||
| 42 | | Testnut no-fee | `https://nofee.testnut.cashu.space` | Alpha router, feeless swaps | | ||
| 43 | | Orangesync compat | `https://testnut-compat.mints.orangesync.tech` | Beta router, mint-token tool default | | ||
| 44 | | Minibits | `https://mint.minibits.cash/Bitcoin` | Alpha router (secondary) | | ||
| 45 | |||
| 46 | --- | ||
| 47 | |||
| 48 | ## Phase 0: Fix Stale Infrastructure | ||
| 49 | |||
| 50 | - [ ] **0.1** Generate random nsec for Board C, store all 3 nsecs in esp32-tollgate/.env | ||
| 51 | - [ ] **0.2** Derive Board C identity (SSID, IP, MACs) from nsec via HMAC-SHA512 | ||
| 52 | - [ ] **0.3** Update physical-router-test-automation/esp32/boards.env: | ||
| 53 | - FIRMWARE_DIR → /home/c03rad0r/esp32-tollgate | ||
| 54 | - ARCH_FIRMWARE_DIR → /home/c03rad0r/esp32-tollgate | ||
| 55 | - RELAY_FIRMWARE_DIR → /home/c03rad0r/esp32-tollgate | ||
| 56 | - Add BOARD_C_SSID, BOARD_C_IP, BOARD_C_UUID | ||
| 57 | - Update ARCH_IP/ARCH_SSID to Board C's derived values | ||
| 58 | - [ ] **0.4** Update SPIFFS generation to read nsec from .env per board | ||
| 59 | - [ ] **0.5** Fix NerdQAxePlus broken symlink → idf_component.yml with override_path | ||
| 60 | - [ ] **0.6** Remove hardcoded include from NerdQAxePlus main/CMakeLists.txt | ||
| 61 | - [ ] **0.7** Verify NerdQAxePlus builds: BOARD=NERDAXE TOLLGATE=1 idf.py build | ||
| 62 | - [ ] **0.8** Verify esp32-tollgate builds: idf.py build | ||
| 63 | - [ ] **0.9** Verify unit tests pass: make test-unit | ||
| 64 | - [ ] **0.10** Commit + push | ||
| 65 | |||
| 66 | ## Phase 1: Baseline Hardware Tests | ||
| 67 | |||
| 68 | - [ ] **1.1** make -C esp32 lock-a PHASE="baseline" | ||
| 69 | - [ ] **1.2** make -C esp32 flash-a | ||
| 70 | - [ ] **1.3** make -C esp32 test-multi-mint-a | ||
| 71 | - [ ] **1.4** make -C esp32 test-cvm-a | ||
| 72 | - [ ] **1.5** make -C esp32 unlock-a | ||
| 73 | - [ ] **1.6** make -C esp32 lock-b PHASE="baseline" | ||
| 74 | - [ ] **1.7** make -C esp32 flash-b | ||
| 75 | - [ ] **1.8** make -C esp32 test-multi-mint-b | ||
| 76 | - [ ] **1.9** make -C esp32 unlock-b | ||
| 77 | - [ ] **1.10** make -C esp32 lock-c PHASE="baseline" | ||
| 78 | - [ ] **1.11** make -C esp32 flash-c | ||
| 79 | - [ ] **1.12** Verify Board C AP reachable (ping derived IP) | ||
| 80 | - [ ] **1.13** make -C esp32 arch-test-api-quick | ||
| 81 | - [ ] **1.14** make -C esp32 unlock-c | ||
| 82 | - [ ] **1.15** make lock PHASE="baseline-router" | ||
| 83 | - [ ] **1.16** make status ROUTER=alpha | ||
| 84 | - [ ] **1.17** make status ROUTER=beta | ||
| 85 | - [ ] **1.18** make smoke-degraded ROUTER=alpha | ||
| 86 | - [ ] **1.19** make test-captive-portal ROUTER=alpha | ||
| 87 | - [ ] **1.20** make smoke-degraded ROUTER=beta | ||
| 88 | - [ ] **1.21** make test-captive-portal ROUTER=beta | ||
| 89 | - [ ] **1.22** make unlock | ||
| 90 | - [ ] **1.23** Playwright E2E from esp32-tollgate (lock-a, connect-a, test-e2e) | ||
| 91 | - [ ] **1.24** Gate: all tests pass before proceeding | ||
| 92 | |||
| 93 | ## Phase 2: Restructure main/ → tollgate_core | ||
| 94 | |||
| 95 | Consolidate 6 duplicated modules. Order: session → firewall → cashu → dns_server → stratum_proxy → mining_payment. | ||
| 96 | |||
| 97 | ### 2A: session module | ||
| 98 | |||
| 99 | - [ ] **2A.1** Diff main/session.c vs tollgate_core/src/tollgate_core_session.c | ||
| 100 | - [ ] **2A.2** Merge unique main/ functionality into tollgate_core | ||
| 101 | - [ ] **2A.3** Update tollgate_core.h public API if needed | ||
| 102 | - [ ] **2A.4** Replace main/session.c with thin wrapper (or remove) | ||
| 103 | - [ ] **2A.5** Update main/CMakeLists.txt | ||
| 104 | - [ ] **2A.6** idf.py build | ||
| 105 | - [ ] **2A.7** make test-unit | ||
| 106 | - [ ] **2A.8** Quick hardware verify (lock-a, flash-a, arch-test-api-quick, unlock-a) | ||
| 107 | - [ ] **2A.9** Commit + push | ||
| 108 | |||
| 109 | ### 2B: firewall module | ||
| 110 | |||
| 111 | - [ ] **2B.1** Diff main/firewall.c vs tollgate_core/src/tollgate_core_firewall.c | ||
| 112 | - [ ] **2B.2** Merge unique main/ functionality into tollgate_core | ||
| 113 | - [ ] **2B.3** Keep lwip_tollgate_hooks.h in main/ (build-system concern) | ||
| 114 | - [ ] **2B.4** main/firewall.c becomes thin wrapper calling tollgate_core_fw_* functions | ||
| 115 | - [ ] **2B.5** Verify LWIP hook still calls tollgate_core_ip4_canforward_filter | ||
| 116 | - [ ] **2B.6** Update main/CMakeLists.txt | ||
| 117 | - [ ] **2B.7** idf.py build | ||
| 118 | - [ ] **2B.8** make test-unit | ||
| 119 | - [ ] **2B.9** Quick hardware verify | ||
| 120 | - [ ] **2B.10** Commit + push | ||
| 121 | |||
| 122 | ### 2C: cashu module | ||
| 123 | |||
| 124 | - [ ] **2C.1** Diff main/cashu.c vs tollgate_core/src/tollgate_core_cashu.c | ||
| 125 | - [ ] **2C.2** Merge unique main/ functionality into tollgate_core | ||
| 126 | - [ ] **2C.3** Replace main/cashu.c with thin wrapper | ||
| 127 | - [ ] **2C.4** Update main/CMakeLists.txt | ||
| 128 | - [ ] **2C.5** idf.py build | ||
| 129 | - [ ] **2C.6** make test-unit | ||
| 130 | - [ ] **2C.7** Quick hardware verify | ||
| 131 | - [ ] **2C.8** Commit + push | ||
| 132 | |||
| 133 | ### 2D: dns_server module | ||
| 134 | |||
| 135 | - [ ] **2D.1** Diff main/dns_server.c vs tollgate_core/src/tollgate_core_dns.c | ||
| 136 | - [ ] **2D.2** Merge unique main/ functionality into tollgate_core | ||
| 137 | - [ ] **2D.3** Replace main/dns_server.c with thin wrapper | ||
| 138 | - [ ] **2D.4** Update main/CMakeLists.txt | ||
| 139 | - [ ] **2D.5** idf.py build | ||
| 140 | - [ ] **2D.6** make test-unit | ||
| 141 | - [ ] **2D.7** Quick hardware verify | ||
| 142 | - [ ] **2D.8** Commit + push | ||
| 143 | |||
| 144 | ### 2E: stratum_proxy module | ||
| 145 | |||
| 146 | - [ ] **2E.1** Diff main/stratum_proxy.c vs tollgate_core/src/tollgate_core_stratum_proxy.c | ||
| 147 | - [ ] **2E.2** Merge unique main/ functionality into tollgate_core | ||
| 148 | - [ ] **2E.3** Replace main/stratum_proxy.c with thin wrapper | ||
| 149 | - [ ] **2E.4** Update main/CMakeLists.txt | ||
| 150 | - [ ] **2E.5** idf.py build | ||
| 151 | - [ ] **2E.6** make test-unit | ||
| 152 | - [ ] **2E.7** Quick hardware verify | ||
| 153 | - [ ] **2E.8** Commit + push | ||
| 154 | |||
| 155 | ### 2F: mining_payment module | ||
| 156 | |||
| 157 | - [ ] **2F.1** Diff main/mining_payment.c vs tollgate_core/src/tollgate_core_mining.c | ||
| 158 | - [ ] **2F.2** Merge unique main/ functionality into tollgate_core | ||
| 159 | - [ ] **2F.3** Replace main/mining_payment.c with thin wrapper | ||
| 160 | - [ ] **2F.4** Update main/CMakeLists.txt | ||
| 161 | - [ ] **2F.5** idf.py build | ||
| 162 | - [ ] **2F.6** make test-unit | ||
| 163 | - [ ] **2F.7** Quick hardware verify | ||
| 164 | - [ ] **2F.8** Commit + push | ||
| 165 | |||
| 166 | ### 2G: Post-restructure verification | ||
| 167 | |||
| 168 | - [ ] **2G.1** Full hardware test (repeat Phase 1) | ||
| 169 | - [ ] **2G.2** make test-unit — all suites pass | ||
| 170 | - [ ] **2G.3** Commit + push | ||
| 171 | |||
| 172 | ## Phase 3: NerdQAxePlus Component Manager Verification | ||
| 173 | |||
| 174 | - [ ] **3.1** BOARD=NERDAXE TOLLGATE=1 idf.py build (from esp-miner-nerdqaxeplus) | ||
| 175 | - [ ] **3.2** Verify tollgate_nerdqaxe_init() links correctly | ||
| 176 | - [ ] **3.3** Commit + push (if any changes) | ||
| 177 | |||
| 178 | ## Phase 4: ESP32 ↔ OpenWRT Interop Tests | ||
| 179 | |||
| 180 | ### Setup infrastructure | ||
| 181 | |||
| 182 | - [ ] **4.1** Create esp32/interop-test.sh orchestration script | ||
| 183 | - [ ] **4.2** Add interop Make targets to esp32/Makefile (all require board lock + hardware.lock) | ||
| 184 | - [ ] **4.3** Add interop Make targets to top-level Makefile (forwarding) | ||
| 185 | - [ ] **4.4** Create tests/protocol/esp32-router-interop.spec.mjs (Playwright) | ||
| 186 | |||
| 187 | ### Direction 1: ESP32 buys from Go router | ||
| 188 | |||
| 189 | - [ ] **4.5** interop-esp32-buy-from-alpha: Board A STA → Alpha AP → discover → pay → internet | ||
| 190 | - [ ] **4.6** interop-esp32-buy-from-beta: Board A STA → Beta AP → discover → pay → internet | ||
| 191 | |||
| 192 | ### Direction 2: Go router buys from ESP32 | ||
| 193 | |||
| 194 | - [ ] **4.7** interop-alpha-buy-from-a: Alpha STA → Board A AP → discover → pay → internet | ||
| 195 | - [ ] **4.8** interop-beta-buy-from-a: Beta STA → Board A AP → discover → pay → internet | ||
| 196 | |||
| 197 | ### Bidirectional | ||
| 198 | |||
| 199 | - [ ] **4.9** interop-bidirectional-a-alpha: Both directions in sequence | ||
| 200 | - [ ] **4.10** Commit + push | ||
| 201 | |||
| 202 | ## Phase 5: Post-Restructure Full Test Suite | ||
| 203 | |||
| 204 | - [ ] **5.1** make test-unit — all suites pass | ||
| 205 | - [ ] **5.2** ESP32 full suite (all 3 boards) | ||
| 206 | - [ ] **5.3** OpenWRT full suite (both routers) | ||
| 207 | - [ ] **5.4** Playwright E2E (ESP32 captive portal + Go captive portal) | ||
| 208 | - [ ] **5.5** Interop tests (all directions) | ||
| 209 | - [ ] **5.6** Final commit + push | ||
| 210 | |||
| 211 | --- | ||
| 212 | |||
| 213 | ## LWIP Hook Integration Pattern (for Bitaxe/esp-miner repos) | ||
| 214 | |||
| 215 | The LWIP hook provides per-client (per-MAC) NAT access control. Other repos integrate it via: | ||
| 216 | |||
| 217 | 1. Add to root CMakeLists.txt: | ||
| 218 | ```cmake | ||
| 219 | idf_component_get_property(lwip lwip COMPONENT_LIB) | ||
| 220 | target_compile_options(${lwip} PRIVATE "-I${PROJECT_DIR}/main") | ||
| 221 | target_compile_definitions(${lwip} PRIVATE "-DESP_IDF_LWIP_HOOK_FILENAME=\"lwip_tollgate_hooks.h\"") | ||
| 222 | ``` | ||
| 223 | |||
| 224 | 2. Copy lwip_tollgate_hooks.h to main/ (calls tollgate_core_ip4_canforward_filter) | ||
| 225 | |||
| 226 | 3. Add tollgate_core as component dependency (override_path or git) | ||
| 227 | |||
| 228 | 4. Call from platform code: | ||
| 229 | - tollgate_core_fw_init(ap_ip) | ||
| 230 | - tollgate_core_fw_grant(client_ip) | ||
| 231 | - tollgate_core_fw_revoke(client_ip) | ||
| 232 | - tollgate_core_fw_is_allowed(client_ip) | ||
| 233 | - tollgate_core_ip4_canforward_filter(p, addr) — called by LWIP hook | ||
| 234 | |||
| 235 | ## Identity Derivation | ||
| 236 | |||
| 237 | All identifiers (SSID, MAC, IP) are derived from nsec via HMAC-SHA512: | ||
| 238 | |||
| 239 | ``` | ||
| 240 | nsec → secp256k1 → npub (Nostr public key) | ||
| 241 | nsec → HMAC-SHA512("sta-mac", 0) → STA MAC (locally administered) | ||
| 242 | nsec → HMAC-SHA512("ap-mac", 0) → AP MAC (locally administered) | ||
| 243 | AP MAC → SSID = "TollGate-{MAC[3]}{MAC[4]}{MAC[5]}" | ||
| 244 | AP MAC → IP = 10.{MAC[3]}.{(MAC[4]^MAC[5])%200+10}.1 | ||
| 245 | ``` | ||
| 246 | |||
| 247 | Rotating nsec automatically rotates all identifiers. | ||
| 248 | |||
| 249 | ## Board Configuration | ||
| 250 | |||
| 251 | | Board | nsec source | SSID | AP IP | Port | | ||
| 252 | |-------|-----------|------|-------|------| | ||
| 253 | | A | .env BOARD_A_NSEC | TollGate-B96D80 | 10.185.47.1 | /dev/ttyACM0 | | ||
| 254 | | B | .env BOARD_B_NSEC | TollGate-C0E9CA | 10.192.45.1 | /dev/ttyACM1 | | ||
| 255 | | C | .env BOARD_C_NSEC | (derived) | (derived) | /dev/ttyACM2 | | ||
| 256 | |||
| 257 | ## OpenWRT Routers | ||
| 258 | |||
| 259 | | Router | IP (LAN) | SSID (open) | API | Mint | | ||
| 260 | |--------|----------|-------------|-----|------| | ||
| 261 | | Alpha | 10.47.41.1 | TollGate-EVXZ-2.4GHz | :2121 | nofee.testnut, minibits | | ||
| 262 | | Beta | 192.168.244.1 | TollGate-24A6-2.4GHz | :2121 | testnut-compat.orangesync | | ||