Verify the sim/header-side half of the tokenless-sim REJECT root cause
against current source (second link of the bf-34lwt split). Three facts
re-checked against current source:
- Sim supplies its token ONLY as the X-Spaxel-Token HTTP header on the
WS dial — cmd/sim/main.go:313, mothership/cmd/sim/main.go:633,
mothership/cmd/sim/scenario.go:318 (all three connect paths).
- The hello JSON map the sim sends has NO token field —
cmd/sim/main.go:348-359, mothership/cmd/sim/main.go:652-665,
mothership/cmd/sim/scenario.go:331-342. Only "--token" hits are CLI
flag defs, never a JSON body key.
- The mothership NEVER reads that header on the WS path —
grep 'X-Spaxel-Token' mothership/ excluding _test.go and cmd/sim/
returns zero hits. HandleNodeWS (server.go:455-469) passes r straight
to Upgrade; the only Header ref on the path is the outbound
w.Header().Set response header.
Conclusion: header ignored -> hello.Token (message.go:22) empty ->
tokenOK (server.go:513) always false. The "have the sim supply valid
tokens" option is currently DEAD. Companion to bf-5ig3e (validator half);
both roll up into bf-34lwt.
Co-Authored-By: Claude <noreply@anthropic.com>
Bead-Id: bf-29wyl
Verify the validator-side half of the tokenless-sim REJECT root cause
against current source (first link of the bf-34lwt split):
- mothership/cmd/mothership/main.go:4494 — SetTokenValidator(...) is a
bare statement with no env/build guard; provSrv is created
unconditionally at :4492. 'validator configured?' is always YES.
- mothership/internal/ingestion/server.go:513 — tokenOK :=
hello.Token != "" && validator(hello.MAC, hello.Token) depends
solely on the deserialized hello JSON body field (message.go:22),
not any HTTP header. No X-Spaxel-Token read exists on this path.
Conclusion: validator always configured; accept/reject hinges entirely
on hello.Token.
Co-Authored-By: Claude <noreply@anthropic.com>
Definitive root-cause for the bf-4iewr split's first child. Confirms
against current source (with file:line citations) that:
- The token validator is wired UNCONDITIONALLY (main.go:4494)
- It reads hello.Token only (server.go:513); the sim never populates it
- The sim sends its token only as the X-Spaxel-Token header (cmd/sim
main.go:633/scenario.go:318), and the mothership never reads that
header (HandleNodeWS upgrades unconditionally at server.go:469) -> the
token-supply path is currently DEAD
- The default 24h migration window (config.go:139) is the only thing
accepting sim nodes -> current 'no reject' is a window MASK, not a fix
- REJECT fires only when the window closes (SPAXEL_MIGRATION_WINDOW_HOURS=0
or uptime > 24h)
Corroborated by the e2e harness comment (tests/e2e/e2e_test.go:86-94)
which pins the window open and documents exactly this.
Co-Authored-By: Claude <noreply@anthropic.com>
Appendix A to ci-test-sim-reference-map.md: line-by-line path inventory
of the spaxel-build WorkflowTemplate. Every Go step runs with cwd=mothership,
so ./cmd/sim (L385), ./cmd/mothership (L392), and ./test/acceptance/ (L400)
all resolve under the mothership module. Confirms the template references
none of: root cmd/sim, root test/acceptance, tests/e2e/run.sh, or
mothership/tests/e2e/e2e_test.go (the latter only transitively compile-
covered by go test ./...).
Co-Authored-By: Claude <noreply@anthropic.com>
Decision spike for the firmware/test/ host harness (split of bf-4ne).
Records why the ESP-IDF --target linux / Unity-host path was rejected:
csi.c is blocked by esp_wifi.h and provision.c by driver/uart.h, and
firmware/main builds as one component whose REQUIRES line names
esp_wifi/bt/driver — none of which have a linux build. Falls back to a
plain gcc harness under firmware/test/ that does not link main/*.c.
Reason must be carried into bf-4ne's test-runner header comment.
Co-Authored-By: Claude <noreply@anthropic.com>
Add optional mothership IP override to the provisioning flow so nodes
on networks where mDNS is blocked (enterprise WiFi, mesh, VLANs) can
connect on first boot without manual intervention.
- Add ms_ip field to provisioning Payload and request structs
- Firmware writes ms_ip to both NVS_KEY_MS_IP and NVS_KEY_MS_IP_PROV
- Discovery prefers provisioned IP on first attempt, falls back to
mDNS, then cached IP
- Web Serial wizard adds Mothership IP field in Network Troubleshooting
- Auto-populates IP when browser accesses dashboard by IP address
- Document when/how to use the override in docs/notes/mdns-override.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>