# Changelog
## 0.2.0 — delegate → notary rename
The PKI intermediate signing key has been renamed from "delegate" to
"notary" throughout the `ghostkey_lib` source API, the `ghostkey` CLI,
the `ghostkey-api` server, and the Freenet.org Hugo site. The rename is
tracked in [freenet/web#24](https://github.com/freenet/web/issues/24) and
deconflicts with Freenet's own `Delegate` concept (sandboxed WASM agents).
### Why 0.2.0 and not 0.1.5
Public struct fields on `NotaryCertificateV1`, `NotaryPayload`, and
`GhostkeyCertificateV1` have been renamed (`.delegate` → `.notary`,
`.delegate_verifying_key` → `.notary_verifying_key`). Downstream code that
accesses those fields directly will no longer compile against the new
version. Under pre-1.0 Rust semver, `0.1.x → 0.1.y` is the compatible
range, so Cargo would auto-upgrade downstream crates and break their builds;
`0.1.x → 0.2.0` is the breaking range and requires explicit opt-in. This
is a breaking bump to make that opt-in explicit.
### Wire-format compatibility
This is a **source-API rename only**. Ghost-key certificates minted by
earlier releases continue to parse, verify, and round-trip byte-identically
under 0.2.0. A regression test suite in `tests/legacy_v1_compat.rs` loads
real fixtures generated by pre-rename code and asserts the freeze.
### Terminology — notary vs delegate vs vault
Three distinct concepts, all worth calling out because they collide:
- **notary certificate** (this crate) — the PKI intermediate. Signs a
donation attestation.
- **Freenet `Delegate`** — the generic platform primitive: a sandboxed
WASM agent running inside a Freenet node.
- **Ghostkey Vault** — the specific `freenet/ghostkeys` delegate that
stores user ghost keys and handles identity operations. "Vault" is its
product name (see `ghostkeys/ui/`). Issue #24 called it a "wallet
delegate", which is superseded — use "vault" in all forward-looking
docs.
### Library changes (`ghostkey_lib`)
- New module `ghostkey_lib::notary_certificate` exporting
`NotaryCertificateV1` and `NotaryPayload`.
- Deprecated stub module `ghostkey_lib::delegate_certificate` re-exports
the renamed types as `DelegateCertificateV1` / `DelegatePayload` so
downstream code that imported the old path continues to compile with
deprecation warnings. Slated for removal in a future release.
- `GhostkeyCertificateV1.delegate` field renamed to `notary` but its CBOR
wire-format key is frozen as `"delegate"` via `#[serde(rename)]`.
- `NotaryPayload.notary_verifying_key` has its CBOR wire-format key frozen
as `"delegate_verifying_key"` via `#[serde(rename)]`. Because cert
signatures cover the serialized payload bytes, the wire format cannot
change without invalidating every existing ghost key.
- PEM armor: writes always use the canonical `BEGIN NOTARY_CERTIFICATE_V1`
header. Reads accept both the canonical header and the legacy
`BEGIN DELEGATE_CERTIFICATE_V1` header via a `legacy_armor_aliases` table
in `armorable.rs`. Slated for removal in a future release.
- New regression test suite `tests/legacy_v1_compat.rs` pins the wire-format
compatibility decisions against real fixtures under
`tests/fixtures/legacy_v1/`.
### CLI changes (`ghostkey`)
- New canonical subcommands `generate-notary` and `verify-notary`. The
legacy `generate-delegate` and `verify-delegate` are retained as clap
aliases and emit a one-shot stderr deprecation warning before clap
parses (via a manual argv pre-scan, since clap normalizes matches to
the canonical name).
- New canonical flags `--notary-certificate`, `--notary-dir`. The legacy
`--delegate-certificate` and `--delegate-dir` are retained as clap
aliases with the same deprecation warning.
- Default on-disk filenames: `notary_certificate.pem`,
`notary_signing_key.pem` (was `delegate_*.pem`).
`generate-ghost-key` reads the new canonical filenames first and
transparently falls back to the legacy names with a deprecation
warning. Existing key directories keep working unchanged.
- Shell helper renamed from `generate_delegate_keys.sh` to
`generate_notary_keys.sh`. The old filename is preserved as a stub
that warns and execs the new script. Per-amount on-disk filenames
move from `delegate_{kind}_{amount}.pem` to
`notary_{kind}_{amount}.pem`.
### API server changes (`ghostkey-api`)
- Canonical CLI flag `--notary-dir` (legacy `--delegate-dir` accepted
as a clap alias with deprecation warning).
- The `--notary-dir` flag is bound to `NOTARY_DIR` via clap's `.env()`
binding. If the operator has only the legacy `DELEGATE_DIR` set, a
pre-parse hook in `main()` copies it into `NOTARY_DIR` before clap
runs, with a deprecation warning. Operators on systemd units or
`.env` files that only declare `DELEGATE_DIR` keep working unchanged.
- Per-amount key file lookup in `delegates::pick_scheme` resolves the
naming scheme at the directory level, not per-file. A partial
on-disk migration (e.g. only the cert renamed, signing key still
legacy) is explicitly rejected to avoid pairing a new-named cert
with a legacy-named signing key — that mismatch would produce ghost
certs whose signatures don't chain. Unit tests in `delegates::tests`
pin every resolution branch.
- `DonationResponse` and `SignCertificateResponse` dual-emit BOTH
`delegate_certificate_base64` (legacy) and `notary_certificate_base64`
(canonical) fields with identical values. This lets already-cached
browser JS keep working while freshly served JS picks up the new
field. Removal of the legacy field tracked for a future release.
### Hugo site changes
- `donation-success.js` reads `notary_certificate_base64` first and
falls back to `delegate_certificate_base64`, migrating the value to
the new key. The legacy key is intentionally NOT deleted for one
release to avoid breaking a stale multi-tab session.
- `stripe-donation-form.html` writes to both localStorage keys for the
same reason.
- `/ghostkey/` landing page copy refers to the notary key where it
previously said "delegate key" (in the PKI sense only — mentions of
Freenet's WASM Delegate / Ghostkey Vault are correctly left alone).
### Deliberately NOT renamed
- `hugo-site/content/about/news/introducing-ghost-keys.md` — historical
blog post, the `delegate-key-created` JSON key inside the embedded
sample is baked into the actual `info` field of real pre-rename
certificates.
- Inside the cert `info` field JSON: the `delegate-key-created` key
name is emitted by `generate_notary_keys.sh` verbatim and is parsed
by River's UI. Renaming it would break every historical donation.
- `rust/api/src/delegates.rs` module filename: the internals are
renamed, but moving the file would churn the module path without
buying anything. Documented in the file's module doc comment.
### Upgrading
Breaking bump. Downstream code that imports from the deprecated module
path (`ghostkey_lib::delegate_certificate::DelegateCertificateV1`) will
still compile with a deprecation warning, but code that accesses
`GhostkeyCertificateV1.delegate` or `DelegatePayload.delegate_verifying_key`
as struct fields must update to `.notary` / `.notary_verifying_key`.
In particular, the `freenet/ghostkeys` Ghostkey Vault will need a
follow-up PR that bumps its `ghostkey_lib` dependency to `0.2` and
updates field accesses in `delegates/ghostkey-delegate/src/handlers.rs`.
This is planned and out of scope for this release.
### Release checklist note
The `ghostkey-api` and `integration_test` crates previously depended on
`ghostkey_lib` from crates.io and now depend on the in-tree `../gklib`
path. This removes an implicit check that the published crate didn't
drift from the in-tree source. After publishing 0.2.0, manually verify
the publish succeeded by temporarily flipping `rust/api/Cargo.toml` to
`ghostkey_lib = "0.2"` from crates.io and running
`cargo check --manifest-path rust/api/Cargo.toml`.