6.9 KiB
Customer identity verification
Task SXCHNGE #48, following sign-up Facts intake. Platform implementation: Sendico #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 before this task's branch. Deploy the Sendico identity-proofs PR before using this flow. The platform change reuses the Limits assignment contract being developed in Sendico #2884; its PR documents the shared scope and merge order. No merge or deployment is automatic.
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.