feat: CLI audit + local/api parity: open-dispatch - #18
Open
andrei-hasna wants to merge 3 commits into
Open
Conversation
…uests Three reviewer findings on the local/api parity slice. 1. In API mode the CLI decided "did this route to the remote authority?" from the truthiness of the resolved response. withApiDaemon()/withApiClient() signalled "not API mode" with undefined, and request() also resolved undefined for an empty body, so a 204 or null answer from the authority silently handed the command to the local box: `daemon status`/`doctor` printed local SQLite daemon state, and `fleet summary` invoked the local tmux runner. Both helpers now return DispatchApiRouteResult<T>, whose `routed` flag comes from the route decision alone, and request() raises REMOTE_API_EMPTY_RESPONSE for a body-less or null success instead of resolving undefined. 2. Side-effecting POSTs (/dispatches, /dispatches/bulk, /exec, /keys, /recover) were retried up to 3x — including after a client-side timeout — on the strength of an Idempotency-Key contract no authority in this repo implements or is tested against. `dispatch exec` against a slow authority could submit a command into a live shell pane three times. Only HTTP-idempotent methods are retried now, and an in-flight abort/timeout is never replayed. The header is still sent as advisory metadata for the authority. 3. The credential-exfiltration assertion in api-client.test.ts was a tautology: its `|| call.headers.Authorization === "Bearer secret"` arm was true for every call, so it passed even against a fixture leaking the key into the request body. Replaced with a predicate over url+body (auth headers excluded) plus a negative control proving the predicate can fail. Docs updated to match: README "Local and API mode" and docs/architecture.md "Client route".
getDispatchApiConfigStatus validated both HASNA_DISPATCH_STORAGE_MODE and
its lower-precedence DISPATCH_STORAGE_MODE alias, so a stale or invalid
alias returned {selected: true, ok: false} even when the canonical name was
set and valid. Every CLI, MCP and SDK entry point funnels through this
function, so a leftover DISPATCH_STORAGE_MODE=sqlite hard-failed the whole
tool — including the default local mode, which never reads either variable.
Resolve precedence first via firstEnv (the same rule the API URL/key pair
already uses), then validate only the variable that actually won. An alias
that is never consulted can no longer veto the mode that outranks it.
Invalid values still fail closed when that variable is the one in effect.
Covers both directions: the new precedence tests fail without the fix, and
the negative control fails if the validation is dropped instead of scoped.
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.
Objective
CLI audit + local/api parity: open-dispatch
Repo: hasna/dispatch (local: /home/hasna/workspace/hasna/opensource/open-dispatch).
Audit this repo's CLI: (1) Find every DEAD command — commands that are broken, error out, reference removed code, or are declared but non-functional — and fix them or remove them with justification. (2) Find every command that only works in 'local' mode (on-box SQLite/files) and does NOT work against the 'api' (self-hosted/remote) path; implement full api-mode support for each so every command works identically against local AND api backends (route through the cloud-router/stage-A/HTTP path per this repo's existing pattern). Ensure both modes are fully implemented and tested. Add regression tests for the fixed commands and for local-vs-api parity. Open a PR; do not merge.
Verification
Run
run_44b4d1862024· backendcodewith· task669f8958-59ff-4265-9a2b-3fee768f9f8c🏭 Generated by @hasnaxyz/factory
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.