125 lines
7.3 KiB
Markdown
125 lines
7.3 KiB
Markdown
# Customer identity verification
|
||
|
||
Task [SXCHNGE #48](https://git.sendico.io/tech/sxchnge/issues/48), following
|
||
[sign-up Facts intake](signup-facts.md). Platform implementation:
|
||
[Sendico #2885](https://git.sendico.io/tech/sendico/issues/2885).
|
||
|
||
## Customer flow
|
||
|
||
Sign-up still creates a basic account and submits its initial name/email/customer
|
||
reference as immutable facts. Email verification and login remain independent of
|
||
identity proof collection. After the first authenticated login in an app session,
|
||
an unverified customer is offered verification and can choose **Keep basic
|
||
limits**. An unavailable optional identity dependency does not prevent login.
|
||
**Accounts → Identity verification**, **Limits**, and the existing identity
|
||
navigation let the customer return later.
|
||
|
||
The customer supplies their full legal name, date of birth (YYYY-MM-DD), country
|
||
of residence, an ID document photo and a selfie holding that same document. The
|
||
backend supplies the authenticated customer's email and reference. The client
|
||
cannot choose a platform subject, organization, source principal, review status
|
||
or limits profile. JPEG/PNG photos must decode, be at least 600×600, at most
|
||
40 megapixels and no larger than 10 MiB each. Sendico also enforces its existing
|
||
configured evidence cap, MIME/extension rules and submission rate limits.
|
||
|
||
Unsent fields and photos stay in memory, survive retryable errors and are cleared
|
||
on successful submission, discard or page disposal. Previews leave Flutter's
|
||
image cache on exit/replacement. Profile edits or photo replacements create a
|
||
new request key; unchanged retries retain their key. Draft loss requires an
|
||
explicit discard choice. No sensitive extras enter browser history or analytics.
|
||
|
||
A successful submission means **pending staff review**. Corrections permit a new
|
||
submission; rejection retains basic access and the existing support route. A
|
||
recorded approval with an unfinished limits assignment is shown as **Limits
|
||
upgrade pending**, rather than verified. Refresh fetches the real reviewed state
|
||
and the authoritative limits. Production uses no simulated KYC review controls
|
||
or illustrative limit amounts. Demo mode remains separately simulated.
|
||
|
||
## Boundaries and contracts
|
||
|
||
The authenticated local routes are `GET/POST /accounts/identity` and
|
||
`GET /accounts/limits`, under the configured API mount. Multipart POST fields are
|
||
`profile` (JSON), `document`, `selfie`, and `idempotencyKey`. A customer ID is
|
||
always resolved from the full authenticated session. Pending-login tokens do not
|
||
provide account access. Browser and native requests both carry the access token;
|
||
browser refresh cookies remain an auth concern.
|
||
|
||
The existing `signup_facts` binding resolves each local customer to one independent
|
||
Sendico subject. A conditional unique `(namespace, subjectRef)` index prevents
|
||
binding the same provider subject to two customers. Empty registration claims
|
||
are excluded. Existing duplicates cause bootstrap to fail and require controlled
|
||
reconciliation; the application never guesses a replacement subject. Credential
|
||
rotation must retain the configured source account.
|
||
|
||
The Sendico adapter exclusively uses public HTTP:
|
||
|
||
- `GET/POST /identity_facts/{organization}/proofs/{subject}`;
|
||
- `GET /identity_facts/{organization}/proofs/{subject}/limits`.
|
||
|
||
Adapter DTOs and mappers remain separate from local models and local HTTP DTOs.
|
||
There are no Sendico database, gRPC, bus or sibling-module imports in SXCHNGE.
|
||
Provider organization/source settings remain in the adapter configuration.
|
||
Uploads have a bounded 60-second upstream timeout and redirects are rejected.
|
||
Upstream error bodies and photo bytes are never logged. Rate-limit responses
|
||
retain typed recovery. Registration's existing non-idempotent reconciliation
|
||
rules are unchanged.
|
||
|
||
Visible policy entries retain exact decimal strings, currency, group labels and
|
||
per-operation minimum/maximum, day and month slots. Usage is not invented for
|
||
per-operation slots. The backend owns the effective policy and remaining
|
||
capacity. The existing wallet remains a simulated service; this contribution
|
||
connects identity and visible limits, not real money movement. Future money
|
||
adapters must use the platform-owned customer account resource and authoritative
|
||
Limits reservation path, not a browser-selected policy or displayed balance.
|
||
|
||
## Review and rollout
|
||
|
||
Staff work in the existing **Sendico backoffice → KYC → Identity proof review**.
|
||
The platform stores private proofs, immutable profile assertions, review history
|
||
and the reviewed limits assignment. See the platform's
|
||
`docs/customer-identity-proofs.md` for authorization, retry and retention details.
|
||
|
||
Deploy Sendico Product/provider, Backoffice, Limits and backoffice frontend
|
||
changes together before enabling the new SXCHNGE frontend/backend adapters.
|
||
Existing `api.sendico` settings are reused. The integration account needs
|
||
organization read/update access. The platform's existing evidence/storage,
|
||
cleanup, discovery and limits configuration must be provisioned. Its ACCOUNT
|
||
default for SXCHNGE must be the existing unverified profile, and the existing
|
||
verified profile and personal-account visible view must be active. No new runtime
|
||
configuration parameters or live submissions are introduced by this work.
|
||
|
||
Merge [SXCHNGE sign-up Facts PR #47](https://git.sendico.io/tech/sxchnge/pulls/47)
|
||
before [this flow's PR #49](https://git.sendico.io/tech/sxchnge/pulls/49).
|
||
For the combined existing backoffice, apply
|
||
[Sendico identity-proofs PR #2886](https://git.sendico.io/tech/sendico/pulls/2886)
|
||
before [Facts review PR #2887](https://git.sendico.io/tech/sendico/pulls/2887).
|
||
They share one Limits assignment contract and retain both review destinations.
|
||
Proof cases go to Identity proof review; generic Facts review cannot link them
|
||
to a login account or assign limits through that path. Deploy the reconciled
|
||
Sendico services and frontend before using this flow. Deployment is separate.
|
||
|
||
## UX, measurement and validation
|
||
|
||
Existing KYC journey events measure preparation, selection, accepted submission,
|
||
status reads, retries, abandonment and latency. Profile contents, filenames,
|
||
photo bytes and credentials are excluded. Submission success is an intake
|
||
outcome, not proof of approval. Pending asynchronous staff review is not counted
|
||
as customer abandonment. A resumed route starts a new client attempt; immutable
|
||
submission IDs deduplicate backend business outcomes.
|
||
|
||
Authoritative completion is the staff decision plus the Limits assignment
|
||
receipt for that submission. Backend IDs correlate these records without becoming
|
||
metric labels. Existing identity request counters/histograms distinguish accepted,
|
||
invalid, denied, conflict, rate-limited and unavailable operations and include
|
||
actual authorization/I/O duration. Client analytics still defaults to the
|
||
existing in-memory sink; retained cross-device analytics depends on deployment.
|
||
|
||
Review covers optional onboarding, later account navigation, editable profile,
|
||
readable ID/selfie guidance, disabled actions, error/session recovery, input
|
||
preservation, correction/rejection/pending/approval, exact monetary presentation,
|
||
EN/RU at narrow widths and large text, keyboard access and private-image cache
|
||
eviction. Tests use synthetic data, local HTTP servers and disposable MongoDB.
|
||
No live ID documents, live email, production review or deployment were exercised.
|
||
Full validation commands and final PR links are recorded in `implementation.md`
|
||
and the task.
|