From 4a00352dcad4bced9b7ad212391449e49eedbe33 Mon Sep 17 00:00:00 2001 From: "@tanya_r" Date: Fri, 19 Jun 2026 15:09:28 -0300 Subject: [PATCH] feat(devex): add the compliance service to the bruno api collection Extend the importable API collection with the KYC and case endpoints so the compliance service is explorable alongside ledger, payments and decision: initiate and read a KYC session, and open, list, read, claim, resolve and escalate a case. Requests mirror the existing folders - bearer from the environment, an Idempotency-Key on session initiation, read and write scopes documented per request. The sandbox environment gains a compliance base URL and the new resource id variables, and the README is updated. Closes #303 --- api/collection/README.md | 22 ++++++++------- api/collection/compliance/Claim case.bru | 19 +++++++++++++ api/collection/compliance/Escalate case.bru | 19 +++++++++++++ api/collection/compliance/Get KYC session.bru | 19 +++++++++++++ api/collection/compliance/Get case.bru | 19 +++++++++++++ .../compliance/Initiate KYC session.bru | 27 +++++++++++++++++++ api/collection/compliance/List cases.bru | 23 ++++++++++++++++ api/collection/compliance/Open case.bru | 26 ++++++++++++++++++ api/collection/compliance/Resolve case.bru | 19 +++++++++++++ api/collection/environments/sandbox.bru | 3 +++ 10 files changed, 186 insertions(+), 10 deletions(-) create mode 100644 api/collection/compliance/Claim case.bru create mode 100644 api/collection/compliance/Escalate case.bru create mode 100644 api/collection/compliance/Get KYC session.bru create mode 100644 api/collection/compliance/Get case.bru create mode 100644 api/collection/compliance/Initiate KYC session.bru create mode 100644 api/collection/compliance/List cases.bru create mode 100644 api/collection/compliance/Open case.bru create mode 100644 api/collection/compliance/Resolve case.bru diff --git a/api/collection/README.md b/api/collection/README.md index 7d34070..69d1813 100644 --- a/api/collection/README.md +++ b/api/collection/README.md @@ -1,18 +1,19 @@ # FinCore Engine API collection -An importable [Bruno](https://www.usebruno.com/) collection covering the implemented ledger, payments and decision -endpoints, for exploring a local sandbox. Bruno is open source and stores requests as plain text, so the collection is -diffable and reviewable. Postman and Insomnia can import a Bruno collection if you prefer those tools. +An importable [Bruno](https://www.usebruno.com/) collection covering the implemented ledger, payments, decision and +compliance (KYC + cases) endpoints, for exploring a local sandbox. Bruno is open source and stores requests as plain +text, so the collection is diffable and reviewable. Postman and Insomnia can import a Bruno collection if you prefer +those tools. ## Use 1. Install Bruno, then open this folder (`api/collection`) as a collection. 2. Select the **sandbox** environment and set its variables: - - `ledgerUrl`, `paymentsUrl`, `decisionUrl` - base URLs (defaults target the local compose stack). + - `ledgerUrl`, `paymentsUrl`, `decisionUrl`, `complianceUrl` - base URLs (defaults target the local compose stack). - `token` - a bearer JWT with the required scopes. **Empty by default**; the sandbox compose stack does not run an identity provider, so obtain a token from your own Keycloak (or run the services against one) before calling the authenticated endpoints. - - resource ids (`accountId`, `secondAccountId`, `transactionId`, `paymentId`) - fill in after creating a resource. + - resource ids (`accountId`, `secondAccountId`, `transactionId`, `paymentId`, `kycSessionId`, `caseId`) - fill in after creating a resource. - `webhookSignature` - empty by default; see Webhooks below. ## Scopes @@ -22,9 +23,10 @@ diffable and reviewable. Postman and Insomnia can import a Bruno collection if y | Ledger | `ledger:read` | `ledger:write` | | Payments | `payments:read` | `payments:write` | | Decision | `decision:read` | `decision:write` | +| Compliance | `compliance:read` | `compliance:write` | -Mutating ledger requests (create account, post transaction, reverse) and payment initiation require an -`Idempotency-Key` header; the other endpoints do not. +Mutating ledger requests (create account, post transaction, reverse), payment initiation and KYC session initiation +require an `Idempotency-Key` header; the other endpoints do not. ## Webhooks @@ -34,8 +36,8 @@ signature computed from the body and the configured sandbox secret. The end-to-e ## Services and the sandbox -The sandbox compose stack runs ledger (`8080`) and payments (`8081`). The decision service is not part of that stack; -`decisionUrl` is a placeholder for running it separately. Endpoints that are specified but not yet implemented -(compliance/KYC, webhook subscriptions) are intentionally omitted. +The sandbox compose stack runs ledger (`8080`) and payments (`8081`). The decision and compliance services are not part +of that stack; `decisionUrl` (`8082`) and `complianceUrl` (`8083`) are placeholders for running them separately. +Webhook subscription endpoints are specified but not yet implemented and are intentionally omitted. SPDX-License-Identifier: BUSL-1.1 diff --git a/api/collection/compliance/Claim case.bru b/api/collection/compliance/Claim case.bru new file mode 100644 index 0000000..c514a33 --- /dev/null +++ b/api/collection/compliance/Claim case.bru @@ -0,0 +1,19 @@ +meta { + name: Claim case + type: http + seq: 6 +} + +post { + url: {{complianceUrl}}/v1/compliance/cases/{{caseId}}/claim + body: none + auth: none +} + +headers { + Authorization: Bearer {{token}} +} + +docs { + Scope: compliance:write. OPEN to CLAIMED, or 409 if the transition is illegal. +} diff --git a/api/collection/compliance/Escalate case.bru b/api/collection/compliance/Escalate case.bru new file mode 100644 index 0000000..0b33d8d --- /dev/null +++ b/api/collection/compliance/Escalate case.bru @@ -0,0 +1,19 @@ +meta { + name: Escalate case + type: http + seq: 8 +} + +post { + url: {{complianceUrl}}/v1/compliance/cases/{{caseId}}/escalate + body: none + auth: none +} + +headers { + Authorization: Bearer {{token}} +} + +docs { + Scope: compliance:write. Marks the case ESCALATED (from CLAIMED), or 409 if illegal. +} diff --git a/api/collection/compliance/Get KYC session.bru b/api/collection/compliance/Get KYC session.bru new file mode 100644 index 0000000..ac35aad --- /dev/null +++ b/api/collection/compliance/Get KYC session.bru @@ -0,0 +1,19 @@ +meta { + name: Get KYC session + type: http + seq: 2 +} + +get { + url: {{complianceUrl}}/v1/kyc/sessions/{{kycSessionId}} + body: none + auth: none +} + +headers { + Authorization: Bearer {{token}} +} + +docs { + Scope: compliance:read. Fill kycSessionId from a previous initiate response. +} diff --git a/api/collection/compliance/Get case.bru b/api/collection/compliance/Get case.bru new file mode 100644 index 0000000..d1375e5 --- /dev/null +++ b/api/collection/compliance/Get case.bru @@ -0,0 +1,19 @@ +meta { + name: Get case + type: http + seq: 5 +} + +get { + url: {{complianceUrl}}/v1/compliance/cases/{{caseId}} + body: none + auth: none +} + +headers { + Authorization: Bearer {{token}} +} + +docs { + Scope: compliance:read. Fill caseId from an open/list response. +} diff --git a/api/collection/compliance/Initiate KYC session.bru b/api/collection/compliance/Initiate KYC session.bru new file mode 100644 index 0000000..67fd708 --- /dev/null +++ b/api/collection/compliance/Initiate KYC session.bru @@ -0,0 +1,27 @@ +meta { + name: Initiate KYC session + type: http + seq: 1 +} + +post { + url: {{complianceUrl}}/v1/kyc/sessions + body: json + auth: none +} + +headers { + Authorization: Bearer {{token}} + Idempotency-Key: {{idempotencyKey}} + Content-Type: application/json +} + +body:json { + { + "subjectReference": "subject-001" + } +} + +docs { + Scope: compliance:write. Requires an Idempotency-Key. subjectReference is an opaque token (non-blank, max 140 chars); a repeat with the same key returns the original session. +} diff --git a/api/collection/compliance/List cases.bru b/api/collection/compliance/List cases.bru new file mode 100644 index 0000000..c4e5e34 --- /dev/null +++ b/api/collection/compliance/List cases.bru @@ -0,0 +1,23 @@ +meta { + name: List cases + type: http + seq: 4 +} + +get { + url: {{complianceUrl}}/v1/compliance/cases?status=OPEN + body: none + auth: none +} + +params:query { + status: OPEN +} + +headers { + Authorization: Bearer {{token}} +} + +docs { + Scope: compliance:read. status is required and must be one of OPEN, CLAIMED, ESCALATED, RESOLVED. +} diff --git a/api/collection/compliance/Open case.bru b/api/collection/compliance/Open case.bru new file mode 100644 index 0000000..f81ae95 --- /dev/null +++ b/api/collection/compliance/Open case.bru @@ -0,0 +1,26 @@ +meta { + name: Open case + type: http + seq: 3 +} + +post { + url: {{complianceUrl}}/v1/compliance/cases + body: json + auth: none +} + +headers { + Authorization: Bearer {{token}} + Content-Type: application/json +} + +body:json { + { + "reference": "case-ref-001" + } +} + +docs { + Scope: compliance:write. reference is an opaque token (non-blank, max 140 chars). Opens the case in the OPEN state. +} diff --git a/api/collection/compliance/Resolve case.bru b/api/collection/compliance/Resolve case.bru new file mode 100644 index 0000000..332b048 --- /dev/null +++ b/api/collection/compliance/Resolve case.bru @@ -0,0 +1,19 @@ +meta { + name: Resolve case + type: http + seq: 7 +} + +post { + url: {{complianceUrl}}/v1/compliance/cases/{{caseId}}/resolve + body: none + auth: none +} + +headers { + Authorization: Bearer {{token}} +} + +docs { + Scope: compliance:write. Marks the case RESOLVED (from CLAIMED or ESCALATED), or 409 if illegal. +} diff --git a/api/collection/environments/sandbox.bru b/api/collection/environments/sandbox.bru index 975246f..73a7458 100644 --- a/api/collection/environments/sandbox.bru +++ b/api/collection/environments/sandbox.bru @@ -2,6 +2,7 @@ vars { ledgerUrl: http://localhost:8080 paymentsUrl: http://localhost:8081 decisionUrl: http://localhost:8082 + complianceUrl: http://localhost:8083 token: idempotencyKey: demo-key-0001 webhookSignature: @@ -11,4 +12,6 @@ vars { paymentId: ruleKey: demo.approve inputHash: + kycSessionId: + caseId: }