"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const node_test_1 = require("node:test"); const strict_1 = __importDefault(require("node:assert/strict")); const MockHybxClient_1 = require("./hybx/MockHybxClient"); const config_1 = require("./hybx/config"); const ComplianceDecisionEngine_1 = require("./compliance/ComplianceDecisionEngine"); const AuditEvent_1 = require("./audit/AuditEvent"); const idempotency_1 = require("./resilience/idempotency"); const CanonicalFinancialEvent_1 = require("./iso20022/CanonicalFinancialEvent"); const RegulatedEntity_1 = require("./entities/RegulatedEntity"); const verifySignature_1 = require("./webhooks/verifySignature"); const HttpHybxClient_1 = require("./hybx/HttpHybxClient"); const ReconciliationStatus_1 = require("./reconciliation/ReconciliationStatus"); const circuitBreaker_1 = require("./resilience/circuitBreaker"); (0, node_test_1.describe)('MockHybxClient', () => { (0, node_test_1.it)('returns typed mock payment response', async () => { const client = new MockHybxClient_1.MockHybxClient('sandbox'); const res = await client.initiatePayment({ idempotencyKey: 'key-001', entityId: 'ent-1', tenantId: 'tenant-a', amount: '100.00', currency: 'USD', debtorAccountRef: 'debtor-1', creditorAccountRef: 'creditor-1', }); strict_1.default.equal(res.status, 'accepted'); strict_1.default.ok(res.paymentId.startsWith('mock-pay-')); strict_1.default.ok(res.uetr); }); }); (0, node_test_1.describe)('loadHybxConfig', () => { (0, node_test_1.it)('loads sandbox placeholders', () => { const cfg = (0, config_1.loadHybxConfig)({ testMode: true, env: { HYBX_ENVIRONMENT: 'sandbox', HYBX_BASE_URL: 'https://hybx-sandbox.example.invalid', HYBX_CLIENT_ID: 'placeholder', HYBX_CLIENT_SECRET: 'placeholder', HYBX_API_KEY: 'placeholder', HYBX_WEBHOOK_SECRET: 'placeholder', }, }); strict_1.default.equal(cfg.environment, 'sandbox'); }); (0, node_test_1.it)('rejects production in test mode', () => { strict_1.default.throws(() => (0, config_1.loadHybxConfig)({ testMode: true, env: { HYBX_ENVIRONMENT: 'production', HYBX_BASE_URL: 'https://x' }, })); }); }); (0, node_test_1.describe)('MockComplianceDecisionEngine', () => { (0, node_test_1.it)('blocks sanctions hits', async () => { const engine = new ComplianceDecisionEngine_1.MockComplianceDecisionEngine(); const res = await engine.evaluateTransaction({ entityId: 'e1', tenantId: 't1', amount: '10', currency: 'USD', transactionType: 'payment', riskHints: ['sanctions_hit'], }); strict_1.default.equal(res.decision, 'block'); }); (0, node_test_1.it)('reviews PEP matches', async () => { const engine = new ComplianceDecisionEngine_1.MockComplianceDecisionEngine(); const res = await engine.evaluateTransaction({ entityId: 'e1', tenantId: 't1', amount: '10', currency: 'USD', transactionType: 'payment', riskHints: ['pep_match'], }); strict_1.default.equal(res.decision, 'review'); }); }); (0, node_test_1.describe)('audit redaction', () => { (0, node_test_1.it)('removes secret-like and PII-like fields', () => { const redacted = (0, AuditEvent_1.redactMetadata)({ api_key: 'sk-test-dummy', email: 'user@example.com', amount: '100', }); strict_1.default.equal(redacted.api_key, '[REDACTED]'); strict_1.default.equal(redacted.email, '[REDACTED]'); strict_1.default.equal(redacted.amount, '100'); }); (0, node_test_1.it)('creates audit event with redacted metadata', () => { const evt = (0, AuditEvent_1.createAuditEvent)({ audit_event_id: 'a1', actor_type: 'service', actor_id: 'svc-1', tenant_id: 't1', entity_id: 'e1', action: 'payment.initiated', resource_type: 'payment', resource_id: 'p1', metadata: { client_secret: 'dummy-secret' }, }); strict_1.default.equal(evt.metadata_redacted.client_secret, '[REDACTED]'); }); }); (0, node_test_1.describe)('idempotency', () => { (0, node_test_1.it)('returns stable keys for identical inputs', () => { const input = { tenantId: 't1', entityId: 'e1', operation: 'payment', payload: { amount: '10' }, }; strict_1.default.equal((0, idempotency_1.deriveIdempotencyKey)(input), (0, idempotency_1.deriveIdempotencyKey)(input)); }); (0, node_test_1.it)('returns distinct keys for distinct inputs', () => { const a = (0, idempotency_1.deriveIdempotencyKey)({ tenantId: 't1', entityId: 'e1', operation: 'payment', }); const b = (0, idempotency_1.deriveIdempotencyKey)({ tenantId: 't2', entityId: 'e1', operation: 'payment', }); strict_1.default.notEqual(a, b); }); }); (0, node_test_1.describe)('CanonicalFinancialEvent', () => { const valid = { schema_version: '1.0', message_id: 'msg-1', end_to_end_id: 'e2e-1', debtor: { id: 'd1' }, creditor: { id: 'c1' }, amount: '100.00', currency: 'USD', source_system: 'hybx', target_system: 'omnl', entity_id: 'e1', tenant_id: 't1', }; (0, node_test_1.it)('validates required fields', () => { strict_1.default.equal((0, CanonicalFinancialEvent_1.validateCanonicalFinancialEvent)(valid).valid, true); strict_1.default.equal((0, CanonicalFinancialEvent_1.validateCanonicalFinancialEvent)({}).valid, false); }); }); (0, node_test_1.describe)('tenant isolation', () => { (0, node_test_1.it)('throws on tenant mismatch', () => { strict_1.default.throws(() => (0, RegulatedEntity_1.assertTenantIsolation)('t1', 't2')); }); }); (0, node_test_1.describe)('HttpHybxClient', () => { (0, node_test_1.it)('refuses production environment', () => { strict_1.default.throws(() => new HttpHybxClient_1.HttpHybxClient({ testMode: false, config: { environment: 'production', baseUrl: 'https://hybx.example.invalid', clientId: 'p', clientSecret: 'p', apiKey: 'p', webhookSecret: 'p', requestTimeoutMs: 1000, maxRetries: 1, }, }), /refuses production/); }); (0, node_test_1.it)('parses webhook payload shape', () => { const client = new HttpHybxClient_1.HttpHybxClient({ testMode: true, config: { environment: 'sandbox', baseUrl: 'https://hybx-sandbox.example.invalid', clientId: 'placeholder', clientSecret: 'placeholder', apiKey: 'placeholder', webhookSecret: 'placeholder', requestTimeoutMs: 1000, maxRetries: 1, }, }); const parsed = client.parseWebhookPayload(JSON.stringify({ eventType: 'settlement.completed', eventId: 'evt-1', data: { amount: '100' } })); strict_1.default.equal(parsed.eventType, 'settlement.completed'); strict_1.default.equal(parsed.eventId, 'evt-1'); strict_1.default.equal(parsed.data.amount, '100'); }); }); (0, node_test_1.describe)('MockReconciliationEngine', () => { (0, node_test_1.it)('detects missing fineract refs', async () => { const engine = new ReconciliationStatus_1.MockReconciliationEngine(); const snap = await engine.reconcileTripleState({ tenantId: 't1', entityId: 'e1', hybxRefs: ['ref-1'], fineractRefs: [], chainRefs: ['ref-1'], }); strict_1.default.equal(snap.status, 'breaks_found'); strict_1.default.ok(snap.breaks.length >= 1); }); }); (0, node_test_1.describe)('CircuitBreaker', () => { (0, node_test_1.it)('opens after threshold failures', async () => { const cb = new circuitBreaker_1.CircuitBreaker({ failureThreshold: 2, resetTimeoutMs: 60_000 }); const fail = () => cb.execute(async () => { throw new Error('fail'); }); await strict_1.default.rejects(fail); await strict_1.default.rejects(fail); strict_1.default.equal(cb.getState(), 'open'); }); }); (0, node_test_1.describe)('webhook verification', () => { (0, node_test_1.it)('verifies HMAC signature', () => { const secret = 'test-webhook-secret-dummy'; const payload = '{"event":"payment.settled"}'; const sig = (0, verifySignature_1.computeWebhookSignature)(secret, payload); strict_1.default.equal((0, verifySignature_1.verifyWebhookSignature)({ secret, payload, signature: sig }), true); strict_1.default.equal((0, verifySignature_1.verifyWebhookSignature)({ secret, payload, signature: 'bad' }), false); }); (0, node_test_1.it)('verifies sha256= prefixed OMNL-style signatures', () => { const secret = 'omnl-webhook-secret'; const payload = '{"event":"ReserveCommitted"}'; const sig = `sha256=${(0, verifySignature_1.computeWebhookSignature)(secret, payload)}`; strict_1.default.equal((0, verifySignature_1.verifyWebhookSignature)({ secret, payload, signature: sig }), true); }); });