Skip to content

Match enrolled nodes exactly, check their Core address and serve artifacts only from the console - #144

Merged
SaladDay merged 7 commits into
mainfrom
codex/node-enrollment-core
Sep 25, 2026
Merged

SaladDay merged 7 commits into
mainfrom
codex/node-enrollment-core

Conversation

@SaladDay

@SaladDay SaladDay commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Phase 2a of the new-user install work is the Core side of adding a node with one command. The installer's sudo mode (2b) follows separately.

  • enrollment_id: POST /core/v1/sandbox/enrollment-tokens returns a non-secret enrollment_id, a random UUID that is not derived from the token. A node records it at registration, and the /core/v1/sandbox/nodes list and detail return it (null for older nodes). With it, Web can match the node a command registered exactly. Migration 000077_node_enrollment_id.
  • Enrollment carries the node's address: POST /api/v1/sandbox-node/enroll now requires core_url.
    • A missing value gets 400.
    • A value that differs from Core's public URL gets 409 sandbox_node_address_mismatch. That is checked before the token is consumed, so a retry with the right address works until the token expires.
    • An invalid or foreign token still gets 401 before any deployment state is revealed.
    • parsar-sandbox-node sends the address.
    • After a mismatch the node installer removes its unregistered local state, so a new command works on the same host.
  • Node restarts:
    • Node units keep retrying every 5 s with no start limit, so a node outlasts a Core outage.
    • Only a 401 (credential rejection, i.e. a removed or retired node) makes parsar-sandbox-node exit 78, which systemd does not restart.
    • A 403 from a proxy or WAF stays retryable.
  • Artifacts only from the console: nodes and self-hosted executors download artifacts and metadata only from the console origin, even when the build recorded a GitHub release URL. Every redirect is refused. Integrity checks are unchanged.
  • Console: /console/config adds node_artifacts, the providers whose node files the console holds. It is checked on every request and is always an array. The config keeps all five fields.
  • Docs:
    • CONTRIBUTING allows a root-owned system service for the planned sudo mode (phase 2b) and describes the restart rule.
    • The install and node guides, sandbox-deployment.md and the machine OpenAPI are updated.

Behaviour change: a local node installed from a thin bundle now needs the release assets placed in <bundle>/artifacts/, because the GitHub fallback is gone. The install guide says so.

Review

  • Independent blind review found no P0 or P1.
  • The P2 (redirects were followed across origins) and the P3s were fixed in 82e20013: 409 cleanup, 403 no longer permanent, CONTRIBUTING wording, exit-code table test, test placement, and node_artifacts as an array. These were verified by tests and the gate, per the small-fix rule.

Verification


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.

…e address

- POST /core/v1/sandbox/enrollment-tokens returns a non-secret enrollment_id.
  Registration copies it to the node, and the node list and detail report it
  (null for nodes enrolled before Core recorded it). Migration 000077.
- POST /api/v1/sandbox-node/enroll requires core_url, the origin the node stores.
  A missing value gets 400 (param core_url); an address other than the public
  URL gets 409 sandbox_node_address_mismatch before the token is consumed. The
  node records the address it sent. parsar-sandbox-node sends it.
- Node services keep retrying while Core is unreachable (RestartSec=5s, no start
  limit). parsar-sandbox-node exits 78 when Core rejects its credential, as after
  removal, and RestartPreventExitStatus=78 ends the restarts.
- Nodes and self-hosted executors download artifacts only from their console,
  never from a release URL the build recorded. /console/config reports the
  providers whose node assets the console holds (node_artifacts).
- The node installer explains Core's registration answer (address changed,
  command expired) with fixed text.
…retryable

- Artifact and metadata downloads refuse every redirect. The console never
  redirects, and following one could fetch verified names from another origin.
  This covers the self-hosted installer's SHA256SUMS and manifest.json.
- After a 409 sandbox_node_address_mismatch, the node installer removes the
  unregistered files that name the old address (installation.json,
  provider.json, state/node), so a new command registers the same host. Core
  never recorded the node and the token was not used. A command whose Core
  address changed before registration now says the public URL changed.
- Only Core's 401 stops the node for good (exit 78); a 403 from a proxy or
  firewall stays retryable.
- CONTRIBUTING describes only what main does: sudo mode is planned for phase
  2b, and Web's exact enrollment_id match lands with the Web follow-up.
- Tests: exit codes of parsar-sandbox-node, redirect refusal, state cleanup and
  a node_artifacts list that is [] without a node payload.
# Conflicts:
#	docs/api/web-management.md
#	services/core-console/node_installation.go
@SaladDay
SaladDay merged commit 0d89a84 into main Sep 25, 2026
3 checks passed
@SaladDay
SaladDay deleted the codex/node-enrollment-core branch October 7, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant