fix(broker/cli): e2e get_file owner sealedKey bug
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

broker: owner also fetches sealedKey from mesh.file_key (not skipped),
  only non-owners are blocked when key is missing
cli: explicit error when encrypted file has no sealedKey (no silent raw download)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-07 12:56:36 +01:00
parent 5f696f47ea
commit e70f0ed1ff
2 changed files with 10 additions and 10 deletions

View File

@@ -977,19 +977,18 @@ function handleConnection(ws: WebSocket): void {
break;
}
}
// E2E: for encrypted files, fetch the sealed key for this peer
// E2E: for encrypted files, fetch the sealed key for this peer.
// Owners are not blocked if their key is missing (edge case), but
// they still get it returned so the CLI can decrypt normally.
let sealedKey: string | null = null;
if (file.encrypted) {
const peerPubkey = conn.sessionPubkey ?? conn.memberPubkey;
const isOwner = file.ownerPubkey && peerPubkey === file.ownerPubkey;
if (!isOwner) {
sealedKey = peerPubkey ? await getFileKey(gf.fileId, peerPubkey) : null;
if (!sealedKey) {
sendError(conn.ws, "forbidden", "no decryption key for this file");
break;
}
const isOwner = !!(file.ownerPubkey && peerPubkey === file.ownerPubkey);
sealedKey = peerPubkey ? await getFileKey(gf.fileId, peerPubkey) : null;
if (!sealedKey && !isOwner) {
sendError(conn.ws, "forbidden", "no decryption key for this file");
break;
}
// Owner gets sealedKey = null (they already have Kf from upload)
}
// Generate presigned URL (60s expiry)
const bucket = meshBucketName(conn.meshId);