Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ uv run ty check src/

The CLI entry point after install:
```bash
uv run authsome init
uv run authsome onboard
uv run authsome login github
uv run authsome provider list
```
Expand Down Expand Up @@ -144,9 +144,9 @@ vault:<vault_id>:<provider>:state
server:<provider>:client
```

**Config** (`GlobalConfig`) is stored in the KV store under `config/global`. Key fields: `active_identity` (the handle of the current identity), `vault_id` (the active vault resolved at `authsome init`). Encryption mode is set via `config.encryption.mode` (`local_key` or `keyring`).
**Config** (`GlobalConfig`) is stored in the KV store under `config/global`. Key fields: `active_identity` (the handle of the current identity), `vault_id` (the active vault resolved at `authsome onboard`). Encryption mode is set via `config.encryption.mode` (`local_key` or `keyring`).

**CLI (`src/authsome/cli/main.py`)** is Click-based. All commands support `--json` for machine-readable output. `authsome init` creates the local identity, registers it with the daemon, and writes `active_identity` to config.
**CLI (`src/authsome/cli/main.py`)** is Click-based. All commands support `--json` for machine-readable output. `authsome onboard` creates the local identity, registers it with the daemon, imports API keys from env, and writes `active_identity` to config.

## Agent skills

Expand Down
4 changes: 2 additions & 2 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ _Avoid_: vault_name, vault_handle

**VaultHandle**: Human-readable name for a Vault (e.g., `default`). Used in UIs and CLI; the VaultId is authoritative in storage.

**IdentityClaimRecord**: Binding from an Identity (Handle) to a Principal (PrincipalId) with a `ClaimStatus`. Created when an authenticated Principal confirms the browser claim that `authsome init` initiates. Vault access is gated until the claim is accepted.
**IdentityClaimRecord**: Binding from an Identity (Handle) to a Principal (PrincipalId) with a `ClaimStatus`. Created when an authenticated Principal confirms the browser claim that `authsome onboard` initiates. Vault access is gated until the claim is accepted.
_Avoid_: Claim, IdentityRegistration (as claim), join request

**ClaimStatus**: Lifecycle state: `pending` → `accepted` | `rejected`.
Expand All @@ -211,7 +211,7 @@ _Avoid_: Claim, IdentityRegistration (as claim), join request

## Initialization & Claim Flow

There is a single flow for every deployment — no deployment mode (see ADR 0007). `authsome init` creates an Identity and registers it; the daemon returns `registration_status = "claim_required"` with a browser **claim URL**. The user opens the URL and registers (or logs in) with **email + password**: the first Principal created on a server becomes `admin`, all subsequent Principals are `user`. The authenticated Principal then confirms the claim, which binds the Identity to the Principal and creates the Principal's default Vault. Until the claim is `accepted`, all vault operations return `403`. The CLI opens the claim URL automatically and polls for completion (and prints the URL to stderr for headless use).
There is a single flow for every deployment — no deployment mode (see ADR 0007). `authsome onboard` creates an Identity and registers it; the daemon returns `registration_status = "claim_required"` with a browser **claim URL**. The user opens the URL and registers (or logs in) with **email + password**: the first Principal created on a server becomes `admin`, all subsequent Principals are `user`. The authenticated Principal then confirms the claim, which binds the Identity to the Principal and creates the Principal's default Vault. Until the claim is `accepted`, all vault operations return `403`. The CLI opens the claim URL automatically and polls for completion (and prints the URL to stderr for headless use).

---

Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ See the [self-hosting guide](docs/guides/self-hosting.md) for volume backup, TLS

## Quick Start

Install and run first-time setup (identity, claim, and API key import from `.env`):

```bash
authsome onboard
```

For a remote daemon, pass `--base-url` once — it is saved in client config for later commands:

```bash
authsome onboard --base-url https://authsome.example.com
```

Add the authsome skill to your agent (claude, codex, cursor, hermes, etc.):

```bash
Expand Down
2 changes: 1 addition & 1 deletion docs/internal/manual-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ uv run authsome doctor

**Expected:** Exit code `0`; JSON `{"v": 1, "status": "ready", "checks": {"spec_version": "ok", "store": "ok", "identity": "ok", "providers": "ok", "connections": "ok", "vault": "ok", "integrity": "ok"}, "issues": [], "warnings": [...]}`. The `warnings` array is non-empty on a fresh install with no connections (e.g. "no active provider connections found"). A non-`ready` status exits `1`.

> **Tip:** `authsome init` performs the same register + claim flow explicitly and prints an `{"status": "initialized", ...}` payload.
> **Tip:** `authsome onboard` performs register + claim and imports API keys from env in one step, printing a combined JSON payload.

---

Expand Down
2 changes: 1 addition & 1 deletion docs/site/concepts/principal-vault-identity.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ An **Identity** does not own credentials directly. Instead, an Identity claims a

Here is how the initialization and claim flow works:

1. **Initialize Identity:** Running `authsome init` creates a new Identity and registers it with the daemon. The daemon returns a claim URL.
1. **Initialize Identity:** Running `authsome onboard` creates a new Identity and registers it with the daemon. The daemon returns a claim URL.
2. **Register/Login Principal:** The user opens the claim URL and signs in (with email and password). The first Principal created becomes the server `admin`, subsequent ones are `user`.
3. **Accept Claim:** The authenticated Principal confirms the claim, binding the Identity to the Principal and creating the Principal's default Vault.
4. **Access Granted:** Vault access is granted only after the claim is `accepted`.
Expand Down
14 changes: 10 additions & 4 deletions docs/site/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ If `doctor` reports failures, see [Diagnose with doctor](/troubleshooting/doctor

## First-run initialization

On `authsome init`, authsome initializes its home directory at `~/.authsome/`, creates a generated identity handle and Ed25519 DID, and registers that identity with the local daemon:
On `authsome onboard`, authsome initializes its home directory at `~/.authsome/`, creates a generated identity handle and Ed25519 DID, registers that identity with the daemon, completes claim, and imports API keys from `.env` files and the process environment:

```text
~/.authsome/
Expand All @@ -98,7 +98,7 @@ On `authsome init`, authsome initializes its home directory at `~/.authsome/`, c
daemon/
```

On a fresh `init`, authsome resolves the master key source in this order:
On a fresh `onboard`, authsome resolves the master key source in this order:

1. `AUTHSOME_MASTER_KEY` from the environment, when set. The value must be a base64-encoded 32-byte key.
2. An existing OS keyring entry.
Expand All @@ -110,7 +110,13 @@ Override the home location with `AUTHSOME_HOME` for ephemeral or per-project set

```bash
export AUTHSOME_HOME=/var/lib/authsome
authsome init
authsome onboard
```

For a remote or self-hosted daemon, pass `--base-url` once; authsome saves it in client config for later commands:

```bash
authsome onboard --base-url https://authsome.example.com
```


Expand All @@ -129,7 +135,7 @@ By default, authsome uses `encryption.mode = "auto"` and applies the precedence

Re-run `authsome doctor` to confirm the backend is reachable. The trade-offs are covered in [Encryption at rest](/security/encryption).

Older installs that used the implicit `default` profile must run `authsome init` again. This release does not migrate credentials under old `profile:default:*` keys.
Older installs that used the implicit `default` profile must run `authsome onboard` again. This release does not migrate credentials under old `profile:default:*` keys.

## Optional: trust the proxy CA

Expand Down
51 changes: 20 additions & 31 deletions docs/site/reference/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ All commands support `--json` for machine-readable output, `--quiet` to suppress
| `daemon` | Manage the local Authsome daemon. |
| `doctor` | Run health checks on directory layout and encryption. |
| `agent` | Manage local agents backed by signing keys. |
| `init` | Initialize local storage and register a fresh agent. |
| `onboard` | First-run setup: identity, claim, and API key import from env. |
| `log` | View structured audit entries or the raw client debug log. |
| `login <provider>` | Authenticate with PROVIDER using the configured flow. |
| `logout <provider>` | Log out of the specified PROVIDER connection. |
| `provider` | Manage provider definitions and provider-level operations. |
| `run -- <cmd>` | Run COMMAND as a subprocess injected with authentication credentials. |
| `scan` | Scan env files and process env for provider API keys. |
| `whoami` | Show basic local context. |

## Global flags
Expand All @@ -35,15 +34,28 @@ All commands support `--json` for machine-readable output, `--quiet` to suppress

## Command details

### `init` / `whoami` / `doctor`
### `onboard` / `whoami` / `doctor`

```bash
authsome init # initialize local storage and register agent
authsome whoami # show agent context and encryption mode
authsome doctor # run health checks
authsome doctor --json # structured output for monitoring
authsome onboard # identity + claim + import API keys from env
authsome onboard --base-url https://host:7998 # point at a remote daemon (saved for later runs)
authsome onboard --scan-only # drift report without importing
authsome whoami # show agent context and encryption mode
authsome doctor # run health checks
authsome doctor --json # structured output for monitoring
```

`onboard` is idempotent — safe to re-run. It creates a local identity when needed, completes daemon registration and claim, then imports API keys discovered in `.env` files and the process environment. OAuth providers still require `authsome login <provider>`.

When `--base-url` is passed, the URL is persisted in `~/.authsome/client/config.json` as `daemon_base_url` and used automatically on subsequent commands (unless overridden by `AUTHSOME_BASE_URL`).

| Option | Description |
|--------|-------------|
| `--base-url <url>` | Daemon URL to connect to; saved in client config for future commands. |
| `--scan-only` | Report env/vault drift without importing discovered keys. |

`onboard` does not support `--quiet`. Use `--json` for headless contexts.

`doctor` runs six checks and exits `0` when all pass:

| Check | What it verifies |
Expand Down Expand Up @@ -118,29 +130,6 @@ How it works:

See [Proxy injection](/concepts/proxy-injection) for the routing contract.

### `scan`

```bash
authsome scan [OPTIONS]
```

Scans `.env` files in the current directory tree and the active process environment for credentials matching bundled providers. By default it prints a drift report (what's in your env vs. what's in the vault).

| Option | Description |
|--------|-------------|
| `--import` | Apply the discovered values, creating connections in the vault. |
| `--connection <name>` | Target a non-default connection name when importing. |
| `--json` | Machine-readable drift report. Combine with `--import` to apply. |

```bash
authsome scan # report-only
authsome scan --json # report-only, JSON output
authsome scan --import # write discovered keys into the vault
authsome scan --import --connection ci # import into a named connection
```

`scan` does not support `--quiet`. Use `--json` for headless contexts.

### `connections set-default`

```bash
Expand Down Expand Up @@ -218,7 +207,7 @@ authsome log --raw # raw client debug log (loguru format)
authsome log --raw -n 20 # last 20 lines of the client debug log
```

Reads from `~/.authsome/server/logs/authsome.log` (the server-side structured audit log). Each entry records actions like `login`, `logout`, `revoke`, and `scan`, with fields: `timestamp`, `event`, `provider`, `connection`, `identity`, `status`.
Reads from `~/.authsome/server/logs/authsome.log` (the server-side structured audit log). Each entry records actions like `login`, `logout`, `revoke`, and `onboard`, with fields: `timestamp`, `event`, `provider`, `connection`, `identity`, `status`.

The `--raw` flag switches to the client-side debug log at `~/.authsome/client/logs/authsome.log` (loguru format, DEBUG level).

Expand Down
2 changes: 1 addition & 1 deletion docs/site/reference/python-library.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ The exact session shape depends on the flow type. For automation, prefer driving

### Manage Principals and Identities

CLI-level Principal and Identity switching is managed via `authsome init` and `authsome login`. The library provides programmatic access to these constructs, but typically you rely on the daemon resolving the active context.
CLI-level Principal and Identity switching is managed via `authsome onboard` and `authsome login`. The library provides programmatic access to these constructs, but typically you rely on the daemon resolving the active context.

### Register a custom provider

Expand Down
2 changes: 1 addition & 1 deletion docs/site/troubleshooting/doctor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ A healthy machine prints `OK` for each check and exits with code `0`.

Causes:

- You haven't initialized authsome on this machine. Run `authsome init` to provision the home directory, identity, and master key.
- You haven't initialized authsome on this machine. Run `authsome onboard` to provision the home directory, identity, and master key.
- You moved or deleted `~/.authsome`. If you have a backup, restore it. Without the master key, encrypted records cannot be decrypted.
</Accordion>

Expand Down
21 changes: 16 additions & 5 deletions src/authsome/cli/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from fastapi import status

import authsome.errors as err_mod
from authsome.cli.config import ClientConfig
from authsome.cli.identity import RuntimeIdentity
from authsome.config import get_authsome_config
from authsome.identity.proof import POP_AUTH_SCHEME, create_proof_jwt
Expand All @@ -22,11 +23,21 @@
API_PREFIX = "/api"


def resolve_daemon_url(env: Mapping[str, str] | None = None) -> str:
"""Return the top-level configured Authsome server URL."""
configured = get_authsome_config().base_url
raw = (env or {}).get("AUTHSOME_BASE_URL", configured).strip()
return raw.rstrip("/") or configured
def resolve_daemon_url(env: Mapping[str, str] | None = None, home: Path | None = None) -> str:
"""Return the top-level configured Authsome server URL.

Precedence: ``AUTHSOME_BASE_URL`` env, then ``daemon_base_url`` in client
config (set by ``authsome onboard --base-url``), then the default from
``AuthsomeConfig``.
"""
configured = get_authsome_config(home).base_url.rstrip("/")
raw = (env or {}).get("AUTHSOME_BASE_URL", "").strip()
if raw:
return raw.rstrip("/") or configured
saved = ClientConfig.load(home).daemon_base_url
if saved:
return saved.rstrip("/")
return configured


def is_local_daemon_url(url: str) -> bool:
Expand Down
3 changes: 1 addition & 2 deletions src/authsome/cli/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
def register_commands(cli) -> None:
"""Attach command groups and root commands to the root CLI."""
cli.add_command(core_module.login)
cli.add_command(core_module.scan)
cli.add_command(core_module.onboard)
cli.add_command(core_module.logout)
cli.add_command(core_module.run)
cli.add_command(core_module.init)
cli.add_command(core_module.whoami)
cli.add_command(core_module.doctor)
cli.add_command(core_module.log_cmd)
Expand Down
Loading
Loading