node report: a claimed device sends its own signed heartbeat - #426
Merged
Merged
Conversation
The console has accepted device-signed heartbeats (POST /api/devices/:did/heartbeat) for some time but nothing on a device called it, so a claimed box showed 'never seen'. murakumo node report signs the body as sent (aiueos-device-heartbeat-v1 + DID + the origin reached + SHA-256 of the body) with the device key and posts it. Metrics are the machine's own health only; no host name, address, SSID or account data. Exit codes separate accepted, rejected, unreachable, not-yet-claimed and clock-ahead. Adds services.murakumoNode.report (timer, default 60 s) and its smoke assertions. The packaged CLI is tested against an independent re-implementation of the server's signature check. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The site's cljk-mirror refuses a .cljk file with no entry in its repo's cljk-origin.edn (the Worker build of murakumo.cloud mirrors this repo), so these files must be recorded or merging would stop that build. They are node-side (js interop), so .cljs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… cljk-origin records)
com-junkawasaki
marked this pull request as ready for review
October 2, 2026 06:46
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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.
Stacked on #424 (→ #423 → #421); base is
feat/node-onboard-device. Draft; retarget as the lower PRs merge.Why
The console accepts device-signed heartbeats (
POST /api/devices/:did/heartbeat,devices-http/device-heartbeat) but nothing on a device called it. A claimed box therefore showednever seenhowever healthy it was; only the operator collector's fleet pushes (shared token, one host that can reach every box) made rows live. A device signing with the key it already holds needs neither.What
murakumo.device-report: builds the body, signsgrant.device-attest/heartbeat-signing-input(domain, DID, the origin the request reaches, SHA-256 of the body as sent) with the device's Ed25519 key, posts it, and sorts the answer into outcomes with distinct exit codes.murakumo node report [--site URL] [--once | --interval SECONDS]. The loop prints only when the answer changes, so a healthy box is quiet and an unclaimed one does not fill a log.load1,mem-free-ratio,uptime-s,platform,arch,node. No host name, address, SSID, path or account data; this is tested.services.murakumoNode.report.{enable,intervalSeconds}(timer, default 60 s). Exit 4 (not claimed yet) is a success status, so an unclaimed box does not alarm.Verification
kbb -M:test -n murakumo.device-report-test: 8 tests, 34 assertions. The signing input is pinned as a literal; a signature verifies with the DID's key via node:crypto (a different path from the signer) and does not verify for another body hash, endpoint, or the enrolment domain; every server answer maps to an outcome; the posted request carries a signature over the exact body.node test/device_report_test.mjs(added to CI): the packaged CLI against a fake console that re-implements the server's check independently (DID → public key,domain\ndid\norigin\nsha256(raw body)\n, Ed25519 verify). Covers accepted (server-side verification passed), the fixed body shape and no identifying data, not-claimed (exit 4), clock-ahead (5), replayed observation (0), a mismatched identity, unreachable (3), and the site allow-list.nixos/node.nixandrelease/nixos-node.nixare in sync (the CIcmp).Not verified
verify-heartbeatfrom reading its source. The Worker itself (devices_http.cljk) was not run, and/api/devices/*is behind the broken production deploy (cloud-murakumo#253).nixhere);nixos-node-moduleCI is the first evaluation.GET /api/devicesmust return the storedlast_metricsfor the console to show anything beyondlast seen; I read the code but did not run it. The matching console change is a separate PR.unknown-device); that is exit 4, not an error.🤖 Generated with Claude Code