docs: add device identity reference - #3
Merged
Merged
Conversation
Documents the hardware-stable device_id resolution chain (make:serial > mac: > ep:), the ARP-based L2 lookup, the devices table schema, the 3-second bootstrap flow from registry.Add through registerAllDevices, and the one-shot battery_models key migration. Cites source lines so readers can jump from prose to code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
|
🎉 This PR is included in version 2.0.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
erikarenhill
added a commit
that referenced
this pull request
Apr 17, 2026
Three items in the 11-comment review are still outstanding after the earlier rebase — the rest were already addressed in b6a5c78 / 4f3ad01: - #3 EV card keyboard accessibility (web/index.html + web/app.js): add role="button", tabindex="0", aria-label, and Enter/Space key handler so the summary card can be activated without a mouse and is announced correctly by assistive tech. - #9 Hardcoded "easee" provider (web/settings.js): Connect button now derives the provider name from the driver's lua path (strip dirs, trailing "_cloud", ".lua"), falling back to "easee" when the driver config is missing or oddly named. Lets a second cloud driver slot in without touching the button. - #5 Missing tests for path normalization (config_test.go): cover stripLeadingDotDot, ResolveDriverPaths (relative / absolute-in-tree / absolute-out-of-tree / leading-"../"), and the full Resolve → Unresolve → Resolve round-trip. The round-trip test is the one that pins down Copilot #11 — absolute paths outside baseDir must stay absolute so the next Resolve doesn't strip a "../" from filepath.Rel and silently re-anchor the driver under baseDir. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
erikarenhill
added a commit
that referenced
this pull request
Apr 20, 2026
5-agent vote per comment accepted 6 of 7: - Offload HealthTick observeAt to a goroutine so a slow ntfy Publish (10 s timeout) can't stall the control loop. The event bus runs handlers inline on the publisher, and HealthTick is emitted every control tick. (Copilot #1) - Nil-publisher guard in dispatch(): cold-start or reload with an unknown/unconfigured provider used to panic at s.pub.Publish; now it's treated as a failed dispatch with a history entry. (Copilot #3) - Emit NotificationDispatched on template render failures too, so the history UI surfaces template errors instead of only publish errors. (Copilot #4) - activeAlert leak fix: when no driver_recovered rule is enabled, a post-pass cleanup clears activeAlert for any driver whose telemetry is fresh (<30 s). Preserves the original lifecycle: when recovered IS enabled, the recovered rule still owns the clear. (Copilot #5) - Stop seeding backend default templates into currentConfig. Render title/body template fields as raw inputs whose placeholder is the server default. Blank stays blank, backend fallback keeps working, and future server-side default changes apply without operator action. (Copilot #6) - driver_recovered ignores threshold_s on the backend (hardcoded 30 s staleness window). Don't render the threshold input for that event type — show a clarifying note instead. (Copilot #7) Tests: new TestActiveAlertClearsWhenRecoveredDisabled and TestNilPublisherNoPanic. Full suite still green (35 packages). Skipped Copilot #2 (SQLite write in NotificationDispatched subscriber blocks the publisher): the write runs after HTTP publish on a path that already blocks for up to 10 s, a sub-millisecond SQLite insert adds nothing measurable. 3-of-5 agent votes INVALID. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
erikarenhill
added a commit
that referenced
this pull request
Apr 30, 2026
Five comments, four logical fixes: #1, #2, #3 — config.SafetyMarginA: float64 → *float64 so we can distinguish "unset → use 0.5 default" from "explicit 0 → operator chose to disable margin". Single source of truth via new DefaultFuseSafetyMarginA constant + Fuse.EffectiveSafetyMarginA() helper. main.go startup + hot-reload both call the helper instead of duplicating `<= 0 → 0.5` shortcuts that clobbered the disable case. Validate() updated to dereference; explicit 0 is accepted (and verified by a new round-trip test). #4, #5 — direction attribution in applyFuseGuard + forceFuseDischarge now gates on `currentGrid` (live aggregate at the meter) instead of `predicted` (post-target hypothetical). Per-phase amps and currentGrid come from the same DerMeter sample; predicted mixes in sumTarget which can swing across 0 on a large planner request and silently flip the gate, attributing a current-export overage to the import path (or vice versa). New tests: - TestFuseSafetyMarginNilUsesDefault — back-compat for unset YAML - TestFuseSafetyMarginExplicitZeroDisables — locks the new contract - TestFuseSafetyMarginExplicitValuePassesThrough - TestValidateRejectsNegativeSafetyMargin (parses YAML) - TestValidateRejectsSafetyMarginAtOrAboveMaxAmps - TestValidateAcceptsExplicitZeroSafetyMargin (round-trips through Parse + EffectiveSafetyMarginA to verify 0 stays 0)
frahlg
added a commit
that referenced
this pull request
Jun 5, 2026
Codex returned NO-GO on the parallel build; these close the findings relevant to the shippable relay-hardening (slices 1+2): - #1 CRITICAL: require -home-web when a home host is set (else the relay fell back to forwarding anonymous GETs to the Pi — the exact surface we forbid). requireHomePin now enforces it. - #2 HIGH: device_pubkeys are now covered by the registration signature (MeRegisterSigningStringV2); a captured /me/register can no longer be replayed with a swapped/added device key. + regression test. - #4 MED: symlink-escape in the -home-web static server closed (EvalSymlinks + re-check the resolved path stays under the web root). Deferred to the C2-enforcement phase (inert until the device-key gate is ON), with TODOs: #3 (bind device_pubkey to the enroll ceremony) and #5 (separate per-IP limiter on challenge issuance). All Go unit + 97 web tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
frahlg
added a commit
that referenced
this pull request
Jun 5, 2026
* feat(home-route): inline passkey sign-in on the dashboard The dashboard now reveals a discreet sign-in banner + header key when whoami reports the viewer isn't signed in on a remote origin, and runs the passkey login ceremony in place over the same strict P2P channel (ownerFetch) — no redirect to /owner-access/login.html, which would spawn a fresh channel with no session. Re-checks on P2P (re)connect. LAN bypass + signed-in views never show it. Closes the discoverability gap (part of #438 seamless UX). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(home-route): full sign-in gate + informational transport indicator Evolve the inline-signin banner into a real gate: a logged-out remote visitor now sees ONLY a clean sign-in card, never the empty dashboard chrome (which rendered 'No devices configured' and read as an unconfigured instance). The gate covers the dashboard until whoami confirms a signed-in owner; the passkey ceremony runs in place over the strict P2P channel. Suppresses the no-devices prompt while logged out. The transport indicator is now informational (direct/ relayed/connecting), not a confusing toggle that broke the P2P-only channel. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(home-route): no dashboard flash on reload behind the sign-in gate A reload briefly painted the dashboard before next-app.js could cover it with the gate. Add a pre-paint inline <head> script (mirroring the theme-flash guard) that marks <html class=ftw-gated> on a remote origin from the first frame; CSS shows the opaque full-screen gate immediately, and setupAuth() clears ftw-gated once whoami confirms a signed-in owner. The gate is now a class toggle (not the hidden attribute) so the pre-paint CSS can win. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: hardened-relay + device-key design spec (no anonymous path to a Pi) Spec for the relay-hardening Fredrik approved: relay serves the sign-in shell + /api/identity from its own embedded copy (Pi not touched), and forwards signaling to the Pi ONLY when it carries a device-key proof the relay can verify. The device-key (LAN-born, wallet-bound) becomes the sole credential that can reach a Pi from the internet, and also mints the session silently. Surface-by-surface threat model + build slices + one open trade-off for review. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(home-route): hardened relay + device-key remote access (no anonymous path to a Pi) Relay serves the sign-in shell (-home-web) + /api/identity (from -home-pubkey) itself, so anonymous visitors never reach the Pi. Signaling is gated by a device-key proof (relay-issued nonce, signed by a non-extractable WebCrypto ECDSA P-256 key minted at LAN enrollment, verified against the device-pubkeys the Pi publishes on /me/register) — else 403, Pi never woken. The device-key also mints the session silently over the channel (device-PoP); step-up keeps a passkey; revocation drops the key on Pi + relay. Built in parallel across relay/ Pi/browser against locked wire contracts (C1-C4), then integrated. All Go unit tests + 97 web tests pass. Pending Codex security GO before live. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(home-route): address Codex security review of the device-key build Codex returned NO-GO on the parallel build; these close the findings relevant to the shippable relay-hardening (slices 1+2): - #1 CRITICAL: require -home-web when a home host is set (else the relay fell back to forwarding anonymous GETs to the Pi — the exact surface we forbid). requireHomePin now enforces it. - #2 HIGH: device_pubkeys are now covered by the registration signature (MeRegisterSigningStringV2); a captured /me/register can no longer be replayed with a swapped/added device key. + regression test. - #4 MED: symlink-escape in the -home-web static server closed (EvalSymlinks + re-check the resolved path stays under the web root). Deferred to the C2-enforcement phase (inert until the device-key gate is ON), with TODOs: #3 (bind device_pubkey to the enroll ceremony) and #5 (separate per-IP limiter on challenge issuance). All Go unit + 97 web tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(relay): -require-device-key rollout flag (C2 gate dormant by default) Slices 1+2 (relay serves the shell + /api/identity itself, closing the anonymous-FETCH surface) ship independently of the device-key signaling gate: -require-device-key defaults OFF, so signalBrowserOffer parks the raw offer with no proof (pre-C2 behaviour) and a home Pi that doesn't yet publish device-keys keeps working. Flip it on once device-keys are enrolled to close the anonymous-SIGNALING surface. C2 tests now assert the enforced path; a new test asserts the dormant default. All Go unit + web tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/device-identity.mdcovering the hardware-stabledevice_idchain (
make:serial>mac:>ep:), the ARP L2 fallback, thedevicestable schema, bootstrap flow, and the battery-modelmigration.
to code.
registerAllDevicesat boot) ratherthan implying a periodic re-tick.
Test plan
cd go && go build ./...cd go && go test -timeout 120s -count=1 ./...devices.go,store.go,arp.go,registry.go,main.go,api.go,sungrow.lua).grep /api/devices internal/api/confirms the endpoint is registered.Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
Generated with Claude Code