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: }