Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
249 changes: 175 additions & 74 deletions apps/api/src/lib/pricing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,15 @@ describe("provider pricing", () => {
latencyEstimateMs: 100,
qualityScore: 80,
sourceType: "deterministic-fallback",
enabled: true
enabled: true,
slaBadges: {
latencyBand: "fast",
latencyLabel: "Fast response",
reliabilityBand: "fallback",
reliabilityLabel: "Fallback cached",
paymentMode: "x402",
paymentLabel: "Pay-per-query (x402)"
}
});

providers.push({
Expand All @@ -94,7 +102,15 @@ describe("provider pricing", () => {
latencyEstimateMs: 100,
qualityScore: 80,
sourceType: "deterministic-fallback",
enabled: true
enabled: true,
slaBadges: {
latencyBand: "fast",
latencyLabel: "Fast response",
reliabilityBand: "fallback",
reliabilityLabel: "Fallback cached",
paymentMode: "x402",
paymentLabel: "Pay-per-query (x402)"
}
});

const sorted = getSortedProviders();
Expand All @@ -121,7 +137,15 @@ describe("provider pricing", () => {
latencyEstimateMs: 100,
qualityScore: 50,
sourceType: "deterministic-fallback",
enabled: false
enabled: false,
slaBadges: {
latencyBand: "fast",
latencyLabel: "Fast response",
reliabilityBand: "fallback",
reliabilityLabel: "Fallback cached",
paymentMode: "x402",
paymentLabel: "Pay-per-query (x402)"
}
});

const sorted = getSortedProviders();
Expand All @@ -139,6 +163,11 @@ describe("provider catalog baseline", () => {
priceUsd: number;
enabled: boolean;
sourceType: string;
slaBadges: {
latencyBand: string;
reliabilityBand: string;
paymentMode: string;
};
}

// These are the canonical baseline providers the demo and SCF pitch depend on.
Expand All @@ -150,21 +179,36 @@ describe("provider catalog baseline", () => {
category: "search",
priceUsd: 0.01,
enabled: true,
sourceType: "deterministic-fallback"
sourceType: "deterministic-fallback",
slaBadges: {
latencyBand: "fast",
reliabilityBand: "fallback",
paymentMode: "x402"
}
},
{
id: "news.fast",
category: "news",
priceUsd: 0.015,
enabled: true,
sourceType: "deterministic-fallback"
sourceType: "deterministic-fallback",
slaBadges: {
latencyBand: "fast",
reliabilityBand: "fallback",
paymentMode: "x402"
}
},
{
id: "scrape.page",
category: "scrape",
priceUsd: 0.02,
enabled: true,
sourceType: "deterministic-fallback"
sourceType: "deterministic-fallback",
slaBadges: {
latencyBand: "standard",
reliabilityBand: "fallback",
paymentMode: "x402"
}
}
];

Expand All @@ -182,10 +226,79 @@ describe("provider catalog baseline", () => {
expect(actual!.priceUsd, `${rowLabel} priceUsd mismatch`).toBe(expected.priceUsd);
expect(actual!.enabled, `${rowLabel} enabled mismatch`).toBe(expected.enabled);
expect(actual!.sourceType, `${rowLabel} sourceType mismatch`).toBe(expected.sourceType);
expect(actual!.slaBadges, `${rowLabel} slaBadges missing`).toBeDefined();
expect(actual!.slaBadges.latencyBand, `${rowLabel} latencyBand mismatch`).toBe(
expected.slaBadges.latencyBand
);
expect(actual!.slaBadges.reliabilityBand, `${rowLabel} reliabilityBand mismatch`).toBe(
expected.slaBadges.reliabilityBand
);
expect(actual!.slaBadges.paymentMode, `${rowLabel} paymentMode mismatch`).toBe(
expected.slaBadges.paymentMode
);
expect(actual!.slaBadges.latencyLabel, `${rowLabel} latencyLabel missing`).toBeTruthy();
expect(
actual!.slaBadges.reliabilityLabel,
`${rowLabel} reliabilityLabel missing`
).toBeTruthy();
expect(actual!.slaBadges.paymentLabel, `${rowLabel} paymentLabel missing`).toBeTruthy();
});
}
});

describe("provider SLA badges shape", () => {
it("every provider has slaBadges with all required fields", () => {
for (const p of providers) {
expect(p.slaBadges).toBeDefined();
expect(["fast", "standard", "slow"]).toContain(p.slaBadges.latencyBand);
expect(["demo", "fallback", "live"]).toContain(p.slaBadges.reliabilityBand);
expect(["demo", "x402", "sponsored"]).toContain(p.slaBadges.paymentMode);
expect(typeof p.slaBadges.latencyLabel).toBe("string");
expect(p.slaBadges.latencyLabel.length).toBeGreaterThan(0);
expect(typeof p.slaBadges.reliabilityLabel).toBe("string");
expect(p.slaBadges.reliabilityLabel.length).toBeGreaterThan(0);
expect(typeof p.slaBadges.paymentLabel).toBe("string");
expect(p.slaBadges.paymentLabel.length).toBeGreaterThan(0);
}
});

it("derives correct latencyBand for each provider", () => {
const expectations: Record<string, string> = {
"search.live": "standard",
"search.basic": "fast",
"search.pro": "standard",
"news.fast": "fast",
"news.deep": "standard",
"scrape.page": "standard",
"scrape.extract": "slow"
};

for (const [id, expectedBand] of Object.entries(expectations)) {
const provider = providers.find((p) => p.id === id);
expect(provider, `Provider "${id}" not found`).toBeDefined();
expect(provider!.slaBadges.latencyBand).toBe(expectedBand);
}
});

it("derives correct reliabilityBand from sourceType", () => {
for (const p of providers) {
const expectedBand =
p.sourceType === "live"
? "live"
: p.sourceType === "deterministic-fallback"
? "fallback"
: "demo";
expect(p.slaBadges.reliabilityBand).toBe(expectedBand);
}
});

it("all providers have paymentMode x402", () => {
for (const p of providers) {
expect(p.slaBadges.paymentMode).toBe("x402");
}
});
});

describe("x402 cross-layer price consistency", () => {
// Convert USD to integer micro-USD units to eliminate IEEE 754 float comparison risk.
function toMicroUsd(value: number): number {
Expand Down Expand Up @@ -242,79 +355,67 @@ describe("x402 cross-layer price consistency", () => {
});
}

it(
"falls back to route base price for unknown provider IDs — base price must be defined for all x402 route modes",
() => {
for (const mode of routeModes) {
const routeKey = `GET /x402/${mode}`;
const basePrice = protectedRouteBasePrices[routeKey];
expect(
basePrice,
`Missing fallback base price for route "${routeKey}" — agents with unknown providers would receive no valid payment requirement`
).toBeDefined();
expect(
basePrice,
`Fallback base price for "${routeKey}" is not a valid USD price string`
).toMatch(/^\$\d+\.?\d*$/);
}
}
);

it(
"getProviderById('phantom.provider') returns undefined — unknown providers resolve to undefined and do not alter base price",
() => {
expect(getProviderById("phantom.provider")).toBeUndefined();
expect(getProviderById("")).toBeUndefined();
expect(getProviderById("search")).toBeUndefined();
it("falls back to route base price for unknown provider IDs — base price must be defined for all x402 route modes", () => {
for (const mode of routeModes) {
const routeKey = `GET /x402/${mode}`;
const basePrice = protectedRouteBasePrices[routeKey];
expect(
basePrice,
`Missing fallback base price for route "${routeKey}" — agents with unknown providers would receive no valid payment requirement`
).toBeDefined();
expect(
basePrice,
`Fallback base price for "${routeKey}" is not a valid USD price string`
).toMatch(/^\$\d+\.?\d*$/);
}
);

it(
"category mismatch guard — a provider from one category cannot resolve under a different route mode",
() => {
const allIds = providers.map((p) => p.id);
const uniqueIds = new Set(allIds);
expect(uniqueIds.size).toBe(allIds.length);

for (const mode of routeModes) {
const categoryIds = new Set(providers.filter((p) => p.category === mode).map((p) => p.id));
const otherModes = routeModes.filter((m) => m !== mode);
for (const other of otherModes) {
const otherIds = providers.filter((p) => p.category === other).map((p) => p.id);
const collision = otherIds.find((id) => categoryIds.has(id));
expect(
collision,
`Provider ID "${collision}" appears in both "${mode}" and "${other}" categories — x402 category-match guard would be bypassed`
).toBeUndefined();
}
});

it("getProviderById('phantom.provider') returns undefined — unknown providers resolve to undefined and do not alter base price", () => {
expect(getProviderById("phantom.provider")).toBeUndefined();
expect(getProviderById("")).toBeUndefined();
expect(getProviderById("search")).toBeUndefined();
});

it("category mismatch guard — a provider from one category cannot resolve under a different route mode", () => {
const allIds = providers.map((p) => p.id);
const uniqueIds = new Set(allIds);
expect(uniqueIds.size).toBe(allIds.length);

for (const mode of routeModes) {
const categoryIds = new Set(providers.filter((p) => p.category === mode).map((p) => p.id));
const otherModes = routeModes.filter((m) => m !== mode);
for (const other of otherModes) {
const otherIds = providers.filter((p) => p.category === other).map((p) => p.id);
const collision = otherIds.find((id) => categoryIds.has(id));
expect(
collision,
`Provider ID "${collision}" appears in both "${mode}" and "${other}" categories — x402 category-match guard would be bypassed`
).toBeUndefined();
}
}
);

it(
"drift-detection: surfaces offending provider ID when catalog price diverges from route base price",
() => {
// Simulate drift: search.basic raised from $0.01 to $0.05 without updating protectedRouteBasePrices.
const driftedProviders = providers.map((p) =>
p.id === "search.basic" ? { ...p, priceUsd: 0.05 } : p
);
});

const searchProviders = driftedProviders.filter((p) => p.category === "search" && p.enabled);
const routeBase = protectedRouteBasePrices["GET /x402/search"];
expect(routeBase).toBeDefined();
it("drift-detection: surfaces offending provider ID when catalog price diverges from route base price", () => {
// Simulate drift: search.basic raised from $0.01 to $0.05 without updating protectedRouteBasePrices.
const driftedProviders = providers.map((p) =>
p.id === "search.basic" ? { ...p, priceUsd: 0.05 } : p
);

const baseMicroUsd = toMicroUsd(parseRoutePrice(routeBase));
const minCategoryMicroUsd = toMicroUsd(Math.min(...searchProviders.map((p) => p.priceUsd)));
const searchProviders = driftedProviders.filter((p) => p.category === "search" && p.enabled);
const routeBase = protectedRouteBasePrices["GET /x402/search"];
expect(routeBase).toBeDefined();

// With search.basic at 0.05, new minimum is search.pro at 0.02 (20000 µ$).
// Route base remains $0.01 (10000 µ$) — drift is detected.
const hasDrift = baseMicroUsd !== minCategoryMicroUsd;
expect(hasDrift).toBe(true);
const baseMicroUsd = toMicroUsd(parseRoutePrice(routeBase));
const minCategoryMicroUsd = toMicroUsd(Math.min(...searchProviders.map((p) => p.priceUsd)));

const deviatingProviders = searchProviders
.filter((p) => toMicroUsd(p.priceUsd) !== baseMicroUsd)
.map((p) => p.id);
expect(deviatingProviders).toContain("search.basic");
}
);
// With search.basic at 0.05, new minimum is search.pro at 0.02 (20000 µ$).
// Route base remains $0.01 (10000 µ$) — drift is detected.
const hasDrift = baseMicroUsd !== minCategoryMicroUsd;
expect(hasDrift).toBe(true);

const deviatingProviders = searchProviders
.filter((p) => toMicroUsd(p.priceUsd) !== baseMicroUsd)
.map((p) => p.id);
expect(deviatingProviders).toContain("search.basic");
});
});
Loading
Loading