Skip to content

feat(auth): token admin, whoami, ping, config update (PR5) - #5

Merged
xe-nvdk merged 1 commit into
mainfrom
feat/pr5-auth
Sep 7, 2026
Merged

xe-nvdk merged 1 commit into
mainfrom
feat/pr5-auth

Conversation

@xe-nvdk

@xe-nvdk xe-nvdk commented Sep 7, 2026

Copy link
Copy Markdown
Member

Summary

  • arcli auth whoami and arcli auth token {list,show,permissions,create,update,rotate,revoke,delete} over Arc's /api/v1/auth/* routes. Tokens are addressed by numeric id or exact name.
  • arcli ping: GET /health (no token sent) then GET /api/v1/auth/verify; exit 1 on either failure, -o json always emitted. A 404 on verify is reported as "auth disabled on server" (the route only exists when auth is on); /health must carry Arc's time/uptime fields so a load balancer's own health page can't pass as Arc.
  • arcli config update <name> for refreshing a stored token/endpoint/default-database/insecure flag. config create|update now validate the endpoint scheme+host and reject userinfo; profile names starting with ( are rejected (Resolve's sentinels).
  • Secret handling: create and rotate are the only commands that print a plaintext token, to stdout alone (T=$(arcli auth token create ...) works); reminders and ids go to stderr. rotate --save rewrites every profile that held the old token, prints the secret before touching the config, and re-loads the config after the rotate so a concurrent config edit during the prompt is not clobbered. --save is refused up front for ad-hoc connections, when /verify can't confirm the target is the token in use, or when the config dir isn't writable.
  • Guards: rotate refuses revoked/expired tokens (the new secret could never authenticate); revoke/delete of the last enabled admin token need --force; operating on the token in use prints a warning. Confirmation prompts now go to stderr (also for db drop / config delete), answering anything but y/yes exits 1, and non-TTY stdin without --yes is refused.
  • Typed client.HTTPError (status + server message) replaces the string-only error from decodeWriteError; buildClient split into buildClientFrom so rotate can keep the loaded config.
  • README: Auth & tokens section, roadmap revised to the agreed PR5–PR10 + post-1.0 plan. CLAUDE.md: secret-printing exception documented under Security Checklist item 1.

Test plan

  • gofmt -l . empty, go vet ./..., go test -race -count=1 ./... green
  • Unit: client wire shapes incl. tokens: null → [], new_token key on rotate, nil-vs-empty permissions on create, expires-in grammar; command flag validation with no network (--permission , / "" refused); httptest fake for create/rotate/delete/ping flows; concurrent-edit safety of --save; last-admin guard
  • 37-check smoke against a freshly bootstrapped arc serve (HEAD e5c3f5e, ARC_AUTH_BOOTSTRAP_TOKEN): ping good/bad/unreachable/json, whoami, list, create (stdout capture + json id), show/permissions by name and id, update incl. empty-permission refusal, rotate (old secret dead, new works), self-rotate without --save then repair via config update, rotate --save -o json, --save refused ad-hoc, revoke → 401 → rotate refused, delete by name/id/missing, last-admin guard and --force, non-admin token → 403, first-run error, sentinel name and userinfo endpoint refused
  • Docker image unaffected (no Dockerfile changes)

Review notes

Internal: adversarial review of the plan (3 design changes adopted before code), deep diff review (2 High fixed: empty --permission silently sending []; JSON-mode rotate printed the secret after Save()), security review (checklist all PASS; 3 Medium fixed: lost-update race on --save, per-profile endpoint reporting, last-admin guard). Deferred: --token-stdin follow-up.

arcli auth whoami and auth token {list,show,permissions,create,update,
rotate,revoke,delete} over /api/v1/auth/*; arcli ping over /health +
/verify; arcli config update for refreshing stored fields.

Secrets from create/rotate are the only plaintext tokens ever printed
and go to stdout alone. rotate --save rewrites every profile holding the
old token, printing the secret first and re-loading the config after the
rotate so concurrent edits are not clobbered. Revoke/delete refuse the
last enabled admin token without --force. Confirmation prompts now go to
stderr and are refused on non-TTY stdin without --yes.
@xe-nvdk
xe-nvdk merged commit bc9d03d into main Sep 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant