const { assertPeopleBaseline, buildRulePlan, execute, parseArgs, } = require("../../../src/scripts/apply-ceo-finance-fallback"); function currentRows() { return [ { id: "small-id", min_amount: "0.00", max_amount: "500.00", level1_role: "manager", level2_role: "finance", level3_role: null, owner_self_fallback_role: "finance_mgr", }, { id: "medium-id", min_amount: "500.00", max_amount: "5000.00", level1_role: "manager", level2_role: "finance_mgr", level3_role: null, owner_self_fallback_role: "finance_mgr", }, { id: "large-id", min_amount: "5000.00", max_amount: null, level1_role: "manager", level2_role: "ceo", level3_role: "finance_mgr", owner_self_fallback_role: "finance_mgr", }, ]; } describe("CEO finance fallback production apply contract", () => { it("builds the exact three-band target without exposing identifiers in the result shape", () => { const plan = buildRulePlan(currentRows()); expect(plan.map((item) => ({ band: item.band, after: item.after }))).toEqual([ { band: "small", after: { level1_role: "manager", level2_role: "finance", level3_role: null, owner_self_fallback_role: "finance", }, }, { band: "medium", after: { level1_role: "manager", level2_role: "finance", level3_role: null, owner_self_fallback_role: "finance", }, }, { band: "large", after: { level1_role: "manager", level2_role: "ceo", level3_role: "finance", owner_self_fallback_role: "finance", }, }, ]); }); it.each([ [currentRows().slice(0, 2), "approval_rule_count_drift"], [[...currentRows(), currentRows()[0]], "approval_rule_count_drift"], [currentRows().map((row, index) => index === 1 ? { ...row, level2_role: "finance" } : row), "approval_rule_role_drift:medium"], [currentRows().map((row, index) => index === 2 ? { ...row, min_amount: "6000" } : row), "approval_rule_amount_band_drift"], ])("fails closed on approval-rule drift", (rows, message) => { expect(() => buildRulePlan(rows)).toThrow(message); }); it("requires one bound CEO without manager/fallback role, one bound non-CEO finance, and one admin", () => { expect(() => assertPeopleBaseline({ ceos: [{ direct_manager_id: null, has_wecom_binding: true, roles: ["ceo"] }], finances: [{ has_wecom_binding: true, roles: ["finance"] }], admins: [{ roles: ["admin"] }], })).not.toThrow(); expect(() => assertPeopleBaseline({ ceos: [], finances: [], admins: [] })) .toThrow("active_ceo_count_drift"); expect(() => assertPeopleBaseline({ ceos: [{ direct_manager_id: null, has_wecom_binding: true, roles: ["ceo", "finance"] }], finances: [{ has_wecom_binding: true, roles: ["finance"] }], admins: [{ roles: ["admin"] }], })).toThrow("ceo_holds_fallback_role"); }); it("defaults to dry-run and rejects unknown arguments", () => { expect(parseArgs([])).toEqual({ apply: false, format: "text" }); expect(parseArgs(["--apply", "--format=json"])).toEqual({ apply: true, format: "json" }); expect(() => parseArgs(["--force"])).toThrow("Unsupported argument"); }); it("supplies an explicit UUID for each raw audit-log insert", async () => { const ruleIds = [ "11111111-1111-4111-8111-111111111111", "22222222-2222-4222-8222-222222222222", "33333333-3333-4333-8333-333333333333", ]; const sourceRows = currentRows().map((row, index) => ({ ...row, id: ruleIds[index] })); const targetRows = sourceRows.map((row) => ({ ...row, level2_role: row.id === ruleIds[2] ? "ceo" : "finance", level3_role: row.id === ruleIds[2] ? "finance" : null, owner_self_fallback_role: "finance", })); const adminId = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"; const auditCalls = []; const transactionCommands = []; let ruleSelectCount = 0; let invariantCount = 0; const client = { query: vi.fn(async (sql, params = []) => { const normalized = String(sql).replace(/\s+/g, " ").trim(); if (normalized.startsWith("BEGIN ") || normalized.startsWith("ROLLBACK")) { transactionCommands.push(normalized); return {}; } if (normalized.includes("FROM approval_rules")) { ruleSelectCount += 1; return { rows: ruleSelectCount === 1 ? sourceRows : targetRows }; } if (normalized.includes("JOIN employee_roles selected_role")) { if (params[0] === "ceo") { return { rows: [{ id: "ceo-id", direct_manager_id: null, has_wecom_binding: true, roles: ["ceo"] }] }; } if (params[0] === "finance") { return { rows: [{ id: "finance-id", direct_manager_id: null, has_wecom_binding: true, roles: ["finance"] }] }; } return { rows: [{ id: adminId, direct_manager_id: null, has_wecom_binding: false, roles: ["admin"] }] }; } if (normalized.includes("AS active_employees")) { invariantCount += 1; return { rows: [{ active_employees: 6, active_role_rows: 8, active_bindings: 6, workflow_snapshots: 0 }] }; } if (normalized.startsWith("UPDATE approval_rules")) return { rowCount: 1, rows: [{ id: params[0] }] }; if (normalized.startsWith("INSERT INTO audit_logs")) { auditCalls.push({ sql: normalized, params }); return { rowCount: 1 }; } throw new Error(`unexpected query: ${normalized}`); }), release: vi.fn(), }; const pool = { connect: vi.fn(async () => client), end: vi.fn(async () => {}) }; await expect(execute({ apply: false, format: "json" }, pool)).resolves.toMatchObject({ status: "DRY_RUN_PASS", rules: 3, auditRows: 0, }); expect(invariantCount).toBe(2); expect(transactionCommands).toEqual([ "BEGIN ISOLATION LEVEL SERIALIZABLE", "ROLLBACK", ]); expect(auditCalls).toHaveLength(3); for (const [index, call] of auditCalls.entries()) { expect(call.sql).toContain("(id, request_id, actor_id"); expect(call.sql).toContain("VALUES ($1::uuid, $2, $3::uuid"); expect(call.params[0]).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i); expect(call.params[1]).toMatch(/^ceo-finance-fallback-[0-9a-f-]+$/i); expect(call.params[2]).toBe(adminId); expect(call.params[3]).toBe(ruleIds[index]); expect(JSON.parse(call.params[4])).toMatchObject({ task: "07-28-ceo-finance-fallback", band: ["small", "medium", "large"][index], }); expect(call.params).toHaveLength(5); } }); });