KYC & User Management
This page covers user onboarding, the KYC lifecycle, session management, and role assignment — all managed via the user database service (port 8548) and the admin dashboard.
User Registration
New users register by providing email, username, and password. On creation:
The user receives a unique UUID and an Ethereum address (either provided by the user or generated by the system using their encrypted private key).
A Swiss-style IBAN is registered in the backend proxy's IBAN registry and linked to their Ethereum address.
kyc_statusis set topending. All trading and payment operations are blocked until KYC is approved.
Demo Seed Accounts
The user DB service seeds two pre-verified investor accounts on first startup:
Alice
password
Trader
verified
0x70997970C51812dc3A010C7d01b50e0d17dc79C8
CH5200033000000000002
Bob
password
Trader
verified
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC
CH2500033000000000003
These seed accounts use well-known Anvil test private keys. Do not use them in production — the keys are publicly known and any funds sent to these addresses can be stolen.
KYC Lifecycle
Every user progresses through a defined KYC state machine. The state is stored in the user database and enforced at the frontend layer before any on-chain action is allowed.
pending
Registered, no document submitted
View app; cannot trade, pay, or swap
submitted
Document uploaded, awaiting admin review
View app; cannot trade, pay, or swap
verified
Admin has approved the KYC submission
Full access to trading, payments, and swaps
rejected
Admin has rejected the submission
View rejection reason; re-submit documents
KYC Gate Enforcement
The frontend checks kyc_status from the session token on every protected route. A user with kyc_status != "verified" sees a banner explaining their status and a link to submit or re-submit their documents. All portfolio, payment, and swap action buttons are disabled.
Admin KYC Review
Admins review pending KYC submissions via the dashboard at http://localhost:3000/kyc.
The KYC page shows:
A list of users with
kyc_status: submitted, sorted by submission time.The uploaded document (PDF) viewable inline.
User details: email, username, Ethereum address, IBAN.
Approve and Reject buttons with an optional rejection reason field.
Approvals and rejections take effect immediately — the user's next session refresh picks up the new status.
Configuring KYC Settings
KYC document requirements and approval workflow can be configured via the admin settings:
User Roles
Each user is assigned exactly one role. Roles are assigned by an Admin via the dashboard or the user DB API.
Admin
Unlimited
Full access: user management, KYC approval, permission configuration, all chain operations
Trader
≤ $1,000,000 per transfer
Subscribe/redeem MMF shares, send IBAN payments, swap assets
SeniorTrader
≤ $5,000,000 per transfer
All Trader actions at higher limits
Compliance
Read-only
Read all transactions and positions; configure compliance rules; freeze/unfreeze wallets
Auditor
Read-only
Access to transactions and audit logs only
Regulator
Read-only
Access to selective disclosure endpoints and regulatory reports
Transfer limits are enforced by the PermissionRegistry contract via the backend proxy. See Permission Rules for the full rule format and how to customize limits.
Changing a User's Role
Via the dashboard (Users page):
Find the user in the user list.
Click the role badge to open the role editor.
Select the new role and confirm.
Via the API:
Session Management
Sliding Window Sessions
Sessions use a sliding window model. Each authenticated call to GET /auth/me extends the session by the configured TTL (default: 30 minutes). A user who stays active never gets logged out. A user who goes idle for longer than the TTL is automatically logged out on their next action.
Session TTL
30 minutes
Yes — via PATCH /admin/settings
Session cache in proxy
5 seconds
Via SESSION_CACHE_TTL env var
Session storage
localStorage (token + expiry)
—
Session Cache
The backend proxy caches validated session tokens for 5 seconds to avoid a user DB round-trip on every RPC call. The cache key is SHA-256(token) — the raw token is never cached or logged.
This means:
In
AUTH_MODE=advisory(default): all RPC calls are forwarded; caller identity is logged from the cache.In
AUTH_MODE=strict: calls with no valid session token are rejected with HTTP 401.
Configuring Session Timeout
Changes take effect for new sessions immediately. Existing sessions retain their original TTL until they are next refreshed.
User DB API Reference
The user DB service exposes a REST API at port 8548. These endpoints are consumed by the dashboard and investor frontends — they are not part of the JSON-RPC interface.
Authentication
POST /auth/login
POST /auth/loginAuthenticate a user and return a session token.
Request:
Response:
GET /auth/me
GET /auth/meValidate the current session token and return the user profile. Extends the session TTL.
Headers: Authorization: Bearer <token>
Response:
User Management (Admin Only)
GET /admin/users
GET /admin/usersList all registered users.
PATCH /admin/users/{user_id}
PATCH /admin/users/{user_id}Update a user's role or KYC status.
Request: { "role": "SeniorTrader" } or { "kyc_status": "verified" }
DELETE /admin/users/{user_id}
DELETE /admin/users/{user_id}Remove a user account. Does not affect on-chain state.
KYC
POST /kyc/submit
POST /kyc/submitUpload a KYC document (PDF). Sets kyc_status to submitted.
Request: multipart/form-data with file field.
GET /admin/kyc/pending
GET /admin/kyc/pendingList users with kyc_status: submitted, ordered by submission time.
POST /admin/kyc/{user_id}/approve
POST /admin/kyc/{user_id}/approveApprove a KYC submission. Sets kyc_status to verified.
POST /admin/kyc/{user_id}/reject
POST /admin/kyc/{user_id}/rejectReject a KYC submission. Optionally include a reason in the request body.
Settings
GET /admin/settings
GET /admin/settingsReturn current settings (session timeout, KYC configuration).
PATCH /admin/settings
PATCH /admin/settingsUpdate one or more settings. Accepts session_timeout_minutes, kyc_expiry_days, kyc_document_types.
Last updated