feat: harden bridge origin/CSP, cache decryption, and overhaul the web client UI

This commit is contained in:
randogoth 2026-09-26 19:04:36 +03:00
parent f637d5be57
commit 80133da100
10 changed files with 975 additions and 352 deletions

View file

@ -317,11 +317,16 @@ export class Session {
have = concat(have, await this.readNoise());
if (length < 0 && have.length >= 4) {
length = new DataView(have.buffer).getUint32(0);
if (length < 1 || length > MAX_FRAME)
// §6.1: the shortest response is a type byte and a status byte.
if (length < 2 || length > MAX_FRAME)
throw new SmolError(`server sent a frame of length ${length}`);
}
}
const payload = have.slice(4, 4 + length);
// §6.1: a response reuses the request's type byte. A mismatch means the
// session desynchronised, which must not be mistaken for a status.
if (payload[0] !== op)
throw new SmolError(`server answered op 0x${payload[0].toString(16)}, expected 0x${op.toString(16)}`);
return { status: payload[1], body: payload.slice(2) }; // op echo, status, body (§6.1)
}
}
@ -391,7 +396,7 @@ export async function deleteOp(session, ids) {
const body = concat(u16BE(ids.length), ...ids);
const { status, body: reply } = await session.call(OP.DELETE, body);
expectOk(status, "acknowledging");
return new DataView(reply.buffer).getUint16(0);
return new Reader(reply).u16();
}
export async function registerOp(session, { username, identity, token = "", cert = null }) {