Project overview lives in README.md: custom ESPHome firmware + external component for Levoit air purifiers. Per-device YAML under devices/<device>/.
Based on /opt/autocoder/CREDENTIAL_CONVENTIONS_TEMPLATE.md (canonical), adapted for this repo.
Each flashable device has its own devices/<device>/secrets.yaml holding wifi_ssid, wifi_password, wifi_ap_password, ota_password, and api_key. These files are per-device, gitignored, and must be mode 0600 (each devices/<device>/ directory has its own .gitignore containing /secrets.yaml; the root .gitignore covers secret.yaml and components/secrets.yaml but does not match devices/<device>/secrets.yaml — so the per-device .gitignore is what actually protects the secrets file. Only the chmod protects against local read by other users).
Workflow when onboarding a new device:
- For a brand-new device directory, create
devices/<device>/.gitignorecontaining/secrets.yamlbefore anything else — the root.gitignorewill not cover the secrets file otherwise. - Copy
devices/<device>/secrets-example.yamltodevices/<device>/secrets.yaml. - Fill in the five fields with values from David's IoT VLAN credential store.
chmod 600 devices/<device>/secrets.yaml.- Verify with
ls -la devices/<device>/secrets.yaml— must show-rw-------. esphome run devices/<device>/<device>.yamlto flash.
The YAML files reference these values via ESPHome's !secret indirection (api_key: !secret api_key, etc.) — never inline a literal. Rotation = re-flash; the device must be physically reachable, so rotation is per-device and event-driven, not scheduled. Central rotation runbook: /opt/autocoder/ROTATION_RUNBOOK.md ("Levoit device creds" row).
Conventions for credentialed work in this session. Never cat, echo, or otherwise render secrets.yaml content to stdout. ESPHome reads it directly; verify success via esphome run output (device booting, Wi-Fi connecting), not by reading the file back.