Menu

#216 Redesign apra-fleet auth → secret subcommand

open
nobody
None
2026-05-01
2026-05-01
Anonymous
No

Originally created by: kumaakh

Background

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:

  1. --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.
  2. There is no user-facing CLI for managing the vault. The only way to set/list/delete secrets is through MCP tool calls — not from a terminal.
  3. The naming (auth) is confusing. The subsystem manages secrets, not authentication in the broad sense.

New CLI: apra-fleet secret

Synopsis

apra-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:

  1. 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.

  2. OOB delivery + persist — same as (1), but --persist also writes the value to credentials.json so it survives server restarts.

  3. 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

--list

Prints 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 --all

Deletes all secrets. Requires explicit confirmation: "Delete all secrets? Type yes to confirm: "

Network policy: allow / deny

V1 supports two states:

Value Meaning
allow Always permit without prompting
deny Always block without prompting — default

Server-Side: credential_store_set OOB flow

Secret collection remains OOB — the LLM must never see secret values. When credential_store_set starts waiting, the server fires three parallel signals:

  1. Auto-launch a terminal — spawn apra-fleet secret --set <name>.
  2. Print to LLM console — tool response visible in PM chat: Waiting for secret NAME. Run in any terminal: apra-fleet secret --set NAME
  3. Log it — write to fleet-<pid>.log at info level.

Terminal auto-close on receipt

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 subcommand

Removed 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 changes

Top-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

Migration

No data migration needed. Vault format (credentials.json, session store) is unchanged. Existing network_policy values are preserved as-is.

Stretch: 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:

  1. execute_command returns early with { "status": "confirmation_required", "confirmation_id": "...", "secret": "...", "command": "..." } instead of blocking.
  2. The fleet skill instructs Claude: when you see confirmation_required, call AskUserQuestion with the context, then call credential_confirm(confirmation_id, choice), then retry the original command.
  3. A new 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.

Out of scope

  • --from-env — not implemented, not needed.

Forward compatibility with [#193] (per-instance data directories)

No new CLI flag needed. The hook is APRA_FLEET_DATA_DIR:

  • Server prefixes auto-launched terminals with APRA_FLEET_DATA_DIR=<path> so the CLI writes to the correct vault.
  • Users can set APRA_FLEET_DATA_DIR manually to target a specific instance vault.
  • Default: global path, same as today.

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.

Related

Tickets: #193
Tickets: #256

Discussion


Log in to post a comment.

MongoDB Logo MongoDB