AI Research Library

Credit Underwriting with Auditable Reasoning

Rajesh Ranjan Mahapatra

A credit decision becomes defensible when every material claim can be replayed from admitted evidence through calculation and policy to a separately authorised judgement.

© 2026 Rajesh Ranjan Mahapatra. 25 min read

Credit Underwriting with Auditable ReasoningAll AI Research Library

Credit Underwriting with Auditable Reasoning

A credit decision becomes defensible when every material claim can be replayed from admitted evidence through calculation and policy to a separately authorised judgement.

TLDR

  1. Auditability is a property of the decision chain, not the fluency of a credit memo or the availability of a feature-attribution chart.
  2. The mechanism is a replayable credit argument separating evidence, deterministic calculations, applicable policy, model proposal, independent review and accountable decision authority.
  3. Models may extract, compare, estimate and draft, while typed controls preserve lineage, recompute numbers, resolve policy versions and prevent proposals becoming approvals.
  4. A scorecard and ordinary case file may suffice when reviewers can reproduce every material decision reliably; the fuller pattern must earn its operating cost.
  5. The architecture decision changes from buying an “AI underwriter” to building a governed decision compiler with explicit release gates and a signed decision receipt.

The two identical memos

A credit committee receives two polished memos for the same fictional borrower, Redbridge Engineering. Both recommend a £4 million revolving-credit increase, subject to renewal of a factory lease. Every sentence, ratio and condition looks identical.

In the first system, the memo is the record. A reviewer can see the stated debt-service coverage ratio, a risk grade and three model-generated reasons. Finding the source behind a number requires opening folders, emails and spreadsheets. The policy threshold is described in prose. Nobody can tell whether the final wording came from the model, the relationship manager or the credit officer.

In the second system, each material claim points to admitted evidence. Every ratio has a calculation receipt. Every policy finding records the rule version and effective time. The model recommendation is stored as a proposal. The reviewer’s changes are visible. The approving officer signs a decision receipt binding the case, conditions and authority held at that moment.

Now change one item: management accounts arrive showing cash available for debt service is 8% lower. Both memos are regenerated and still look convincing. Only one system can answer, without detective work, which claims changed, whether the threshold still passes, who saw the change and whether the approval remains valid.

The difference is not explanation quality. It is replay. An auditable underwriting system can reconstruct why the institution was entitled to make a particular decision from the evidence, policy and authority available then. That requirement changes where probabilistic models belong, what must remain deterministic and what the final memo is allowed to claim.

Figure 1. The polished memo paradox
Worked scenario. The displayed recommendation is held constant; only the retained causal structure changes.
Part one

A clear memo can still be unauditable

Credit underwriting has always mixed different kinds of work. Documents are collected. Facts are reconciled. Ratios are calculated. Policies are applied. Forecasts are judged. Exceptions are negotiated. Conditions are drafted. A person or committee accepts responsibility. The memo compresses this activity into a form that can be read and approved.

Compression is useful, but it destroys distinctions unless the underlying system preserves them. A sentence such as “cash generation remains adequate” may contain a reported fact, an adjusted calculation, a policy threshold, a forecast assumption and a reviewer’s judgement. Those components have different error modes and different owners. Treating them as one generated paragraph makes the result easier to read while making challenge harder.

Supervisory material does not prescribe this article’s architecture. It does, however, make the control burden visible. Basel’s current credit-risk principles retain separate expectations around the credit environment, sound credit granting, administration and monitoring, and adequate controls.[1] The European Banking Authority’s loan-origination guidelines distinguish assessment, proposal, the relevant decision-maker, conditions and decision validity.[2] Model-risk regimes add inventory, validation, documentation, challenge and ongoing monitoring, with scope depending on jurisdiction and model type.[3][4]

These are related controls, not interchangeable evidence. A validated probability-of-default model does not prove the borrower’s latest cash balance. A source citation does not prove a ratio was calculated under the approved definition. A policy result does not confer authority on the person pressing approve. A signed decision does not make an unsupported model narrative true.

Thought experiment: change one cell

Imagine a spreadsheet that feeds the Redbridge memo. Cell G42 contains adjusted earnings before interest, tax, depreciation and amortisation. Change G42 from £1.8 million to £1.65 million while holding the document text, model version, policy library and approver constant.

What should move? The derived coverage ratio should change. Any covenant headroom using that ratio should change. Policy findings depending on the threshold should be re-evaluated. Forecast commentary may need revision. The proposal should be withdrawn or versioned. A prior reviewer attestation should expire if the change is material. The approval may need a new signature. Other facts, such as legal entity identity, should remain stable.

A system that only regenerates prose cannot prove this selective propagation. It may update too little, leaving a stale conclusion, or too much, rewriting unaffected statements and obscuring the causal break. Auditability requires an explicit dependency structure so that a changed input invalidates exactly the claims and acts that depended on it.

Practitioner synthesis

Use the smallest material claim as the unit of replay. Whole-document versioning tells an auditor that something changed. Claim-level dependencies show what changed, why it mattered and which approvals became stale.

Explanation, audit and challenge are different jobs

An explanation helps a particular audience understand a result. An audit establishes whether required evidence and controls existed and operated. Challenge tests whether the result survives alternatives, counterevidence and independent calculation. Good interfaces may support all three, but the evidence needed is different.

A feature-attribution chart can indicate which inputs influenced a model output. It does not establish that the inputs belong to the right borrower, were valid at the decision time, were permitted for that use or were interpreted under current policy. Shapley-value explanations also carry modelling assumptions that can be misunderstood as causal contributions.[9] Post-hoc explanation methods can be manipulated by adversarial model behaviour.[10] Their proper role is bounded model evidence, not a substitute for the wider decision record.

The same caution applies to natural-language rationales. A language model can turn structured factors into a concise paragraph, but fluency creates no extra lineage. The rationale must remain a projection of retained objects. If the paragraph mentions a declining order book, the system should point to the source and extraction. If it says a policy exception is acceptable, it should identify the rule, exception owner and recorded judgement. Unsupported sentences should fail validation even when they sound plausible.

The United States provides a useful, jurisdiction-specific example. Current Regulation B requires disclosed reasons to relate to factors actually considered or scored; combined scoring and judgement systems must draw reasons from the component that produced the adverse action.[5] That requirement is narrower than full auditability, yet it exposes the same principle: a reason is defensible only when it corresponds to the actual decision process.

What the memo must not blur

A credit memo commonly contains at least six claim types:

Observed claims report what a source says, such as revenue in signed accounts. Derived claims transform evidence using a formula, such as leverage. Policy claims state how a rule applies, such as whether the ratio exceeds a minimum. Predictive claims estimate an uncertain future, such as default probability. Judgement claims express accountable interpretation, such as accepting temporary margin compression. Authority claims establish who may approve which amount, tenor, grade and exception.

Each type needs a different receipt. Observed claims need provenance and validity. Derived claims need typed inputs and executable formulas. Policy claims need effective-time resolution. Predictive claims need model identity, calibration context and limitations. Judgement claims need an identified reviewer and recorded basis. Authority claims need identity, delegated limit and any required concurrence.

Figure 2. A core sample of underwriting correctness
Conceptual model. A readable memo sits at the surface; defensibility depends on the integrity of all layers beneath it.

The serious counterexample

The preferred pattern can be unnecessary. Consider a small lender using a stable, transparent scorecard for low-value, homogeneous products. Inputs arrive from controlled systems. Every calculation is deterministic. A short policy matrix maps results to approve, decline or manual review. An ordinary case file records source snapshots, score, decision and operator. Independent reviewers can reproduce a sample in minutes.

Adding a graph of claim objects, hashes and event streams might increase cost without improving control. The architecture would become ceremony. It could even reduce review quality by presenting more information than staff can use. FCA research on explanation interfaces found that extra information can increase confidence while impairing error detection in some conditions.[6]

The negative control is replay performance, not architectural fashion. If the simpler baseline reliably reconstructs material decisions, localises errors and preserves decision rights, keep it. Introduce the fuller credit argument map when cases are document-heavy, policies are time-sensitive, models are probabilistic, exceptions are frequent, decisions are high-consequence or several systems jointly create the outcome.

Part two

The credit argument map

The central artefact is a directed, versioned argument rather than a generated memo. It connects admitted evidence to calculations, policy findings, model proposals, review and an authorised decision. Each edge names the dependency. Each object has an owner, identity, time and state. The memo is rendered from this graph and therefore cannot silently outrun it.

Figure 3. The credit argument map
Credit argument map from evidence to decision receipt Evidence enters a calculation and policy path. A model proposal travels beside the controlled path. Review can challenge every layer. Only an authorised decision creates a decision receipt. Unresolved exceptions block release. ADMITTEDEVIDENCE CALCULATIONRECEIPTS POLICYFINDINGS MODELPROPOSAL INDEPENDENTREVIEW AUTHORISED DECISION identity · limit · conditions · validity UNRESOLVED EXCEPTION disputed source · failed replay · policy conflict missing review · insufficient authority DECISION RECEIPT
Signature figure. The topology is an argument and authority flow, not a generic component diagram. The model contributes a proposal; it never crosses the authority boundary by itself.

Six objects that must not collapse

1. Admitted evidence. A document is not automatically evidence for a particular claim. Admission establishes the entity, source, period, scope, authenticity status, entitlement, validity window and any dispute. Extraction outputs remain candidate facts until reconciled. A page citation is useful, but the durable object is the claim and its relation to a source version. W3C PROV-O offers a general vocabulary for entities, activities and agents; a credit implementation still needs domain-specific types and rules.[7]

2. Calculation receipts. Ratios, limits, aggregations and adjustments should be reproduced by deterministic code. The receipt records formula identity, version, typed inputs, units, currency conversion, precision, rounding and result. A language model may locate candidate inputs or explain a formula. It should not be the authoritative calculator where exact replay is practical.

3. Policy findings. Policy is evaluated against case facts at an effective time. The finding states the rule identity, version, inputs, outcome, severity, owner and permitted exception route. This matters because a true fact can be paired with an obsolete rule. It also prevents a policy summary in a prompt from acquiring the force of the actual controlled policy.

4. Model proposal. The model object records the requested task, model and prompt versions, context manifest, output, confidence or uncertainty where meaningful, supporting object references, limitations and tests. Its status is explicitly non-authoritative. That label is not cosmetic. It prevents downstream systems from interpreting a fluent recommendation as a decision.

5. Review. Review records what the reviewer actually saw, challenged and changed. A checkbox that says “human reviewed” is weak evidence. The useful object binds the reviewed basis, questions raised, independent calculations, counterevidence, unresolved issues and disposition. If the basis changes materially, the attestation expires.

6. Decision receipt. The receipt binds the final outcome to case version, material claims, conditions, decision-maker, delegated authority, concurrence, time and validity. It does not certify that the judgement was correct. It proves which accountable actor made which decision on which retained basis.

The release predicate

The map becomes operational when release is defined as a mechanical predicate rather than a social expectation. A simplified form is:

Release = E ∧ C ∧ P ∧ M ∧ R ∧ A ∧ ¬X

E means all material evidence is admitted and valid; C means deterministic calculations replay; P means applicable policy is resolved; M means the model proposal passes schema and support checks; R means review covers the current basis; A means the decision-maker holds sufficient authority; X means an unresolved blocking exception.

Changing a term changes the permitted action. If C fails, the system may still allow an analyst to inspect the case, but approval cannot release. If M fails while the model is advisory, the case may continue without the proposal after policy-defined handling. If A fails, a sound credit judgement still cannot take effect until the case reaches an authorised decision-maker. The conjunction therefore captures both epistemic and institutional requirements.

This is a design predicate, not a universal legal formula. Each institution must map its own products, policies, jurisdictions and decision rights. Some terms will contain thresholds rather than Booleans. Others will require dual control or committee quorum. The important move is to make the release condition explicit, executable and testable.

The decision receipt is not another memo

A memo is optimised for reading. A receipt is optimised for proof and replay. It should be compact enough to retain and compare, while pointing to richer objects. A minimal receipt may include a basis hash, outcome, approved amount and tenor, risk grade, conditions, exceptions, decision-maker identity, authority source, concurrence, decision time, validity window and supersession relation.

The basis hash is a tamper-evident summary of reviewed material, not a mystical guarantee. Hashing cannot establish truth. It can establish that the decision is no longer bound to the same object set after a material change. That makes stale approval detectable.

The receipt also separates decision from effect. “Approve with conditions” is an institutional judgement. Booking the facility, sending a notice or permitting drawdown is a later effect. Before each effect, the system should confirm that conditions are satisfied, authority remains valid, the decision has not been superseded and the requested action matches the approved scope.

The map needs time and state

Credit files contain several times that should not be collapsed. A document has an observation period and a received time. A fact has a validity interval. Policy has an effective interval. A model has a release and retirement period. Review has a completed time and expiry trigger. A decision has a validity window. An effect has an execution time and outcome.

Without these distinctions, a later audit can reconstruct today’s interpretation rather than the decision-time world. The system should answer two questions: what was believed and permitted then, and what is known now? Bitemporal records or event-sourced case state are common implementation choices, but the mechanism matters more than the storage fashion.

State also distinguishes unresolved, accepted and superseded objects. A disputed revenue figure should not silently remain “the revenue.” A policy conflict should not be flattened into a recommendation. A replaced decision should remain queryable without remaining executable. Auditability improves when invalidation is a first-class event.

Typed boundaries around the model

The model should receive a context manifest rather than an undifferentiated document dump. The manifest can include admitted claims, candidate claims, calculation receipts, policy findings, unresolved exceptions and the exact task. Its output should conform to a schema that distinguishes proposal, supporting references, assumptions, uncertainty, requested human judgement and prohibited claims.

For example, the model may propose: “Approve £4 million for twelve months, conditional on lease renewal before first drawdown.” It may cite the ratio receipt and lease-expiry evidence. It may not set `decision_status=approved`, assert that policy passed without a policy finding, or invent a decision-maker. A deterministic validator rejects any unsupported reference or authority-bearing field.

This boundary also makes model replacement easier. A scorecard, gradient-boosted model or language model can produce a proposal object with different internal methods. The downstream authority kernel consumes the same typed contract. Model risk remains important, but the institution avoids building decision rights into a vendor-specific prompt.

Part three
The argument in one passChart · flow
flowchart LR
  A["A clear memo can still be<br/>unauditable"] --> B["The credit argument map"]
  B --> C["Two cases through the map"]
  C --> D["Make replay an operating property"]
  D -. "re-test" .-> A
  classDef first fill:#0a1424,stroke:#007D68,stroke-width:2px,color:#e6f3ff
  classDef step fill:#0a1424,stroke:#3f7da0,stroke-width:1px,color:#e6f3ff
  class A first
  class B,C,D step
A structural route through Credit Underwriting with Auditable Reasoning, from A clear memo can still be unauditable to Sources. Reading use: follow the relation, then test it against the surrounding evidence and limits.

Two cases through the map

Minimal worked example: one ratio, one condition

Take a synthetic small-business case with £180,000 cash available for debt service and £130,000 scheduled debt service. The approved formula gives a debt-service coverage ratio of 180 divided by 130, or 1.384615 before presentation rounding. Policy requires at least 1.25. The ratio passes.

The borrower’s factory lease expires in nine months, while the proposed facility runs for twelve. A separate policy rule requires control of premises throughout the committed period. The correct result is therefore not an unconditional approval. It is a pass on coverage with a condition that satisfactory lease renewal be evidenced before first drawdown.

Figure 4. The ratio passes; the case still carries a condition
Coverage rule: 1.38 ≥ 1.25, pass
Separate premises rule: lease renewal required before drawdown
Synthetic worked example. Values are illustrative and shown in GBP thousands. The calculation and condition come from different dependencies.

The model can draft a concise rationale using those objects. The validator can prove that the numeric statement matches the calculation receipt and that the condition matches a policy finding. The credit officer can accept or alter the proposal. The decision receipt then records the actual outcome and authority. If the lease is renewed, the drawdown control verifies the condition from new evidence without recreating the original credit judgement.

Notice what has been gained. The model did not need to “understand” institutional authority. The policy engine did not need to narrate commercial judgement. The officer did not need to recompute arithmetic manually. Each mechanism performs the work for which its evidence is strongest.

Thought experiment: hold the score constant

Now hold the borrower data, default estimate and model explanation constant. Change only the institutional context.

In world A, concentration to the borrower’s sector remains within appetite. The relevant officer holds a £5 million delegated limit. The facility can be approved with the lease condition.

In world B, a new sector-concentration rule became effective yesterday. The case requires an exception, and the same officer’s authority excludes concentration overrides. The identical risk estimate now leads to escalation rather than approval.

Figure 5. One risk estimate, two permissible outcomes
Thought experiment. Only policy effective time and authority change. A model explanation cannot determine the permissible institutional act.

The experiment isolates the error in treating prediction as decision. Default risk is relevant, but an underwriting outcome also depends on policy, portfolio context, conditions and decision rights. A more explainable model does not erase those variables. Nor should they all be absorbed into the model, because doing so makes policy change harder to govern and authority harder to inspect.

Production-shaped worked scenario: Redbridge Engineering

Redbridge is a synthetic composite designed to expose the mechanism. It is not a reported deployment. The borrower requests a £4 million increase to support seasonal working capital. The case includes signed accounts, management accounts, bank statements, an aged-debtor report, group structure, existing facilities, a property lease and relationship notes.

Intake and identity. The system resolves the legal entity and associates each source with the correct company and period. An extraction model proposes values from documents. Deterministic checks reconcile opening and closing cash, compare totals to source pages and flag mismatched currencies. The analyst admits supported claims and leaves two disputed customer concentrations unresolved.

Calculation. A controlled library computes leverage, coverage, liquidity and covenant headroom from admitted claims. It produces receipts showing definitions and adjustments. One management-account input initially uses group revenue while the formula expects borrower-only revenue. Independent replay detects the mismatch and invalidates the affected ratios.

Policy. The policy service resolves rules effective for the product, jurisdiction, sector and decision date. Coverage passes. Leverage passes after the entity mismatch is corrected. The lease creates a pre-drawdown condition. Customer concentration requires explicit reviewer judgement because the aged-debtor report contains disputed classifications.

Model proposal. A language model receives the typed context and proposes approval with conditions. It identifies concentration and lease risks, compares the latest period with prior performance and drafts a memo. It is barred from introducing unreferenced figures or setting approval status. Its recommendation travels as one object beside the controlled evidence and policy path.

Review. The credit officer challenges the customer concentration interpretation and asks for the ten largest invoices. New evidence changes two classifications. The concentration falls below the exception threshold. The proposal and memo are regenerated, but the system preserves the old versions and records why the reviewer changed the basis.

Decision and effect. An authorised officer approves £4 million for twelve months with a lease-renewal condition. The receipt binds the corrected calculations, policy findings, final proposal, review and authority. The booking workflow receives only the approved terms. Drawdown remains blocked until lease evidence is admitted and read back from the relevant system.

Figure 6. Redbridge moves through versions, not one static memo
Synthetic sequence. The failure is contained before approval, and the corrected basis requires fresh review.

The reviewer interface is part of the control

A complete graph can still produce a poor decision if the interface hides the causal structure. The reviewer should see changes, exceptions and disagreements before polished narrative. Material figures should open to calculations and sources. Policy findings should show the applicable rule and time. Model suggestions should be visually distinct from admitted facts. A changed basis should be impossible to miss.

Review views should also be task-specific. A relationship manager may need missing evidence and customer questions. A credit officer needs risk drivers, calculations, policy and alternatives. A validator needs model lineage and performance. An auditor needs replay and control evidence. Giving everyone the entire graph can create information overload.

The interface should therefore compile views from one underlying record while preserving traceability. This is where explanation belongs: adapting the same defensible basis to the needs of different audiences without changing the source of institutional truth.

Part four

Make replay an operating property

A well-designed schema is necessary but insufficient. The organisation must test whether evidence, calculation, policy, model, review and authority failures propagate as intended. The governing question is simple: when one causal feature is corrupted, does the system expose the break before release?

The six-break release test

Injected breakExpected control responseRequired operating evidenceRelease result
Source is stale, disputed or belongs to another entityDerived claims lose admitted statusProvenance, validity and supersession eventBlock affected decisions
Formula, unit, currency or rounding changesIndependent replay differsCalculation version, typed inputs and test resultBlock until reconciled
Policy version is inapplicable or conflictingFinding becomes unresolvedEffective-time query and rule traceEscalate or block
Model cites absent support or invents a claimProposal fails claim validationObject references and unsupported-claim reportWithdraw proposal
Reviewer did not see the final basisPrior attestation becomes invalidReviewed-basis hash and version eventRequire fresh review
Approver lacks authority or conditions expireDecision cannot release or drawIdentity, delegated limit, conditions and validityEscalate or stop effect

Run these tests in development, before each material release and periodically in operation. Use synthetic cases with known truths, historical cases whose records may be used lawfully, and carefully governed shadow traffic. Test each component alone, then test the compound trajectory. A model can pass its benchmark while the underwriting system fails because a source was misbound or an approval remained active after the basis changed.

Figure 7. Failure propagation should be selective and visible
Illustrative control matrix, not measured performance. Darker cells indicate stronger invalidation or blocking. The expected response is deliberately selective.

Adopt the pattern in bounded stages

Start by inventorying decision objects rather than selecting a model. Identify material facts, deterministic calculations, policy findings, judgement points, approval rights and downstream effects. Map where each currently lives and how a reviewer reconstructs it. This baseline often reveals that the largest audit gap is not the model. It may be spreadsheet lineage, policy ambiguity or undocumented exception authority.

Next, create stable identifiers and receipts for the most consequential calculations. Add effective-time policy evaluation. Separate proposal fields from decision fields. Bind review to a basis version. Introduce release gates at one decision boundary. Only then add probabilistic extraction or drafting where the task has a measurable benefit.

Run the old and new paths on matched cases. Compare analyst time, replay distance, unsupported claims, calculation discrepancies, policy conflicts, review changes and escaped control failures. A better memo is not enough. The system should localise defects faster and reduce the chance that stale or unauthorised decisions take effect.

Scope should follow consequence. Low-value, reversible cases may use lighter receipts and sampling. Large, complex or exception-heavy facilities warrant deeper provenance and explicit concurrence. This keeps the design proportionate and aligns with the risk-tailored direction of current model-risk guidance.[4]

A decision is not the same as its effect

Many compound systems prove that an API accepted a command and then assume the intended state exists. Credit operations cannot rely on that shortcut. Booking may time out after the core system commits. A notification may be sent twice. A condition may be marked complete in one store but absent in another. The result is an unknown outcome.

The effect layer therefore needs idempotency, correlation identifiers, timeouts, execution receipts and independent readback. A decision receipt authorises a bounded intent. An effect receipt records what the operational system says happened. A postcondition check verifies the resulting facility, limits, conditions and status. If the outcome remains unknown, the workflow should stop retries that could duplicate an effect and escalate for reconciliation.

This separation keeps the credit argument honest. It does not claim that approval created the facility. It records the path from justified decision to verified business outcome, including any failure between them.

Measure replay, not document presence

A folder can contain every required document and still be unauditable. Useful operating measures focus on reconstruction and failure response:

Replay distance is the elapsed time and unresolved effort required for an independent reviewer to reproduce a material decision. Support coverage is the proportion of material memo claims linked to admitted evidence, calculations, policy or explicit judgement. Basis freshness measures decisions whose review and authority still match the current material object set. Failure containment measures whether injected faults invalidate the correct downstream objects before effect. Challenge yield records how often review changes evidence, calculation, policy interpretation, proposal or outcome.

These measures should be segmented by product, case complexity, model version and reviewer role. A global average can hide the cases that matter most. Targets should also avoid perverse incentives. Minimising review time alone may suppress challenge. Maximising citation count may flood the interface. The objective is decision-sufficient evidence with proportionate effort.

Executable artefact: audit-replay validator

The following standard-library Python prototype expresses a small part of the release predicate. It uses synthetic data. The validator checks evidence identity and validity, calculation replay, policy effective time, non-authoritative model status, delegated authority and a basis hash. The positive case passes. Four mutations create five blocking findings because changing the model’s authority flag also changes the reviewed basis.

credit_underwriting_audit_replay.py
"""Synthetic audit-replay validator for a credit decision pack.

The example uses public-domain logic and synthetic data only. It demonstrates
how a decision release can be blocked when evidence, calculation, policy,
model status, authority or reviewed-basis invariants fail.
"""

from __future__ import annotations

from dataclasses import asdict, dataclass, replace
from datetime import datetime, timezone
from decimal import Decimal, getcontext
from hashlib import sha256
import json
from typing import Iterable

getcontext().prec = 28


@dataclass(frozen=True)
class Evidence:
    evidence_id: str
    entity_id: str
    kind: str
    value: str
    valid_from: datetime
    valid_to: datetime | None
    source_hash: str

    def valid_at(self, moment: datetime) -> bool:
        return self.valid_from <= moment and (
            self.valid_to is None or moment < self.valid_to
        )


@dataclass(frozen=True)
class Calculation:
    calculation_id: str
    formula_id: str
    input_ids: tuple[str, ...]
    reported_result: Decimal


@dataclass(frozen=True)
class PolicyFinding:
    rule_id: str
    effective_from: datetime
    effective_to: datetime | None
    outcome: str

    def effective_at(self, moment: datetime) -> bool:
        return self.effective_from <= moment and (
            self.effective_to is None or moment < self.effective_to
        )


@dataclass(frozen=True)
class ModelProposal:
    proposal_id: str
    model_id: str
    recommendation: str
    authoritative: bool


@dataclass(frozen=True)
class Review:
    reviewer_id: str
    basis_hash: str
    disposition: str


@dataclass(frozen=True)
class DecisionReceipt:
    decision_id: str
    decision_maker_id: str
    authority_limit: Decimal
    facility_amount: Decimal
    basis_hash: str
    outcome: str
    decided_at: datetime


@dataclass(frozen=True)
class CreditPack:
    case_id: str
    entity_id: str
    evidence: tuple[Evidence, ...]
    calculations: tuple[Calculation, ...]
    policy_findings: tuple[PolicyFinding, ...]
    proposal: ModelProposal
    review: Review
    decision: DecisionReceipt


def canonical(value: object) -> object:
    """Convert dataclasses, datetimes and decimals into hash-stable JSON."""
    if hasattr(value, "__dataclass_fields__"):
        return canonical(asdict(value))
    if isinstance(value, dict):
        return {key: canonical(value[key]) for key in sorted(value)}
    if isinstance(value, (tuple, list)):
        return [canonical(item) for item in value]
    if isinstance(value, datetime):
        return value.astimezone(timezone.utc).isoformat()
    if isinstance(value, Decimal):
        return format(value, "f")
    return value


def reviewed_basis(pack: CreditPack) -> dict[str, object]:
    """Return the objects whose material change requires renewed review."""
    return {
        "case_id": pack.case_id,
        "entity_id": pack.entity_id,
        "evidence": pack.evidence,
        "calculations": pack.calculations,
        "policy_findings": pack.policy_findings,
        "proposal": pack.proposal,
    }


def digest(value: object) -> str:
    payload = json.dumps(
        canonical(value), sort_keys=True, separators=(",", ":")
    ).encode("utf-8")
    return sha256(payload).hexdigest()


def replay(calculation: Calculation, evidence: dict[str, Evidence]) -> Decimal:
    if calculation.formula_id != "DSCR_V1":
        raise ValueError(f"unknown formula {calculation.formula_id}")
    cash_available = Decimal(evidence[calculation.input_ids[0]].value)
    debt_service = Decimal(evidence[calculation.input_ids[1]].value)
    return cash_available / debt_service


def validate(pack: CreditPack) -> list[str]:
    findings: list[str] = []
    moment = pack.decision.decided_at
    evidence = {item.evidence_id: item for item in pack.evidence}

    for item in pack.evidence:
        if item.entity_id != pack.entity_id:
            findings.append(
                f"evidence {item.evidence_id} belongs to another entity"
            )
        if not item.valid_at(moment):
            findings.append(
                f"evidence {item.evidence_id} was not valid at decision time"
            )

    for calculation in pack.calculations:
        missing = [item for item in calculation.input_ids if item not in evidence]
        if missing:
            findings.append(
                f"calculation {calculation.calculation_id} has missing inputs {missing}"
            )
            continue
        expected = replay(calculation, evidence)
        if expected != calculation.reported_result:
            findings.append(
                f"calculation {calculation.calculation_id} reports "
                f"{calculation.reported_result}, replay gives "
                f"{expected.quantize(Decimal('0.000001'))}"
            )

    for finding in pack.policy_findings:
        if not finding.effective_at(moment):
            findings.append(
                f"policy {finding.rule_id} was not effective at decision time"
            )

    if pack.proposal.authoritative:
        findings.append("model proposal is marked authoritative")

    if pack.decision.authority_limit < pack.decision.facility_amount:
        findings.append("approver authority is below the facility amount")

    current_basis_hash = digest(reviewed_basis(pack))
    if (
        pack.review.basis_hash != current_basis_hash
        or pack.decision.basis_hash != pack.review.basis_hash
    ):
        findings.append("decision receipt no longer matches the reviewed basis")

    return findings


def make_positive_pack() -> CreditPack:
    decided_at = datetime(2026, 6, 30, 14, 0, tzinfo=timezone.utc)
    evidence = (
        Evidence(
            "ev-cash",
            "redbridge",
            "cash_available_for_debt_service_gbp_thousands",
            "180",
            datetime(2026, 1, 1, tzinfo=timezone.utc),
            None,
            "sha256:synthetic-cash",
        ),
        Evidence(
            "ev-debt",
            "redbridge",
            "scheduled_debt_service_gbp_thousands",
            "130",
            datetime(2026, 1, 1, tzinfo=timezone.utc),
            None,
            "sha256:synthetic-debt",
        ),
    )
    calculation = Calculation(
        "calc-dscr",
        "DSCR_V1",
        ("ev-cash", "ev-debt"),
        Decimal("180") / Decimal("130"),
    )
    policy = PolicyFinding(
        "SME.DSCR.MIN",
        datetime(2026, 1, 1, tzinfo=timezone.utc),
        None,
        "PASS_WITH_LEASE_CONDITION",
    )
    proposal = ModelProposal(
        "proposal-17",
        "synthetic-credit-proposer-v1",
        "approve_with_conditions",
        False,
    )
    provisional = CreditPack(
        "case-redbridge-188",
        "redbridge",
        evidence,
        (calculation,),
        (policy,),
        proposal,
        Review("reviewer-42", "", "challenged_and_supported"),
        DecisionReceipt(
            "decision-88",
            "credit-officer-7",
            Decimal("5000000"),
            Decimal("4000000"),
            "",
            "approve_with_conditions",
            decided_at,
        ),
    )
    basis_hash = digest(reviewed_basis(provisional))
    return replace(
        provisional,
        review=replace(provisional.review, basis_hash=basis_hash),
        decision=replace(provisional.decision, basis_hash=basis_hash),
    )


def make_negative_pack(positive: CreditPack) -> CreditPack:
    return replace(
        positive,
        calculations=(
            replace(
                positive.calculations[0],
                reported_result=Decimal("1.58"),
            ),
        ),
        policy_findings=(
            replace(
                positive.policy_findings[0],
                effective_to=datetime(
                    2026, 6, 1, tzinfo=timezone.utc
                ),
            ),
        ),
        proposal=replace(positive.proposal, authoritative=True),
        decision=replace(
            positive.decision,
            authority_limit=Decimal("3000000"),
        ),
    )


def report(label: str, findings: Iterable[str]) -> None:
    items = list(findings)
    if not items:
        print(f"{label}: PASS")
        return
    print(f"{label}: BLOCKED ({len(items)} findings)")
    for item in items:
        print(f" - {item}")


if __name__ == "__main__":
    positive = make_positive_pack()
    negative = make_negative_pack(positive)
    report("POSITIVE", validate(positive))
    report("NEGATIVE", validate(negative))
Expected output
POSITIVE: PASS
NEGATIVE: BLOCKED (5 findings)
 - calculation calc-dscr reports 1.58, replay gives 1.384615
 - policy SME.DSCR.MIN was not effective at decision time
 - model proposal is marked authoritative
 - approver authority is below the facility amount
 - decision receipt no longer matches the reviewed basis
Implementation notes and extensions

The prototype deliberately omits identity providers, cryptographic signing, policy conflict resolution, currencies, committee quorum and effect verification. A production implementation would use typed schemas, controlled formula libraries, immutable or tamper-evident event records, purpose-bound access, observability and independent tests.

Property tests should mutate every material input and assert selective invalidation. Security tests should attempt cross-entity evidence substitution, stale-policy replay, unsupported model references, authority escalation and duplicate effects. The same pack should be replayable without invoking the language model.

Figure 8. Release is a gate; the receipt is the retained proof
Practitioner synthesis. The proposal travels with the case but is deliberately excluded from the mechanical authority condition.

The explicit failure boundary

The credit argument map fails when its objects create an illusion of certainty. A source hash proves file identity, not truth. A replayed formula proves consistent arithmetic, not a sensible definition. A policy engine proves encoded rules fired, not that the policy is lawful or wise. A signed receipt proves who approved the recorded basis, not that they exercised good judgement.

The pattern also ceases to help when the institution cannot define material claims, maintain stable identifiers, govern effective time or preserve historical meaning. Excessive granularity can overwhelm reviewers and bury the risk, echoing the FCA finding that added information may impair error detection. The answer is to design audience-specific views over a disciplined record and test whether each view improves the intended challenge task.

Interpretability choices remain important inside the model boundary. For high-stakes decisions, Rudin argues that interpretable models should be preferred where they can perform adequately rather than explaining an avoidable black box after the event.[8] Credit-scoring research also distinguishes transparency, auditability and explainability as separate dimensions.[11] Yet even a transparent model cannot validate source identity, policy effective time or decision authority. The wider chain is still required.

Finally, auditability cannot repair a poor credit strategy. If incentives reward volume over sound judgement, if exceptions become routine, if data excludes important populations or if policy converts historical inequality into future denial, a perfect trail may only make a flawed process easier to inspect. Research on machine learning in credit markets shows that predictive improvements and distributional effects can coexist.[12] Governance must use visibility to change models, rules, products and decision rights.

How the claim changes under pressureChart · state
stateDiagram-v2
  [*] --> Claim
  state "Thought experiment, change one<br/>cell" as Claim
  state "Explanation, audit and<br/>challenge are different jobs" as Test
  state "What the memo must not blur" as Revision
  Claim --> Test: expose mechanism
  Test --> Decision: evidence survives
  Test --> Revision: rival survives
  Revision --> Claim: narrow or rebuild
  Decision --> [*]
The revision loop begins with Thought experiment, change one cell and keeps counterexamples inside the reasoning path. Reading use: follow the relation, then test it against the surrounding evidence and limits.

Compact glossary

Admitted evidence
A source-backed claim that has passed identity, scope, validity, entitlement and quality checks for use in the case.
Calculation receipt
A replayable record of formula version, typed inputs, transformations, precision and result.
Policy finding
The evaluated relation between an effective rule and case facts, including outcome, exception route and owner.
Model proposal
A probabilistic estimate, comparison or draft that may inform judgement but carries no institutional authority.
Decision receipt
The immutable or tamper-evident record binding the final basis, outcome, conditions, decision-maker, authority and validity.
Replay distance
The time and unresolved effort required for an independent reviewer to reconstruct a material decision from retained evidence.

Build the trail before the model

The familiar automation question asks how much of underwriting a model can perform. That framing begins too late. The prior question is which claims, transformations and acts must remain independently inspectable when the decision is challenged months later.

The answer separates the system. Evidence must be admitted and versioned. Arithmetic must replay. Policy must resolve against facts and effective time. Models may estimate and draft within declared boundaries. Review must record actual challenge. Authority must attach to an identified decision-maker. Release must fail when any blocking invariant breaks. The final memo becomes a readable projection of this structure rather than its substitute.

The changed architecture decision is to build a governed credit decision compiler, not a monolithic AI underwriter. Start with argument objects and six-break tests. Establish a baseline using the existing case file and scorecard. Measure replay distance, error localisation and review quality. Add probabilistic models only where they improve a defined task without weakening the chain.

That trail also makes disagreement productive. Validators can challenge the model without reopening arithmetic. Policy owners can change rules without rewriting evidence. Credit officers can exercise judgement without disguising it as model output. Auditors can identify the exact layer where a failure entered and whether the control response contained it.

This design does not promise correct loans. It creates something more modest and operationally valuable: when the institution says yes, no or not yet, it can show what it knew, what it calculated, which rule applied, what the model proposed, who challenged it and who had the right to decide.

The evidence conversationChart · sequence
sequenceDiagram
  participant Q as Question
  participant M as Mechanism
  participant E as Evidence
  participant D as Decision
  Q->>M: A clear memo can still be unauditable
  M->>E: Thought experiment, change one cell
  E-->>M: compare rival explanations
  E->>D: Sources
  D-->>Q: revise scope or act
Question, mechanism, evidence and decision exchange the burdens developed in Credit Underwriting with Auditable Reasoning. Reading use: follow the relation, then test it against the surrounding evidence and limits.

Sources

Official and supervisory sources

  1. Basel Committee on Banking Supervision, Principles for the Management of Credit Risk. Current principles covering the credit-risk environment, credit-granting process, administration and monitoring, and controls.
  2. European Banking Authority, Guidelines on loan origination and monitoring, especially the relation between assessment, proposal, decision-maker, conditions and validity.
  3. Prudential Regulation Authority, SS1/23: Model risk management principles for banks.
  4. Board of Governors of the Federal Reserve System, FDIC and OCC, Supervisory Guidance on Model Risk Management, SR 26-2. Scope and applicability are jurisdiction-specific.
  5. Consumer Financial Protection Bureau, 12 CFR 1002.9, Regulation B: Notifications and specific reasons. Used as a US example, not a global underwriting rule.
  6. Financial Conduct Authority, Credit where credit is due: How can we explain AI’s role in credit decisions for consumers?
  7. W3C, PROV-O: The PROV Ontology. General provenance vocabulary used as an implementation reference, not a credit-policy specification.

Primary and scholarly sources

  1. Cynthia Rudin, Stop explaining black box machine learning models for high stakes decisions and use interpretable models instead, Nature Machine Intelligence.
  2. I. Elizabeth Kumar, Suresh Venkatasubramanian, Carlos Scheidegger and Sorelle Friedler, Problems with Shapley-value-based explanations as feature importance measures, ICML.
  3. Dylan Slack, Sophie Hilgard, Emily Jia, Sameer Singh and Himabindu Lakkaraju, Fooling LIME and SHAP: Adversarial Attacks on Post hoc Explanation Methods.
  4. Michael Bücker, Gero Szepannek, Alicja Gosiewska and Przemyslaw Biecek, Transparency, Auditability and eXplainability of Machine Learning Models in Credit Scoring.
  5. Andreas Fuster, Paul Goldsmith-Pinkham, Tarun Ramadorai and Ansgar Walther, Predictably Unequal? The Effects of Machine Learning on Credit Markets, The Journal of Finance.
  6. Finale Doshi-Velez and Been Kim, Towards a Rigorous Science of Interpretable Machine Learning.
  7. Zachary C. Lipton, The Mythos of Model Interpretability, ACM Queue.