diff --git a/docs/CLI.md b/docs/CLI.md new file mode 100644 index 0000000..30258da --- /dev/null +++ b/docs/CLI.md @@ -0,0 +1,254 @@ +# ZKAC CLI Guide + +This guide documents the `zkac-node` CLI and the related `zkac-node-i2p-server` helper, with practical workflows for creating users, issuing credentials, and authenticating. + +## Install + +From the repository root: + +```bash +# Build/install the zkac Python extension first. +maturin develop + +# Install CLI entrypoints. +pip install -e ./cli +``` + +Check installed commands: + +```bash +zkac-node --help +zkac-node-i2p-server --help +``` + +## Concepts + +- `userid` is your local identity name; each user is stored under `~/.zkac//`. +- `server` is always a network endpoint string in `host:port` form. +- Most management operations require pinning the server public key first. +- Credentials are granted directly over authenticated P2P delivery (`grant` -> `p2p-listen`). + +## Command Groups + +## `user` + +Manage local identities. + +```bash +zkac-node user create +zkac-node user list +zkac-node user show [--peer host:port] +``` + +- `create` generates issuance and transport keypairs. +- `show --peer host:port` embeds your receiving endpoint into a shareable contact bundle, used by admins when granting. + +## `serve` + +Run a ZKAC node server: + +```bash +zkac-node serve [--data-dir DIR] [--host HOST] [--port PORT] \ + [--max-connections N] [--idle-timeout SECONDS] [--listen-backlog N] \ + [--allow-non-loopback] +``` + +Defaults: `--host 127.0.0.1`, `--port 9800`, data at `~/.zkac//server/`. + +By default non-loopback binds are blocked unless you explicitly pass `--allow-non-loopback`. + +## `server pin` + +Pin a server transport public key per user: + +```bash +zkac-node server pin --key +``` + +Pins are exact string matches. If you connect with `example.b32.i2p:9800`, pin exactly that, not `localhost:9800`. + +## `registry` + +Manage registries you own: + +```bash +zkac-node registry create --roles role1,role2 +zkac-node registry update --registry --add-roles role3,role4 +zkac-node registry get --registry +zkac-node registry list +zkac-node registry revoke --registry --role +zkac-node registry revoke --registry --all +``` + +- `create` initializes a registry and stores local admin metadata. +- `update` adds new roles. +- `revoke` bumps role epoch(s), invalidating credentials for that role or all roles. + +## `grant` + +Grant one credential directly to a recipient: + +```bash +zkac-node grant --server --registry \ + --role --to "" +``` + +The `--to` bundle must include both: +- recipient issuance key and transport key +- grant pairing token and `peer` endpoint (from `user show --peer`) + +## `p2p-listen` + +Receive exactly one direct grant and store it locally: + +```bash +zkac-node p2p-listen [--host HOST] [--port PORT] [--timeout SECONDS] \ + [--allow-non-loopback] +``` + +Default bind is `127.0.0.1:9810`. + +## `credentials list` + +Show locally stored credentials: + +```bash +zkac-node credentials list +``` + +## `auth` + +Authenticate using a credential: + +```bash +zkac-node auth --registry --role [--server host:port] +``` + +If `--server` is omitted, the CLI tries to use server info from local admin metadata for that registry. + +## `net check` + +Connectivity diagnostics: + +```bash +zkac-node net check [--timeout SECONDS] [--handshake] [--userid ] [--key ] +``` + +- Without `--handshake`, this verifies TCP reachability. +- With `--handshake`, it additionally verifies anonymous ZKAC handshake. +- For handshake mode, provide either `--key` or `--userid` (not both). + +## End-to-End Workflow: Create, Grant, Receive, Authenticate + +Two users: `alice` (admin) and `bob` (recipient), one server on `localhost:9800`. + +1) Create users + +```bash +zkac-node user create alice +zkac-node user create bob +``` + +2) Start server (Alice host) + +```bash +zkac-node serve alice --host 127.0.0.1 --port 9800 +``` + +3) Pin server key for both users + +```bash +zkac-node server pin alice localhost:9800 --key +zkac-node server pin bob localhost:9800 --key +``` + +4) Bob shares contact bundle with peer endpoint + +```bash +zkac-node user show bob --peer 127.0.0.1:9810 +``` + +Copy the emitted contact blob from Bob to Alice through an out-of-band channel. + +5) Alice creates registry + +```bash +zkac-node registry create alice localhost:9800 --roles analyst,operator +``` + +Save the `registry_id` from command output. + +6) Bob starts one-shot receiver + +```bash +zkac-node p2p-listen bob --host 127.0.0.1 --port 9810 +``` + +7) Alice grants Bob `analyst` + +```bash +zkac-node grant alice --server localhost:9800 --registry \ + --role analyst --to "" +``` + +8) Bob verifies local credential + +```bash +zkac-node credentials list bob +``` + +9) Bob authenticates + +```bash +zkac-node auth bob --registry --role analyst --server localhost:9800 +``` + +## Workflow: Revoke a Role + +Revoke only one role: + +```bash +zkac-node registry revoke alice localhost:9800 --registry --role analyst +``` + +Revoke all roles: + +```bash +zkac-node registry revoke alice localhost:9800 --registry --all +``` + +After revocation, existing credentials for bumped epoch(s) no longer authenticate. + +## Workflow: I2P Connectivity + +Run server intended for I2P tunnel exposure: + +```bash +zkac-node-i2p-server alice --host 127.0.0.1 --port 9800 +``` + +For outbound client traffic to `.i2p` endpoints, configure SOCKS5: + +```bash +export ZKAC_SOCKS5_PROXY=127.0.0.1:4447 +``` + +Then use normal commands against `*.b32.i2p:port`: + +```bash +zkac-node net check exampledestination.b32.i2p:9800 +zkac-node net check exampledestination.b32.i2p:9800 --handshake --key +zkac-node auth bob --registry --role analyst --server exampledestination.b32.i2p:9800 +``` + +## Local Storage Layout + +Per user directory (`~/.zkac//`): + +```text +identity.json issuance + p2p transport identity data +admin/.json local admin material for owned registries +credentials/_.json received credentials +servers/sha256_*.json pinned server public keys +server/ server state if `serve` is run for this userid +```