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
27 KiB
Goa GEL Blockchain Document Verification Platform - Architecture Guide
Executive Summary
The Goa Government E-License (GEL) Blockchain Document Verification Platform is a comprehensive solution for managing government licenses and permits through a multi-department approval workflow backed by blockchain technology. The platform leverages Hyperledger Besu with QBFT consensus to ensure tamper-proof records of license issuance.
Key Innovation: Multi-department approval workflows with immutable blockchain records and soulbound NFT certificates.
1. System Context (C4 Level 1)
Overview
The GEL platform serves as the central integration point for government entities, citizens, and external systems.
Actors & Systems
External Actors
- Citizens: Submit license requests, upload documents, track approval status
- Government Departments: Configure workflows, review and approve requests
- Department Operators: Manage department users and approval rules
- Platform Operators: System administration, monitoring, maintenance
External Systems
- DigiLocker Mock: Verifies document authenticity (POC implementation)
- Legacy Department Systems: Integration for existing government databases
- National Blockchain Federation: Future interoperability with national systems
2. Container Architecture (C4 Level 2)
Layered Architecture
Frontend Layer
Next.js 14 + shadcn/ui
├── Pages: Dashboard, License Requests, Approvals
├── Components: Forms, Document Upload, Status Tracking
├── State: React Context + TanStack Query
└── Styling: Tailwind CSS (dark theme optimized)
Port: 3000
API & Backend Layer
NestJS TypeScript API Gateway (Port 3001)
├── Auth Service (API Key + Secret POC)
├── Workflow Service
├── Approval Service
├── Document Service
└── Blockchain Integration Module
Data Layer
PostgreSQL Database (Port 5432)
├── license_requests table
├── approvals table
├── documents table
├── audit_logs table
└── department_registry table
Redis Cache (Port 6379)
├── Session management
├── Workflow state cache
└── Real-time notifications
MinIO Object Storage (Port 9000)
├── License documents (PDFs)
├── Supporting images
├── Document proofs
└── Generated certificates
Blockchain Layer
Hyperledger Besu Network (QBFT Consensus)
├── 4 Validator Nodes (Ports 8545-8548)
├── RPC Endpoints
├── Peer-to-Peer Network
└── Smart Contracts:
├── LicenseRequestNFT (ERC-721 Soulbound)
├── ApprovalManager
├── DepartmentRegistry
└── WorkflowRegistry
3. Blockchain Architecture Deep Dive
Hyperledger Besu Configuration
Network Topology
4 Validator Nodes (QBFT Consensus)
├── Validator 1 (RPC: 8545, P2P: 30303)
├── Validator 2 (RPC: 8546, P2P: 30304)
├── Validator 3 (RPC: 8547, P2P: 30305)
└── Validator 4 (RPC: 8548, P2P: 30306)
Consensus Rule: Requires 3/4 (75%) validator approval
Block Time: ~12 seconds
Smart Contracts
1. LicenseRequestNFT (ERC-721 Soulbound)
Contract Type: ERC-721 (Non-Fungible Token)
Purpose: Issue immutable, non-transferable license certificates
Key Functions:
- mint(applicant, licenseHash, metadataURI, issuerDept)
└─ Creates NFT, emits Transfer event
- burn(tokenId)
└─ Revokes license, removes from circulation
- ownerOf(tokenId) → address
- tokenURI(tokenId) → string (IPFS or HTTP)
Soulbound Property:
- _beforeTokenTransfer() override prevents transfers
- Only issuer can revoke
- Applicant owns NFT but cannot sell/transfer
2. ApprovalManager
Purpose: Record and manage multi-department approvals
Key Functions:
- recordApproval(licenseHash, department, signature)
└─ Logs approval from specific department
- recordRejection(licenseHash, department, reason)
└─ Logs rejection with reason
- requestChanges(licenseHash, department, details)
└─ Request changes from applicant
- getApprovalChain(licenseHash) → approvalRecord[]
└─ Full approval history
Data Structures:
ApprovalRecord {
licenseHash: bytes32,
department: address,
approvalStatus: enum (PENDING, APPROVED, REJECTED, CHANGES_REQUESTED),
timestamp: uint256,
notes: string,
signature: bytes
}
3. DepartmentRegistry
Purpose: Maintain department information and approvers
Key Functions:
- registerDepartment(deptId, deptName, metadata)
- setApprovers(deptId, approverAddresses[])
- getApprovers(deptId) → address[]
- isDeptApprover(deptId, address) → bool
Data Structure:
Department {
deptId: bytes32,
name: string,
approvers: address[],
isActive: bool,
registeredAt: uint256
}
4. WorkflowRegistry
Purpose: Define and manage license approval workflows
Key Functions:
- defineWorkflow(workflowId, licenseType, departments[])
- getWorkflow(workflowId) → workflowConfig
- getNextApprovers(workflowId, currentStep) → address[]
Data Structure:
Workflow {
workflowId: bytes32,
licenseType: string,
departments: Department[],
isSequential: bool,
timeout: uint256,
createdAt: uint256
}
Example: Resort License POC
├─ Step 1: Tourism Department Review (Parallel possible)
└─ Step 2: Fire Safety Department Review
On-Chain vs Off-Chain Data Split
On-Chain Data (Blockchain State)
Immutable & Transparent
├── License Hashes (SHA-256 of documents)
├── Approval Records (with signatures)
├── Department Registry
├── Workflow Definitions
└── NFT Ownership Records
Benefits:
- Tamper-proof
- Publicly verifiable
- Immutable audit trail
- Non-repudiation
Off-Chain Data (PostgreSQL + MinIO)
Flexible & Queryable
├── Full License Request Details
├── Applicant Information
├── Document Metadata
├── Workflow State (current step)
├── User Comments & Notes
├── Audit Logs (indexed queries)
└── Actual Document Files (PDFs, images)
Benefits:
- Searchable
- Quick queries
- Scalable storage
- Privacy controls
Data Linking
SHA-256 Hash: Immutable Bridge Between On-Chain & Off-Chain
Document File
↓ (hash)
SHA-256: 0x7f8c...a1b2
↓ (stored on-chain)
Smart Contract State
↓ (referenced in off-chain DB)
PostgreSQL record contains this hash
↓ (verification)
Anyone can hash the document and verify it matches blockchain record
4. Workflow State Machine
License Request States
DRAFT
├─ Initial state
├─ Applicant can edit
├─ No blockchain record
└─ Can transition to: SUBMITTED or [abandon]
↓ [submit for review]
SUBMITTED
├─ Hash recorded on blockchain
├─ Locked from editing
├─ Routed to appropriate departments
└─ Can transition to: IN_REVIEW or [withdraw]
↓ [route to approvers]
IN_REVIEW
├─ Multi-department approval workflow
├─ Can be parallel or sequential
├─ Department approvers review documents
└─ Can transition to: APPROVED, REJECTED, or PENDING_RESUBMISSION
├─ [all approve] → APPROVED
├─ [any reject] → REJECTED
└─ [changes requested] → PENDING_RESUBMISSION
PENDING_RESUBMISSION
├─ Applicant notified of required changes
├─ Time-limited window for corrections
├─ Can resubmit documents
└─ Can transition to: SUBMITTED or [withdraw]
↓ [resubmit with changes]
SUBMITTED (again in workflow)
↓ [back to IN_REVIEW]
APPROVED (Final State)
├─ All departments approved
├─ ERC-721 Soulbound NFT minted
├─ License certificate generated
├─ Verifiable on blockchain
└─ Can transition to: REVOKED only
↓ [license revoked/expired]
REVOKED
├─ License cancelled
├─ NFT burned from circulation
├─ Audit trail preserved
└─ End state
REJECTED (Terminal State)
├─ Request denied permanently
├─ Reason recorded on-chain
├─ Applicant can appeal (future feature)
└─ Can transition to: DRAFT (reapply)
Approval States (Per Department)
PENDING
├─ Awaiting department review
├─ Notification sent to approvers
└─ Can transition to: APPROVED, REJECTED, or CHANGES_REQUESTED
├─ [approve] → APPROVED
├─ [reject] → REJECTED
└─ [request changes] → CHANGES_REQUESTED
APPROVED
├─ Department approved this request
└─ Recorded on blockchain with signature
REJECTED
├─ Department rejected request
├─ Reason recorded
└─ Triggers overall REJECTED state
CHANGES_REQUESTED
├─ Department needs clarifications/corrections
├─ Specific details provided
└─ Applicant must resubmit
REVIEW_REQUIRED
├─ Resubmitted after changes
├─ Needs re-review
└─ Back to PENDING
5. End-to-End Data Flow
11-Step Resort License Approval Process
Step 1-2: Submission & Upload
1. Citizen creates Resort License request in Next.js frontend
2. Fills in applicant information (name, contact, resort details)
3. Uploads supporting documents:
- Property proof
- Health certificate
- Fire safety plan
- Environmental clearance
- etc.
Frontend sends to NestJS API:
POST /licenses/create
├── Body: License form data
├── Files: Multipart documents
└── Auth: API Key header
Step 3: Document Processing & Hashing
3a. NestJS Document Service:
- Receives files
- Validates file types and sizes
- Uploads to MinIO with unique IDs
- Generates SHA-256 hash of each document
- Creates document metadata records in PostgreSQL
3b. License Request:
- Created with status: DRAFT
- All documents linked via hashes
- No blockchain record yet
3c. API Response to Frontend:
- License request ID
- Document upload status
- License saved locally for editing
Step 4: Blockchain Recording
4a. When citizen submits for approval:
- API aggregates all document hashes
- Creates combined SHA-256 (licenseHash)
- Calls smart contract via RPC
4b. Smart Contract Call:
POST https://besu-validator-1:8545
├─ Method: DocumentRegistrar.recordDocumentHash()
├─ Params:
│ ├─ licenseHash: bytes32
│ ├─ licenseType: "ResortLicense"
│ ├─ department: address (Tourism Dept)
│ └─ timestamp: uint256
└─ Result: Transaction receipt with block number
4c. QBFT Consensus:
- Transaction sent to all 4 validators
- Each validator verifies signature and state
- 3/4 validators must agree
- Block included in chain
- Event: DocumentHashRecorded emitted
4d. Database Update:
UPDATE license_requests
SET status = 'SUBMITTED',
blockchain_tx_hash = '0x...',
blockchain_block_num = 12345,
submitted_at = NOW()
WHERE request_id = 'LR-001'
Step 5-6: Route to Departments (Parallel)
5a. Workflow Engine determines routing:
- License type: ResortLicense
- Query WorkflowRegistry for approval workflow
- Returns: [Tourism Department, Fire Safety Department]
- Mode: Parallel (can approve simultaneously)
5b. Create Approval Requests:
INSERT INTO approvals
├─ approval_id: 'APR-001-TOURISM'
├─ license_id: 'LR-001'
├─ department: 'Tourism'
├─ status: 'PENDING'
├─ assigned_to: [list of approver emails]
└─ created_at: NOW()
INSERT INTO approvals
├─ approval_id: 'APR-001-FIRE'
├─ license_id: 'LR-001'
├─ department: 'Fire Safety'
├─ status: 'PENDING'
├─ assigned_to: [list of approver emails]
└─ created_at: NOW()
5c. Webhook Notifications (via Redis Pub/Sub):
EventPublished: "approval.assigned"
├─ recipient: approver@tourism.gov.in
├─ action: "Resort License #LR-001 awaiting review"
└─ link: "https://gel-platform/approvals/APR-001-TOURISM"
6. Parallel Approval Assignment:
- Tourism Department reviews resort location & management
- Fire Safety Department reviews fire safety plan
- Both can review simultaneously
Step 7-8: Department Approvals
7a. Tourism Approver Reviews:
Frontend shows:
├─ Applicant details (name, experience)
├─ Resort location (map, nearby facilities)
├─ Proposed capacity & amenities
├─ Property proof documents
└─ Can download or view embedded
7b. Tourism Approver Approves:
POST /approvals/APR-001-TOURISM/approve
├─ Body:
│ ├─ decision: "APPROVED"
│ ├─ comments: "Location suitable, management experienced"
│ └─ signature: signatureHash (if using digital signature)
└─ Auth: Department user credentials
7c. Backend Processing:
a) Update database:
UPDATE approvals
SET status = 'APPROVED',
reviewed_by = 'approver@tourism.gov.in',
reviewed_at = NOW(),
comments = 'Location suitable...'
WHERE approval_id = 'APR-001-TOURISM'
b) Record on blockchain:
Call ApprovalManager.recordApproval()
├─ licenseHash: 0x7f8c...a1b2
├─ department: 0xTourismDeptAddress
├─ status: APPROVED
├─ timestamp: block.timestamp
└─ Result: Event ApprovalRecorded emitted
c) Update workflow state (Redis cache):
KEY: "license:LR-001:approvals"
VALUE: {
"APR-001-TOURISM": {"status": "APPROVED", ...},
"APR-001-FIRE": {"status": "PENDING", ...}
}
7d. Fire Safety Approver Reviews & Approves (Parallel):
Similar process with fire safety specific documents
8. Parallel Completion:
Both departments complete their approvals
- Database updated
- Blockchain events recorded
- Workflow cache synchronized
Step 9: Final Approval & NFT Minting
9a. Workflow Engine Monitors State:
Check all approvals for license LR-001
Result: 2/2 approvals = APPROVED
9b. Trigger License Approval:
a) Generate License Certificate:
- Template: ResortLicense_Template.pdf
- Fill with: Applicant name, Resort location, Date, etc.
- Upload to MinIO: /certificates/LR-001-cert.pdf
- Hash: SHA-256 of PDF
b) Prepare NFT Metadata:
{
"name": "Goa Resort License - [Resort Name]",
"description": "Blockchain-verified Resort License issued by...",
"image": "https://storage/license-badge.png",
"attributes": {
"license_type": "ResortLicense",
"issue_date": "2026-02-03",
"expiry_date": "2027-02-03",
"issuer": "Tourism Department, Goa",
"certificate_hash": "0xabcd...",
"license_request_hash": "0x7f8c...",
"applicant": "Resort Owner Name"
}
}
Upload to MinIO: /metadata/LR-001-metadata.json
c) Mint Soulbound NFT:
Call LicenseRequestNFT.mint()
├─ to: applicant_wallet_address
├─ licenseHash: 0x7f8c...a1b2
├─ metadataURI: "https://storage/metadata/LR-001-metadata.json"
├─ issuerDept: tourismDeptAddress
└─ Result: Transaction with tokenId
d) QBFT Consensus & Finalization:
- 3/4 validators approve mint transaction
- NFT created in smart contract state
- tokenId: 1001 (auto-incremented)
- ownerOf(1001) = applicant_wallet
- Event: Transfer(address(0), applicant, 1001)
e) Update Database:
UPDATE license_requests
SET status = 'APPROVED',
nft_token_id = 1001,
nft_address = '0xLicenseNFTContractAddress',
approved_at = NOW()
WHERE request_id = 'LR-001'
INSERT INTO audit_logs
VALUES (license_id='LR-001', action='APPROVED', ..., timestamp=NOW())
Step 10: Notifications & State Update
10a. Send Approval Notification:
Webhook Event: "license.approved"
├─ recipient: citizen@email.com
├─ subject: "Your Resort License Has Been Approved!"
├─ body: "License #LR-001 approved on [date]"
└─ link: "https://gel-platform/licenses/LR-001"
10b. Update Frontend:
WebSocket notification to citizen's browser
├─ Status changed to: APPROVED
├─ Show NFT badge
├─ Enable download buttons
└─ Display approval timeline
10c. Cache Invalidation:
Redis invalidates:
├─ license:LR-001:* (all license data)
├─ citizen:citizen@email.com:licenses
└─ dashboard:pending-approvals
(Fresh data will be loaded on next request)
10d. Update Department Dashboards:
├─ Remove from "Pending Review" list
├─ Add to "Approved" list with approval details
└─ Show NFT minting confirmation
Step 11: License Verification
11a. Citizen Downloads License Certificate:
GET /licenses/LR-001/certificate
11b. Certificate Generation:
a) Retrieve license metadata from DB
b) Get NFT details from blockchain
c) Generate PDF with all details + QR code
d) QR Code contains: https://gel-verify.goa.gov.in?verify=0x7f8c...a1b2
e) Return PDF
11c. Third-party Verification (e.g., Hotel Inspector):
a) Scan QR code on license certificate
b) GET https://gel-verify.goa.gov.in/verify?hash=0x7f8c...a1b2
c) Verification Service:
i. Query blockchain for this hash
ii. Check if NFT still valid (not revoked/burned)
iii. Return: {
"valid": true,
"license_type": "ResortLicense",
"holder": "Resort Name",
"issue_date": "2026-02-03",
"expiry_date": "2027-02-03",
"issuer": "Tourism Department"
}
iv. Inspector can verify instantly without needing central server
11d. On-Chain Verification:
Call LicenseRequestNFT.ownerOf(tokenId)
└─ Returns: citizen_address (verifying NFT still exists)
Call ApprovalManager.getApprovalChain(licenseHash)
└─ Returns: Complete approval history [Tourism: APPROVED, Fire: APPROVED]
6. Deployment Architecture
Docker Compose Environment
All services run in isolated containers with defined networks and volumes.
Services Overview
version: '3.9'
services:
# Frontend
frontend:
image: node:18-alpine
build: ./frontend
container_name: gel-frontend
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://api:3001
- NEXT_PUBLIC_BLOCKCHAIN_RPC=http://besu-1:8545
volumes:
- ./frontend:/app
- /app/node_modules
depends_on:
- api
networks:
- gel-network
# NestJS Backend API
api:
image: node:18-alpine
build: ./backend
container_name: gel-api
ports:
- "3001:3001"
environment:
- DATABASE_URL=postgresql://gel_user:${DB_PASSWORD}@postgres:5432/goa_gel
- REDIS_URL=redis://redis:6379
- MINIO_ENDPOINT=minio:9000
- BLOCKCHAIN_RPC=http://besu-1:8545
- BLOCKCHAIN_NETWORK_ID=1337
- API_SECRET_KEY=${API_SECRET_KEY}
volumes:
- ./backend:/app
- /app/node_modules
depends_on:
- postgres
- redis
- minio
- besu-1
networks:
- gel-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
interval: 30s
timeout: 10s
retries: 3
# PostgreSQL Database
postgres:
image: postgres:15-alpine
container_name: gel-postgres
ports:
- "5432:5432"
environment:
- POSTGRES_DB=goa_gel
- POSTGRES_USER=gel_user
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- gel-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U gel_user"]
interval: 10s
timeout: 5s
retries: 5
# Redis Cache
redis:
image: redis:7-alpine
container_name: gel-redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- gel-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# MinIO S3-compatible Storage
minio:
image: minio/minio:latest
container_name: gel-minio
ports:
- "9000:9000"
- "9001:9001"
environment:
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=${MINIO_PASSWORD}
volumes:
- minio_data:/minio_data
command: server /minio_data --console-address ":9001"
networks:
- gel-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
# Hyperledger Besu Validator Nodes
besu-1:
image: hyperledger/besu:latest
container_name: gel-besu-1
ports:
- "8545:8545" # RPC
- "30303:30303" # P2P
volumes:
- ./besu/config.toml:/etc/besu/config.toml
- ./besu/genesis.json:/etc/besu/genesis.json
- ./besu/keys/node1:/opt/besu/keys
- besu_data_1:/data
environment:
- BESU_RPC_HTTP_ENABLED=true
- BESU_RPC_HTTP_HOST=0.0.0.0
- BESU_RPC_HTTP_PORT=8545
- BESU_RPC_WS_ENABLED=true
- BESU_RPC_WS_HOST=0.0.0.0
networks:
- gel-network
depends_on:
- besu-2
- besu-3
- besu-4
besu-2:
image: hyperledger/besu:latest
container_name: gel-besu-2
ports:
- "8546:8545"
- "30304:30303"
volumes:
- ./besu/config.toml:/etc/besu/config.toml
- ./besu/genesis.json:/etc/besu/genesis.json
- ./besu/keys/node2:/opt/besu/keys
- besu_data_2:/data
networks:
- gel-network
besu-3:
image: hyperledger/besu:latest
container_name: gel-besu-3
ports:
- "8547:8545"
- "30305:30303"
volumes:
- ./besu/config.toml:/etc/besu/config.toml
- ./besu/genesis.json:/etc/besu/genesis.json
- ./besu/keys/node3:/opt/besu/keys
- besu_data_3:/data
networks:
- gel-network
besu-4:
image: hyperledger/besu:latest
container_name: gel-besu-4
ports:
- "8548:8545"
- "30306:30303"
volumes:
- ./besu/config.toml:/etc/besu/config.toml
- ./besu/genesis.json:/etc/besu/genesis.json
- ./besu/keys/node4:/opt/besu/keys
- besu_data_4:/data
networks:
- gel-network
# Prometheus Monitoring
prometheus:
image: prom/prometheus:latest
container_name: gel-prometheus
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
networks:
- gel-network
# Grafana Dashboards
grafana:
image: grafana/grafana:latest
container_name: gel-grafana
ports:
- "3002:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
volumes:
- grafana_storage:/var/lib/grafana
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning
depends_on:
- prometheus
networks:
- gel-network
networks:
gel-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
postgres_data:
redis_data:
minio_data:
besu_data_1:
besu_data_2:
besu_data_3:
besu_data_4:
prometheus_data:
grafana_storage:
Environment Configuration
# .env file
DB_PASSWORD=your_secure_db_password
MINIO_PASSWORD=your_secure_minio_password
API_SECRET_KEY=your_secure_api_key
GRAFANA_PASSWORD=your_secure_grafana_password
# Optional: Domain configuration
FRONTEND_URL=https://gel-platform.goa.gov.in
API_URL=https://api.gel-platform.goa.gov.in
Startup Process
# 1. Build all images
docker-compose build
# 2. Start all services
docker-compose up -d
# 3. Initialize database
docker-compose exec postgres psql -U gel_user -d goa_gel -f /docker-entrypoint-initdb.d/init.sql
# 4. Verify services
docker-compose ps
docker-compose logs -f api
# 5. Access services
# Frontend: http://localhost:3000
# API: http://localhost:3001
# MinIO Console: http://localhost:9001
# Prometheus: http://localhost:9090
# Grafana: http://localhost:3002
7. Key Technical Benefits
Immutability & Trust
- Once a license is recorded on blockchain, it cannot be tampered with
- Full approval history is cryptographically verifiable
- Any party can independently verify license authenticity
Transparency
- Multi-department approvals are publicly recorded
- Citizens can see real-time status of their requests
- Audit trail of every action is preserved
Efficiency
- Parallel approval workflows reduce processing time
- Automated notifications keep stakeholders informed
- Real-time status updates via WebSocket/Redis
Security
- API Key + Secret authentication (POC)
- JWT tokens for session management
- Role-based access control (RBAC)
- Immutable audit logs prevent tampering
Scalability
- Off-chain document storage (MinIO)
- On-chain hashing ensures scalability
- Redis caching for high-traffic operations
- Horizontal scaling possible for all services
Interoperability
- ERC-721 standard enables future integrations
- REST API for third-party systems
- Blockchain records can be shared with National Blockchain Federation
- Legacy system integration via adapters
8. Future Enhancements
Phase 2 (Post-POC)
- OAuth 2.0 integration with DigiLocker (real, not mocked)
- Multi-signature smart contracts for critical decisions
- Insurance coverage integration
Phase 3
- DAO governance for workflow changes
- Cross-chain interoperability (Cosmos/Polkadot)
- Mobile app for on-the-go approvals
Phase 4
- AI-powered document verification
- National Blockchain Federation integration
- License marketplace for portability
9. File Locations
All diagrams and related files are located in:
/sessions/cool-elegant-faraday/mnt/Goa-GEL/
Mermaid Diagram Files (.mermaid)
system-context.mermaid- C4 Context diagramcontainer-architecture.mermaid- Container architectureblockchain-architecture.mermaid- Blockchain layer detailsworkflow-state-machine.mermaid- State transitionsdata-flow.mermaid- Sequence diagramdeployment-architecture.mermaid- Docker Compose setup
HTML Preview Files (.html)
- Each .mermaid file has a corresponding .html file for browser viewing
- Open in any modern web browser (Chrome, Firefox, Safari, Edge)
- Uses CDN-hosted mermaid.js for rendering
Conversion to PNG
See the README.md file for multiple options to convert diagrams to PNG format.
10. Getting Started
-
Review Diagrams
- Open .html files in browser for quick visualization
- Or visit mermaid.live to paste .mermaid content
-
Understand Architecture
- Start with system-context for high-level overview
- Move to container-architecture for technical details
- Deep-dive with blockchain-architecture for smart contracts
-
Implement
- Use deployment-architecture for Docker Compose setup
- Reference data-flow for integration points
- Review workflow-state-machine for business logic
-
Documentation
- Convert diagrams to PNG for presentations
- Include in technical documentation
- Share with stakeholders for feedback
Document Version: 1.0
Platform: Goa GEL (Goa Government E-License)
Last Updated: 2026-02-03
Status: POC Phase 1