import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { join } from "node:path"; import test from "node:test"; const source = async (relativePath: string) => { return await readFile( join(process.cwd(), ...relativePath.split("/")), "utf8", ); }; test("public audit schema stores reviewed public observations and offer separately", async () => { const schemaSource = await source("convex/schema.ts"); assert.match(schemaSource, /publicObservations/); assert.match(schemaSource, /observation:\s*v\.string\(\)/); assert.match(schemaSource, /impact:\s*v\.string\(\)/); assert.match(schemaSource, /suggestion:\s*v\.string\(\)/); assert.match(schemaSource, /screenshotIds:\s*v\.optional\(v\.array\(v\.id\("_storage"\)\)\)/); assert.match(schemaSource, /publicOffer/); assert.match(schemaSource, /ctaLabel:\s*v\.optional\(v\.string\(\)\)/); assert.match(schemaSource, /ctaHref:\s*v\.optional\(v\.string\(\)\)/); }); test("public audit convex query only exposes published, bounded, public data", async () => { const auditsSource = await source("convex/audits.ts"); assert.match(auditsSource, /export const getPublicBySlug = query/); assert.match( auditsSource, /\.withIndex\("by_slug",\s*\(q\)\s*=>\s*q\.eq\("slug",\s*args\.slug\)\)\s*\.unique\(\)/, "Public lookup should use the unique slug index.", ); assert.match( auditsSource, /audit\.status !== "published"/, "Draft and approved audits should not expose public content.", ); assert.match(auditsSource, /audit\.status === "deactivated"/); assert.match(auditsSource, /\.withIndex\("by_auditId"/); assert.match(auditsSource, /\.take\(\s*8\s*\)/); assert.match(auditsSource, /ctx\.storage\.getUrl\(screenshot\.storageId\)/); assert.doesNotMatch( auditsSource.match(/export const getPublicBySlug[\s\S]*?export const/)?.[0] ?? "", /usedSkills|internalSummary|skillSummaries|pageSpeedSummary/, "The public query should not return internal audit fields.", ); }); test("public audit write mutations require authenticated operators", async () => { const auditsSource = await source("convex/audits.ts"); for (const exportName of [ "savePublicAuditContent", "publishPublicAudit", "reapprovePublicAudit", "deactivatePublicAudit", ]) { assert.match(auditsSource, new RegExp(`export const ${exportName} = mutation`)); } assert.match(auditsSource, /ctx\.auth\.getUserIdentity\(\)/); assert.match(auditsSource, /Nicht autorisiert/); assert.match(auditsSource, /publishedAt:\s*now/); assert.match(auditsSource, /deactivatedAt:\s*now/); });