Originally created by: kumaakh
The existing apra-fleet auth subcommand was designed purely as internal plumbing: the server auto-launches it in a new terminal when a tool like credential_store_set needs a secret, the user types the value, it sends it back over a named pipe/UDS socket, and exits. Users were never meant to type apra-fleet auth directly.
The problems:
--help describes auth as "Provide password for pending member registration" — incorrect. It has three modes (SSH password, API key, network egress confirm) with completely different semantics.auth) is confusing. The subsystem manages secrets, not authentication in the broad sense.apra-fleet secretapra-fleet secret --set <name> Deliver a secret value to a waiting request
apra-fleet secret --set <name> --persist Deliver and also persist to disk
apra-fleet secret --update <name> Update metadata of an existing secret
apra-fleet secret --list List secret names and metadata (no values)
apra-fleet secret --delete <name> Delete a named secret
apra-fleet secret --delete --all Delete all secrets
apra-fleet secret --help Show this help
--set <name>Delivers a secret value. The name must match [a-zA-Z0-9_]{1,64}.
Valid use cases:
OOB delivery (waiting request exists) — the server has a pending credential_store_set call blocked waiting for this secret name. The value is forwarded over the auth socket to unblock that call. Primary use case.
OOB delivery + persist — same as (1), but --persist also writes the value to credentials.json so it survives server restarts.
Persist only (no waiting request, --persist required) — if no waiting request exists, --set requires --persist. Without it the command errors: "No pending request for NAME. Use --persist to store for future use." Standalone password-manager mode — server does not need to be running.
The CLI always prompts for the value with no-echo secure input.
Flags:
| Flag | Meaning |
|---|---|
--persist |
Also write to credentials.json (survives server restart) |
--allow |
Set network_policy=allow — always permit without prompting — only applies with --persist |
--deny |
Set network_policy=deny — always block without prompting — only applies with --persist |
--members <list> |
Comma-separated member names, or * (default: *) — only applies with --persist |
--ttl <seconds> |
Expiry in seconds — only applies with --persist |
Default network policy (no flag): deny.
Examples:
# Deliver to waiting request (session-only, network blocked by default)
apra-fleet secret --set github_pat
# Deliver and persist with network blocked
apra-fleet secret --set github_pat --persist
# Persist and always allow network use without prompting
apra-fleet secret --set github_pat --persist --allow
# Persist and explicitly block network use
apra-fleet secret --set github_pat --persist --deny
# Persist scoped to specific members
apra-fleet secret --set db_password --persist --members fleet-dev,fleet-rev
--update <name>Updates metadata of an existing secret without re-entering the value. Backed by the existing credential_store_update MCP tool.
Flags:
| Flag | Meaning |
|---|---|
--allow |
Set network_policy=allow (always permit) |
--deny |
Set network_policy=deny (always block) |
--members <list> |
New member scope (* or comma-separated) |
--ttl <seconds> |
New TTL in seconds from now; 0 to remove expiry |
At least one flag must be provided. Examples:
# Grant permanent network access
apra-fleet secret --update github_pat --allow
# Restrict to specific members and set expiry
apra-fleet secret --update db_password --members fleet-dev --ttl 3600
# Remove expiry
apra-fleet secret --update github_pat --ttl 0
--listPrints a table of all secrets in the vault (session + persistent). Values are never shown.
NAME SCOPE POLICY MEMBERS EXPIRES
github_pat persistent allow * none
db_password session deny fleet-dev 23m 14s
--delete <name>Deletes from both session and persistent stores. Exits 0 if deleted, 1 if not found.
--delete --allDeletes all secrets. Requires explicit confirmation: "Delete all secrets? Type yes to confirm: "
allow / denyV1 supports two states:
| Value | Meaning |
|---|---|
allow |
Always permit without prompting |
deny |
Always block without prompting — default |
credential_store_set OOB flowSecret collection remains OOB — the LLM must never see secret values. When credential_store_set starts waiting, the server fires three parallel signals:
apra-fleet secret --set <name>.Waiting for secret NAME. Run in any terminal: apra-fleet secret --set NAMEfleet-<pid>.log at info level.Server records the PID of the auto-launched terminal. When the secret is received via any path, the server kills that process. If it arrived from the auto-launched terminal itself, the process has already exited — kill is a no-op.
auth subcommandRemoved from --help entirely. May be kept as an undocumented alias for the server auto-launch path if refactor cost is not worth it, but must not appear in any user-facing output or documentation.
--help changesTop-level apra-fleet --help replaces the auth line with:
apra-fleet secret --set <name> Deliver a secret to a waiting request
apra-fleet secret --list List secrets
apra-fleet secret --delete <name> Delete a secret
No data migration needed. Vault format (credentials.json, session store) is unchanged. Existing network_policy values are preserved as-is.
confirm policy (not in V1)A third policy value confirm is reserved for a future version. It would prompt the user each time the secret is about to be used for a network call, with choices to escalate trust progressively:
apra-fleet — Network access request
Secret: github_pat
Member: fleet-dev
Command: git push origin main
Allow network access using this secret?
1. Allow only this time
2. Allow for this session
3. Always allow (save permanently)
4. Deny
| Choice | Effect |
|---|---|
| Allow only this time | Proceeds once; policy unchanged |
| Allow for this session | Proceeds; policy upgraded to allow in session store |
| Always allow | Proceeds; policy upgraded to allow in credentials.json |
| Deny | Blocks this call; policy unchanged |
Architecture note: The confirmation has nothing to hide so it does not need to be OOB. The fleet server cannot push to Claude — it can only respond to tool calls. The correct mechanism is:
execute_command returns early with { "status": "confirmation_required", "confirmation_id": "...", "secret": "...", "command": "..." } instead of blocking.confirmation_required, call AskUserQuestion with the context, then call credential_confirm(confirmation_id, choice), then retry the original command.credential_confirm MCP tool delivers the choice to the server.For Gemini: same two fleet tools work identically. The AskUserQuestion step falls back to OOB terminal since Gemini has no equivalent — documented in the fleet skill.
--from-env — not implemented, not needed.No new CLI flag needed. The hook is APRA_FLEET_DATA_DIR:
APRA_FLEET_DATA_DIR=<path> so the CLI writes to the correct vault.APRA_FLEET_DATA_DIR manually to target a specific instance vault.Constraint from this issue: do not hardcode FLEET_DIR in any new code paths. credential-store.ts should derive CREDENTIALS_PATH at call time from process.env.APRA_FLEET_DATA_DIR (can be deferred to the [#193] sprint).
When [#193] lands, also update: server startup env for auto-launched terminals; credential-store.ts path derivation; apra-fleet secret docs; fleet_status credentials scoping.