Repository navigation
fix: isolate Boat credential brokers per lease - #251
Merged
Merged
Conversation
A Python listener on 127.0.0.1:8765 returned 404 for broker health and caused the auth-run service to fail with canonical broker unavailable. Select a free loopback port for each default lease instead of depending on that shared address; retain the explicit shared-broker override. Cover concurrent default leases with distinct fixture credentials and verify release leaves the other lease usable. Real Boat wake succeeds; remote doctor still requires its stopped job worker and Herdr services to be restored outside this brief's lifecycle authority.
…ide documentation
… poll completion before asserting cleanup. Forced-delay reproduction failed before and passed after; four focused checks, pinned ShellCheck, and diff checks passed. Full suite stopped at a separate timeout whose isolated rerun passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Repair the Boat second mate's wake path so it can take routed work again. The captain chose fixing Boat first after the main Firstmate could not route builds there. This changes Firstmate shared tracked code; follow firstmate-coding-guidelines. The main home is
/Desktop/firstmate and the existing secondmate is boatmate (SSH alias boat-boatmate). Observed failure: an initial remote-doctor SSH connection timed out while the sandbox was suspended; fm-compute-wake.sh boatmate then failed after about 58 seconds with credential acquisition did not become ready; compensation confirmed. Find and fix the root cause from concrete logs, the auth-run service journal, and endpoint facts, not speculation. Cover the actual failure mode with a regression using existing bin/tests conventions. Do not merely suppress the error or weaken readiness.\n\nProven root cause and implementation decision: auth-run unit fm-boat-61eff1a1e9791eacdd85-9aa78d4f5cdec5e28a5c7ca5ea398737.service logged canonical broker unavailable at 2026-10-15 21:19:37 +0800. The workstation's conventional address 127.0.0.1:8765 was occupied by unrelated Python process /tmp/cdp-probe/refstub.py, whose /v1/healthz returned HTTP 404. An exact installed OMP broker bind probe failed with EADDRINUSE. Credential installation had not begun. SSH endpoint refresh and verified host-key handling were already working; they were not the cause. The fix selects a free service-private workstation loopback broker port for each default credential lease, retains the explicit FM_BOAT_BROKER_URL shared-broker override, and leaves the remote bind 127.0.0.1:8765 unchanged. Never kill the unrelated listener. The regression starts two default credential leases using real systemd services, fixture HTTP brokers and the real scoped facade: each must vend its own distinct fixture credential, and stopping one must not interrupt the other. It failed before the fix with the reported readiness error and passes after.\n\nOperational constraints: owner scripts may diagnose and prove the fix against the real existing boatmate from the main home (fm-compute-wake.sh boatmate; fm-on.sh boatmate fm-remote-doctor.sh; fm-boat.py status/wake/sleep boatmate). Wakes cost compute, so keep them few and deliberate. Never destroy, recreate, or re-provision the sandbox. Never relaunch or steer the boatmate agent itself; Firstmate owns the post-merge relaunch. Never print, manually copy, export, or commit a credential, including the sandbox gh login. Do not hand-edit main-home data or state; owner scripts own operational mutations. Never run doctor --fix or any Herdr lifecycle action. Leave boatmate either asleep or awake with doctor passing; it has already been safely returned asleep, with the scoped bearer shredded, and must not be left awake with failed doctor readiness. Do not run paid live smoke as part of automated fixture tests or create a smoke sandbox. No agent launch, steer, --fix, Herdr lifecycle action, sandbox recreation, or credential disclosure occurred in the implementation smoke.\n\nAcceptance criteria, with current accepted AC2 rescope: AC1: identify the wake root cause with concrete log/unit-journal/SSH or address evidence and write it in the PR, with a receipt citing that evidence. AC2: after the fix, fm-compute-wake.sh boatmate succeeds from the main home, and fm-on.sh boatmate fm-remote-doctor.sh reaches the host. Every remaining failing doctor check must be named, and the PR must show the wake path does not cause it. Remote services normally restored by the second mate's relaunch are Firstmate's post-merge responsibility, not part of this task. Specifically name remote-job-worker, remote-job-probe and the Herdr server for fm-remote; never claim doctor was fully green. Prove through code/docs that ordinary relaunch starts them, without running --fix or any Herdr lifecycle action. AC3: a regression test or deterministic check covers the failure mode where feasible; otherwise explain why and document the manual check in the PR. AC4: no credential printed, manually copied or committed and no sandbox recreation; provide secret-scan evidence and state this in completion.\n\nObserved implementation proof: one real wake using this isolated branch's owner scripts with FM_HOME=/Desktop/firstmate and the main home as current directory returned ready: boatmate. Its lease reached ready using workstation broker http://127.0.0.1:46651 and an authenticated reverse-forward check. The subsequent remote doctor reached the Linux host and exited 1 with exactly remote-job-worker, remote-job-probe and fm-remote herdr-server missing. These are expected separate post-resume restoration prerequisites, not a remaining credential-wake failure. fm-spawn.sh:775-796 orders compute wake before fm_remote_readiness_ensure; fm-remote-readiness-lib.sh:24-43 checks doctor, repairs, then checks again as the relaunch gate; fm-remote-doctor.sh:469-475,775-785,801-842 owns remote worker/probe and Herdr startup; docs/remote-secondmates.md:175-201 confirms compute stop loses the agent and ordinary launch/recovery restores through readiness. Cite these boundaries in the PR. After smoke, the authorized fm-boat.py sleep command returned suspended: boatmate; the same sandbox bx_cbbk3thq is stopped, lease retired, bearer shredded, and the unrelated listener remains untouched.\n\nPrivate evidence to read and carry into the PR's root-cause and verification sections: ~/Desktop/firstmate/data/fm-boatmate-wake-credential/artifacts/wake-evidence.md . Do not publish credentials or incidental private operational paths in the PR. All AC1-AC4 receipts are complete after Firstmate's explicit AC2 rescope; the former AC2 failure remains append-only history, not an accepted-blocked exception. Existing implementation commit is e7475ca. Already exercised: targeted new regression red before and green after; credential suite 15 tests OK, lifecycle suite 24 tests OK, routing 11 checks pass; changed-shell lint with pinned ShellCheck 0.11.0 and documentation audience/link check pass. A full canonical lint invocation hit its 300-second caller deadline; do not misreport that as passing full lint. A targeted ten-family secret signature scan of all added lines found zero findings; gitleaks/detect-secrets/trufflehog were unavailable, so do not imply they ran. Keep the pipeline full: no requested step skips, no bypass of findings, no merge. Ask-user findings must be escalated to Firstmate and never self-answered or bypassed with --yes. Finish at a PR with verified green checks, not at mere implementation completion.What Changed
FM_BOAT_BROKER_URLand the remote127.0.0.1:8765bind.Risk Assessment
✅ Low: The change narrowly isolates default broker ports while preserving the explicit override, remote binding, scoped authorization, and cleanup behavior.
Testing
Inspected the change, passed the focused credential suite and isolated product checks, reproduced the failure before the fix, and retained credential-free transcripts. Existing boatmate smoke was not repeated; its accepted operational receipt was supplied in context.
Evidence: Product behavior transcript
Evidence: Before-fix failure reproduction
Evidence: Targeted credential suite
Evidence: Reproducible isolated product driver
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
git diff 76de0c5e3512d16769a14b17d1b1d3449e057bce e7475ca8863ec31520d37699548247ed187722bdTMPDIR="$PWD/.boat-test-tmp" PYTHONDONTWRITEBYTECODE=1 bash tests/fm-boat-omp-auth.test.sh— 15 tests passedpython3 .boat-test-tmp/drive.py "$PWD"— real systemd credential services and scoped facade against isolated fixture endpointspython3 .boat-test-tmp/drive.py "$PWD/.boat-test-tmp/before"— baseline module reproducedcredential acquisition did not become readyRemoved disposable homes and baseline copy; verified service/helper retirement and clean git status✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.