Перейти до основного вмісту

Adapter contract

The PlatformAdapter interface is the seam between UCRM and your casino platform. Every casino platform has its own bonus engine, KYC flow, and webhook scheme; we don't try to be every platform's API — we provide a stable contract that platforms implement once.

For the full spec, see Adapter integration. This page is the conceptual overview.

Interface

interface PlatformAdapter {
readonly slug: string; // 'acme-prod', 'zero', ...
readonly displayName: string;
readonly capabilities: AdapterCapabilities; // declares what it supports

bonus?: BonusOps; // grantBonus, cancelBonus, getBonusStatus
kyc?: KYCOps; // initiateKYC, queryKYCStatus, updateKYCStatus
rg?: ResponsibleGamingOps; // setSelfExclusion, setLimit, etc.
wallet?: WalletOps; // getBalance, snapshot streams
}

Each ops bag is optional. An adapter that doesn't support KYC just leaves kyc undefined — the registry won't route any KYC ops to it.

Capabilities

Every adapter declares static capabilities:

interface AdapterCapabilities {
verticals: readonly Vertical[]; // casino, sportsbook, ...
bonus: { issue, cancel, query_status } // booleans
kyc: { initiate, query, update, webhooks }
rg_features: readonly RGFeature[];
wallet: { balance_pull, balance_push }
signature_scheme: "hmac_sha256" | "hmac_sha512" | "rsa";
}

Effective capabilities = tenant.config ∩ adapter.capabilities. If the tenant wants deposit_limit_daily but the adapter doesn't support it, the feature falls back to CRM-only enforcement (capability_mock pattern) — the limit is tracked in CRM, but the platform isn't told about it.

Bidirectional flow

Every domain (bonus / KYC / RG) follows the same pattern:

CRM → Adapter (outbound):

  • Sync HTTP call from the bonus engine / admin action.
  • Returns platform_*_id we persist for correlation.

Adapter → CRM (inbound):

  • Webhook hits POST /v1/adapters/:slug/webhooks/{bonus,kyc}-events.
  • HMAC-SHA256 over <timestamp>.<body> (Stripe-compatible).
  • Idempotency dedupe via webhook_events_processed (adapter_slug, event_id).
  • State sync: lifecycle events update domain state under RLS context.

Adapter Zero — the reference

Adapter Zero is the in-process synthetic adapter we ship for testing + demos. It declares maximum capabilities (every vertical, every KYC flow, every RG feature) so tests exercise the full surface. Real-platform adapters declare narrower capabilities — what the platform actually supports.

Adapter Zero plays both sides: when CRM calls adapter.bonus.grantBonus(), AdapterZero queues a synthetic webhook back through the receiver via fastify.inject(). Same code paths as a real HTTP roundtrip — HMAC verification, idempotency, state sync — without the network.

Adding a new adapter

Three steps:

  1. Create services/adapters/<your-platform>/ with the canonical event mapping (your platform's events → UCRM canonical events).
  2. Implement the PlatformAdapter interface in apps/api/src/lib/bonus-adapter-<your-platform>.ts (or your own service).
  3. Register the adapter by slug in bonus-adapter-registry.ts + add the HMAC secret resolver in bonus-webhooks.ts.

That's it. A complete adapter is ~200-400 lines of TypeScript.