Templates/Fintech & Payments/PSD3 SCA exemption decider

PSD3 SCA exemption decider

Risk-based + transaction-risk-analysis exemption verdict per RTS on SCA. Each decision binds the risk score + exemption category to the spec hash for proposed PSR Arts. 85–89 reproducibility.

Category: classifier·Reviewer-gate: on-low-confidence·For Fintech & Payments·Use-case page →

What this template is

Pattern: per-payment-attempt evaluation of whether SCA can be skipped under the RTS on SCA Arts. 16-18. Output is bounded to the exemption category enum + risk score + reason code. Always-human reviewer NOT used here (would defeat the exemption flow); reviewer-gate on low confidence captures edge cases without blocking. Deterministic fallback to 'apply-sca' when the LLM fails or violates schema — exemption-conservatism: applying SCA is recoverable, skipping it when you shouldn't is regulatory.

The template

TypeScript · BSL-1.1 · License

import { RuntimeAISpec } from '@promethean/runtime-ai';

export const scaExemptionSpec: RuntimeAISpec = {
  specId: 'sca-exemption-v1',
  displayName: 'PSD3 SCA exemption decider',
  description:
    'Per-payment exemption verdict under PSD2 RTS on SCA Arts. 16-18.',
  category: 'classifier',
  schemaVersion: 'promethean-runtime-ai-spec-1.0',
  canonicalForm: 'v1',

  inputSchema: {
    fields: [
      { name: 'paymentId', type: 'string', required: true,
        redaction: 'hash-only' },
      { name: 'amountMinor', type: 'number', required: true,
        min: 0, max: 50_000_00 },
      { name: 'currency', type: 'enum', required: true,
        enumValues: ['EUR', 'GBP'] },
      { name: 'psp90DayFraudRateBps', type: 'number', required: true,
        min: 0, max: 1000 },
      { name: 'beneficiaryRelationship', type: 'enum', required: true,
        enumValues: ['new', 'trusted', 'corporate'] },
      { name: 'transactionRiskScore', type: 'number', required: true,
        min: 0, max: 1 },
    ],
  },

  outputSchema: {
    fields: [
      { name: 'verdict', type: 'enum', required: true,
        enumValues: ['exempt', 'apply-sca'] },
      { name: 'exemptionCategory', type: 'enum', required: true,
        enumValues: [
          'low-value-art-16',
          'tra-art-18-tier-1',
          'tra-art-18-tier-2',
          'corporate-art-17',
          'trusted-beneficiary-art-13',
          'not-applicable',
        ] },
      { name: 'confidence', type: 'number', required: true,
        min: 0, max: 1 },
      { name: 'reasonCode', type: 'string', required: true,
        maxLength: 80 },
    ],
  },

  promptTemplate: {
    system:
      'You decide SCA exemption eligibility under PSD2 RTS on SCA. ' +
      'Be conservative — when in doubt, apply SCA. ' +
      'Exemption category must match the actual reason. ' +
      'Verdict "exempt" requires confidence ≥ 0.85.',
    user:
      'Payment {{paymentId}}: {{amountMinor}} {{currency}}. ' +
      'PSP 90-day fraud rate: {{psp90DayFraudRateBps}} bps. ' +
      'Beneficiary: {{beneficiaryRelationship}}. ' +
      'Transaction risk score: {{transactionRiskScore}}.',
  },

  modelIdentity: {
    provider: 'anthropic',
    model: 'claude-sonnet-4-5',
    version: '20250929',
  },

  reviewerGate: 'on-low-confidence',
  lowConfidenceThreshold: 0.85,
  maxLatencyMs: 600,
  fallbackBehavior: 'deterministic-default',
  deterministicDefault: {
    verdict: 'apply-sca',
    exemptionCategory: 'not-applicable',
    confidence: 0,
    reasonCode: 'fallback-apply-sca',
  },
};

Regulations addressed

This template's configuration choices map to specific regulatory obligations. The substrate doesn't certify compliance — but the spec hash + reviewer-verdict + modelIdentity per L12 entry give you the evidence layer for these citations:

  • ·PSD2 RTS on SCA — Arts. 16-18 exemption regime
  • ·Proposed PSR Arts. 85–89 — SCA + risk-based exemptions, per-decision documentation
  • ·EBA Guidelines on fraud reporting (EBA/GL/2020/01)

See citations index for official source URLs →

Installation + usage

  1. Create a free Dev-tier workspace — API key + Ed25519 signing key issued instantly.
  2. Install the SDK: npm install https://promethean.software/runtime-ai/latest.tgz.
  3. Paste the template above into your codebase. Adjust modelIdentity + prompt for your context.
  4. Call runConstrainedAI(spec, input, { client, receiptLogPath, productId, signingKey }) from your service code. For local testing pass createMockRuntimeAIClient(spec); for production, an Anthropic / OpenAI / Azure adapter.
  5. Verify the chain with the Apache-2.0 verifier.