feat(agent-fleet): add safe multi-account provider routing - #5
Closed
ruby-dlee wants to merge 0 commit into
Closed
Conversation
ruby-dlee
force-pushed
the
codex/bridge-agent-fleet-v015
branch
from
July 19, 2026 03:16
58cde83 to
ac74baa
Compare
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
Import Agent Fleet into the existing public ruby-dlee/firstmate repository as an independently versioned 0.2.0 provider-neutral package and ship it through a GitHub PR, not as local-only work or a separate/private repository. Make multi-account Claude and Codex routing safe enough that Desktop/default CLI sessions cannot silently share or eject worker identities: verify opaque remote identity sets, fail closed on base/Desktop overlap or unavailable proof, reread Claude Desktop identity at selection time, disable Claude login/logout commands in workers, scrub ambient provider variables, and keep worker launch task-bound with verified process ownership. Serialize profile changes, verification, quota refresh, selection, and enrollment under provider maintenance locks; refuse auth maintenance while same-provider leases are live. Make Codex enrollment non-destructive through an isolated staging home, atomic promotion, durable transaction journal, and crash recovery. Preserve sticky managed resume, isolated provider homes, and the existing Firstmate/Bridge architecture; do not touch live auth/config/tmux or merge without fresh owner authorization. Include regression coverage, locked uv metadata, provenance/release docs, root CI/no-mistakes integration, push the feature branch, and open a PR only after local and CI gates pass.
What Changed
uvmetadata, provenance and release documentation, plus root CI and no-mistakes validation.Risk Assessment
🚨 High: Captain, the change should not merge without approval because documented Claude aliases and subcommands can still bypass the task-bound launch boundary and outlive verified lease ownership.
Testing
The supplied shell baseline, locked Agent Fleet pytest suite, focused Firstmate routing checks, isolated synthetic-provider CLI workflows, and built-wheel installation smoke all passed; CLI/package artifacts capture the user-facing behavior without touching live provider auth, configuration, or tmux.
Evidence: End-to-end CLI transcript
Evidence: Reproducible E2E harness
Evidence: Built-wheel installation smoke
installed_distribution=agent-fleet installed_version=0.2.0 console_entrypoint=agent_fleet.cli:main {"cli_version":"0.2.0","contract_version":1}/var/folders/y_/bfdbj_vx20l9b9tw7crgkzwm0000gn/T/no-mistakes-evidence/01KXSJTEG548G0EWKQ9JWFTFQT/agent-fleet-dist/agent_fleet-0.2.0-py3-none-any.whl) - Evidence: Agent Fleet 0.2.0 source distribution (local file:/var/folders/y_/bfdbj_vx20l9b9tw7crgkzwm0000gn/T/no-mistakes-evidence/01KXSJTEG548G0EWKQ9JWFTFQT/agent-fleet-dist/agent_fleet-0.2.0.tar.gz) - Outcome: 🔧 1 issue found → auto-fixed ✅ across 2 runs (1h16m59s)Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
tools/agent-fleet/src/agent_fleet/enrollment.py:462- The required criterion “durable transaction journal, and crash recovery” is not met when rolling back an existing credential. Restoring the copied backup creates a different inode fromoriginal_stat; if the process crashes before quota restoration and journal deletion, the next recovery rejects the already-restored auth as an outside change and permanently blocks recovery. Record an idempotent rollback phase/restored identity before replacing the file.tools/agent-fleet/src/agent_fleet/cli.py:417- The criteria “verify opaque remote identity sets” and “fail closed on … unavailable proof” are contradicted here. After Claude login changes a profile’s credential,keychain_access_requiredcan cause verification to reuse the pre-login cached fingerprint;auth_probesupplies no identity to bind that cache to the new credential, so a different account can be enabled using the old account’s proof. Invalidate proof after login or cryptographically bind cached proof to the current credential/home.tools/agent-fleet/src/agent_fleet/cli.py:992- The criteria “refuse auth maintenance while same-provider leases are live,” non-destructive Codex enrollment, and sticky managed resume are bypassable because workerexecforwards arbitrary provider subcommands. For example,exec … -- loginmutates Codex auth outside the maintenance lock/staging journal, whileexec … -- resume <id>bypasses the recorded task/session mapping. Reject auth and resume subcommands inexec, leaving them to the dedicated enrollment/resume paths.tools/agent-fleet/src/agent_fleet/cli.py:694- The required serialization of profile changes under provider maintenance locks is contradicted byinit --force, which directly replaces the entire registry. It can remove or redirect profiles while their leases are live and can orphan pending Codex journals. Existing registries must be replaced only under all provider locks with live-lease and transaction checks, or force replacement should be removed.tools/agent-fleet/src/agent_fleet/enrollment.py:178- The required non-destructive isolated Codex staging behavior is contradicted for custom profile homes.ensure_private_dir(profile.home.parent)unconditionally chmods an existing parent to 0700, so enrolling a profile under a user-owned shared/project directory silently changes that directory’s permissions. Require an already-private Fleet-owned parent or stage under a dedicated managed directory without mutating arbitrary parents.tools/agent-fleet/src/agent_fleet/config.py:171- The isolated-home criterion and README invariant that auth/provider state is “never shared” are not enforced.shared_entriesaccepts any simple filename, so entries such as Codexauth.jsonor Claude credential/state files are symlinked from the base home during provisioning; enrollment may then operate on the base credential before identity checks run. Restrict this field to an explicit provider-specific workflow-asset allowlist.tools/agent-fleet/src/agent_fleet/cli.py:1072- Mutations complete before the default TOON encoder is checked. On a standalone installation withouttoon, documented commands such asinitorprofile enrollcan successfully change registry/auth state and then exit 2 during output, encouraging unsafe retries. Preflight the selected encoder before_run, bundle the dependency, or use a built-in default format.tools/agent-fleet/README.md:53- The quickstart initializes three Claude workers but enrolls onlyclaude-1; the subsequent enable always fails because complete-worker-set verification requires recent identity proof forclaude-2andclaude-3. Initialize one profile per provider in this example or document enrollment and verification of the entire configured worker set before enabling any member.🔧 Fix: Harden Agent Fleet trust and recovery
6 errors still open:
tools/agent-fleet/src/agent_fleet/scheduler.py:158- The required Gate-E behavior to refuse an unallowlisted cwd before lease creation, while preserving the Firstmate/Bridge architecture, is not met. Selection validatesinvocation_workspace(), but Firstmate callslease choosefrom the supervisor process cwd while the actual task worktree remains in$WT. A registered task can therefore be rejected, or an unregistered task can receive a lease when the supervisor repo is registered and fail only duringexec. Pass and validate the intended task worktree during choose/recover.tools/agent-fleet/src/agent_fleet/providers.py:47- The required criterion “Preserve sticky managed resume” remains bypassable for Claude.-c, Claude’s short form of--continue, is absent from the blocked arguments, soexec … -- -cresumes the most recent unmanaged session without the recorded task/session mapping. Block Claude-cand attached-r<session>forms.tools/agent-fleet/src/agent_fleet/providers.py:92- Codex configuration filtering handles only separated-c VALUEarguments. Attached short-option values such as-cfeatures.plugins=truebypass validation and appear after Fleet’s--disable plugins, allowing managed plugin, hook, or trust settings to be overridden. Reject or safely parse attached-c…and-p…forms.tools/agent-fleet/src/agent_fleet/provision.py:209- The required Gate-E behavior to fail closed on changed hook markers is incomplete.session_commandis only type-checked and then treated as the expected command; changing it in both the marker and hooks file and recomputing the unkeyedhooks_hashpasses readiness with an arbitrary SessionStart command. Derive the expected command independently withsession_hook_command()and compare the marker to it.tools/agent-fleet/src/agent_fleet/identity.py:207- The criterion “fail closed on base/Desktop overlap or unavailable proof” is contradicted when a configured base home is absent or moved. Both anchor refresh and conflict checking skip the base boundary unlessbase_home.exists(), allowing workers to route without any proof of the default CLI identity. Treat a configured-but-missing base home asbase_identity_unverified.tools/agent-fleet/src/agent_fleet/quota.py:283- The criteria “verify opaque remote identity sets” and “fail closed on … unavailable proof” are bypassable because the installed CLI honorsAGENT_FLEET_QUOTA_FIXTURE_DIRand accepts local JSON instead of invoking the remote quota reader. A stale ambient test variable can fabricate fresh identities and quota evidence. Replace this production environment seam with test-only dependency injection or an explicitly isolated test mode that cannot enable or lease profiles.🔧 Fix: Harden Agent Fleet routing and trust boundaries
3 issues (1 error, 2 warnings) still open:
tools/agent-fleet/src/agent_fleet/providers.py:93- The required criterion “keep worker launch task-bound with verified process ownership” is still contradicted. This denylist misses Claude’s documented-wand--bgaliases plus positionalsetup-tokenandagentscommands, allowing callers to escape the verified workspace, create background sessions that outlive the PID-bound lease, or perform auth/session administration (Claude CLI reference). Prefer an allowlist of the exact Firstmate-supported arguments.bin/fm-account-routing-lib.sh:88- Firstmate kills control commands after 10 seconds, but one Fleet auth probe alone permits 15 seconds, after base/quota refreshes and potentially once per profile. A healthy slow selection can therefore be terminated while holding the provider lock, leaving routing unavailable until stale-lock recovery. Align the outer deadline with Fleet’s bounded worst case or parallelize/bound the probes below it.tools/agent-fleet/src/agent_fleet/config.py:397- Every registry save unconditionally changes the existing config parent to mode 0700. Because--configaccepts arbitrary paths, initializing or mutating a registry inside a project or shared dotfiles directory silently removes group/world access from that whole directory. Only harden a newly created Fleet-owned directory, or reject an unsuitable existing parent without modifying it.🔧 **Test** - 1 issue found → auto-fixed ✅
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"🔧 Fix: Captain, fix Agent Fleet lint parity assertion
✅ Re-checked - no issues remain.
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"Supplied passing baseline:command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"cd tools/agent-fleet && uv run --locked pytestFM_TEST_FOCUSED=gate-e-workspace bash tests/fm-account-routing.test.shPYTHONDONTWRITEBYTECODE=1 python3 /var/folders/y_/bfdbj_vx20l9b9tw7crgkzwm0000gn/T/no-mistakes-evidence/01KXSJTEG548G0EWKQ9JWFTFQT/agent-fleet-e2e.py /Users/dongkeun/.no-mistakes/worktrees/b174997b7206/01KXSJTEG548G0EWKQ9JWFTFQT/tools/agent-fleet /var/folders/y_/bfdbj_vx20l9b9tw7crgkzwm0000gn/T/no-mistakes-evidence/01KXSJTEG548G0EWKQ9JWFTFQTcd tools/agent-fleet && uv build --out-dir /var/folders/y_/bfdbj_vx20l9b9tw7crgkzwm0000gn/T/no-mistakes-evidence/01KXSJTEG548G0EWKQ9JWFTFQT/agent-fleet-distInstalledagent_fleet-0.2.0-py3-none-any.whlwithout dependencies into an isolated virtual environment and ranagent-fleet --format json versionpython3 -m py_compile tools/agent-fleet/src/agent_fleet/cli.py tools/agent-fleet/src/agent_fleet/enrollment.pytools/agent-fleet/tests/test_quota_scheduler.py:1- Locked ruff validation still fails with I001 for an unsorted import block. This executable test file is outside the documentation-only edit scope.🔧 Fix: Correct Agent Fleet runtime documentation
1 error still open:
tools/agent-fleet/tests/test_quota_scheduler.py:1- Locked ruff validation still fails with I001 for an unsorted import block. Fixing it requires editing executable test code, outside this documentation-only scope.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.