Summary
dcd login records the environment you logged into (api_url, env) in the config store. But most commands default --api-url to the hard-coded prod URL (https://api.devicecloud.dev) and ignore the stored api_url. A user who logs into a non-prod env (e.g. dev) and then runs dcd list/status/cloud/artifacts/live without re-passing --api-url sends their dev Bearer token to the prod API and gets an auth failure.
Reproduction
$ dcd login --api-url https://api.dev.devicecloud.dev # stores env=dev, api_url=dev
$ dcd whoami
...
Env: dev # whoami reads config, correct
$ dcd list --limit 1
✗ Error: Failed to list uploads: Access denied. Invalid or expired JWT token
# defaulted to PROD, dev token rejected
dcd list --api-url https://api.dev.devicecloud.dev works fine.
Inconsistency
The codebase is split on this:
switch-org (src/commands/switch-org.ts) correctly falls back to the stored api_url, with an explicit comment: "Honor the env the user logged into — defaulting to prod here would send a dev Bearer token to the prod API."
whoami reads purely from config (correct).
cloud, list, status, artifacts, live read args['api-url'], which defaults to prod from apiFlags regardless of the logged-in env.
So the exact footgun switch-org guards against is live in every other session-aware command.
Impact
- Affects anyone on a non-prod env (internal dev/staging, self-hosted), and any future multi-env usage.
- The error ("Invalid or expired JWT") is misleading — the token is valid, it's just being sent to the wrong environment.
Suggested fix
When --api-url is not explicitly provided, fall back to config.api_url (as switch-org already does) before the prod default. The api-key auth path is unaffected since those users pass --api-key/env explicitly.
Found during a full feature sweep of v5.0.0 against the dev environment.
Summary
dcd loginrecords the environment you logged into (api_url,env) in the config store. But most commands default--api-urlto the hard-coded prod URL (https://api.devicecloud.dev) and ignore the storedapi_url. A user who logs into a non-prod env (e.g. dev) and then runsdcd list/status/cloud/artifacts/livewithout re-passing--api-urlsends their dev Bearer token to the prod API and gets an auth failure.Reproduction
dcd list --api-url https://api.dev.devicecloud.devworks fine.Inconsistency
The codebase is split on this:
switch-org(src/commands/switch-org.ts) correctly falls back to the storedapi_url, with an explicit comment: "Honor the env the user logged into — defaulting to prod here would send a dev Bearer token to the prod API."whoamireads purely from config (correct).cloud,list,status,artifacts,livereadargs['api-url'], which defaults to prod fromapiFlagsregardless of the logged-in env.So the exact footgun
switch-orgguards against is live in every other session-aware command.Impact
Suggested fix
When
--api-urlis not explicitly provided, fall back toconfig.api_url(asswitch-orgalready does) before the prod default. The api-key auth path is unaffected since those users pass--api-key/env explicitly.Found during a full feature sweep of v5.0.0 against the dev environment.