The main branch workflow runs four independent jobs before a change is
considered to have passed the quality gate:
init -backend=false, and validate.
CI is validation-only. The workflow does not deploy, run terraform apply,
destroy resources, or migrate Terraform state.
cd backend
python -m pytest -v
The test suite covers:
All 204 tests pass on Python 3.11. Running time: approximately 8 seconds.
cd frontend
npm test
Covers: component rendering, WebSocket hook state transitions, session timer, and microphone permission error states. Zero production vulnerabilities at release time.
CI never applies infrastructure. It validates format and syntax only:
terraform -chdir=infrastructure/terraform fmt -check
terraform -chdir=infrastructure/terraform init -backend=false
terraform -chdir=infrastructure/terraform validate
gitleaks detect --source . --verbose
Gitleaks runs against the full Git history. A clean scan is required before any
git push.
The FastAPI backend emits structured JSON logs to the /ecs/livecap-backend-dev
CloudWatch log group. Log retention is 14 days.
# Stream live logs
aws logs tail /ecs/livecap-backend-dev --follow --region ap-southeast-1 --profile <aws-profile>
Key log events you will see during a session:
session_start – new session opened, with session ID and client IP hashwebsocket_connect – WebSocket connection establishedwebsocket_disconnect – client disconnected or timed outsession_end – session closed, with duration and reasonintegration_error – error from Transcribe, Translate, or S3



| Metric | Source | What it tells you |
|---|---|---|
HTTPCode_Target_5XX_Count | ALB | Backend errors returned to CloudFront |
HealthyHostCount | ALB Target Group | Number of healthy Fargate tasks |
CPUUtilization | ECS | Task CPU usage (alert if > 80%) |
MemoryUtilization | ECS | Task memory usage |
BlockedRequests | WAF | WAF is actively blocking threats |
4xx/5xx error rate | CloudFront | End-to-end error rate |
Create an alarm that fires when the ALB returns 5XX errors:
aws cloudwatch put-metric-alarm `
--alarm-name "livecap-alb-5xx" `
--metric-name "HTTPCode_Target_5XX_Count" `
--namespace "AWS/ApplicationELB" `
--statistic Sum `
--period 300 `
--threshold 5 `
--comparison-operator GreaterThanOrEqualToThreshold `
--evaluation-periods 1 `
--alarm-actions "arn:aws:sns:ap-southeast-1:720459752315:livecap-alerts" `
--region ap-southeast-1 --profile <aws-profile>
| Control | Implementation |
|---|---|
| No root account usage | Deployment uses IAM user camgiacntn |
| IAM least privilege | Separate task execution role and task role |
| No hardcoded credentials | IAM roles only; no keys in .env, images, or Git |
| Private S3 frontend | Block public access + OAC origin |
| Private S3 transcripts | Block public access; presigned URLs expire in 24 hours |
| HTTPS everywhere | CloudFront terminates viewer TLS |
| WAF at CloudFront and ALB | Managed rules in BLOCK mode; rate-based rules |
| CORS restriction | ALLOWED_ORIGIN limits accepted frontend origin |
| Session limits | 4 global + 1 per IP prevent runaway Transcribe cost |
| Transcript expiry | 14-day S3 lifecycle rule; no raw audio stored |
| Secret scanning | Gitleaks runs in CI on full Git history |
| Immutable image tags | Git SHA tags prevent accidental latest drift |
Both Web ACLs are in BLOCK mode. Production probes confirmed:

| Resource | Cost basis | Optimization |
|---|---|---|
| ECS Fargate | Per vCPU-second + GB-second | Scale to 0 when idle (target feature) |
| ALB | Fixed hourly + LCU | Incurs cost even when ECS is at 0; only removed by destroying the full stack |
| NAT Gateway | Hourly + per-GB data | Single NAT in one AZ (cost trade-off) |
| Amazon Transcribe | Per minute of audio | Session limits cap usage |
| Amazon Translate | Per million characters | Only finalized segments are translated |
| CloudWatch | Log ingestion + storage | 14-day retention limits storage cost |
| WAF | Per ACL + per rule | Fixed baseline; worth it for blocking |
An AWS Budget alert is managed by Terraform at $50/month. It sends a notification directly to an email subscriber when actual or forecast spend approaches the threshold (not via SNS).
Note: Budget alerts are a delayed billing signal, not real-time enforcement. They help you notice runaway costs within hours, not seconds.