DEV Community

Cover image for Stripe 2025-03-31.basil Migration, Non-Destructive Visa CE 3.0 Staging & EU VIES Circuit-Breaker (Open-Source MCP)
RevClamp Enterprise
RevClamp Enterprise

Posted on Originally published at revclamp.com

Stripe 2025-03-31.basil Migration, Non-Destructive Visa CE 3.0 Staging & EU VIES Circuit-Breaker (Open-Source MCP)

Modern B2B SaaS and high-volume commerce stacks rarely lose revenue to a single catastrophic outage. Instead, revenue leaks through silent schema shifts, third-party SOAP/REST edge cases, and irreversible API mutations:

  1. Stripe API 2025-03-31.basil Item-Level Period Migration: Top-level subscription.current_period_start and subscription.current_period_end were removed in favor of item-level items.data[i].current_period_start / current_period_end. Webhook consumers that still read top-level fields silently compute NaN proration windows or skip dunning recovery.
  2. Irreversible Visa CE 3.0 Dispute Submissions: Calling stripe.disputes.update(disputeId, { evidence, submit: true }) without pre-validating two qualified historical charges (120–365 days prior, matching ip_address, device_fingerprint, or billing_address) and checking Stripe's 18,000 UTF-16 code-unit ceiling permanently locks the dispute and forfeits the $15–$100 dispute fee.
  3. EU/XI VIES HTTP 200 OK Fault Wrappers: The European Commission VIES SOAP endpoint frequently returns HTTP 200 OK while embedding MS_UNAVAILABLE or GLOBAL_MAX_CONCURRENT_REQ inside the XML envelope—causing naive checkout flows to wrongly strip B2B reverse-charge exemptions or drop enterprise carts.
  4. Shopify Plus B2B Net-Terms Float Drift: Splitting B2B wholesale invoices across 30/40/30 milestones or Net-30/60/90 schedules using IEEE-754 floating-point math produces 1–2 cent reconciliation mismatches that block ERP auto-reconciliation.

Below is the deterministic architecture we built at RevClamp Enterprise—and open-sourced as an MCP server (revclamp-mcp on npm / GitHub revclamp/revclamp-mcp) so any AI agent or CI/CD pipeline can run these exact audits with zero credentials.


1. Stripe 2025-03-31.basil Item-Level Window Normalization & Non-Destructive Visa CE 3.0 Staging

Stripe 2025-03-31.basil & Non-Destructive Visa CE 3.0 Flowchart

Resolving Mixed-Interval Subscription Items in 2025-03-31.basil

When a customer has a base annual seat plan plus a monthly metered overage item, subscription.items.data contains multiple billing intervals. Rather than assuming index [0], normalize the effective billing window deterministically across all active items:

export interface NormalizedPeriodWindow {
  earliestStart: number;
  latestEnd: number;
  hasMixedIntervals: boolean;
  schemaSource: "basil_item_level" | "legacy_top_level";
}

export function resolveSubscriptionPeriodWindow(sub: Record<string, any>): NormalizedPeriodWindow {
  const items: Array<Record<string, any>> = Array.isArray(sub?.items?.data) ? sub.items.data : [];
  const itemStarts = items
    .map((item) => Number(item.current_period_start))
    .filter((v) => Number.isFinite(v) && v > 0);
  const itemEnds = items
    .map((item) => Number(item.current_period_end))
    .filter((v) => Number.isFinite(v) && v > 0);

  if (itemStarts.length > 0 && itemEnds.length > 0) {
    const intervals = new Set(items.map((i) => i?.price?.recurring?.interval).filter(Boolean));
    return {
      earliestStart: Math.min(...itemStarts),
      latestEnd: Math.max(...itemEnds),
      hasMixedIntervals: intervals.size > 1,
      schemaSource: "basil_item_level",
    };
  }

  return {
    earliestStart: Number(sub.current_period_start ?? 0),
    latestEnd: Number(sub.current_period_end ?? 0),
    hasMixedIntervals: false,
    schemaSource: "legacy_top_level",
  };
}
Enter fullscreen mode Exit fullscreen mode

Non-Destructive Visa CE 3.0 Evidence Staging (submit: false)

Visa Compelling Evidence 3.0 (reason 10.4 / Stripe fraudulent) shifts liability back to the issuer when you prove at least 2 undisputed prior transactions settled 120 to 365 days before the disputed charge share at least two fingerprint signals (ip_address, device_fingerprint, shipping_address, or billing_address).

Crucially:

  • Never set submit: true automatically in an unreviewed webhook handler. Always stage via submit: false so finance teams can inspect the draft in the Stripe Dashboard before final lock.
  • Measure payload length using UTF-16 code units (str.length in JS) rather than ASCII character assumptions—emoji or CJK characters in customer communication logs consume 2 UTF-16 code units per astral symbol and can trigger silent truncation at the 18,000 UTF-16 code-unit limit.

Interactive browser diagnostic tools (100% client-side / zero signup):


2. EU/XI VIES VAT HTTP 200 OK Fault Wrapper Circuit-Breaker

EU/XI VIES HTTP 200 OK Fault Wrapper Circuit-Breaker

A common B2B checkout bug is checking if (res.status === 200) on the EU VIES SOAP endpoint and immediately trusting <valid>false</valid>. When a national Member State database (such as Germany DE or France FR) is undergoing maintenance or rate-limiting, VIES returns HTTP 200 OK with a SOAP fault code inside the payload (MS_UNAVAILABLE, GLOBAL_MAX_CONCURRENT_REQ, SERVICE_UNAVAILABLE, or TIMEOUT).

Additionally, Northern Ireland B2B merchants operate under the Windsor Framework and must be routed with the XI prefix rather than GB.

const RETRIABLE_VIES_FAULTS = new Set([
  "MS_UNAVAILABLE",
  "GLOBAL_MAX_CONCURRENT_REQ",
  "MS_MAX_CONCURRENT_REQ",
  "SERVICE_UNAVAILABLE",
  "SERVER_BUSY",
  "TIMEOUT",
]);

export function classifyViesResponse(xmlBody: string): {
  status: "VALID" | "INVALID" | "DEGRADED_QUEUE_RETRY";
  faultCode: string | null;
} {
  const faultMatch = xmlBody.match(/<faultstring>([A-Z_]+)<\/faultstring>/i);
  if (faultMatch) {
    const code = faultMatch[1].toUpperCase();
    if (RETRIABLE_VIES_FAULTS.has(code)) {
      return { status: "DEGRADED_QUEUE_RETRY", faultCode: code };
    }
    return { status: "INVALID", faultCode: code };
  }
  const isValid = /<valid>true<\/valid>/i.test(xmlBody);
  return { status: isValid ? "VALID" : "INVALID", faultCode: null };
}
Enter fullscreen mode Exit fullscreen mode

Try it live against edge cases (DE, FR, IE, NL, and Northern Ireland XI):


3. Deterministic Integer-Cent Allocation for Shopify Plus B2B Net-Terms

Shopify Plus B2B Integer-Cent Net-Terms Schedule

When splitting a $10,000.00 (1,000,000 cents) wholesale order across three equal milestones (33.33% / 33.33% / 33.34%) or applying an early-payment discount (2/10 Net 30), floating-point rounding (Math.round(total * weight)) can cause the sum of installments to drift by ±1 cent from the invoice total.

Using the Largest Remainder Method strictly in integer cents guarantees that the sum of all scheduled installments equals the exact invoice total down to the cent:

export function allocateInstallmentsCents(totalCents: number, weights: number[]): number[] {
  const weightSum = weights.reduce((a, b) => a + b, 0);
  const rawQuotas = weights.map((w) => (totalCents * w) / weightSum);
  const floored = rawQuotas.map((q) => Math.floor(q));
  let remainder = totalCents - floored.reduce((a, b) => a + b, 0);

  const indicesByFraction = rawQuotas
    .map((q, idx) => ({ idx, frac: q - Math.floor(q) }))
    .sort((a, b) => b.frac - a.frac || a.idx - b.idx);

  for (let i = 0; i < remainder; i++) {
    floored[indicesByFraction[i].idx] += 1;
  }
  return floored;
}
Enter fullscreen mode Exit fullscreen mode

Interactive calculator:


4. Run All 6 Deterministic Tools Directly in Claude, Cursor, or Windsurf via MCP

We packaged all six deterministic billing and compliance engines into revclamp-mcp (v1.20.7, MIT License), supporting both local stdio execution and zero-auth remote Streamable HTTP / JSON-RPC 2.0.

Quickstart via npx (Local Stdio)

npx -y revclamp-mcp@1.20.7
Enter fullscreen mode Exit fullscreen mode

Zero-Install Remote MCP Configuration (claude_desktop_config.json / .cursor/mcp.json)

{
  "mcpServers": {
    "revclamp": {
      "url": "https://api.revclamp.com/api/mcp"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Included Tools (tools/list)

Tool Name Purpose
revclamp_audit_stripe_basil_payload Audits Stripe 2025-03-31.basil payloads for item-level period migration & mixed-interval drift
revclamp_check_visa_ce3_eligibility Evaluates Visa CE 3.0 120–365d historical match rules & UTF-16 code-unit limits for non-destructive staging (submit: false)
revclamp_validate_eu_vies_vat Validates EU27 + Northern Ireland (XI) VAT IDs and classifies SOAP HTTP 200 OK fault wrappers
revclamp_reconcile_b2b_net_terms Computes zero-drift integer-cent B2B Net-30/60/90 installment schedules & 2/10 Net 30 discounts
revclamp_calculate_chargeback_roi Benchmarks flat-rate non-destructive CE 3.0 staging vs. 20–25% contingency chargeback vendors
revclamp_audit_revenue_leakage Runs a multi-pillar B2B revenue leakage diagnostic across Stripe, VIES VAT, and Shopify B2B

Top comments (0)