WIP did-plc controller - #47
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning MetaMask internal reviewing guidelines:
|
82270b1 to
e9ae33f
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e9ae33f. Configure here.
478ec68 to
d41b7e8
Compare
e9ae33f to
29c0603
Compare
There was a problem hiding this comment.
Pull request overview
Adds full did:plc controller support, including signed operations, registry access, recovery, and chain verification.
Changes:
- Implements create, update, recovery, tombstone, head, and audit workflows.
- Adds DAG-CBOR encoding, CID derivation, key policies, and legacy operation support.
- Adds live fixtures, hostile-history tests, documentation, and concrete
did:keyreturn types.
Reviewed changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
Readme.md |
Marks did:plc controller support. |
go.mod |
Adds CID and multiformat dependencies. |
go.sum |
Records dependency checksums. |
controller/did-key/key.go |
Returns concrete DidKey values. |
verifiers/did-key/key.go |
Exposes concrete DidKey constructors. |
controller/did-plc/controller.go |
Implements controller operations. |
controller/did-plc/registry.go |
Implements registry HTTP access. |
controller/did-plc/options.go |
Adds registry configuration options. |
controller/did-plc/state.go |
Defines and validates document state. |
controller/did-plc/spec.go |
Defines protocol constants and DID derivation. |
controller/did-plc/operation.go |
Implements operation signing and verification. |
controller/did-plc/key.go |
Handles rotation keys and signer authorization. |
controller/did-plc/codec.go |
Encodes and parses current operations. |
controller/did-plc/codec_legacy.go |
Normalizes legacy genesis operations. |
controller/did-plc/chain.go |
Replays and validates operation histories. |
controller/did-plc/errors.go |
Defines controller sentinel errors. |
controller/did-plc/doc.go |
Documents architecture and protocol behavior. |
controller/did-plc/example_test.go |
Demonstrates controller workflows. |
controller/did-plc/fake_test.go |
Provides a rule-enforcing fake registry. |
controller/did-plc/roundtrip_test.go |
Tests registry and controller workflows. |
controller/did-plc/chain_test.go |
Tests valid and hostile histories. |
controller/did-plc/internal/dagcbor/dagcbor.go |
Implements DAG-CBOR and CID utilities. |
controller/did-plc/internal/dagcbor/dagcbor_test.go |
Tests encoding and CID validation. |
controller/did-plc/testdata/README.md |
Documents captured fixtures. |
controller/did-plc/testdata/audit_atproto.json |
Adds current-format audit fixture. |
controller/did-plc/testdata/audit_legacy.json |
Adds legacy audit fixture. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| rawSig, err := base64.RawURLEncoding.DecodeString(sig) | ||
| if err != nil { | ||
| return -1, fmt.Errorf("%w: decoding signature: %w", ErrInvalidChain, err) | ||
| } |
| // The timestamps this relies on are the registry's own and are not signed, so the window | ||
| // and ordering checks hold the registry to its account of events rather than proving | ||
| // anything on their own. | ||
| func (c chain) validate(didStr string) error { |
| nullified := make(map[string]bool, len(c)) | ||
|
|
||
| for i := range c { | ||
| e := &c[i] |
| rotKeys, err := c.rotationKeysFromWire(raw.RotationKeys) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| vms, err := c.verificationMethodsFromWire(raw.VerificationMethods) |
| func appendString(buf []byte, s string) []byte { | ||
| buf = appendHead(buf, majorString, uint64(len(s))) | ||
| return append(buf, s...) | ||
| } |
| assert.Equal(t, "AtprotoPersonalDataServer", entries[0].State.Services["atproto_pds"].Type) | ||
| } | ||
|
|
||
| // Every key handed out in an State must be one the same package would accept back, so that |

Note
High Risk
New code paths create and mutate DIDs via rotation-key signing and replay chain rules; mistakes or gaps in validation could allow trusting a hostile registry or signing unauthorized state.
Overview
Adds
didplcctl(controller/did-plc), a full did:plc controller on top of the existing verifier:Registrytalks to plc.directory (or a custom URL),Createregisters genesis operations, andControllersupportsHead,Update,Recover,Tombstone, andAudit.Operations are built through a codec that validates write-time limits, encodes DAG-CBOR (via new
internal/dagcbor), signs with low-S ECDSA, and parsesplc_operation,plc_tombstone, and legacycreategenesis ops.chain.validatereplays the audit log to enforce genesis DID binding, prev/signature authority, recovery ranking, the 72h window, and agreement with registry nullified flags; optionalWithFullChainVerificationuses that replay forHeadinstead of trusting/log/last.Coverage includes a fake registry, golden logs from the live directory, and upstream interop audit vectors. Readme marks
did:plcas controller-supported;did-keyhelpers now returndidkey.DidKeywith doc comments only.Reviewed by Cursor Bugbot for commit b5cb3d0. Bugbot is set up for automated code reviews on this repo. Configure here.