logicsrc/packages/agentad/src/tokens.test.ts
Anthony Ettinger 7d62e3b661
Some checks failed
CI / build (push) Has been cancelled
test / test (push) Has been cancelled
feat(agentad): AgentAd Marketplace PRD + reference exchange (M5)
Add the AgentBBS M5 "AgentAd marketplace" spec and a working reference
implementation built on the existing @logicsrc/schemas AgentAd contracts.

- docs/agentad-marketplace.md: two-sided exchange PRD (buy/sell sides,
  match -> auction -> pace -> serve -> meter -> settle, CoinPay settlement,
  AgentBBS as reference publisher, milestones M5.0-M5.5).
- packages/agentad (@logicsrc/agentad): reference exchange
  - builders that emit schema-valid, always-disclosed ad/campaign/placement docs
  - HMAC-signed, single-use impression/click tracking tokens
  - AgentAdExchange: targeting/format/category matching, second-price auction,
    budget pacing + daily caps, frequency capping, token-driven metering
  - pluggable settlement (InMemorySettlement) that can't overspend escrow
  - runtime validation against the canonical agentad-*.schema.json
- 22 vitest cases (builders, tokens, full serve/meter/settle lifecycle).
- Wire package into root build; link the PRD from README + docs/agentad.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 10:29:36 +00:00

49 lines
1.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { mintToken, verifyToken, type TokenPayload } from "./tokens.js";
const base: TokenPayload = {
k: "impression",
rid: "req-1",
pid: "plc-1",
aid: "ad-1",
cid: "cmp-1",
model: "cpc",
charge: 0.5,
cur: "USD",
exp: 2_000_000_000_000,
n: "abc123"
};
describe("AgentAd tracking tokens", () => {
it("round-trips a signed payload", () => {
const token = mintToken("s3cret", base);
const result = verifyToken("s3cret", token, 1_000);
expect(result.ok).toBe(true);
expect(result.payload).toEqual(base);
});
it("rejects a token signed with a different secret", () => {
const token = mintToken("s3cret", base);
const result = verifyToken("other", token, 1_000);
expect(result.ok).toBe(false);
expect(result.reason).toBe("bad_signature");
});
it("rejects a tampered body", () => {
const token = mintToken("s3cret", base);
const [, sig] = token.split(".");
const forged = `${Buffer.from(JSON.stringify({ ...base, charge: 9999 })).toString("base64url")}.${sig}`;
expect(verifyToken("s3cret", forged).ok).toBe(false);
});
it("rejects expired tokens", () => {
const token = mintToken("s3cret", { ...base, exp: 500 });
const result = verifyToken("s3cret", token, 1_000);
expect(result.ok).toBe(false);
expect(result.reason).toBe("expired");
});
it("flags malformed tokens", () => {
expect(verifyToken("s3cret", "not-a-token").reason).toBe("malformed");
});
});