#
Identity & KYC
Technical overview of how KYC/KYB verification is bound to user principals on the Internet Computer.
#
Identity Binding
Tortuga uses Sumsub for identity verification. Once verified, the KYC status is bound to a principal on the Internet Computer.
flowchart TB
USER[User] --> SUMSUB[Sumsub Verification]
SUMSUB --> RESULT{Approved?}
RESULT -->|Yes| BIND[Bind to Principal]
RESULT -->|No| REJECT[Rejected]
BIND --> OPT1[New Principal]
BIND --> OPT2[Internet Identity]
#
Binding Options
#
Option 1: New Principal
A new cryptographic principal is created specifically for the user.
sequenceDiagram
participant User
participant Sumsub
participant Backend as Tortuga Backend
participant Registry as KYC Registry
User->>Sumsub: Complete Verification
Sumsub-->>Backend: Webhook (Approved)
Backend->>Backend: Generate New Principal
Backend->>Registry: Store (Principal, KYC Status)
Backend-->>User: Principal + Seed Phrase
#
Option 2: Internet Identity
KYC status is bound to the user's existing Internet Identity.
sequenceDiagram
participant User
participant II as Internet Identity
participant Sumsub
participant Backend as Tortuga Backend
participant Registry as KYC Registry
User->>II: Authenticate
II-->>Backend: Principal
Backend->>Sumsub: Start KYC (with Principal ref)
User->>Sumsub: Complete Verification
Sumsub-->>Backend: Webhook (Approved)
Backend->>Registry: Store (II Principal, KYC Status)
#
KYC Registry Canister
The KYC Registry is a canister on ICP that stores verification status.
flowchart LR
subgraph KYC Registry
MAP[Principal → Status]
LEVEL[Verification Level]
EXPIRY[Expiration]
end
ML[Master Ledger] --> MAP
ML --> LEVEL
#
Data Model
type KycStatus = variant {
Pending;
Verified : KycData;
Rejected;
Expired;
};
type KycData = record {
level : KycLevel;
verified_at : Timestamp;
expires_at : opt Timestamp;
provider_ref : Text; // Sumsub reference
};
type KycLevel = variant {
Basic; // Individual KYC
Enhanced; // Enhanced due diligence
Corporate; // KYB for entities
};
#
Registry Interface
service : {
// Query KYC status
get_status : (Principal) -> (opt KycStatus) query;
// Check if principal is verified (used by Master Ledger)
is_verified : (Principal) -> (bool) query;
// Called by backend after Sumsub webhook
set_verified : (Principal, KycData) -> (Result);
// Revoke verification
revoke : (Principal) -> (Result);
}
#
Integration with Master Ledger
The Master Ledger queries the KYC Registry before allowing operations.
flowchart TB
REQ[Transfer Request] --> ML[Master Ledger]
ML --> CHECK[Query KYC Registry]
CHECK --> STATUS{Both Verified?}
STATUS -->|Yes| EXEC[Execute Transfer]
STATUS -->|No| DENY[Deny Transfer]All token operations (mint, transfer, burn) require:
- Caller principal is verified
- Recipient principal is verified (for transfers)
- Verification has not expired