Repository navigation
Commit 5ff7af8
* feat(core): ed25519 to x25519 key conversion for envelope crypto
* feat(core): seal/open per-blob encryption envelopes
* feat(node): resolve per-blob encryption recipients (least-privilege)
* feat(node): encrypted_blobs table and recipient-scoped queries
* feat(node): encrypt-then-pin withheld blobs at push (IPFS)
At the push chokepoint, after pinning withheld objects, resolve each
withheld blob's recipient DIDs and seal it to their Ed25519 keys with
seal_blob, pinning the ciphertext to IPFS and recording it in
encrypted_blobs. Best-effort per blob: failures are logged and skipped,
never pinned in plaintext. Pinata replication is unchanged; B1
encrypts to IPFS only.
Adds ed25519-dalek as a direct dependency of gitlawb-node (it was only
declared in the workspace Cargo.toml).
* feat(node): authenticated discovery and fetch for encrypted blobs
* feat(gl): transparent recovery of authorized encrypted blobs on clone
* style: cargo fmt
* fix(node): re-seal encrypted blob when recipient set changes
Skip re-pinning only when an existing envelope already covers exactly the
current recipients. A reader added to a rule after the first pin now gets
a re-seal on the next push instead of being permanently locked out.
Reader removal stays non-retroactive (the old envelope is already public).
* feat(node): unscoped encrypted-blob listing for replication
* feat(node): encrypted-blobs/replicate endpoint for peer mirrors
* feat(node): route encrypted-blobs/replicate under git_read_routes
* feat(node): peer mirrors replicate encrypted withheld blobs (Option B2)
* feat(node): anchor_encrypted_manifest for Option B3 Arweave manifests
* feat(node): encrypt_and_pin returns the per-push sealed delta
* feat(node): anchor encrypted-blob manifest on push (Option B3)
* feat(gl): Arweave/IPFS gateway recovery for encrypted blobs (Option B3)
* feat(gl): transparent Arweave fallback recovery on clone (Option B3)
* style: cargo fmt
* fix(gl): bound Arweave recovery gateway requests with a 30s timeout
* test(gl): read-path recovery tests for Arweave fallback; quiet promisor present-check
Add two hermetic integration tests for recover_from_arweave that drive the
full read path over mocked Arweave GraphQL + IPFS gateways: discover the
manifest, fetch it, fetch the envelope, decrypt, and install the withheld
blob. One covers an authorized recipient (blob installed), the other a
non-recipient (nothing recovered). Both simulate origin death by removing
the promisor remote and enable uploadpack.allowFilter so the blob is truly
withheld over file://.
Also harden the local presence check in recover_from_arweave with
GIT_NO_LAZY_FETCH=1 and .output() so the expected 'missing object' case does
not trigger a wasted promisor fetch or leak git stderr to the user.
* fix: surface corrupt recipients JSON and silent recovery I/O failures
db: parse_recipients now propagates a descriptive error instead of
defaulting corrupt recipients JSON to an empty list, which would have
denied authorized readers and handed peers incomplete metadata.
gl: clone recovery now warns when the sparse-checkout file cannot be read
or written, or when the post-recovery checkout fails, instead of silently
discarding those errors and claiming files were recovered.
* feat(core): blind recipient identities in withheld-blob envelopes
Envelope v2 drops the cleartext recipient public key (kid) from each
wrapped-key header entry, so a party holding the public IPFS/Arweave copy
can no longer enumerate who is authorized to decrypt a withheld blob. The
version is bumped to 2 and v1 envelopes are rejected. open_blob now selects
the reader's entry by trial decryption (the AEAD tag authenticates exactly
one entry) instead of matching on the public key.
Recipient count is still visible; identity is not. Scope is envelope-only,
the node DB recipients column and peer replication metadata are unchanged.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
* fix(core): reject malformed envelope nonces instead of panicking
open_blob fed attacker-controlled envelopes to GenericArray::from_slice and
XNonce::from_slice, which panic on a wrong-length input. Validate both the
per-recipient box nonce and the body nonce to 24 bytes before use: skip a
recipient entry whose nonce is malformed, and return an error for a malformed
body nonce, so the public recovery path surfaces an error rather than panicking.
* feat(node): blind recipient identities on the B2 replication surface
The encrypted-blobs/replicate endpoint shipped every blob's full recipient
DID list to mirrors, which persisted it, so any mirroring peer learned the
reader set. The v2 envelope blinding already removed recipient public keys
from the pinned envelopes, so the comment justifying this (DIDs are already
public) was no longer true.
/replicate now returns {oid, cid} only. Mirrors detect a re-seal by the CID
changing (the OID is stable across re-seals) instead of comparing recipient
sets, and store no recipient identities. Origin-side authz and the at-rest
recipients column are unchanged; this blinds only the peer-facing surface.
* feat(node): stop anchoring recipient identities to Arweave
The B3 encrypted-blob manifest anchored {oid, cid, recipients} to Arweave, a
permanent public record of every blob's reader set. The v2 envelope blinding
already removed recipient keys from the pinned envelopes, so the comment
justifying this (recipient DIDs are already public) was no longer true. The
manifest now anchors {oid, cid} only. The gl reader already ignores the
recipients field (it recovers by trial decryption), so no reader changes.
---------
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
1 parent 8680d0f commit 5ff7af8
18 files changed
Lines changed: 1938 additions & 1 deletion
File tree
- crates
- gitlawb-core
- src
- gitlawb-node
- src
- api
- db
- git
- gl/src
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
26 | 29 | | |
27 | 30 | | |
28 | 31 | | |
0 commit comments