/*
RFC-1326 acceptance tests: CLOUDFLARE_PERMISSIONS registry contents
(AC-1 — Vectorize Edit carries agent.search.index.create in usedBy),
probe coverage invariants, WORKSHOP_ENV_ALLOWLIST matching, and the
registry-rendered doc/hint strings the three permission surfaces consume.
- RFC-1326: initial — AC-1 registry assertions, probe/unknown invariants, allow-list match, render helpers.
- RFC-1326: single Cloudflare permission registry, token preflight, birth provisioning
- RFC-1326: review-fix pass — siteName targeting for app-scoped provisioning, allow-list completion
*/
import { describe, expect, test } from "vitest";
import {
CLOUDFLARE_PERMISSIONS,
WORKSHOP_ENV_ALLOWLIST,
cloudflareTokenObtainHint,
renderCloudflarePermissionCommentLines,
renderCloudflarePermissionTableRows,
workshopEnvAllowed,
} from "./permissions.ts";
describe("CLOUDFLARE_PERMISSIONS", () => {
// AC-1: Vectorize Edit is listed and names agent.search.index.create.
test("AC-1: account.vectorize.edit lists agent.search.index.create in usedBy", () => {
const vectorize = CLOUDFLARE_PERMISSIONS.find((p) => p.id === "account.vectorize.edit");
expect(vectorize).toBeDefined();
expect(vectorize!.scope).toBe("account");
expect(vectorize!.level).toBe("Edit");
expect(vectorize!.requiredFor).toBe("always");
expect(vectorize!.usedBy).toContain("agent.search.index.create");
});
test("the eight dp7-verified permissions are present", () => {
expect(CLOUDFLARE_PERMISSIONS.map((p) => p.id)).toEqual([
"account.workers-scripts.edit",
"account.vectorize.edit",
"account.account-settings.read",
"zone.zone.read",
"zone.dns.edit",
"zone.workers-routes.edit",
"zone.cache-purge.purge",
"zone.single-redirect.edit",
]);
});
test("every permission is probeable except write-only Cache Purge", () => {
for (const p of CLOUDFLARE_PERMISSIONS) {
if (p.id === "zone.cache-purge.purge") {
expect(p.probe).toBeNull();
} else {
expect(p.probe, p.id).not.toBeNull();
expect(p.probe!.method).toBe("GET");
}
}
});
test("account probes substitute {accountId}, zone probes substitute {zoneId}", () => {
for (const p of CLOUDFLARE_PERMISSIONS) {
if (!p.probe) continue;
if (p.scope === "account") {
expect(p.probe.path, p.id).toContain("{accountId}");
} else {
expect(p.probe.path, p.id).toContain("{zoneId}");
}
}
});
test("Page Rules is absent — the stale copy listed it, the registry does not", () => {
expect(CLOUDFLARE_PERMISSIONS.some((p) => /page.rules/i.test(p.id))).toBe(false);
});
});
describe("WORKSHOP_ENV_ALLOWLIST", () => {
test("kernel keys are allowed; site/service keys are not", () => {
for (const allowed of [
"CLOUDFLARE_API_TOKEN",
"CLOUDFLARE_ACCOUNT_ID",
"CLOUDFLARE_ZONE_ID",
"CLOUDFLARE_READONLY_API_TOKEN",
"SIGNING_PRIVATE_KEY",
"SIGNING_PRIVATE_KEY_PATH",
"WERKSTATT_OPERATOR_SIGNING_KEY",
"R2_AXIOM_ACCOUNT_ID",
"R2_NACHWEIS_SECRET_ACCESS_KEY",
"FLEET_OWNERSHIP_REGISTRY_URL",
"FLEET_OWNERSHIP_REGISTRY_TOKEN",
"PASSPORT_SIGNING_KEY",
"PUBLIC_KEY_URL",
"LLM_PROVIDER",
"LLM_MODEL",
"LLM_API_KEY",
"WARPGOGOL_OTLP_ENDPOINT",
"WARPGOGOL_OTLP_TOKEN",
"UPSTASH_REDIS_REST_URL",
"UPSTASH_REDIS_REST_TOKEN",
]) {
expect(workshopEnvAllowed(allowed), allowed).toBe(true);
}
for (const denied of [
"LANGUAGETOOL_URL",
"LAGEBILD_API_KEY",
"GH_TOKEN",
"OPENAI_API_KEY",
"SEARCH_REINDEX_TOKEN",
"STRIPE_SECRET_KEY",
"GSC_SERVICE_ACCOUNT_JSON",
"ECOSYSTEM_COMMIT",
]) {
expect(workshopEnvAllowed(denied), denied).toBe(false);
}
});
test("every entry names its consumer — a wildcard request cannot sneak in", () => {
for (const entry of WORKSHOP_ENV_ALLOWLIST) {
expect(entry.consumer.length, entry.key).toBeGreaterThan(10);
}
});
});
describe("registry-rendered surfaces", () => {
test("the token obtain hint lists every registry permission", () => {
const hint = cloudflareTokenObtainHint();
for (const p of CLOUDFLARE_PERMISSIONS) {
expect(hint).toContain(`${p.group} → ${p.level}`);
}
expect(hint).not.toContain("Page Rules");
});
test("doc table rows carry scope, level and consumers", () => {
const rows = renderCloudflarePermissionTableRows();
expect(rows).toHaveLength(CLOUDFLARE_PERMISSIONS.length);
expect(rows[1]).toContain("**Account → Vectorize**");
expect(rows[1]).toContain("`agent.search.index.create`");
});
test("env comment lines are #-prefixed and carry consumers", () => {
const lines = renderCloudflarePermissionCommentLines();
expect(lines).toHaveLength(CLOUDFLARE_PERMISSIONS.length);
for (const line of lines) {
expect(line.startsWith("# ")).toBe(true);
}
expect(lines[1]).toContain("agent.search.index.create");
});
});