Skip to content

Proof-of-concept distributed voting system for 8M voters. Supports elections (single-choice + ranked-choice) and citizen referendums. Learning project demonstrating microservices architecture with hash-based authentication. Seeking community review and collaboration. Fork and improve welcome!

License

Notifications You must be signed in to change notification settings

Deadlydav/Distributed-Voting-System-v2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Distributed Voting System v2

Author: David Marleau License: MIT License Status: 🚧 DEMO VERSION - FUNCTIONAL BUT INCOMPLETE 🚧

📖 Lire en Français | 🇬🇧 English Version


Executive Summary

A production-grade distributed electronic voting system engineered to handle 8 million concurrent voters across Canada. This system supports both direct democracy referendums (law voting) and electoral elections with single-choice and ranked-choice voting capabilities.

Key Highlights

  • High Performance: Designed to process 8M+ votes with RabbitMQ queue buffering and horizontal scaling
  • Secure: Offline hash validation, zero PII storage, complete audit trails
  • Scalable: Microservices architecture ready for Kubernetes deployment
  • Real-time: Live results with auto-refresh dashboards
  • Monitored: Comprehensive Prometheus + Grafana observability stack

Quick Stats

Metric Value
Target Capacity 8 million voters
Throughput ~1,000 votes/sec (production target)
Current Performance 150-250 votes/sec (local Docker)
Latency (p95) <100ms
Architecture Microservices + Message Queue
Security Hash-based authentication, no PII

💡 About This Project

This is a learning project and proof-of-concept built to share an idea for modernizing democratic voting systems.

Important Context:

  • Built by a non-developer as a learning exercise ("vibe coding")
  • Demonstrates architecture concepts, not production-ready code
  • Functional demo that shows the idea works at scale
  • Needs significant work before real-world use

Why Share This?

This project aims to contribute an idea to the democratic technology community. If you're a security professional, experienced developer, or electoral systems expert:

  • 🔍 Review the architecture - does the concept have merit?
  • 🔧 Fork and improve - make it production-ready
  • 💡 Use as inspiration - build something better
  • 🤝 Contribute fixes - all improvements welcome

📋 Security Assessment: See SECURITY.md for honest assessment of current limitations and what would be needed for production use.

🎯 Goal: Advance democratic participation technology, whether through this implementation or by inspiring better solutions.


Use Cases

This voting infrastructure could be deployed in various democratic scenarios:

Use Case 1: Traditional Elections

The system supports standard electoral processes:

  • Single-choice voting for simple elections
  • Ranked-choice voting (RCV) for preferential ballots
  • Regional representation with national aggregation
  • Real-time results with audit trails

Use Case 2: Citizen Referendums

The same infrastructure could enable direct democracy votes on legislation. Examples where referendum mechanisms have been discussed:

  1. Parliamentary Salary Adjustments (Canada, April 2024)

    • MPs received 4.4% increase (MPs: $203,100/year, PM: $406,200)
    • Polling showed 80% public opposition
    • Currently automatic with no citizen input mechanism
  2. Healthcare Policy Reforms (Quebec, October 2024)

    • Bill 2 imposed physician compensation changes
    • Some doctors faced salary reductions up to $145,000
    • Minister Lionel Carmant resigned; medical associations filed legal challenges
    • Passed under closure vote without extended consultation
  3. Global Trend Toward Direct Democracy

    • 700+ citizen protests in 147+ countries (2023-2024)
    • Growing demand for referendum mechanisms on major policy decisions
    • Technology enabling real-time citizen participation at scale

Technical Capabilities

This system provides:

  • Scalability: Designed for 8M concurrent voters
  • Flexibility: Law voting OR elections OR both
  • Security: Hash-based authentication, zero PII storage
  • Transparency: Open source, auditable results
  • Performance: 1,000 votes/sec production target

Implementation Options

Organizations could deploy this for:

  • Municipal/provincial elections
  • Union votes or organizational ballots
  • Legislative referendums (if legally enabled)
  • Pilot programs testing direct democracy models
  • Academic research on voting systems

Table of Contents

  1. Features
  2. Quick Start
  3. Architecture Overview
  4. System Components
  5. Election System
  6. Testing
  7. Deployment
  8. Security
  9. Performance & Scaling
  10. Troubleshooting
  11. Project Structure

Features

Voting Capabilities

  • Law Voting (Referendums): Direct democracy with Oui/Non choices
  • Electoral Elections: Regional representative elections
    • Single-choice voting support
    • Ranked-choice voting (RCV) support
    • Multi-candidate races with party affiliations
    • Election timing controls (start/end datetime)
    • Real-time results tracking

Technical Features

  • High Performance: RabbitMQ queue buffering for 8M+ concurrent users
  • Security: Offline hash validation, no PII storage, complete audit trail
  • Scalability: Kubernetes-ready microservices architecture
  • Monitoring: Prometheus + Grafana dashboards with alerting
  • Duplicate Detection: Redis-based deduplication with attempt tracking
  • Real-time Results: Auto-refreshing dashboard (5-second intervals)
  • National Aggregation: "All Regions" view for nationwide totals
  • Load Testing: Comprehensive test suite with 8M vote capacity

Quick Start

Ultra-Fast Start (Single Command)

./quick-start.sh

This script automatically starts all services in ~20 seconds! 🚀

Manual Start

Prerequisites

  • Docker & Docker Compose
  • Python 3.11+
  • kubectl (for production deployment)

Steps

  1. Start Docker services:
docker-compose up -d
  1. Start the monitor dashboard:
python3 monitor_dashboard/server.py &
  1. Start the voting interface:
cd demo_ui && python3 app.py &
  1. Access the services:

Submit Test Votes

Law Vote:

curl -X POST http://localhost:8000/api/v1/vote \
  -H "Content-Type: application/json" \
  -d '{
    "nas": "123456789",
    "code": "ABC123",
    "law_id": "L2025-001",
    "vote": "oui"
  }'

Election Vote:

curl -X POST http://localhost:8000/api/v1/elections/vote \
  -H "Content-Type: application/json" \
  -d '{
    "nas": "123456789",
    "code": "ABC123",
    "election_id": 1,
    "region_id": 1,
    "candidate_id": 1,
    "voting_method": "single_choice"
  }'

View Results

Law Results:

curl http://localhost:8000/api/v1/results/L2025-001

Election Results:

curl http://localhost:8000/api/v1/elections/1/regions/1/results

Architecture Overview

The system uses a microservices architecture with message queue buffering to handle high-volume concurrent traffic while maintaining data integrity.

High-Level Flow

Voter → Ingestion API (FastAPI)
          ↓
       RabbitMQ Queue (BUFFER) ← Handles burst traffic
          ↓
     Validation Workers (Scalable)
          ├─→ Redis (Hash Validation + Deduplication)
          └─→ PostgreSQL (Audit Log)
          ↓
       Aggregation Service
          ↓
       PostgreSQL (Vote Results)
          ↓
    Real-time Dashboard

Key Architectural Decisions

  1. Message Queue Buffer: RabbitMQ absorbs traffic spikes (8M voters over 24 hours)
  2. Stateless Workers: Validation workers can scale horizontally without coordination
  3. Redis for Speed: Fast hash lookups (8M hashes) and duplicate detection
  4. PostgreSQL for Persistence: Reliable storage for votes and audit trails
  5. Batch Aggregation: Efficient vote counting with 100-vote batches

Infrastructure Components

  • Ingestion API: FastAPI vote submission endpoint
  • RabbitMQ: Message queue buffer (handles burst traffic)
  • Redis: Fast hash lookup (8M hashes) and duplicate detection
  • PostgreSQL: Persistent storage for votes, elections, candidates, results
  • Prometheus + Grafana: Metrics collection and visualization
  • Validation Workers: Scalable workers for hash validation (horizontal scaling)
  • Aggregation Service: Batch processing for vote counting

System Components

1. Ingestion API

Location: services/ingestion_api/

The FastAPI-based entry point for all vote submissions.

Responsibilities:

  • Accept HTTP POST requests with vote data
  • Perform basic input validation (format, required fields)
  • Publish messages to RabbitMQ validation queue
  • Return 202 Accepted response immediately (async processing)
  • Expose health check and metrics endpoints

Endpoints:

  • POST /api/v1/vote - Submit law vote
  • POST /api/v1/elections/vote - Submit election vote
  • GET /api/v1/results/{law_id} - Get law results
  • GET /api/v1/elections/{election_id}/regions/{region_id}/results - Get election results
  • GET /health - Health check

Performance:

  • Current: ~250 votes/second (local Docker)
  • Target: ~1,000 votes/second (production Kubernetes)

Configuration:

  • Rate limiting enabled
  • Request/response validation
  • CORS support for web UI
  • Prometheus metrics export

2. Validation Workers

Location: services/validation_worker/

Scalable workers that process votes from the RabbitMQ validation queue.

Processing Flow:

  1. Consume from votes.validation queue
  2. Validate Hash: Check if hash exists in valid_hashes Redis SET
    • If invalid → publish to votes.review queue with status='invalid'
  3. Check Duplicate: Check if hash exists in voted_hashes Redis SET
    • If duplicate:
      • Increment duplicate_count:{hash} counter
      • Publish to votes.review queue with status='duplicate' and attempt count
  4. Process Valid Vote:
    • Add hash to voted_hashes SET
    • Insert audit log into PostgreSQL vote_audit table
    • Publish to votes.aggregation queue
    • ACK message

Key Features:

  • Vote validation against Redis hash database
  • Duplicate detection with attempt counting
  • Audit logging in PostgreSQL
  • Graceful error handling with message requeuing
  • Prometheus metrics for monitoring
  • Horizontal scaling support

Scaling:

# Scale to 8 workers
docker-compose up -d --scale validation-worker=8

Metrics:

  • validation_votes_processed_total{status}: Total votes by status
  • validation_processing_latency_seconds: Processing time
  • validation_errors_total{error_type}: Errors by type
  • redis_operations_total{operation,status}: Redis operations
  • database_operations_total{operation,status}: DB operations

3. Aggregation Service

Location: services/aggregation/

Consumes validated votes from RabbitMQ and updates PostgreSQL with aggregated vote counts.

How It Works:

The aggregation service uses intelligent batching for efficiency:

  1. Size-based batching: Processes when batch reaches 100 votes
  2. Time-based batching: Processes every 1 second if votes are pending
  3. Shutdown batching: Processes all remaining votes on graceful shutdown

Database Operations:

  • Uses INSERT ... ON CONFLICT UPDATE (UPSERT) for efficiency
  • Batch updates minimize database connections
  • Connection pooling for performance
  • Automatic retry with exponential backoff

Database Schema:

vote_results - Primary aggregation table:

  • law_id (PK): Law identifier
  • oui_count: Count of "oui" votes
  • non_count: Count of "non" votes
  • updated_at: Last update timestamp

vote_audit - Individual vote audit log:

  • vote_hash (UNIQUE): Hash of the vote
  • citizen_id: Voter identifier
  • law_id: Law identifier
  • choice: Vote choice (oui/non)
  • timestamp: Vote timestamp

Performance:

  • Processes ~10,000 votes/second (hardware dependent)
  • Batch size tunable for throughput vs latency
  • Horizontal scaling supported

Prometheus Metrics:

  • votes_aggregated_total{law_id, choice}: Total votes aggregated
  • current_vote_totals{law_id, choice}: Current vote counts
  • batch_processing_duration_seconds: Processing time
  • batch_size_processed_total: Votes per batch
  • aggregation_errors_total{error_type}: Aggregation errors

4. Hash Generator Service

Location: services/hash_generator/

A containerized utility for generating cryptographic hashes for voter authentication.

Purpose: Create unique authentication credentials for testing and deployment.

Hash Format: Each hash is computed as: SHA-256(f"{nas}|{code.upper()}|{law_id}")

Generated Data:

{
  "nas": "123456789",        // 9-digit random number
  "code": "ABC123",           // 6-character uppercase alphanumeric
  "law_id": "L2025-001",      // Law identifier
  "hash": "a1b2c3d4e5f6...",  // SHA-256 hash
  "vote": "oui"               // Random vote (oui/non)
}

Usage:

# Generate 1 million hashes
python generator.py --count 1000000 --output ./output

# Generate 5 million hashes for a specific law
python generator.py --count 5000000 --output ./output --law-id L2025-042

# Docker usage
docker run -v $(pwd)/output:/output hash-generator \
  --count 1000000 \
  --output /output

Output:

  • Sharded JSON files (hashes_shard_0000.json, hashes_shard_0001.json, etc.)
  • Default: 1 million hashes per shard
  • Progress bar with real-time generation status
  • Summary statistics (vote distribution, file sizes)

Performance:

  • Generation speed: ~100,000-500,000 hashes per second
  • Memory efficient with sharded output
  • Can generate 8M hashes in under 2 minutes

Integration:

  • Load hashes into Redis for validation
  • Distribute shard files to voting nodes
  • Use for load testing and simulation

5. Demo Web UI

Location: demo_ui/

A Flask-based web interface for the electronic voting system with real-time results display.

Features:

  • Voting Form: Submit votes with NAS, validation code, law selection, and vote choice
  • Real-time Validation: Client-side form validation with instant feedback
  • Results Display: Live results with auto-refresh every 5 seconds
  • Interactive Charts: Visual representation using Chart.js
  • Responsive Design: Mobile-friendly Bootstrap 5 interface
  • Dark Theme: Professional dark color scheme
  • Error Handling: Comprehensive error messages for all scenarios

Routes:

  • GET / - Main voting page with form and current results
  • POST /vote - Submit a vote (AJAX endpoint)
  • GET /results - Full results page with charts and tables
  • GET /api/results - JSON API for fetching current results
  • GET /health - Health check endpoint

Technologies:

  • Backend: Flask 3.0
  • Frontend: Bootstrap 5, Chart.js
  • HTTP Client: Requests library
  • Styling: Custom CSS with dark theme
  • JavaScript: Vanilla JS with AJAX

Running Locally:

cd demo_ui
pip install -r requirements.txt
python app.py
# Access at http://localhost:3000

Production Deployment:

pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:3000 app:app

6. Monitoring Stack

Location: monitoring/

Comprehensive observability with Prometheus metrics collection and Grafana visualization.

Components:

  • Prometheus: Time-series database and alerting engine
  • Grafana: Visualization and dashboard platform
  • Exporters: Specialized exporters for Redis, PostgreSQL, and RabbitMQ

Access:

Key Dashboards:

  1. Votes Per Second - Time series showing vote ingestion rate
  2. Total Votes by Law - Gauge showing cumulative votes per law
  3. Validation Status Breakdown - Pie chart of valid/invalid/duplicate votes
  4. Queue Depth - Time series of message queue depths
  5. API Latency (p50/p95/p99) - Percentile latencies
  6. Duplicate Attempt Rate - Percentage of duplicate attempts
  7. Active Workers - Number of running validation workers
  8. Redis Memory Usage - Memory consumption gauge
  9. Database Connections - DB connection pool utilization
  10. HTTP Requests by Status Code - Stacked area chart

Alert Rules:

Critical Alerts (Immediate Action Required):

  • IngestionAPIDown - API unreachable for 1 minute
  • ValidationWorkerDown - Less than 2 workers for 2 minutes
  • RabbitMQDown - RabbitMQ unreachable for 1 minute
  • RedisDown - Redis unreachable for 1 minute
  • PostgresDown - PostgreSQL unreachable for 1 minute
  • CriticalValidationQueueDepth - >50,000 messages for 2 minutes
  • CriticalDuplicateRate - >15% duplicate rate for 5 minutes
  • APICriticalLatency - p95 latency >500ms for 2 minutes
  • CriticalAPIErrorRate - >15% error rate for 2 minutes

Warning Alerts (Action Recommended):

  • HighValidationQueueDepth - >10,000 messages for 5 minutes
  • HighDuplicateRate - >5% duplicate rate for 10 minutes
  • APIHighLatency - p95 latency >200ms for 5 minutes
  • HighAPIErrorRate - >5% error rate for 5 minutes

Metrics Categories:

Application Metrics:

  • votes_received_total - Counter of votes received
  • votes_by_law_total - Counter per law/referendum
  • votes_validation_processed_total - Counter of validated votes
  • votes_aggregated_total - Counter of aggregated votes
  • http_requests_total - HTTP requests by status code

Infrastructure Metrics:

  • rabbitmq_queue_messages - Messages in queue
  • redis_memory_used_bytes - Memory usage
  • pg_stat_database_numbackends - Active connections
  • validation_duration_seconds - Processing time histogram

Election System

Database Schema

Elections Table:

  • election_code, election_name, election_type
  • start_datetime, end_datetime - Voting window control
  • voting_method - single_choice or ranked_choice
  • status - draft, active, completed

Candidates Table:

  • Links to elections, regions, and political parties
  • first_name, last_name, bio
  • Party affiliations with colors and branding

Election Results:

  • Real-time aggregation in election_results table
  • Vote counts and percentages per candidate/region
  • National aggregation across all regions

Features Implemented

  • ✅ Ranked-choice voting toggle in Admin Panel
  • ✅ Election timing (start/end datetime)
  • ✅ Vote cutoff validation (no votes after deadline)
  • ✅ Election results on monitor dashboard with "All Regions" aggregation
  • ✅ National election totals (automatic aggregation across all regions)
  • ✅ Region-specific result breakdowns
  • ✅ RabbitMQ pipeline: API → Queue → Workers → PostgreSQL
  • ✅ Multi-candidate elections working
  • ✅ Party colors and branding
  • ✅ Real-time auto-refresh (5-second intervals)

Testing

Location: tests/

Comprehensive integration and load testing suite.

Test Coverage

  • Total Integration Tests: 40+
  • Test Coverage Target: >80%
  • Performance Targets:
    • Throughput: 1000 votes/second
    • Latency: p95 < 100ms
    • Success Rate: >99.9%

Running Tests

# Run all integration tests
cd tests/
pytest integration/ -v

# With coverage report
pytest integration/ -v --cov --cov-report=html

# Run specific test files
pytest integration/test_vote_flow.py -v
pytest integration/test_api.py -v
pytest integration/test_duplicate_detection.py -v

Load Testing

Generate 8 million test credentials:

python3 scripts/preload_test_hashes.py 8000000

This creates:

  • test_votes.txt (251MB, 8M lines)
  • Loads all hashes into Redis for validation

Run load tests:

# Standard load test (with valid credentials)
python3 -u tests/load_test.py --votes 100000 --rate 1000

# Direct DB test (elections, 30k votes)
python3 tests/test_election_simple.py

# Using Locust (web UI)
locust -f tests/load_test.py --host=http://localhost:8000
# Open browser to http://localhost:8089

Performance Results:

  • Direct DB: 3,558 votes/sec
  • API Load Test: 160-265 votes/sec (with full validation pipeline)
  • System Capacity: Designed for 8M votes in 24 hours (~92 votes/sec average)

Test Categories

  1. Integration Tests - End-to-end testing of complete voting pipeline
  2. API Tests - REST API endpoint validation
  3. Duplicate Detection Tests - Vote deduplication logic verification
  4. Load Tests - Performance and scalability testing

Deployment

Docker Compose (Local Development)

# Start all services
docker-compose up -d

# Scale validation workers
docker-compose up -d --scale validation-worker=5

# Check status
docker-compose ps

# View logs
docker-compose logs -f validation-worker

Kubernetes (Production)

# Apply base configuration
kubectl apply -k k8s/overlays/prod/

# Scale workers
kubectl scale deployment validation-worker --replicas=20

# Check status
kubectl get pods

# View logs
kubectl logs -f deployment/validation-worker

Production Scaling Recommendations

Development (docker-compose):

  • Current performance: ~250 votes/second via API
  • Direct DB: 3,500+ votes/second
  • Good for testing and demos

Production (Kubernetes):

  • 10x Ingestion API replicas
  • 20x Validation Workers
  • 3x Aggregation Service
  • Redis Cluster (3 nodes)
  • PostgreSQL with read replicas
  • Target: 1000 votes/second sustained

Security

Security Features

  • No PII Storage: Only hashes stored, no personally identifiable information
  • Offline Hash Database: Prevents fake votes, hashes generated offline
  • Duplicate Detection: Redis-based deduplication with attempt tracking
  • Complete Audit Trail: Every vote logged in PostgreSQL
  • Rate Limiting: API rate limiting to prevent abuse
  • Election Timing Enforcement: No early/late votes accepted
  • TLS Communication: Inter-service communication encrypted (production)

Hash-Based Authentication

The system uses SHA-256 hashes for voter authentication:

Hash = SHA-256(NAS | Code | Law_ID)

Benefits:

  1. No personal information stored in the system
  2. Offline hash generation ensures vote credential integrity
  3. Cannot reverse-engineer voter identity from hash
  4. Each hash is unique to voter + law combination

Data Protection

Redis:

  • Valid hashes stored in valid_hashes SET (8M hashes)
  • Voted hashes stored in voted_hashes SET (deduplication)
  • Duplicate attempt counters: duplicate_count:{hash}
  • TTL set on all keys for automatic cleanup

PostgreSQL:

  • Audit log: vote_audit table (immutable record)
  • Results: vote_results table (aggregated counts)
  • Elections: elections, candidates, election_results tables
  • All tables indexed for performance and security queries

Performance & Scaling

Current Performance (Local Docker)

Metric Value
Peak Throughput (API) ~250 votes/sec
Peak Throughput (Direct DB) ~3,500 votes/sec
p95 Latency 80ms
Success Rate 99.5%

Production Targets (Kubernetes)

Metric Target
Peak Throughput 1,000 votes/sec
p95 Latency <100ms
Success Rate >99.9%
Availability 99.9%

Scaling for 8M Votes

Scenario: 8 million voters over 24-hour voting period

Average Load: 8,000,000 / (24 * 3600) = ~92 votes/second

Peak Load (assuming 10x spike): ~920 votes/second

Scaling Strategy:

  1. Horizontal Scaling:

    • 10x Ingestion API instances (load balanced)
    • 20x Validation Workers (parallel processing)
    • 3x Aggregation Services (batch processing)
  2. Infrastructure Scaling:

    • Redis Cluster (3 nodes, sharded)
    • PostgreSQL with read replicas (1 primary, 2 replicas)
    • RabbitMQ Cluster (3 nodes, mirrored queues)
  3. Performance Optimizations:

    • Connection pooling (PostgreSQL)
    • Batch operations (Aggregation)
    • Prefetch count tuning (RabbitMQ)
    • Redis pipelining

Capacity Planning:

Component Min Medium Load High Load
API Instances 2 4 10
Validation Workers 4 8 20
Aggregation Services 1 2 3
Expected Throughput ~200/sec ~500/sec ~1000/sec

Troubleshooting

Votes Not Being Processed

Symptoms: Votes submitted but not appearing in results

Diagnostic Steps:

  1. Check RabbitMQ queue depth: curl -u guest:guest http://localhost:15672/api/queues
  2. Check validation worker logs: docker-compose logs validation-worker
  3. Verify Redis has hashes: docker-compose exec redis redis-cli SCARD valid_hashes

Solutions:

  • Scale validation workers: docker-compose up -d --scale validation-worker=8
  • Load hashes into Redis: python3 scripts/load_hashes_to_redis.py
  • Restart workers: docker-compose restart validation-worker

Election Results Not Showing

Diagnostic Steps:

  1. Check election_results table:
    docker-compose exec postgres psql -U voting_user -d voting -c "SELECT * FROM election_results;"
  2. Verify candidates exist in admin panel
  3. Check monitor dashboard for live results
  4. Verify election is active and within time window

Solutions:

  • Verify election status: Check admin panel Tab 7
  • Check aggregation service logs: docker-compose logs aggregation
  • Verify time window: Ensure current time is between start_datetime and end_datetime

High Queue Depth

Symptoms: Messages accumulating in validation or aggregation queues

Possible Causes:

  • Insufficient worker capacity
  • Worker crashes or deadlocks
  • Database performance issues
  • Network connectivity problems

Solutions:

  • Scale up workers: docker-compose up -d --scale validation-worker=8
  • Restart stuck workers: docker-compose restart validation-worker
  • Check database performance: Monitor connection count and query times
  • Monitor Grafana dashboard for bottlenecks

Performance Issues

Diagnostic Steps:

  1. Check Prometheus metrics: http://localhost:9090
  2. Monitor Redis memory: docker-compose exec redis redis-cli INFO memory
  3. Check database connections: docker-compose exec postgres psql -U voting_user -d voting -c "SELECT count(*) FROM pg_stat_activity;"

Solutions:

  • Scale validation workers: docker-compose up -d --scale validation-worker=5
  • Increase Redis memory limit in docker-compose.yml
  • Optimize database queries or add indexes

Clean Slate Reset

If tests or system are failing unexpectedly:

# Stop and remove all containers, volumes, networks
docker-compose down -v

# Remove test artifacts
rm -rf htmlcov/ .coverage .pytest_cache/

# Restart fresh
docker-compose up -d
sleep 30

# Reload hashes
python3 scripts/load_hashes_to_redis.py --sample

Project Structure

electionscriptanalyse/
├── services/                           # Microservices
│   ├── ingestion_api/                 # Vote submission API (FastAPI)
│   │   ├── main.py                    # API endpoints
│   │   ├── requirements.txt           # Dependencies
│   │   └── Dockerfile                 # Container config
│   ├── validation_worker/             # Hash validation & deduplication
│   │   ├── worker.py                  # Main worker logic
│   │   ├── redis_client.py            # Redis operations
│   │   ├── rabbitmq_client.py         # RabbitMQ consumer
│   │   ├── database.py                # PostgreSQL client
│   │   ├── config.py                  # Configuration
│   │   ├── requirements.txt           # Dependencies
│   │   ├── Dockerfile                 # Container config
│   │   └── README.md                  # Service documentation
│   ├── aggregation/                   # Vote counting & aggregation
│   │   ├── aggregator.py              # Main aggregation logic
│   │   ├── requirements.txt           # Dependencies
│   │   ├── Dockerfile                 # Container config
│   │   └── README.md                  # Service documentation
│   ├── hash_generator/                # Hash generation utility
│   │   ├── generator.py               # Hash generator script
│   │   ├── requirements.txt           # Dependencies
│   │   ├── Dockerfile                 # Container config
│   │   └── README.md                  # Service documentation
│   └── shared/                        # Shared utilities & models
│       ├── models.py                  # Data models
│       └── utils.py                   # Common utilities
├── demo_ui/                            # Web-based voting interface
│   ├── app.py                         # Flask application
│   ├── config.py                      # Configuration
│   ├── requirements.txt               # Dependencies
│   ├── Dockerfile                     # Container config
│   ├── README.md                      # UI documentation
│   ├── templates/                     # HTML templates
│   │   ├── index.html                 # Voting page
│   │   └── results.html               # Results page
│   └── static/                        # Static assets
│       ├── style.css                  # Custom styling
│       └── script.js                  # Client-side logic
├── tests/                              # Test suites
│   ├── integration/                   # Integration tests
│   │   ├── conftest.py                # Pytest fixtures
│   │   ├── test_vote_flow.py          # End-to-end vote flow tests
│   │   ├── test_api.py                # API endpoint tests
│   │   └── test_duplicate_detection.py # Duplicate handling tests
│   ├── unit/                          # Unit tests
│   ├── load_test.py                   # Load testing script (8M votes)
│   ├── voting_test_gui.py             # Streamlit admin panel
│   ├── test_election_simple.py        # Direct DB election test (30k votes)
│   ├── small_rabbitmq_test.py         # Small-scale RabbitMQ test (17 votes)
│   ├── small_election_test.py         # Small-scale election test (17 votes)
│   ├── requirements.txt               # Test dependencies
│   └── README.md                      # Testing documentation
├── monitor_dashboard/                  # Real-time results dashboard
│   ├── server.py                      # Python HTTP server
│   └── monitor.html                   # Live election results UI
├── monitoring/                         # Prometheus & Grafana
│   ├── prometheus/                    # Prometheus configuration
│   │   ├── prometheus.yml             # Main config
│   │   └── alerts.yml                 # Alert rules
│   ├── grafana/                       # Grafana configuration
│   │   ├── dashboards/                # Dashboard JSON files
│   │   │   └── voting_overview.json   # Main dashboard
│   │   └── provisioning/              # Auto-provisioning
│   │       ├── datasources/           # Datasource config
│   │       │   └── prometheus.yml     # Prometheus datasource
│   │       └── dashboards/            # Dashboard provisioning
│   │           └── dashboards.yml     # Dashboard config
│   └── README.md                      # Monitoring documentation
├── scripts/                            # Utility scripts
│   ├── preload_test_hashes.py         # Generate 8M test vote credentials
│   ├── load_hashes_to_redis.py        # Load hash database
│   └── quick-start.sh                 # One-command startup script
├── k8s/                               # Kubernetes manifests
│   ├── base/                          # Base configurations
│   └── overlays/                      # Environment-specific configs
│       ├── dev/                       # Development
│       └── prod/                      # Production
├── test_results/                      # Load test results (organized)
├── data/                              # Data directory
│   └── init_db.sql                    # Database schema & sample data
├── docker-compose.yml                 # Local development stack
├── ARCHITECTURE.md                    # System architecture documentation
├── QUICKSTART.md                      # Getting started guide
├── README.md                          # Main README (original)
└── readme2.md                         # This comprehensive README

Recent Updates

2025-11-21

  • Added "All Regions" aggregation to monitor dashboard
    • National election totals shown by default
    • Automatic vote aggregation across all regions
    • Seamless switching between national and regional views
  • Created small-scale testing scripts (17 votes)
    • tests/small_rabbitmq_test.py - Test RabbitMQ pipeline
    • tests/small_election_test.py - Test election voting
    • Fast debugging without loading 8M votes
  • Created quick-start.sh - One-command system startup
  • Removed redundant law chart from monitor dashboard
  • ✅ Successfully tested complete RabbitMQ pipeline:
    • API → RabbitMQ → Validation Workers → PostgreSQL
    • All 17/17 votes processed correctly
  • ✅ Updated README with improved quick-start guide

2025-11-16

  • ✅ Generated 8 million test vote credentials (251MB file)
  • ✅ Loaded 8M hashes into Redis (~2 min load time)
  • ✅ Cleaned up 154 Zone.Identifier files
  • ✅ Organized test results into test_results/ folder
  • ✅ Updated documentation (README + GEMINI.md)

Contributing

This is a demo/prototype project. For production use, additional development required:

  1. Security Hardening:

    • Implement rate limiting per IP
    • Add API authentication/authorization
    • Enable TLS/SSL for all communications
    • Implement intrusion detection
  2. Scalability Enhancements:

    • Redis Cluster implementation
    • PostgreSQL read replicas
    • RabbitMQ clustering
    • CDN for static assets
  3. Operational Improvements:

    • Automated backups
    • Disaster recovery procedures
    • Blue-green deployment
    • Canary releases
  4. Compliance:

    • GDPR compliance audit
    • Accessibility (WCAG 2.1 AA)
    • Security audit
    • Penetration testing

Support & Documentation

For issues and questions:

  1. Check Troubleshooting section
  2. Review ARCHITECTURE.md for system design
  3. See component-specific READMEs:
  4. Check service logs: docker-compose logs <service-name>
  5. Monitor system health: http://localhost:3001 (Grafana)

License

MIT License

Copyright (c) 2025 David Marleau

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Built with ❤️ for democratic participation at scale

About

Proof-of-concept distributed voting system for 8M voters. Supports elections (single-choice + ranked-choice) and citizen referendums. Learning project demonstrating microservices architecture with hash-based authentication. Seeking community review and collaboration. Fork and improve welcome!

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published