feat(storage): Blossom Phase 2 — BUD-12 delete/list primitives [LOCAL] (#30)

The management primitives, self-contained + unit-tested. Not yet wired into the
S3-shaped orphan-GC / delete-flow (that reconcile system assumes bucket/key
semantics — its own browser-tested increment, same pattern as the upload).

- Vendor entry: export createDeleteAuth (+ rebuilt bundle, still ~27KB).
- blossomService.deleteFile({ server, sha256, signer }) — BUD-12 DELETE /<sha256>
  with a signed kind-24242 delete auth (BUD-11).
- blossomService.listFiles({ server, pubkey, signer }) — BUD-12 GET /list/<pubkey>,
  optional list auth.

Tests: blossom-service 9/9 (added delete/list guards + happy paths). Lint + build
clean.

REMAINING Phase 2: wire deleteFile into video-delete cleanup (resolve
server+sha256 from the blossom storagePointer), orphan-GC parity, and the
kind-10063 discovery UI (import/publish server list — needs relay fetch/publish
plumbing).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-07-09 16:36:31 -04:00
1 parent c5e8c7f9f1
commit 5935702e75
4 files changed
+89 -1

No files matched your search

+49
View File
@@ -179,6 +179,55 @@ export class BlossomService {
return result;
}
/**
* Delete a blob from one Blossom server (BUD-12 `DELETE /<sha256>`), authorized
* by a signed kind-24242 delete auth (BUD-11). Returns true on success.
*/
async deleteFile({ server, sha256, signer } = {}) {
const url = typeof server === "string" ? server.trim() : "";
const hash = typeof sha256 === "string" ? sha256.trim() : "";
if (!url || !hash) {
throw new Error("Blossom delete requires a server and a sha256.");
}
if (typeof signer !== "function") {
throw new Error("Blossom delete requires a signer.");
}
const sdk = await this.loadSdk();
const { deleteBlob, createDeleteAuth } = sdk;
if (
typeof deleteBlob !== "function" ||
typeof createDeleteAuth !== "function"
) {
throw new Error("Blossom SDK is missing delete exports.");
}
return deleteBlob(url, hash, {
onAuth: () => createDeleteAuth(signer, hash),
});
}
/**
* List a user's blobs on a Blossom server (BUD-12 `GET /list/<pubkey>`). Some
* servers require a signed list auth; provide the signer to cover those.
* Returns the array of blob descriptors.
*/
async listFiles({ server, pubkey, signer } = {}) {
const url = typeof server === "string" ? server.trim() : "";
const pk = typeof pubkey === "string" ? pubkey.trim() : "";
if (!url || !pk) {
throw new Error("Blossom list requires a server and a pubkey.");
}
const sdk = await this.loadSdk();
const { listBlobs, createListAuth } = sdk;
if (typeof listBlobs !== "function") {
throw new Error("Blossom SDK is missing list exports.");
}
const opts =
typeof signer === "function" && typeof createListAuth === "function"
? { onAuth: () => createListAuth(signer) }
: {};
return listBlobs(url, pk, opts);
}
}
const blossomService = new BlossomService();