diff options
Diffstat (limited to 'ROADMAP.md')
| -rw-r--r-- | ROADMAP.md | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..b4fe16b --- /dev/null +++ b/ROADMAP.md | |||
| @@ -0,0 +1,262 @@ | |||
| 1 | # TollGate Core Extraction Roadmap | ||
| 2 | |||
| 3 | **Branch:** `feature/tollgate-core-v2` | ||
| 4 | **Start commit:** `851801f` (Phase 5 complete, hardware-verified) | ||
| 5 | **Goal:** Extract all portable TollGate business logic into `components/tollgate_core/` for reuse in NerdQAxePlus and other ESP32 firmware. | ||
| 6 | |||
| 7 | ## Testing Protocol | ||
| 8 | |||
| 9 | After **every** step: | ||
| 10 | |||
| 11 | 1. `make test-unit` -- all 21+ unit tests must pass | ||
| 12 | 2. `idf.py build` -- ESP-IDF build must succeed | ||
| 13 | 3. After multi-step phases: flash Board A + `pytest tests/test_smoke.py --board=a` | ||
| 14 | |||
| 15 | --- | ||
| 16 | |||
| 17 | ## Phase 6: Consolidate & Clean Up | ||
| 18 | |||
| 19 | ### 6a. Delete standalone `tollgate_core/` | ||
| 20 | |||
| 21 | Dead code -- nothing in the build references it. The component version is what's compiled. | ||
| 22 | |||
| 23 | - [ ] `git rm -r tollgate_core/` | ||
| 24 | - [ ] Verify nothing references it: `grep -r "tollgate_core/" main/ components/ tests/` | ||
| 25 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 26 | |||
| 27 | ### 6b. Eliminate `dns_server.c` duplication | ||
| 28 | |||
| 29 | `main/dns_server.c` (316 lines) duplicates `components/tollgate_core/src/tollgate_core_dns.c`. | ||
| 30 | |||
| 31 | - [ ] Rewrite `main/dns_server.c` as thin shim: `dns_server_*()` calls `tollgate_core_dns_*()` | ||
| 32 | - [ ] Update `main/dns_server.h` to keep original function signatures | ||
| 33 | - [ ] Move `dns_server_set_client_authenticated()` notification to component's internal DNS | ||
| 34 | - [ ] Add unit test for DNS shim if not covered by existing `test_firewall_sandbox` | ||
| 35 | - [ ] Test: `make test-unit` + `idf.py build` + flash + pytest smoke | ||
| 36 | |||
| 37 | ### 6c. Eliminate `stratum_proxy.c` duplication | ||
| 38 | |||
| 39 | `main/stratum_proxy.c` (160 lines) duplicates `components/tollgate_core/src/tollgate_core_stratum_proxy.c`. | ||
| 40 | |||
| 41 | - [ ] Rewrite `main/stratum_proxy.c` as thin shim: `stratum_proxy_*()` -> `tollgate_core_stratum_proxy_*()` | ||
| 42 | - [ ] Update `main/stratum_proxy.h` to keep original type names for backward compat | ||
| 43 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 44 | |||
| 45 | ### 6d. Move sandbox logic into component firewall | ||
| 46 | |||
| 47 | `main/firewall.c` has `is_sandbox_allowed()` (allows TCP to ports 80/2121/mining_port for unauth clients) -- missing from component. | ||
| 48 | |||
| 49 | - [ ] Add `tollgate_core_fw_set_sandbox_ports()` to component's firewall API | ||
| 50 | - [ ] Add `tollgate_core_fw_is_sandbox_allowed()` to component's internal firewall | ||
| 51 | - [ ] Update component's `tollgate_core_ip4_canforward_filter` to check sandbox rules | ||
| 52 | - [ ] Update `main/firewall.c` shim to call `tollgate_core_fw_set_sandbox_ports()` in init | ||
| 53 | - [ ] Add unit test for sandbox logic with known port combinations | ||
| 54 | - [ ] Test: `make test-unit` + `idf.py build` + flash + `pytest tests/test_dns_firewall.py --board=a` | ||
| 55 | |||
| 56 | ### 6e. Break `mint_health` <-> `tollgate_api` circular dependency | ||
| 57 | |||
| 58 | `mint_health.c` includes `tollgate_api.h` for `tls_worker_set_queue()`. `tollgate_api.c` includes `mint_health.h` for `mint_health_get_all()`. | ||
| 59 | |||
| 60 | - [ ] Extract `QueueHandle_t tls_worker_queue` into a shared module (e.g., `tls_worker.h/c`) | ||
| 61 | - [ ] `mint_health.c` includes `tls_worker.h` instead of `tollgate_api.h` | ||
| 62 | - [ ] `tollgate_api.c` includes `tls_worker.h` to get the queue | ||
| 63 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 64 | |||
| 65 | ### 6f. Break `config.h` -> `lightning_payout.h` reverse dependency | ||
| 66 | |||
| 67 | `config.h` includes `lightning_payout.h` for `payout_config_t` type. | ||
| 68 | |||
| 69 | - [ ] Move `payout_config_t` typedef to `config.h` (or a shared `tollgate_types.h`) | ||
| 70 | - [ ] Remove `#include "lightning_payout.h"` from `config.h` | ||
| 71 | - [ ] Add `#include "config.h"` to `lightning_payout.c` if needed | ||
| 72 | - [ ] Test: `make test-unit` + `idf.py build` + **commit + push** | ||
| 73 | |||
| 74 | --- | ||
| 75 | |||
| 76 | ## Phase 7: Eliminate Shim Files | ||
| 77 | |||
| 78 | Remove thin wrappers. Consumers use component headers directly. | ||
| 79 | |||
| 80 | ### 7a. Remove `session.c` / `session.h` shim | ||
| 81 | |||
| 82 | - [ ] Update `tollgate_api.c`: `#include "tollgate_core_session.h"` instead of `#include "session.h"` | ||
| 83 | - [ ] Update `captive_portal.c`: same | ||
| 84 | - [ ] Update any other consumers of `session.h` | ||
| 85 | - [ ] Delete `main/session.c` and `main/session.h` | ||
| 86 | - [ ] Remove from `main/CMakeLists.txt` SRCS | ||
| 87 | - [ ] Update unit test Makefile if needed | ||
| 88 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 89 | |||
| 90 | ### 7b. Remove `cashu.c` / `cashu.h` shim | ||
| 91 | |||
| 92 | - [ ] Update `tollgate_api.c`: `#include "tollgate_core_cashu.h"` instead of `#include "cashu.h"` | ||
| 93 | - [ ] Move multi-mint logic (iterating `accepted_mints[]`) into component's `tollgate_core_cashu_is_mint_accepted()` | ||
| 94 | - [ ] Delete `main/cashu.c` and `main/cashu.h` | ||
| 95 | - [ ] Remove from `main/CMakeLists.txt` SRCS | ||
| 96 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 97 | |||
| 98 | ### 7c. Remove `mining_payment.c` / `mining_payment.h` shim | ||
| 99 | |||
| 100 | - [ ] Update all consumers: `#include "tollgate_core_mining.h"` instead of `#include "mining_payment.h"` | ||
| 101 | - [ ] Delete `main/mining_payment.c` and `main/mining_payment.h` | ||
| 102 | - [ ] Remove from `main/CMakeLists.txt` SRCS | ||
| 103 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 104 | |||
| 105 | ### 7d. Remove `firewall.c` / `firewall.h` shim | ||
| 106 | |||
| 107 | After 6d, firewall shim only has lwIP hook registration + DNS notification. | ||
| 108 | |||
| 109 | - [ ] Move lwIP hook registration into `tollgate_main.c` or a new `main/esp_hooks.c` | ||
| 110 | - [ ] Update consumers to use `tollgate_core_fw_*()` directly | ||
| 111 | - [ ] Delete `main/firewall.c` and `main/firewall.h` | ||
| 112 | - [ ] Remove from `main/CMakeLists.txt` SRCS | ||
| 113 | - [ ] Test: `make test-unit` + `idf.py build` + flash + pytest smoke + DNS/firewall tests | ||
| 114 | - [ ] **Commit + push** | ||
| 115 | |||
| 116 | --- | ||
| 117 | |||
| 118 | ## Phase 8: Extract Layer 1 into Component | ||
| 119 | |||
| 120 | ### 8a. Extract `beacon_price.c` -> `tollgate_core_beacon.c` | ||
| 121 | |||
| 122 | Dependencies: `config`, `identity`, `esp_wifi`, `mbedtls/sha256` | ||
| 123 | |||
| 124 | - [ ] Create `components/tollgate_core/src/tollgate_core_beacon.c/h` | ||
| 125 | - [ ] Abstract WiFi vendor IE API via `tollgate_platform_t` callbacks: `set_vendor_ie()`, `scan_start()` | ||
| 126 | - [ ] Move mint URL + npub hashing, geohash embedding, IE construction to component | ||
| 127 | - [ ] Rewrite `main/beacon_price.c` as thin ESP-specific glue calling component | ||
| 128 | - [ ] Add unit test with known IE vectors | ||
| 129 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 130 | |||
| 131 | ### 8b. Extract `market.c` -> `tollgate_core_market.c` | ||
| 132 | |||
| 133 | Dependencies: `beacon_price`, `config`, `identity`, `esp_wifi` | ||
| 134 | |||
| 135 | - [ ] Create `components/tollgate_core/src/tollgate_core_market.c/h` | ||
| 136 | - [ ] Abstract WiFi scan results via platform callback: `on_scan_result()` | ||
| 137 | - [ ] Move market entry table, price comparison, cheapest selection to component | ||
| 138 | - [ ] Rewrite `main/market.c` as thin glue | ||
| 139 | - [ ] Add unit test for market table operations | ||
| 140 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 141 | |||
| 142 | ### 8c. Extract `captive_portal.c` -> `tollgate_core_portal.c` | ||
| 143 | |||
| 144 | Dependencies: `firewall`, `session`, `config`, `mining_payment`, `stratum_proxy`, `esp_http_server` | ||
| 145 | |||
| 146 | - [ ] Create `components/tollgate_core/src/tollgate_core_portal.c/h` | ||
| 147 | - [ ] Extract template rendering logic (HTML generation, `__AP_IP__`/`__PRICE__` substitution) | ||
| 148 | - [ ] Extract captive detection URI handling (generate_204, hotspot-detect, success.txt, etc.) | ||
| 149 | - [ ] Extract payment processing flow (POST token -> decode -> validate -> grant) | ||
| 150 | - [ ] Abstract HTTP server via platform callbacks: `httpd_start()`, `register_handler()`, `send_response()` | ||
| 151 | - [ ] Keep ESP `httpd` glue in `main/captive_portal.c` (thin handler registration) | ||
| 152 | - [ ] Add unit test for template substitution + captive URI detection | ||
| 153 | - [ ] Test: `make test-unit` + `idf.py build` + flash + pytest portal tests | ||
| 154 | |||
| 155 | ### 8d. Extract `stratum_client.c` -> `tollgate_core_stratum_client.c` | ||
| 156 | |||
| 157 | Dependencies: `stratum_proxy`, `mining_payment`, `config`, `esp_transport` | ||
| 158 | |||
| 159 | - [ ] Create `components/tollgate_core/src/tollgate_core_stratum_client.c/h` | ||
| 160 | - [ ] Abstract TCP transport via platform callbacks | ||
| 161 | - [ ] Move Stratum V1 protocol logic (subscribe, authorize, handle mining.notify, submit share) | ||
| 162 | - [ ] Rewrite `main/stratum_client.c` as thin glue | ||
| 163 | - [ ] Add unit test for Stratum message parsing | ||
| 164 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 165 | |||
| 166 | ### 8e. Extract `mint_health.c` -> `tollgate_core_mint_health.c` | ||
| 167 | |||
| 168 | Dependencies: `tls_worker` (after 6e), `nucula_wallet`, `esp_http_client` | ||
| 169 | |||
| 170 | - [ ] Create `components/tollgate_core/src/tollgate_core_mint_health.c/h` | ||
| 171 | - [ ] Abstract HTTP client via platform callback: `http_get()`, `tls_worker_queue` | ||
| 172 | - [ ] Move mint probing logic, health state tracking, reachable/unreachable marking | ||
| 173 | - [ ] Rewrite `main/mint_health.c` as thin glue | ||
| 174 | - [ ] Add unit test for health state machine | ||
| 175 | - [ ] Test: `make test-unit` + `idf.py build` | ||
| 176 | |||
| 177 | ### 8f. Extract `tollgate_client.c` -> `tollgate_core_client.c` | ||
| 178 | |||
| 179 | Dependencies: `config`, `market`, `nucula_wallet`, `esp_http_client` | ||
| 180 | |||
| 181 | - [ ] Create `components/tollgate_core/src/tollgate_core_client.c/h` | ||
| 182 | - [ ] Abstract HTTP + wallet via platform callbacks | ||
| 183 | - [ ] Move upstream TollGate discovery, auto-pay, usage tracking, auto-renew logic | ||
| 184 | - [ ] Rewrite `main/tollgate_client.c` as thin glue | ||
| 185 | - [ ] Add unit test for client state machine (already exists: `test_tollgate_client.c`) | ||
| 186 | - [ ] Test: `make test-unit` + `idf.py build` + flash + full pytest suite | ||
| 187 | - [ ] **Commit + push** | ||
| 188 | |||
| 189 | --- | ||
| 190 | |||
| 191 | ## Phase 9: NerdQAxePlus Integration | ||
| 192 | |||
| 193 | ### 9a. Restore miner-integration worktree | ||
| 194 | |||
| 195 | - [ ] `git worktree add /home/c03rad0r/esp32-miner-integration feature/miner-integration` | ||
| 196 | - [ ] Or create fresh from `remotes/orangesync/feature/miner-integration` | ||
| 197 | - [ ] Verify NerdQAxePlus fork at `/home/c03rad0r/esp-miner-nerdqaxeplus/` is intact | ||
| 198 | |||
| 199 | ### 9b. Copy finalized `tollgate_core` component | ||
| 200 | |||
| 201 | - [ ] Sync `components/tollgate_core/` from esp32-tollgate -> NerdQAxePlus `components/tollgate_core/` | ||
| 202 | - [ ] Update NerdQAxePlus `CMakeLists.txt` to depend on `tollgate_core` | ||
| 203 | - [ ] Verify `BOARD=NERDAXE TOLLGATE=1 idf.py build` succeeds | ||
| 204 | |||
| 205 | ### 9c. Implement `tollgate_platform_t` for BitAxe/BM1397 | ||
| 206 | |||
| 207 | - [ ] Create `components/tollgate_baxe/` with BitAxe-specific platform implementation | ||
| 208 | - [ ] Implement callbacks: `get_price_sats()`, `get_mint_url()`, `spend_proofs()`, stratum config | ||
| 209 | - [ ] Wire BM1397 ASIC -> stratum proxy -> tollgate_core mining pipeline | ||
| 210 | - [ ] Wire eCash payment -> session -> internet access on BitAxe AP | ||
| 211 | |||
| 212 | ### 9d. Integrate into NerdQAxePlus UI | ||
| 213 | |||
| 214 | - [ ] Add payment status to OLED/LCD display | ||
| 215 | - [ ] Add WiFi AP setup with SSID derived from identity | ||
| 216 | - [ ] Add Cashu token input via web portal | ||
| 217 | - [ ] Test: Flash NerdAxe Ultra + mining test + payment test + internet verification | ||
| 218 | - [ ] **Commit + push** | ||
| 219 | |||
| 220 | --- | ||
| 221 | |||
| 222 | ## Phase 10: Publish | ||
| 223 | |||
| 224 | ### 10a. Component metadata | ||
| 225 | |||
| 226 | - [ ] Update `idf_component.yml` with proper version, description, dependencies | ||
| 227 | - [ ] Add `README.md` to `components/tollgate_core/` with API docs | ||
| 228 | - [ ] Add `CHANGELOG.md` to component | ||
| 229 | |||
| 230 | ### 10b. CI pipeline | ||
| 231 | |||
| 232 | - [ ] GitHub Actions or self-hosted CI: build on push, run unit tests | ||
| 233 | - [ ] Hardware-in-the-loop testing on push to develop (Board A) | ||
| 234 | - [ ] Integration test matrix: Board A + Board B + Board C | ||
| 235 | |||
| 236 | ### 10c. Publish to IDF Component Registry | ||
| 237 | |||
| 238 | - [ ] `compote component upload` to ESP-IDF Component Registry | ||
| 239 | - [ ] Verify `idf.py add-dependency` works from a clean project | ||
| 240 | - [ ] Document usage in top-level README | ||
| 241 | |||
| 242 | --- | ||
| 243 | |||
| 244 | ## Dependency Graph (Extraction Order) | ||
| 245 | |||
| 246 | ``` | ||
| 247 | Layer 0: dns_server, lnurl_pay, asic_miner (no main/ deps) | ||
| 248 | Layer 1: config, identity, session, cashu, mining (foundation) | ||
| 249 | Layer 2: firewall, beacon_price, lightning_payout (depends on Layer 1) | ||
| 250 | Layer 3: market, stratum_proxy, stratum_client (depends on Layer 2) | ||
| 251 | Layer 4: captive_portal, tollgate_client, mint_health (depends on Layer 3) | ||
| 252 | Layer 5: tollgate_api (depends on everything) | ||
| 253 | ``` | ||
| 254 | |||
| 255 | ## Current Test Coverage | ||
| 256 | |||
| 257 | | Type | Count | Command | | ||
| 258 | |------|-------|---------| | ||
| 259 | | Host unit tests | 21 | `make test-unit` | | ||
| 260 | | Integration tests | 17 | `TOLLGATE_IP=x make test-integration` | | ||
| 261 | | E2E tests | 3 suites | `make test-e2e` | | ||
| 262 | | Pytest (hardware) | 12 files | `pytest tests/ --board=a` | | ||