10 - Database & Sync Tables

PostgreSQL schema with 75 tables managed via EF Core. Plus 22 reference tables that must be synced from the existing MOSL data lake / legacy DB.

Database Setup

EnginePostgreSQL 14+
Database nameekyc3
Schemaekyc (default for all tables)
ORMEF Core 8 with Npgsql provider
NamingSnake_case via EFCore.NamingConventions (automatic)
Connection stringHost=127.0.0.1;Port=5432;Database=ekyc3;Username=postgres;Password=root123;Search Path=ekyc
MigrationsNone - schema is code-first via EntityTypeConfigurations in OnModelCreating
No migration files yet

The project currently has no Migrations/ folder. Schema setup is manual or via DbContext.Database.EnsureCreatedAsync(). For production, generate migrations with dotnet ef migrations add InitialCreate.

Table Categories (75 tables total)

CategoryCountTables
Lead & Session3leads, lead_sessions, lead_state_transitions
Consent & Fraud3consents, fraud_checks, negative_list_entries
OTP & Email2otp_verifications, email_verifications
PAN & KRA3pan_verifications, kra_records, csafe_checks
Aadhaar1aadhaar_verifications
Bank3bank_accounts, bank_verification_attempts, bank_auto_verifies (Decentro)
Biometrics & Docs3liveness_verifications, signature_verifications, document_uploads
Personal & Nominee5personal_details, nominees, nominee_witnesses, fatca_declarations, guardians
Final Validation1final_validations
AOF & eSign3aof_documents, esign_transactions, document_path_infos
Account & Payment2account_activations, fund_transfers
CS Journey1cs_journey_holds
Verifier & Objection2verifier_reviews, objection_corrections
Journey Tracking5journey_stage_events, journey_activity_logs, stage_dropoff_configs, analytics_snapshots, journey_configurations
Downstream & Notifications2downstream_events, notifications
SEBI1sebi_submissions
Audit & Admin7api_audit_log, provider_configurations, provider_health_metrics, mock_response_templates, mock_scenarios, admin_users, feature_flags
Lookups & Config3lookups, application_config, handoff_links
Reference Masters22See "Sync Tables" section below
Account Aggregator & Income2account_aggregator_requests, income_proof_records

Key Tables - Detailed

leads

The root entity. Every journey starts with a row here.

ColumnTypeNotes
lead_iduuid PKGenerated at arrival
mobilevarchar(15)Plain for SMS sending
mobile_hashvarchar(255)BCrypt hash for dedup lookup
full_namevarchar(255)
current_stagesmallint0-15, matches StageDefinitions
current_statevarchar(50)INITIATED, OTP_VERIFIED, BANK_VERIFIED, etc.
is_completedbooleanFinal activation flag
client_idvarchar(20)Assigned at Stage 14 (CBOS)
consent_terms, consent_bank_autoverify, consent_aabooleanCaptured at registration
created_at, updated_attimestamptzupdated_at set automatically in SaveChanges override

provider_configurations

Runtime provider chain config. Read by ProviderChainExecutor on every call.

ColumnNotes
id (PK), provider_name, categorye.g. ("HypervergePan", "PAN")
enabledboolean - include in chain at all
prioritysmallint - lower = tried first
timeout_msPer-provider HTTP timeout
mock_modeWhen true, executor returns default without calling provider
mock_latency_msArtificial delay in mock mode
circuit_breaker_threshold, circuit_breaker_cooldown_secondsFailure handling

api_audit_log

Every external provider call is logged here with full request/response for audit and debugging.

ColumnNotes
id, lead_id, correlation_idTrace across related calls
provider, api_name, methode.g. ("Decentro", "MobileToAccount", "POST")
request_url, request_headers, request_bodyJSON or text
response_status_code, response_body
duration_msEnd-to-end timing
is_success, is_mock, error_message
created_at

journey_activity_logs

Human-readable activity log per lead. Powered by async channel + ActivityLogWriterService hosted service for batched writes.

bank_auto_verifies

Results of Decentro mobile-to-bank auto-verify. Triggered at Stage 2 (OTP verified). Contains encrypted account number, IFSC, beneficiary name, account type. BankVerificationService.GetBankDetailsAsync() auto-promotes successful active savings records to a verified bank_accounts row.

Sync Tables (From Data Lake / Legacy DB)

Important

Several reference tables are not populated by the new eKYC backend itself. They are expected to be synced from the existing MOSL data lake, back-office systems, or external regulators (SEBI, RBI). Without these tables populated, parts of the journey will fail.

The authoritative list and sync strategy is documented in the BRD Analysis folder:

Sync Strategy Summary

Sync TypeCountSourceTables
Daily sync5MOSL back-officeclient_master, branch_master, subbroker_master, employee_pan_master, franchise_pan_whitelist
External / regulatory2SEBI, RBInegative_list_entries (SEBI), bank_ifsc_masters (RBI)
One-time / manual populate15BRD docs, config files, old DBstate_masters, city_masters, pincode_masters, nsdl_error_masters, cvl_status_mappings, allowed_email_domains, restricted_email_domains, restricted_mobiles, suspicious_contacts, location_exception_whitelist, duplicate_bypass_whitelist, proof_upload_configs, referral_codes, lookups, application_config

Why sync tables matter

For the detailed list of each table - its columns, source system, sync job details, and expected row count - open the Sync Tables Master List.

EF Core DbContext

backend/src/MO.Ekyc.Infrastructure/Persistence/EkycDbContext.csC#excerpt
public class EkycDbContext : DbContext
{
    public DbSet<Lead> Leads => Set<Lead>();
    public DbSet<LeadSession> LeadSessions => Set<LeadSession>();
    public DbSet<OtpVerification> OtpVerifications => Set<OtpVerification>();
    public DbSet<PanVerification> PanVerifications => Set<PanVerification>();
    public DbSet<BankAccount> BankAccounts => Set<BankAccount>();
    public DbSet<BankAutoVerify> BankAutoVerifies => Set<BankAutoVerify>();
    public DbSet<ProviderConfiguration> ProviderConfigurations => Set<ProviderConfiguration>();
    public DbSet<ApiAuditLog> ApiAuditLogs => Set<ApiAuditLog>();
    // ... 75 DbSets total

    protected override void OnModelCreating(ModelBuilder mb)
    {
        mb.HasDefaultSchema("ekyc");
        mb.ApplyConfigurationsFromAssembly(typeof(EkycDbContext).Assembly);
    }

    public override async Task<int> SaveChangesAsync(CancellationToken ct = default)
    {
        // Auto-update Lead.UpdatedAt on any modification
        foreach (var entry in ChangeTracker.Entries<Lead>())
            if (entry.State == EntityState.Modified)
                entry.Entity.UpdatedAt = DateTimeOffset.UtcNow;

        return await base.SaveChangesAsync(ct);
    }
}

Useful DB Queries

SQLDaily onboarding funnel
SELECT current_stage, COUNT(*) AS count
FROM ekyc.leads
WHERE created_at::date = CURRENT_DATE
GROUP BY current_stage
ORDER BY current_stage;
SQLLead state transition history
SELECT from_state, to_state, trigger_action, transitioned_at
FROM ekyc.lead_state_transitions
WHERE lead_id = '8f2a1c9e-...'
ORDER BY transitioned_at;
SQLProvider health metrics
SELECT provider_name, success_count, failure_count,
       avg_duration_ms, last_failure_at
FROM ekyc.provider_health_metrics
ORDER BY success_count DESC;
SQLRecent provider calls (audit)
SELECT provider, api_name, response_status_code, duration_ms, is_success, is_mock, created_at
FROM ekyc.api_audit_log
WHERE lead_id = '8f2a1c9e-...'
ORDER BY created_at DESC;