From 6cd982aa90b11832a4cd08bbcf3b9417e11aa4a0 Mon Sep 17 00:00:00 2001 From: Davifek <178534466+Davifek@users.noreply.github.com> Date: Mon, 18 May 2026 20:49:06 +0200 Subject: [PATCH] feat: add pricing experiment guard --- pricing-experiment-guard/README.md | 38 +++ pricing-experiment-guard/demo.gif | Bin 0 -> 54710 bytes pricing-experiment-guard/demo.js | 56 +++++ pricing-experiment-guard/index.js | 253 ++++++++++++++++++++ pricing-experiment-guard/requirement-map.md | 30 +++ pricing-experiment-guard/test.js | 119 +++++++++ 6 files changed, 496 insertions(+) create mode 100644 pricing-experiment-guard/README.md create mode 100644 pricing-experiment-guard/demo.gif create mode 100644 pricing-experiment-guard/demo.js create mode 100644 pricing-experiment-guard/index.js create mode 100644 pricing-experiment-guard/requirement-map.md create mode 100644 pricing-experiment-guard/test.js diff --git a/pricing-experiment-guard/README.md b/pricing-experiment-guard/README.md new file mode 100644 index 0000000..42528be --- /dev/null +++ b/pricing-experiment-guard/README.md @@ -0,0 +1,38 @@ +# Pricing Experiment Guard + +This self-contained revenue infrastructure module checks whether pricing and packaging experiments are safe to launch. It is designed for finance, growth, and product teams that need audit-ready controls before changing SaaS prices, entitlements, or AI-compute bundles. + +## What It Checks + +- A measurable hypothesis and unchanged control cohort +- Gross-margin headroom against a finance-approved floor +- Entitlement removals without grandfathering +- Variant exposure limits and rollback readiness +- Invoice copy review, customer notice windows, and tax review +- Finance/legal approvals and revenue-recognition notes + +## Run It + +```bash +node pricing-experiment-guard/test.js +node pricing-experiment-guard/demo.js +``` + +The module uses only Node.js standard library APIs. + +## Public API + +```js +const { evaluatePricingExperiment } = require("./index.js"); + +const result = evaluatePricingExperiment(experiment); +console.log(result.summary.launchDecision); +console.log(result.findings); +console.log(result.financePacket.requiredActions); +``` + +The guard returns a launch decision of `approve`, `needs-remediation`, or `block`, plus finance-owner remediation steps and audit questions. + +## Demo + +The included `demo.gif` shows a risky enterprise AI-compute price lift being blocked because it lacks a hypothesis/control, breaches margin floors, removes entitlements, exceeds rollout limits, and has incomplete billing/audit controls. diff --git a/pricing-experiment-guard/demo.gif b/pricing-experiment-guard/demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..d11a649e113bb78728ee72daa1933a8a6b478451 GIT binary patch literal 54710 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 Uhx#V81?$BH9@?JRV8Ac=FDy7o$N&HU literal 0 HcmV?d00001 diff --git a/pricing-experiment-guard/demo.js b/pricing-experiment-guard/demo.js new file mode 100644 index 0000000..bbdbb62 --- /dev/null +++ b/pricing-experiment-guard/demo.js @@ -0,0 +1,56 @@ +const { evaluatePricingExperiment } = require("./index.js"); + +const experiment = { + title: "Enterprise AI Compute Price Lift", + hypothesis: "", + cohorts: [ + { + name: "new-pricing", + exposurePercent: 42, + priceMultiplier: 1.35, + entitlementsRemoved: ["priority-support", "included-compute-pack"], + grandfathering: false + } + ], + economics: { + grossMarginFloorPercent: 55, + projectedGrossMarginPercent: 41 + }, + rollout: { + maxExposurePercent: 25, + rollbackMetric: "", + rollbackThreshold: null, + owner: "revenue-ops" + }, + billing: { + invoiceCopyReviewed: false, + customerNoticeDays: 3, + taxTreatmentReviewed: false + }, + audit: { + approvalRecords: [], + revenueRecognitionNotes: "" + } +}; + +const result = evaluatePricingExperiment(experiment); + +console.log(`Pricing experiment guard: ${result.summary.experimentTitle}`); +console.log(`Decision: ${result.summary.launchDecision}`); +console.log(`Finance readiness: ${result.summary.financeReadiness}`); +console.log(`Findings: ${result.summary.findingCount}`); +console.log(""); + +for (const finding of result.findings) { + console.log(`[${finding.severity.toUpperCase()}] ${finding.title}`); + for (const evidence of finding.evidence) { + console.log(` - ${evidence}`); + } + console.log(` Remediation: ${finding.remediation}`); + console.log(""); +} + +console.log("Finance actions:"); +for (const action of result.financePacket.requiredActions) { + console.log(`- ${action}`); +} diff --git a/pricing-experiment-guard/index.js b/pricing-experiment-guard/index.js new file mode 100644 index 0000000..e45635f --- /dev/null +++ b/pricing-experiment-guard/index.js @@ -0,0 +1,253 @@ +const crypto = require("node:crypto"); + +function evaluatePricingExperiment(experiment) { + const normalized = normalizeExperiment(experiment); + const findings = [ + ...findMissingHypothesisOrControl(normalized), + ...findMarginFloorBreach(normalized), + ...findEntitlementRegressions(normalized), + ...findRollbackGaps(normalized), + ...findBillingNoticeGaps(normalized), + ...findAuditGaps(normalized) + ]; + + const severityCounts = countSeverities(findings); + const summary = { + experimentTitle: normalized.title, + findingCount: findings.length, + severityCounts, + launchDecision: decideLaunch(severityCounts), + financeReadiness: scoreFinanceReadiness(findings) + }; + + return { + summary, + findings, + financePacket: buildFinancePacket(summary, findings) + }; +} + +function normalizeExperiment(experiment) { + if (!experiment || typeof experiment !== "object") { + throw new TypeError("evaluatePricingExperiment expects an experiment object"); + } + + return { + title: experiment.title || "Untitled pricing experiment", + hypothesis: experiment.hypothesis || "", + cohorts: Array.isArray(experiment.cohorts) ? experiment.cohorts : [], + economics: experiment.economics || {}, + rollout: experiment.rollout || {}, + billing: experiment.billing || {}, + audit: experiment.audit || {} + }; +} + +function findMissingHypothesisOrControl(experiment) { + const evidence = []; + if (!experiment.hypothesis.trim()) evidence.push("experiment hypothesis is missing"); + if (!experiment.cohorts.some((cohort) => Number(cohort.priceMultiplier) === 1)) { + evidence.push("control cohort with unchanged pricing is missing"); + } + + if (evidence.length === 0) return []; + + return [ + finding({ + type: "missing_hypothesis_or_control", + severity: "critical", + title: "Pricing experiment lacks a measurable hypothesis or control cohort", + evidence, + remediation: + "Define the business hypothesis and add a control cohort before exposing customers to changed prices." + }) + ]; +} + +function findMarginFloorBreach(experiment) { + const floor = Number(experiment.economics.grossMarginFloorPercent); + const projected = Number(experiment.economics.projectedGrossMarginPercent); + + if (!Number.isFinite(floor) || !Number.isFinite(projected) || projected >= floor) { + return []; + } + + return [ + finding({ + type: "margin_floor_breach", + severity: "high", + title: "Projected gross margin falls below the approved floor", + evidence: [`projected margin ${projected}% is below the ${floor}% floor`], + remediation: + "Reprice the cohort, reduce compute cost, or lower exposure until projected gross margin clears the finance floor." + }) + ]; +} + +function findEntitlementRegressions(experiment) { + const regressions = []; + + for (const cohort of experiment.cohorts) { + const removed = Array.isArray(cohort.entitlementsRemoved) ? cohort.entitlementsRemoved : []; + if (removed.length > 0 && !cohort.grandfathering) { + regressions.push( + `${cohort.name || "unnamed cohort"} removes ${removed.join(", ")} without grandfathering` + ); + } + } + + if (regressions.length === 0) return []; + + return [ + finding({ + type: "entitlement_regression", + severity: "high", + title: "Pricing change removes customer entitlements without protection", + evidence: regressions, + remediation: + "Grandfather existing customers, add customer-facing entitlement notices, or remove entitlement regressions from the experiment." + }) + ]; +} + +function findRollbackGaps(experiment) { + const evidence = []; + const maxExposure = Number(experiment.rollout.maxExposurePercent); + + for (const cohort of experiment.cohorts) { + const exposure = Number(cohort.exposurePercent); + const changesPrice = Number(cohort.priceMultiplier) !== 1; + if (changesPrice && Number.isFinite(exposure) && Number.isFinite(maxExposure) && exposure > maxExposure) { + evidence.push( + `${cohort.name || "unnamed cohort"} exposure ${exposure}% exceeds max ${maxExposure}%` + ); + } + } + + if (!experiment.rollout.rollbackMetric) evidence.push("rollback metric is missing"); + if (!experiment.rollout.rollbackThreshold) evidence.push("rollback threshold is missing"); + if (!experiment.rollout.owner) evidence.push("rollout owner is missing"); + + if (evidence.length === 0) return []; + + return [ + finding({ + type: "rollback_gap", + severity: "medium", + title: "Rollout controls are not ready for a pricing experiment", + evidence, + remediation: + "Set cohort exposure limits, rollback metrics, rollback thresholds, and a named owner before launch." + }) + ]; +} + +function findBillingNoticeGaps(experiment) { + const evidence = []; + const noticeDays = Number(experiment.billing.customerNoticeDays); + + if (!experiment.billing.invoiceCopyReviewed) evidence.push("invoice copy has not been reviewed"); + if (!Number.isFinite(noticeDays) || noticeDays < 14) { + evidence.push(`customer notice window is ${Number.isFinite(noticeDays) ? noticeDays : "missing"} days`); + } + if (!experiment.billing.taxTreatmentReviewed) evidence.push("tax treatment review is missing"); + + if (evidence.length === 0) return []; + + return [ + finding({ + type: "billing_notice_gap", + severity: "medium", + title: "Billing and customer notice controls are incomplete", + evidence, + remediation: + "Review invoice copy, confirm tax treatment, and provide an adequate customer notice window before billing changes go live." + }) + ]; +} + +function findAuditGaps(experiment) { + const evidence = []; + const approvals = Array.isArray(experiment.audit.approvalRecords) + ? experiment.audit.approvalRecords + : []; + + if (approvals.length === 0) evidence.push("finance/legal approval records are missing"); + if (!experiment.audit.revenueRecognitionNotes) { + evidence.push("revenue recognition notes are missing"); + } + + if (evidence.length === 0) return []; + + return [ + finding({ + type: "audit_packet_gap", + severity: "medium", + title: "Finance audit packet is incomplete", + evidence, + remediation: + "Attach finance/legal approvals and revenue-recognition notes before the experiment is approved." + }) + ]; +} + +function buildFinancePacket(summary, findings) { + if (findings.length === 0) { + return { + requiredActions: ["Proceed with monitored launch."], + ownerQuestions: [ + "Are finance and support teams ready to watch refund, churn, and gross-margin triggers?" + ], + auditSummary: `${summary.experimentTitle} is ready for monitored launch.` + }; + } + + return { + requiredActions: findings.map((finding) => finding.remediation), + ownerQuestions: [ + "Is there a control cohort and a measurable revenue hypothesis?", + "Can finance confirm the projected margin stays above the approved floor?", + "Can billing roll back invoices and entitlements without customer harm?" + ], + auditSummary: `${summary.experimentTitle} needs ${findings.length} remediation action(s) before launch.` + }; +} + +function finding(input) { + return { + id: `${input.type}-${hash(input.evidence.join("|")).slice(0, 8)}`, + type: input.type, + severity: input.severity, + title: input.title, + evidence: input.evidence, + remediation: input.remediation + }; +} + +function countSeverities(findings) { + const counts = { critical: 0, high: 0, medium: 0 }; + for (const finding of findings) counts[finding.severity] += 1; + return counts; +} + +function decideLaunch(counts) { + if (counts.critical > 0 || counts.high > 0) return "block"; + if (counts.medium > 0) return "needs-remediation"; + return "approve"; +} + +function scoreFinanceReadiness(findings) { + if (findings.some((finding) => finding.severity === "critical" || finding.severity === "high")) { + return "low"; + } + if (findings.length > 0) return "medium"; + return "high"; +} + +function hash(value) { + return crypto.createHash("sha256").update(String(value)).digest("hex"); +} + +module.exports = { + evaluatePricingExperiment +}; diff --git a/pricing-experiment-guard/requirement-map.md b/pricing-experiment-guard/requirement-map.md new file mode 100644 index 0000000..4b13258 --- /dev/null +++ b/pricing-experiment-guard/requirement-map.md @@ -0,0 +1,30 @@ +# Requirement Map + +Issue: SCIBASE-AI/SCIBASE.AI#20, Revenue Infrastructure. + +## Tiered Subscription Billing + +- Validates pricing changes against unchanged control cohorts. +- Detects entitlement removals without grandfathering so plan changes do not silently break customer expectations. +- Checks invoice copy and customer notice readiness before billing changes go live. + +## AI Compute Billing + +- Enforces projected gross-margin floors for compute-heavy plan changes. +- Supports safe AI-compute bundle experiments through exposure limits and rollback triggers. + +## Licensing APIs And Analytics + +- Produces an audit packet that finance and analytics teams can attach to pricing-experiment reviews. +- Captures owner questions for margin, billing, and rollback readiness before revenue experiments affect customers. + +## Safety And Scope + +- Uses synthetic sample data only. +- Requires no payment provider, external service, credential, or network access. +- Keeps the implementation isolated under `pricing-experiment-guard/`. + +## Verification + +- `node pricing-experiment-guard/test.js` +- `node pricing-experiment-guard/demo.js` diff --git a/pricing-experiment-guard/test.js b/pricing-experiment-guard/test.js new file mode 100644 index 0000000..d70bc54 --- /dev/null +++ b/pricing-experiment-guard/test.js @@ -0,0 +1,119 @@ +const assert = require("node:assert/strict"); +const { evaluatePricingExperiment } = require("./index.js"); + +function test(name, fn) { + try { + fn(); + console.log(`ok - ${name}`); + } catch (error) { + console.error(`not ok - ${name}`); + throw error; + } +} + +const riskyExperiment = { + title: "Enterprise AI Compute Price Lift", + hypothesis: "", + cohorts: [ + { + name: "new-pricing", + exposurePercent: 42, + priceMultiplier: 1.35, + entitlementsRemoved: ["priority-support", "included-compute-pack"], + grandfathering: false + } + ], + economics: { + grossMarginFloorPercent: 55, + projectedGrossMarginPercent: 41 + }, + rollout: { + maxExposurePercent: 25, + rollbackMetric: "", + rollbackThreshold: null, + owner: "revenue-ops" + }, + billing: { + invoiceCopyReviewed: false, + customerNoticeDays: 3, + taxTreatmentReviewed: false + }, + audit: { + approvalRecords: [], + revenueRecognitionNotes: "" + } +}; + +const safeExperiment = { + title: "Pro Annual Discount Copy Test", + hypothesis: "Annual discount positioning improves conversion without lowering margin.", + cohorts: [ + { + name: "control", + exposurePercent: 50, + priceMultiplier: 1, + entitlementsRemoved: [], + grandfathering: true + }, + { + name: "variant", + exposurePercent: 10, + priceMultiplier: 0.95, + entitlementsRemoved: [], + grandfathering: true + } + ], + economics: { + grossMarginFloorPercent: 60, + projectedGrossMarginPercent: 74 + }, + rollout: { + maxExposurePercent: 20, + rollbackMetric: "gross margin below 60% or refund requests above 2%", + rollbackThreshold: "2 consecutive days", + owner: "growth-finance" + }, + billing: { + invoiceCopyReviewed: true, + customerNoticeDays: 30, + taxTreatmentReviewed: true + }, + audit: { + approvalRecords: ["finance-approval-2026-05-18", "legal-review-2026-05-18"], + revenueRecognitionNotes: "Discount is applied prospectively and deferred revenue remains unchanged." + } +}; + +test("blocks risky pricing experiments with missing controls, margin breach, entitlement regressions, and weak rollback", () => { + const result = evaluatePricingExperiment(riskyExperiment); + const types = result.findings.map((finding) => finding.type); + + assert.equal(result.summary.launchDecision, "block"); + assert.ok(types.includes("missing_hypothesis_or_control")); + assert.ok(types.includes("margin_floor_breach")); + assert.ok(types.includes("entitlement_regression")); + assert.ok(types.includes("rollback_gap")); + assert.ok(types.includes("billing_notice_gap")); + assert.ok(result.financePacket.requiredActions.some((action) => action.includes("control cohort"))); +}); + +test("approves a bounded experiment with controls, margin headroom, notice, and audit evidence", () => { + const result = evaluatePricingExperiment(safeExperiment); + + assert.equal(result.summary.launchDecision, "approve"); + assert.equal(result.summary.findingCount, 0); + assert.equal(result.summary.financeReadiness, "high"); + assert.deepEqual(result.findings, []); + assert.ok(result.financePacket.requiredActions.includes("Proceed with monitored launch.")); +}); + +test("emits audit-ready findings with owner-facing remediation", () => { + const result = evaluatePricingExperiment(riskyExperiment); + + for (const finding of result.findings) { + assert.ok(finding.id); + assert.ok(["critical", "high", "medium"].includes(finding.severity)); + assert.ok(finding.evidence.length > 0); + assert.ok(finding.remediation.length > 10); + } +});