Chapter 3 · Track 2 · Technical

Data Dictionary, API Surface & BigInt Validation

Verified: prisma/schema.prisma, docs/technical/api-documentation.md, app/utils/financialIntegrityLedgerCsv.ts

1. Five-step Pre-Change Protocol

  1. Read TASdocs/TAS.md constitutional anchors
  2. Validate Invariants — BigInt cents, physical-unit gates, verbatim UI labels
  3. Cite Impact — blast-radius doc + affected Prisma models
  4. Confirm Zero-Bleed — tenant cookie scope, RLS, integration tests TENANT-*
  5. Formulate Proposal — amendment metadata in Audit Trail before merge

2. Monetary data dictionary (BIGINT cents only)

Model.fieldSQL columnType
Tenant.ale_baselineale_baselineBigInt NOT NULL
ThreatEvent.financialRisk_centsfinancialRisk_centsBigInt
ThreatEvent.mitigatedValueCentsmitigated_value_centsBigInt?
RiskEvent.governedImpactgoverned_impactBigInt (generated)
SustainabilityMetric.mitigatedValueCentsmitigated_value_centsBigInt NOT NULL
ActiveRisk.score_centsscore_centsBigInt
Company.industry_avg_loss_centsindustry_avg_loss_centsBigInt?

3. API routes (tenant-scoped excerpt)

MethodPathNotes
GET/api/dashboardtotalValueMitigatedYtdCents as digit string
POST/api/sustainability/ironbloom400 PHYSICAL_UNIT_REQUIRED if monetary-only
GET/api/insurance/actuarial-reportPDF export; premiumCents query param (string)
GET/api/docs/download-protocolFeature test protocol docx + ?manifest=1 JSON
GET/api/docs/download-matrixIronframe-UI-UX-Feature-Test-Matrix.csv

4. Java — BigIntContractValidator

package com.ironframe.grc.contract;

import java.math.BigInteger;
import java.util.regex.Pattern;

/** Mirrors app/utils/financialIntegrityLedgerCsv.parseCentsInput */
public final class BigIntContractValidator {
  private static final Pattern DIGIT_CENTS = Pattern.compile("^-?\\d+$");

  public static BigInteger parseCentsString(String raw) {
    if (raw == null || raw.isBlank()) return BigInteger.ZERO;
    String trimmed = raw.trim().replace(",", "");
    if (!DIGIT_CENTS.matcher(trimmed).matches()) {
      throw new IllegalArgumentException("FIN_LEDGER_CSV_FLOAT_BLOCKED: cents must be whole digits");
    }
    return new BigInteger(trimmed);
  }

  public static String formatUsdFromCents(BigInteger cents) {
    boolean neg = cents.signum() < 0;
    BigInteger abs = cents.abs();
    BigInteger dollars = abs.divide(BigInteger.valueOf(100));
    int frac = abs.mod(BigInteger.valueOf(100)).intValue();
    return String.format("%s%s.%02d", neg ? "-" : "", dollars, frac);
  }

  public static void rejectPhysicalUnitPayload(boolean hasKwh, boolean hasLiters, boolean hasKm, boolean monetaryOnly) {
    if (monetaryOnly && !(hasKwh || hasLiters || hasKm)) {
      throw new PhysicalUnitRequiredException("PHYSICAL_UNIT_REQUIRED");
    }
  }

  public static class PhysicalUnitRequiredException extends RuntimeException {
    public PhysicalUnitRequiredException(String code) { super(code); }
  }
}

5. Security & compliance matrix

ControlImplementationEvidence
DMZ air-gapIrongate (Agent 14) mandatory ingressdocs/TAS.md § DMZ
Row isolationSupabase RLS + tenantCompanyId filterstests/integration/dashboard.test.ts
WORM evidenceEpic 12 sealed bucket policydocs/pr/EPIC12_WORM_OPS.md
Export integrityExport Tabular Ledger Data (CSV) — data-testid export-tabular-ledger-csvtests/unit/financialIntegrityLedgerCsv.test.ts

6. CSV ledger matrix columns

metric_key, unit, amount_cents, amount_usd, bps_value, text_value, carrier_key, framework

amount_usd derived via integer division: dollars = cents / 100n; frac = cents % 100n (no JavaScript Number division on export path).