An easy-to-host PDS on the ATProtocol, MacOS. Grandma-approved.

docs: update project context for MM-90 device-signed DID ceremony

Add verify_genesis_op and VerifiedGenesisOp to crypto CLAUDE.md
contracts. Update root CLAUDE.md crypto description to mention
verification.

authored by malpercio.dev and committed by

Tangled 814ce9df 6f6eacef

+27 -6
+2 -2
CLAUDE.md
··· 1 1 # ezpds 2 2 3 - Last verified: 2026-03-13 3 + Last verified: 2026-03-14 4 4 5 5 ## Tech Stack 6 6 - Language: Rust (stable channel via rust-toolchain.toml) ··· 31 31 ## Project Structure 32 32 - `crates/relay/` - Web relay (axum-based) 33 33 - `crates/repo-engine/` - ATProto repo engine 34 - - `crates/crypto/` - Cryptographic operations (P-256 key generation, did:key derivation, AES-256-GCM encryption, did:plc genesis ops) 34 + - `crates/crypto/` - Cryptographic operations (P-256 key generation, did:key derivation, AES-256-GCM encryption, did:plc genesis ops and verification) 35 35 - `crates/common/` - Shared types and utilities 36 36 - `nix/` - Nix packaging and deployment (docker.nix: container image; module.nix: NixOS module) 37 37 - `docs/` - Specs, design plans, implementation plans
+25 -4
crates/crypto/CLAUDE.md
··· 1 1 # Crypto Crate 2 2 3 - Last verified: 2026-03-13 3 + Last verified: 2026-03-14 4 4 5 5 ## Purpose 6 6 Provides cryptographic primitives for the ezpds workspace: P-256 key generation, 7 7 did:key derivation, AES-256-GCM encryption/decryption of private key material, 8 - and Shamir Secret Sharing for DID rotation key recovery. 8 + Shamir Secret Sharing for DID rotation key recovery, and did:plc genesis 9 + operation building and verification. 9 10 This is a pure functional core -- no I/O, no database, no config. 10 11 11 12 ## Contracts ··· 64 65 - Deterministic: same inputs → same DID (RFC 6979 ECDSA + SHA-256 + base32) 65 66 - Errors: `CryptoError::PlcOperation` if `signing_private_key` is an invalid P-256 scalar 66 67 68 + **`verify_genesis_op`** (new, MM-90) 69 + ```rust 70 + pub fn verify_genesis_op( 71 + signed_op_json: &str, // JSON-encoded signed genesis op from client 72 + rotation_key: &DidKeyUri, // P-256 did:key URI to verify signature against 73 + ) -> Result<VerifiedGenesisOp, CryptoError> 74 + ``` 75 + - Parses signed op JSON (rejects unknown fields via `serde(deny_unknown_fields)`) 76 + - Reconstructs unsigned op with DAG-CBOR canonical field ordering, verifies ECDSA-SHA256 signature 77 + - Derives DID from SHA-256 of signed CBOR (same algorithm as `build_did_plc_genesis_op`) 78 + - Returns extracted op fields for semantic validation by the caller 79 + - Errors: `CryptoError::PlcOperation` for any parse, format, or signature failure 80 + 67 81 ### Public types 68 82 69 83 **`P256Keypair`** ··· 75 89 - `did`: `"did:plc:xxxx..."` (28 chars total) 76 90 - `signed_op_json`: contains `type`, `rotationKeys`, `verificationMethods`, `alsoKnownAs`, `services`, `prev` (null), `sig` 77 91 92 + **`VerifiedGenesisOp`** (new, MM-90) 93 + - `did`: derived DID string 94 + - `rotation_keys`: full `rotationKeys` array from the op 95 + - `also_known_as`: full `alsoKnownAs` array from the op 96 + - `verification_methods`: full `verificationMethods` map from the op 97 + - `atproto_pds_endpoint`: endpoint from `services["atproto_pds"]`, if present 98 + 78 99 **`ShamirShare`** 79 100 - `index`: u8 in [1, 3] (not secret) 80 101 - `data`: `Zeroizing<[u8; 32]>` (zeroized on drop) ··· 90 111 91 112 ## Dependencies 92 113 - **Uses**: p256 (ECDSA/key generation), aes-gcm (AES-256-GCM), multibase (base58btc encoding), rand_core (OS RNG), base64 (storage encoding), zeroize (secret cleanup), ciborium (CBOR serialization for did:plc), data-encoding (base32-lowercase), sha2 (SHA-256), serde/serde_json (struct serialization) 93 - - **Used by**: `crates/relay/` (key generation, did:plc genesis endpoint) 114 + - **Used by**: `crates/relay/` (key generation, did:plc genesis building and verification in POST /v1/dids) 94 115 95 116 ## Invariants 96 117 - Private key bytes are always wrapped in `Zeroizing` -- callers must not copy them into non-zeroizing storage ··· 104 125 ## Key Files 105 126 - `src/lib.rs` - Re-exports public API 106 127 - `src/keys.rs` - P-256 key generation, AES-256-GCM encrypt/decrypt 107 - - `src/plc.rs` - did:plc genesis operation builder (MM-89) 128 + - `src/plc.rs` - did:plc genesis operation builder (MM-89) and verifier (MM-90) 108 129 - `src/shamir.rs` - Shamir Secret Sharing (split/combine, GF(2^8) arithmetic) 109 130 - `src/error.rs` - CryptoError enum