diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..341cd60
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,24 @@
+# ===========================================
+# Pretexta - Environment Configuration
+# ===========================================
+# Copy this file to .env and fill in your values
+# cp .env.example .env
+
+# ---- Ports ----
+FRONTEND_PORT=9443
+BACKEND_PORT=9442
+MONGO_PORT=47017
+
+# ---- MongoDB ----
+MONGO_USERNAME=soceng_admin
+MONGO_PASSWORD=soceng_secure_password_2025
+DB_NAME=Pretexta
+
+# ---- JWT Secret (CHANGE IN PRODUCTION) ----
+JWT_SECRET=change-this-secret-key-in-production
+
+# ---- CORS Origins (comma-separated) ----
+CORS_ORIGINS=http://localhost:9443,http://localhost:80
+
+# ---- Frontend โ Backend URL ----
+REACT_APP_BACKEND_URL=http://localhost:9442
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..612211c
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,67 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+jobs:
+ backend-lint:
+ name: Backend Lint
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: backend
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.11"
+
+ - name: Install ruff
+ run: pip install ruff
+
+ - name: Lint
+ run: ruff check .
+
+ - name: Format check
+ run: ruff format --check .
+
+ frontend-lint:
+ name: Frontend Lint & Build
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: frontend
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+ cache: "yarn"
+ cache-dependency-path: frontend/yarn.lock
+
+ - name: Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: Lint
+ run: yarn lint 2>/dev/null || true
+
+ - name: Build
+ run: yarn build
+
+ docker-build:
+ name: Docker Build
+ runs-on: ubuntu-latest
+ needs: [backend-lint, frontend-lint]
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Build backend image
+ run: docker build -f Dockerfile.backend -t pretexta-backend:test .
+
+ - name: Build frontend image
+ run: docker build -f Dockerfile.frontend -t pretexta-frontend:test .
diff --git a/Dockerfile.frontend b/Dockerfile.frontend
index 39ed265..e9cab13 100644
--- a/Dockerfile.frontend
+++ b/Dockerfile.frontend
@@ -1,8 +1,12 @@
-FROM node:20-alpine as builder
+FROM node:20-alpine AS builder
# Set working directory
WORKDIR /app
+# Build arg โ passed from docker-compose at build time
+ARG REACT_APP_BACKEND_URL=http://localhost:9442
+ENV REACT_APP_BACKEND_URL=$REACT_APP_BACKEND_URL
+
# Copy package files
COPY frontend/package.json frontend/yarn.lock ./
@@ -12,7 +16,7 @@ RUN yarn install --frozen-lockfile
# Copy source code
COPY frontend/ .
-# Build the application
+# Build the application (REACT_APP_* env vars are baked in here)
RUN yarn build
# Production stage
@@ -28,4 +32,4 @@ COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 3000
# Start nginx
-CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
+CMD ["nginx", "-g", "daemon off;"]
diff --git a/Makefile b/Makefile
index e9a386f..172ace6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
# SocengLab Makefile
-.PHONY: help install build up down restart logs clean test seed
+.PHONY: help install build up down restart logs clean test seed lint lint-fix
# Default target
help:
@@ -23,6 +23,8 @@ help:
@echo " make logs-backend - Show backend logs only"
@echo " make logs-frontend - Show frontend logs only"
@echo " make test - Run tests"
+ @echo " make lint - Run backend linter"
+ @echo " make lint-fix - Auto-fix lint issues"
@echo ""
@echo "Maintenance:"
@echo " make clean - Remove containers and volumes"
@@ -37,20 +39,22 @@ install:
build:
@echo "Building Docker images..."
+ @if [ ! -f .env ]; then cp .env.example .env && echo "๐ Created .env from .env.example"; fi
@docker-compose build
@echo "โ
Docker images built"
up:
@echo "Starting Pretexta..."
+ @if [ ! -f .env ]; then cp .env.example .env && echo "๐ Created .env from .env.example"; fi
@docker-compose up -d
@echo "โณ Waiting for services to start..."
@sleep 10
@echo ""
@echo "โ
Pretexta is running!"
@echo ""
- @echo "๐ Frontend: http://localhost:3000"
- @echo "๐ Backend API: http://localhost:8001"
- @echo "๐๏ธ MongoDB: mongodb://localhost:27017"
+ @echo "๐ Frontend: http://localhost:9443"
+ @echo "๐ Backend API: http://localhost:9442"
+ @echo "๐๏ธ MongoDB: mongodb://localhost:47017"
@echo ""
@echo "๐ Default credentials: soceng / Cialdini@2025!"
@echo ""
@@ -76,7 +80,7 @@ logs-frontend:
@docker-compose logs -f frontend
db-shell:
- @docker-compose exec mongodb mongosh -u soceng_admin -p soceng_secure_password_2025 --authenticationDatabase admin Pretexta
+ @docker-compose exec mongodb mongosh -u soceng_admin -p soceng_secure_password_2025 --authenticationDatabase admin Pretexta 2>/dev/null || docker compose exec mongodb mongosh -u soceng_admin -p soceng_secure_password_2025 --authenticationDatabase admin Pretexta
seed:
@echo "Importing sample challenges and quizzes..."
@@ -90,6 +94,18 @@ test:
@cd frontend && yarn test --watchAll=false
@echo "โ
Tests completed"
+lint:
+ @echo "Linting backend..."
+ @cd backend && ruff check .
+ @cd backend && ruff format --check .
+ @echo "โ
Backend lint passed"
+
+lint-fix:
+ @echo "Fixing backend lint issues..."
+ @cd backend && ruff check --fix .
+ @cd backend && ruff format .
+ @echo "โ
Backend lint fixed"
+
clean:
@echo "Cleaning up containers and volumes..."
@docker-compose down -v
diff --git a/README.md b/README.md
index de41bbb..eaad620 100644
--- a/README.md
+++ b/README.md
@@ -2,163 +2,326 @@
-### The Psychology Behind Successful Attacks
-#### An Open Source Lab for Simulating Human Exploitation via Social Engineering
+**Defensive Social Engineering Simulation Lab**
-
-
-
-
+Train your team to recognize and resist psychological attacks โ before real attackers strike.
+
+[](https://github.com/fdciabdul/Pretexta/releases)
+[](LICENSE)
+[](https://github.com/fdciabdul/Pretexta/actions)
+[](CONTRIBUTING.md)
+
+[Quick Start](#quick-start) ยท [Features](#features) ยท [LLM Providers](#llm-providers) ยท [Contributing](#contributing)
---
-Most security tools are designed to protect systems. **Pretexta is designed to understand why humans fail.
-
** Modern social engineering attacks do not rely on malware or exploits. They rely on **pretexting, authority, urgency, trust, and cognitive bias**.
+## Why Pretexta?
-Pretexta was created as an **open source simulation lab** to model how thesepsychological attack techniques work in practice โ in a controlled, ethical, and defensive environment.
-This project focuses on **learning, experimentation, and community research**,
-not on generating real-world attacks.
+Most security tools protect systems. Pretexta protects **people**.
----
+Social engineering is the #1 attack vector โ and it doesn't exploit software. It exploits **trust, urgency, authority, and cognitive bias**. Pretexta is an open-source simulation lab where your team practices defending against these attacks in a safe, controlled environment.
-### What Pretexta Is
+Built on **Cialdini's 6 Principles of Influence**: Reciprocity, Scarcity, Authority, Commitment, Liking, and Social Proof.
-- A **defensive social engineering simulation lab**
-- A platform to study **human decision-making under pressure**
-- An interactive environment for experimenting with **pretexting techniques**
-- A community-driven, **fully open source** research project
+## Screenshots
-All scenarios are **fictional, self-contained, and designed for defense and education only**.
+Dashboard
----
+
-### Features
+AI Chat Simulation โ Real-time roleplay with "The Urgent CEO"
----
+
-### How a Typical Demo Works
+AI Challenge Selection โ 8 built-in social engineering personas
-This flow is intentionally designed to fit a **short, repeatable demo format**
-suitable for live Demo Lab environments.
+
----
+Settings โ 6 LLM providers with model selection (200+ models via OpenRouter)
+
+
-### Quick Start (Demo Environment)
+Leaderboard โ XP, levels, streaks, and rankings
+
+
+
+Login
+
+
+
+30+ REST Endpoints (click to expand)
+
+| Group | Endpoints |
+|-------|-----------|
+| **Auth** | `POST /register`, `POST /login`, `GET /me`, `PUT /profile`, `POST /change-password` |
+| **Challenges** | `GET /challenges`, `GET /challenges/:id`, `POST /challenges` |
+| **Quizzes** | `GET /quizzes`, `GET /quizzes/:id` |
+| **Simulations** | `CRUD /simulations` |
+| **LLM** | `GET /providers`, `GET /models/:provider`, `POST /config`, `POST /generate`, `POST /chat` |
+| **Campaigns** | `GET /campaigns`, `POST /start`, `POST /stage/:idx/complete` |
+| **Leaderboard** | `GET /leaderboard`, `GET /me`, `GET /badges` |
+| **Analytics** | `GET /personal`, `GET /team` |
+| **Organizations** | `POST /create`, `GET /mine`, `POST /join`, `DELETE /leave` |
+| **Debrief** | `GET /:simulation_id`, `POST /:simulation_id/ai-analysis` |
+| **Certificates** | `GET /:simulation_id`, `GET /user/all` |
+| **Notifications** | `GET /`, `PUT /:id/read`, `PUT /read-all` |
+| **Webhooks** | `CRUD /webhooks` |
+| **Scenario Builder** | `CRUD /templates`, `POST /publish` |
+| **Adaptive** | `GET /difficulty`, `GET /persona-params` |
+| **Health** | `GET /health` |
+
+All endpoints prefixed with `/api`. Full OpenAPI docs at `/docs` when running.
+
+
+ to {to || 'me'} + {cc && , cc: {cc}} +
++ Something went wrong. The application encountered an unexpected error. +
+
+ {this.state.error?.message || 'Unknown error'}
+
+
+