Repository navigation
Conversation
… confirm Found in incident #2984: after POST /api/kernels returned HTTP 401, pcc-node start printed "Node running. Accepting jobs." and the daemon logged "Kernel ... registered", then polled, announced and heartbeated with the rejected key every few seconds for five minutes. register_kernel returned an error dict on failure, which no caller could tell apart from a registration record. It now raises KernelRegistrationError (status, body, auth_rejected) for anything but 200/201, including status 0 (unreachable). - start: on failure, say "NOT registered", why, and "Nothing was started", and exit non-zero. Devices, signing key, announce and the daemon are all skipped (the existing comment already required this). A key the gateway minted in this run is saved first, so it is not lost. - daemon: "registered" is logged only on success. A rejected key (401/403) stops the daemon before it polls; start then exits 1. Other failures are logged as NOT registered, and the running line says so. - discover --register: a refused registration counts as failed, not registered, and the command exits 1. Tests: pcc-node 360 passed, 2 failed. The 2 are the headless-consent failures that also fail on master; #388 fixes them. 24 new tests. The old TestRegisterKernel.test_failure expected an error dict; it now expects the exception (reason in its docstring). 8 mutants (reverting each part of the fix) are all killed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy
…mand #388 also appends a test class at the end of test_cli.py. Keeping this class above TestStartCommand lets the two PRs merge without a conflict. No test changed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy
…file test_cli.py is back to master's bytes, so this PR and #388 (which appends to test_cli.py) merge without a conflict. The tests are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy
LamaSu
added a commit
that referenced
this pull request
Sep 29, 2026
…le's gateway is honoured (N57) Product-steward's review of #457 (bus #4076) adds the confirmation half of N57 and a label fix. - The gateway is now resolved once: --pcc-base, then PCC_BASE, then the config file's pcc_base, then the public default. The banner and registration both use it. Before this, start ALWAYS overwrote the config's gateway with the CLI value (config.pcc_base = pcc_base), so a gateway chosen in `pcc-node setup` was silently replaced by the public default. The banner now labels that source "(from <config path>)". - --yes (-y). When the public gateway comes from the default, and there is no --yes and no earlier yes on this machine (~/.pcc-node/confirmed-gateways), start asks on a terminal: "Register this machine on the public PCC network (https://capability.network)? [y/N]". On yes it remembers. Without a terminal it exits 1 with "Pass --yes or set PCC_BASE to register with the public network." The check runs after the already-running check and before any network step. install.sh exports PCC_BASE (install.sh:187), so it keeps working. - #396's truth half stays required. This commit stays clear of its lines. Tests: test_start_banner.py now has 8 cases: non-TTY default refuses; --yes; PCC_BASE; --pcc-base; a config-file gateway that is used, labelled and not clobbered; a yes on a terminal that is remembered from another directory; no refuses; the banner comes first. test_cli's start flow and test_discovery's --discover start pass --yes. Mutation-checked (confirmation bypass, config clobber, no memory). Full pcc-node suite with HOME in scratch: 346 passed. agent: pcc-adk (4f6668ed) 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.
What
pcc-node could report a kernel as registered when the gateway had rejected the registration. This PR stops that.
Found in incident #2984, where
pcc-node startran against prod with no valid key:POST /api/kernelsreturned HTTP 401;startstill printedNode running. Accepting jobs.;Kernel … registered;Root cause:
register_kernelreturned an error dict on failure, and no caller could tell it apart from a registration record.startignored the value. The daemon logged success whenever no exception was raised.discover --registercounted every attempt as registered.Change
register_kernelraisesKernelRegistrationError(kernel_id, status, data)for anything other than 200 or 201. That includes status 0 (unreachable) and 202..auth_rejectedis true for 401 and 403.start, on failure:Kernel X was NOT registered: <why> Nothing was started.and exits non-zero;registeredis logged only on success;startexit 1;NOT registered (HTTP n), and theDaemon runningline says(NOT registered).discover --register: a refused registration counts as failed, and the command exits 1. Output:registered 0, failed 1.Unchanged: the success path. The same statuses (200/201) count as success, and the same requests are sent in the same order.
Tests
test_cli::TestStartCommand::test_start_flowandtest_discovery::…test_start_with_discover_flag, the headless-consent failures that also fail on master. ci+fix(pcc-node): run the Python suite in CI; headless start; tests keep keys in tmp (N52) #388 fixes them.test_register.py: the failure contract, and "only 200/201 counts" across 9 statuses;test_registration_truth.py: start aborts honestly for 401, 0 and 503; a minted key is kept; an unsavable key is reported and not printed; a daemon stop gives a non-zero exit;test_discovery.py: failures are counted honestly;test_daemon_loop.py: 401 and 403 stop before polling; 503 is logged as NOT registered; success is logged.TestRegisterKernel.test_failureexpected the old error dict. It now expects the exception; the docstring says why.http://pcc.invalid.git merge-treeis clean against feat(pcc-node): settle accepted prints on device-reported completion (IPP job-state, OctoPrint /api/job) #377 (and so fix(pcc-node): emit execution_failed, never execution_completed, on failed device results (OH-1, evidence sec-10) #333/fix(pcc-node): device acceptance is submitted evidence, never execution_completed #343), ci+fix(pcc-node): run the Python suite in CI; headless start; tests keep keys in tmp (N52) #388, fix(pcc-node): announce capabilities through the heartbeat, not the store-nothing stub #390, fix(pcc-node): stop tracking the local node key file and Python build artifacts #366 and fix(pcc-node): verify_signature fails closed; never default to a key file in the checkout (N35b) #374.Not in scope
register_deviceshas the same return-dict shape, so it is a follow-up.🤖 Generated with Claude Code
https://claude.ai/code/session_01PkeiQMnVePeBGU9svhREFy