Skip to content

feat(auth): add local token config commands#17

Open
robinbraemer wants to merge 7 commits into
mainfrom
fm/akua-cli-auth-config-mvp
Open

feat(auth): add local token config commands#17
robinbraemer wants to merge 7 commits into
mainfrom
fm/akua-cli-auth-config-mvp

Conversation

@robinbraemer

Copy link
Copy Markdown
Member

Intent

Implement the next Akua CLI MVP slice for auth/config commands from docs/architecture.md in the cli repo only. Add minimal local config/token handling for akua auth login --token , akua auth status, and akua auth logout, with tests. AKUA_API_TOKEN must take precedence for noninteractive auth, stored tokens must use user-only permissions, browser/device login is out of scope, and all output must follow the existing human/agent/json/quiet runtime contract. Do not implement broad OpenAPI command execution or destructive operations; validate with mise run check before reporting done.

What Changed

  • Added akua auth login, auth status, and auth logout local token/config commands with human, agent, JSON, and quiet output handling.
  • Implemented environment-token precedence via AKUA_API_TOKEN, user-only local config permissions, redacted auth usage errors, and preservation of non-token config keys.
  • Documented the auth/config MVP behavior in the README and architecture docs, with CLI tests covering the new auth flows.

Risk Assessment

✅ Low: The change is limited to the auth/config MVP path, preserves existing CLI output contracts, and the prior token-handling/config-preservation risks have been addressed in the current diff.

Testing

Exercised the new auth/config slice through automated CLI tests, the full Bun test suite, and a product-level transcript; all checks passed, tokens stayed out of CLI output, stored config used 700/600 permissions, and I did not run mise run check because this testing prompt forbids static-analysis steps while check depends on generate:check and build.

Evidence: Auth/config end-to-end CLI transcript
Akua auth/config CLI end-to-end evidence
workspace=/Users/robin/.no-mistakes/worktrees/ef29b7d1bc46/01KX3JJE3JSY1X7WD5X1MVSJME
home=/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e

$ HOME="$home_dir" bun src/bin/akua.ts auth status --json
{
  "status": "ok",
  "command": "akua auth status",
  "observations": [
    "No Akua authentication token found."
  ],
  "data": {
    "authenticated": false,
    "source": "none",
    "config_path": "/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e/.config/akua/config.json"
  },
  "next_steps": [
    {
      "command": "akua auth login --token <token>"
    }
  ]
}

$ HOME="$home_dir" bun src/bin/akua.ts auth login --token "$LOGIN_TOKEN" --json
{
  "status": "ok",
  "command": "akua auth login",
  "observations": [
    "Authentication token saved."
  ],
  "data": {
    "authenticated": true,
    "source": "config",
    "config_path": "/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e/.config/akua/config.json"
  },
  "next_steps": [
    {
      "command": "akua auth status"
    }
  ]
}

$ stat modes for ~/.config/akua and config.json
dir_mode=700 path=/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e/.config/akua
file_mode=600 path=/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e/.config/akua/config.json

$ persisted config shape
{
  "has_token": true,
  "keys": [
    "token"
  ]
}

$ HOME="$home_dir" bun src/bin/akua.ts auth status
Authenticated with stored token.
{
  "authenticated": true,
  "source": "config",
  "config_path": "/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e/.config/akua/config.json"
}

$ AKUA_API_TOKEN="$ENV_TOKEN" HOME="$home_dir" bun src/bin/akua.ts auth status --output agent
status: ok
command: akua auth status
observations[1]:
  Authenticated with AKUA_API_TOKEN.
data:
  authenticated: true
  source: env
  config_path: /var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e/.config/akua/config.json

$ AKUA_API_TOKEN="$ENV_TOKEN" HOME="$home_dir" bun src/bin/akua.ts auth logout --json
{
  "status": "ok",
  "command": "akua auth logout",
  "observations": [
    "Stored authentication token removed. AKUA_API_TOKEN is still active."
  ],
  "data": {
    "authenticated": true,
    "source": "env",
    "config_path": "/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e/.config/akua/config.json"
  },
  "next_steps": [
    {
      "command": "unset AKUA_API_TOKEN"
    }
  ]
}

$ HOME="$home_dir" bun src/bin/akua.ts auth status --json
{
  "status": "ok",
  "command": "akua auth status",
  "observations": [
    "No Akua authentication token found."
  ],
  "data": {
    "authenticated": false,
    "source": "none",
    "config_path": "/var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/home-auth-e2e/.config/akua/config.json"
  },
  "next_steps": [
    {
      "command": "akua auth login --token <token>"
    }
  ]
}

$ HOME="$home_dir" bun src/bin/akua.ts auth login --token "$QUIET_TOKEN" --quiet; echo exit=$? bytes=<captured>
exit=0 bytes=0

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed (5) ✅
  • ⚠️ src/commands/auth.ts:44 - Config read/write/remove failures now propagate out of auth commands as plain errors, and main converts those to usage_error exit code 2 with akua --help. Permission errors, malformed config JSON, and other local config failures are runtime/config failures, so they should be wrapped into a runtime-style AkuaCliError instead of being reported as invalid user syntax.
  • ⚠️ src/commands/auth.ts:170 - writeFile(..., { mode: 0o600 }) only applies the mode when creating a new file. If an existing config file is more permissive, auth login writes the new token before the later chmod, briefly storing the secret under the old permissions. Tighten permissions before writing or write a 0600 temp file and rename it over the target.

🔧 Fix: Harden auth config storage errors
2 issues (1 error, 1 warning) still open:

  • 🚨 src/commands/auth.ts:101 - auth login echoes unexpected positional arguments in the usage error, so a common typo like akua auth login sk_akua_secret --json will print the token back to stdout. For auth token parsing, avoid including the rejected argument value in the error message.
  • ⚠️ src/commands/auth.ts:80 - auth logout parses the config before attempting removal, so malformed JSON prevents logout from deleting the stored-token file at all. Since logout's primary job is cleanup, it should still attempt to remove the local config/token when the file exists even if parsing fails.

🔧 Fix: Harden auth logout and login errors
1 warning still open:

  • ⚠️ src/commands/auth.ts:61 - auth status resolves the config path before checking AKUA_API_TOKEN, so an environment-token-only invocation with HOME unset or empty exits with a usage error even though the env token should take precedence and no config read is needed. Check AKUA_API_TOKEN before requiring HOME, or make the config path optional for env-authenticated status output.

🔧 Fix: Honor env auth without HOME
1 error still open:

  • 🚨 src/commands/auth.ts:39 - Auth positional usage errors still echo rejected values outside login; a pasted token in akua auth sk_akua_secret --json is returned in the error payload, and the same pattern applies to extra positional args for status/logout. Keep auth positional diagnostics generic or redact token-like values before rendering errors.

🔧 Fix: Redact auth positional usage errors
1 warning still open:

  • ⚠️ src/commands/auth.ts:45 - auth login writes a fresh { token } config and auth logout removes the whole config file, so any existing non-token keys under ~/.config/akua/config.json are lost. Since the architecture reserves this file for broader profile config, confirm whether this MVP intentionally treats it as token-only; otherwise preserve unknown keys and only remove the token.

🔧 Fix: Preserve auth config keys
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • bun test test/cli.test.ts
  • bun test
  • Manual CLI flow captured to /var/folders/1y/cjgf53nj31n_dxsspqnjfjvc0000gn/T/no-mistakes-evidence/01KX3JJE3JSY1X7WD5X1MVSJME/auth-config-e2e-transcript.txt: auth status --json, auth login --token ... --json, config permission checks, human auth status, agent AKUA_API_TOKEN=... auth status, env-aware auth logout --json, post-logout auth status --json, and quiet auth login --quiet
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

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