Vow, uncensorable PDS written in Go

docs: fix readme about rotation keys

+8 -3
+8 -3
readme.md
··· 146 146 147 147 ### BYOK (Bring Your Own Key) 148 148 149 - The PDS holds one key — the **rotation key** — used only for lightweight PDS-level operations (service-auth JWTs, genesis DID creation, and PLC operations before the user has registered their wallet). It is never used to sign user content. 149 + The PDS holds two keys: 150 + 151 + - **Rotation key** (`rotation.key`) — a secp256k1 key used for DID genesis operations and for signing the PLC operation that transfers control to the user's wallet during `supplySigningKey`. It is never used to sign user content. 152 + - **JWK key** (`jwk.key`) — a P-256 ECDSA key used exclusively to sign ATProto session JWTs (access and refresh tokens) and OAuth tokens. It has no role in repo writes or identity operations. 153 + 154 + Neither key is ever used to sign repo commits or service-auth JWTs. 150 155 151 156 Every repo write from the Bluesky app, Tangled, or any other standard ATProto client is held open until the user's Ethereum wallet returns a signature through the browser signer on the account page. 152 157 ··· 177 182 - **Identity operations** — PLC operations and handle updates, **once the user's wallet key is the rotation key**. Before that, the PDS rotation key signs them directly. 178 183 - **x402 payments** — EIP-712 payment authorisations for gated pinning 179 184 180 - Read-only operations (browsing feeds, loading profiles, fetching notifications, etc.) do **not** prompt the wallet. Service-auth JWTs for proxied requests are signed directly by the PDS rotation key — fast, in-process, no wallet involved. 185 + Read-only operations (browsing feeds, loading profiles, fetching notifications, etc.) do **not** prompt the wallet. Service-auth JWTs for proxied requests (`getServiceAuth`, ATProto proxy) are also signed by the user's wallet via the signer WebSocket — the wallet tab must be open for these to succeed. 181 186 182 187 #### WebSocket connection 183 188 ··· 249 254 250 255 **Phase 1 — Account creation.** `createAccount` works like standard ATProto: the PDS creates the `did:plc` with its own rotation key. 251 256 252 - **Phase 2 — Key registration.** When the user completes onboarding and calls `supplySigningKey`, the PDS submits one PLC operation that makes the user's wallet key both the signing key and the **only rotation key**, removing the PDS key. After that, only the user's Ethereum wallet can authorise future PLC operations. 257 + **Phase 2 — Key registration.** When the user completes onboarding and calls `supplySigningKey`, the PDS submits one PLC operation that makes the user's wallet key both the signing key and the **only rotation key**, removing the PDS key from the DID document. After that, only the user's Ethereum wallet can authorise future PLC operations. The PDS rotation key file is not destroyed — it continues to be used for DID genesis when new accounts register — but it no longer has any authority over this user's DID document. 253 258 254 259 ### What the user gets 255 260