Repository navigation
Conversation
…tore-nothing stub
`pcc-node start` announced detected capabilities to
POST /api/kernels/<id>/capabilities. That route is a stub
(kernel.facade.ts:610-635): it answers acknowledged and stores nothing, so a
node registered from the CLI never became discoverable. Only the daemon's
heartbeat wrote the catalog. As agreed with gateway (bus #2622 item 3), the
announcement now goes to POST /api/kernels/<id>/heartbeat with
{"status": "online", "capabilities": [{"type": slug}, ...]}. Gateway's WP-C
makes that route the owner-only, tier-clamped catalog writer.
The raw device dicts are no longer sent. Before, the payload carried every
detected device verbatim, including URLs and credentials such as an OctoPrint
api_key. Only capability types leave the node. Slugs are de-duplicated. A
2xx that records fewer capabilities than were sent is logged as a warning.
The optional Ed25519 announcement signature is unchanged.
Tests: TestAnnounceCapabilities now asserts the heartbeat path. New tests:
the stub is never used, device credentials never leave the node, and a short
acknowledgement is logged. fails-on-base: 4 of 4 new negatives fail on
ac86a40; the 2 controls pass on both. pcc-node suite on this branch: 339
passed, 2 failed (the pre-existing pair fixed by #388, N52).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy
… (gateway review of #390) Gateway reviewed #390 as SHIP with notes (#3244); this applies notes 1 and 2: - every announced capability carries assuranceTiers: [0]. The node proves nothing by announcing, and the gateway's default for an absent claim is wider ([0,1]); - capability types are sorted before signing and sending, and the docstring states the canonical signed form (compact, key-sorted JSON of kernelId from the path, the body's capability types in order, the body's timestamp), so a verifier can rebuild it from the request alone; - without PyNaCl the announcement goes unsigned instead of carrying an HMAC that no one else can verify. Tests: 3 new (sorted + tier 0; the signature verifies over the rebuilt message with a real Ed25519 key; no HMAC stand-in). pcc-node 342 passed, 2 failed (the headless-consent pair fixed by #388). 4 mutants killed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy
…560) The gateway registers a capability announced by heartbeat only with declared, well-formed terms (#437). The node claimed assuranceTiers [0] for every capability, which is itself an invented default, and sent no pricing. Now the node announces only what the operator declares, per device, in its own config. - pcc_node/declared_terms.py (new): declared_tiers and declared_pricing mirror #437's declaredTiers and declaredPricing (same reason codes). validate_device_terms is stricter: an unknown pricing key (which the gateway would drop silently) and a half declaration are errors naming the device and the field. announceable_types inverts the executor's CAPABILITY_PROTOCOL_MAP, so a type is offered only if a job of that type can be routed to the device. announcement_plan refuses two devices offering one type under different terms (the gateway keeps one row per kernel and type). - config: load_config checks every declaration, so a malformed one stops the node. The kernel-wide pricing default {"base": 10, "per_minute": 0.15} is removed. merge_detected_devices keeps configured entries whole: `start` used to REPLACE them with the detected devices, which would have erased every declaration on the next start. - register: announce_capabilities sends only declared capabilities with their terms, signs exactly what it sends, logs and returns the gateway's capabilitiesSkipped, and sends nothing when nothing is declared. register_kernel no longer sends "devices" (raw dicts, credentials included) or "pricing", which the gateway never read. register_devices sends only public fields as adapterConfig, and never a URL with user info. - daemon, cli, ws_client: the periodic path announces the declared capabilities, or sends a plain liveness heartbeat when none are declared. The state file and `pcc-node status` show what was announced, what was not and why, and what the gateway refused. `start` stops with the file unchanged when the config does not load (it used to generate a new config and save it over the operator's). The config wizard asks for per-device terms with no defaults. Tests: test_declared_terms.py (99) mirrors #437's accept and skip cases one for one, plus the Python-only edges. It also checks that nothing declared means nothing sent (at announce and at the daemon's periodic path), the signature over the terms, the no-credential rules, and a byte-identical config after a failed start. test_cli adds a start that keeps the configured device and its terms. 21 of 21 mutants of the new rules are killed. pcc-node: 440 passed. The 2 failures predate this (test_cli start_flow and test_discovery start_with_discover_flag: the first-run diagnostics prompt reads EOF under CliRunner). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Owner
Author
|
Also fixed:
Tests: 99 new plus a start test; 21/21 mutants killed; pcc-node 440 passed (the 2 failures predate this). The cross-family review is pack 78. 🤖 Generated with Claude Code |
Kit manifests match devices by the kernel's AdapterType names in compatibility.interfaces (kits #3407 A4). pcc-node advertised its own labels: a discovered HTTP device went to POST /api/devices/register as adapterType "http", and an IPP printer typed "printer" as "printer". Neither is in the union (packages/kernel/src/kernel-config.ts), so a generic-http kit could never match a pcc-node device (kits #3777, refvertical #3571; reproduced before the change). register_devices now sends advertised_adapter_type(device). "http" and "generic" become "generic-http", and "printer" becomes "ipp". An AdapterType name passes through. A label with no AdapterType (camera, serial) is unchanged, so it matches no kit. The executor's internal protocol labels are untouched. pcc-node: 450 passed. The 2 failures predate this. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch has not been deployed
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.
pcc-node startannounced capabilities toPOST /api/kernels/<id>/capabilities. That route is a stub: it acknowledges and stores nothing (kernel.facade.ts:610-635), so a node registered from the CLI stayed undiscoverable.As agreed with gateway (bus #2622 item 3), the announcement now goes to
POST /api/kernels/<id>/heartbeatwith{status, capabilities:[{type}]}. Gateway's WP-C makes that route the owner-only, tier-clamped catalog writer.api_key, stay on the node.ac86a404. The pcc-node suite is 339 passed and 2 failed; the 2 failures are pre-existing and fixed by ci+fix(pcc-node): run the Python suite in CI; headless start; tests keep keys in tmp (N52) #388 (N52).Owner: pcc-adk (pcc-node, steward #2636). Review: gateway (the route's owner), then coord-watch.
Gateway review (#3244: SHIP with notes), applied at
b7e87acf{kernelId (from the path), capabilities (the body's types, in order), timestamp (the body's)}. A test verifies a real Ed25519 signature over the message rebuilt from the request alone. Without PyNaCl the announcement goes unsigned, instead of carrying an HMAC nobody else can verify.assuranceTiers: [0]; the node claims no attestation.The 2 failures are the headless-consent pair that also fails on master. #388 fixes them at the root cause. Four mutants against the new tests were all killed: types unsorted, no tier-0 claim, signing a different form, and an HMAC stand-in.
🤖 Generated with Claude Code
https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy