diff --git a/revenue-tax-exemption-controls/README.md b/revenue-tax-exemption-controls/README.md new file mode 100644 index 0000000..fcc565c --- /dev/null +++ b/revenue-tax-exemption-controls/README.md @@ -0,0 +1,24 @@ +# Revenue Tax Exemption Controls + +This module adds a focused Revenue Infrastructure slice for institutional tax exemption and grant billing compliance. It avoids live payment credentials and evaluates invoice readiness with deterministic local data. + +## What it checks + +- Expired or missing exemption certificates +- Reverse-charge invoices without VAT ID evidence +- Tax amount mismatch against configured jurisdictions +- Unknown tax jurisdictions that require finance review +- Grant budget overrun risk +- Invoice line categories outside grant-approved spend +- Payment settlement events that are missing or mismatched +- Invoice-level recommended actions and an audit digest + +## Run locally + +```bash +npm run check +npm test +npm run demo +``` + +The sample data intentionally places two invoices on hold: one has an expired exemption certificate, grant-category drift, and settlement mismatch; the other has missing VAT ID evidence for reverse charge. diff --git a/revenue-tax-exemption-controls/demo.js b/revenue-tax-exemption-controls/demo.js new file mode 100644 index 0000000..f57edd3 --- /dev/null +++ b/revenue-tax-exemption-controls/demo.js @@ -0,0 +1,23 @@ +"use strict"; + +const sampleBundle = require("./sample-data.json"); +const { + analyzeRevenueTaxControls, +} = require("./src/revenue-tax-exemption-controls"); + +const result = analyzeRevenueTaxControls(sampleBundle); + +console.log(`Decision: ${result.decision}`); +console.log(`Audit digest: ${result.auditDigest}`); +console.log(""); +console.log("Invoice summaries:"); +for (const summary of result.invoiceSummaries) { + console.log(`- ${summary.invoiceId}: ${summary.recommendedAction} (${summary.blockerCount} blocker, ${summary.warningCount} warning)`); +} +console.log(""); +console.log("Findings:"); +for (const finding of result.findings) { + console.log(`- [${finding.severity}] ${finding.invoiceId} ${finding.id}: ${finding.title}`); + console.log(` detail: ${finding.detail}`); + console.log(` remediation: ${finding.remediation}`); +} diff --git a/revenue-tax-exemption-controls/docs/requirement-map.md b/revenue-tax-exemption-controls/docs/requirement-map.md new file mode 100644 index 0000000..20294c2 --- /dev/null +++ b/revenue-tax-exemption-controls/docs/requirement-map.md @@ -0,0 +1,14 @@ +# Requirement Map + +| Revenue Infrastructure requirement | Implementation | +| --- | --- | +| Institutional billing | Customers include institutional tax profiles, jurisdictions, exemption certificates, and VAT/reverse-charge evidence. | +| Invoice controls | Invoices include subscription/compute line items, tax jurisdictions, tax cents, grant budget IDs, and gross amount summaries. | +| Grants and cost controls | Grant budgets enforce approved spend totals and allowed line-item categories. | +| Payment/settlement evidence | Settlement events are reconciled against invoice gross amounts before revenue can be treated as cleanly billable. | +| Compliance holds | Blockers produce `billing-hold`; warnings produce `finance-review`; clean invoices produce `billable`. | +| Auditability | Results include invoice summaries, findings, recommended actions, and a deterministic `sha256` audit digest. | + +## Demo Video + +The PR includes `docs/tax-exemption-demo.mp4`, a real terminal walkthrough running the local check, test, and demo scripts. diff --git a/revenue-tax-exemption-controls/docs/tax-exemption-demo.mp4 b/revenue-tax-exemption-controls/docs/tax-exemption-demo.mp4 new file mode 100644 index 0000000..0803a84 Binary files /dev/null and b/revenue-tax-exemption-controls/docs/tax-exemption-demo.mp4 differ diff --git a/revenue-tax-exemption-controls/package.json b/revenue-tax-exemption-controls/package.json new file mode 100644 index 0000000..cb71ff1 --- /dev/null +++ b/revenue-tax-exemption-controls/package.json @@ -0,0 +1,12 @@ +{ + "name": "revenue-tax-exemption-controls", + "version": "1.0.0", + "description": "Institutional tax exemption and grant billing compliance controls.", + "main": "src/revenue-tax-exemption-controls.js", + "scripts": { + "check": "node --check src/revenue-tax-exemption-controls.js && node --check test.js && node --check demo.js", + "test": "node test.js", + "demo": "node demo.js" + }, + "license": "MIT" +} diff --git a/revenue-tax-exemption-controls/sample-data.json b/revenue-tax-exemption-controls/sample-data.json new file mode 100644 index 0000000..02ded32 --- /dev/null +++ b/revenue-tax-exemption-controls/sample-data.json @@ -0,0 +1,97 @@ +{ + "now": "2026-05-15T00:00:00.000Z", + "customers": [ + { + "id": "cust-university-lab", + "name": "Northbridge University Lab", + "taxProfile": { + "jurisdiction": "US-CA", + "exemptionStatus": "exempt", + "reverseCharge": false, + "vatId": null, + "exemptionCertificate": { + "id": "cert-2025-ca-221", + "status": "verified", + "expiresAt": "2026-04-01T00:00:00.000Z" + } + } + }, + { + "id": "cust-eu-institute", + "name": "Helix EU Institute", + "taxProfile": { + "jurisdiction": "DE", + "exemptionStatus": "standard", + "reverseCharge": true, + "vatId": "", + "exemptionCertificate": null + } + } + ], + "grantBudgets": [ + { + "id": "grant-nih-atlas-2026", + "approvedCents": 300000, + "usedCents": 252000, + "allowedCategories": ["subscription", "storage"] + }, + { + "id": "grant-eu-knowledge-graph", + "approvedCents": 220000, + "usedCents": 80000, + "allowedCategories": ["subscription", "compute", "storage"] + } + ], + "invoices": [ + { + "id": "inv-1007", + "customerId": "cust-university-lab", + "taxJurisdiction": "US-CA", + "grantBudgetId": "grant-nih-atlas-2026", + "taxCents": 0, + "lines": [ + { + "description": "SCIBASE Enterprise workspace", + "category": "subscription", + "quantity": 1, + "unitCents": 42000 + }, + { + "description": "GPU compute overage", + "category": "compute", + "quantity": 1, + "unitCents": 12000 + } + ] + }, + { + "id": "inv-1008", + "customerId": "cust-eu-institute", + "taxJurisdiction": "DE", + "grantBudgetId": "grant-eu-knowledge-graph", + "taxCents": 0, + "lines": [ + { + "description": "Knowledge graph API seats", + "category": "subscription", + "quantity": 2, + "unitCents": 18000 + } + ] + } + ], + "settlementEvents": [ + { + "invoiceId": "inv-1007", + "status": "settled", + "amountCents": 51000, + "processor": "stripe" + }, + { + "invoiceId": "inv-1008", + "status": "settled", + "amountCents": 36000, + "processor": "stripe" + } + ] +} diff --git a/revenue-tax-exemption-controls/src/revenue-tax-exemption-controls.js b/revenue-tax-exemption-controls/src/revenue-tax-exemption-controls.js new file mode 100644 index 0000000..a32cbe1 --- /dev/null +++ b/revenue-tax-exemption-controls/src/revenue-tax-exemption-controls.js @@ -0,0 +1,260 @@ +"use strict"; + +const crypto = require("node:crypto"); + +const TAX_RATES = { + "US-CA": 0.0875, + "US-MA": 0.0625, + "GB": 0.2, + "DE": 0.19, +}; + +function stableStringify(value) { + if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`; + if (value && typeof value === "object") { + return `{${Object.keys(value) + .sort() + .map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`) + .join(",")}}`; + } + return JSON.stringify(value); +} + +function stableHash(value) { + return crypto.createHash("sha256").update(stableStringify(value)).digest("hex"); +} + +function requireFields(object, fields, label) { + const missing = fields.filter((field) => object[field] === undefined || object[field] === null); + if (missing.length > 0) throw new Error(`${label} is missing required field(s): ${missing.join(", ")}`); +} + +function parseDate(value) { + const parsed = new Date(value); + if (Number.isNaN(parsed.getTime())) throw new Error(`Invalid date: ${value}`); + return parsed; +} + +function finding(severity, id, invoiceId, title, detail, remediation) { + return { severity, id, invoiceId, title, detail, remediation }; +} + +function centsForLines(lines) { + return lines.reduce((total, line) => total + line.quantity * line.unitCents, 0); +} + +function expectedTaxCents(invoice, customer) { + if (customer.taxProfile.exemptionStatus === "exempt") return 0; + if (customer.taxProfile.reverseCharge === true) return 0; + const rate = TAX_RATES[invoice.taxJurisdiction]; + if (rate === undefined) return null; + return Math.round(centsForLines(invoice.lines) * rate); +} + +function hasCurrentExemption(customer, now) { + const certificate = customer.taxProfile.exemptionCertificate; + if (!certificate) return false; + return certificate.status === "verified" && parseDate(certificate.expiresAt) > now; +} + +function evaluateTaxTreatment(invoice, customer, now) { + const findings = []; + const expectedTax = expectedTaxCents(invoice, customer); + + if (customer.taxProfile.exemptionStatus === "exempt" && !hasCurrentExemption(customer, now)) { + findings.push(finding( + "blocker", + "exemption-certificate-expired", + invoice.id, + "Invoice claims tax exemption without current certificate", + `${customer.name} is marked exempt but the exemption certificate is missing, unverified, or expired.`, + "Put the invoice on billing hold until a current exemption certificate is verified.", + )); + } + + if (customer.taxProfile.reverseCharge === true && !customer.taxProfile.vatId) { + findings.push(finding( + "blocker", + "reverse-charge-vat-id-missing", + invoice.id, + "Reverse charge invoice lacks VAT ID evidence", + `${customer.name} uses reverse charge but has no VAT ID on file.`, + "Collect and verify the VAT ID before issuing the invoice with zero tax.", + )); + } + + if (expectedTax === null) { + findings.push(finding( + "warning", + "unknown-tax-jurisdiction", + invoice.id, + "Tax jurisdiction has no configured rate", + `${invoice.taxJurisdiction} is not present in the configured tax rate table.`, + "Route the invoice to finance review before issuance.", + )); + } else if (invoice.taxCents !== expectedTax) { + findings.push(finding( + "blocker", + "tax-amount-mismatch", + invoice.id, + "Invoice tax does not match configured treatment", + `Expected ${expectedTax} cents but invoice records ${invoice.taxCents} cents.`, + "Recalculate tax or correct exemption/reverse-charge evidence before billing.", + )); + } + + return findings; +} + +function evaluateGrantControls(invoice, grantBudgets) { + const findings = []; + const grant = grantBudgets.find((budget) => budget.id === invoice.grantBudgetId); + + if (!grant) { + findings.push(finding( + "warning", + "grant-budget-missing", + invoice.id, + "Invoice is not attached to a grant budget", + `${invoice.id} has no recognized grant budget.`, + "Attach a grant or mark the invoice as non-grant commercial revenue.", + )); + return findings; + } + + const usedCents = grant.usedCents + centsForLines(invoice.lines); + if (usedCents > grant.approvedCents) { + findings.push(finding( + "blocker", + "grant-budget-exceeded", + invoice.id, + "Invoice would exceed approved grant budget", + `${grant.id} would exceed its approved amount by ${usedCents - grant.approvedCents} cents.`, + "Hold billing until the grant budget is expanded or line items are moved to another funding source.", + )); + } + + for (const line of invoice.lines) { + if (!grant.allowedCategories.includes(line.category)) { + findings.push(finding( + "blocker", + "grant-category-disallowed", + invoice.id, + "Invoice line item is outside grant-approved categories", + `${line.description} uses category ${line.category}, which is not allowed by ${grant.id}.`, + "Remove the line item from the grant invoice or obtain written budget approval.", + )); + } + } + + return findings; +} + +function evaluateSettlement(invoice, settlementEvents) { + const findings = []; + const settled = settlementEvents.find((event) => event.invoiceId === invoice.id && event.status === "settled"); + const grossCents = centsForLines(invoice.lines) + invoice.taxCents; + + if (!settled) { + findings.push(finding( + "warning", + "settlement-event-missing", + invoice.id, + "Invoice has no settled payment event", + `${invoice.id} has no processor settlement event yet.`, + "Keep fulfillment entitlements provisional until settlement is recorded.", + )); + return findings; + } + + if (settled.amountCents !== grossCents) { + findings.push(finding( + "blocker", + "settlement-amount-mismatch", + invoice.id, + "Payment settlement does not match invoice gross amount", + `Expected settlement ${grossCents} cents but received ${settled.amountCents} cents.`, + "Reconcile processor fees, credits, refunds, or invoice amount before recognizing payment.", + )); + } + + return findings; +} + +function buildInvoiceSummary(invoice, findings) { + const invoiceFindings = findings.filter((item) => item.invoiceId === invoice.id); + const blockerCount = invoiceFindings.filter((item) => item.severity === "blocker").length; + const warningCount = invoiceFindings.filter((item) => item.severity === "warning").length; + let recommendedAction = "issue-invoice"; + if (blockerCount > 0) recommendedAction = "billing-hold"; + else if (warningCount > 0) recommendedAction = "finance-review"; + + return { + invoiceId: invoice.id, + grossCents: centsForLines(invoice.lines) + invoice.taxCents, + taxCents: invoice.taxCents, + blockerCount, + warningCount, + recommendedAction, + }; +} + +function decide(findings) { + if (findings.some((item) => item.severity === "blocker")) return "billing-hold"; + if (findings.some((item) => item.severity === "warning")) return "finance-review"; + return "billable"; +} + +function assertBundle(bundle) { + requireFields(bundle, ["customers", "invoices", "grantBudgets", "settlementEvents"], "revenue controls bundle"); +} + +function analyzeRevenueTaxControls(bundle, options = {}) { + assertBundle(bundle); + const now = parseDate(options.now || bundle.now || new Date().toISOString()); + const findings = []; + + for (const invoice of bundle.invoices) { + requireFields(invoice, ["id", "customerId", "taxJurisdiction", "taxCents", "lines"], `invoice ${invoice.id || "(unknown)"}`); + const customer = bundle.customers.find((item) => item.id === invoice.customerId); + if (!customer) { + findings.push(finding( + "blocker", + "invoice-customer-missing", + invoice.id, + "Invoice customer is missing", + `${invoice.id} references unknown customer ${invoice.customerId}.`, + "Attach a valid customer record before billing.", + )); + continue; + } + requireFields(customer, ["id", "name", "taxProfile"], `customer ${customer.id}`); + findings.push(...evaluateTaxTreatment(invoice, customer, now)); + findings.push(...evaluateGrantControls(invoice, bundle.grantBudgets)); + findings.push(...evaluateSettlement(invoice, bundle.settlementEvents)); + } + + const invoiceSummaries = bundle.invoices.map((invoice) => buildInvoiceSummary(invoice, findings)); + const decision = decide(findings); + const auditDigest = stableHash({ + decision, + invoiceSummaries, + findings, + evaluatedAt: now.toISOString(), + }); + + return { + evaluatedAt: now.toISOString(), + decision, + findings, + invoiceSummaries, + auditDigest: `sha256:${auditDigest}`, + }; +} + +module.exports = { + TAX_RATES, + analyzeRevenueTaxControls, + stableHash, + stableStringify, +}; diff --git a/revenue-tax-exemption-controls/test.js b/revenue-tax-exemption-controls/test.js new file mode 100644 index 0000000..64d7668 --- /dev/null +++ b/revenue-tax-exemption-controls/test.js @@ -0,0 +1,44 @@ +"use strict"; + +const assert = require("node:assert/strict"); +const sampleBundle = require("./sample-data.json"); +const { + analyzeRevenueTaxControls, + stableHash, +} = require("./src/revenue-tax-exemption-controls"); + +function clone(value) { + return JSON.parse(JSON.stringify(value)); +} + +function ids(result) { + return new Set(result.findings.map((finding) => finding.id)); +} + +const held = analyzeRevenueTaxControls(sampleBundle); +const heldIds = ids(held); + +assert.equal(held.decision, "billing-hold"); +assert.match(held.auditDigest, /^sha256:[a-f0-9]{64}$/); +assert(heldIds.has("exemption-certificate-expired")); +assert(heldIds.has("grant-budget-exceeded")); +assert(heldIds.has("grant-category-disallowed")); +assert(heldIds.has("settlement-amount-mismatch")); +assert(heldIds.has("reverse-charge-vat-id-missing")); +assert.equal(held.invoiceSummaries.find((item) => item.invoiceId === "inv-1007").recommendedAction, "billing-hold"); + +const billableBundle = clone(sampleBundle); +billableBundle.customers[0].taxProfile.exemptionCertificate.expiresAt = "2026-12-31T00:00:00.000Z"; +billableBundle.customers[1].taxProfile.vatId = "DE123456789"; +billableBundle.grantBudgets[0].approvedCents = 330000; +billableBundle.grantBudgets[0].allowedCategories.push("compute"); +billableBundle.settlementEvents[0].amountCents = 54000; + +const billable = analyzeRevenueTaxControls(billableBundle); +assert.equal(billable.decision, "billable"); +assert.equal(billable.findings.length, 0); +assert.equal(billable.invoiceSummaries.every((item) => item.recommendedAction === "issue-invoice"), true); +assert.notEqual(held.auditDigest, billable.auditDigest); +assert.equal(stableHash({ b: 2, a: 1 }), stableHash({ a: 1, b: 2 })); + +console.log("revenue tax exemption control tests passed");