feat(web): add account workspaces and signed content flows

This commit is contained in:
justme committed 2026-10-14 04:06:03 +08:00
1 parent 7b8d61d1ba
commit b5cf3d5958
117 files changed
+2789 -1674

No files matched your search

+8 -1
View File
@@ -3,6 +3,8 @@ import { equalBytes, type Bytes } from './bytes.js';
import { IntegrityError } from './errors.js';
import { MAX_ENC_PAYLOAD, openFrame, parseEnvelope, peekEnvelopeLength } from './frame.js';
import { decodeFirstFrame, type ItemMeta } from './item.js';
import { sha256 } from './kdf.js';
import { frameManifestHash } from './signatures.js';
import type { ReaderContext } from './reader.js';
/** 字节队列:接收任意切分的块,按需取出前 n 个字节。 */
@@ -106,6 +108,8 @@ export interface ItemDecodeResult {
nextIndex: number;
/** 第 0 帧里的元数据;从中间帧续传时没有。 */
meta: ItemMeta | undefined;
/** Present only for complete reads starting at frame zero. */
ciphertextManifestHash?: Bytes;
}
/**
@@ -125,8 +129,10 @@ export async function* decryptItemFrames(
let flagsMask: number | undefined;
let finalSeen = false;
let meta: ItemMeta | undefined;
const frameDigests: Bytes[] = [];
for await (const bytes of splitEnvelopes(source)) {
frameDigests.push(await sha256(bytes));
const env = parseEnvelope(bytes);
const isEnc = (env.flags & Flags.Enc) !== 0;
@@ -157,7 +163,8 @@ export async function* decryptItemFrames(
if (data.length > 0) yield data;
}
return { complete: finalSeen, nextIndex: expected, meta };
return { complete: finalSeen, nextIndex: expected, meta,
...(finalSeen && (opts.fromIndex ?? 0) === 0 ? { ciphertextManifestHash: Uint8Array.from(await frameManifestHash(frameDigests)) } : {}) };
}
/** 把 decryptItemFrames 包成 ReadableStream,便于直接 pipe 到文件。 */