1
0
Fork 0
mirror of https://github.com/imjasonh/esp32 synced 2026-07-17 06:01:41 +00:00

Provision Wi-Fi creds + trust roots via NVS instead of compile-time embed

Implements provisioning-plan.md. The OTA-distributed firmware no longer
contains any secrets or per-device config — those live in NVS and are
written via USB by `make provision` from a (gitignored)
`provisioning.toml`. Same firmware bytes can run on any device.

Firmware changes:
- src/main.rs reads wifi/ssid + wifi/pass from NVS namespace `wifi`.
  Strict-inert (sit-and-log) when missing; no compile-time fallback.
  WIFI_SSID/WIFI_PASS env! macros gone.
- src/trust.rs becomes a `TrustConfig::load(nvs)` loader. Identities
  come from NVS namespace `trust`, key `identities` (JSON-encoded
  array). Sigstore root + intermediate PEMs come from `trust/fulcio_root`
  and `trust/fulcio_inter` blobs. include_str! gone.
- src/sig.rs and src/ota.rs thread &TrustConfig through verify_bundle
  and the OTA loop instead of reading global consts.
- build.rs no longer tracks WIFI_* env changes.

New tool:
- tools/provision/ host-side cargo crate. Reads provisioning.toml,
  emits an NVS CSV, shells out to ESP-IDF's nvs_partition_gen.py to
  produce a binary NVS image, optionally `espflash write-bin`'s it.

Make targets:
- `make provision` — build NVS image + flash it.
- `make bootstrap` — flash-all + provision (new device setup).
- `make build` no longer requires wifi.env.
- wifi.env removed from prereqs / WIFI_ENV variable removed.

Workflows:
- ci.yml: drops the placeholder wifi.env step, adds a `build provision`
  job alongside the firmware + publisher jobs.
- publish.yml: drops WIFI_SSID/WIFI_PASS secret reads. Only secret
  needed is the auto-injected GITHUB_TOKEN.

Docs:
- README updated to use `make bootstrap` + `make provision` flow.
  Project layout moved to a new repo-local CLAUDE.md.
- provisioning.toml.example committed as the template the user copies.
- wifi.env.example removed (no longer used).

Migration: existing devices need `make bootstrap` over USB. The new
firmware has no embedded creds; OTAing to it without provisioning
would just sit in strict-inert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jason Hall 2026-05-02 16:14:26 -04:00
parent 89a80d7ba3
commit 1928dcfd47
18 changed files with 1402 additions and 150 deletions

View file

@ -54,18 +54,10 @@ jobs:
with:
shared-key: ci-firmware
- name: Write placeholder wifi.env
# The firmware embeds WIFI_SSID/WIFI_PASS at compile time via
# env!() but doesn't validate them. CI just needs the build to
# succeed; runtime Wi-Fi connect with these placeholders would
# fail, but that's not what CI is testing.
run: |
{
echo 'export WIFI_SSID="ci-placeholder"'
echo 'export WIFI_PASS="ci-placeholder"'
} > wifi.env
- name: Build firmware
# No wifi.env needed — the firmware reads Wi-Fi creds from NVS
# at runtime, not from env!() at compile time. The published
# OCI image is device-agnostic.
run: make build
publisher:
@ -85,3 +77,18 @@ jobs:
# `target = "xtensa-esp32-espidf"`. Hardcoded triple is fine
# because we control the runner (ubuntu-latest = x86_64-linux).
run: cd tools/publisher && cargo build --release --target x86_64-unknown-linux-gnu
provision:
name: build provision
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- uses: Swatinem/rust-cache@v2
with:
workspaces: tools/provision
shared-key: ci-provision
- name: Build provision
run: cd tools/provision && cargo build --release --target x86_64-unknown-linux-gnu