Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions committed-revenue-drawdown-guard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Committed Revenue Drawdown Guard

This module adds a self-contained finance control slice for SCIBASE revenue infrastructure. It evaluates institutional minimum commitments across subscription seats, AI compute, and analytics licensing so finance and customer teams can see whether contracted revenue is being consumed, at risk, or ready for a paid amendment.

The implementation is dependency-free and uses synthetic customer data only. It does not connect to Stripe, PayPal, bank rails, wallets, billing providers, live customer records, or external APIs.

## What It Checks

- Contracted annual minimums by revenue stream
- Actual consumption against the time-elapsed expectation
- Projected final consumption and overage risk
- Under-consumption that could threaten renewal or recognition confidence
- Expiring prepaid credits without a drawdown plan
- AI compute usage below the configured gross-margin floor
- Recommended actions for finance, customer success, account executives, and finance ops
- Deterministic audit digests for reviewer and month-end evidence packets

## Usage

Run the assertion tests:

```bash
node committed-revenue-drawdown-guard/test.js
```

Run the demo:

```bash
node committed-revenue-drawdown-guard/demo.js
```

The demo writes:

- `reports/demo-output.json` with the full portfolio evaluation
- `reports/demo.svg` with a visual portfolio summary
- `reports/demo.gif` as a short visual walkthrough artifact
- `reports/demo.mp4` as the H.264 short demo video for bounty review

## Files

- `index.js`: revenue drawdown, amendment, credit-expiration, margin, and audit logic
- `sample-data.js`: synthetic institutional contracts and usage
- `test.js`: dependency-free regression assertions
- `demo.js`: CLI demo plus JSON and SVG report generation
- `requirements-map.md`: mapping from issue requirements to implementation evidence

## Scope Differentiation

This is not another generic billing ledger, usage meter, tax guard, dispute packet, SLA credit calculator, royalty settlement module, recognition close, or revenue forecast. It focuses on the contract drawdown boundary: whether prepaid or committed institutional revenue is actually being consumed in the right stream at the right pace, and whether the customer needs a drawdown plan, a paid amendment, or an expansion motion before the next finance checkpoint.
88 changes: 88 additions & 0 deletions committed-revenue-drawdown-guard/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"use strict";

const fs = require("fs");
const path = require("path");
const sampleContracts = require("./sample-data");
const { evaluatePortfolio, formatUsd } = require("./index");

const report = evaluatePortfolio(sampleContracts, { asOf: "2026-05-20" });
const reportsDir = path.join(__dirname, "reports");
fs.mkdirSync(reportsDir, { recursive: true });
fs.writeFileSync(path.join(reportsDir, "demo-output.json"), `${JSON.stringify(report, null, 2)}\n`);

function statusColor(status) {
if (status === "amendment-review-needed") return "#b42318";
if (status === "monitor") return "#b54708";
return "#027a48";
}

function bar(width, value, max) {
return Math.max(8, Math.round((value / max) * width));
}

const maxCommitted = Math.max(...report.contracts.map((contract) => contract.totals.committed));
const rows = report.contracts
.map((contract, index) => {
const y = 170 + index * 112;
const consumedWidth = bar(420, contract.totals.consumed, maxCommitted);
const projectedWidth = bar(420, contract.totals.projectedFinal, maxCommitted);
const color = statusColor(contract.status);
const topAction = contract.actions[0]?.action || "No action needed.";
return `
<g transform="translate(44 ${y})">
<text x="0" y="0" class="customer">${contract.customer}</text>
<text x="0" y="24" class="muted">${contract.recommendation} - score ${contract.revenueCertaintyScore}</text>
<rect x="0" y="42" width="420" height="16" rx="8" fill="#e4e7ec" />
<rect x="0" y="42" width="${projectedWidth}" height="16" rx="8" fill="#d0d5dd" />
<rect x="0" y="42" width="${consumedWidth}" height="16" rx="8" fill="${color}" />
<text x="440" y="55" class="metric">${formatUsd(contract.totals.consumed)} used / ${formatUsd(
contract.totals.committed,
)} committed</text>
<text x="0" y="84" class="action">${topAction}</text>
</g>`;
})
.join("\n");

const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="720" viewBox="0 0 1280 720" role="img" aria-labelledby="title desc">
<title id="title">Committed revenue drawdown guard demo</title>
<desc id="desc">Portfolio status for institutional minimum commitments across subscription, compute, and analytics revenue.</desc>
<style>
.bg { fill: #f8fafc; }
.panel { fill: #ffffff; stroke: #d0d5dd; stroke-width: 1; }
.title { font: 700 34px Arial, sans-serif; fill: #101828; }
.subtitle { font: 400 17px Arial, sans-serif; fill: #475467; }
.label { font: 700 13px Arial, sans-serif; fill: #475467; text-transform: uppercase; }
.number { font: 700 28px Arial, sans-serif; fill: #101828; }
.customer { font: 700 20px Arial, sans-serif; fill: #101828; }
.metric { font: 700 15px Arial, sans-serif; fill: #344054; }
.muted { font: 400 14px Arial, sans-serif; fill: #667085; }
.action { font: 400 15px Arial, sans-serif; fill: #344054; }
</style>
<rect class="bg" width="1280" height="720" />
<rect class="panel" x="24" y="24" width="1232" height="672" rx="10" />
<text x="44" y="72" class="title">Committed Revenue Drawdown Guard</text>
<text x="44" y="104" class="subtitle">Institutional contract consumption, overage, credit-expiration, and amendment readiness as of ${report.asOf}</text>
<g transform="translate(44 132)">
<text class="label" x="0" y="0">Committed</text>
<text class="number" x="0" y="34">${formatUsd(report.portfolio.committed)}</text>
<text class="label" x="250" y="0">Consumed</text>
<text class="number" x="250" y="34">${formatUsd(report.portfolio.consumed)}</text>
<text class="label" x="500" y="0">At risk</text>
<text class="number" x="500" y="34">${formatUsd(report.portfolio.atRisk)}</text>
<text class="label" x="750" y="0">Expansion upside</text>
<text class="number" x="750" y="34">${formatUsd(report.portfolio.expansionUpside)}</text>
</g>
${rows}
<text x="44" y="666" class="muted">Audit digest: ${report.auditDigest}</text>
</svg>
`;

fs.writeFileSync(path.join(reportsDir, "demo.svg"), svg);

console.log(`Contracts evaluated: ${report.portfolio.contractCount}`);
console.log(`Committed: ${formatUsd(report.portfolio.committed)}`);
console.log(`Consumed: ${formatUsd(report.portfolio.consumed)}`);
console.log(`At risk: ${formatUsd(report.portfolio.atRisk)}`);
console.log(`Expansion upside: ${formatUsd(report.portfolio.expansionUpside)}`);
console.log(`Top action: ${report.contracts[0].actions[0].action}`);
console.log(`Digest: ${report.auditDigest}`);
Loading