All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
<<<<<<< feature/deep-scan-governance-rollout
- Governance baseline for solo-safe development:
CODEOWNERS, PR template, structured issue templates, a live workboard, and repo-local skills under.agents/. - CI coverage for documentation drift and Terraform parsing via
docs-checkandterraform-validate. code-review.ymlworkflow to summarize PR review context against the required branch checks.
- Local Docker defaults no longer rely on a pre-created
.env;.env.exampleis now the explicit starting point. - Documentation now treats
documentation/WORKBOARD.mdas the source of truth for milestone, issue, and branch tracking. - Terraform, Docker, and config baselines were corrected to match the current repository layout and runtime behavior. =======
- Project structure overhaul: moved Lambda function source code (
campaign_mailer/,registration_worker/) from the repository root intophishing-platform-infra/lambda/so all AWS infrastructure assets are co-located under one top-level directory. - Build scripts updated:
scripts/build_campaign_mailer.shandscripts/build_registration_worker.shnow resolve source files from their new location underphishing-platform-infra/lambda/. - Directory rename:
Phishing AOC/renamed tophishing-aoc/to remove the space from the directory name. - Documentation reorganised: root-level guide files moved to the appropriate
documentation/subdirectory —DEPLOYMENT_GUIDE.md→documentation/operator/,TESTING_GUIDE.mdandREALISM_GUIDE.md→documentation/dev/. - README updated: repository structure tree reflects the new layout with
phishing-platform-infra/lambda/and consolidated documentation paths.
documentation/REPO_SEPARATION.md: step-by-step guide for splitting the Flask application and AWS infrastructure into two standalone repositories, includinggit filter-repocommands, CI/CD handoff strategy, and CODEOWNERS alternative.- Documentation index updates:
documentation/README.md,documentation/dev/README.md, anddocumentation/operator/README.mdnow list all files in their respective directories.
main
- Real-time cache + SSE: provisioned ElastiCache Redis with pub/sub wiring in the dashboard for live stats and OpenPhish caching; added threat-cache DynamoDB table for TTL persistence.
- Campaign mailer pipeline: new SQS campaign queue, Lambda campaign mailer, EventBridge scheduler (optional), and DynamoDB
campaigns+campaign_eventstables for tracking. - Admin tooling: dashboard now targets cohorts/groups for campaign launches and validation emails via SES with Redis-backed updates.
- Build tooling:
make campaign-mailer+scripts/build_campaign_mailer.shto package the new Lambda.
- Main Lambda now runs inside the default VPC for Redis access and publishes campaign/threat feed updates through Redis where available.
- Local setup scripts and tests create the new DynamoDB tables and queues; README documents the additional env vars and targets.
- Split infrastructure assets into
phishing-platform-infra/(Terraform, Ansible, legacy AWS helpers, infra scripts) and retargeted deploy workflows/docs to the new path.
- Full documentation overhaul — accuracy and completeness pass across all 13 documentation files:
documentation/operator/CICD.md— full rewrite replacing GitLab CI content with accurate GitHub Actions coverage (4 workflows, OIDC auth flow, Mermaid pipeline diagram, required secrets/environments)documentation/dev/SETUP.md— fixed allen-garde-dev-*table names tophishing-app-dev-*; added missing env vars (DYNAMODB_COHORT_TOKENS,SQS_REGISTRATION_QUEUE_URL,SES_FROM_EMAIL); added Docker Compose Option A section withsetup_local_db.pystepCLAUDE.md— fixeden-garde-dev-*env var examples; added missing env vars; updated CI/CD deployment note to mention OIDC and all 4 workflowsREADME.md— fixeden-garde-dev-*table names and S3 bucket in Quick Start blockdocumentation/ARCHITECTURE.md— updated "En Garde" title to project name; fixed Lambda/IAM/S3/CloudWatch naming (en-garde-*→phishing-app-*); added new quizzes to quiz catalog; added AWS service badges; fixed local dev.envS3_BUCKET referencedocumentation/REQUIREMENTS.md— updated title; added GDPR anonymous inspector requirement and QR+SQS registration requirementdocumentation/operator/DEPLOYMENT.md— removed GitLab CI references; added GitHub Environment Setup section; fixed S3 bucket name examplesdocumentation/operator/INFRASTRUCTURE.md— added cohort-tokens table; fixeden-gardenaming; added SQS DLQ; added AWS service badgesdocumentation/operator/README.md— replaced GitLab CI reference with GitHub Actionsdocumentation/user/STUDENT_GUIDE.md— replaced Obsidian image tags with descriptive text; added Quiz Completion and Inspector Completion sectionsdocumentation/user/ADMIN_GUIDE.md— replaced Obsidian image tags with descriptive text; added QR Code Generation, Inspector Reset, and Answer Key Editor sectionsaws/README.md— added deprecation banner (legacy EC2 guide)
- New developer guides:
documentation/dev/ADDING_QUIZZES.mdanddocumentation/dev/ADDING_EML_FILES.md
- No application code changes in this release — documentation only.
-
Documentation overhaul — comprehensive update to all four documentation files based on a full codebase scan:
documentation/ARCHITECTURE.md— updated CI/CD pipeline diagram to reflect the actual three-job structure (ci→plan_dev→deploy_dev), IAM bootstrap step,deploy-prod.ymlanddestroy.ymlworkflows, and refined blueprint routing table with all current routesdocumentation/REQUIREMENTS.md— added full functional requirements section (AUTH, QUIZ, INSP, DASH, WORK), expanded non-functional requirements, updated IAM permission tables to match currentgithub_actions_oidc.tf(addedTagResource,UntagResource,ListTagsfor Lambda;GetFunctionCodeSigningConfig;ListIdentitiesfor SES;GetSubscriptionAttributes,ListSubscriptionsByTopicfor SNS;ListQueueTagsfor SQS;ListTagsForResourcefor CloudWatch;ListInstanceProfilesForRole,TagRolefor IAM), expanded DynamoDB and CloudWatch alarm reference tablesCHANGELOG.md— this entry
-
VERSIONfile — addedVERSIONfile at project root, set to1.2.3
- No application code changes in this release — documentation only.
- Architecture documentation (
documentation/ARCHITECTURE.md) — 10 Mermaid diagrams rendered natively on GitHub covering:- System Overview (C4-style context: actors + all AWS services)
- AWS Infrastructure (all resources grouped by service)
- Flask Software Architecture (app factory, blueprints, models, config)
- DynamoDB Schema (all 9 tables, PKs, SKs, GSIs, and relationships)
- CI/CD Pipeline (push → CI → Terraform → seed full flow)
- Login Flow (sequence diagram with auth paths)
- Quiz Flow (flowchart including video gate and one-attempt enforcement)
- Email Inspector Flow (sequence diagram with S3/DDB interactions per email)
- QR Self-Registration Flow (async SQS/Lambda/SES registration sequence)
- Local Development Architecture (Docker Compose vs standalone dev server)
README.md: added link todocumentation/ARCHITECTURE.mdunder the Requirements section
- Makefile (
S3_BUCKET := …→S3_BUCKET = …):S3_BUCKETwas a simply-expanded variable (:=), causingterraform outputto run at Makefile parse time — beforeterraform initis called. This leaked a "Backend initialization required" Terraform error into the stderr of themake lambdaCI step. Changed to a recursively-expanded variable (=) so theterraform outputcall only runs whensync-assetsis actually invoked. deploy-dev.yml: Addedchmod +x scripts/*.shstep beforemake lambda. Globalcore.filemode=false(set by Windows/WSL2 git config) can silently drop the execute bit when shell scripts are committed from a Windows filesystem, causingPermission deniedon the runner despite the git tree recording100755. The explicitchmodmakes the workflow resilient to this regardless of the committed file mode.
- UI overhaul — quiz cards, score ring, stat cards, rank badges, and video gate redesign for improved student experience
fix: use direct S3 URL for videos— CloudFront has no S3 origin configured; video assets must be served directly from S3fix: update VIDEO_BASE_URL to use CloudFront URL for video assets— seeder and README updated to reflect correct base URLfix: app_name en-garde → phishing-app— updated in all three workflow files (deploy-dev.yml,deploy-prod.yml,destroy.yml) so Terraform resource prefixes match the deployed infrastructurefix: add CloudWatchLogDelivery IAM permission— addedlogs:CreateLogDeliveryand related permissions togithub_actions_oidc.tfso API Gateway structured access logs can be configured by CI
- CloudFront distribution (
terraform/cloudfront.tf) — stabledXXXXX.cloudfront.netURL in front of API Gateway; survives Lambda/API Gateway destroy-recreate cycles without changing the URL shared with students- No custom domain or ACM certificate required (uses AWS-managed
*.cloudfront.netcertificate) - Zero-TTL caching — all requests pass through to the Flask app (correct for session-based app)
- All cookies and query strings forwarded; all 7 HTTP methods allowed
- HTTP → HTTPS redirect enforced via
viewer_protocol_policy = "redirect-to-https"
- No custom domain or ACM certificate required (uses AWS-managed
- New Terraform output
cloudfront_urlinterraform/outputs.tf— prints the stable URL afterterraform apply
- Editable Answer Key (Admin UI) — admins can now change any email's classification (Phishing ↔ Spam) and required signals without a code deployment
- New "Edit" button per row in Admin → Inspector Analytics → View Answer Key & Troubleshoot
- Edit modal with classification radio buttons, signal checkboxes (all 10 signal types), and explanation textarea
- "Save Changes" posts to
POST /dashboard/inspector/answer-key/edit; row DOM is updated immediately without a page reload - "Reset to Default" posts to
POST /dashboard/inspector/answer-key/reset; reverts toanswer_key.pybaseline - Yellow "overridden" badge shown on rows that have a DynamoDB override active
- DynamoDB Answer Key Overrides table (
DYNAMODB_ANSWER_KEY_OVERRIDES) — persists admin overrides keyed byemail_file; survives Lambda restarts get_effective_answer_key()inapp/models.py— merges staticANSWER_KEYdict with DynamoDB overrides at runtime (overrides win); falls back gracefully if the table does not existget_answer_key_overrides(),set_answer_key_override(),delete_answer_key_override()added toapp/models.py- Dynamic signal count — required signal count per email is now driven by
len(entry['signals'])from the effective answer key, not hardcoded to 3api_email_detailresponse includesrequiredSignals(integer)- Student JS reads
requiredSignalsand updates instruction text ("Select exactly N phishing signal(s)") and submit validation accordingly - Server-side
api_submitvalidates against the dynamic count
- New admin dashboard routes:
POST /dashboard/inspector/answer-key/editandPOST /dashboard/inspector/answer-key/reset
app/inspector/routes.py: removed staticANSWER_KEYimport; all answer key lookups now go throughget_effective_answer_key()app/dashboard/routes.py:inspector_answer_key()passeshas_overrideflag per item to templateapp/templates/admin/inspector_answer_key.html: column header renamed from "Required Phishing Signals (3)" → "Required Signals"- README project description updated: "Cloud SecDevOps course (TP1/TP2)" → "Master Project"
tests/conftest.py: addedDYNAMODB_ANSWER_KEY_OVERRIDESenv var (test-answer-key-overrides) and table creation soget_effective_answer_key()works correctly in tests
- GitLab CI: corrected heredoc indentation in destroy jobs to prevent YAML/shell parse errors.
- GitLab CI: seed step now uses a venv to avoid PEP 668 "externally managed" failures.
- GitLab CI: seed step reads Terraform outputs from
terraform/aftercd ..to avoid invalid DynamoDB table names. - Safe commit:
7f023ef3b34d6e6c1022a038e60fcae89dd8aee0.
- Email Threat Inspector (
/inspector/) — a standalone email analysis tool modeled after TryHackMe's "Wareville Email Threat Inspector"- Sidebar listing all 6
.emlfiles fromexamples/with subject, from, to, and date metadata - Full email detail view with: message overview, HTML preview (sandboxed iframe), headers table, extracted links, attachments list, and security warnings
- Client-side classification form: users classify each email as Spam or Phishing, select phishing signals, and receive immediate correct/incorrect feedback with CTF flags
- 10 phishing signal categories supported: Impersonation, Typosquatting/Punycodes, External Sender Domain, Spoofing, Social Engineering Text, Sense of Urgency, Fake Invoice, Malicious Attachment, Fake Login Page, Side Channel Communication Attempt
- Backend EML parsing using Python stdlib (
emailmodule) — no new dependencies - Path traversal protection on the email detail API endpoint
- Security warnings auto-detected: From/Return-Path domain mismatch, punycode domains in links, suspicious
@in URLs
- Sidebar listing all 6
- New Flask blueprint:
app/inspector/with 3 routes (/inspector/,/inspector/api/emails,/inspector/api/emails/<filename>) - Standalone dark-themed inspector template (does not extend
base.html) - "Email Inspector" link added to the main app navbar
.emlfiles now included in Docker image (COPY examples/ examples/in Dockerfile, removedexamples/from.dockerignore)
app/inspector/__init__.py— Blueprint registrationapp/inspector/routes.py— API routes and EML parsing logicapp/templates/inspector/inspector.html— Standalone inspector UI (CSS + JS)
app/__init__.py— Registered inspector blueprintapp/templates/base.html— Added "Email Inspector" navbar link.dockerignore— Removedexamples/exclusionDockerfile— AddedCOPY examples/ examples/
- Phishing Awareness Quiz App — Flask web application for phishing awareness training
- User authentication: register, login, logout with password hashing (Werkzeug)
- Admin vs regular user roles (
is_adminflag) - Quiz system: list quizzes, take multiple-choice quizzes, view explanations after each question, progress bar, score summary with color-coded feedback
- Quiz history per user
- Admin dashboard: stat cards (total users, attempts, average score), score distribution bar chart (Chart.js), per-quiz stats table, recent activity table
- Seed script (
seed.py) creating admin user and 10 phishing awareness questions
- Data models: User, Quiz, Question, Answer, QuizAttempt (SQLAlchemy + SQLite)
- Docker support: Dockerfile (python:3.12-slim + gunicorn), docker-compose.yml (web + Nginx), Nginx reverse proxy config
- AWS deployment guide:
aws/README.mdwith EC2 Free Tier setup,user-data.shboot script,env.exampletemplate - Real phishing email samples (
examples/): 6.emlfiles from TryHackMe Advent of Cyber lab covering fake invoices, impersonation, urgency, spoofing, punycode, and spam - TryHackMe reference materials (
Phishing AOC/): CTF flags/answers, download scripts, email inspector source HTML