fix(node): fail closed when a recipient DID can't be resolved (#47)#67
fix(node): fail closed when a recipient DID can't be resolved (#47)#67beardthelion wants to merge 1 commit into
Conversation
encrypt_and_pin resolved recipient DIDs with filter_map, silently dropping any that failed to resolve and sealing the envelope to the remaining subset while still recording the full intended recipient set as covered. A reader whose DID could not be resolved at seal time (any did:web/did:gitlawb, or a malformed did:key) was then permanently locked out: the dedup compares the recorded full set against the desired set, matches, and never re-seals. Resolve all recipient DIDs up front via resolve_all_recipients; if any fail, log and skip the blob rather than seal to a partial set. Nothing partial is recorded, so the dedup stays honest and the blob re-seals on a later push once resolution is available. Add a bounded per-blob warn plus one aggregate coverage warn so a fully-migrated did:gitlawb org (zero encrypted-pin coverage) is one greppable line, not a scrape, and give the previously silent read_object and pin_git_object failure arms warn logs.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthrough
ChangesFail-closed recipient resolution in
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
encrypted_pin::encrypt_and_pinsealed a withheld blob to whatever subset of its recipient DIDs resolved locally and recorded the full intended set as covered, permanently locking out any reader whose DID could not be resolved at seal time. This makes sealing fail closed: resolve all recipients or skip the blob.Motivation & context
Closes #47
did_to_keyonly resolvesdid:key;did:web/did:gitlawb(the canonical identity actors migrate to once DHT anchoring is live) and any malformeddid:keyreturnNone. The oldfilter_mapdropped those silently and sealed to the rest as long as one key resolved, then recorded the full DID set. Because the dedup compares the recorded set against the desired set, it matched on the next push and never re-sealed, so the dropped reader stayed locked out forever with no signal.Kind of change
What changed
gitlawb-node (
crates/gitlawb-node/src/encrypted_pin.rs):resolve_all_recipients: resolves every recipient DID all-or-nothing, returningErr(unresolved)listing the DIDs that failed.encrypt_and_pinnow skips the blob on any failure instead of sealing to a partial set. Nothing partial is recorded, so the dedup stays honest and the blob re-seals on a later push once resolution is available (no automatic backfill).did:keyis not DHT-pending).did:gitlawborg dropping to zero encrypted-pin coverage is a single greppable line rather than a per-oid scrape.read_objectandpin_git_objectfailure arms warn logs.Fail-closed is deliberate: a blob with an unresolvable reader gets no encrypted recovery envelope until resolution exists, but it is never leaked in plaintext (it was already pinned as withheld upstream). This trades recovery coverage during a transition for a clean audit invariant: a recorded
encrypted_blobsrow always means every authorized reader can recover the blob.How a reviewer can verify
The core regression is
mixed_set_with_did_gitlawb_fails_closed: a resolvabledid:keysubset plus onedid:gitlawbmust returnErrnaming only the unresolvable DID, never a sealable key set.malformed_did_key_fails_closedcovers the corrupt-did:keycase.Before you request review
cargo test --workspacepasses locallycargo fmt --allandcargo clippy --workspace --all-targets -- -D warningsare cleanfeat(...),fix(...),docs(...)).env.exampleupdated if behavior or config changed (or N/A)Protocol & signing impact
did:key, Ed25519 / RFC 9421 signatures, UCAN, ref certs, or P2P wire formatsThis reads DID strings to resolve recipient keys but changes no signature, wire-format, or identity logic; existing envelopes and recorded recipient sets are untouched.
Notes for reviewers
The peer-sync path (
sync.rsrecords an empty recipient set for replicated envelopes via an overwriting upsert) interacts with the dedup but self-heals on the next push; it is pre-existing and out of scope here. A typed resolution-failure reason (distinguishing "method not resolvable yet" from "malformeddid:key") is a possible follow-up; fail-closed behavior is identical for both today.Summary by CodeRabbit
Improvements
Tests