Initial commit: MOPC platform with Docker deployment setup
Full Next.js 15 platform with tRPC, Prisma, PostgreSQL, NextAuth. Includes production Dockerfile (multi-stage, port 7600), docker-compose with registry-based image pull, Gitea Actions CI workflow, nginx config for portal.monaco-opc.com, deployment scripts, and DEPLOYMENT.md guide. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
374
docs/architecture/README.md
Normal file
374
docs/architecture/README.md
Normal file
@@ -0,0 +1,374 @@
|
||||
# MOPC Platform - Architecture Overview
|
||||
|
||||
## System Overview
|
||||
|
||||
The MOPC Platform is a secure jury voting system built as a modern full-stack TypeScript application for the **Monaco Ocean Protection Challenge**. It follows a layered architecture with clear separation of concerns.
|
||||
|
||||
**Phase 1 Focus**: Jury selection rounds (130→60→6 projects)
|
||||
**Domain**: `monaco-opc.com`
|
||||
|
||||
## Finalized Decisions
|
||||
|
||||
| Decision | Choice |
|
||||
|----------|--------|
|
||||
| **Domain** | `monaco-opc.com` |
|
||||
| **Evaluation Criteria** | Fully configurable per round (admin defines) |
|
||||
| **CSV Import** | Flexible column mapping (admin maps columns) |
|
||||
| **Max File Size** | 500MB (for videos) |
|
||||
| **Observer Role** | Included in Phase 1 |
|
||||
| **First Admin** | Database seed script |
|
||||
| **Past Evaluations** | Visible read-only after submit |
|
||||
| **Grace Period** | Admin-configurable per juror/project |
|
||||
| **Smart Assignment** | AI-powered (GPT) + Smart Algorithm fallback |
|
||||
| **AI Provider** | Admin-configurable (OpenAI GPT) |
|
||||
| **AI Data Privacy** | All data anonymized/encoded before sending to GPT |
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology | Version |
|
||||
|-------|-----------|---------|
|
||||
| **Framework** | Next.js (App Router) | 15.x |
|
||||
| **Language** | TypeScript | 5.x |
|
||||
| **UI Components** | shadcn/ui | latest |
|
||||
| **Styling** | Tailwind CSS | 3.x |
|
||||
| **API Layer** | tRPC | 11.x |
|
||||
| **Database** | PostgreSQL | 16.x |
|
||||
| **ORM** | Prisma | 6.x |
|
||||
| **Authentication** | NextAuth.js (Auth.js) | 5.x |
|
||||
| **AI** | OpenAI GPT | 4.x SDK |
|
||||
| **File Storage** | MinIO (S3-compatible) | External |
|
||||
| **Email** | Nodemailer + Poste.io | External |
|
||||
| **Animation** | Motion (Framer Motion) | 11.x |
|
||||
| **Notifications** | Sonner | 1.x |
|
||||
| **Command Palette** | cmdk | 1.x |
|
||||
| **Containerization** | Docker Compose | 2.x |
|
||||
| **Reverse Proxy** | Nginx | External |
|
||||
|
||||
## Brand Identity
|
||||
|
||||
### Colors
|
||||
| Name | Hex | Usage |
|
||||
|------|-----|-------|
|
||||
| Primary Red | `#de0f1e` | Accents, CTAs, alerts |
|
||||
| Dark Blue | `#053d57` | Headers, sidebar, primary text |
|
||||
| White | `#fefefe` | Backgrounds |
|
||||
| Teal | `#557f8c` | Secondary elements, links |
|
||||
|
||||
### Typography
|
||||
- **Headings**: Montserrat (600/700 weight)
|
||||
- **Body**: Montserrat Light (300/400 weight)
|
||||
|
||||
## High-Level Architecture Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ PRESENTATION LAYER │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ Admin Views │ │ Jury Views │ │ Auth Views │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ - Dashboard │ │ - Project List │ │ - Login │ │
|
||||
│ │ - Rounds │ │ - Project View │ │ - Magic Link │ │
|
||||
│ │ - Projects │ │ - Evaluation │ │ - Verify │ │
|
||||
│ │ - Jury Mgmt │ │ - My Progress │ │ │ │
|
||||
│ │ - Assignments │ │ │ │ │ │
|
||||
│ │ - Reports │ │ │ │ │ │
|
||||
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
|
||||
│ │
|
||||
│ Built with: Next.js App Router + React Server Components + shadcn/ui │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ API LAYER │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ tRPC Router │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
|
||||
│ │ │program │ │ round │ │project │ │ user │ │assign- │ │evalua- │ │ │
|
||||
│ │ │Router │ │Router │ │Router │ │Router │ │ment │ │tion │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │ │Router │ │Router │ │ │
|
||||
│ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ Auth Middleware │ │ RBAC Middleware │ │ Audit Logger │ │
|
||||
│ │ (NextAuth.js) │ │ (role checks) │ │ (all actions) │ │
|
||||
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ SERVICE LAYER │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ Program │ │ Round │ │ Assignment │ │ Evaluation │ │
|
||||
│ │ Service │ │ Service │ │ Service │ │ Service │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ File │ │ Email │ │ Export │ │ Audit │ │
|
||||
│ │ Service │ │ Service │ │ Service │ │ Service │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ DATA LAYER │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Prisma ORM │ │
|
||||
│ │ │ │
|
||||
│ │ Type-safe database access, migrations, query building │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ PostgreSQL │ │ MinIO │ │
|
||||
│ │ (Database) │ │ (File Store) │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ - Users │ │ - PDFs │ │
|
||||
│ │ - Programs │ │ - Videos │ │
|
||||
│ │ - Rounds │ │ - Exports │ │
|
||||
│ │ - Projects │ │ │ │
|
||||
│ │ - Evaluations │ │ │ │
|
||||
│ │ - Audit Logs │ │ │ │
|
||||
│ └──────────────────┘ └──────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Component Responsibilities
|
||||
|
||||
### Presentation Layer
|
||||
|
||||
| Component | Responsibility |
|
||||
|-----------|----------------|
|
||||
| **Admin Views** | Program/round management, project import, jury management, assignments, dashboards |
|
||||
| **Jury Views** | View assigned projects, evaluate projects, track progress |
|
||||
| **Auth Views** | Login, magic link verification, session management |
|
||||
| **Layouts** | Responsive navigation, sidebar, mobile adaptations |
|
||||
| **UI Components** | shadcn/ui based, reusable, accessible |
|
||||
|
||||
### API Layer
|
||||
|
||||
| Component | Responsibility |
|
||||
|-----------|----------------|
|
||||
| **tRPC Routers** | Type-safe API endpoints grouped by domain |
|
||||
| **Auth Middleware** | Session validation via NextAuth.js |
|
||||
| **RBAC Middleware** | Role-based access control enforcement |
|
||||
| **Audit Logger** | Record all significant actions |
|
||||
| **Validators** | Zod schemas for input validation |
|
||||
|
||||
### Service Layer
|
||||
|
||||
| Service | Responsibility |
|
||||
|---------|----------------|
|
||||
| **ProgramService** | CRUD for programs (e.g., "MOPC 2026") |
|
||||
| **RoundService** | Round lifecycle, voting windows, form versions |
|
||||
| **AssignmentService** | Jury-project assignments, load balancing |
|
||||
| **EvaluationService** | Form submission, autosave, scoring |
|
||||
| **FileService** | MinIO uploads, pre-signed URLs |
|
||||
| **EmailService** | Magic links, notifications via Nodemailer |
|
||||
| **ExportService** | CSV/Excel generation |
|
||||
| **AuditService** | Immutable event logging |
|
||||
|
||||
### Data Layer
|
||||
|
||||
| Component | Responsibility |
|
||||
|-----------|----------------|
|
||||
| **Prisma Client** | Type-safe database queries |
|
||||
| **PostgreSQL** | Primary data store (relational) |
|
||||
| **MinIO** | S3-compatible file storage |
|
||||
| **Migrations** | Schema versioning and evolution |
|
||||
|
||||
## Data Flow Examples
|
||||
|
||||
### 1. Jury Login Flow
|
||||
|
||||
```
|
||||
User Next.js NextAuth PostgreSQL
|
||||
│ │ │ │
|
||||
│ 1. Enter email │ │ │
|
||||
│───────────────────────>│ │ │
|
||||
│ │ 2. Request magic link │ │
|
||||
│ │───────────────────────>│ │
|
||||
│ │ │ 3. Store token │
|
||||
│ │ │───────────────────────>│
|
||||
│ │ │<───────────────────────│
|
||||
│ │ 4. Send email │ │
|
||||
│ │<───────────────────────│ │
|
||||
│ 5. Email with link │ │ │
|
||||
│<───────────────────────│ │ │
|
||||
│ │ │ │
|
||||
│ 6. Click link │ │ │
|
||||
│───────────────────────>│ │ │
|
||||
│ │ 7. Verify token │ │
|
||||
│ │───────────────────────>│ │
|
||||
│ │ │ 8. Validate │
|
||||
│ │ │───────────────────────>│
|
||||
│ │ │<───────────────────────│
|
||||
│ │ 9. Create session │ │
|
||||
│ │<───────────────────────│ │
|
||||
│ 10. Redirect to dash │ │ │
|
||||
│<───────────────────────│ │ │
|
||||
```
|
||||
|
||||
### 2. Jury Evaluation Flow
|
||||
|
||||
```
|
||||
Jury Member Next.js/tRPC Service Layer PostgreSQL/MinIO
|
||||
│ │ │ │
|
||||
│ 1. View project list │ │ │
|
||||
│───────────────────────>│ 2. project.listAssigned() │
|
||||
│ │───────────────────────>│ 3. Query assignments │
|
||||
│ │ │───────────────────────>│
|
||||
│ │ │<───────────────────────│
|
||||
│ 4. Show assigned projects │ │
|
||||
│<───────────────────────│ │ │
|
||||
│ │ │ │
|
||||
│ 5. Open project │ │ │
|
||||
│───────────────────────>│ 6. project.getDetails() │
|
||||
│ │───────────────────────>│ 7. Get project + files│
|
||||
│ │ │───────────────────────>│
|
||||
│ │ │ 8. Generate pre-signed URLs
|
||||
│ │ │<───────────────────────│
|
||||
│ 9. Show project with file links │ │
|
||||
│<───────────────────────│ │ │
|
||||
│ │ │ │
|
||||
│ 10. Fill evaluation │ │ │
|
||||
│ (typing...) │ 11. evaluation.autosave() (debounced) │
|
||||
│───────────────────────>│───────────────────────>│ 12. Save draft │
|
||||
│ │ │───────────────────────>│
|
||||
│ │ │<───────────────────────│
|
||||
│ 13. Autosaved indicator │ │
|
||||
│<───────────────────────│ │ │
|
||||
│ │ │ │
|
||||
│ 14. Submit final │ │ │
|
||||
│───────────────────────>│ 15. evaluation.submit() │
|
||||
│ │───────────────────────>│ 16. Validate window │
|
||||
│ │ │ 17. Lock evaluation │
|
||||
│ │ │ 18. Log audit event │
|
||||
│ │ │───────────────────────>│
|
||||
│ │ │<───────────────────────│
|
||||
│ 19. Success, mark complete │ │
|
||||
│<───────────────────────│ │ │
|
||||
```
|
||||
|
||||
### 3. Admin Export Flow
|
||||
|
||||
```
|
||||
Admin Next.js/tRPC Service Layer PostgreSQL/MinIO
|
||||
│ │ │ │
|
||||
│ 1. Request CSV export │ │ │
|
||||
│───────────────────────>│ 2. export.generateCSV() │
|
||||
│ │───────────────────────>│ 3. Query all evals │
|
||||
│ │ │───────────────────────>│
|
||||
│ │ │<───────────────────────│
|
||||
│ │ │ 4. Build CSV │
|
||||
│ │ │ 5. Upload to MinIO │
|
||||
│ │ │───────────────────────>│
|
||||
│ │ │<───────────────────────│
|
||||
│ │ │ 6. Log audit event │
|
||||
│ │ │───────────────────────>│
|
||||
│ │ 7. Return download URL│ │
|
||||
│ │<───────────────────────│ │
|
||||
│ 8. Download file │ │ │
|
||||
│<───────────────────────│ │ │
|
||||
```
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### Authentication
|
||||
- **Method**: Email magic links (passwordless)
|
||||
- **Sessions**: JWT stored in HTTP-only cookies
|
||||
- **Provider**: NextAuth.js with custom email provider
|
||||
|
||||
### Authorization (RBAC)
|
||||
- **Enforcement**: tRPC middleware checks role before procedure
|
||||
- **Granularity**: Role + resource-level (jury sees only assigned projects)
|
||||
- **Storage**: User.role field in database
|
||||
|
||||
### Data Security
|
||||
- **File Access**: Pre-signed URLs with short TTL (15 min)
|
||||
- **SQL Injection**: Prevented by Prisma parameterized queries
|
||||
- **XSS**: React's built-in escaping + CSP headers
|
||||
- **CSRF**: NextAuth.js built-in protection
|
||||
|
||||
### Audit Trail
|
||||
- **Coverage**: All admin actions, all state changes
|
||||
- **Immutability**: Append-only audit_logs table
|
||||
- **Fields**: user, action, entity, details, timestamp, IP
|
||||
|
||||
## Scalability Considerations
|
||||
|
||||
### Current Design (Phase 1)
|
||||
- Single PostgreSQL instance (sufficient for ~200 concurrent users)
|
||||
- Single Next.js instance behind Nginx
|
||||
- MinIO for file storage (horizontally scalable)
|
||||
|
||||
### Future Scale Path
|
||||
1. **Database**: Read replicas for dashboards, connection pooling (PgBouncer)
|
||||
2. **Application**: Multiple Next.js instances behind load balancer
|
||||
3. **Caching**: Redis for session storage and query caching
|
||||
4. **CDN**: Static assets via CDN
|
||||
5. **Background Jobs**: BullMQ for email queues, exports
|
||||
|
||||
## Smart Assignment System
|
||||
|
||||
The platform includes two assignment modes:
|
||||
|
||||
### 1. AI-Powered Assignment (GPT)
|
||||
- Analyzes juror expertise and project tags
|
||||
- Optimizes for balanced workload
|
||||
- Respects organizational conflicts
|
||||
- **Privacy**: All data is anonymized before sending to GPT
|
||||
- Names → `JUROR_A`, `JUROR_B`
|
||||
- Projects → `PROJECT_1`, `PROJECT_2`
|
||||
- Organizations → `ORG_X`, `ORG_Y`
|
||||
- Emails and personal details are never sent
|
||||
|
||||
### 2. Smart Algorithm (Rule-Based Fallback)
|
||||
- Fully featured scoring algorithm
|
||||
- No external API required
|
||||
- Handles 200 projects × 50 jurors in < 1 second
|
||||
- Deterministic results
|
||||
|
||||
**Scoring Formula**:
|
||||
```
|
||||
Score = (expertise_match × 40) + (load_balance × 25) +
|
||||
(specialty_match × 20) + (diversity × 10) - (conflict × 100)
|
||||
```
|
||||
|
||||
## Admin Settings Panel
|
||||
|
||||
Centralized configuration for:
|
||||
- **AI Configuration**: Provider, API key, model, budget limits
|
||||
- **Platform Branding**: Logo, colors, name
|
||||
- **Email/SMTP**: Server, credentials, templates
|
||||
- **File Storage**: MinIO endpoint, bucket, limits
|
||||
- **Security**: Session duration, rate limits
|
||||
- **Defaults**: Timezone, pagination, autosave interval
|
||||
|
||||
## User Roles (RBAC)
|
||||
|
||||
| Role | Permissions |
|
||||
|------|------------|
|
||||
| **SUPER_ADMIN** | Full system access, all programs, user management |
|
||||
| **PROGRAM_ADMIN** | Manage specific programs, rounds, projects, jury |
|
||||
| **JURY_MEMBER** | View assigned projects only, submit evaluations |
|
||||
| **OBSERVER** | Read-only access to dashboards |
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Database Design](./database.md) - Schema, relationships, indexes
|
||||
- [API Design](./api.md) - tRPC routers, endpoints, auth flow
|
||||
- [Infrastructure](./infrastructure.md) - Docker, Nginx, deployment
|
||||
- [UI/UX Patterns](./ui.md) - Components, responsive design
|
||||
Reference in New Issue
Block a user