Agent enrollment by approval (SPEC §7.1.1) #10
Loading…
Reference in a new issue
No description provided.
Delete branch "agent-enrollment"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds approve-to-join agent enrollment (SPEC §7.1.1, §9).
An agent started with
--enroll(NixOS:services.krisbuild.agent.enroll = true), when no token file holds a token, generates its ownkbat_token. It persists the token at<work_dir>/agent-token(0600) and presents it withX-KB-Enroll: <node>. The control plane records an unknown token presented this way as a pending request. It refuses the connection with a machine-readableX-KB-Enrollmentstatus: pending, rejected, throttled, disabled or invalid. An operator approves or rejects the request on/ui/tokensor via/api/agent-enrollments. Approving turns it into an ordinaryagent_tokensrow with the same hash, so the secret is never shown to anyone.kb-corechanges are additive only (header constants and the status enum). No protocol message ordef_hashchanges.enrolloption defaults to off, so today's tokenless agents are unaffected.🤖 Generated with Claude Code
Adding a node no longer means minting a token on the LAN UI and copying it to the node. An agent started with --enroll (module: enroll = true) and no provisioned token generates its own kbat_ token from the OS CSPRNG, keeps it 0600 in its work dir, and presents it with an X-KB-Enroll header. The control plane records an unknown token so presented as a pending request and refuses with X-KB-Enrollment: pending (403), which the agent tells apart from a plain 401: it logs "awaiting approval" once, with a fingerprint, and retries on its capped backoff. An operator approves on /ui/tokens (or POST /api/agent-enrollments/{id}/ approve), choosing label and max_trust (default 0); that inserts an ordinary agent_tokens row with the same hash, so from then on it is exactly a minted token. Reject marks the request; its token stays refused while its agent keeps retrying and is forgotten after 7 idle days. Since the agent listener is public: verification and the request run in one database call, a request can only create one bounded inert row (32 pending, 12 new per hour, 24 h idle expiry, retries bump their own row), and nothing but an operator's approval writes agent_tokens. A request for a name with an active token is flagged, and approving it requires choosing to keep or revoke that token. agent_enrollment (default true) turns it off. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>Reviewed: public enrollment requests can only create a bounded, inert pending row (well-formed token, global caps, dedupe by hash, first name stands); lookup + request share one DB call; approval is transactional and forces an explicit keep/revoke on name collisions. CI green (graph 561).
@krisbuild r+
Removed from the merge queue: the merge conflicts in SPEC.md, crates/kb-agent/src/config.rs, crates/kb-cli/src/engine.rs, crates/kb-cli/tests/remote.rs, docs/forgejo-setup.md, flake.nix.
b43471ba177d845cdf96Merged main (#18) and moved
agent_enrollmentintotests/it/. Build, clippy and kb-check were green on the rebased head (graph 592); its test run was superseded by this push.@krisbuild r+
Merged as
ded08eaa93.