From 21a911081075d559a921d3b90df124b6514d5619 Mon Sep 17 00:00:00 2001 From: Keon Kim Date: Sun, 31 May 2026 16:24:03 +0900 Subject: [PATCH] Add revenue refund liability reserve guard --- .../README.md | 49 ++++ .../demo.js | 27 ++ .../index.js | 269 ++++++++++++++++++ .../render-video.js | 50 ++++ .../reports/demo.mp4 | Bin 0 -> 53967 bytes .../reports/refund-liability-review.json | 109 +++++++ .../reports/refund-liability-review.md | 69 +++++ .../reports/refund-liability-review.svg | 35 +++ .../sample-data.js | 75 +++++ .../test.js | 66 +++++ 10 files changed, 749 insertions(+) create mode 100644 revenue-refund-liability-reserve-guard/README.md create mode 100644 revenue-refund-liability-reserve-guard/demo.js create mode 100644 revenue-refund-liability-reserve-guard/index.js create mode 100644 revenue-refund-liability-reserve-guard/render-video.js create mode 100644 revenue-refund-liability-reserve-guard/reports/demo.mp4 create mode 100644 revenue-refund-liability-reserve-guard/reports/refund-liability-review.json create mode 100644 revenue-refund-liability-reserve-guard/reports/refund-liability-review.md create mode 100644 revenue-refund-liability-reserve-guard/reports/refund-liability-review.svg create mode 100644 revenue-refund-liability-reserve-guard/sample-data.js create mode 100644 revenue-refund-liability-reserve-guard/test.js diff --git a/revenue-refund-liability-reserve-guard/README.md b/revenue-refund-liability-reserve-guard/README.md new file mode 100644 index 00000000..885235bd --- /dev/null +++ b/revenue-refund-liability-reserve-guard/README.md @@ -0,0 +1,49 @@ +# Revenue Refund Liability Reserve Guard + +This module adds a focused refund liability reserve guard for the Revenue +Infrastructure bounty. It evaluates whether subscription, institutional +invoice, and compute-credit refund requests are financially safe before cash +leaves the platform or entitlements are reversed. + +## Scope + +The guard checks synthetic refund packets for: + +- annual subscription refund eligibility and proration +- institutional invoice reversal evidence and approval status +- unused AI compute credit refund treatment +- non-refundable processor fees and tax handling +- entitlement rollback readiness before cash release +- refund evidence completeness +- reserve sufficiency by revenue stream and currency +- reviewer actions for hold, approve, or manual finance review decisions + +This is not a generic quote approval, billing readiness, payment rail, +dunning, dispute, tax exemption, proration, prepaid credit breakage, or +collections module. It focuses specifically on refund liability exposure and +reserve sufficiency before money is returned. + +## Issue #20 Requirement Mapping + +- Tiered subscription billing: evaluates subscription refunds, annual-plan + proration, cancellation terms, and entitlement rollback readiness. +- AI compute billing: checks unused compute-credit refund requests against + consumed usage, restricted grants, and available reserve coverage. +- Institutional invoicing: validates invoice reversal approvals, PO evidence, + and tax/processor fee treatment. +- Revenue operations: emits deterministic finance review packets, reserve + impact, audit digests, and curator actions for revenue teams. + +## Validation + +```bash +node revenue-refund-liability-reserve-guard/test.js +node revenue-refund-liability-reserve-guard/demo.js +node revenue-refund-liability-reserve-guard/render-video.js +node --check revenue-refund-liability-reserve-guard/index.js +node --check revenue-refund-liability-reserve-guard/sample-data.js +node --check revenue-refund-liability-reserve-guard/test.js +node --check revenue-refund-liability-reserve-guard/demo.js +node --check revenue-refund-liability-reserve-guard/render-video.js +git diff --check +``` diff --git a/revenue-refund-liability-reserve-guard/demo.js b/revenue-refund-liability-reserve-guard/demo.js new file mode 100644 index 00000000..ecde0e08 --- /dev/null +++ b/revenue-refund-liability-reserve-guard/demo.js @@ -0,0 +1,27 @@ +const fs = require("fs"); +const path = require("path"); +const packets = require("./sample-data"); +const { + evaluateRefundBatch, + renderMarkdownReport, + renderSvgReport, +} = require("./index"); + +const reportDir = path.join(__dirname, "reports"); +fs.mkdirSync(reportDir, { recursive: true }); + +const report = evaluateRefundBatch(packets); +const jsonPath = path.join(reportDir, "refund-liability-review.json"); +const markdownPath = path.join(reportDir, "refund-liability-review.md"); +const svgPath = path.join(reportDir, "refund-liability-review.svg"); + +fs.writeFileSync(jsonPath, `${JSON.stringify(report, null, 2)}\n`); +fs.writeFileSync(markdownPath, renderMarkdownReport(report)); +fs.writeFileSync(svgPath, renderSvgReport(report)); + +console.log(`wrote ${path.relative(process.cwd(), jsonPath)}`); +console.log(`wrote ${path.relative(process.cwd(), markdownPath)}`); +console.log(`wrote ${path.relative(process.cwd(), svgPath)}`); +console.log( + `summary: ${report.summary.hold} held refunds, ${report.summary.refundableAmount} refundable` +); diff --git a/revenue-refund-liability-reserve-guard/index.js b/revenue-refund-liability-reserve-guard/index.js new file mode 100644 index 00000000..1efce99a --- /dev/null +++ b/revenue-refund-liability-reserve-guard/index.js @@ -0,0 +1,269 @@ +const crypto = require("crypto"); + +function money(value) { + return Math.round(Number(value || 0) * 100) / 100; +} + +function requiredEvidenceFor(packet) { + const evidence = ["contract-term", "entitlement-rollback"]; + if (packet.revenueStream === "institutional_invoice") { + evidence.push("finance-approval"); + if (packet.requiresPOEvidence) { + evidence.push("po-or-invoice-evidence"); + } + } + if (packet.revenueStream === "ai_compute") { + evidence.push("credit-ledger", "usage-meter-snapshot"); + if (packet.restrictedGrantFunded) { + evidence.push("grant-refund-approval"); + } + } + if (packet.taxCollected > 0) { + evidence.push("tax-refund-treatment"); + } + return evidence; +} + +function missingEvidence(packet) { + const present = new Set(packet.evidence || []); + return requiredEvidenceFor(packet).filter((item) => !present.has(item)); +} + +function refundableAmount(packet) { + const serviceRefund = Math.min(packet.requestedRefund, packet.unusedServiceValue); + const taxComponent = packet.taxRefundable ? packet.taxCollected : 0; + return money(Math.max(0, serviceRefund + taxComponent - packet.processorFee)); +} + +function reserveImpact(packet) { + return money(refundableAmount(packet)); +} + +function evaluateRefund(packet) { + const blockers = []; + const warnings = []; + const actions = []; + const missing = missingEvidence(packet); + const refundable = refundableAmount(packet); + const overRequest = money(Math.max(0, packet.requestedRefund - packet.unusedServiceValue)); + const reserveAfter = money(packet.reserveAvailable - reserveImpact(packet)); + + if (missing.length > 0) { + blockers.push(`missing evidence: ${missing.join(", ")}`); + actions.push("hold refund until evidence packet is complete"); + } + + if (packet.approvalStatus !== "approved") { + blockers.push(`approval status is ${packet.approvalStatus}`); + actions.push("route to finance approver before cash release"); + } + + if (!packet.entitlementsRolledBack) { + blockers.push("entitlements are not rolled back"); + actions.push("rollback entitlements before refund release"); + } + + if (overRequest > 0) { + warnings.push(`requested refund exceeds unused service value by ${overRequest} ${packet.currency}`); + actions.push("cap refundable service amount at unused value"); + } + + if (packet.processorFee > 0) { + warnings.push(`processor fee ${packet.processorFee} ${packet.currency} is non-refundable`); + } + + if (packet.taxCollected > 0 && !packet.taxRefundable) { + warnings.push(`tax collected ${packet.taxCollected} ${packet.currency} requires non-refund treatment`); + } + + if (packet.restrictedGrantFunded && !(packet.evidence || []).includes("grant-refund-approval")) { + blockers.push("restricted grant-funded compute lacks refund approval"); + actions.push("hold refund for grant compliance review"); + } + + if (reserveAfter < 0) { + blockers.push(`refund reserve short by ${money(Math.abs(reserveAfter))} ${packet.currency}`); + actions.push("top up refund reserve before release"); + } else if (reserveAfter < refundable * 0.25) { + warnings.push(`reserve after refund is low at ${reserveAfter} ${packet.currency}`); + actions.push("notify finance about low reserve coverage"); + } + + if (blockers.length === 0) { + actions.push("approve refund for payment queue"); + actions.push("record reserve draw and revenue reversal"); + } + + const decision = + blockers.length > 0 ? "hold" : warnings.length > 0 ? "approve_with_adjustments" : "approve"; + + const result = { + refundId: packet.id, + customer: packet.customer, + revenueStream: packet.revenueStream, + currency: packet.currency, + requestedRefund: money(packet.requestedRefund), + refundableAmount: refundable, + reserveAvailable: money(packet.reserveAvailable), + reserveAfter, + decision, + blockers, + warnings, + actions: [...new Set(actions)], + }; + + return { + ...result, + auditDigest: digest(result), + }; +} + +function evaluateRefundBatch(packets) { + const decisions = packets.map(evaluateRefund); + const summary = decisions.reduce( + (acc, item) => { + acc.total += 1; + acc[item.decision] += 1; + acc.requestedRefund = money(acc.requestedRefund + item.requestedRefund); + acc.refundableAmount = money(acc.refundableAmount + item.refundableAmount); + acc.reserveDraw = money(acc.reserveDraw + Math.max(0, item.refundableAmount)); + if (item.decision === "hold") { + acc.heldRefunds = money(acc.heldRefunds + item.requestedRefund); + } + return acc; + }, + { + total: 0, + approve: 0, + approve_with_adjustments: 0, + hold: 0, + requestedRefund: 0, + refundableAmount: 0, + reserveDraw: 0, + heldRefunds: 0, + } + ); + + const report = { + generatedAt: new Date("2026-05-31T00:00:00Z").toISOString(), + summary, + decisions, + }; + + return { + ...report, + auditDigest: digest(report), + }; +} + +function renderMarkdownReport(report) { + const lines = [ + "# Revenue Refund Liability Reserve Report", + "", + `Generated: ${report.generatedAt}`, + `Audit digest: ${report.auditDigest}`, + "", + "## Summary", + "", + `- Refund packets: ${report.summary.total}`, + `- Approve: ${report.summary.approve}`, + `- Approve with adjustments: ${report.summary.approve_with_adjustments}`, + `- Hold: ${report.summary.hold}`, + `- Requested refund: ${report.summary.requestedRefund}`, + `- Refundable amount: ${report.summary.refundableAmount}`, + `- Reserve draw: ${report.summary.reserveDraw}`, + `- Held refunds: ${report.summary.heldRefunds}`, + "", + "## Decisions", + "", + ]; + + for (const item of report.decisions) { + lines.push(`### ${item.refundId}`); + lines.push(""); + lines.push(`- Customer: ${item.customer}`); + lines.push(`- Stream: ${item.revenueStream}`); + lines.push(`- Decision: ${item.decision}`); + lines.push(`- Requested refund: ${item.requestedRefund} ${item.currency}`); + lines.push(`- Refundable amount: ${item.refundableAmount} ${item.currency}`); + lines.push(`- Reserve after: ${item.reserveAfter} ${item.currency}`); + lines.push(`- Blockers: ${item.blockers.join("; ") || "none"}`); + lines.push(`- Warnings: ${item.warnings.join("; ") || "none"}`); + lines.push(`- Actions: ${item.actions.join("; ")}`); + lines.push(`- Digest: ${item.auditDigest}`); + lines.push(""); + } + + while (lines[lines.length - 1] === "") { + lines.pop(); + } + + return `${lines.join("\n")}\n`; +} + +function escapeXml(value) { + return String(value) + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """); +} + +function renderSvgReport(report) { + const cards = [ + ["Packets", report.summary.total, "#355c7d"], + ["Approved", report.summary.approve, "#2a9d8f"], + ["Adjusted", report.summary.approve_with_adjustments, "#e9c46a"], + ["Held", report.summary.hold, "#e76f51"], + ["Refundable", `$${report.summary.refundableAmount}`, "#457b9d"], + ["Held value", `$${report.summary.heldRefunds}`, "#b56576"], + ]; + + const cardSvg = cards + .map(([label, value, color], index) => { + const x = 72 + (index % 3) * 380; + const y = 188 + Math.floor(index / 3) * 150; + return [ + ``, + ``, + `${escapeXml(label)}`, + `${escapeXml(value)}`, + ].join("\n"); + }) + .join("\n"); + + const queueRows = report.decisions + .filter((item) => item.decision !== "approve") + .slice(0, 3) + .map((item, index) => { + const y = 545 + index * 32; + return `${escapeXml(item.refundId)} - ${escapeXml(item.decision)} - ${escapeXml(item.actions[0])}`; + }) + .join("\n"); + + return ` + + + Revenue Refund Liability Reserve Guard + Refund exposure and reserve sufficiency review + ${cardSvg} + Finance queue + ${queueRows} + Audit digest ${escapeXml(report.auditDigest.slice(0, 32))} +`; +} + +function digest(value) { + return crypto.createHash("sha256").update(JSON.stringify(value)).digest("hex"); +} + +module.exports = { + evaluateRefund, + evaluateRefundBatch, + refundableAmount, + reserveImpact, + requiredEvidenceFor, + renderMarkdownReport, + renderSvgReport, + digest, +}; diff --git a/revenue-refund-liability-reserve-guard/render-video.js b/revenue-refund-liability-reserve-guard/render-video.js new file mode 100644 index 00000000..40b0a9df --- /dev/null +++ b/revenue-refund-liability-reserve-guard/render-video.js @@ -0,0 +1,50 @@ +const fs = require("fs"); +const path = require("path"); +const { execFileSync } = require("child_process"); + +const reportDir = path.join(__dirname, "reports"); +const jsonPath = path.join(reportDir, "refund-liability-review.json"); +const svgPath = path.join(reportDir, "refund-liability-review.svg"); +const framePath = path.join(reportDir, "refund-liability-review.png"); +const outputPath = path.join(reportDir, "demo.mp4"); + +if (!fs.existsSync(jsonPath) || !fs.existsSync(svgPath)) { + require("./demo"); +} + +const report = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + +execFileSync( + "rsvg-convert", + ["--width", "1280", "--height", "720", "--output", framePath, svgPath], + { stdio: "inherit" } +); + +execFileSync( + "ffmpeg", + [ + "-y", + "-loop", + "1", + "-framerate", + "25", + "-i", + framePath, + "-t", + "4", + "-pix_fmt", + "yuv420p", + "-vf", + "scale=1280:720", + "-movflags", + "+faststart", + outputPath, + ], + { stdio: "inherit" } +); + +fs.unlinkSync(framePath); + +console.log( + `wrote ${path.relative(process.cwd(), outputPath)} for ${report.summary.total} refund packets` +); diff --git a/revenue-refund-liability-reserve-guard/reports/demo.mp4 b/revenue-refund-liability-reserve-guard/reports/demo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..879da938c351c00503bd23eefbbaa42394aefac2 GIT binary patch literal 53967 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 literal 0 HcmV?d00001 diff --git a/revenue-refund-liability-reserve-guard/reports/refund-liability-review.json b/revenue-refund-liability-reserve-guard/reports/refund-liability-review.json new file mode 100644 index 00000000..c7d896ce --- /dev/null +++ b/revenue-refund-liability-reserve-guard/reports/refund-liability-review.json @@ -0,0 +1,109 @@ +{ + "generatedAt": "2026-05-31T00:00:00.000Z", + "summary": { + "total": 4, + "approve": 0, + "approve_with_adjustments": 2, + "hold": 2, + "requestedRefund": 11100, + "refundableAmount": 9498, + "reserveDraw": 9498, + "heldRefunds": 7600 + }, + "decisions": [ + { + "refundId": "refund:annual-pro-cancel-clean", + "customer": "Northbridge Lab", + "revenueStream": "subscription", + "currency": "USD", + "requestedRefund": 900, + "refundableAmount": 938, + "reserveAvailable": 1200, + "reserveAfter": 262, + "decision": "approve_with_adjustments", + "blockers": [], + "warnings": [ + "processor fee 34 USD is non-refundable" + ], + "actions": [ + "approve refund for payment queue", + "record reserve draw and revenue reversal" + ], + "auditDigest": "39dbf4dd893713fc64b55d5d5ef6de4669a088120c01b5074ec3ed851de81155" + }, + { + "refundId": "refund:institutional-invoice-missing-po", + "customer": "East Valley University", + "revenueStream": "institutional_invoice", + "currency": "USD", + "requestedRefund": 7000, + "refundableAmount": 6200, + "reserveAvailable": 5000, + "reserveAfter": -1200, + "decision": "hold", + "blockers": [ + "missing evidence: entitlement-rollback, finance-approval, po-or-invoice-evidence", + "approval status is pending", + "entitlements are not rolled back", + "refund reserve short by 1200 USD" + ], + "warnings": [ + "requested refund exceeds unused service value by 800 USD" + ], + "actions": [ + "hold refund until evidence packet is complete", + "route to finance approver before cash release", + "rollback entitlements before refund release", + "cap refundable service amount at unused value", + "top up refund reserve before release" + ], + "auditDigest": "7705b511278e5888ce93be1264ae43da26dd26d8c441be69fbef7d6e50c351d1" + }, + { + "refundId": "refund:compute-credit-over-request", + "customer": "Helix AI Core", + "revenueStream": "ai_compute", + "currency": "USD", + "requestedRefund": 2600, + "refundableAmount": 1815, + "reserveAvailable": 2400, + "reserveAfter": 585, + "decision": "approve_with_adjustments", + "blockers": [], + "warnings": [ + "requested refund exceeds unused service value by 700 USD", + "processor fee 85 USD is non-refundable" + ], + "actions": [ + "cap refundable service amount at unused value", + "approve refund for payment queue", + "record reserve draw and revenue reversal" + ], + "auditDigest": "f8c6f3e25b3e20063c04d6ff23ce2c88a6a2975967f406763ccd19049e41aa49" + }, + { + "refundId": "refund:restricted-grant-compute", + "customer": "Civic Bio Grant", + "revenueStream": "ai_compute", + "currency": "USD", + "requestedRefund": 600, + "refundableAmount": 545, + "reserveAvailable": 1000, + "reserveAfter": 455, + "decision": "hold", + "blockers": [ + "missing evidence: grant-refund-approval", + "restricted grant-funded compute lacks refund approval" + ], + "warnings": [ + "processor fee 55 USD is non-refundable" + ], + "actions": [ + "hold refund until evidence packet is complete", + "hold refund for grant compliance review" + ], + "auditDigest": "adda46759e57cf7997019364e7c8467be44025f767d05debfcf68a612fa8798d" + } + ], + "auditDigest": "6c51ddbe808a1a8cacb81a52cfd1e832b78f82bbfc31c0e4df4bb16a373022af" +} diff --git a/revenue-refund-liability-reserve-guard/reports/refund-liability-review.md b/revenue-refund-liability-reserve-guard/reports/refund-liability-review.md new file mode 100644 index 00000000..2255e9de --- /dev/null +++ b/revenue-refund-liability-reserve-guard/reports/refund-liability-review.md @@ -0,0 +1,69 @@ +# Revenue Refund Liability Reserve Report + +Generated: 2026-05-31T00:00:00.000Z +Audit digest: 6c51ddbe808a1a8cacb81a52cfd1e832b78f82bbfc31c0e4df4bb16a373022af + +## Summary + +- Refund packets: 4 +- Approve: 0 +- Approve with adjustments: 2 +- Hold: 2 +- Requested refund: 11100 +- Refundable amount: 9498 +- Reserve draw: 9498 +- Held refunds: 7600 + +## Decisions + +### refund:annual-pro-cancel-clean + +- Customer: Northbridge Lab +- Stream: subscription +- Decision: approve_with_adjustments +- Requested refund: 900 USD +- Refundable amount: 938 USD +- Reserve after: 262 USD +- Blockers: none +- Warnings: processor fee 34 USD is non-refundable +- Actions: approve refund for payment queue; record reserve draw and revenue reversal +- Digest: 39dbf4dd893713fc64b55d5d5ef6de4669a088120c01b5074ec3ed851de81155 + +### refund:institutional-invoice-missing-po + +- Customer: East Valley University +- Stream: institutional_invoice +- Decision: hold +- Requested refund: 7000 USD +- Refundable amount: 6200 USD +- Reserve after: -1200 USD +- Blockers: missing evidence: entitlement-rollback, finance-approval, po-or-invoice-evidence; approval status is pending; entitlements are not rolled back; refund reserve short by 1200 USD +- Warnings: requested refund exceeds unused service value by 800 USD +- Actions: hold refund until evidence packet is complete; route to finance approver before cash release; rollback entitlements before refund release; cap refundable service amount at unused value; top up refund reserve before release +- Digest: 7705b511278e5888ce93be1264ae43da26dd26d8c441be69fbef7d6e50c351d1 + +### refund:compute-credit-over-request + +- Customer: Helix AI Core +- Stream: ai_compute +- Decision: approve_with_adjustments +- Requested refund: 2600 USD +- Refundable amount: 1815 USD +- Reserve after: 585 USD +- Blockers: none +- Warnings: requested refund exceeds unused service value by 700 USD; processor fee 85 USD is non-refundable +- Actions: cap refundable service amount at unused value; approve refund for payment queue; record reserve draw and revenue reversal +- Digest: f8c6f3e25b3e20063c04d6ff23ce2c88a6a2975967f406763ccd19049e41aa49 + +### refund:restricted-grant-compute + +- Customer: Civic Bio Grant +- Stream: ai_compute +- Decision: hold +- Requested refund: 600 USD +- Refundable amount: 545 USD +- Reserve after: 455 USD +- Blockers: missing evidence: grant-refund-approval; restricted grant-funded compute lacks refund approval +- Warnings: processor fee 55 USD is non-refundable +- Actions: hold refund until evidence packet is complete; hold refund for grant compliance review +- Digest: adda46759e57cf7997019364e7c8467be44025f767d05debfcf68a612fa8798d diff --git a/revenue-refund-liability-reserve-guard/reports/refund-liability-review.svg b/revenue-refund-liability-reserve-guard/reports/refund-liability-review.svg new file mode 100644 index 00000000..baba5bb9 --- /dev/null +++ b/revenue-refund-liability-reserve-guard/reports/refund-liability-review.svg @@ -0,0 +1,35 @@ + + + + Revenue Refund Liability Reserve Guard + Refund exposure and reserve sufficiency review + + +Packets +4 + + +Approved +0 + + +Adjusted +2 + + +Held +2 + + +Refundable +$9498 + + +Held value +$7600 + Finance queue + refund:annual-pro-cancel-clean - approve_with_adjustments - approve refund for payment queue +refund:institutional-invoice-missing-po - hold - hold refund until evidence packet is complete +refund:compute-credit-over-request - approve_with_adjustments - cap refundable service amount at unused value + Audit digest 6c51ddbe808a1a8cacb81a52cfd1e832 + \ No newline at end of file diff --git a/revenue-refund-liability-reserve-guard/sample-data.js b/revenue-refund-liability-reserve-guard/sample-data.js new file mode 100644 index 00000000..3bb58bee --- /dev/null +++ b/revenue-refund-liability-reserve-guard/sample-data.js @@ -0,0 +1,75 @@ +const refundPackets = [ + { + id: "refund:annual-pro-cancel-clean", + customer: "Northbridge Lab", + revenueStream: "subscription", + currency: "USD", + originalCharge: 2400, + requestedRefund: 900, + unusedServiceValue: 960, + processorFee: 34, + taxCollected: 72, + taxRefundable: true, + cancellationReason: "lab merged into institutional plan", + approvalStatus: "approved", + evidence: ["contract-term", "cancellation-ticket", "entitlement-rollback", "tax-refund-treatment"], + entitlementsRolledBack: true, + reserveAvailable: 1200, + }, + { + id: "refund:institutional-invoice-missing-po", + customer: "East Valley University", + revenueStream: "institutional_invoice", + currency: "USD", + originalCharge: 18000, + requestedRefund: 7000, + unusedServiceValue: 6200, + processorFee: 0, + taxCollected: 0, + taxRefundable: false, + cancellationReason: "department budget reallocation", + approvalStatus: "pending", + evidence: ["contract-term"], + entitlementsRolledBack: false, + reserveAvailable: 5000, + requiresPOEvidence: true, + }, + { + id: "refund:compute-credit-over-request", + customer: "Helix AI Core", + revenueStream: "ai_compute", + currency: "USD", + originalCharge: 5000, + requestedRefund: 2600, + unusedServiceValue: 1900, + processorFee: 85, + taxCollected: 0, + taxRefundable: false, + cancellationReason: "unused top-up credits", + approvalStatus: "approved", + evidence: ["contract-term", "credit-ledger", "usage-meter-snapshot", "entitlement-rollback"], + entitlementsRolledBack: true, + reserveAvailable: 2400, + restrictedGrantFunded: false, + }, + { + id: "refund:restricted-grant-compute", + customer: "Civic Bio Grant", + revenueStream: "ai_compute", + currency: "USD", + originalCharge: 3200, + requestedRefund: 600, + unusedServiceValue: 650, + processorFee: 55, + taxCollected: 0, + taxRefundable: false, + cancellationReason: "grant-funded compute pack closed", + approvalStatus: "approved", + evidence: ["contract-term", "entitlement-rollback", "credit-ledger", "usage-meter-snapshot", "grant-restriction"], + entitlementsRolledBack: true, + reserveAvailable: 1000, + restrictedGrantFunded: true, + }, +]; + +module.exports = refundPackets; diff --git a/revenue-refund-liability-reserve-guard/test.js b/revenue-refund-liability-reserve-guard/test.js new file mode 100644 index 00000000..7c6a05bb --- /dev/null +++ b/revenue-refund-liability-reserve-guard/test.js @@ -0,0 +1,66 @@ +const assert = require("assert"); +const packets = require("./sample-data"); +const { + evaluateRefund, + evaluateRefundBatch, + refundableAmount, + requiredEvidenceFor, +} = require("./index"); + +const report = evaluateRefundBatch(packets); + +function decision(id) { + return report.decisions.find((item) => item.refundId === id); +} + +assert.strictEqual(report.summary.total, 4); +assert.strictEqual(report.summary.approve, 0); +assert.strictEqual(report.summary.approve_with_adjustments, 2); +assert.strictEqual(report.summary.hold, 2); +assert.strictEqual(report.summary.requestedRefund, 11100); +assert.strictEqual(report.summary.heldRefunds, 7600); + +const clean = decision("refund:annual-pro-cancel-clean"); +assert.strictEqual(clean.decision, "approve_with_adjustments"); +assert.strictEqual(clean.refundableAmount, 938); +assert( + clean.warnings.some((item) => item.includes("processor fee")), + "clean annual refund should surface non-refundable processor fee" +); + +const invoice = decision("refund:institutional-invoice-missing-po"); +assert.strictEqual(invoice.decision, "hold"); +assert( + invoice.blockers.some((item) => item.includes("po-or-invoice-evidence")), + "institutional refund should require PO or invoice evidence" +); +assert( + invoice.blockers.some((item) => item.includes("approval status")), + "institutional refund should require approved finance status" +); +assert( + invoice.blockers.some((item) => item.includes("reserve short")), + "institutional refund should be held if reserve coverage is short" +); + +const compute = decision("refund:compute-credit-over-request"); +assert.strictEqual(compute.decision, "approve_with_adjustments"); +assert.strictEqual(compute.refundableAmount, 1815); +assert( + compute.warnings.some((item) => item.includes("exceeds unused service value")), + "compute over-request should be capped by unused service value" +); + +const restricted = decision("refund:restricted-grant-compute"); +assert.strictEqual(restricted.decision, "hold"); +assert( + restricted.blockers.some((item) => item.includes("grant-refund-approval")), + "restricted grant funded compute refund needs grant approval evidence" +); + +assert.strictEqual(refundableAmount(packets[0]), 938); +assert(requiredEvidenceFor(packets[1]).includes("po-or-invoice-evidence")); +assert.match(report.auditDigest, /^[a-f0-9]{64}$/); +assert.match(evaluateRefund(packets[0]).auditDigest, /^[a-f0-9]{64}$/); + +console.log("revenue refund liability reserve guard tests passed");