/* RFC-1301 parity test — every fixture entity gets the same accept/reject verdict from the canonical pbpSchemaById Zod schema and from the exported werkstatt:intake/v1 JSON Schema $defs (Ajv draft 2020-12), so external producers can validate pbp[] entities without the werkstatt checkout. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-1328 review (F-1): envelope-level Ajv coverage — $defs accept statementByLocale/localeNeutral, canonical strict schemas still reject them. RFC-1311: Compass header sweep — declares the intake suite's contract for test-file scaffold coverage. */ import Ajv2020 from "ajv/dist/2020.js"; import addFormats from "ajv-formats"; import { describe, expect, it } from "vitest"; import YAML from "yaml"; import { pbpSchemaById } from "@warpgogol/pbp/entities"; import { INTAKE_PBP_SCHEMA_ALLOWLIST, intakePbpDefKey, renderIntakeSchemaExport, } from "@warpgogol/werkstatt-shared/onboarding/intake"; import { renderIntakePbpEntityJsonSchemas } from "./intake-schema-export.ts"; const base = (type: string, id: string) => ({ schema: `pbp/${type}@1`, id, type, status: "published", }); const VALID: Record[] = [ { ...base("business", "business/dp7"), name: "DP7", legalIdentityRef: { ref: "pbp/legal-identity@1:legal-identity/dp7" }, }, { ...base("legal-identity", "legal-identity/dp7"), legalName: "DP7 Digitalprojekt GmbH" }, { ...base("offering", "offering/seo-audit"), name: "SEO Audit Standard", businessRef: { ref: "pbp/business@1:business/dp7" }, availability: { mode: "declared" }, pricing: { currency: "EUR" }, }, { ...base("claim", "claim/european-quality"), claimClass: "factual", claimKind: "fact", subject: { kind: "business", name: "DP7" }, statement: "European quality", statementLang: "en", governance: { authorityRef: "pbp/business@1:business/dp7" }, }, { ...base("evidence-source", "evidence-source/src-01"), name: "Client interview", kind: "client-statement", authority: { kind: "client" }, slug: "client-interview", display: { document: "visible", screenshot: "hidden", websiteLink: "hidden" }, items: { src: { sha256: "a".repeat(64), mediaType: "text/markdown", storage: "private" } }, }, { ...base("disclosure", "disclosure/cdn"), kind: "technology-dependency", name: "Cloudflare Dependency", statement: "Site uses Cloudflare CDN", materiality: "informative", publication: { required: true }, }, { ...base("contact-point", "contact-point/email"), name: "General Email", channel: "email", value: "hello@example.com", }, { ...base("brand", "brand/dp7"), name: "DP7", ownerBusinessRef: { ref: "pbp/business@1:business/dp7" }, }, ]; /** Structural violations — both validators must reject. */ const INVALID: Record[] = [ { ...VALID[0], name: undefined }, { ...VALID[0], unknownField: 1 }, { ...VALID[1], status: "archived" }, { ...VALID[2], businessRef: undefined }, { ...VALID[2], presentation: { price: { monthly: "70 € / Monat" } } }, { ...VALID[3], claimClass: 42 }, { ...VALID[4], items: "src" }, { ...VALID[5], publication: { required: "yes" } }, { ...VALID[6], channel: "fax" }, { ...VALID[7], ownerBusinessRef: undefined }, ].map((e) => JSON.parse(JSON.stringify(e)) as Record); function exportedValidators() { const doc = YAML.parse( renderIntakeSchemaExport({ pbpEntitySchemas: renderIntakePbpEntityJsonSchemas() }), ) as Record; const ajv = new Ajv2020({ allErrors: true, strict: false }); addFormats(ajv); ajv.addSchema(doc); const id = doc["$id"] as string; return (schemaId: string) => ajv.getSchema(`${id}#/$defs/${intakePbpDefKey(schemaId)}`)!; } describe("RFC-1301 intake pbp entity JSON Schema parity", () => { const exported = exportedValidators(); it("exports a $defs entry for every v1 allow-listed entity type", () => { for (const id of INTAKE_PBP_SCHEMA_ALLOWLIST) expect(exported(id)).toBeTypeOf("function"); }); it("covers every allow-listed type in the valid fixture set", () => { expect(new Set(VALID.map((e) => e["schema"]))).toEqual(new Set(INTAKE_PBP_SCHEMA_ALLOWLIST)); }); for (const entity of [...VALID, ...INVALID]) { const label = `${String(entity["schema"])} ${JSON.stringify(entity).slice(0, 80)}`; it(`agrees with pbpSchemaById: ${label}`, () => { const schemaId = entity["schema"] as string; const zodOk = pbpSchemaById[schemaId]!.safeParse(entity).success; const jsonOk = exported(schemaId)(entity) as boolean; expect(jsonOk).toBe(zodOk); }); } it("accepts every valid fixture and rejects every invalid one", () => { for (const e of VALID) expect(pbpSchemaById[e["schema"] as string]!.safeParse(e).success).toBe(true); for (const e of INVALID) expect(pbpSchemaById[e["schema"] as string]!.safeParse(e).success, JSON.stringify(e)).toBe( false, ); }); }); describe("RFC-1328/AMD-005: envelope-only fields on the exported $defs", () => { const exported = exportedValidators(); it("every allow-listed $def accepts statementByLocale + localeNeutral", () => { // The $defs describe pbp[] items *as they appear in the envelope* — a // producer validating an AMD-005-conformant entity must not be rejected // by additionalProperties: false inside the $ref'd canonical fragment. for (const entity of VALID) { const withEnvelopeFields = { ...entity, statementByLocale: { "uz-Latn": "Lokalisierte Angabe" }, localeNeutral: false, }; expect( exported(entity["schema"] as string)(withEnvelopeFields), String(entity["schema"]), ).toBe(true); } }); it("the canonical strict Zod schemas still reject the envelope fields", () => { // Envelope-only by contract — pbp/*@1 schemas stay frozen; the intake // layer strips the fields before the canonical parse (INTAKE-03, seed). const withEnvelopeFields = { ...VALID[3], statementByLocale: { "uz-Latn": "x" }, localeNeutral: true, }; expect( pbpSchemaById[VALID[3]!["schema"] as string]!.safeParse(withEnvelopeFields).success, ).toBe(false); }); });