Skip to content

Repository files navigation

NotJira Banner

NotJira

A secure, highly available task-management platform deployed on AWS, demonstrating cloud architecture, RBAC, event-driven processing, serverless workloads, monitoring, and secure network design.

Live Demo β€’ Demo Video β€’ Architecture β€’ Security

Demo Availability To minimize AWS costs, compute resources may occasionally be offline. If the live application is unavailable, the complete deployment and high-availability demonstration can be viewed in the demo video.


πŸš€ Quick Start

Demo Accounts

Role Email Password Access
Manager ali@minijira.com Password123! All teams, create/assign tasks, audit log
Employee (Frontend) sara@minijira.com Password123! Frontend team tasks only
Employee (Backend) omar@minijira.com Password123! Backend team tasks only

πŸ—οΈ Architecture Overview

Note on Diagrams: We originally designed our architecture diagram in draw.io to ensure 100% technical accuracy. To make it visually stunning for our demo, we enhanced it using an AI tool (which introduced a few minor text typos like the AZ labels). Both versions are provided below for transparency!

1. Original Draw.io Diagram (Technically Accurate)

AWS Architecture (Draw.io)

2. AI Enhanced Diagram (Visually Polished)

AWS Architecture (AI)

High Availability Design

  • 2 Availability Zones (eu-north-1a, eu-north-1b) for fault tolerance
  • Auto Scaling Group (Min:2, Desired:2, Max:4) β€” self-healing infrastructure
  • Application Load Balancer distributes traffic across instances with /api/health checks
  • CloudFront CDN for global low-latency delivery (static assets cached, /api/* bypassed)
  • Private subnets for EC2 instances β€” no direct public internet access
  • 1 NAT Gateway in AZ-A for cost-optimized outbound internet access (HA option: 2 NAT Gateways at double the cost)

πŸ” Security Highlights

Security Measure Implementation
Private subnets for EC2 No direct public internet access to backend
Cognito JWT validation Every API route validates token via middleware
Team isolation (server-side) DynamoDB GSI enforces cross-team data access
Security Groups ALB: 443 from internet. EC2: 80 from ALB only
IAM least-privilege EC2 instance profile; Lambda roles scope to specific actions
Presigned S3 URLs Upload URLs expire in 5 min; View URLs expire in 1 hour
No credentials in code All secrets via environment variables on EC2
A+ Security Grade Achieved an 'A' on SecurityHeaders.com using a CloudFront Custom Response Headers Policy to enforce HSTS, Content-Security-Policy, X-Frame-Options, and X-Content-Type-Options

🎯 Key Features Demonstrated

βœ… Role-Based Access Control (Cognito)

  • AWS Cognito User Pool with custom attributes: custom:role, custom:teamId
  • JWT tokens validated on every API request via middleware
  • Two roles: Manager (full access) and Employee (team-scoped)

βœ… Team Isolation (Server-Enforced)

  • Employees see only their team's tasks
  • Manager sees all tasks with team filter dropdown
  • DynamoDB GSI query on teamId enforces cross-team access prevention at the data layer

βœ… Full Task Lifecycle (Kanban Board)

  • Drag-and-drop Kanban board (To Do β†’ In Progress β†’ In Review β†’ Done)
  • Every status change logged to MiniJira_AuditLog DynamoDB table
  • Comments with full CRUD (Create, Read, Update, Delete)
  • Image attachments on tasks

βœ… Event-Driven Notification Architecture

Task Assignment β†’ SNS Topic (MiniJira-TaskAssignment)
β”œβ”€β”€ (a) Email Subscription β†’ Assignee notification email
└── (b) SQS Queue (MiniJira-AssignmentQueue)
    └── Assignment Worker Lambda
        β”œβ”€β”€ Writes audit record to DynamoDB AuditLog
        └── Publishes CloudWatch custom metric (AssignmentsProcessed)

βœ… Serverless Image Processing Pipeline

User uploads image β†’ S3 PUT (minijira-originals-ali-605856)
β†’ S3 Event triggers Image Resize Lambda
β†’ Sharp library resizes to 400Γ—400 JPEG (quality: 85)
β†’ Saves thumbnail to S3 Resized Bucket (minijira-resized-ali-605856)
β†’ Frontend fetches thumbnail via presigned URL (expires 1 hour)

βœ… Daily Digest (EventBridge Scheduler)

  • Runs every day at 9:00 AM UTC via cron (0 9 * * ?)
  • Paginated DynamoDB Scan for tasks due today or overdue
  • Groups tasks by assignee, sends personalized summary email via SNS
  • Publishes OverdueTasksCount metric to CloudWatch

βœ… CloudWatch Monitoring & Alerting

Dashboard: MiniJira-Overview

Widget Metric
Lambda Invocations All 3 functions
Lambda Errors Spike detection
S3 Storage Growth Both buckets
SQS Message Traffic AssignmentQueue
Custom: TasksCreated Per team
Custom: TasksClosed Time-to-close
Custom: OverdueTasksCount Daily

Alarms (3 configured):

  • MiniJira-ImageResizer-Errors β€” fires if Lambda errors > 1 in 5 min
  • MiniJira-AssignmentWorker-Errors β€” fires if Lambda errors > 1 in 5 min
  • MiniJira-SQS-OldMessages β€” fires if messages stuck > 5 min

πŸ› οΈ Tech Stack

Frontend

  • React 18 + Vite β€” fast SPA build
  • Vanilla CSS β€” custom glassmorphism dark theme
  • @dnd-kit β€” drag-and-drop Kanban board
  • TanStack Query (React Query) β€” server state management
  • Amazon Cognito SDK β€” authentication and JWT management

Backend

  • Node.js 20 + Express β€” REST API
  • AWS SDK v3 β€” DynamoDB, S3, SNS, SQS, CloudWatch
  • PM2 β€” process management and auto-restart
  • Nginx β€” reverse proxy and static file server

Infrastructure & AWS Services

  • VPC, Public/Private Subnets, NAT Gateway, Internet Gateway
  • EC2 Auto Scaling Group, Application Load Balancer
  • CloudFront CDN
  • DynamoDB (6 tables, 2 GSIs)
  • S3 (2 buckets)
  • Lambda (3 functions)
  • SNS + SQS
  • EventBridge
  • Cognito
  • CloudWatch + Alarms
  • IAM (least-privilege roles)

πŸ“Š AWS Architecture Components

# Service Role
1 EC2 (Auto Scaling) Hosts Node.js backend across 2 AZs
2 Application Load Balancer Distributes traffic, health checks /api/health
3 CloudFront CDN β€” caches static assets, bypasses cache for /api/*
4 VPC Isolated private network (10.0.0.0/16)
5 Public Subnets (x2) ALB and NAT Gateway placement
6 Private Subnets (x2) EC2 instances β€” no direct internet access
7 NAT Gateway Outbound internet for EC2 (GitHub clone, npm install)
8 DynamoDB Users, Teams, Projects, Tasks, Comments, AuditLog
9 S3 (Originals) Raw task image attachments
10 S3 (Resized) 400Γ—400 JPEG thumbnails
11 Lambda β€” Image Resize S3 PUT trigger β†’ Sharp resize β†’ Resized bucket
12 Lambda β€” Assignment Worker SQS consumer β†’ audit log β†’ email β†’ metrics
13 Lambda β€” Daily Digest EventBridge trigger β†’ scan tasks β†’ email digest
14 SNS Fan-out notifications for assignments
15 SQS Decoupled queue for assignment processing
16 EventBridge Cron scheduler β€” daily digest at 9:00 AM UTC
17 Cognito User authentication, JWT, custom:role, custom:teamId
18 CloudWatch Dashboard, 6 custom metrics, 3 alarms
19 IAM EC2 Instance Profile + Lambda execution roles

πŸ“‚ Project Structure

Mini-JiraAWS/
β”œβ”€β”€ client/                     # React frontend (Vite)
β”‚   └── src/
β”‚       β”œβ”€β”€ components/
β”‚       β”‚   β”œβ”€β”€ kanban/         # Kanban board, TaskCard, TaskDetailModal
β”‚       β”‚   └── layout/         # Sidebar, MainLayout
β”‚       β”œβ”€β”€ pages/              # Dashboard, Tasks, Analytics, Projects, Teams
β”‚       β”œβ”€β”€ context/            # AuthContext (Cognito)
β”‚       └── lib/                # API client
β”œβ”€β”€ server/                     # Express backend (Node.js 20)
β”‚   └── src/
β”‚       β”œβ”€β”€ routes/             # API endpoints (tasks, teams, projects, etc.)
β”‚       β”œβ”€β”€ services/           # Database and AWS services
β”‚       β”œβ”€β”€ middleware/         # Auth and team isolation
β”‚       └── config/             # Environment & SDK configurations
└── infrastructure/             # AWS configuration & IaC scripts
    β”œβ”€β”€ lambda/
    β”‚   β”œβ”€β”€ image-resize/       # Serverless image processing (sharp)
    β”‚   β”œβ”€β”€ assignment-worker/  # SQS consumer (audit log + email)
    β”‚   └── daily-digest/       # EventBridge cron scheduled notifications
    β”œβ”€β”€ cloudwatch/             # Dashboard and custom alarm scripts
    β”œβ”€β”€ sns/                    # SNS topic configuration
    β”œβ”€β”€ sqs/                    # SQS queue creation
    β”œβ”€β”€ s3-sns/                 # S3 bucket and trigger setup
    └── users/                  # Cognito test users creation script

πŸ’° Cost Optimization

5-Day Total Deployment Cost: ~$8–10

Resource Cost
NAT Gateway $5.40 (5 days Γ— $1.08/day)
EC2 (above free tier) ~$2.50
All other services ~$0 (free tier / pay-per-use)

Strategies Applied:

  • βœ… 1 NAT Gateway instead of 2 (saves ~$32/month; HA tradeoff accepted for cost)
  • βœ… ASG desired = 0 when not testing (stops EC2 billing)
  • βœ… DynamoDB On-Demand β€” pay per request, zero idle cost
  • βœ… Lambda β€” only charged per invocation, not idle

πŸ† Engineering Challenges Overcome

1. Sharp Binary Compatibility (Lambda on Linux)

Problem: Installing sharp on Windows produced binaries incompatible with Lambda's Linux runtime. Solution: Used AWS CloudShell (Linux) to install and package sharp, ensuring correct glibc-linked binaries.

2. Double-Wrapped JSON (SNS β†’ SQS β†’ Lambda)

Problem: Lambda received SQS records where the body was a JSON string containing another JSON string (SNS envelope wrapping). Caused SyntaxError: Unexpected token. Solution: Double JSON parse with graceful fallback:

const snsMessage = JSON.parse(record.body);      // SQS body = SNS envelope
const taskData = JSON.parse(snsMessage.Message); // SNS message = actual task data

3. CloudFront Caching API Responses

Problem: CloudFront cached API calls, causing users to see stale task data. Solution: Created a dedicated cache behavior for /api/* path with Managed-CachingDisabled policy, while keeping CachingOptimized for static React assets.

4. Hardcoded localhost in Production Frontend

Problem: TaskDetailModal.jsx fetched image URLs from http://localhost:5000/api/upload/view-url/.... In production, browsers couldn't resolve localhost. Solution: Changed to relative path /api/upload/view-url/... β€” Nginx on EC2 proxies to the Express server.

5. Image Viewing from Wrong S3 Bucket

Problem: Backend view-url endpoint generated presigned URLs from the Originals bucket instead of the Resized bucket, causing large file transfers. Solution: Updated server/src/routes/upload.js to read from S3_BUCKETS.RESIZED.


πŸŽ₯ Demo Video

Watch Full Demo

Demo covers:

  1. Architecture diagram walkthrough
  2. Manager creates and assigns task with image upload
  3. Employee login β€” team isolation in action
  4. Drag-and-drop Kanban status update
  5. Image thumbnail display (Lambda resize pipeline)
  6. CloudWatch dashboard
  7. Live high-availability test β€” stop one EC2, app keeps running, ASG auto-replaces

πŸ“Ž Links


About

this project is about making an app similar to Jira or Trello but a miniature version of it, fully running on AWS.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages