Files
Goa-gel-fullstack/backend/DATABASE_SETUP.md
Mahi 80566bf0a2 feat: Goa GEL Blockchain e-Licensing Platform - Full Stack Implementation
Complete implementation of the Goa Government e-Licensing platform with:

Backend:
- NestJS API with JWT authentication
- PostgreSQL database with Knex ORM
- Redis caching and session management
- MinIO document storage
- Hyperledger Besu blockchain integration
- Multi-department workflow system
- Comprehensive API tests (266/282 passing)

Frontend:
- Angular 21 with standalone components
- Angular Material + TailwindCSS UI
- Visual workflow builder
- Document upload with progress tracking
- Blockchain explorer integration
- Role-based dashboards (Admin, Department, Citizen)
- E2E tests with Playwright (37 tests)

Infrastructure:
- Docker Compose orchestration
- Blockscout blockchain explorer
- Development and production configurations
2026-02-07 10:23:29 -04:00

16 KiB

Goa GEL Database Setup - Complete Guide

Overview

This document provides a comprehensive overview of the complete database setup for the Goa GEL Blockchain Document Verification Platform, including all 12 entities, complete migrations, seeders, and configuration.

Created Files Summary

1. Entity Files (12 entities)

All entities are located in /src/database/entities/:

Entity File Purpose
Applicant applicant.entity.ts Represents license applicants with wallet integration
Department department.entity.ts Government departments handling approvals
Workflow workflow.entity.ts Multi-stage approval workflow definitions
LicenseRequest license-request.entity.ts Main license application entity (8 statuses)
Document document.entity.ts Uploaded documents with versioning support
DocumentVersion document-version.entity.ts Version history for documents (SHA-256 hashing)
Approval approval.entity.ts Department-level approvals (5 statuses)
WorkflowState workflow-state.entity.ts Execution state tracking with full audit
Webhook webhook.entity.ts Department webhook configurations
WebhookLog webhook-log.entity.ts Webhook delivery audit trail (retry tracking)
AuditLog audit-log.entity.ts Comprehensive change audit with actor tracking
BlockchainTransaction blockchain-transaction.entity.ts NFT minting and on-chain operations (5 tx types)

Index File: entities/index.ts - Exports all entities and enums

2. Core Configuration

  • data-source.ts - TypeORM DataSource with PostgreSQL configuration
    • Environment variable driven
    • Connection pooling configured
    • Logging support for development
    • All 12 entities registered

3. Migrations

  • 1704067200000-InitialSchema.ts - Complete initial schema
    • 12 tables created with proper constraints
    • 7 custom PostgreSQL enums
    • 40+ indexes for performance optimization
    • Foreign key relationships with cascade delete
    • Complete down migration for rollback

4. Database Seeders

  • seeders/seed.ts - Sample data generator
    • Creates 4 sample departments (Fire, Tourism, Municipal, Health)
    • Defines RESORT_LICENSE workflow with 5 stages
    • Creates 2 sample applicants
    • Creates 1 license request in DRAFT status
    • Generates workflow state with execution log

5. Documentation

  • src/database/README.md - Comprehensive database documentation
  • DATABASE_SETUP.md - This file

Database Schema Details

Table: applicants

id: UUID (PK)
digilockerId: varchar(255) UNIQUE
name: varchar(255)
email: varchar(255) UNIQUE
phone: varchar(20)
walletAddress: varchar(255) UNIQUE
isActive: boolean (default: true)
createdAt: TIMESTAMP WITH TIME ZONE
updatedAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - digilockerId
  - walletAddress
  - email

Table: departments

id: UUID (PK)
code: varchar(50) UNIQUE
name: varchar(255)
walletAddress: varchar(255) UNIQUE
apiKeyHash: varchar(255)
apiSecretHash: varchar(255)
webhookUrl: text NULLABLE
webhookSecretHash: varchar(255) NULLABLE
isActive: boolean (default: true)
createdAt: TIMESTAMP WITH TIME ZONE
updatedAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - code
  - walletAddress

Table: workflows

id: UUID (PK)
workflowType: varchar(100) UNIQUE
name: varchar(255)
description: text NULLABLE
version: integer (default: 1)
definition: jsonb
isActive: boolean (default: true)
createdBy: UUID NULLABLE
createdAt: TIMESTAMP WITH TIME ZONE
updatedAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - workflowType

Table: license_requests

id: UUID (PK)
requestNumber: varchar(50) UNIQUE (auto-generated: RL-YYYY-XXXXXX)
tokenId: bigint NULLABLE
applicantId: UUID (FK: applicants)
requestType: varchar(50)
workflowId: UUID (FK: workflows)
status: ENUM (DRAFT, SUBMITTED, IN_REVIEW, PENDING_RESUBMISSION, APPROVED, REJECTED, REVOKED, CANCELLED)
metadata: jsonb (default: {})
currentStageId: varchar(100) NULLABLE
blockchainTxHash: varchar(255) NULLABLE
createdAt: TIMESTAMP WITH TIME ZONE
updatedAt: TIMESTAMP WITH TIME ZONE
submittedAt: TIMESTAMP WITH TIME ZONE NULLABLE
approvedAt: TIMESTAMP WITH TIME ZONE NULLABLE

Indexes:
  - requestNumber
  - applicantId
  - workflowId
  - status
  - createdAt
  - (applicantId, status)

Table: documents

id: UUID (PK)
requestId: UUID (FK: license_requests)
docType: varchar(100)
originalFilename: varchar(255)
currentVersion: integer (default: 1)
currentHash: varchar(64) [SHA-256]
minioBucket: varchar(255)
isActive: boolean (default: true)
createdAt: TIMESTAMP WITH TIME ZONE
updatedAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - requestId
  - (requestId, docType)
  - currentHash

Table: document_versions

id: UUID (PK)
documentId: UUID (FK: documents)
version: integer
hash: varchar(64) [SHA-256]
minioPath: text
fileSize: bigint
mimeType: varchar(100)
uploadedBy: UUID
blockchainTxHash: varchar(255) NULLABLE
createdAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - documentId
  - hash

Unique Constraint:
  - (documentId, version)

Table: approvals

id: UUID (PK)
requestId: UUID (FK: license_requests)
departmentId: UUID (FK: departments)
status: ENUM (PENDING, APPROVED, REJECTED, CHANGES_REQUESTED, REVIEW_REQUIRED)
remarks: text NULLABLE
remarksHash: varchar(64) NULLABLE [SHA-256]
reviewedDocuments: jsonb (array of UUIDs, default: [])
blockchainTxHash: varchar(255) NULLABLE
isActive: boolean (default: true)
invalidatedAt: TIMESTAMP WITH TIME ZONE NULLABLE
invalidationReason: varchar(255) NULLABLE
createdAt: TIMESTAMP WITH TIME ZONE
updatedAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - requestId
  - departmentId
  - status
  - (requestId, departmentId)
  - (requestId, status)

Table: workflow_states

id: UUID (PK)
requestId: UUID (FK: license_requests) UNIQUE
currentStageId: varchar(100)
completedStages: jsonb (array of stage IDs, default: [])
pendingApprovals: jsonb (array of {departmentCode, status, createdAt}, default: [])
executionLog: jsonb (array of {timestamp, stageId, action, details}, default: [])
stageStartedAt: TIMESTAMP WITH TIME ZONE NULLABLE
createdAt: TIMESTAMP WITH TIME ZONE
updatedAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - requestId

Table: webhooks

id: UUID (PK)
departmentId: UUID (FK: departments)
url: text
events: jsonb (array of event types, default: [])
secretHash: varchar(255)
isActive: boolean (default: true)
createdAt: TIMESTAMP WITH TIME ZONE
updatedAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - departmentId
  - (departmentId, isActive)

Table: webhook_logs

id: UUID (PK)
webhookId: UUID (FK: webhooks)
eventType: varchar(100)
payload: jsonb
responseStatus: integer NULLABLE
responseBody: text NULLABLE
responseTime: integer NULLABLE [milliseconds]
retryCount: integer (default: 0)
status: ENUM (PENDING, SUCCESS, FAILED)
createdAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - webhookId
  - eventType
  - status
  - createdAt
  - (webhookId, status)

Table: audit_logs

id: UUID (PK)
entityType: ENUM (REQUEST, APPROVAL, DOCUMENT, DEPARTMENT, WORKFLOW)
entityId: UUID
action: varchar(100)
actorType: ENUM (APPLICANT, DEPARTMENT, SYSTEM, ADMIN)
actorId: UUID NULLABLE
oldValue: jsonb NULLABLE
newValue: jsonb NULLABLE
ipAddress: varchar(45) NULLABLE
userAgent: text NULLABLE
correlationId: varchar(255) NULLABLE
createdAt: TIMESTAMP WITH TIME ZONE

Indexes:
  - entityType
  - entityId
  - action
  - actorType
  - createdAt
  - (entityType, entityId)
  - (actorId, createdAt)

Table: blockchain_transactions

id: UUID (PK)
txHash: varchar(255) UNIQUE
txType: ENUM (MINT_NFT, APPROVAL, DOC_UPDATE, REJECT, REVOKE)
relatedEntityType: varchar(100)
relatedEntityId: UUID
fromAddress: varchar(255)
toAddress: varchar(255) NULLABLE
status: ENUM (PENDING, CONFIRMED, FAILED)
blockNumber: bigint NULLABLE
gasUsed: bigint NULLABLE
errorMessage: text NULLABLE
createdAt: TIMESTAMP WITH TIME ZONE
confirmedAt: TIMESTAMP WITH TIME ZONE NULLABLE

Indexes:
  - txHash
  - status
  - txType
  - relatedEntityId
  - createdAt
  - (status, txType)

Enums Defined

LicenseRequestStatus (license_requests table)

  • DRAFT
  • SUBMITTED
  • IN_REVIEW
  • PENDING_RESUBMISSION
  • APPROVED
  • REJECTED
  • REVOKED
  • CANCELLED

ApprovalStatus (approvals table)

  • PENDING
  • APPROVED
  • REJECTED
  • CHANGES_REQUESTED
  • REVIEW_REQUIRED

WebhookLogStatus (webhook_logs table)

  • PENDING
  • SUCCESS
  • FAILED

AuditEntityType (audit_logs table)

  • REQUEST
  • APPROVAL
  • DOCUMENT
  • DEPARTMENT
  • WORKFLOW

AuditActorType (audit_logs table)

  • APPLICANT
  • DEPARTMENT
  • SYSTEM
  • ADMIN

BlockchainTransactionType (blockchain_transactions table)

  • MINT_NFT
  • APPROVAL
  • DOC_UPDATE
  • REJECT
  • REVOKE

BlockchainTransactionStatus (blockchain_transactions table)

  • PENDING
  • CONFIRMED
  • FAILED

Key Features

1. Data Integrity

  • All foreign keys with CASCADE DELETE
  • UNIQUE constraints on critical fields
  • NOT NULL constraints where required
  • CHECK constraints via TypeORM validation

2. Performance Optimization

  • 40+ indexes covering all query patterns
  • Composite indexes for common joins
  • JSONB columns for flexible metadata
  • Partitioning ready for large audit tables

3. Audit & Compliance

  • Complete audit_logs tracking all changes
  • Actor identification (who made the change)
  • Old/new values for change comparison
  • Correlation IDs for distributed tracing
  • IP address and user agent capture

4. Blockchain Integration

  • blockchain_transactions table for on-chain tracking
  • NFT token ID field in license_requests
  • Transaction hash storage for verification
  • Block confirmation tracking

5. Workflow Management

  • workflow_states for execution tracking
  • Complete execution log with timestamps
  • Pending approvals tracking by department
  • Completed stages audit trail

6. Document Versioning

  • Multiple versions per document
  • SHA-256 hashing for integrity
  • File size and mime type tracking
  • Upload attribution and timestamps

7. Webhook System

  • Flexible event subscription model
  • Retry mechanism with count tracking
  • Response time monitoring
  • Status tracking (PENDING, SUCCESS, FAILED)

Setup Instructions

Prerequisites

  • PostgreSQL 12+ with UUID extension
  • Node.js 16+ with TypeORM
  • npm or yarn package manager

Steps

  1. Install Dependencies

    npm install typeorm pg uuid crypto dotenv
    
  2. Create PostgreSQL Database

    createdb goa_gel_db
    
  3. Configure Environment Create .env file:

    DATABASE_HOST=localhost
    DATABASE_PORT=5432
    DATABASE_USER=postgres
    DATABASE_PASSWORD=your_password
    DATABASE_NAME=goa_gel_db
    DATABASE_LOGGING=true
    DATABASE_SSL=false
    NODE_ENV=development
    
  4. Run Migrations

    npx typeorm migration:run -d src/database/data-source.ts
    
  5. Seed Sample Data

    npx ts-node src/database/seeders/seed.ts
    
  6. Verify Setup

    psql goa_gel_db -c "\dt"
    

Entity Relationships

┌─────────────┐
│ Applicant   │
└──────┬──────┘
       │ 1:N
       │
       ├─────────────────────────────┬──────────────────┐
       │                             │                  │
       ▼                             ▼                  ▼
┌──────────────────┐      ┌──────────────┐     ┌────────────────┐
│ LicenseRequest   │      │  Workflow    │     │ WorkflowState  │
└────┬─────────────┘      └──────────────┘     └────────────────┘
     │                                                    △
     │ 1:N                                               │
     ├─────────┬──────────┐                              │
     │         │          │                              │
     ▼         ▼          ▼                          1:1 relation
┌────────────┐ ┌───────────┐ ┌──────────────┐
│ Document   │ │ Approval  │ │ Approval     │
│ 1:N        │ │ 1:N       │ │ Status       │
│ DocumentV  │ │ Department│ │ Tracking     │
└────────────┘ └─────┬─────┘ └──────────────┘
               │
               │ N:1
               │
        ┌──────▼──────┐
        │ Department  │
        │ 1:N         │
        │ Webhook     │
        │ 1:N         │
        │ WebhookLog  │
        └─────────────┘

AuditLog ─── Tracks all changes to above entities

BlockchainTransaction ─── Records NFT minting and approvals

Common Operations

Create a New Migration

npx typeorm migration:generate -d src/database/data-source.ts -n AddNewField

Generate Migration from Entity Changes

npx typeorm migration:generate -d src/database/data-source.ts -n AutoGenerated

Revert Last Migration

npx typeorm migration:revert -d src/database/data-source.ts

View Migration Status

npx typeorm migration:show -d src/database/data-source.ts

Security Considerations

  1. Hash Storage - API keys, secrets, and webhook secrets are hashed with SHA-256
  2. Wallet Addresses - Normalized to lowercase to prevent duplication
  3. Cascade Delete - Foreign keys cascade to prevent orphaned records
  4. Audit Trail - All critical operations logged with actor identification
  5. Correlation IDs - Support distributed tracing for audit
  6. JSONB Validation - Additional validation at application layer

Performance Tips

  1. Index Usage - All frequently queried columns are indexed
  2. Composite Indexes - Multi-column queries optimized
  3. JSONB Queries - Use PostgreSQL native JSONB operations
  4. Batch Operations - Use chunking for large inserts
  5. Connection Pooling - Configured at 20 connections (production)

File Locations

/sessions/cool-elegant-faraday/mnt/Goa-GEL/backend/src/database/
├── entities/
│   ├── applicant.entity.ts
│   ├── approval.entity.ts
│   ├── audit-log.entity.ts
│   ├── blockchain-transaction.entity.ts
│   ├── department.entity.ts
│   ├── document-version.entity.ts
│   ├── document.entity.ts
│   ├── index.ts
│   ├── license-request.entity.ts
│   ├── webhook-log.entity.ts
│   ├── webhook.entity.ts
│   ├── workflow-state.entity.ts
│   └── workflow.entity.ts
├── migrations/
│   └── 1704067200000-InitialSchema.ts
├── seeders/
│   └── seed.ts
├── data-source.ts
├── index.ts
└── README.md

Next Steps

  1. Install PostgreSQL and create database
  2. Configure environment variables in .env
  3. Run migrations: npx typeorm migration:run -d src/database/data-source.ts
  4. Seed sample data: npx ts-node src/database/seeders/seed.ts
  5. Start backend application
  6. Verify database tables: psql goa_gel_db -c "\dt"

Support

For detailed information, see:

  • /src/database/README.md - Database documentation
  • /src/database/entities/ - Entity definitions with comments
  • /src/database/migrations/ - SQL migration details