The existing README is a solid reference but assumes you already know
what KEZ is and what each subcommand does. Add a parallel TUTORIAL.md
that takes a complete newcomer from "I have a nostr nsec" to "I have
a published, verified sigchain" in ~15 minutes.
Sections (~500 lines):
0. Install (incl. cargo-run alternative + GITHUB_TOKEN tip)
1. Pick your primary key — use your existing nsec (recommended) OR
generate a fresh ed25519. Concrete warnings about nsec handling.
2. Sign your first claim — full markdown/compact/json walkthrough
with a real github:tudisco example.
3. Publish the proof — separate concrete how-tos per channel:
github (gist + profile README), DNS (zone-file output), nostr
(3 places it can live), bluesky, ActivityPub, your own website.
4. Verify it — `kez verify id` + a full "if verification fails"
troubleshooting block (not_found, subject_mismatch, bad sig,
github rate limit).
5. Sigchain basics — when you actually need one, add/show/revoke,
where chain files live on disk.
6. Publish your sigchain — server, web (.well-known), DNS,
nostr (kind-30078), and how to combine destinations.
7. Verify someone else — the reverse direction (verify id, walk
a chain by --primary, verify a chain bundle from disk).
8. Quick-reference command card.
9. Common confusions FAQ — sigchain optional? two key types?
nsec leakage? proof copying? key rotation?
10. Where to go next — kez.lat, SPEC.md, sig-server, channel plugin
trait.
All commands cross-checked against crates/kez-cli/src/main.rs (every
flag and output format quoted in the tutorial actually exists in the
binary).
README now points to TUTORIAL.md as the on-ramp; the existing reference
content stays put.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rename the CLI binary from `kez-cli` to `kez` (via a [[bin]] section in
the package's Cargo.toml; package name and `-p kez-cli` invocations stay
the same so the workspace build, tests, and the cross-test harness are
unaffected).
Then update the READMEs to recommend `cargo install --path` once at the
top of Quick Start, after which every example is the much shorter
`kez ...` form. Mention `cargo run -p kez-cli --` as the dev iteration
alternative for anyone who doesn't want to install.
- rust/README.md: 11 `cargo run -p kez-cli --` → `kez` substitutions,
plus a stale "81 tests" → "99 tests" fix.
- README.md (root): Quick start gains a `cargo install` line.
- rust-sig-server/README.md: Quick start uses `kez-sig-server`
(post-install) with `cargo run` as the dev alternative; "Try it"
section rewritten to use the actual `kez sigchain` CLI (which now
exists) instead of the stale "hand-build via kez-core" workaround.
The Keybase-comparison line said "KEZ has no central server," which is
misleading now that the rust-sig-server exists. Reframe it as "no
*required* central server" — the chain server is a convenience tier,
not a trust authority, and the protocol works identically whether the
sigchain lives there or in a gist / DNS / nostr event / well-known URL.
KEZ is a portable, decentralized identity graph: a person signs claims
linking their many accounts, publishes those claims in places only the
claimed account can publish to, and anyone can verify the connections
without trusting a central server.
Layout
------
- SPEC.md Language-agnostic protocol spec (v0.2)
- rust/ Rust implementation: kez-core, kez-channels, kez-cli
- nodejs/ TypeScript port at full parity
- rust-sig-server/ Optional axum + SQLite storage server for sigchains
- crosstest.sh Cross-implementation interop harness
Capabilities (both implementations, byte-compatible)
----------------------------------------------------
- Two primary-key algorithms: nostr/secp256k1 Schnorr (BIP-340) and
Ed25519 (RFC 8032). Identifiers: nostr:npub1... and ed25519:<hex>.
- JCS (RFC 8785) canonicalization for everything signed.
- Four proof encodings: JSON envelope, compact (kez:z1:<base64url(zstd(json))>),
Markdown fence, DNS TXT.
- Five channel plugins (no API keys, no auth needed for any of them):
dns: system resolver, _kez.<domain> TXT records
github: public gist scan + <user>/<user> profile README fallback
nostr: kind-30078 events from default relays
bluesky: public AppView author feed
ap: WebFinger + actor JSON (alias mastodon:)
- Identical CLI surface:
kez identity new [--key-type nostr|ed25519]
kez claim create <subject> (--nsec | --ed25519-seed) [--format ...] [--out ...]
kez claim dns <domain> (--nsec | --ed25519-seed)
kez verify file <path>
kez verify id <identifier>
kez sigchain add|revoke|show|export|publish
- Sigchains: append-only signed log per primary, hash-chained per spec §6,
stored locally at ~/.kez/sigchains/, exportable as JSONL or kez:zc1: bundle.
- Sigchain publish destinations: chain server, web (file dump), DNS (zone
record print), nostr (kind-30078 wrapping event).
kez-sig-server
--------------
Optional storage tier. Axum + SQLite, single binary, no external deps.
- No auth — the cryptography is the access control. The server validates
every signature, every seq, every prev hash before storing.
- REST API: POST /v1/sigchains/{scheme}/{id}/events (append signed event,
201 with new head hash or 4xx); GET /{scheme}/{id} (full chain as JSONL);
GET /head; GET /healthz.
- Designed for one central instance for now; the design doesn't preclude
running more later (clients gain a configurable list, verifiers
reconcile per spec §6.2).
- Channel-based publishing remains the always-available fallback if the
server is unavailable.
Tests
-----
- rust/ 99 tests
- rust-sig-server/ 10 integration tests (real HTTP, real SQLite)
- nodejs/ 91 tests (vitest)
- crosstest.sh 19 cross-impl scenarios — proves JCS bytes,
Schnorr + Ed25519 sigs, all four claim encodings,
and the sigchain JSONL bundle are byte-compatible
between Rust and Node in both directions.
What's not done yet
-------------------
- verify id consulting the sigchain for revocations (data path exists,
just not wired into the verifier output).
- rotate and add_device sigchain ops (types reserved).
- expires_at enforcement during claim verification.
- Typed VerificationStatus.status reflecting the five failure modes.
- Auth-required publishers (GitHub gist, Bluesky, ActivityPub).