Some checks failed
CI / Frontend Lint (push) Has been cancelled
CI / Frontend Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Frontend E2E Tests (push) Has been cancelled
CI / Orchestrator Build (push) Has been cancelled
CI / Orchestrator Unit Tests (push) Has been cancelled
CI / Orchestrator E2E (Testcontainers) (push) Has been cancelled
CI / Contracts Compile (push) Has been cancelled
CI / Contracts Test (push) Has been cancelled
Security Scan / Dependency Vulnerability Scan (push) Has been cancelled
Security Scan / OWASP ZAP Scan (push) Has been cancelled
113 lines
2.9 KiB
TypeScript
113 lines
2.9 KiB
TypeScript
import type { Plan } from "../types/plan";
|
|
import { generatePacs008 } from "./iso20022";
|
|
import { logger } from "../logging/logger";
|
|
|
|
/**
|
|
* Bank-instruction client — two-phase-commit adapter for the payment
|
|
* leg (arch §4.3 Payment Messaging / Settlement Layer).
|
|
*
|
|
* Until `d-bis/dbis_core` is reachable as a live API, every call here
|
|
* is a deterministic mock. That corresponds to blocker EXT-DBIS-CORE
|
|
* in proxmox/docs/03-deployment/EXTERNAL_DEPENDENCY_BLOCKERS.md and
|
|
* flips to real once DBIS_CORE_URL is set (see services/dbisCore/).
|
|
*/
|
|
const BLOCKER_ID = "EXT-DBIS-CORE";
|
|
|
|
function bankMode(): "live" | "mock" {
|
|
return process.env.DBIS_CORE_URL ? "live" : "mock";
|
|
}
|
|
|
|
/**
|
|
* Prepare bank instruction (2PC prepare phase)
|
|
* Sends provisional ISO-20022 message
|
|
*/
|
|
export async function prepareBankInstruction(plan: Plan): Promise<boolean> {
|
|
const mode = bankMode();
|
|
logger.info(
|
|
{
|
|
planId: plan.plan_id,
|
|
mode,
|
|
...(mode === "mock" ? { blockerId: BLOCKER_ID } : {}),
|
|
},
|
|
"[Bank] prepareBankInstruction()",
|
|
);
|
|
|
|
// Mock: In real implementation, this would:
|
|
// 1. Generate provisional ISO-20022 message (pacs.008 with conditional settlement)
|
|
// 2. Send to bank connector
|
|
// 3. Receive provisional acceptance
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Commit bank instruction (2PC commit phase)
|
|
* Confirms final settlement
|
|
*/
|
|
export async function commitBankInstruction(plan: Plan): Promise<{
|
|
success: boolean;
|
|
isoMessageId?: string;
|
|
error?: string;
|
|
}> {
|
|
const mode = bankMode();
|
|
logger.info(
|
|
{
|
|
planId: plan.plan_id,
|
|
mode,
|
|
...(mode === "mock" ? { blockerId: BLOCKER_ID } : {}),
|
|
},
|
|
"[Bank] commitBankInstruction()",
|
|
);
|
|
|
|
try {
|
|
// Generate final ISO-20022 message
|
|
const isoMessage = await generatePacs008(plan);
|
|
|
|
// Mock: In real implementation, this would:
|
|
// 1. Send ISO message to bank connector
|
|
// 2. Receive confirmation and message ID
|
|
// 3. Store message ID for audit trail
|
|
|
|
const isoMessageId = `MSG-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
|
|
// Simulate processing delay
|
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
|
|
return {
|
|
success: true,
|
|
isoMessageId,
|
|
};
|
|
} catch (err) {
|
|
const error = err instanceof Error ? err.message : String(err);
|
|
return {
|
|
success: false,
|
|
error,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Abort bank instruction (2PC abort phase)
|
|
* Cancels provisional instruction
|
|
*/
|
|
export async function abortBankInstruction(planId: string): Promise<void> {
|
|
const mode = bankMode();
|
|
logger.info(
|
|
{
|
|
planId,
|
|
mode,
|
|
...(mode === "mock" ? { blockerId: BLOCKER_ID } : {}),
|
|
},
|
|
"[Bank] abortBankInstruction()",
|
|
);
|
|
|
|
// Mock: In real implementation, this would:
|
|
// 1. Generate cancellation message (camt.056)
|
|
// 2. Send to bank connector
|
|
// 3. Confirm cancellation
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
}
|