{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://finance.entelekron.org/schemas/bank-payment-instruction.schema.json",
  "title": "Verified bank payment instruction",
  "type": "object",
  "additionalProperties": false,
  "required": ["schemaVersion", "instructionId", "idempotencyKey", "canonicalAssetId", "environment", "legalEntity", "jurisdictionEntitlementId", "bankingProviderId", "rail", "sourceAccountEntitlementId", "beneficiaryId", "beneficiaryVersion", "beneficiaryVerificationDigest", "accountNameMatchDecision", "amount", "currency", "paymentPurpose", "sanctionsScreeningDigest", "fraudRiskDecisionDigest", "deviceSessionRiskDigest", "amountLimitDecisionDigest", "velocityLimitDecisionDigest", "policyBundleDigest", "ledgerOrderId", "approvals", "nonce", "createdAt", "expiresAt", "auditCorrelationId"],
  "properties": {
    "schemaVersion": {"const": "1.0.0"},
    "instructionId": {"type": "string", "pattern": "^[A-Za-z0-9:_-]{16,128}$"},
    "idempotencyKey": {"type": "string", "pattern": "^[A-Za-z0-9:_-]{16,128}$"},
    "canonicalAssetId": {"const": "tvk-group:tvkusd"},
    "environment": {"enum": ["sandbox", "staging", "production"]},
    "legalEntity": {"type": "string", "minLength": 1, "maxLength": 160},
    "jurisdictionEntitlementId": {"type": "string", "minLength": 1, "maxLength": 128},
    "bankingProviderId": {"type": "string", "minLength": 1, "maxLength": 128},
    "rail": {"enum": ["sepa-credit-transfer", "sepa-instant", "swift", "ach", "faster-payments", "local-bank-transfer"]},
    "sourceAccountEntitlementId": {"type": "string", "minLength": 1, "maxLength": 128},
    "beneficiaryId": {"type": "string", "minLength": 1, "maxLength": 128},
    "beneficiaryVersion": {"type": "integer", "minimum": 1},
    "beneficiaryVerificationDigest": {"$ref": "#/$defs/digest"},
    "accountNameMatchDecision": {"enum": ["exact-match", "close-match", "no-match", "unavailable"]},
    "amount": {"type": "string", "pattern": "^(0|[1-9][0-9]{0,17})\\.[0-9]{2,8}$"},
    "currency": {"type": "string", "pattern": "^[A-Z]{3}$"},
    "paymentPurpose": {"type": "string", "minLength": 3, "maxLength": 280},
    "sanctionsScreeningDigest": {"$ref": "#/$defs/digest"},
    "fraudRiskDecisionDigest": {"$ref": "#/$defs/digest"},
    "deviceSessionRiskDigest": {"$ref": "#/$defs/digest"},
    "amountLimitDecisionDigest": {"$ref": "#/$defs/digest"},
    "velocityLimitDecisionDigest": {"$ref": "#/$defs/digest"},
    "policyBundleDigest": {"$ref": "#/$defs/digest"},
    "ledgerOrderId": {"type": "string", "minLength": 1, "maxLength": 128},
    "approvals": {
      "type": "array", "minItems": 2, "uniqueItems": true,
      "items": {
        "type": "object", "additionalProperties": false,
        "required": ["approvalDomain", "authorityId", "decisionDigest", "approvedAt", "expiresAt"],
        "properties": {
          "approvalDomain": {"enum": ["payments-operations", "treasury-control", "financial-crime", "risk-control"]},
          "authorityId": {"type": "string", "minLength": 1, "maxLength": 128},
          "decisionDigest": {"$ref": "#/$defs/digest"},
          "approvedAt": {"type": "string", "format": "date-time"},
          "expiresAt": {"type": "string", "format": "date-time"}
        }
      }
    },
    "nonce": {"type": "string", "pattern": "^[A-Za-z0-9_-]{22,128}$"},
    "createdAt": {"type": "string", "format": "date-time"},
    "expiresAt": {"type": "string", "format": "date-time"},
    "auditCorrelationId": {"type": "string", "minLength": 1, "maxLength": 128}
  },
  "$defs": {
    "digest": {"type": "string", "pattern": "^[a-f0-9]{64}$"}
  },
  "x-tvkusd-invariants": [
    "raw bank-account data is prohibited; beneficiaryId resolves only inside a restricted provider boundary",
    "amount must be greater than zero and validated using exact decimal arithmetic at the currency-approved scale",
    "beneficiary version, amount and currency become immutable after the first approval",
    "close-match requires manual review; no-match and unavailable are denied",
    "at least two approval domains and two approval authority identities are required, and each set must be pairwise distinct",
    "provider finality and balanced reconciliation are required before success"
  ]
}
