docs(rust): add TUTORIAL.md — friendly step-by-step for first-time users
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>
This commit is contained in:
parent
7bbf8baf86
commit
d10dfb93f2
@ -41,6 +41,12 @@ Three crates, ~2,500 lines of Rust, **99 tests**.
|
|||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
|
> **New to KEZ?** Read [**`TUTORIAL.md`**](TUTORIAL.md) — a friendly
|
||||||
|
> step-by-step walkthrough that takes you from "I have a nostr `nsec`"
|
||||||
|
> to "I have a verified, published sigchain." It assumes nothing.
|
||||||
|
>
|
||||||
|
> This README is the reference; the tutorial is the on-ramp.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Build, test, and install the `kez` binary to ~/.cargo/bin (one time)
|
# Build, test, and install the `kez` binary to ~/.cargo/bin (one time)
|
||||||
cargo build
|
cargo build
|
||||||
|
|||||||
557
rust/TUTORIAL.md
Normal file
557
rust/TUTORIAL.md
Normal file
@ -0,0 +1,557 @@
|
|||||||
|
# Tutorial — your first KEZ identity, end to end
|
||||||
|
|
||||||
|
This is a hands-on walkthrough. By the end you'll have:
|
||||||
|
|
||||||
|
- ✅ A KEZ identity tied to a key you already trust (your existing nostr
|
||||||
|
`nsec`, or a brand-new Ed25519 key).
|
||||||
|
- ✅ A signed proof that *you* control a GitHub account (or DNS domain, or
|
||||||
|
nostr handle, etc.) — verifiable by anyone, no central server needed.
|
||||||
|
- ✅ A sigchain that ties multiple identities together, exported in a
|
||||||
|
portable format, and published where strangers can find it.
|
||||||
|
- ✅ The ability to verify other people's identities the same way.
|
||||||
|
|
||||||
|
If you've used [Keybase](https://keybase.io), the mental model is the same.
|
||||||
|
The difference: KEZ has no required central authority. Your proofs live
|
||||||
|
wherever you publish them; the verifier just walks the links.
|
||||||
|
|
||||||
|
For the full protocol spec, see [`../SPEC.md`](../SPEC.md). This document
|
||||||
|
is the friendly cousin.
|
||||||
|
|
||||||
|
> **Time budget:** 10–15 minutes for the first claim. A bit more if you
|
||||||
|
> want to set up DNS or a sigchain publish.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://git.ptud.biz/DukeInc/Kez.git
|
||||||
|
cd Kez/rust
|
||||||
|
cargo build --release
|
||||||
|
cargo install --path crates/kez-cli # puts `kez` in ~/.cargo/bin
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez --help
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see subcommands `identity`, `claim`, `verify`, and `sigchain`.
|
||||||
|
|
||||||
|
> **Don't want to install globally?** Replace every `kez` below with
|
||||||
|
> `cargo run -p kez-cli --` (from the `rust/` directory). Slower to
|
||||||
|
> start each time, but no install side effects.
|
||||||
|
|
||||||
|
> **Optional but recommended:** `export GITHUB_TOKEN=ghp_...` in your
|
||||||
|
> shell before verifying github claims. Anonymous GitHub limits you to
|
||||||
|
> 60 requests/hour; with a token it's 5000/hour. Any read-only token
|
||||||
|
> works; KEZ never sends it anywhere but `api.github.com`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Pick your primary key
|
||||||
|
|
||||||
|
Your **primary key** is the one private key the rest of your identity
|
||||||
|
hangs off of. It signs every claim you make. Two choices:
|
||||||
|
|
||||||
|
### Option A: use your existing nostr key (recommended if you have one)
|
||||||
|
|
||||||
|
If you already use nostr (Damus, Amethyst, primal, etc.), you already
|
||||||
|
have an `nsec1...` private key. Use it. KEZ understands nostr keys
|
||||||
|
natively as Schnorr/secp256k1.
|
||||||
|
|
||||||
|
Export the `nsec` from your nostr client (every client has a way —
|
||||||
|
usually Settings → Keys → Show / Export). Keep it secret; treat it the
|
||||||
|
same as a wallet seed.
|
||||||
|
|
||||||
|
> **Warning.** Pasting your `nsec` into a CLI is fine on a machine you
|
||||||
|
> trust. Don't do it on a shared box, and consider whether you want
|
||||||
|
> shell history to remember it (`unset HISTFILE` for the session, or
|
||||||
|
> prefix the command with a space if `HISTCONTROL=ignorespace`).
|
||||||
|
|
||||||
|
You can confirm KEZ accepts your key without signing anything yet:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez identity new --key-type nostr # only if you want a NEW key
|
||||||
|
# vs.
|
||||||
|
# (no command needed to "register" an existing nsec — just pass it
|
||||||
|
# directly with --nsec on the first claim you sign)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option B: generate a fresh Ed25519 primary
|
||||||
|
|
||||||
|
If you'd rather start clean, generate a new Ed25519 key:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez identity new --key-type ed25519
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
Primary: ed25519:7a3b4c…
|
||||||
|
Public: 7a3b4c… (hex)
|
||||||
|
Secret: 9e3f51… (hex — 64 chars, KEEP SECRET)
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Save the secret.** It's the only thing that can sign as this
|
||||||
|
> identity. There's no recovery flow — lose it and the identity is
|
||||||
|
> gone. Write it down offline, or paste it into a password manager.
|
||||||
|
> From here on this tutorial assumes you stored it.
|
||||||
|
|
||||||
|
For the rest of this tutorial we'll use a nostr key for examples and
|
||||||
|
write the secret as `nsec1FAKE...` — substitute your real one.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Sign your first claim
|
||||||
|
|
||||||
|
A **claim** is just a signed sentence: *"the key I signed this with also
|
||||||
|
controls `<subject>`."* The subject is a `system:identifier` string —
|
||||||
|
`github:tudisco`, `dns:tud.ink`, `nostr:npub1…`, etc.
|
||||||
|
|
||||||
|
Say you want to prove you control the GitHub username `tudisco`.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez claim create github:tudisco \
|
||||||
|
--nsec nsec1FAKE... \
|
||||||
|
--format markdown \
|
||||||
|
--out github-tudisco.kez.md
|
||||||
|
```
|
||||||
|
|
||||||
|
That writes a file like:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# KEZ Proof
|
||||||
|
|
||||||
|
This account publishes a signed KEZ identity claim.
|
||||||
|
|
||||||
|
- Primary: `nostr:npub1tkf…`
|
||||||
|
- Subject: `github:tudisco`
|
||||||
|
- Created: `2026-05-27T19:21:46Z`
|
||||||
|
|
||||||
|
```kez
|
||||||
|
{
|
||||||
|
"kez": "claim",
|
||||||
|
"payload": { ... },
|
||||||
|
"signature": {
|
||||||
|
"alg": "ed25519-sha512-jcs" / "nostr-schnorr-bip340-jcs",
|
||||||
|
"key": "nostr:npub1tkf…",
|
||||||
|
"sig": "abc123…"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
### Picking the right format
|
||||||
|
|
||||||
|
Same claim, three packagings — same signature inside:
|
||||||
|
|
||||||
|
| Format | When to use | Command |
|
||||||
|
|---|---|---|
|
||||||
|
| **markdown** | Anywhere you can paste rich text — gists, profile READMEs, social posts. Most human-readable. | `--format markdown` |
|
||||||
|
| **compact** | Tight places: DNS TXT records, QR codes, chat messages. One-liner that decompresses back to the full envelope. | `--format compact` |
|
||||||
|
| **json** | Self-hosted `.well-known/kez.json`, developer tooling, anything that wants the raw envelope. | (default — no flag needed) |
|
||||||
|
|
||||||
|
If you skip `--out`, the proof prints to stdout — handy for piping.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Publish the proof
|
||||||
|
|
||||||
|
This is where KEZ does its job: you put the signed claim in a place that
|
||||||
|
only *that specific account* could have put it. Anyone who can fetch
|
||||||
|
that place can then verify it themselves.
|
||||||
|
|
||||||
|
Pick the section that matches the subject system you claimed.
|
||||||
|
|
||||||
|
### GitHub
|
||||||
|
|
||||||
|
You signed `github:tudisco`. Publish the markdown block to either:
|
||||||
|
|
||||||
|
**A public gist named `kez.md`** — easiest.
|
||||||
|
1. Go to <https://gist.github.com/>.
|
||||||
|
2. New gist → filename `kez.md` → paste the contents of
|
||||||
|
`github-tudisco.kez.md`.
|
||||||
|
3. Click **Create public gist**.
|
||||||
|
|
||||||
|
**Or your profile README** — fancier but you only get one.
|
||||||
|
1. Make a repo named the same as your username (e.g.
|
||||||
|
`tudisco/tudisco`). GitHub treats it as your profile README.
|
||||||
|
2. Add the markdown block to `README.md`.
|
||||||
|
3. Push.
|
||||||
|
|
||||||
|
KEZ's GitHub verifier checks public gists first, then the profile
|
||||||
|
README.
|
||||||
|
|
||||||
|
### DNS — your own domain
|
||||||
|
|
||||||
|
You signed `dns:tud.ink`. The CLI generates a ready-to-paste zone-file
|
||||||
|
line for you:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez claim dns tud.ink --nsec nsec1FAKE...
|
||||||
|
```
|
||||||
|
|
||||||
|
Output (abbreviated):
|
||||||
|
|
||||||
|
```
|
||||||
|
_kez.tud.ink. 3600 IN TXT
|
||||||
|
"kez:z1:KLUv_WAsACUHAD…<chunk 1>…"
|
||||||
|
"<chunk 2>…"
|
||||||
|
```
|
||||||
|
|
||||||
|
Add that TXT record at `_kez.<your-domain>` in your DNS provider's
|
||||||
|
console (Cloudflare, Route 53, Gandi, Porkbun — wherever you registered
|
||||||
|
the domain). Most providers will accept the whole compact string in one
|
||||||
|
field and split it for you; the multi-chunk form above is the safe one
|
||||||
|
for providers that don't.
|
||||||
|
|
||||||
|
Wait a minute or two for propagation, then you can verify it.
|
||||||
|
|
||||||
|
### Nostr — your own npub
|
||||||
|
|
||||||
|
You signed `nostr:npub1...`. Three places work (verifiers check all of
|
||||||
|
them):
|
||||||
|
|
||||||
|
- **Profile `about` field** (kind-0 event) — easiest, one-time. Edit
|
||||||
|
your nostr profile and paste the markdown block into your bio.
|
||||||
|
- **A normal post** (kind-1) containing the markdown block — quickest if
|
||||||
|
you're already active.
|
||||||
|
- **A NIP-78 kind-30078 event** with `d` tag = `kez` — cleanest for
|
||||||
|
tooling, but most clients don't expose it.
|
||||||
|
|
||||||
|
### Bluesky
|
||||||
|
|
||||||
|
Post the markdown block (or just the compact `kez:z1:…` string) as a
|
||||||
|
public post on the account you claimed. The verifier scans your recent
|
||||||
|
posts.
|
||||||
|
|
||||||
|
### Mastodon / ActivityPub
|
||||||
|
|
||||||
|
You signed `ap:@user@instance`. Add the markdown block to your profile
|
||||||
|
**metadata** field (most instances expose 4 of them), or post it as a
|
||||||
|
pinned toot. The verifier resolves via WebFinger → actor JSON → checks
|
||||||
|
those fields.
|
||||||
|
|
||||||
|
### Your own website
|
||||||
|
|
||||||
|
You signed `web:https://example.com`. Upload the JSON form to
|
||||||
|
`https://example.com/.well-known/kez.json`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez claim create web:https://example.com --nsec nsec1FAKE... > kez.json
|
||||||
|
scp kez.json youruser@example.com:/var/www/.well-known/kez.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure it's publicly fetchable (no auth gate).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Verify it
|
||||||
|
|
||||||
|
This is the moment of truth. Pretend you're a stranger checking that the
|
||||||
|
claim is real:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez verify id github:tudisco
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
Primary: nostr:npub1tkf...
|
||||||
|
|
||||||
|
Verified identities:
|
||||||
|
- github:tudisco
|
||||||
|
|
||||||
|
Status: valid
|
||||||
|
Confidence: strong
|
||||||
|
```
|
||||||
|
|
||||||
|
Same shape for any channel:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez verify id dns:tud.ink
|
||||||
|
kez verify id nostr:npub1tkf...
|
||||||
|
kez verify id bluesky:tudisco.bsky.social
|
||||||
|
kez verify id ap:@tudisco@mastodon.social
|
||||||
|
kez verify id web:https://tud.ink
|
||||||
|
```
|
||||||
|
|
||||||
|
The verifier:
|
||||||
|
|
||||||
|
1. Figured out which channel from the prefix.
|
||||||
|
2. Fetched the proof from where you published it (gist, TXT, etc.).
|
||||||
|
3. Decoded the envelope.
|
||||||
|
4. Verified the cryptographic signature against the key inside.
|
||||||
|
|
||||||
|
**No KEZ server was involved.** Each side of the conversation independently
|
||||||
|
proves the claim — that's the whole point.
|
||||||
|
|
||||||
|
### If verification fails
|
||||||
|
|
||||||
|
A few common ones:
|
||||||
|
|
||||||
|
- **`not_found`** — the proof isn't where the verifier looked. For
|
||||||
|
GitHub, check the gist is public and the filename contains `kez`. For
|
||||||
|
DNS, the TXT record is at `_kez.<domain>`, not `<domain>` itself; give
|
||||||
|
propagation a minute.
|
||||||
|
- **`subject_mismatch`** — you published a proof for one subject but
|
||||||
|
asked the verifier to check a different one. The claim's `subject`
|
||||||
|
must equal the identifier you're verifying.
|
||||||
|
- **`invalid_signature`** — the proof was tampered with, or you
|
||||||
|
re-signed with a different key after publishing. Re-sign and
|
||||||
|
re-publish.
|
||||||
|
- **GitHub `403 rate_limited`** — anonymous gets 60 req/hr; export
|
||||||
|
`GITHUB_TOKEN`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Sigchain — link multiple identities together
|
||||||
|
|
||||||
|
A **sigchain** is an append-only log of "this key controls X" events,
|
||||||
|
each signed by your primary. Once you have more than one claim, you
|
||||||
|
want a sigchain so:
|
||||||
|
|
||||||
|
- Verifiers can discover your full identity graph from a single
|
||||||
|
starting point.
|
||||||
|
- You can later **revoke** a claim (e.g., you lost access to that
|
||||||
|
github account) without invalidating the others.
|
||||||
|
- Old events stay verifiable; the chain head is the current truth.
|
||||||
|
|
||||||
|
Chains live at `~/.kez/sigchains/<safe-primary>.jsonl`. The CLI creates
|
||||||
|
the directory on first use; you don't manage it manually.
|
||||||
|
|
||||||
|
Add the github claim you already signed:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain add github:tudisco --nsec nsec1FAKE...
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a DNS claim too:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain add dns:tud.ink --nsec nsec1FAKE...
|
||||||
|
```
|
||||||
|
|
||||||
|
You can optionally include a `--proof-url` pointing to where you
|
||||||
|
published this claim's proof (your gist URL, etc.). Verifiers can use
|
||||||
|
it to skip discovery.
|
||||||
|
|
||||||
|
Inspect what you've got:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain show --nsec nsec1FAKE...
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
Primary: nostr:npub1tkf...
|
||||||
|
Path: /home/you/.kez/sigchains/nostr_npub1tkf….jsonl
|
||||||
|
Length: 2 events
|
||||||
|
Head: sha256:9c3a…
|
||||||
|
Events:
|
||||||
|
1. add github:tudisco proof_url=https://gist.github.com/tudisco/abc
|
||||||
|
2. add dns:tud.ink
|
||||||
|
```
|
||||||
|
|
||||||
|
Read-only view of a published chain (no secret needed):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain show --primary nostr:npub1tkf...
|
||||||
|
```
|
||||||
|
|
||||||
|
This is what other people will do to inspect your identity graph.
|
||||||
|
|
||||||
|
### Revoking
|
||||||
|
|
||||||
|
If you ever lose control of an account (your github gets hacked, you
|
||||||
|
sell a domain), revoke that subject:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain revoke github:tudisco --nsec nsec1FAKE...
|
||||||
|
```
|
||||||
|
|
||||||
|
That appends a revoke event. Subsequent verifications treat that subject
|
||||||
|
as "no longer claimed" by your primary, even if the old proof is still
|
||||||
|
out there.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Publish your sigchain
|
||||||
|
|
||||||
|
Now make your chain discoverable so anyone with your primary can walk
|
||||||
|
it. Options, in rough order of how much infra they need:
|
||||||
|
|
||||||
|
### To a kez-sig-server (zero setup)
|
||||||
|
|
||||||
|
If you have access to a [`kez-sig-server`](../rust-sig-server/) (one
|
||||||
|
runs at `https://sig.kez.lat`):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain publish --nsec nsec1FAKE... \
|
||||||
|
--server https://sig.kez.lat
|
||||||
|
```
|
||||||
|
|
||||||
|
Each event is POSTed to the server, which exposes them at predictable
|
||||||
|
URLs. Cheap, fast, but you're trusting that server to stay up. Mitigate
|
||||||
|
by also publishing to one of the channels below.
|
||||||
|
|
||||||
|
### To your own website (self-sovereign)
|
||||||
|
|
||||||
|
Export the chain bundle and host it yourself:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain publish --nsec nsec1FAKE... \
|
||||||
|
--web --out kez-sigchain.jsonl
|
||||||
|
```
|
||||||
|
|
||||||
|
Then upload `kez-sigchain.jsonl` to
|
||||||
|
`https://<your-domain>/.well-known/kez-sigchain.jsonl`. Verifiers
|
||||||
|
fetch it directly. Hardest to censor; you own it.
|
||||||
|
|
||||||
|
### To DNS
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain publish --nsec nsec1FAKE... --dns tud.ink
|
||||||
|
```
|
||||||
|
|
||||||
|
Prints a TXT record at `_kez-chain.<domain>` containing the
|
||||||
|
compressed chain. Add it to your zone. Works for short chains; for
|
||||||
|
long chains, prefer `--web` (TXT records are size-limited).
|
||||||
|
|
||||||
|
### To nostr
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain publish --nsec nsec1FAKE... \
|
||||||
|
--nostr wss://relay.damus.io
|
||||||
|
```
|
||||||
|
|
||||||
|
Publishes the compact bundle as a kind-30078 event on that relay. Any
|
||||||
|
nostr client / verifier subscribed can find it.
|
||||||
|
|
||||||
|
### Pick more than one
|
||||||
|
|
||||||
|
`publish` accepts any combination of these flags — you can mirror to
|
||||||
|
all four in one shot:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain publish --nsec nsec1FAKE... \
|
||||||
|
--server https://sig.kez.lat \
|
||||||
|
--web --out kez-sigchain.jsonl \
|
||||||
|
--dns tud.ink \
|
||||||
|
--nostr wss://relay.damus.io
|
||||||
|
```
|
||||||
|
|
||||||
|
Redundancy is good. If one channel goes down, the others still serve
|
||||||
|
your identity graph.
|
||||||
|
|
||||||
|
### Export-only (no publish)
|
||||||
|
|
||||||
|
If you want to see the bundle without publishing:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez sigchain export --nsec nsec1FAKE... --format compact > my-chain.txt
|
||||||
|
kez sigchain export --nsec nsec1FAKE... --format jsonl > my-chain.jsonl
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Verifying someone else
|
||||||
|
|
||||||
|
You've done the publishing side. Here's the receiving side — how to
|
||||||
|
verify someone *else's* identity:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Start from any identifier they've published a proof for.
|
||||||
|
kez verify id github:linus
|
||||||
|
|
||||||
|
# Or walk their chain from any known endpoint:
|
||||||
|
kez sigchain show --primary nostr:npub1abc...
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have the chain bundle on disk:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kez verify file ./their-chain.jsonl
|
||||||
|
```
|
||||||
|
|
||||||
|
`verify id` is the friendly day-to-day verb. `sigchain show
|
||||||
|
--primary <id>` is what you'd reach for to see the whole graph at once.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Quick reference card
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Generate a fresh primary
|
||||||
|
kez identity new
|
||||||
|
kez identity new --key-type ed25519
|
||||||
|
|
||||||
|
# Sign a claim
|
||||||
|
kez claim create <subject> --nsec <nsec> # nostr key
|
||||||
|
kez claim create <subject> --ed25519-seed <hex-seed> # ed25519 key
|
||||||
|
kez claim create <subject> --nsec <nsec> --format markdown --out file.md
|
||||||
|
kez claim create <subject> --nsec <nsec> --format compact # one-liner
|
||||||
|
kez claim dns <domain> --nsec <nsec> # zone-file output
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
kez verify id <subject> # live channel fetch
|
||||||
|
kez verify file <path> # local file
|
||||||
|
|
||||||
|
# Sigchain
|
||||||
|
kez sigchain add <subject> --nsec <nsec> [--proof-url <url>]
|
||||||
|
kez sigchain revoke <subject> --nsec <nsec>
|
||||||
|
kez sigchain show --nsec <nsec> # your own
|
||||||
|
kez sigchain show --primary <id> # someone else's
|
||||||
|
kez sigchain export --nsec <nsec> --format jsonl|compact [--out file]
|
||||||
|
kez sigchain publish --nsec <nsec> \
|
||||||
|
[--server <url>] [--web --out <path>] [--dns <domain>] [--nostr <relay>]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Common confusions
|
||||||
|
|
||||||
|
**"Do I need a sigchain to use KEZ?"** No. A single signed claim,
|
||||||
|
published, works on its own. The sigchain is for when you have several
|
||||||
|
claims and want them discoverable together (and revocable).
|
||||||
|
|
||||||
|
**"Why two key types — nostr and ed25519?"** Different ecosystems use
|
||||||
|
different curves. Nostr is secp256k1/Schnorr; the rest of the world
|
||||||
|
mostly likes Ed25519. KEZ supports both natively so you can use the
|
||||||
|
key you already have rather than spinning up a new one for KEZ
|
||||||
|
specifically.
|
||||||
|
|
||||||
|
**"Is my `nsec` sent to KEZ servers?"** No, never. The CLI uses it
|
||||||
|
locally to sign things. Only the *signed envelope* (public key + claim
|
||||||
|
+ signature) ever leaves your machine.
|
||||||
|
|
||||||
|
**"What if I publish a proof and then someone else copies it and
|
||||||
|
publishes it as theirs?"** They can copy the bytes, but the signature
|
||||||
|
inside is over *your* primary. Their primary won't match, so any
|
||||||
|
verifier sees through it immediately.
|
||||||
|
|
||||||
|
**"What if my key is compromised?"** Append a `sigchain revoke
|
||||||
|
<subject>` for the affected subjects, and ideally rotate to a new
|
||||||
|
primary by signing a final "this primary is succeeded by <new>" event
|
||||||
|
(planned for the spec; not yet enforced by the CLI in v0.1).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Where to go next
|
||||||
|
|
||||||
|
- The web client at <https://kez.lat> — same protocol, no CLI.
|
||||||
|
Useful for showing non-technical friends.
|
||||||
|
- [`../SPEC.md`](../SPEC.md) — the formal protocol, if you want to know
|
||||||
|
exactly what every byte means.
|
||||||
|
- [`../rust-sig-server/`](../rust-sig-server/) — run your own
|
||||||
|
sig-server, federate with others.
|
||||||
|
- The channel plugin trait in
|
||||||
|
[`crates/kez-channels/src/lib.rs`](crates/kez-channels/src/lib.rs) —
|
||||||
|
~40 lines, add a new channel in an afternoon.
|
||||||
|
|
||||||
|
That's the whole tutorial. Welcome to KEZ.
|
||||||
Loading…
x
Reference in New Issue
Block a user