diff --git a/lib/services/phishing-automation-gate.ts b/lib/services/phishing-automation-gate.ts new file mode 100644 index 0000000..c6cd297 --- /dev/null +++ b/lib/services/phishing-automation-gate.ts @@ -0,0 +1,58 @@ +/** + * Phase 23 D-06/D-07: per-company phishing automation gate reader. + * + * Opt-in model — a company with no `phishing_automation_gate` row has all + * three stages OFF. Mirrors the COALESCE(..., false)-over-LEFT-JOIN pattern + * used by `app/api/admin/phishing-automation/route.ts`, but scoped to a + * single company for the webhook's per-ticket gate check. + */ + +import { postgresClient } from './postgres-client'; + +export interface CompanyAutomationGate { + autoParse: boolean; + autoClassify: boolean; + autoReport: boolean; +} + +const ALL_FALSE: CompanyAutomationGate = { + autoParse: false, + autoClassify: false, + autoReport: false, +}; + +/** + * Reads the automation gate flags for a company. Absent row, null, or NaN + * companyId all resolve to all-false — never throws. + */ +export async function getCompanyAutomationGate( + companyId: number | null +): Promise { + if (companyId === null || Number.isNaN(companyId)) { + return { ...ALL_FALSE }; + } + + const result = await postgresClient.query<{ + auto_parse: boolean; + auto_classify: boolean; + auto_report: boolean; + }>( + `SELECT COALESCE(auto_parse, false) AS auto_parse, + COALESCE(auto_classify, false) AS auto_classify, + COALESCE(auto_report, false) AS auto_report + FROM phishing_automation_gate + WHERE company_id = $1`, + [companyId] + ); + + const row = result.rows[0]; + if (!row) { + return { ...ALL_FALSE }; + } + + return { + autoParse: row.auto_parse, + autoClassify: row.auto_classify, + autoReport: row.auto_report, + }; +}