Files
sxchnge/docs/architecture/bff.md

136 lines
8.4 KiB
Markdown

# SXCHNGE BFF and Sendico public API boundary
SXCHNGE is one organization in Sendico, just like any other organization.
SXCHNGE owns its customers, registration, credentials, sessions, profile settings
and application UX. Sendico is the financial platform. All provider access goes
through its public HTTP API using SXCHNGE's organization and an integration
principal. A customer is not a Sendico organization or the integration principal.
This replaces the earlier proposal for a new BFF shell and delegated Sendico
customer provisioning. The starting point is copied Sendico BFF code, maintained
and allowed to diverge within this repository.
## Copied starting point
Source: `S_I/sendico`, commit `8bb20dcd622dd8eb92d289b6b34411e7eccab083`.
The source checkout's unrelated dependency edits were not copied.
`backend/` groups Go modules. The implemented executable is `backend/product`,
with its own `main.go` and `go.mod`. `backend/shared` is a separate library module.
Backoffice will be a separate executable module (`backend/backoffice`) with its
own entry point, operator identity, configuration and deployment. Product's entry
point is not the entry point for every future backend.
| Owner | Retained implementation |
| --- | --- |
| `product/app` | HTTP runtime, startup, composition and health |
| `product/customers` | Local customer models, service and account repository |
| `product/auth` | Login/protected routes, local DTOs/mappers and auth configuration |
| `product/sessions` | Session/client models, refresh storage, cookies and token generation |
| `product/verification` | Verification models, configuration and storage |
| `shared` | Generic database/transaction/query code, errors, logging and HTTP helpers |
Shared infrastructure imports no executable module. Customer repositories are
constructed by the product module rather than the generic database factory.
There is no global customer/session model package or Sendico `edge/product`
source hierarchy. Source provenance follows the moved files across Go modules.
Local customers have no organization membership, roles, policies or tenant ID.
Creation validates/hashes passwords and commits the account and activation token
atomically. Deletion revokes that customer's sessions. The runtime starts without
any seed. Casbin, invitations and platform provisioning are absent.
## Identity and ownership
Keep three distinct identifiers:
1. The configured SXCHNGE Sendico organization reference.
2. SXCHNGE's backend integration principal, with the public API permissions it needs.
3. The authenticated local customer and its persisted provider resource references.
The browser supplies neither the authoritative organization nor customer owner.
Resolve both from server configuration and the authenticated local customer.
Validate ownership before returning balances/history or submitting operations.
Never give a customer organization-wide data because the integration principal
can see it. Do not pass SXCHNGE customer passwords or session tokens to Sendico.
Sendico's `/accounts/login/api` is an existing password/client-secret grant with
client/account binding and IP policy, not a generic OAuth client-credentials flow.
Its tokens are server-side platform credentials, separate from customer sessions.
Confirm the deployed credential policy before configuring a provider client.
## Contract and service structure
The bootstrap has no Sendico runtime calls and therefore no copied public wire
snapshot. When implementing an adapter, keep only its consumed request/response
contracts within that adapter. Pin their upstream revision separately from local
customer DTOs/models; do not copy the entire platform contract or synchronize
source automatically.
When wiring a feature, keep the existing architecture:
`app DTO → mapper → service → data model → provider → UI`
On the backend, local HTTP request/response DTOs map into account/application
services. A Sendico adapter maps those local models to/from the public HTTP wire
contract. Only the adapter handles provider URLs, credentials, response envelopes
and provider-specific errors. Do not expose provider wire types in Flutter models
or replace local account services with Sendico login/customer calls.
The next adapter will use a configured public HTTPS base URL, a fixed organization
reference, bounded request timeouts and an injected HTTP transport. It must reject
cross-origin credential redirects. Use the public contract and response
conventions for each implemented operation; do not invent a parallel provider facade or call internal services.
## Required public Sendico capabilities
The source reviewed at the pinned revision describes API version 4.2.37. Its
public routes and schemas establish available shapes; they do not prove that a deployment enables every feature.
| Need | Existing public surface / work required |
| --- | --- |
| Integration session | `/accounts/login/api`, `/accounts/refresh`, `/accounts/rotate`; provision SXCHNGE integration credentials and permissions |
| Organization context | `/organizations` and organization lookup; configure the existing SXCHNGE organization, no customer organization provisioning |
| Currency accounts and history | Organization-scoped ledger account listing, balance and operation routes; confirm supported external-customer ownership and available-balance semantics |
| Top-up instructions | Wallets, assets and ledger inbound-route HTTP handlers; confirm customer allocation, expiry, observed versus credited states, fees and settlement callbacks |
| Exchange and payout | Public quote/multiquote, by-quote execution, payment lookup/history, payment methods and recipients; verify external-customer resource scope and idempotent retry/reconciliation behavior |
| KYC and limits usage | Product has `/accounts/compliance`, `/accounts/compliance/evidence`, `/accounts/compliance/submit`; they use the authenticated Sendico account and organization ownership. A supported public external-customer contract is needed for SXCHNGE customers |
| Manual review | Agree on public submission/status/reason contracts for passport plus passport-selfie review, resubmission and denial; do not invoke internal case/KYC services directly |
| Status updates | Public callback subscription and signing contracts exist. Confirm supported events, replay, deduplication and reconciliation before relying on them |
Required platform capabilities stay inside Sendico: ledger, quotation/execution,
receiving routes, payment methods/rails, KYC decisions, policy and limit enforcement.
If the public API lacks a needed capability, extend that public API in a separate
Sendico task. No private transport fallback is allowed.
## Next wiring sequence
1. Wire local signup, verification delivery/completion and profile endpoints onto
the copied account and verification services. Configure the SXCHNGE application
client for web/native sessions; keep signup independent of Sendico availability.
Never add local organization, membership, role or policy requirements.
2. Implement the public HTTP adapter and confirm organization/resource scoping
with the integration principal. Agree on external-customer contracts where the
existing public API assumes a Sendico account.
3. Wire read-only accounts, available funds, operation history and usage/limits.
Return local models to the existing shared Flutter services/providers.
4. Wire top-up, quote/review, exchange/payout execution and reconciliation with
local two-factor approval bound to the exact operation and idempotency key.
5. Wire KYC uploads/status/review and callback processing through public APIs.
Before enabling money operations, test customer isolation within the same
organization, expired credentials/quotes, denied KYC, exhausted limits, duplicate
submission, timeout-after-acceptance and delayed settlement. An uncertain response
must remain pending until reconciled. UI balances show available funds, while
operation details explain what has happened and what remains pending.
## Current delivery boundary
This task supplies the selected copied starting point in independently buildable
Go modules and a public API integration plan.
The local runtime installs the existing authentication transport and account
service. Local signup/profile HTTP endpoints, verification delivery/completion,
application client setup, Flutter HTTP adapters and live Sendico calls
are not connected yet. The frontend continues using its existing dummy services.
No new provider organization, customer or payment has been created.