Specification · v0.1 draft

BAINK Evidence Standard

A typed, hash-linked, profile-validated evidence bundle for AI-assisted banking decisions.

Primitive Objects

Six primitive types form the evidence grammar. They are intentionally minimal so they can describe any AI-assisted banking workflow.

  • Decision
    What was decided
  • Source
    What was used as input
  • Claim
    What the system asserted
  • Policy
    What rule applied
  • Actor
    Who or what acted
  • Event
    What happened, in order
rustclaim.rs
pub struct Claim {
    pub claim_id: ClaimId,
    pub text: String,
    pub claim_type: ClaimType,
    pub materiality: Materiality,
    pub status: ClaimStatus,
    pub supporting_sources: Vec<SourceId>,
    pub calculations: Vec<CalculationRef>,
    pub policy_refs: Vec<PolicyId>,
    pub generated_by: ActorId,
    pub confidence: Option<Confidence>,
    pub supersedes: Option<ClaimId>,
}

Bundle Format

A portable directory or archive. baink-bundle.json is the entrypoint and lists every artifact with its hash and required flag.

jsonbaink-bundle.json
{
  "bundle_id": "loan_123",
  "standard_version": "0.1.0",
  "profile": "baink-cm-0.1",
  "decision_id": "dec_8f3a",
  "artifacts": [
    { "path": "manifest.json", "type": "manifest", "required": true, "hash": "sha256:…" },
    { "path": "events.jsonl",  "type": "event_log", "required": true, "hash": "sha256:…" },
    { "path": "evidence_map.json", "type": "evidence_map", "required": true, "hash": "sha256:…" }
  ],
  "bundle_hash": "sha256:…"
}

Canonicalization Rules

Pretty JSON is for humans. Canonical JSON is for machines. The hash is for proof. Every object is serialized in canonical key order before hashing.

rust
pub trait Canonicalize {
    fn canonical_bytes(&self) -> Result<Vec<u8>, BainkError>;
    fn canonical_hash(&self) -> Result<Hash256, BainkError> {
        let bytes = self.canonical_bytes()?;
        Ok(Hash256::sha256(&bytes))
    }
}

Hash-Chain Protocol

The event ledger is append-only. Each event hash includes the canonical body and the previous event's hash, so removing or reordering events breaks every later fingerprint.

rust
pub fn verify_hash_chain(events: &[Event]) -> VerificationResult {
    for w in events.windows(2) {
        let (prev, next) = (&w[0], &w[1]);
        if next.prev_event_hash != Some(prev.event_hash.clone()) {
            return VerificationResult::fail("broken_hash_chain");
        }
        if next.compute_hash()? != next.event_hash {
            return VerificationResult::fail("invalid_event_hash");
        }
    }
    VerificationResult::pass()
}

EvidenceMap Protocol

The EvidenceMap links claims to sources, policies, reviewers, and exceptions. Every material claim must have source, calculation, policy, or reviewer support.

rust
pub struct EvidenceMappedClaim {
    pub claim_id: ClaimId,
    pub claim_text: String,
    pub claim_type: ClaimType,
    pub generated_by: ActorId,
    pub materiality: Materiality,
    pub support: ClaimSupport,
    pub policy_refs: Vec<PolicyId>,
    pub review: Option<ReviewRecord>,
    pub exceptions: Vec<ExceptionRef>,
}

Conformance Levels

Conformance is executable, not a marketing badge. Each level maps to a required set of verification rules.

  1. L0Compatibleschemas validate
  2. L1Verifiablerequired artifacts present, hashes match, chain valid
  3. L2Controlledclaims linked, policies versioned, actors resolved, exceptions recorded
  4. L3AuditGradesignoffs, replay recipe, retention policy, signed verification report
  5. L4Insurableincident workflow, control history, metrics, insurer intake fields

Profile System

The base standard defines what a claim is. A profile defines what a specific workflow's claims require — for example, every financial-metric claim in a credit memo must have both source support and calculation support.