AUDIT / src /lib /acceptancePatternsCore.ts
Arypulka98's picture
feat(audit): deploy full backend cluster node (part 2)
cc11e77 verified
Raw
History Blame Contribute Delete
9.37 kB
// acceptancePatternsCore.ts — S-P3-1: split da acceptancePatterns.ts
// Sezioni: Auth / Login, CRUD, Dashboard, API / Backend, Database,
// Pagamenti, SaaS / Multi-tenant, Test suite, Package.json / deps
import type { AcceptanceTest } from './acceptanceTypes'; // anti-ciclo: tipo estratto da goalTestDeriver
export interface GoalPattern {
re: RegExp;
tests: Array<Omit<AcceptanceTest, "id">>;
}
export const CORE_PATTERNS: GoalPattern[] = [
// ── Auth / Login / Registration ─────────────────────────────────────────────
{
re: /login|signin|sign.?in|sign.?up|signup|registr(?:az|ation|ati)?|autenticaz|authentication|auth(?:orization|entication)?|logout|sessione?|password|jwt|bearer|token.?auth|oauth|2fa|mfa|otp/i,
tests: [
{
requirement: "File di autenticazione presente",
critical: true,
checkFn: `
const authFiles = files.filter(f =>
/auth|login|signin|session/i.test(f.path) && f.content
);
return { pass: authFiles.length > 0,
detail: authFiles.length > 0
? "Trovato: " + authFiles.map(f=>f.path).join(", ")
: "Mancano file auth/login nel VFS" };
`,
},
{
requirement: "Form di login con input email/password",
critical: false,
checkFn: `
const loginFile = files.find(f =>
/login|signin/i.test(f.path) && /email|password|input/i.test(f.content||"")
);
return { pass: !!loginFile,
detail: loginFile ? loginFile.path : "Nessun form login con email+password trovato" };
`,
},
],
},
// ── CRUD (crud|crm|list|crea|create|gestione) ───────────────────────────────
{
re: /\bcrud\b|(?:crea|aggiungi|add).{0,50}(?:modifica|edit|update).{0,50}(?:elimina|delete|rimuovi)|(?:insert|update|delete).{0,30}(?:insert|update|delete)|gestione.{0,40}(?:utenti|prodotti|ordini|clienti|record|entit)|lista.*(?:crea|aggiungi|modifica|elimina)|tabella.*modificabil/i,
tests: [
{
requirement: "Operazioni CRUD presenti nel codice",
critical: true,
checkFn: `
const crudOps = { create: false, read: false, update: false, delete: false };
for (const f of files) {
const c = (f.content||"").toLowerCase();
if (/insert|create|post.*body|supabase.*insert|\.add\(/i.test(c)) crudOps.create = true;
if (/select|find|get.*list|fetch.*all|supabase.*select/i.test(c)) crudOps.read = true;
if (/update|patch|put.*body|supabase.*update|\.set\(/i.test(c)) crudOps.update = true;
if (/delete|remove|supabase.*delete|\.destroy\(/i.test(c)) crudOps.delete = true;
}
const missing = Object.entries(crudOps).filter(([,v])=>!v).map(([k])=>k);
return { pass: missing.length === 0,
detail: missing.length === 0
? "C/R/U/D tutte presenti"
: "Mancano operazioni: " + missing.join(", ") };
`,
},
],
},
// ── Dashboard ───────────────────────────────────────────────────────────────
{
re: /dashboard|pannello|statistiche|analytics|chart|grafico|kpi/i,
tests: [
{
requirement: "Componente dashboard / statistiche presente",
critical: true,
checkFn: `
const dash = files.find(f =>
/dashboard|stats|analytics/i.test(f.path) && f.content
);
return { pass: !!dash,
detail: dash ? dash.path : "Manca file dashboard/stats nel VFS" };
`,
},
{
requirement: "Dati / metriche visualizzati (chart o tabella)",
critical: false,
checkFn: `
const hasChart = files.some(f =>
/recharts|chart\.js|apex|d3|nivo|canvas|<table|<tr/i.test(f.content||"")
);
return { pass: hasChart,
detail: hasChart ? "Libreria chart o tabella trovata" : "Nessuna visualizzazione dati trovata" };
`,
},
],
},
// ── API / Backend ───────────────────────────────────────────────────────────
{
re: /api|endpoint|rest|fastapi|express|backend|server/i,
tests: [
{
requirement: "File route/endpoint presente",
critical: true,
checkFn: `
const route = files.find(f =>
/route|endpoint|controller|api\//i.test(f.path) &&
/(app\.(get|post|put|delete|patch)|router\.|@app\.|@router\.)/i.test(f.content||"")
);
return { pass: !!route,
detail: route ? route.path : "Nessun route/endpoint trovato" };
`,
},
{
requirement: "Almeno 1 endpoint GET e 1 POST",
critical: false,
checkFn: `
const allCode = files.map(f=>f.content||"").join("\\n");
const hasGet = /(app|router)\.(get|route)\(|@app\.get|@router\.get/i.test(allCode);
const hasPost = /(app|router)\.(post|route)\(|@app\.post|@router\.post/i.test(allCode);
return { pass: hasGet && hasPost,
detail: (!hasGet ? "Manca GET " : "") + (!hasPost ? "Manca POST" : "GET e POST presenti") };
`,
},
],
},
// ── Database ────────────────────────────────────────────────────────────────
{
re: /database|supabase|postgresql|postgres|mysql|mongodb|sqlite|prisma|drizzle/i,
tests: [
{
requirement: "Schema / modello dati presente",
critical: true,
checkFn: `
const schema = files.find(f =>
/schema|model|migration|\.sql$|prisma/i.test(f.path) && f.content
);
const hasTableDef = files.some(f =>
/create table|defineTable|pgTable|model.*{|Schema\(/i.test(f.content||"")
);
return { pass: !!(schema || hasTableDef),
detail: schema ? schema.path : (hasTableDef ? "Schema trovato in codice" : "Manca schema/modello dati") };
`,
},
],
},
// ── Pagamenti ───────────────────────────────────────────────────────────────
{
re: /pagamento|stripe|payment|checkout|abbonamento|subscription/i,
tests: [
{
requirement: "Integrazione pagamenti (Stripe / checkout)",
critical: true,
checkFn: `
const payment = files.find(f =>
/stripe|payment|checkout/i.test(f.content||"")
);
return { pass: !!payment,
detail: payment ? payment.path : "Nessuna integrazione pagamenti trovata" };
`,
},
],
},
// ── SaaS / Multi-tenant ─────────────────────────────────────────────────────
{
re: /saas|multi.?tenant|organization|workspace|team/i,
tests: [
{
requirement: "Isolamento tenant (organization_id / workspace_id)",
critical: true,
checkFn: `
const allCode = files.map(f=>f.content||"").join("\\n");
const hasTenant = /organization_id|tenant_id|workspace_id|org_id|team_id/i.test(allCode);
return { pass: hasTenant,
detail: hasTenant ? "Tenant isolation trovata" : "Manca organization_id/tenant_id nei modelli" };
`,
},
],
},
// ── Test suite ──────────────────────────────────────────────────────────────
{
re: /test.*suite|unit test|integration test|vitest|jest|pytest/i,
tests: [
{
requirement: "File di test presenti",
critical: true,
checkFn: `
const tests = files.filter(f => /\\.test\\.|spec\\.|__tests__/i.test(f.path));
return { pass: tests.length > 0,
detail: tests.length > 0
? tests.length + " file di test: " + tests.slice(0,3).map(f=>f.path).join(", ")
: "Nessun file .test.ts / spec.ts trovato" };
`,
},
],
},
// ── Package.json / deps ─────────────────────────────────────────────────────
{
re: /\bapp\b|\bsito\b|progetto|project|applicazione/i,
tests: [
{
requirement: "package.json o requirements.txt presente",
critical: false,
checkFn: `
const pkg = files.find(f => f.path === "package.json" || f.path === "/package.json"
|| f.path === "requirements.txt");
return { pass: !!pkg, detail: pkg ? pkg.path + " trovato" : "Manca package.json / requirements.txt" };
`,
},
],
},
];