Complete the approved SSH bootstrap and self-install paths #72
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Problem and evidence
crates/server/src/install.rs:162-175rejects root-mode installs and installs through an enrolled infraternal agent before reserving a job.docs/DESIGN.md:194-200records root mode, relay mode and MCP completion as missing. The current binary hashosts ... installcommands, butAgentCommandincrates/infraternal/src/main.rs:176+has no self-install command for an infraternal agent, and the server command has noserver installlifecycle subcommand.Recommendation
Complete the owner-approved flow: add
infraternal agent installandinfraternal server installfor hardened root/system and user/rootless services; have SSH bootstrap upload and verify the configured binary then invoke its self-install path; support both server-held bootstrap SSH and a selected enrolled infraternal agent; finish API/CLI/MCP parity and installed-host SSH settings. Preserve fingerprint Trust, durable retry, path ownership, enrollment consumption and audit behavior.Payoff and estimate
Completes the approved host onboarding path and makes root/rootless and remote installation behave consistently. Estimate: 5–10 engineering days including tests and security review. The 24 install-core commits across 33 files in the report show lifecycle breadth, not person-hours.
Priority: Next milestone.
2026-10-04 owner decisions: Direct match to DECISIONS §30 and the owner's 2026-10-04 decision to add self-install commands and make SSH bootstrap call them. The report's suggestion to reopen a manual-enrollment-first release cut is already superseded by that approval. Install is a security surface and needs Sol-tier implementation/review.
Report: arch-review report
Source: arch-review 2026-10-04
Starting self-install-merge on self-install at
5b5cf987fc; merging dev87bb5bd2b7. Retain network/key SSH auth and pins with delegated infraternal agent install/uninstall. Requested checks only; no push.Conflict reconciliation: kept dev decisions §§31–43 and renumbered self-install to §44. Retained banner detection, none-auth admission, explicit trust, auth override and exact pin checks. InstallRemote now combines the fixed per-job auth with delegated install token delivery; start only confirms readiness; removal delegates uninstall using the same auth. Worker fake records auth through every remote operation. Replaced the obsolete dummy-binary linger regression with real compiled-CLI reenrollment checks in the full integration scenario, and run that scenario against both real OpenSSH key auth and a loopback russh none-auth server executing as sshtarget. The loopback server records offered methods, so the complete network installation asserts no public key was offered. Updated stale install/start documentation after the textual auto-merge. No new hot path.
Conflict reconciliation: kept dev decisions §§31–43 and renumbered self-install to §44. Retained banner detection, none-auth admission, explicit trust, auth override and exact pin checks. InstallRemote now combines the fixed per-job auth with delegated install token delivery; start only confirms readiness; removal delegates uninstall using the same auth. Worker fake records auth through every remote operation. Replaced the obsolete dummy-binary linger regression with real compiled-CLI reinstall checks in the full integration scenario, and run that scenario against both real OpenSSH key auth and a loopback russh none-auth server executing as sshtarget. The loopback server records offered methods, so the complete network installation asserts no public key was offered. Updated stale install/start documentation after the textual auto-merge. No new hot path.
Network SSH can omit pam_systemd and XDG_RUNTIME_DIR. Install, readiness and removal now preserve an existing runtime path or use /run/user/; the loopback fixture intentionally has no PAM session or runtime environment, so it tests that fallback. Source: https://www.freedesktop.org/software/systemd/man/latest/pam_systemd.html . Initial clippy found items_after_statements in the new test import; fixed by moving it to module imports. Install suite passed: cargo test: 56 passed, 4 ignored, 295 filtered out (15 suites, 8.34s).
Real network installation exposed two PAM-less startup issues in delegated self-install: show-user fails when no logind user object exists, and enable-linger starts its manager asynchronously. Self-install now confirms absent users through a successful live list-users query (malformed listing or failed bus queries fail closed), then waits up to ten seconds for a real user-manager bus reply before daemon-reload. Environment replies are discarded without logging. The same readiness helper serves server and infraternal agent installation. Sources: https://github.com/systemd/systemd/blob/main/src/login/loginctl.c and https://github.com/systemd/systemd/blob/main/man/loginctl.xml .
The expanded ignored compiled-binary test now passes both OpenSSH key mode and loopback network none mode, each with real sshtarget systemd service, enrollment, mTLS tunnel, inventory and delegated uninstall. Network mode authorizes no install key and asserts no publickey attempt. Linger ownership failure/reinstall/removal coverage was moved here from the obsolete dummy-binary bootstrap test. Latest output:
sshtarget authorized_keys restored using sudo -n cp -a; sudo -n cmp returned exit 0. Final-source clippy and verify fast are running. No merge gate or push.
Final-source fast gate failed in unchanged crates/server/src/stream.rs timing coverage; the initial run passed. The final run warned load5 above the 8 online CPUs. No test changes made. Rerunning the same required gate. Exact failure excerpt:
Merged
dev(87bb5bd2b7) intoself-install(base5b5cf987fc). Head:bc828c8b3cde57c2f7f3533131039d22f6cf1eb1. Nothing pushed.Conflict resolutions:
DECISIONS.md: retained dev §§31–43 and appended the self-install decision as §44.crates/server/src/install.rs: retained dev's connect/banner/auth/host-key flow and self-install's token mint/delivery/enrollment during Install. Start confirms service readiness. Pass job.auth through all delegated operations and retries.crates/server/src/install_bootstrap.rs: combined auth selection/error classification with delegatedagent install/agent uninstall, preserving exact pins and ownership checks. The obsolete dummy-binary linger test was moved into the compiled CLI integration scenario. Network loopback upload/refusal coverage remains.crates/server/src/install_worker_tests.rs: token-delivery/enrollment hooks remain on Install; the fake records auth on install, start, upload, observe, probe and remove. Existing network/key override, retry, authorization-loss and host-key tests retained.Fresh PAM-less network SSH needed three setup fixes: runtime-directory fallback before delegated service operations; successful live logind listing to distinguish an absent user object from bus errors; bounded user-manager readiness after enabling linger. The shared CLI readiness helper serves both server and infraternal agent installation. No new hot path. Sources: pam_systemd, loginctl source, loginctl manual source. DESIGN and contracts now describe delegated step ordering and auth behavior.
Tests:
cargo clippy --workspace --all-targets -- -D warnings: passed.cargo test -p infraternal-server install:cargo test: 56 passed, 4 ignored, 295 filtered out (15 suites, 8.34s).cargo test -p infraternal-server install -- --ignored: four real OpenSSH tests passed (trust, atomic upload, ownership fencing and convergent cleanup).cargo test -p infraternal-server real_network_auth -- --nocapture: two loopback tests passed (none-auth upload/removal, refusal and key-mode auth exclusivity).cargo test -p infraternal --test agent_install -- --ignored: passed, running the full installation scenario sequentially in both key and network modes. Both install a real sshtarget user service, enroll, establish mTLS, expose inventory, exercise linger ownership failure/reinstall and delegate uninstall. Network mode adds no install key and records no publickey attempt.sudo -n cp -aauthorized_keys backup restored withsudo -n cp -a;sudo -n cmppassed (exit 0).Gate: final-source
INFRATERNAL_VERIFY_RUN_ID=self-install-merge scripts/verify fastpassed all 19 stages in 380.861s (exit 0). No verify merge was run.Exact targeted test outputs:
install-ignored:network:real-install:clippy:An earlier final-source fast run failed in the unchanged
stream::tests::contended_native_close_fence_preserves_original_watcher_deadlinetest (native dispatch did not reach the database barrier by C+650: Elapsed(())) under a load warning. The same gate passed on rerun without changing any test or source. The existing cookie@0.6.0 low-severity advisory remains report-only. No new benchmark or performance claim: all additions are setup work.Exact final gate output:
Exact gate summary:
Final cleanup: the shared authorized_keys file changed again during the later gate run after the earlier successful restoration. No install test process remained active. Restored the job-start backup again with sudo -n cp -a and repeated sudo -n cmp successfully (exit 0). Head
bc828c8b3c; worktree clean; no push. Full report: /mnt/hdd/infraternal/jobs/self-install-merge/result.md.Starting read-only final self-install review, issue #72. Worktree review-self-install; detached HEAD
bc828c8b3c(self-install); diff base87bb5bd. Scope: generated units, context/upgrade/uninstall, SSH bootstrap delegation and auth, server local infraternal agent behavior, OPERATOR docs. Requested debug/sccache install tests and systemd-analyze only; no verify merge, no commits.Verdict: do not merge.
Review of
87bb5bd...bc828c8, HEADbc828c8b3cde57c2f7f3533131039d22f6cf1eb1, detached self-install worktree. Read-only source review; no commits. Verification is in progress; final evidence is appended below.Major — a server upgrade silently changes the database and configuration instead of reusing the installation.
crates/infraternal/src/self_install.rs:903always callsresolve_databasewith the newly parsed CLI arguments; absent--databaseselects the context default at lines 175–182. The savedserver.databasepath is read only by uninstall (line 970), never install. Installation then overwrites the unit and saved database record (lines 935–940). Listener, public origin, tunnel and--no-local-agentalso come from newly parsed defaults. Following OPERATOR.md:250–251 (server installagain from the new binary) after an installation with a custom database switches to a new database and fresh CA/signing/SSH identities (server/src/lib.rs:445–455, 490–496, 558–563), leaving the actual database stranded and replacing the record needed to purge it. A server-only deployment also silently enables the local infraternal agent. Preserve saved configuration when options are absent, or fail before writes and require explicit complete upgrade settings; correct the upgrade documentation and add regression coverage.Minor — system database paths containing
$are escaped with the ExecStart rules in ReadWritePaths.crates/infraternal/src/self_install.rs:889callssystemd_quoteforReadWritePaths, andcrates/agent/src/systemd.rs:108doubles$. For/srv/$cache/db.sqlite3, ExecStart correctly uses/srv/$$cache/db.sqlite3, but the sandbox allow-list incorrectly names/srv/$$cache. systemd only performs the dollar environment expansion for command lines; ReadWritePaths takes literal paths. This can leave the actual database unwritable or make the mount namespace fail. Use directive-specific path quoting. Primary documentation: systemd.service command-line expansion, systemd.exec ReadWritePaths. Normal default paths are unaffected.Minor — the requested revocation-on-cleanup-failure criterion conflicts with the current contract.
crates/server/src/install.rs:575–595returnsssh_errorimmediately if remote removal fails; identity revocation and tunnel shutdown at lines 599–621 are skipped. Thus a partially removed host retains a live identity. This is pre-existing behavior, explicitly promised by contracts §8 and OPERATOR.md:186–188 (nothing revoked on cleanup failure), so it is not classified as a new implementation blocker under the instruction that these documents override the review prompt. The requested assertion does not hold. Reconcile the desired safety rule with the contract before claiming it passes. The testremoval_revokes_identity_enrolled_before_the_timeline_observed_itcovers a failed install followed by successful cleanup, not cleanup failure.Verdict: do not merge.
Review of
87bb5bd...bc828c8, HEADbc828c8b3cde57c2f7f3533131039d22f6cf1eb1, detached self-install worktree. Read-only source review; no commits. Verification is in progress; final evidence is appended below.Major — a server upgrade silently changes the database and configuration instead of reusing the installation.
crates/infraternal/src/self_install.rs:903always callsresolve_databasewith the newly parsed CLI arguments; absent--databaseselects the context default at lines 175–182. The savedserver.databasepath is read only by uninstall (line 970), never install. Installation then overwrites the unit and saved database record (lines 935–940). Listener, public origin, tunnel and--no-local-agentalso come from newly parsed defaults. Following OPERATOR.md:250–251 (server installagain from the new binary) after an installation with a custom database switches to a new database and fresh CA/signing/SSH identities (server/src/lib.rs:445–455, 490–496, 558–563), leaving the actual database stranded and replacing the record needed to purge it. A server-only deployment also silently enables the local infraternal agent. Preserve saved configuration when options are absent, or fail before writes and require explicit complete upgrade settings; correct the upgrade documentation and add regression coverage.Minor — system database paths containing
$are escaped with the ExecStart rules in ReadWritePaths.crates/infraternal/src/self_install.rs:889callssystemd_quoteforReadWritePaths, andcrates/agent/src/systemd.rs:108doubles$. For/srv/$cache/db.sqlite3, ExecStart correctly uses/srv/$$cache/db.sqlite3, but the sandbox allow-list incorrectly names/srv/$$cache. systemd only performs the dollar environment expansion for command lines; ReadWritePaths takes literal paths. This can leave the actual database unwritable or make the mount namespace fail. Use directive-specific path quoting. Primary documentation: systemd.service command-line expansion, systemd.exec ReadWritePaths. Normal default paths are unaffected.Minor — the requested revocation-on-cleanup-failure criterion conflicts with the current contract.
crates/server/src/install.rs:575–595returnsssh_errorimmediately if remote removal fails; identity revocation and tunnel shutdown at lines 599–621 are skipped. Thus a partially removed host retains a live identity. This is pre-existing behavior, explicitly promised by contracts §8 and OPERATOR.md:186–188 (nothing revoked on cleanup failure), so it is not classified as a new implementation blocker under the instruction that these documents override the review prompt. The requested assertion does not hold. Reconcile the desired safety rule with the contract before claiming it passes. The testremoval_revokes_identity_enrolled_before_the_timeline_observed_itcovers a failed install followed by successful cleanup, not cleanup failure.Major — SSH removal can delete a binary still required by a co-installed server. Self-uninstall deliberately preserves the shared executable while
infraternal-server.serviceexists (self_install.rs:731–732). In contrast,ROOTLESS_REMOVE_SCRIPTunconditionally requires that binary to disappear (install_bootstrap.rs:708–709). With both services installed, the first removal stops/removes the infraternal agent unit, preserves the executable for the server, and then fails with exit 69 before releasing the bootstrap ownership marker or revoking the identity. A retry now takes the no-unit branch and unconditionally deletes the shared executable (install_bootstrap.rs:701), even though the server unit still exists. The running server loses its restart/upgrade executable. This contradicts the shared-binary and last-service ownership logic introduced in this feature. Apply the server-service ownership check both to fallback deletion and to the post-uninstall absence checks; test coexistence plus retry after partial removal. No systemd unit needs to be launched to establish the fallback deletion in an isolated filesystem fixture.Verdict: do not merge.
Review of
87bb5bd...bc828c8, HEADbc828c8b3cde57c2f7f3533131039d22f6cf1eb1, detached self-install worktree. Read-only source review; no commits. Verification completed; final evidence is appended below. Two majors block merge; the two minors do not.Major — a server upgrade silently changes the database and configuration instead of reusing the installation.
crates/infraternal/src/self_install.rs:903always callsresolve_databasewith the newly parsed CLI arguments; absent--databaseselects the context default at lines 175–182. The savedserver.databasepath is read only by uninstall (line 970), never install. Installation then overwrites the unit and saved database record (lines 935–940). Listener, public origin, tunnel and--no-local-agentalso come from newly parsed defaults. Following OPERATOR.md:250–251 (server installagain from the new binary) after an installation with a custom database switches to a new database and fresh CA/signing/SSH identities (server/src/lib.rs:445–455, 490–496, 558–563), leaving the actual database stranded and replacing the record needed to purge it. A server-only deployment also silently enables the local infraternal agent. Preserve saved configuration when options are absent, or fail before writes and require explicit complete upgrade settings; correct the upgrade documentation and add regression coverage.Minor — system database paths containing
$are escaped with the ExecStart rules in ReadWritePaths.crates/infraternal/src/self_install.rs:889callssystemd_quoteforReadWritePaths, andcrates/agent/src/systemd.rs:108doubles$. For/srv/$cache/db.sqlite3, ExecStart correctly uses/srv/$$cache/db.sqlite3, but the sandbox allow-list incorrectly names/srv/$$cache. systemd only performs the dollar environment expansion for command lines; ReadWritePaths takes literal paths. This can leave the actual database unwritable or make the mount namespace fail. Use directive-specific path quoting. Primary documentation: systemd.service command-line expansion, systemd.exec ReadWritePaths. Normal default paths are unaffected.Minor — the requested revocation-on-cleanup-failure criterion conflicts with the current contract.
crates/server/src/install.rs:575–595returnsssh_errorimmediately if remote removal fails; identity revocation and tunnel shutdown at lines 599–621 are skipped. Thus a partially removed host retains a live identity. This is pre-existing behavior, explicitly promised by contracts §8 and OPERATOR.md:186–188 (nothing revoked on cleanup failure), so it is not classified as a new implementation blocker under the instruction that these documents override the review prompt. The requested assertion does not hold. Reconcile the desired safety rule with the contract before claiming it passes. The testremoval_revokes_identity_enrolled_before_the_timeline_observed_itcovers a failed install followed by successful cleanup, not cleanup failure.Major — SSH removal can delete a binary still required by a co-installed server. Self-uninstall deliberately preserves the shared executable while
infraternal-server.serviceexists (self_install.rs:731–732). In contrast,ROOTLESS_REMOVE_SCRIPTunconditionally requires that binary to disappear (install_bootstrap.rs:708–709). With both services installed, the first removal stops/removes the infraternal agent unit, preserves the executable for the server, and then fails with exit 69 before releasing the bootstrap ownership marker or revoking the identity. A retry now takes the no-unit branch and unconditionally deletes the shared executable (install_bootstrap.rs:701), even though the server unit still exists. The running server loses its restart/upgrade executable. This contradicts the shared-binary and last-service ownership logic introduced in this feature. Apply the server-service ownership check both to fallback deletion and to the post-uninstall absence checks; test coexistence plus retry after partial removal. No systemd unit needs to be launched to establish the fallback deletion in an isolated filesystem fixture.Independent verification evidence
All final commands exited 0. Builds used the supplied preset:
RUSTC_WRAPPER=/home/kayg/.local/bin/sccache,SCCACHE_DIR=/mnt/hdd/infraternal/sccache,CARGO_PROFILE_DEV_DEBUG=0,CARGO_PROFILE_TEST_DEBUG=0,CARGO_INCREMENTAL=0, dedicated target/home/kayg/.cache/infraternal-targets/review-self-install. Cargo used its unoptimized test/debug profile; no release build and noverify merge.The first server test attempt exited 101 because this fresh worktree had no embedded web build. Ran
bun install --frozen-lockfileandscripts/build-websuccessfully, then reran the tests. No tracked files changed.cargo test -p infraternal-server install— exit 0,server-install-rerun.log:cargo test -p infraternal-server install -- --ignored— exit 0,server-install-ignored.log:cargo test -p infraternal --bin infraternal install— exit 0,cli-install.log:cargo test -p infraternal --test self_install— exit 0,cli-self-install.log:cargo test -p infraternal --test agent_install -- --ignored— exit 0,agent-install-ignored.log:cargo test -p infraternal-agent systemd— exit 0,unit-generator.log:The ignored
agent_installtest runs the complete trust/enrollment/tunnel/inventory/removal scenario twice: OpenSSH key authentication on 127.0.0.1:2222, then a real loopback russh server accepting only SSHnonewith exec under sshtarget. The network fixture is not a live NetBird/Tailscale peer. Both use the real compiled binary and sshtarget systemd user manager. They exercise linger ownership failure/retry and reinstall with the existing identity, and assert that the join-token file disappears and the confirmed host pin is present. Source delivery usesumask 077plus a privatemktemptoken file; the CLI refuses group/other-readable token files. Generated units and SSH argv carry only the token-file path. Server default/--with-agentversus--no-local-agentselection was verified through parsing, generated units and existing runtime wiring; no extra standalone server unit was started.Explicit unit verification and safe filesystem fixture checks (
check-fixtures.py,fixtures.log):The four units were obtained from the actual CLI dry-run in root/user contexts; only their ExecStart binary path was redirected to the built executable for verification, matching the existing unit test. Unit contents are retained under
units/. All previous rootless hardening directives remain, and system units render the same canonicaldeploy/o2/infraternal.servicesandbox with service-specific path replacements. The$sandbox-path result is a rendering/directive-semantics finding; no additional system unit was started to exercise mount setup.The coexistence fixture executes the actual production removal script against an isolated directory with the real compiled binary and a generated server unit, representing a retry after the infraternal agent unit has gone. It confirms deletion of the shared binary while the server unit survives; it substitutes no systemctl/loginctl implementation and starts no service.
Uninstall's direct shared-binary check and last-user-service linger check are correct; the SSH fallback/check divergence is finding 4. Standalone infraternal agent uninstall preserves identity by default and purges its fixed data directory with
--purge. Server purge follows its advertised database-only semantics (database plus SQLite sidecars); auxiliary CA/signing/SSH files are retained. This review added no hot path, and no performance measurements are claimed.Authorized keys were backed up with
sudo -n cp -abefore tests and restored withsudo -n cp -aafterward. Actual restoration check:Restored file and backup both have mode 0600 and ownership sshtarget:sshtarget. Key contents were never printed. Final HEAD remains
bc828c8b3cde57c2f7f3533131039d22f6cf1eb1;/usr/bin/git status --shortis empty. No source edits, commits or pushes. Issue #72 has the start and findings comments; this final report is posted as the finish evidence. The author reports were not used to derive these independent findings.Starting self-install-fix on branch
self-install, basebc828c8b3cde57c2f7f3533131039d22f6cf1eb1. Read the complete independent review. Scope: preserve server upgrade configuration/unit settings and prevent SSH removal/retry deleting a co-installed server executable; regression tests and the safe directive-quoting minor. Cleanup-failure revocation remains governed by contracts §8. No merge gate or push.Regression evidence before fixes:
cargo test -p infraternal --test self_installagainst baseline self-install implementation: 1 passed, 3 failed. Tests independently caught custom flags/settings lost, explicit overrides dropping other flags, and unsupported existing flags being silently dropped. Full output:/tmp/self-install-fix-before-cli.log./tmp/self-install-fix-before-removal.log).Implementation decisions: preserve operator unit directives, merge only clap CommandLine value sources (explicit default values count), reject unsupported stored commands before writes, retain installation database record when reinstalling without a unit. Record binary-owner with install id before upload and retain unknown/shared binaries on retries.
$path quoting follows systemd.service and systemd.exec; clap value source uses official clap docs. Minor revocation-on-failed-cleanup remains unchanged because contracts §8 explicitly requires no revocation on failure.Committed fixes on
self-install: server configuration/dollar quoting in3e52408, binary ownership/removal in498b42c667e5278eb9cf83760474de5097438aec. Both commits carry the requested footers. Worktree clean, nothing pushed.Final targeted checks:
Ignored real checks:
The real infraternal-agent install test executes key SSH and network-only SSH; network pass now co-installs an inert server unit and proves successful removal retains the real shared executable and linger while removing ownership records, then uses the product server uninstall for last-service cleanup. Baseline Rust binary-removal regression failed with
server lost its executable; fixed regressions include a real permission-denied cleanup followed by retry and no-op repeated removal. Adjacent server drop-ins and unsupported command/relative/global flags fail before writes instead of guessing the effective database. Clippy with-D warningspassed. No new hot path or performance claims.Final gate currently running:
INFRATERNAL_VERIFY_RUN_ID=self-install-fix scripts/verify fast. No merge gate. Evidence retained under/mnt/hdd/infraternal/jobs/self-install-fix/verification.Head:
498b42c667e5278eb9cf83760474de5097438aec. Branchself-install; basebc828c8b3cde57c2f7f3533131039d22f6cf1eb1. Two commits,3e52408(server configuration and directive quoting) and498b42c(binary ownership and cleanup), with the requested Co-Authored-By and Claude-Session footers. Nothing pushed; no merge gate.Major: server upgrades reset the database and settings. The installer reads the existing unit, merges only explicitly supplied CLI values (including explicit default values and
--with-agent), preserves other service directives, and reuses the saved database record when the unit is absent. Dry-run shows removed/added command lines and the proposed unit, redacting environment/credential values. Unsupported commands, flags, relative paths, global CLI flags and adjacent drop-ins fail before writes. Database changes retain operator sandbox allowances; no absent flag silently resets the installation. Tests:server_upgrade_preserves_configured_flags_and_service_settings,server_upgrade_changes_only_explicit_flags_including_default_values,server_upgrade_refuses_unsupported_existing_command_before_writes,server_reinstall_reuses_database_record_when_unit_is_absent, andserver_upgrade_refuses_adjacent_dropins_before_writes. The first three failed against the original implementation; all pass after the fix. Unit preservation coverage is CLI dry-run in an isolated home, not a live custom-database server upgrade.Minor: dollar signs were doubled in
ReadWritePaths. A shared directive-specific path quoting helper retains literal dollars, while command-line quoting continues to double them. The installer also corrects the old generated dollar directive during reruns without discarding extra operator allowances. Test:server_database_dollar_path_is_literal_in_the_sandbox_directive; all five actual CLI-rendered user/system/dollar fixtures passedsystemd-analyze verify. Directive behavior was checked in the primary systemd.service and systemd.exec documentation. Explicit flag provenance uses the official clap ArgMatches docs; adjacent drop-in handling follows systemd.unit.Minor left unchanged: revocation on cleanup failure conflicts with contracts §8 and the operator guide. Failed remote cleanup still keeps the identity live and the job removable/retryable; successful cleanup revokes it. This report does not claim the conflicting revocation-on-failure criterion passes. Changing it requires an owner decision and corresponding contract change.
Major: SSH removal retries deleted the executable needed by a co-installed server. Bootstrap now records binary ownership per install id before upload. Self-uninstall and fallback cleanup preserve the executable while a server unit exists, including a dangling symlink, and do not delete an executable with missing/mismatched ownership. Delegation to an older executable is refused without a matching ownership record. Partial cleanup retains both ownership records for retries; after verified cleanup, matching records are released even when the shared executable stays for the server. Direct CLI plans/removal and static server logs explain retained binaries without logging remote output. Tests:
removal_retry_keeps_a_coinstalled_server_binary(real permission-denied cleanup, then retry and repeated removal),removal_keeps_a_binary_without_matching_installation_ownership(unknown owner plus installed-unit refusal), andstandalone_uninstall_requires_binary_ownership_and_preserves_server_symlinks. The baseline Rust retry test failed withserver lost its executable; the baseline production filesystem script also deleted the binary while leaving the server unit. The ignoredrootless_install_trust_inventory_and_remove_over_real_sshdtest runs key authentication and network-only SSH; the network pass now seeds a co-installed inert server unit and proves real delegated uninstall retains the compiled binary and linger, releases bootstrap ownership, and then converges through product server uninstall. No server service is launched by that coexistence fixture.Final targeted test and fixture output:
Ignored real checks:
cargo test -p infraternal-agent systemdalso passed (1 test). Final targeted clippy with-D warningspassed.authorized_keyswas backed up withsudo -n cp -a, restored withsudo -n cp -a, and compared withsudo -n cmp; restoration and final comparison exited 0. Contents were never printed. The first standalone unit verification fixture needed its temporary user install path redirected to the built executable; after that fixture correction every unit verified. No new runtime hot path, benchmark requirement or performance claim is introduced. The fast gate's notices generator removed an unrelated jiti license entry; the original committed notices were retained because this job changes no dependencies, and its generated diff is retained as evidence.Final gate:
INFRATERNAL_VERIFY_RUN_ID=self-install-fix scripts/verify fast— exit 0, all 19 stages passed. Full logs and generated unit fixtures are retained underverification/beside this report. Noverify mergewas run. Worktree is clean; final authorized_keys comparison also exited 0. The low-severity cookie@0.6.0 advisory was report-only.Gate output quoted verbatim:
Starting targeted independent re-review at detached HEAD
498b42c667e5278eb9cf83760474de5097438aec, basebc828c8b3cde57c2f7f3533131039d22f6cf1eb1. Scope: both prior majors, regression tests, install tests including ignored real SSH checks, and systemd-analyze verify. Read-only source review; no commits, pushes, release builds or verify merge. SSH authorized_keys will be backed up and restored with cp -a and compared.Diff inspection at
498b42cconfirms saved server arguments are parsed and merged before writes, and binary ownership/server-unit checks apply to delegated uninstall, fallback cleanup, and post-cleanup verification. Regression tests seed every configured server argument; cleanup retry injects a real permission failure and asserts the marker and shared executable survive, then retries twice. Install verification is still running using debug+sccache; final verdict awaits actual output. No blocker or major identified so far. Cleanup-failure revocation remains the contract-defined deferred owner decision.New major found at
498b42c:plan_unit_line(crates/infraternal/src/self_install.rs:1068–1082) redacts only physical lines whose own key is Environment/SetCredential/SetCredentialEncrypted. The dry-run renderer (1233–1253) prints continuation lines unchanged. A systemd-valid multiline Environment directive verified with exit 0, andserver install --user --dry-runexited 0 while printing the continuation placeholder. Only inert review placeholders were used; no actual secret was accessed or printed. Evidence:check-redaction.py,redaction-original.service,redaction-plan.txt. Primary systemd documentation explicitly permits continued directives: https://raw.githubusercontent.com/systemd/systemd/main/man/systemd.syntax.xml . Existing secret-valued continued environment/credential directives can therefore enter captured CLI logs during the recommended upgrade dry-run. This is introduced by preserving and printing existing unit contents; it violates CLAUDE.md’s prohibition on printing credentials. Redact complete logical directives including continuations (and their comments), or refuse these directives before rendering; add placeholder regression coverage. Both original majors independently reproduce as fixed incheck-fixtures.py; all five generated units verify. Final tests still running. Verdict will be do not merge because of this new major.Verdict: do not merge.
Targeted independent re-review of
bc828c8..498b42c, detached HEAD498b42c667e5278eb9cf83760474de5097438aec, issue #72. Both original majors are resolved. One new major blocks merge. Source review is read-only; author statements were treated as claims and checked against the diff, tests and independent fixtures.Major — upgrade dry-run discloses continued environment/credential values.
crates/infraternal/src/self_install.rs:1070redacts only a physical line whose own key isEnvironment,SetCredentialorSetCredentialEncrypted. The new existing-unit renderer at lines 1233–1253 prints every following physical line separately, so a value on a continuation line is printed unchanged. A valid existing server unit containingEnvironment="REVIEW_PLACEHOLDER=first" \followed by a second environment assignment with an inert sentinel passedsystemd-analyze verify;server install --user --dry-runsucceeded and exposed that sentinel in stdout. No actual credentials were used. Seecheck-redaction.py,redaction-original.serviceandredaction-plan.txtbeside this report. This is new behavior: the previous installer printed its generated unit, while the fix prints the operator's existing directives. The documented upgrade dry-run can now copy secret environment/credential values into captured CLI output, violating the operating contract's no-credential-output rule. Redact entire logical directives, including continuations across comment lines, or refuse unsupported sensitive directive syntax before rendering. Add inert-placeholder regression coverage proving that continued values never enter either the proposed unit display or diff. Systemd explicitly joins backslash-continued lines and ignores intervening comment blocks: official systemd.syntax source.Resolved — server upgrades reset configuration. The existing unit is parsed at
self_install.rs:925, explicit CLI provenance controls the merge at line 1016, and configuration resolution finishes at line 1120 before any write at line 1257. Database record fallback covers a missing unit. Unfamiliar saved commands/flags, relative saved paths and adjacent drop-ins refuse the upgrade. Operator directives are preserved. The CLI integration regressions seed a custom database (including escaped dollars/percent and spaces), every saved server flag and custom service settings; omission must retain these, while explicit defaults/--with-agentoverride only their selected fields. Unsupported-command and adjacent-drop-in cases must fail without changing the fixture. These assertions exercise the original reset: its unconditional default resolution could not produce the expected saved arguments. My independent fixture generated a custom unit through the compiled CLI, then upgraded with no flags and confirmed retained database/listener/origin/local infraternal agent selection and operator directives. Dry-run and installation use the same merged unit and database value. This is rendering/configuration-path coverage, not a live custom-database server restart.Resolved — SSH removal retries delete the co-installed server binary.
install_bootstrap.rs:698–761preserves the executable for a server unit, including a dangling symlink, in both fallback deletion and post-uninstall checks. It only deletes a matching owned executable and releases matching records after verifying cleanup. Delegated self-uninstall applies the same server and ownership checks (self_install.rs:738–759).removal_retry_keeps_a_coinstalled_server_binaryexecutes the production script with a real permission-denied directory, checks both ownership records and the executable after failure, restores permissions, then repeats removal twice. The ownership regression tests additionally retain unowned/mismatched binaries and refuse unsafe delegation. My independent fixture exercised that failure/retry with the real compiled executable; the current script retained it and released both records. Running the baseline script against the same isolated shared-server retry fixture deleted the executable while leaving the server unit, independently confirming the original failure. The ignored real CLI test also covers delegated uninstall with a co-installed inert server unit, retention of the real executable and linger, and release of bootstrap ownership. No co-installed server service was started.Non-blocking owner recommendation — cleanup failure and revocation. The retained behavior matches contracts §8: cleanup failure leaves the identity valid, records no terminal removal, and permits convergent cleanup retry. This avoids turning a still-installed infraternal agent into a service repeatedly restarting with a refused identity, but also leaves its authenticated tunnel available until cleanup succeeds. Keep this contract for this change; the owner should decide separately whether explicit emergency revocation should be available while retaining a retryable cleanup job. Bootstrap SSH credentials and certificate identity are separate, so that decision can preserve SSH cleanup retry. This is a deferred policy choice, not a blocker or an asserted revocation-on-failure test pass.
The previous dollar-path minor is also fixed: filesystem directive quoting preserves a literal dollar while ExecStart escapes it. The dedicated regression passes, and the actual CLI-generated dollar-path unit verifies. Official systemd.service expansion rules, filesystem directive documentation, and clap value_source documentation support the reviewed quoting and explicit-override semantics.
Verification evidence follows. No runtime hot path was added; no performance measurements are claimed. No source changes, commits, pushes, release builds or
verify merge.All six targeted test commands exited 0. Debug/test builds used
RUSTC_WRAPPER=/home/kayg/.local/bin/sccache,SCCACHE_DIR=/mnt/hdd/infraternal/sccache,CARGO_PROFILE_DEV_DEBUG=0,CARGO_PROFILE_TEST_DEBUG=0,CARGO_INCREMENTAL=0, and dedicatedCARGO_TARGET_DIR=/home/kayg/.cache/infraternal-targets/rereview-self-install. This fresh worktree neededbun install --frozen-lockfileandscripts/build-webto populate embedded assets; both succeeded. The Rust builds used the unoptimized debug/test profiles.cargo test -p infraternal-server install— exit 0,server-install.log:cargo test -p infraternal-server install -- --ignored— exit 0,server-install-ignored.log:cargo test -p infraternal --bin infraternal install— exit 0,cli-install.log:cargo test -p infraternal --test self_install— exit 0,cli-self-install.log:cargo test -p infraternal --test agent_install -- --ignored— exit 0,cli-agent-install-ignored.log:cargo test -p infraternal-agent systemd— exit 0,unit-generator.log:Independent CLI-generated unit verification and regression fixtures (
check-fixtures.py,check-redaction.py,fixtures.log):The ignored CLI test runs both OpenSSH key authentication against 127.0.0.1:2222 and a real loopback russh SSH server accepting network-style SSH none authentication, using the compiled binary and sshtarget user manager. It is not a live NetBird/Tailscale peer. User/system unit fixtures were obtained independently from CLI dry-run; only ExecStart binary paths were redirected to the built executable for verify. No service manager was mocked in the removal fixture.
SSH authorized_keys was backed up before tests with
sudo -n cp -a, restored withsudo -n cp -a, and checked withsudo -n cmp. No key contents were printed. Actual final restoration output:Final HEAD remains
498b42c667e5278eb9cf83760474de5097438aec;/usr/bin/git status --shortis empty. No source edits or commits. Issue #72 contains the start, findings and finish evidence; no issue was closed.Starting self-install-fix2: branch
self-install, base HEAD498b42c667e5278eb9cf83760474de5097438aec. Read the complete re-review. Scope: systemd logical directive parsing and shared value-free upgrade output; preserve raw directives, add regressions, rerun install/real tests with authorized_keys backup/restore, systemd verification, andINFRATERNAL_VERIFY_RUN_ID=self-install-fix2 scripts/verify fast. No merge gate or push.Confirmed the re-review cause: physical-line rendering disclosed continued values. Shared logical-line parsing now joins odd trailing backslashes before quoting, skips comment blocks, retains raw spans, and handles whole-item quoting/C escapes (systemd.syntax(7): https://raw.githubusercontent.com/systemd/systemd/main/man/systemd.syntax.xml; parity/blank-line behavior: https://raw.githubusercontent.com/systemd/systemd/main/src/shared/conf-parser.c). Both unit plan/diff paths emit only sensitive directive keys and status, covering EnvironmentFile and all Credential directives too; no referenced file is read. The managed infraternal agent endpoint output reports presence only. Added preservation/output/error regressions and extended the existing real reinstall test with byte-for-byte continued Environment preservation. No runtime hot path. Review contains no cheap outstanding minors; emergency-revocation policy stays deferred. Tests are in progress.
Fix committed:
7083ac9055453e3493a8e351ab8592e6646d3c03. All targeted commands exited 0. Real reinstall retained the entire modified unit byte-for-byte, including the inert multiline Environment directive. Four generated user/system units and the continued sensitive-directive fixture passed systemd-analyze verify (tests invoke the real executable; fixture additionally requires no diagnostic output). Parser/redaction regression coverage includes continuation comment gaps, quoting/C escapes, backslash parity, duplicate/reset changes and continued values resembling ExecStart. No runtime hot path changed.cargo test -p infraternal-server install:cargo test -p infraternal-server install -- --ignored:cargo test -p infraternal --bin infraternal install:cargo test -p infraternal --test self_install:cargo test -p infraternal --test agent_install -- --ignored:cargo test -p infraternal-agent systemd:Final
INFRATERNAL_VERIFY_RUN_ID=self-install-fix2 scripts/verify fastis running. No merge gate and no push.First fast attempt stopped at Clippy (exit 101): new doc comments needed Markdown formatting, a redundant closure, equality assertions, and the expanded infraternal agent install function crossed the 100-line lint. Fixed these without weakening diagnostics: shared the full unit presentation boundary and existing-unit reader; sensitive-byte assertions use equality methods so failures cannot print fixture contents. The shared reader retains the server's existing dangling-symlink refusal for both installers; a new CLI regression verifies refusal before writes.
cargo clippy --workspace --all-targets -- -D warningsnow exits 0. Re-running CLI install and real tests before the final fast attempt. Initial failure output preserved injobs/self-install-fix2/evidence/verify-fast-first.logandclippy-initial.log.Completed self-install-fix2 (#72) on branch
self-install.HEAD:
1a733e9eb681fa82617c910d8e39a14140b7264a; base:498b42c667e5278eb9cf83760474de5097438aec. Worktree clean. Two local commits; neither pushed. Both commit messages include the requested co-author and session trailers.Both install upgrade plans now parse complete logical systemd directives, including odd trailing-backslash continuations across comments, whole-item quoting and C escapes. Source references: systemd.syntax(7) and systemd's configuration parser. Shared presentation emits only sensitive directive keys and added/removed/changed/unchanged status; Environment, EnvironmentFile, UnsetEnvironment and all Credential directives are covered. Referenced EnvironmentFiles are never opened for the diff. The installer's managed infraternal agent endpoints are displayed only by presence. Unit values and subprocess stderr stay out of install logs and fixed errors.
Upgrade writes retain exact raw directive spans, including continued values and intervening comments. Both installers replace service commands by logical span, preventing continuation values beginning with ExecStart from being mistaken for a command. The real enrolled infraternal agent reinstall regression proves the entire modified unit survives byte-for-byte. Shared inspection refuses dangling operator unit symlinks before writes. DESIGN and code comments document the behavior. No runtime hot path changed; no performance measurements claimed.
All six targeted commands exited 0, with 89 tests passed in total (including five ignored real tests). Exact output:
cargo test -p infraternal-server install:cargo test -p infraternal-server install -- --ignored:cargo test -p infraternal --bin infraternal install:cargo test -p infraternal --test self_install:cargo test -p infraternal --test agent_install -- --ignored:cargo test -p infraternal-agent systemd:The CLI unit test invokes real
systemd-analyze verifyfor all four generated system/user units. The CLI integration regression verifies the continued sensitive-directive fixture and requires zero diagnostics. All passed. CLI regressions capture stdout and stderr with trace logging, including refusal/error paths, and assert no inert private values appear. Diff coverage includes value-only changes, additions, removals and duplicate/reset changes.The ignored CLI test runs real OpenSSH on 127.0.0.1:2222 plus a loopback network-style SSH-none server, with the real sshtarget user service. This is not a live NetBird/Tailscale peer. Builds use the supplied unoptimized debug/test profiles and dedicated target directory.
authorized_keys was backed up with
sudo -n cp -a, restored withsudo -n cp -a, and compared; after a final successful comparison the private backup was removed. No contents printed:Final gate:
INFRATERNAL_VERIFY_RUN_ID=self-install-fix2 scripts/verify fast— exit 0. Actual output follows verbatim. No merge gate was run. The initial Clippy failure and its fixes remain recorded in the issue and evidence logs. Supply-chain generation temporarily omitted jiti from notices; its transient change was restored to the committed file without changing dependencies.The re-review identified no remaining cheap minors; its separate emergency-revocation policy recommendation stays deferred. Issue #72 remains open.
Starting targeted read-only review on detached HEAD
1a733e9eb6, base498b42c667. Scope: diff 498b42c..1a733e9 only, dry-run logical-directive redaction, byte preservation and refactor regressions. Running targeted install tests with sccache/debug profiles and systemd-analyze verify; no commits, pushes or verify merge.Major: the shared unit_lines parser still permits sensitive-value disclosure for systemd-valid inputs. It splits only LF (self_install.rs:1059) and strips BOM only when start == 0 (1062). Real systemd-analyze verify accepts all independent fixtures without warnings. With a later BOM preceding Environment/EnvironmentFile, or CR/NUL separators after RestartSec, both compiled CLI dry-runs exit 0 and stdout contains the inert placeholder. The new infraternal agent upgrade also combines ExecStart and a following Environment directive separated by CR: its diff exposes the placeholder and the proposed unit drops that Environment directive. This is a regression from displaying only the generated infraternal agent unit, introduced by this diff's existing-unit preservation. Trace stderr did not expose the placeholders. Evidence: /mnt/hdd/infraternal/jobs/rereview2-self-install/check-fixtures.py, fixtures.log and captured plan logs. No actual credentials used.
Fix the shared parser to match systemd's delimiters and BOM handling, or refuse these forms with fixed diagnostics before presentation/writes; add CLI regressions proving redaction and preservation. Systemd primary sources: https://raw.githubusercontent.com/systemd/systemd/main/src/shared/conf-parser.c and https://raw.githubusercontent.com/systemd/systemd/main/src/basic/fileio.c.
Verdict: do not merge.
Targeted read-only review of
498b42c..1a733e9, detached HEAD1a733e9eb681fa82617c910d8e39a14140b7264a, issue #72. One major blocks. No source edits, commits, pushes, release builds, orverify merge.Major — systemd-valid separators and later BOM bypass redaction; the infraternal agent upgrade can also discard an environment directive. The new
unit_linesatcrates/infraternal/src/self_install.rs:1059splits only LF, and at line 1062 strips a UTF-8 BOM only at the start of the file. Systemd accepts CR and NUL separators as well as LF, and its configuration parser removes the first encountered leading BOM even on a later physical line. Consequentlyplan_unit_linesat line 1202 and the ordinary-line diff at line 1262 misclassify sensitive directives as ordinary text.Independent fixtures passed real
systemd-analyze verifywith exit 0 and empty stderr. Both compiled installers' dry-runs exposed an inert placeholder when a later BOM precededEnvironmentorEnvironmentFile, and when CR or NUL separatedRestartSecfromEnvironment. CR-only units also expose environment and inline credential values in the infraternal agent plan. With CR separating an infraternal agentExecStartfromEnvironment, the dry-run diff exposes the environment placeholder and the proposed unit contains no Environment directive:update_installed_unitat line 1339 replaces their combined raw span as one command. Applying that proposal would lose the environment setting. The actual install writes this same proposed string at line 538. No unusual-encoding live service was installed; data loss is established by the actual CLI proposal and write-path source review.This is within the reviewed change: infraternal agent installation now retains and displays an existing unit, whereas the base displayed only its generated unit. The server redaction fix also remains incomplete for these inputs. The fixture stdout establishes disclosure; trace stderr remained free of placeholders. Source fixtures remained byte-identical after every dry-run. See
check-fixtures.py,fixtures.log, andagent-mixed-command-plan.logbeside this report. All values were inert placeholders, never real credentials.Match systemd's physical-line delimiters and BOM handling in the shared parser, or refuse unsupported forms with a fixed diagnostic before rendering or writing. Add CLI regressions covering both presentation and directive preservation. Primary sources: systemd configuration parser, systemd line reader.
The original LF continuation disclosure is fixed for the exercised forms. The shared renderer groups continued lines, ignores intervening comments, redacts Environment/EnvironmentFile/UnsetEnvironment and credential keys, and privately compares ordered duplicate/reset values. Independent continued/quoted/comment/reset fixtures expose no placeholders in either stdout or trace stderr. Adjacent server drop-ins refuse before presentation; infraternal agent drop-in values are not read or printed. Parser errors remain fixed diagnostics, and service-manager subprocess stderr is captured rather than included in install errors.
For ordinary supported syntax, the shared-renderer unit test preserves sensitive raw spans byte-for-byte through atomic writes, and the real SSH reinstall regression preserves the entire modified infraternal agent unit byte-for-byte. Both pass. Existing server configuration/explicit override, unsupported-command, drop-in, dangling-link and binary-ownership tests also pass. No additional major was found in the remaining refactor. No runtime hot path was changed; no performance measurements are claimed.
All six requested targeted test commands exited 0. Builds used the supplied sccache preset:
RUSTC_WRAPPER=/home/kayg/.local/bin/sccache,SCCACHE_DIR=/mnt/hdd/infraternal/sccache,CARGO_TARGET_DIR=/home/kayg/.cache/infraternal-targets/rereview2-self-install,CARGO_PROFILE_DEV_DEBUG=0,CARGO_PROFILE_TEST_DEBUG=0,CARGO_INCREMENTAL=0. Rust builds used debug/test profiles.bun install --frozen-lockfileandscripts/build-websucceeded to supply real embedded assets. These are targeted tests, not a full verification-tier pass.cargo test -p infraternal-server install— exit 0,server-install.log:cargo test -p infraternal-server install -- --ignored— exit 0,server-install-ignored.log:cargo test -p infraternal --bin infraternal install— exit 0,cli-install.log:cargo test -p infraternal --test self_install— exit 0,cli-self-install.log:cargo test -p infraternal --test agent_install -- --ignored— exit 0,cli-agent-install-ignored.log:cargo test -p infraternal-agent systemd— exit 0,unit-generator.log:Real systemd verification ran in the existing
generated_agent_and_server_units_pass_systemd_analyzetest against raw generated user/system units for both modes, and incontinued_environment_fixture_passes_systemd_analyze_verify. Both tests passed. Independent fixtures also invoked the installedsystemd-analyze verifydirectly; each returned 0 with empty stderr. Actual fixture output:The ignored CLI test exercised a real OpenSSH service at 127.0.0.1:2222 and a real loopback SSH server accepting network-style none authentication, enrollment, tunnel/provider readiness, reinstall and removal. It is not a live NetBird/Tailscale peer. The outer runner backed up and restored authorized_keys without displaying its contents, then compared the restored file:
Final HEAD remains
1a733e9eb681fa82617c910d8e39a14140b7264a; tracked worktree status is clean. Findings and finish evidence are recorded in issue #72; the issue remains open.Starting self-install-fix3 on branch
self-install, base1a733e9eb681fa82617c910d8e39a14140b7264a. Read the full rereview2 report. Implementing canonical versioned/hash-verified units, fail-closed inspection and explicit replacement of foreign units; targeted install tests (including real ignored tests), systemd-analyze andINFRATERNAL_VERIFY_RUN_ID=self-install-fix3 scripts/verify fast. No merge gate or push.Design implemented: shared user/system unit renderers seal an LF-only, BOM-free, continuation-free v1 body with a SHA-256 header. Both installers validate header/hash/canonical form and drop-in absence before value parsing or rendering; foreign bytes are discarded after a physical-line count. Dry-run is a hidden-values summary; actual replacement requires --force-replace plus explicit core settings, with no environment/database-record fallback. Optional settings omitted on replacement are disabled. Drop-ins require explicit removal before replacement; a base-file overwrite cannot neutralize effective overrides. All systemd-reported load paths are inspected for unit, dash-prefix and type-wide drop-in directories without reading contents. Primary references: https://raw.githubusercontent.com/systemd/systemd/main/man/systemd.unit.xml and https://raw.githubusercontent.com/systemd/systemd/main/man/systemd-analyze.xml. No runtime hot path changed.
Initial checks: CLI installer unit tests 13 passed; temporary-HOME CLI regressions 12 passed, including foreign BOM/late-BOM/CR/mixed-CR/NUL/invalid-UTF8/continuation/reset/hash-version/manual-edit fixtures and force/drop-in refusal. Unit files remain byte-identical across refused installs and dry-runs. Canonical managed tests preserve directive order and empty resets. Real tests and fast gate still pending.
cargo test -p infraternal-server install— exit 0:cargo test -p infraternal-server install -- --ignored— exit 0:cargo test -p infraternal --bin infraternal install— exit 0:cargo test -p infraternal --test self_install— exit 0:cargo test -p infraternal --test agent_install -- --ignored— exit 0:cargo test -p infraternal-agent systemd— exit 0:Real
systemd-analyze verifypassed ingenerated_agent_and_server_units_pass_systemd_analyze(all four generated user/system units) andcontinued_environment_fixture_passes_systemd_analyze_verify. No simulated systemd result.The real SSH test exercises OpenSSH on 127.0.0.1:2222 and a loopback SSH server with network-style none authentication; it is not a live NetBird/Tailscale peer. It checks canonical byte preservation, refusal of a hand-edited continued/reset unit without changing it, explicit force replacement, and product removal.
Outer runner backed up with
sudo -n cp -a, restored with the same command and compared the file without displaying it:Finished self-install-fix3 on
self-install; HEAD9b67a3a4d2e27e9fadafef69c70fcddf23cec48a. Worktree clean, committed with the requested Claude trailers. No push or merge gate.Design: every shared user/system unit renderer seals a canonical LF-only UTF-8 body with
# infraternal-unit: v1 sha256=<64 lowercase hex digits>. The hash includes all body bytes, comments and final LF. No BOM, control separators or physical continuations. Only a valid header, matching digest, canonical body and absent drop-ins permit value parsing and settings preservation. Unchanged canonical directive spans remain byte-identical, including ordered empty resets; changed bodies are resealed. Foreign bytes are discarded after a physical-line count, with the requested hidden-values diagnostic. Replacement requires --force-replace and explicit core settings, never environment/database-record fallback; omitted optional settings are disabled. Drop-ins must be removed explicitly before replacement because overwriting the base file cannot make its settings effective. Unit-specific, dash-prefix and type-wide directories are checked on systemd-reported load paths without reading contents. The header is an integrity marker, not authentication.Regressions cover BOM/late BOM, CR-only, mixed CR, NUL, continuation with comments and resets (including a matching header/hash on a noncanonical body), manual edits, invalid UTF-8, unknown header versions, local and load-path drop-ins, refused writes, force with missing settings, explicit replacement plans and canonical round trips. Literal server paths round-trip through our serializer/parser. Comments and durable decision/design/format docs match the implementation. No runtime hot path changed or performance measurement claimed.
cargo test -p infraternal-server install— exit 0:cargo test -p infraternal-server install -- --ignored— exit 0:cargo test -p infraternal --bin infraternal install— exit 0:cargo test -p infraternal --test self_install— exit 0:cargo test -p infraternal --test agent_install -- --ignored— exit 0:cargo test -p infraternal-agent systemd— exit 0:Real
systemd-analyze verifypassed ingenerated_agent_and_server_units_pass_systemd_analyze(all four generated user/system units) andcontinued_environment_fixture_passes_systemd_analyze_verify. No simulated systemd result.The real SSH test exercises OpenSSH on 127.0.0.1:2222 and a loopback SSH server with network-style none authentication; it is not a live NetBird/Tailscale peer. It checks canonical byte preservation, refusal of a hand-edited continued/reset unit without changing it, explicit force replacement, and product removal.
Outer runner backed up with
sudo -n cp -a, restored with the same command and compared the file without displaying it:Final gate (same sccache/debug/test preset as targeted tests):
INFRATERNAL_VERIFY_RUN_ID=self-install-fix3 scripts/verify fast— exit 0. Lint findings on earlier attempts were fixed by documenting the renderer assertion and sharing installer options/configuration/context checks; no lint suppression was added. The generated unrelated notices change from the gate was restored to the clean base file before commit. Bun audit reports an existing low cookie finding as report-only; Rust advisory/license checks pass.Verbatim final gate output:
Verbatim gate summary:
Starting read-only final targeted review of
1a733e9..9b67a3a, detached HEAD9b67a3a4d2e27e9fadafef69c70fcddf23cec48a, base1a733e9. Scope: fail-closed unit inspection, canonical integrity/round-trip, drop-ins, install/uninstall and real SSH bootstrap. Will run targeted debug/test-profile install checks with the sccache preset, ignored real tests and systemd-analyze verify; back up/restore/cmp authorized_keys. No commits, pushes, release builds or verify merge.Read-only review progress at detached
9b67a3a4d2e27e9fadafef69c70fcddf23cec48a: shared inspection validates header, exact-body SHA-256 and canonical syntax before either installer receives managed text. Foreign units and drop-in contents have no parsing/presentation path.All 122 independent inert-value checks passed (
check-fixtures.py,fixtures.logbeside the eventual findings): BOM/late BOM, CR/CRLF/mixed CR/NUL, Unicode separators, invalid UTF-8, continuations/comments, stale digest, header version, matching hashes on noncanonical bodies, canonical credential/comment redaction, and unit/dash-prefix/type-wide vendor drop-ins. stdout and trace stderr remained free of fixture private values; all source units remained byte-identical.Server regular/ignored tests, CLI unit/integration tests and the ignored real SSH bootstrap test have passed. Standalone systemd generator tests and the outer authorized_keys restoration/cmp are still pending. No new blocker identified so far.
Verdict: merge.
Final targeted read-only review of
git diff 1a733e9..9b67a3a, detached HEAD9b67a3a4d2e27e9fadafef69c70fcddf23cec48a, Forgejo issue #72. No blockers or majors found. The prior BOM/line-separator disclosure and mixed-CR directive-loss finding is resolved by refusing value inspection of foreign bytes.The shared inspection boundary (
crates/infraternal/src/self_install.rs:1190) validates the first-line v1 header, SHA-256 of the exact body and canonical syntax before either installer receives managed text. Foreign bytes yield only a physical-line count. Unknown headers, body edits with an unchanged header, invalid UTF-8, BOMs, CR/CRLF/NUL, Unicode separators and continuations cannot reach the value parser, plan or diff. The same noncanonical forms remain foreign with a recomputed matching digest. The digest is an edit marker, not authentication; this review does not treat it as a signature.Independent CLI checks in
check-fixtures.pyexercised both service modes with inert private values, trace logging, dry-run, actual refusal and incomplete forced replacement. All 122 checks passed. No private fixture value appeared in stdout or stderr, no source unit changed, and refusal created no installed binary. Canonical credential/environment directives and comments also retained their bytes without exposing their private values. Ordinary canonical nonsecret directives remain visible as specified in DESIGN; foreign units display no directives. Full evidence is infixtures.log.Drop-in inspection (
self_install.rs:1140) reads directory entries only, never contents or filenames into presentation. Unit-specific,infraternal-.service.dandservice.doverrides on an additional vendor load path all refused forced replacement without disclosing values. Repository tests also cover adjacent overrides and a load-path override without any base unit. Foreign replacement requires explicit settings and does not reuse endpoint/environment/database records; optional omitted settings are disabled. Bootstrap does not automatically force replacement.Canonical no-op updates and atomic writes round-trip byte-for-byte. The literal server-command round-trip tests cover quotes, spaces, dollar/percent characters, tabs and BOMs represented through escapes. The ignored real SSH scenario additionally compares the entire installed canonical unit after a real reinstall, refuses a manually edited continued directive without changing the unit, explicitly replaces it with the canonical unit, and removes the installation. Both key and network authentication paths pass; network authentication uses a real loopback SSH server accepting the none method, not a live NetBird/Tailscale peer. Uninstall and shared-binary ownership regressions pass. No new runtime hot path was introduced; no performance measurements or full verification-tier pass are claimed.
All six requested targeted test commands exited 0, using debug/test profiles and the sccache preset:
RUSTC_WRAPPER=/home/kayg/.local/bin/sccache,SCCACHE_DIR=/mnt/hdd/infraternal/sccache,CARGO_TARGET_DIR=/home/kayg/.cache/infraternal-targets/rereview3-self-install,CARGO_PROFILE_DEV_DEBUG=0,CARGO_PROFILE_TEST_DEBUG=0,CARGO_INCREMENTAL=0.bun install --frozen-lockfileandscripts/build-websucceeded to supply real embedded assets.cargo test -p infraternal-server install— exit 0,server-install.log:cargo test -p infraternal-server install -- --ignored— exit 0,server-install-ignored.log:cargo test -p infraternal --bin infraternal install— exit 0,cli-install.log:cargo test -p infraternal --test self_install— exit 0,cli-self-install.log:cargo test -p infraternal --test agent_install -- --ignored— exit 0,cli-agent-install-ignored.log:cargo test -p infraternal-agent systemd— exit 0,unit-generator.log:The installed systemd is
257.13-1~deb13u1.generated_agent_and_server_units_pass_systemd_analyzepassed realsystemd-analyze verifyfor generated user/system units in both modes;continued_environment_fixture_passes_systemd_analyze_verifyalso passed. Independent direct verification accepted the BOM, CR, CRLF, mixed-CR, NUL, continuation and stale-hash fixtures with exit 0 and empty stderr while the CLI hid them. Deliberately invalid UTF-8 fixtures failed systemd verification, and Unicode-separator fixtures produced warnings; the CLI still hid their bytes. Representative actual fixture output:Platform behavior was checked against primary upstream sources: systemd unit/drop-in rules, unit-paths documentation, and systemd v257 continuation parser.
unit-pathsreports compiled/environment-derived paths rather than querying the running manager; the implemented checks match the documented reported-load-path contract.Before tests, the outer runner backed up sshtarget's authorized_keys using
sudo -n cp -a. Its finally block restored usingsudo -n cp -aand compared usingsudo -n cmp, without displaying contents. Actual output:Final HEAD remains
9b67a3a4d2e27e9fadafef69c70fcddf23cec48a; tracked worktree status is clean. No source edits, commits, pushes, release builds, orverify merge. Issue #72 remains open.Starting self-install-merge2: only writer in /mnt/hdd/infraternal/wt-lp/self-install on branch self-install, base
9b67a3a4d2. Merging dev056ef45435after final approval. Preserve self-install behavior; adopt isolated sshd fixtures. Requested verification: workspace clippy with -D warnings, install tests including ignored real tests, systemd-analyze verify, and INFRATERNAL_VERIFY_RUN_ID=self-install-merge2 scripts/verify fast. Will not run verify merge or push.Conflict resolutions: agent_install.rs now uses dev's AccountTestSshd for key auth and keeps the existing private NetworkSshd for network auth, preserving both ordered compiled-binary scenarios and all ownership/header/upgrade checks. Shared authorized_keys backup/append/restore was removed. install_bootstrap.rs retains self-install's delegated CLI implementation and its relocated real linger ownership failure/retry coverage (agent_install.rs); dev's private host-key probe and private account authentication tests were adopted. The obsolete fake-artifact linger test was not restored, because the delegated install now executes the uploaded CLI and requires enrollment. OPERATOR.md combines monitor01 deployment guidance with the self-install instructions; it no longer claims there is no service unit. Production bootstrap implementation is unchanged from self-install. Workspace clippy and requested tests/gate follow.
Workspace clippy passed (exit 0):
cargo clippy --workspace --all-targets -- -D warnings. Verbatim completion:The approved self-install CLI, shared systemd renderer and network-auth fixture are unchanged from
9b67a3a; install_bootstrap.rs differs from that head only inside its test module. Targeted installation tests are now running, including real SSH tests and systemd-analyze verification of all four generated unit variants.Targeted tests: CLI unit tests 12 passed (including systemd-analyze verify of all four unit variants); CLI integration tests 13 passed; shared systemd renderer 2 passed; server installation tests 63 passed with --include-ignored. The first full compiled-binary scenario passed key mode, then network mode failed its install step with the fixed WriteFailed diagnostic. An unchanged rerun passed both modes (1 passed in 42.90s). Suspected fixture lifecycle race: private OpenSSH uses PAM while network SSH deliberately does not; logind releases the prior user object asynchronously. Added a test-only observed logind user-list barrier between the two scenarios, bounded to ten seconds, to enforce a fresh network-auth fixture. No production changes. Will recheck the full scenario and fast gate; retaining the initial failure in the report.
Platform evidence for the fixture barrier: systemd v257 documents UserStopDelaySec as retaining the user record and user@.service after the final session ends (default 10s): https://raw.githubusercontent.com/systemd/systemd/v257/man/logind.conf.xml . The link supports asynchronous teardown; attribution of the initial WriteFailed to that transition remains an inference from its position between key/network scenarios and the unchanged passing rerun. The test waits for absence in loginctl list-users rather than sleeping for an assumed duration or retrying product installation.
Requested fast gate passed (exit 0):
INFRATERNAL_VERIFY_RUN_ID=self-install-merge2 scripts/verify fast. Verbatim gate output:The supply-chain report retains one existing low Bun cookie advisory under the documented report-only policy. No verify merge was run. The full key/network compiled-binary installation scenario has passed 12 consecutive runs with the observed fixture barrier; the 20-run check is still in progress.
Repetition evidence: 14 full key/network runs passed with the new logind barrier. Run 15 failed at the barrier itself (
private SSH fixture left a logind user), before network installation. The initial ten-second bound matched systemd v257's documented default UserStopDelaySec, leaving no teardown margin. Raised only the test isolation timeout to thirty seconds (still polls actual absence every 50ms); no production changes or product retries. Restarting the consecutive repetition check. Source: https://raw.githubusercontent.com/systemd/systemd/v257/man/logind.conf.xml . Fast gate has passed; will rerun it after this final test-only adjustment.Final test-only timeout adjustment verified:
INFRATERNAL_VERIFY_RUN_ID=self-install-merge2 scripts/verify fastpassed (exit 0). Verbatim output:Five consecutive real installation scenarios have passed on the final thirty-second observed isolation bound; continuing to twenty.
Finished self-install-merge2 on branch self-install. Head:
4f4853408290e1fb280d09e01b2a215254db7e72. Merge parents:9b67a3a4d2e27e9fadafef69c70fcddf23cec48aand056ef454356fde7488a207bc1ad735c1b04e6b81. Clean worktree, no push, issue left open.Conflict resolutions:
All requested checks passed. Production self-install CLI, shared v1 header/hash renderer and network-auth fixture remain unchanged from the approved base. The imported dev stream/inventory fixes are included. No new production hot path was added.
Targeted command results (verbatim):
cargo test -p infraternal --bin infraternal self_install -- --nocapturecargo test -p infraternal --test self_install -- --nocapturecargo test -p infraternal-agent systemd -- --nocapturecargo test -p infraternal-server --lib install -- --include-ignored --nocapture --test-threads=1systemd-analyze verifywas actually invoked by the generated-unit test for user/system server and infraternal agent units, and by the continued-line integration fixture. Verbatim test results:Final full real installation check: twenty consecutive runs of
cargo test -p infraternal --test agent_install -- --ignored --nocapture --test-threads=1, each executing key and network installation/removal. Verbatim runner output:Earlier failures are retained in the preceding comments and artifacts: one network install failure before the fixture barrier; then fourteen passing runs followed by a barrier timeout at its initial ten-second limit. The final thirty-second bound passed twenty consecutive runs. The asynchronous logind lifecycle explanation is an inference supported by systemd v257 documentation: https://raw.githubusercontent.com/systemd/systemd/v257/man/logind.conf.xml .
Final requested gate:
INFRATERNAL_VERIFY_RUN_ID=self-install-merge2 scripts/verify fast(exit 0). This includes workspace clippy with-D warningsafter the final edit. Verbatim gate output:Raw verification logs retained at
/mnt/hdd/infraternal/artifacts/verify/self-install-merge2/install. Existing low Bun cookie advisory is report-only; no dependency changes made. Did not run verify merge. Both required commit trailers are present.