Skip to content

Guide Add node through host requirements, expiry and registration - #132

Merged
SaladDay merged 16 commits into
mainfrom
codex/web-add-node
Sep 25, 2026
Merged

SaladDay merged 16 commits into
mainfrom
codex/web-add-node

Conversation

@SaladDay

@SaladDay SaladDay commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Makes adding a node close to "copy one command and paste" in the console (W2 of the new-user install plan, ~/.parsar/plans/new-user-install-20260925/02-web-proposal.md).

Add node dialog

  • Host requirements. A checklist per backend with copyable commands (loginctl enable-linger, the docker/kvm group). Every item comes from the node installer's own preflight, cited in node-enrollment.ts. The checklist opens on first view and collapses once a command exists.
  • Expiry countdown. It counts down to the expires_at Core returns rather than a hard-coded 10 minutes.
  • The command outlives the dialog. Closing and reopening shows the same command and countdown. When it expires, Generate new command reuses the limits already entered. Tokens are never created automatically.
  • Loopback and plain-HTTP origins get a warning before generating, with what to do instead.
  • Registration progress. Steps: waiting for registration → registered · name → connected → waiting for Docker/microsandbox. If the node reports a readiness diagnostic, or isn't ready 60 s after it appears, the existing diagnostic wording shows, plus a copyable journalctl --user -u parsar-node-<installation_id>.service. The unit name is from node_install.py.
  • Wizard to Add node. The first own-machines save in the setup wizard continues straight to Add node.

The token lifetime stays 10 minutes (security boundary, agreed with the backend). The backend's planned sudo-mode node command will later shrink the requirements list.

Tests

  • nodes.spec.ts:
    • the Docker requirements;
    • the loopback warning;
    • the countdown (fake clock);
    • close/reopen keeping the command;
    • regeneration after expiry with the same limits;
    • progress through registration, a docker_limits_unsupported diagnostic and readiness.
  • The wizard test checks that Add node opens after Save configuration.
  • The fixture's tokens now expire after 10 minutes, and /__fixture/node can register or update a node.
  • Unit tests cover the countdown, progress-step and log-command helpers.

Results: typecheck passes; unit tests 336/336; build passes; full web e2e 18/18.


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

The Add node dialog now:
- lists the host requirements the installer and the node's readiness
  probe actually check, per backend, with copyable root commands;
- warns before generating when the console's own address is loopback,
  so a remote host would download from itself;
- counts down to the token's expires_at and keeps the command across
  closing until it expires or its node connects, offering a new command
  for the same limits only on request;
- follows the new node from the polled node list (registered, connected,
  backend ready), showing its readiness diagnostic, or a missing
  connection after the installer's 60-second wait, with the journalctl
  command for the installer's systemd user unit.

The acceptance fixture issues ten-minute tokens as Core does and can
register and change a node for the new end-to-end flow.
Saving an own-machines deployment for the first time opens the Add node
dialog, since a Docker or microsandbox deployment runs nothing until a
node joins. E2B has no machines and stays on the page.
Each step now reads by tense: past once done, "Waiting for…" while
current, a plain greyed noun while ahead. The network requirement no
longer says HTTPS beside what may be loopback http:// addresses; the
loopback warning already covers the HTTPS rule.
As Core does, a node enrolled in the acceptance fixture takes the limits of
the last enrollment token (Docker's retained limit equal to its active one)
and has no diagnostic field until one is reported.
The newest unknown node could belong to another, still valid command.
Core copies a token's limits onto the node it enrolls, so the dialog
follows a new node only when its active limit, and for microsandbox its
retained limit, match the command's.
The dialog read nodes only while open and unexpired, so a node that
registered while it was closed, or in the last seconds, was missed: it
showed "Command expired", and a new command then folded the node into its
known set and waited forever.

Now each opening reads the node list, and at expiry one more read runs
before "Command expired" shows; a node registered by the command outranks
its expiry. Generating a new command first adopts a node the previous
command enrolled as that command's success. The page's refresh settles
when its read does, so the dialog can wait for it.
Enabling lingering starts the user's systemd manager, and the node
service keeps the groups that manager started with; signing in again
doesn't change them. The docker/kvm group command now comes before
enable-linger, and the note says to restart an already running user
manager after a group change (or reboot), with the command.

Two requirements the installer and the node check were missing: running
the command in the user's own session (systemctl --user; sudo -u and su
don't give one), and CPUs and memory for one sandbox of the deployment's
size, which readiness compares with the host's totals.
"Docker ready" as a later step read like a claim, and its dot is hidden
from assistive technology. A later step is now the neutral "Docker check"
("Docker 检查"), like "Connect"; the waiting and done wordings stay.
The progress list was an <ol role="status"> swapped for other status
elements, so a screen reader could miss "Connected". One status region
now stays in place and wraps a plain list, the expired text or the
connected text; only its contents change.
After registration the one-time command only recovers that node, so its
line now reads "Rerun only on <node> if asked" instead of inviting a run
on another host. "Registered · <node>" and "<node> · Connected" are single
translated strings instead of concatenated pieces.
Limits entered for a command stay while it is pending, so an expired one
can be reissued with them. Once the node is done, or the dialog closes
with no command pending, the next opening starts from the defaults.
Continuing from the first own-machines save opens the limits and issues
no enrollment token; saving E2B, which has no machines, opens no dialog.
A shell opened before usermod lacks the new group, so running the command
in it still fails the installer's Docker or KVM check. The note now says
to sign in again as that user, and to restart an already running systemd
user manager (or reboot).
<user> is shell redirection: pasted as is, sudo machinectl shell <user>@
reads a file named user. Every displayed command now uses NODE_USER, and
the first requirement says it is the user that runs the node.
Checking for "Command expired" after progress appeared could not see a
flash before it; a DOM watch from the reopening on now records any render
of it. The setup test waits a second for a token request that must not
come, then checks Core saw only the deployment write.
@SaladDay
SaladDay merged commit ab38d58 into main Sep 25, 2026
2 checks passed
@SaladDay
SaladDay deleted the codex/web-add-node 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