Skip to content

Commit 3f4ab3a

Browse files
committed
docs: update all docs for v5.1.0 Locksmith release
- STATUS.md: bump to v5.1.0, 757 tests, M11 closed, M12 unblocked - ROADMAP.md: M11 marked CLOSED, task cards moved to COMPLETED_TASKS - COMPLETED_TASKS.md: add M11 Locksmith task summaries (11.1–11.4) - README.md: add What's new for v5.1.0/v3.1.0/v3.0.0, expand CLI section with verify/inspect/recipient/json, update feature list
1 parent 96f4d16 commit 3f4ab3a

4 files changed

Lines changed: 113 additions & 265 deletions

File tree

COMPLETED_TASKS.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@ Task cards moved here from ROADMAP.md after completion. Organized by milestone.
44

55
---
66

7+
# M11 — Locksmith (v5.1.0) ✅ CLOSED
8+
9+
**Theme:** Multi-recipient encryption via envelope encryption (DEK/KEK model). Each file is encrypted with a random Data Encryption Key; the DEK is wrapped per-recipient. Adding or removing access never re-encrypts the data.
10+
11+
**Completed:** v5.1.0 (2026-02-28)
12+
13+
- **Task 11.1:** Envelope encryption (DEK/KEK model) — random 32-byte DEK encrypts content via existing AES-256-GCM pipeline; DEK is wrapped per-recipient with AES-256-GCM key-wrapping. Manifest stores `encryption.recipients: [{ label, wrappedDek, nonce, tag }]`. Restore tries each recipient entry to unwrap DEK. Full backward compatibility with old-style manifests.
14+
- **Task 11.2:** Recipient management API — `addRecipient()` unwraps DEK with existing key, re-wraps for new recipient. `removeRecipient()` removes by label with last-recipient guard. `listRecipients()` returns labels. All return new immutable Manifest value objects. Defense-in-depth post-filter guard for corrupted manifests.
15+
- **Task 11.3:** Manifest schema for multi-recipient metadata — `RecipientSchema` (Zod), `EncryptionSchema` extended with `recipients: z.array(RecipientSchema).min(1).optional()`. Error codes: `NO_MATCHING_RECIPIENT`, `DEK_UNWRAP_FAILED`, `RECIPIENT_NOT_FOUND`, `RECIPIENT_ALREADY_EXISTS`, `CANNOT_REMOVE_LAST_RECIPIENT`. `RecipientEntry` type exported.
16+
- **Task 11.4:** CLI multi-recipient support — `--recipient <label:keyfile>` repeatable flag on `git cas store`, `git cas recipient add/remove/list` subcommands, mutual exclusivity guard (`--recipient` vs `--key-file`/`--vault-passphrase`), empty keyfile rejection.
17+
18+
---
19+
720
# M10 — Hydra (v5.0.0) ✅ CLOSED
821

922
**Theme:** Content-defined chunking for dramatically better dedup on versioned files.

README.md

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ We use the object database.
1919
## What you get
2020

2121
- **Dedupe for free** Git already hashes objects. We just lean into it.
22-
- **Chunked storage** big files become stable, reusable blobs.
22+
- **Chunked storage** big files become stable, reusable blobs. Fixed-size or content-defined chunking (CDC).
2323
- **Optional AES-256-GCM encryption** store secrets without leaking plaintext into the ODB.
24+
- **Multi-recipient encryption** envelope model (DEK/KEK) — add/remove access without re-encrypting data.
2425
- **Compression** gzip before encryption — smaller blobs, same round-trip.
2526
- **Passphrase encryption** derive keys from passphrases via PBKDF2 or scrypt — no raw key management.
2627
- **Merkle manifests** large files auto-split into sub-manifests for scalability.
@@ -29,18 +30,49 @@ We use the object database.
2930
- **Full round-trip** store, tree, and restore — get your bytes back, verified.
3031
- **Lifecycle management** `readManifest`, `deleteAsset`, `findOrphanedChunks` — inspect trees, plan deletions, audit storage.
3132
- **Vault** GC-safe ref-based storage. One ref (`refs/cas/vault`) indexes all assets by slug. No more silent data loss from `git gc`.
33+
- **Interactive dashboard** `git cas inspect` with chunk heatmap, animated progress bars, and rich manifest views.
34+
- **Verify & JSON output** `git cas verify` checks integrity; `--json` on all commands for CI/scripting.
3235

3336
**Use it for:** binary assets, build artifacts, model weights, data packs, secret bundles, weird experiments, etc.
3437

3538
<img src="./docs/demo.gif" alt="git-cas demo" />
3639

37-
## What's new in v2.0.0
40+
## What's new in v5.1.0
3841

39-
**Compression**`compression: { algorithm: 'gzip' }` on `store()`. Compression runs before encryption. Decompression on `restore()` is automatic.
42+
**Multi-recipient envelope encryption**Each file is encrypted with a random DEK; recipient KEKs wrap the DEK. Add or remove team members without re-encrypting data.
4043

41-
**Passphrase-based encryption** — Pass `passphrase` instead of `encryptionKey`. Keys are derived via PBKDF2 (default) or scrypt. KDF parameters are stored in the manifest for deterministic re-derivation. Use `deriveKey()` directly for manual control.
44+
```js
45+
// API: store for multiple recipients
46+
const manifest = await cas.storeFile({
47+
filePath: './secrets.tar.gz',
48+
slug: 'prod-secrets',
49+
recipients: [
50+
{ label: 'alice', key: aliceKey },
51+
{ label: 'bob', key: bobKey },
52+
],
53+
});
4254

43-
**Merkle tree manifests** — When chunk count exceeds `merkleThreshold` (default: 1000), manifests are automatically split into sub-manifests stored as separate blobs. `readManifest()` transparently reconstitutes them. Full backward compatibility with v1 manifests.
55+
// Add a recipient later (no re-encryption)
56+
const updated = await cas.addRecipient({
57+
manifest, existingKey: aliceKey, newRecipientKey: carolKey, label: 'carol',
58+
});
59+
60+
// List / remove recipients
61+
const labels = await cas.listRecipients({ manifest });
62+
const trimmed = await cas.removeRecipient({ manifest, label: 'bob' });
63+
```
64+
65+
```bash
66+
# CLI: store with multiple recipients
67+
git cas store ./secrets.tar.gz --slug prod-secrets \
68+
--recipient alice:./keys/alice.key \
69+
--recipient bob:./keys/bob.key --tree
70+
71+
# Manage recipients
72+
git cas recipient list prod-secrets
73+
git cas recipient add prod-secrets --label carol --key-file ./keys/carol.key --existing-key-file ./keys/alice.key
74+
git cas recipient remove prod-secrets --label bob
75+
```
4476

4577
See [CHANGELOG.md](./CHANGELOG.md) for the full list of changes.
4678

@@ -83,6 +115,28 @@ See [CHANGELOG.md](./CHANGELOG.md) for the full list of changes.
83115

84116
See [CHANGELOG.md](./CHANGELOG.md) for the full list of changes.
85117

118+
## What's new in v3.1.0
119+
120+
**Interactive vault dashboard**`git cas inspect --slug my-asset` renders a rich TUI with chunk heatmap, encryption card, and history timeline. Animated progress bars for long store/restore operations.
121+
122+
See [CHANGELOG.md](./CHANGELOG.md) for the full list of changes.
123+
124+
## What's new in v3.0.0
125+
126+
**Vault** — GC-safe ref-based storage under `refs/cas/vault`. Assets are indexed by slug and survive `git gc`. Full CLI: `git cas vault init`, `list`, `info`, `remove`, `history`. Store with `--tree` to vault automatically.
127+
128+
See [CHANGELOG.md](./CHANGELOG.md) for the full list of changes.
129+
130+
## What's new in v2.0.0
131+
132+
**Compression**`compression: { algorithm: 'gzip' }` on `store()`. Compression runs before encryption. Decompression on `restore()` is automatic.
133+
134+
**Passphrase-based encryption** — Pass `passphrase` instead of `encryptionKey`. Keys are derived via PBKDF2 (default) or scrypt. KDF parameters are stored in the manifest for deterministic re-derivation. Use `deriveKey()` directly for manual control.
135+
136+
**Merkle tree manifests** — When chunk count exceeds `merkleThreshold` (default: 1000), manifests are automatically split into sub-manifests stored as separate blobs. `readManifest()` transparently reconstitutes them. Full backward compatibility with v1 manifests.
137+
138+
See [CHANGELOG.md](./CHANGELOG.md) for the full list of changes.
139+
86140
## Install
87141

88142
```bash
@@ -148,18 +202,37 @@ git cas restore --slug my-image --out ./restored.png
148202
# Restore from a direct tree OID
149203
git cas restore --oid <tree-oid> --out ./restored.png
150204

205+
# Verify integrity without restoring
206+
git cas verify --slug my-image
207+
208+
# Inspect manifest (interactive dashboard)
209+
git cas inspect --slug my-image
210+
151211
# Vault management
152212
git cas vault init
153-
git cas vault list
213+
git cas vault list # TTY table
214+
git cas vault list --json # structured JSON
215+
git cas vault list --filter "photos/*" # glob filter
154216
git cas vault info my-image
155217
git cas vault remove my-image
156218
git cas vault history
157219

220+
# Multi-recipient encryption
221+
git cas store ./secret.bin --slug shared \
222+
--recipient alice:./keys/alice.key \
223+
--recipient bob:./keys/bob.key --tree
224+
git cas recipient list shared
225+
git cas recipient add shared --label carol --key-file ./keys/carol.key --existing-key-file ./keys/alice.key
226+
git cas recipient remove shared --label bob
227+
158228
# Encrypted vault round-trip (passphrase via env var or --vault-passphrase flag)
159229
export GIT_CAS_PASSPHRASE="secret"
160230
git cas vault init
161231
git cas store ./secret.bin --slug vault-entry --tree
162232
git cas restore --slug vault-entry --out ./decrypted.bin
233+
234+
# JSON output on any command (for CI/scripting)
235+
git cas store ./data.bin --slug my-data --tree --json
163236
```
164237

165238
## Documentation
@@ -181,7 +254,7 @@ That's git-cas. The orphan branch gives you none of:
181254

182255
| | Orphan branch | git-cas |
183256
|---|---|---|
184-
| **Encryption** | None — plaintext forever in history | AES-256-GCM + passphrase KDF |
257+
| **Encryption** | None — plaintext forever in history | AES-256-GCM + passphrase KDF + multi-recipient |
185258
| **Large files** | Bloats `git clone` for everyone | Chunked, restored on demand |
186259
| **Dedup** | None | Chunk-level content addressing |
187260
| **Integrity** | Git SHA-1 | SHA-256 per chunk + GCM auth tag |

0 commit comments

Comments
 (0)