Something went wrong. Try again.
A local-first event pipeline for independent agents, built on Jazz.
Something went wrong. Try again.
2.4 kB · 61 lines
TypeScript
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162import { describe, expect, test } from "vitest";import { REVIEW_NONCE_HEADER, REVIEW_SIGNATURE_HEADER, REVIEW_TIMESTAMP_HEADER, ReviewCapabilityVerifier, decodeReviewCapability, signReviewRequest,} from "../src/review/web-capability.js";
describe("Review loopback capability", () => { test("binds method, path, body, time, and a one-time nonce", () => { const key = Buffer.alloc(32, 17); const now = 1_800_000_000_000; const path = "/api/reviews/review%3Aitem/decisions"; const body = Buffer.from('{"disposition":"skip"}', "utf8"); const signed = signReviewRequest(key, { method: "POST", path, body, timestamp: now, nonce: "A".repeat(32), }); const headers = { [REVIEW_TIMESTAMP_HEADER]: signed.timestamp, [REVIEW_NONCE_HEADER]: signed.nonce, [REVIEW_SIGNATURE_HEADER]: signed.signature, }; const verifier = new ReviewCapabilityVerifier(key, { now: () => now }); expect(verifier.verify(headers, "POST", path, body)).toBe(true); expect(verifier.verify(headers, "POST", path, body)).toBe(false);
const fresh = (suffix: string, at = now) => { const signature = signReviewRequest(key, { method: "POST", path, body, timestamp: at, nonce: suffix.repeat(32), }); return { [REVIEW_TIMESTAMP_HEADER]: signature.timestamp, [REVIEW_NONCE_HEADER]: signature.nonce, [REVIEW_SIGNATURE_HEADER]: signature.signature, }; }; expect(verifier.verify(fresh("B"), "GET", path, body)).toBe(false); expect(verifier.verify(fresh("C"), "POST", `${path}/other`, body)).toBe(false); expect(verifier.verify(fresh("D"), "POST", path, Buffer.from("{}"))).toBe(false); expect(verifier.verify(fresh("E", now - 31_000), "POST", path, body)).toBe(false); expect(verifier.verify({ ...fresh("F"), [REVIEW_SIGNATURE_HEADER]: "x".repeat(43) }, "POST", path, body)).toBe(false); });
test("loads only canonical bounded key material", () => { const encoded = Buffer.alloc(32, 9).toString("base64"); expect(decodeReviewCapability(encoded)).toEqual(Buffer.alloc(32, 9)); expect(decodeReviewCapability(undefined)).toBeUndefined(); expect(() => decodeReviewCapability("not base64 !!!")).toThrow("canonical base64"); expect(() => decodeReviewCapability(Buffer.alloc(8).toString("base64"))).toThrow("32 to 128"); });});