atproto pds in zig pds.zat.dev
pds atproto
24

Configure Feed

Select the types of activity you want to include in your feed.

support per-account plc repair recovery

zzstoatzz (May 26, 2026, 9:29 PM -0500) 85e57d8a 0a80147c

+19 -5
+7 -4
docs/operations.md
··· 84 84 `rotationKeys`. 85 85 - Existing early accounts can be repaired with `just plc-repair <did>` after 86 86 setting `ZDS_DB` or `ZDS_DB_PATH`, `ZDS_PUBLIC_URL`, `ZDS_PLC_ROTATION_KEY`, 87 - and optional `ZDS_RECOVERY_DID_KEY`. The repair tool is intentionally separate 88 - from normal XRPC handling; it only uses the account signing key if the current 89 - public PLC state already authorizes that key as a rotation key, and submits a 90 - replacement operation containing the intended recovery/PDS rotation keys. 87 + and optional `ZDS_REPAIR_RECOVERY_DID_KEY`, `ZDS_REPAIR_RECOVERY_KEY`, or 88 + `ZDS_RECOVERY_DID_KEY`. The repair tool is intentionally separate from normal 89 + XRPC handling; it only uses the account signing key if the current public PLC 90 + state already authorizes that key as a rotation key, and submits a replacement 91 + operation containing the intended recovery/PDS rotation keys. The 92 + `ZDS_REPAIR_RECOVERY_KEY` form accepts a PDS Moover private multikey and 93 + derives the public `did:key` locally. 91 94 92 95 When invites are required and the database has no accounts or invite codes, ZDS 93 96 creates one bootstrap code and logs it during startup. Invite codes are stored
+12 -1
tools/plc_repair.zig
··· 64 64 } 65 65 66 66 fn targetRotationKeys(allocator: std.mem.Allocator, rotation_did_key: []const u8) ![]const []const u8 { 67 - const recovery = zds.core.config.recoveryDidKey(); 67 + const repair_recovery = try repairRecoveryDidKey(allocator); 68 + const recovery = repair_recovery orelse zds.core.config.recoveryDidKey(); 68 69 const count: usize = if (recovery == null) 1 else 2; 69 70 const keys = try allocator.alloc([]const u8, count); 70 71 var idx: usize = 0; ··· 74 75 } 75 76 keys[idx] = rotation_did_key; 76 77 return keys; 78 + } 79 + 80 + fn repairRecoveryDidKey(allocator: std.mem.Allocator) !?[]const u8 { 81 + if (env("ZDS_REPAIR_RECOVERY_DID_KEY")) |did_key| return did_key; 82 + if (env("ZDS_REPAIR_RECOVERY_KEY")) |private_key| { 83 + var keypair = try zds.atproto.plc.parsePrivateKey(allocator, private_key); 84 + const did_key = try keypair.did(allocator); 85 + return did_key; 86 + } 87 + return null; 77 88 } 78 89 79 90 fn jsonArrayContainsString(value: ?std.json.Value, expected: []const u8) bool {