Security & KYC
Security & KYC
Know Your Customer verification, identity documents, and security controls.
15 tables in this group.
kyc_profiles
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | gen_random_uuid() |
user_id | uuid | No | |
tier | text | No | 'basic'::text |
status | text | No | 'verified'::text |
email_verified | bool | Yes | false |
mfa_enabled | bool | Yes | false |
created_at | timestamptz | No | now() |
updated_at | timestamptz | No | now() |
RLS Policies:
Users can insert their own kyc profile— INSERT for {public}Users can update their own kyc profile— UPDATE for {public}Users can view their own kyc profile— SELECT for {public}
Indexes:
idx_kyc_profiles_user_idkyc_profiles_pkeykyc_profiles_user_id_key
kyc_verifications
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | gen_random_uuid() |
user_id | uuid | No | |
tier | int4 | No | 0 |
status | text | No | 'verified'::text |
verification_type | text | Yes | 'email'::text |
verified_at | timestamptz | Yes | |
expires_at | timestamptz | Yes | |
created_at | timestamptz | No | now() |
updated_at | timestamptz | No | now() |
RLS Policies:
Users can insert their own kyc verifications— INSERT for {public}Users can update their own kyc verifications— UPDATE for {public}Users can view their own kyc verifications— SELECT for {public}
Indexes:
idx_kyc_verifications_user_idkyc_verifications_pkeykyc_verifications_user_id_key
kyc_documents
Stores metadata for user-uploaded KYC documents (files in Supabase Storage) - used for Tier 2 verification
| Column | Type | Nullable | Default |
|---|---|---|---|
id | int8 | No | |
user_id | uuid | No | |
document_type | text | No | |
storage_path | text | No | |
file_name | text | No | |
file_size_bytes | int8 | No | |
mime_type | text | No | |
document_number | text | Yes | |
issuing_country | text | Yes | |
issue_date | date | Yes | |
expiry_date | date | Yes | |
verification_status | text | No | 'pending'::text |
verified_by | uuid | Yes | |
verified_at | timestamptz | Yes | |
rejection_reason | text | Yes | |
metadata | jsonb | Yes | '{}'::jsonb |
uploaded_at | timestamptz | No | now() |
updated_at | timestamptz | No | now() |
RLS Policies:
Admins can update KYC documents— UPDATE for {public}Admins or users can view KYC documents— SELECT for {public}Users can upload their own KYC documents— INSERT for {public}
Indexes:
idx_kyc_documents_verified_bykyc_documents_pkey
kyc_reviews
Tracks manual admin reviews of KYC documents for tier upgrades
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | gen_random_uuid() |
user_id | uuid | No | |
document_id | int8 | Yes | |
reviewer_id | uuid | Yes | |
old_tier | int4 | No | |
new_tier | int4 | No | |
review_status | text | No | |
review_notes | text | Yes | |
reviewed_at | timestamptz | Yes | |
created_at | timestamptz | No | now() |
RLS Policies:
Admins can delete reviews— DELETE for {public}Admins can insert reviews— INSERT for {public}Admins can update reviews— UPDATE for {public}Admins or users can view reviews— SELECT for {public}
Indexes:
idx_kyc_reviews_document_ididx_kyc_reviews_reviewer_ididx_kyc_reviews_user_idkyc_reviews_pkey
kyc_tier_history
Audit trail of KYC tier changes
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | gen_random_uuid() |
user_id | uuid | No | |
old_tier | int4 | No | |
new_tier | int4 | No | |
reason | text | No | |
changed_by | uuid | Yes | |
changed_at | timestamptz | No | now() |
RLS Policies:
Service and admins can insert history— INSERT for {public}Users can view own tier history— SELECT for {public}
Indexes:
idx_kyc_tier_history_changed_byidx_kyc_tier_history_user_idkyc_tier_history_pkey
kyc_history
KYC verification status change history
| Column | Type | Nullable | Default |
|---|---|---|---|
id | int8 | No | |
user_id | uuid | No | |
old_status | kyc_status | Yes | |
new_status | kyc_status | No | |
verified_by | uuid | Yes | |
verification_method | text | Yes | |
document_type | text | Yes | |
verification_notes | text | Yes | |
created_at | timestamptz | No | now() |
RLS Policies:
Admins or users can view KYC history— SELECT for {public}
Indexes:
idx_kyc_history_verified_bykyc_history_pkey
mfa_failed_verification_attempts
Track failed MFA verification attempts for security monitoring
| Column | Type | Nullable | Default |
|---|---|---|---|
id | int8 | No | |
user_id | uuid | No | |
mfa_method | text | No | |
provided_code | text | Yes | |
ip_address | text | No | |
user_agent | text | Yes | |
failure_reason | text | No | |
attempted_at | timestamptz | No | now() |
metadata | jsonb | Yes | '{}'::jsonb |
RLS Policies:
Admins or users can view MFA failures— SELECT for {public}Auth admin can insert MFA failures— INSERT for {supabase_auth_admin}
Indexes:
idx_mfa_failed_attempts_useridx_mfa_failed_verification_attempts_user_idmfa_failed_verification_attempts_pkey
blocked_email_domains
Email domains blocked from registration (disposable email providers, etc.)
| Column | Type | Nullable | Default |
|---|---|---|---|
id | int8 | No | |
domain | text | No | |
reason | text | Yes | |
blocked_by | uuid | Yes | |
is_active | bool | No | true |
added_at | timestamptz | No | now() |
updated_at | timestamptz | No | now() |
RLS Policies:
Admins can manage blocked email domains— ALL for {public}
Indexes:
blocked_email_domains_domain_keyblocked_email_domains_pkey
blocked_ip_addresses
IP addresses temporarily or permanently blocked from registration
| Column | Type | Nullable | Default |
|---|---|---|---|
id | int8 | No | |
ip_address | text | No | |
reason | text | Yes | |
blocked_by | uuid | Yes | |
is_active | bool | No | true |
expires_at | timestamptz | Yes | |
added_at | timestamptz | No | now() |
updated_at | timestamptz | No | now() |
RLS Policies:
Admins can manage blocked IP addresses— ALL for {public}
Indexes:
blocked_ip_addresses_ip_address_keyblocked_ip_addresses_pkeyidx_blocked_ip_addresses_blocked_by
compliance_reports
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | |
report_type | varchar(50) | No | |
report_name | varchar(200) | No | |
report_period_start | timestamp | No | |
report_period_end | timestamp | No | |
jurisdiction | varchar(100) | No | |
regulatory_body | varchar(200) | Yes | |
regulation_reference | varchar(100) | Yes | |
total_users | int4 | Yes | |
total_transactions | int4 | Yes | |
total_volume | numeric | Yes | |
flagged_transactions | int4 | Yes | |
suspicious_activities | int4 | Yes | |
executive_summary | text | Yes | |
detailed_findings | json | Yes | |
recommendations | json | Yes | |
attachments | json | Yes | |
generated_by | uuid | Yes | |
submitted_by | uuid | Yes | |
submission_reference | varchar(100) | Yes | |
status | varchar(20) | Yes | |
generated_at | timestamp | Yes | |
submitted_at | timestamp | Yes | |
created_at | timestamp | No | |
updated_at | timestamp | Yes | |
audit_metadata | json | Yes |
RLS Policies:
compliance_reports_service_all— ALL for {public}
Indexes:
compliance_reports_pkeyidx_compliance_reports_generated_byidx_compliance_reports_submitted_byix_compliance_reports_report_type
enforcement_rules
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | uuid_generate_v4() |
rule_id | varchar(255) | No | |
rule_type | varchar(100) | No | |
conditions | jsonb | No | |
action | varchar(50) | No | |
priority | int4 | Yes | 0 |
active | bool | Yes | true |
expires_at | timestamptz | Yes | |
environment | varchar(50) | Yes | 'staging'::character varying |
created_by | uuid | Yes | |
created_at | timestamptz | Yes | now() |
updated_at | timestamptz | Yes | now() |
RLS Policies:
Admins can manage enforcement rules— ALL for {public}
Indexes:
enforcement_rules_pkeyenforcement_rules_rule_id_keyidx_enforcement_rules_created_by
enforcement_log
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | uuid_generate_v4() |
user_id | uuid | No | |
resource | varchar(255) | No | |
action | varchar(255) | No | |
allowed | bool | No | |
action_taken | varchar(50) | No | |
reason | text | Yes | |
applied_rules | _text | Yes | |
environment | varchar(50) | Yes | 'staging'::character varying |
created_at | timestamptz | Yes | now() |
RLS Policies:
Admins can manage enforcement log— ALL for {public}
Indexes:
enforcement_log_pkeyidx_enforcement_log_user_id
risk_profiles
| Column | Type | Nullable | Default |
|---|---|---|---|
risk_profile_id | uuid | No | |
portfolio_id | uuid | No | |
risk_tolerance | varchar(20) | No | |
max_drawdown_percent | numeric | No | |
volatility_tolerance | numeric | No | |
rebalancing_frequency_hours | int4 | No | |
max_position_size_percent | numeric | No | |
stop_loss_percent | numeric | Yes | |
preferred_assets | json | Yes | |
excluded_assets | json | Yes | |
created_at | timestamp | No | |
updated_at | timestamp | No |
RLS Policies:
risk_profiles_service_all— ALL for {public}
Indexes:
risk_profiles_pkeyrisk_profiles_portfolio_id_key
risk_assessments
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | gen_random_uuid() |
user_id | uuid | No | |
portfolio_id | uuid | Yes | |
assessment_type | varchar(50) | No | |
var_value | numeric | Yes | |
drawdown | numeric | Yes | |
sharpe_ratio | numeric | Yes | |
assessed_at | timestamptz | Yes | now() |
metadata | jsonb | Yes | '{}'::jsonb |
RLS Policies:
Users can insert own risk assessments— INSERT for {public}Users can view own risk assessments— SELECT for {public}
Indexes:
idx_risk_assessments_portfolio_ididx_risk_assessments_typeidx_risk_assessments_user_idrisk_assessments_pkey
risk_alerts
| Column | Type | Nullable | Default |
|---|---|---|---|
id | uuid | No | gen_random_uuid() |
user_id | uuid | No | |
portfolio_id | uuid | Yes | |
alert_type | varchar(50) | No | |
severity | varchar(20) | No | |
message | text | No | |
is_acknowledged | bool | Yes | false |
created_at | timestamptz | Yes | now() |
acknowledged_at | timestamptz | Yes |
RLS Policies:
Users can insert own risk alerts— INSERT for {public}Users can view own risk alerts— SELECT for {public}
Indexes:
idx_risk_alerts_portfolio_ididx_risk_alerts_severityidx_risk_alerts_user_idrisk_alerts_pkey