ZKAC/cli/README.md
2026-05-06 17:39:11 +02:00

136 lines
4.9 KiB
Markdown

# zkac-node CLI
Install the `zkac` wheel from the repo root first (`maturin develop` or `pip install .`), then:
```bash
pip install -e ./cli
zkac-node --help
zkac-node-i2p-server --help
```
## Quick start
```bash
# 1. Create identities (one directory per user under ~/.zkac/<userid>/)
zkac-node user create alice
zkac-node user create bob
# Bob shares one contact string with Alice out-of-band:
# zkac-node user show bob --peer 127.0.0.1:9810
# 2. Alice runs a server; pin its public key for clients
zkac-node serve alice --port 9800 &
zkac-node server pin alice localhost:9800 --key <SERVER_PK_HEX>
zkac-node server pin bob localhost:9800 --key <SERVER_PK_HEX>
# 3. Alice creates a registry and grants Bob a role directly (needs Bob's contact string)
zkac-node registry create alice localhost:9800 --roles analyst,operator
zkac-node grant alice --server localhost:9800 \
--registry <REGISTRY_ID> --role analyst --to "$BOB_CONTACT"
# 4. Bob listens for direct p2p delivery
zkac-node p2p-listen bob --host 127.0.0.1 --port 9810
# 5. Bob lists local creds
zkac-node credentials list bob
# 6. Bob authenticates
zkac-node auth bob --registry <REGISTRY_ID> --role analyst --server localhost:9800
```
## Commands
| Command | Description |
|---------|-------------|
| `user create <id>` | Generate issuance keypair under `~/.zkac/<id>/` |
| `user list` | List all local user ids |
| `user show <id>` | Show issuance pk + owned registries + credentials |
| `serve <id> [--data-dir D]` | Run server; default data dir is `~/.zkac/<id>/server/` (loopback-only unless `--allow-non-loopback`) |
| `zkac-node-i2p-server <id> [--host H --port P]` | Same as `serve`, for I2P server-tunnel exposure (see below) |
| `server pin <id> <host:port> --key <hex>` | Pin server public key for that user |
| `registry create <id> <server> --roles …` | Create registry on server |
| `registry update <id> <server> --registry R --add-roles …` | Add roles |
| `registry get <id> <server> --registry R` | Fetch registry state |
| `registry list <id>` | List registries this user owns locally |
| `grant <id> --server S --registry R --role X --to <blob>` | Admin direct p2p grant (recipient contact bundle must include peer endpoint) |
| `p2p-listen <id> [--host H --port P]` | Receive one direct p2p grant and store credential (loopback-only unless `--allow-non-loopback`) |
| `credentials list <id>` | List local credentials |
| `auth <id> --registry R --role X [--server S]` | Authenticated session |
## Protocol & threat model
See [docs/SECURITY.md](../docs/SECURITY.md) in the repo root for the direct p2p grant model.
## Admin debug web UI (demo)
For a **fully transparent** HTTP dashboard (registry rows, live TCP sessions, data-dir
listing), run **`demo/zkac_admin_serve.py`** from the repo with **`uv sync --extra demo`**.
See [demo/README.md](../demo/README.md).
## Running over I2P
### Inbound: `zkac-node-i2p-server`
Run the node on a loopback TCP port and forward it from an **I2P server tunnel**
(I2P or i2pd). Clients use your published **`*.b32.i2p:port`** as the server
string in all `zkac-node` commands.
```bash
zkac-node-i2p-server alice --host 127.0.0.1 --port 9800
```
They should **pin** that same `host:port` string (the `.b32.i2p` form), not `localhost`.
### Outbound clients
Outbound client connections can be proxied through an I2P SOCKS tunnel.
1. Start I2P/i2pd SOCKS proxy (commonly `127.0.0.1:4447`).
2. Export:
```bash
export ZKAC_SOCKS5_PROXY=127.0.0.1:4447
```
If the destination ends in `.i2p` and `ZKAC_SOCKS5_PROXY` is not set, `zkac-node` fails fast instead of attempting a direct clearnet connect.
3. Use `.b32.i2p:port` endpoints with normal commands:
```bash
zkac-node registry get alice exampledestination.b32.i2p:9800 --registry <REGISTRY_ID>
zkac-node auth bob --registry <REGISTRY_ID> --role analyst --server exampledestination.b32.i2p:9800
```
For inbound direct grants, run `p2p-listen` on a local port and expose it via an I2P inbound tunnel. Peers dial your published I2P destination/port; your tunnel forwards to local `host:port`.
`p2p-listen` now refuses non-loopback binds by default (use `--allow-non-loopback` only when intentional).
Connectivity sanity check:
```bash
zkac-node net check exampledestination.b32.i2p:9800
zkac-node net check exampledestination.b32.i2p:9800 --handshake --key <SERVER_PK_HEX>
# or use an existing pin:
zkac-node net check exampledestination.b32.i2p:9800 --handshake --userid alice
```
With proxy:
```bash
export ZKAC_SOCKS5_PROXY=127.0.0.1:4447
zkac-node net check exampledestination.b32.i2p:9800
```
## Storage layout
Per user `~/.zkac/<userid>/`:
```
identity.json issuance keypair
p2p transport keypair
admin/<registry_id>.json BBS+ admin material for owned registries
credentials/<rid>_<role>.json received credentials
servers/sha256_<...>.json pinned server public keys (includes original server string)
server/ (only if you run `serve <userid>`) server_key.json, registries/
```