upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AGENTS.md3
-rw-r--r--CHECKLIST.md11
-rw-r--r--PLAN.md53
-rw-r--r--main/cvm_server.c21
4 files changed, 59 insertions, 29 deletions
diff --git a/AGENTS.md b/AGENTS.md
index d7d2cfe..368fd83 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -204,5 +204,8 @@ make flash-b # flash to Board B
204- Wifistr event signing uses `secp256k1_schnorrsig_sign32()` — verify with `_verify()` in tests 204- Wifistr event signing uses `secp256k1_schnorrsig_sign32()` — verify with `_verify()` in tests
205- Portal HTML has server-side template substitution (`__AP_IP__`, `__PRICE__`, `__MINT_URL__`) — no JS fetch 205- Portal HTML has server-side template substitution (`__AP_IP__`, `__PRICE__`, `__MINT_URL__`) — no JS fetch
206- **WiFi country code:** Must set `esp_wifi_set_country_code("DE")` before `esp_wifi_start()` — defaults to CN which causes auth failures on EU APs 206- **WiFi country code:** Must set `esp_wifi_set_country_code("DE")` before `esp_wifi_start()` — defaults to CN which causes auth failures on EU APs
207- **Board A WiFi is broken** — hardware issue confirmed: `WIFI_REASON_AUTH_EXPIRED` on all APs in all modes (APSTA, STA-only, factory MAC). Board B with identical firmware connects instantly. Do not waste time debugging Board A WiFi.
207- Default nsec: `a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2` 208- Default nsec: `a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2`
208- Board A nsec: `9af47906b45aca5e238390f3d03c8274e154198e81aa2095065627d1e61ca968` 209- Board A nsec: `9af47906b45aca5e238390f3d03c8274e154198e81aa2095065627d1e61ca968`
210- CVM relay: `relay.primal.net` — relay disconnects every ~15s by default, now has 60s timeout + WS ping/pong keepalive
211- MCP responses sent via existing WS connection (not new TLS) — ESP32 can't handle multiple simultaneous TLS sessions
diff --git a/CHECKLIST.md b/CHECKLIST.md
index b0a842c..7fcc4b7 100644
--- a/CHECKLIST.md
+++ b/CHECKLIST.md
@@ -98,10 +98,15 @@
98- [x] MCP initialize roundtrip via kind 25910 — PASS 98- [x] MCP initialize roundtrip via kind 25910 — PASS
99- [x] tools/call get_config via kind 25910 — PASS 99- [x] tools/call get_config via kind 25910 — PASS
100- [x] tools/call get_balance via kind 25910 — PASS 100- [x] tools/call get_balance via kind 25910 — PASS
101- [ ] tools/call set_price via kind 25910 101- [x] tools/list response via kind 25910 — PASS
102- [ ] End-to-end CVM test: full initialize → tools/list → tools/call sequence 102- [x] tools/call set_price via kind 25910 — PASS (price updated to 42)
103- [ ] End-to-end MCP tools/call roundtrip via kind 25910 103- [ ] tools/call get_sessions via kind 25910
104- [ ] tools/call get_usage via kind 25910
105- [ ] Non-owner auth rejection via live relay (unit test only so far)
104- [ ] Verify board npub on contextvm.org/servers 106- [ ] Verify board npub on contextvm.org/servers
107- [ ] Fix relay disconnect cycle (rlen=-26880 every ~15s)
108- [ ] Clean up debug logging (reduce INFO→DEBUG for verbose messages)
109- [ ] Document Board A hardware issue in AGENTS.md
105 110
106### WiFi Debugging Findings (Board A — 94:a9:90:2e:37:7c) 111### WiFi Debugging Findings (Board A — 94:a9:90:2e:37:7c)
107- **Symptom:** `WIFI_REASON_AUTH_EXPIRED` (0x200) on all upstream APs 112- **Symptom:** `WIFI_REASON_AUTH_EXPIRED` (0x200) on all upstream APs
diff --git a/PLAN.md b/PLAN.md
index 0be2355..9f286a9 100644
--- a/PLAN.md
+++ b/PLAN.md
@@ -575,31 +575,38 @@ Only accept kind 25910 requests from owner npub (derived from nsec in config.jso
575| 66 | MCP initialize roundtrip | Integration | Response received via nak | PASS | 575| 66 | MCP initialize roundtrip | Integration | Response received via nak | PASS |
576| 67 | get_config via CVM | Integration | Returns valid JSON config | PASS | 576| 67 | get_config via CVM | Integration | Returns valid JSON config | PASS |
577| 68 | get_balance via CVM | Integration | Returns balance + proofs | PASS | 577| 68 | get_balance via CVM | Integration | Returns balance + proofs | PASS |
578| 69 | set_price via CVM | Integration | Price updated on device | TODO | 578| 69 | set_price via CVM | Integration | Price updated on device | PASS |
579| 70 | Kind 11317 on relay | Integration | Tools list found on relay | PASS* | 579| 70 | Kind 11317 on relay | Integration | Tools list found on relay | PASS |
580| 71 | Kind 10002 on relay | Integration | Relay list found on relay | PASS* | 580| 71 | Kind 10002 on relay | Integration | Relay list found on relay | PASS |
581| 72 | API reachability from host | Integration | HTTP 200 from board AP | PASS | 581| 72 | API reachability from host | Integration | HTTP 200 from board AP | PASS |
582| 73 | CVM event publish from host | Integration | Kind 25910 published to relay | PASS | 582| 73 | CVM event publish from host | Integration | Kind 25910 published to relay | PASS |
583 583| 74 | tools/list via CVM | Integration | All 10 tools listed | PASS |
584*Passes when board has upstream WiFi and SNTP is synced. Events expire without valid `created_at` timestamp. 584| 75 | get_sessions via CVM | Integration | Returns session array | TODO |
585 585| 76 | get_usage via CVM | Integration | Returns usage stats | TODO |
586#### WiFi Country Code Fix (Critical) 586| 77 | Non-owner rejection (live) | Integration | Unauthorized event ignored | TODO |
587 587| 78 | Relay reconnect resilience | Integration | Board reconnects after disconnect | PASS |
588**Problem:** ESP-IDF defaults to CN (China) regulatory domain when no country code is set. The boards are in DE (Germany/EU). Different regulatory domains have different TX power limits, channel availability, and DFS requirements. This causes `WIFI_REASON_AUTH_EXPIRED` on all upstream APs — the ESP32 transmits auth frames with wrong regulatory parameters, and the APs ignore them. 588
589 589## Total: 85 Tests across 8 phases
590**Fix:** Add `esp_wifi_set_country_code("DE", false)` before `esp_wifi_start()` in `tollgate_main.c`. 590
591 591## Merge Readiness Checklist
592**Evidence:** 592
593- Auth fails even in STA-only mode (no AP at all), ruling out APSTA channel conflicts 593### Code Quality
594- Auth fails against a laptop hotspot 1m away, ruling out signal strength 594- [ ] Fix relay disconnect cycle (rlen=-26880 every ~15s, WS read has no timeout)
595- Auth fails with factory MAC, ruling out MAC filtering 595- [ ] Clean up debug logging (Sending WS response, WS send result → DEBUG level)
596- Auth fails with PMF enabled, WPA2 threshold, all-channel scan 596- [ ] Document Board A hardware WiFi issue in AGENTS.md
597- Laptop connects to same APs at 100% signal — ESP32 radio is the outlier 597
598- Dense 2.4GHz spectrum (ch1: 2 APs, ch6: 4 APs, ch11: 4 APs) but not exhausted 598### Integration Testing (needs Board B + relay.primal.net)
599 599- [ ] tools/list response via kind 25910
600**Alternative hypothesis:** Hardware antenna issue on Board A. Need to test Board B/C to confirm. 600- [ ] tools/call set_price via kind 25910
601 601- [ ] tools/call get_sessions via kind 25910
602## Total: 81 Tests across 8 phases 602- [ ] tools/call get_usage via kind 25910
603- [ ] Non-owner auth rejection via live relay
604- [ ] Verify board npub on contextvm.org/servers
605
606### Pre-merge
607- [ ] `make test-unit` — all 282 unit tests pass
608- [ ] Rebase feature/cvm-integration onto master (1 commit behind)
609- [ ] Verify no conflicts with feature branches (display-fix, multi-mint, price-discovery)
603 610
604## Post-Phase 7: Bug Fixes & Architecture Improvements 611## Post-Phase 7: Bug Fixes & Architecture Improvements
605 612
diff --git a/main/cvm_server.c b/main/cvm_server.c
index 96ce7d3..b93e176 100644
--- a/main/cvm_server.c
+++ b/main/cvm_server.c
@@ -11,6 +11,7 @@
11#include "esp_tls.h" 11#include "esp_tls.h"
12#include "esp_crt_bundle.h" 12#include "esp_crt_bundle.h"
13#include "esp_random.h" 13#include "esp_random.h"
14#include "esp_timer.h"
14#include "freertos/FreeRTOS.h" 15#include "freertos/FreeRTOS.h"
15#include "freertos/task.h" 16#include "freertos/task.h"
16#include <string.h> 17#include <string.h>
@@ -30,6 +31,8 @@ static void publish_announcements_via_ws(esp_tls_t *tls);
30#define CVM_WS_BUF_SIZE 8192 31#define CVM_WS_BUF_SIZE 8192
31#define CVM_MAX_RESPONSE_SIZE 4096 32#define CVM_MAX_RESPONSE_SIZE 4096
32#define CVM_RECONNECT_DELAY_MS 5000 33#define CVM_RECONNECT_DELAY_MS 5000
34#define CVM_WS_READ_TIMEOUT_MS 60000
35#define CVM_WS_PING_INTERVAL_S 30
33 36
34static char *parse_ws_text_frame(const uint8_t *buf, int len) 37static char *parse_ws_text_frame(const uint8_t *buf, int len)
35{ 38{
@@ -148,7 +151,7 @@ static esp_err_t ws_connect(const char *relay_url, esp_tls_t **tls_out)
148 151
149 esp_tls_cfg_t tls_cfg = { 152 esp_tls_cfg_t tls_cfg = {
150 .crt_bundle_attach = esp_crt_bundle_attach, 153 .crt_bundle_attach = esp_crt_bundle_attach,
151 .timeout_ms = 15000, 154 .timeout_ms = CVM_WS_READ_TIMEOUT_MS,
152 }; 155 };
153 esp_tls_t *tls = esp_tls_init(); 156 esp_tls_t *tls = esp_tls_init();
154 if (!tls) return ESP_ERR_NO_MEM; 157 if (!tls) return ESP_ERR_NO_MEM;
@@ -363,9 +366,9 @@ static esp_err_t publish_kind_25910_response_ws(esp_tls_t *tls,
363 return ESP_ERR_NO_MEM; 366 return ESP_ERR_NO_MEM;
364 } 367 }
365 snprintf(msg, msg_len, "[\"EVENT\",%s]", event_json); 368 snprintf(msg, msg_len, "[\"EVENT\",%s]", event_json);
366 ESP_LOGI(TAG, "Sending WS response (%d bytes)", (int)strlen(msg)); 369 ESP_LOGD(TAG, "Sending WS response (%d bytes)", (int)strlen(msg));
367 int rc = ws_send_text(tls, msg); 370 int rc = ws_send_text(tls, msg);
368 ESP_LOGI(TAG, "WS send result: %d", rc); 371 ESP_LOGD(TAG, "WS send result: %d", rc);
369 free(msg); 372 free(msg);
370 free(event_json); 373 free(event_json);
371 return ESP_OK; 374 return ESP_OK;
@@ -613,6 +616,8 @@ static void cvm_relay_task(void *arg)
613 return; 616 return;
614 } 617 }
615 618
619 int64_t last_ping_time = 0;
620
616 while (g_running) { 621 while (g_running) {
617 int rlen = esp_tls_conn_read(tls, buf, CVM_WS_BUF_SIZE - 1); 622 int rlen = esp_tls_conn_read(tls, buf, CVM_WS_BUF_SIZE - 1);
618 if (rlen < 0) { 623 if (rlen < 0) {
@@ -631,6 +636,16 @@ static void cvm_relay_task(void *arg)
631 } 636 }
632 free(text); 637 free(text);
633 } 638 }
639 } else if ((buf[0] & 0x0F) == 0x09) {
640 uint8_t pong[2] = {0x8A, 0x00};
641 esp_tls_conn_write(tls, pong, 2);
642 }
643
644 int64_t now = (int64_t)esp_timer_get_time() / 1000000;
645 if (now - last_ping_time >= CVM_WS_PING_INTERVAL_S) {
646 uint8_t ping[2] = {0x89, 0x00};
647 esp_tls_conn_write(tls, ping, 2);
648 last_ping_time = now;
634 } 649 }
635 } 650 }
636 651