### `wai key`: a developer's signing keys in one keystore, and `--key <name>` on the operations that sign

- **Seven operations**, in the catalogue and in `wai/catalogue/ops.json`: `key.create`, `key.list`,
  `key.show`, `key.rotate`, `key.revoke`, `key.import` and `key.export` (`wai key
  create|list|show|rotate|revoke|import|export`), each with `--json`, and with `--dry-run` where
  it changes something; `--yes` is never implied. They run on this machine, in a build with
  `quickstart`, which the release archive's `wai` is. `wai mcp` does not serve them.
- **Where keys live.** One keystore, a directory: `--keystore DIR`, `$WAI_KEYSTORE`,
  `$XDG_CONFIG_HOME/wai/keys` or `~/.config/wai/keys` (`%APPDATA%\wai\keys` on Windows), made with
  mode 0700. Each key is a record, `<name>.json` (format `wai.key/1`), holding public halves alone.
  Each secret is kept where `--store` says: `keychain`, the default on macOS, in the login
  keychain through `/usr/bin/security`, the secret on the tool's standard input and never on a
  command line; or `file`, the default elsewhere, `<key-id>.seed`. No operation prints a secret.
  `--store keychain` on another system is refused (`keychain-unavailable`): the keychain of macOS
  is the only one `wai` uses, and on Linux and Windows the secret is in the file.
- **What protects a seed file.** On Unix, its mode: it is made with 0600, the keystore with 0700. On
  Windows, an access list: the seed, the record and a keystore `wai` makes each have this account as
  owner and as their one entry, with inheritance off, so a keystore in `C:\Users\Public` gets what
  one in `%APPDATA%` gets. SYSTEM and Administrators are not listed: nothing here needs them. Either
  way the call that makes the file restricts it, before the secret is written. A seed file another
  account may read is refused, exit 3, `key-file-exposed`, naming the file and the command that fixes
  it: on Unix any mode bit for group or other, and on Windows any entry granting another account
  anything, read by SID, or another account as its owner. The seed is not encrypted on either system.
- **The keychain path runs against the real tool.** A test on macOS drives `/usr/bin/security` in a
  scratch keychain it makes and removes in every case, never the login keychain: an item kept, read
  back, replaced through `-U` and removed, no secret on any process argument, and the search list
  and the default keychain as they were. `wai-key-keychain.yml` runs that test alone, on a pull
  request whose own diff changes `dx/key.rs` or the workflow.
- **WAI's own key rules** (extensions/jwp-receipts.md §7). A key's first version has its name as
  its key id, and each rotation adds `<name>.<n>`. A version's status is the key log's: `active`,
  `retired` with `until`, or `revoked` with `compromised_since`. `wai key rotate` makes the
  successor under a new id and retires the old version at that moment (§7.6); `wai key revoke`
  revokes the newest version or `--id`'s, from `--compromised-since` or now, and its time never
  changes after. Each destroys the secret of the version it ends, so each waits for `--yes`. No two
  keys of a keystore hold one public key (`key-duplicate`).
- **A published seed.** `wai key import` refuses a seed of one byte repeated 32 times, the form of
  every seed WAI publishes (§7.8), unless `--published-test-seed` names it a test key, and the
  record says so.
- **Into a key log.** `wai key export` gives the public half alone: `hex`, `did-key`, `entry` (each
  version as a key-log entry, with the authorities `--may-sign` names) or `wai-keys` (the newest,
  as `wai-keys init --key` and `append --add` take it). `wai-keys` itself is unchanged, and still
  makes no key. A test builds a log from what `wai key` exports and verifies it.
- **How other commands find a key.** `--key <name>` signs with the key's newest version on `wai
  enrolment create`, `wai channel import`, `wai contract create|accept`, `wai statement
  create|check`, `wai opportunity create`, `wai upscale run`, `wai tonemap run`, `wai encode avc|hevc`,
  `wai http seal-playlist` and `wai conform`. A path that exists is still read as a key file first,
  so a command that ran before runs the same. A revoked key signs nothing (exit 2, `key-revoked`).
- **Not folded.** `wai package build` hands `--key` to `wai-pack`, which reads a file. `wai-keys`,
  `wai-room keygen`, `wai-remote-host key`, `wai-key-proxy keygen`, `wai-audit key`, `wai-ledger
  key` and `wai-quantum key` keep their own keys and verbs, and `wai keylog` is not built.
