Skip to content
Open

Dev #200

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
d2557aa
phase 1 initial commit
Josephrp Jan 17, 2026
8b7de16
adds nexus file sharing initial commit
Josephrp Jan 17, 2026
dc836e0
adds prometheus metrics initial commit
Josephrp Jan 17, 2026
eb5c32b
Prometheus (#135)
Josephrp Jan 17, 2026
f277bbe
adds prometheus metrics initial commit
Josephrp Jan 18, 2026
7224dc7
adds prometheus metrics initial commit
Josephrp Jan 18, 2026
42ad8e8
adds prometheus, electron build passing , business logic , tsx bugfixes
Josephrp Jan 18, 2026
ff49b50
adds bugfixes , electron build
Josephrp Jan 18, 2026
e7e4b25
Merge branch 'dev' into bugfixes1
Josephrp Jan 18, 2026
971fdd5
Bugfixes1 (#140)
Josephrp Jan 18, 2026
e355de2
adds logging , pm2 , tests , compatibility tests
Josephrp Jan 19, 2026
d615ce7
Merge branch 'dev' into pm2
Josephrp Jan 19, 2026
2a42e75
adds logging , pm2 , tests , compatibility tests (#141)
Josephrp Jan 19, 2026
a3bf25a
Phase 1 Debug: Fix Critical Errors and Verify Build (#144)
biniyam69 Jan 19, 2026
4be5f6c
adds pm2 , dev scripts, environment , logs , ecosyste, server debug l…
Josephrp Jan 19, 2026
c95f667
adds pm2 , dev scripts, environment , logs , ecosyste, server debug l…
Josephrp Jan 19, 2026
4f70a5f
adds e2e test for nexus file transfer , bugfixes, tests refactor , pm…
Josephrp Jan 19, 2026
ce71c11
Merge branch 'dev' into phase1nexus
Josephrp Jan 19, 2026
31b13f2
Delete scripts/dev/nexus_file_transfer_test_plan.md
Josephrp Jan 20, 2026
9ab6c8b
adds e2e test for nexus file transfer , bugfixes, tests refactor , pm…
Josephrp Jan 20, 2026
eac1bf8
Issue #78: Trading Dashboard UI - Complete Implementation (#148)
biniyam69 Jan 20, 2026
2a8a977
Issue #77: Document Review Workflows - Complete Implementation (#150)
biniyam69 Jan 20, 2026
f51f8ae
Issue #76: Document Extraction Chains - Implementation & Tests (#145)
biniyam69 Jan 20, 2026
b4b5846
Issue #79: Order Management System - Complete Implementation (#149)
biniyam69 Jan 20, 2026
c34b695
Merge branch 'dev' into phase1nexus
Josephrp Jan 20, 2026
36f3fae
adds debugging , removes logs , improves agent routes (works now) , s…
Josephrp Jan 21, 2026
5f32b5f
solves display bugs , trading interface , routes , verification route…
Josephrp Jan 21, 2026
c863718
removes x402 unused snippet with no args, adds else branch x402
Josephrp Jan 21, 2026
a9c690d
debugs unified dashboard view : trading , now displays
Josephrp Jan 21, 2026
0ab8e4f
Phase1nexus (#151)
Josephrp Jan 21, 2026
b53ae88
Merge branch 'dev' into phase1final
Josephrp Jan 21, 2026
504c47e
adds debugging , removes logs , improves agent routes (works now) , s…
Josephrp Jan 21, 2026
b7e8eb9
Tradingdash (#155)
Josephrp Jan 21, 2026
45dcbd0
Addsguides (#156)
Josephrp Jan 22, 2026
ce53af5
solves merge conflict with main
Josephrp Jan 22, 2026
5156d9b
solves merge conflict with main
Josephrp Jan 22, 2026
a737527
adds debug fixes, dash fixes, alpaca fixes, market data fixes , valid…
Josephrp Jan 22, 2026
6f352dc
adds debug fixes, dash fixes, alpaca fixes, market data fixes , valid…
Josephrp Jan 22, 2026
5e21991
adds bugfix , modal , predictions , market , hydration , session cont…
Josephrp Jan 23, 2026
8ceafe7
Merge main into dev, conflicts resolved
Josephrp Jan 24, 2026
e41beec
adds debugs , solves hydration in verification demos , heads merge co…
Josephrp Jan 24, 2026
799eaa3
Solves Interface p0 restructuring and core features (#196)
Josephrp Jan 29, 2026
e0d58fc
solve merge conflict
Josephrp Jan 29, 2026
d6c6b22
solves conflict markers
Josephrp Jan 29, 2026
45d2b67
initial commit alpaca brokerage
Josephrp Jan 29, 2026
2a7392b
adds bugfixes and improvements
Josephrp Jan 29, 2026
fa433e2
adds kyc , user settings
Josephrp Jan 30, 2026
5f6ae2b
some bug fixes
Josephrp Jan 30, 2026
de5bb2e
removes debug instrumentation
Josephrp Jan 30, 2026
b789377
initial commit polymarket integration , funding , withdrawals , alpac…
Josephrp Jan 30, 2026
1e87343
initial commit polymarket integration , funding , withdrawals , alpa…
Josephrp Jan 30, 2026
c264faa
initial commit billing , dashboards , aggregated information , connec…
Josephrp Jan 31, 2026
014d485
Addfeats (#199)
Josephrp Jan 31, 2026
a2c5fee
various bugfixes and adds demo agent initial commit
Josephrp Jan 31, 2026
f8f852d
Refactor x402 MCP server architecture, fix critical issues (facilitat…
MarioAderman Feb 1, 2026
dc2c27d
Remove old demo/mcp_demo structure and finalize autonomous agent MCP …
MarioAderman Feb 1, 2026
a231e52
Merge pull request #203 from MarioAderman/mcp-server-on-chorebugfixes
Josephrp Feb 1, 2026
ec45eb7
initial commit x402 facilitator
Josephrp Feb 1, 2026
d6abe76
Merge branch 'chorebugfixes' of https://github.com/FinTechTonic/credi…
Josephrp Feb 1, 2026
60388d8
initial commit mcp , api keys, x402, routes , agentic score , docs , …
Josephrp Feb 1, 2026
5b89e40
bugfixes
Josephrp Feb 1, 2026
8f64d17
Chorebugfixes (#202)
Josephrp Feb 1, 2026
0e46f59
adds bugfixes and demo
Josephrp Feb 1, 2026
d1c4cfe
solves merge conflict
Josephrp Feb 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
94 changes: 83 additions & 11 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,36 @@ FILING_CHAIN_MAX_RETRIES=3
SIGNATURE_CHAIN_MAX_RETRIES=3

# =============================================================================
# DigiSigner API Configuration (for Digital Signatures)
# Plaid / Banking (Trading Phase 1)
# =============================================================================
# DigiSigner API key (get from https://www.digisigner.com/)
# Required for digital signature functionality
DIGISIGNER_API_KEY=
# DigiSigner API base URL (default: https://api.digisigner.com/v1)
DIGISIGNER_BASE_URL=https://api.digisigner.com/v1
# Webhook secret for verifying DigiSigner webhook signatures
# Optional but recommended for production
DIGISIGNER_WEBHOOK_SECRET=
# Enable Plaid bank linking (accounts, balances, and transactions) for trading/portfolio views.
# When enabled and correctly configured, the backend exposes:
# - /api/banking/status, /link-token, /connect, /accounts, /balances, /transactions, /disconnect
# and the frontend `LinkAccounts` app uses `react-plaid-link` to open Plaid Link.
# No Plaid secrets are stored in the client; everything flows through these APIs.
PLAID_ENABLED=false

# Plaid API credentials — obtain from the Plaid dashboard.
# For development, use a sandbox or development client ID/secret.
PLAID_CLIENT_ID=
PLAID_SECRET=

# Plaid environment: sandbox, development, or production.
# This controls which Plaid API host is used by `app.services.plaid_service`.
PLAID_ENV=sandbox

# Cost per Plaid API call (accounts/balances/transactions = dashboard refresh). USD shown in 402 when credits insufficient.
# Optional markup: PLAID_MARKUP_PERCENT (see Credits & micropayments section below).
PLAID_COST_USD=0.27

# Brokerage funding: link bank (Auth product → processor token → Alpaca ACH), fund (INCOMING), withdraw (OUTGOING).
# Requires PLAID_* above and ALPACA_BROKER_* below. See docs/guides/brokerage-funding.md.

# Plaid Transfer API (instant interbank: RTP when eligible, else ACH). Requires Transfer product enabled in Plaid dashboard.
# Reuses PLAID_CLIENT_ID and PLAID_SECRET from above; no separate Transfer credentials.
PLAID_TRANSFER_ENABLED=false
# Origination account ID from Plaid (for debits). Required when PLAID_TRANSFER_ENABLED=true.
PLAID_TRANSFER_ORIGINATION_ACCOUNT_ID=

# =============================================================================
# Companies House API Configuration (for UK Regulatory Filings)
Expand All @@ -255,11 +275,55 @@ COMPANIES_HOUSE_API_KEY=
# See docs/guides/alpaca-trading-setup.md
# Trading: place/cancel orders, portfolio, market data in Trading Dashboard.
# Historical bars: when ALPACA_DATA_ENABLED=true, used for stock prediction and backtest; else yahooquery.
# Note: For multiuser brokerage use ALPACA_BROKER_* below; Trading API vars are for data/backtest only.
ALPACA_BASE_URL=https://paper-api.alpaca.markets
ALPACA_API_KEY=
ALPACA_API_SECRET=
ALPACA_DATA_ENABLED=false

# =============================================================================
# Alpaca Broker API (multiuser brokerage)
# =============================================================================
# Each user gets an Alpaca customer account; orders are placed per account.
# Sandbox: https://broker-api.sandbox.alpaca.markets | Live: https://broker-api.alpaca.markets
ALPACA_BROKER_BASE_URL=https://broker-api.sandbox.alpaca.markets
ALPACA_BROKER_API_KEY=
ALPACA_BROKER_API_SECRET=
ALPACA_BROKER_PAPER=true

# Brokerage onboarding product and optional fee (Plaid link-for-brokerage + payment)
BROKERAGE_ONBOARDING_PRODUCT_ID=brokerage_onboarding
BROKERAGE_ONBOARDING_FEE_ENABLED=false
BROKERAGE_ONBOARDING_FEE_AMOUNT=0.00
BROKERAGE_ONBOARDING_FEE_CURRENCY=USD

# Optional: max single transfer amount for brokerage fund/withdraw (e.g. 25000.00). Leave empty for no limit.
BROKERAGE_MAX_SINGLE_TRANSFER=

# =============================================================================
# Unified funding (credit top-up, Fund Polymarket, Alpaca via x402)
# =============================================================================
# POST /api/funding/request, POST /api/credits/top-up use the payment router (x402 + optional RevenueCat).
# Required: X402_ENABLED and X402_* (see Payment & x402 section below) for MetaMask/facilitator payments.
# Optional: REVENUECAT_ENABLED and REVENUECAT_* for "Add credits" / credit top-up via RevenueCat.
# Credits = pennies: 1 USD top-up adds CREDITS_PENNIES_PER_USD credits (default 100).
CREDITS_PENNIES_PER_USD=100

# Credits granted per entitlement / purchase (≈ dollar value in pennies when 100 pennies/USD).
# Web subscribe $2 → 200 credits; mobile ~$3.60 → 360 credits. Top-up via MetaMask, RevenueCat, or (future) Plaid.
ORG_ADMIN_SIGNUP_CREDITS=200
SUBSCRIPTION_UPGRADE_CREDITS=200
MOBILE_APP_PURCHASE_CREDITS=360

# Billable feature 402 cost (predictions, people search, green finance, agents). USD shown when credits insufficient.
BILLABLE_FEATURE_COST_USD=0.30

# Plaid: cost per call is PLAID_COST_USD (see Plaid section). Optional markup: PLAID_MARKUP_PERCENT (e.g. 20 = 20%).
PLAID_MARKUP_PERCENT=0

# Brokerage fund/withdraw: credits deducted per transfer (0 = no fee). Subscribe or pay-as-you-go.
BROKERAGE_TRANSFER_FEE_CREDITS=600

# =============================================================================
# Stock Prediction & Modal (Chronos)
# =============================================================================
Expand Down Expand Up @@ -301,6 +365,12 @@ POLYMARKET_GAMMA_API_URL=https://gamma-api.polymarket.com
POLYMARKET_DATA_API_URL=https://data-api.polymarket.com
POLYMARKET_SURVEILLANCE_ENABLED=false
POLYMARKET_PUBLISH_EXTERNAL=false
# Builders Program: order attribution & relayer (obtain from polymarket.com/settings?tab=builder)
POLY_BUILDER_API_KEY=
POLY_BUILDER_SECRET=
POLY_BUILDER_PASSPHRASE=
POLYMARKET_BUILDER_SIGNING_MODE=remote
POLYMARKET_RELAYER_URL=https://relayer-v2.polymarket.com/

# =============================================================================
# Polymarket Cross-Chain (bridge, outcome tokens)
Expand Down Expand Up @@ -342,8 +412,8 @@ REVENUECAT_ENABLED=false
# RevenueCat secret API key (sk_...) for REST API. Required when REVENUECAT_ENABLED=true.
REVENUECAT_API_KEY=

# Entitlement identifier for Pro tier (Polymarket, premium features)
REVENUECAT_ENTITLEMENT_PRO=pro
# Entitlement identifier for Pro tier. Use the exact identifier from RevenueCat Dashboard (e.g. entlfa0ee126b6 for REST API).
REVENUECAT_ENTITLEMENT_PRO=examplekey1234567890

# Amount in USD for subscription upgrade via x402 (POST /api/subscriptions/upgrade). Pro tier.
SUBSCRIPTION_UPGRADE_AMOUNT=9.99
Expand Down Expand Up @@ -509,6 +579,8 @@ DATABASE_ENABLED=true
# JWT secret key for token generation (generate a secure random string)
JWT_SECRET_KEY=your_jwt_secret_key_here
JWT_ALGORITHM=HS256
# When MCP server (or other service) authenticates with X-API-Key (admin-generated), requests act as this user. Create a user and set its ID.
# MCP_DEMO_USER_ID=1

# =============================================================================
# Seeding Configuration
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,6 @@ ruff-security-report.json
zap-report.json
zap-report.html
security-summary.md
security-reports/
security-reports/
.claude/
.tmp/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
[![Green Finance](https://img.shields.io/badge/Green-Finance-green?style=flat-square)](https://tonic-ai.mintlify.app/features/green-finance)
[![Join us on Discord](https://img.shields.io/discord/1109943800132010065?label=Discord&logo=discord&style=flat-square)](https://discord.gg/qdfnvSPcqP)

CreditNexus is a next-generation financial operating system that bridges the gap between **Sustainabiity-Linked Loans (Legal Contracts)** and **Physical Reality (Satellite Data)**. It uses AI agents to extract covenants from PDF agreements and orchestrates "Ground Truth" verification using geospatial deep learning.
CreditNexus is a next-generation financial operating system that bridges the gap between **Sustainabiity-Linked Loans (Legal Contracts)** and **Physical Reality (Satellite Data)**. It uses AI agents to extract covenants from PDF agreements and orchestrates "Ground Truth" verification using geospatial deep learning. **Multiuser trading brokerage** is supported via the Alpaca Broker API (one Alpaca customer account per user), with optional Plaid bank linking and onboarding fees.

> 📚 **[Full Documentation](https://tonic-ai.mintlify.app)** | 🏢 **[Company Site](https://josephrp.github.io/creditnexus)** | 🎥 **[Demo Video](https://www.youtube.com/watch?v=jg25So46Wks)**

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""merge deal and internal signature heads

Revision ID: 1245cc8cc703
Revises: 7d47d1a7fd1b, cafedeadbeef
Create Date: 2026-01-28 11:19:05.845874

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '1245cc8cc703'
down_revision: Union[str, Sequence[str], None] = ('7d47d1a7fd1b', 'cafedeadbeef')
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Upgrade schema."""
pass


def downgrade() -> None:
"""Downgrade schema."""
pass
54 changes: 54 additions & 0 deletions alembic/versions/2345bc8cc704_add_document_model_enhancements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""add document model enhancements

Revision ID: 2345bc8cc704
Revises: 1245cc8cc703
Create Date: 2026-01-28 14:30:00.000000

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '2345bc8cc704'
down_revision: Union[str, Sequence[str], None] = '1245cc8cc703'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Add document model enhancement fields to documents table."""
op.add_column('documents', sa.Column('classification', sa.String(length=50), nullable=True))
op.add_column('documents', sa.Column('status', sa.String(length=50), server_default='draft', nullable=False))
op.add_column('documents', sa.Column('retention_policy', sa.String(length=100), nullable=True))
op.add_column('documents', sa.Column('retention_expires_at', sa.DateTime(), nullable=True))
op.add_column('documents', sa.Column('parent_document_id', sa.Integer(), nullable=True))
op.add_column('documents', sa.Column('compliance_status', sa.String(length=50), server_default='pending', nullable=False))
op.add_column('documents', sa.Column('regulatory_check_metadata', postgresql.JSONB(astext_type=sa.Text()), nullable=True))

op.create_foreign_key('fk_documents_parent_document_id', 'documents', 'documents', ['parent_document_id'], ['id'])

op.create_index(op.f('ix_documents_classification'), 'documents', ['classification'], unique=False)
op.create_index(op.f('ix_documents_status'), 'documents', ['status'], unique=False)
op.create_index(op.f('ix_documents_parent_document_id'), 'documents', ['parent_document_id'], unique=False)
op.create_index(op.f('ix_documents_compliance_status'), 'documents', ['compliance_status'], unique=False)


def downgrade() -> None:
"""Remove document model enhancement fields from documents table."""
op.drop_index(op.f('ix_documents_compliance_status'), table_name='documents')
op.drop_index(op.f('ix_documents_parent_document_id'), table_name='documents')
op.drop_index(op.f('ix_documents_status'), table_name='documents')
op.drop_index(op.f('ix_documents_classification'), table_name='documents')

op.drop_constraint('fk_documents_parent_document_id', 'documents', type_='foreignkey')

op.drop_column('documents', 'regulatory_check_metadata')
op.drop_column('documents', 'compliance_status')
op.drop_column('documents', 'parent_document_id')
op.drop_column('documents', 'retention_expires_at')
op.drop_column('documents', 'retention_policy')
op.drop_column('documents', 'status')
op.drop_column('documents', 'classification')
103 changes: 103 additions & 0 deletions alembic/versions/3456cd9dd805_add_kyc_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""add kyc models

Revision ID: 3456cd9dd805
Revises: 2345bc8cc704
Create Date: 2026-01-28 14:40:00.000000

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '3456cd9dd805'
down_revision: Union[str, Sequence[str], None] = '2345bc8cc704'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Add KYC verification, user licenses, and KYC documents tables."""
# Create kyc_verifications table
op.create_table('kyc_verifications',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('kyc_status', sa.String(length=50), nullable=False),
sa.Column('kyc_level', sa.String(length=50), nullable=False),
sa.Column('identity_verified', sa.Boolean(), nullable=False),
sa.Column('address_verified', sa.Boolean(), nullable=False),
sa.Column('document_verified', sa.Boolean(), nullable=False),
sa.Column('license_verified', sa.Boolean(), nullable=False),
sa.Column('sanctions_check_passed', sa.Boolean(), nullable=False),
sa.Column('pep_check_passed', sa.Boolean(), nullable=False),
sa.Column('verification_metadata', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
sa.Column('policy_evaluation_result', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
sa.Column('peoplehub_profile_id', sa.String(length=255), nullable=True),
sa.Column('submitted_at', sa.DateTime(), nullable=False),
sa.Column('completed_at', sa.DateTime(), nullable=True),
sa.Column('expires_at', sa.DateTime(), nullable=True),
sa.Column('reviewed_at', sa.DateTime(), nullable=True),
sa.Column('reviewed_by', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['reviewed_by'], ['users.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('user_id')
)
op.create_index(op.f('ix_kyc_verifications_kyc_status'), 'kyc_verifications', ['kyc_status'], unique=False)

# Create kyc_documents table
op.create_table('kyc_documents',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('kyc_verification_id', sa.Integer(), nullable=True),
sa.Column('document_type', sa.String(length=100), nullable=False),
sa.Column('document_category', sa.String(length=100), nullable=False),
sa.Column('document_id', sa.Integer(), nullable=False),
sa.Column('verification_status', sa.String(length=50), nullable=False),
sa.Column('extracted_data', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
sa.Column('ocr_confidence', sa.Float(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['document_id'], ['documents.id'], ),
sa.ForeignKeyConstraint(['kyc_verification_id'], ['kyc_verifications.id'], ondelete='CASCADE'),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_kyc_documents_kyc_verification_id'), 'kyc_documents', ['kyc_verification_id'], unique=False)
op.create_index(op.f('ix_kyc_documents_user_id'), 'kyc_documents', ['user_id'], unique=False)

# Create user_licenses table
op.create_table('user_licenses',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('kyc_verification_id', sa.Integer(), nullable=True),
sa.Column('license_type', sa.String(length=100), nullable=False),
sa.Column('license_number', sa.String(length=255), nullable=False),
sa.Column('license_category', sa.String(length=50), nullable=False),
sa.Column('issuing_authority', sa.String(length=255), nullable=False),
sa.Column('issue_date', sa.Date(), nullable=True),
sa.Column('expiration_date', sa.Date(), nullable=True),
sa.Column('document_id', sa.Integer(), nullable=True),
sa.Column('verification_status', sa.String(length=50), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['document_id'], ['documents.id'], ),
sa.ForeignKeyConstraint(['kyc_verification_id'], ['kyc_verifications.id'], ondelete='CASCADE'),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_user_licenses_kyc_verification_id'), 'user_licenses', ['kyc_verification_id'], unique=False)
op.create_index(op.f('ix_user_licenses_user_id'), 'user_licenses', ['user_id'], unique=False)


def downgrade() -> None:
"""Remove KYC verification, user licenses, and KYC documents tables."""
op.drop_index(op.f('ix_user_licenses_user_id'), table_name='user_licenses')
op.drop_index(op.f('ix_user_licenses_kyc_verification_id'), table_name='user_licenses')
op.drop_table('user_licenses')
op.drop_index(op.f('ix_kyc_documents_user_id'), table_name='kyc_documents')
op.drop_index(op.f('ix_kyc_documents_kyc_verification_id'), table_name='kyc_documents')
op.drop_table('kyc_documents')
op.drop_index(op.f('ix_kyc_verifications_kyc_status'), table_name='kyc_verifications')
op.drop_table('kyc_verifications')
Loading