This guide covers all steps required to deploy JGA BRICS OS to production for April 27, 2026 launch.
Target Environment: AWS (EKS), CloudFront CDN, RDS/DynamoDB, Route 53
# Create EKS cluster (3-node minimum)
eksctl create cluster \
--name jga-os-prod \
--region us-east-1 \
--nodegroup-name workers \
--nodes 3 \
--node-type t3.xlarge \
--managed
# Add IAM roles for Pods
eksctl utils associate-iam-oidc-provider --cluster=jga-os-prod --region=us-east-1
# Install AWS Load Balancer Controller
helm repo add eks https://aws.github.io/eks-charts
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=jga-os-prod
# CA State Database
aws rds create-db-instance \
--db-instance-identifier jga-os-state-ca \
--db-instance-class db.t3.large \
--engine postgres \
--master-username postgres \
--master-user-password [GENERATE_STRONG_PASSWORD] \
--allocated-storage 100 \
--storage-encrypted \
--kms-key-id [KMS_KEY_ARN] \
--multi-az \
--vpc-security-group-ids [SECURITY_GROUP_ID]
# TX State Database
aws rds create-db-instance \
--db-instance-identifier jga-os-state-tx \
--db-instance-class db.t3.large \
--engine postgres \
--master-username postgres \
--master-user-password [GENERATE_STRONG_PASSWORD] \
--allocated-storage 100 \
--storage-encrypted \
--kms-key-id [KMS_KEY_ARN] \
--multi-az
# CA State Key
aws kms create-key \
--description "JGA OS State BRIC CA encryption key" \
--tags TagKey=State,TagValue=CA TagKey=Project,TagValue=jga-os
# TX State Key
aws kms create-key \
--description "JGA OS State BRIC TX encryption key" \
--tags TagKey=State,TagValue=TX TagKey=Project,TagValue=jga-os
# Store key IDs in Kubernetes Secrets
kubectl create secret generic kms-keys \
--from-literal=ca-key-id=[CA_KMS_KEY_ID] \
--from-literal=tx-key-id=[TX_KMS_KEY_ID] \
-n jga-os
# Build
docker build -t jga-os:1.0 .
# Tag for ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin [AWS_ACCOUNT_ID].dkr.ecr.us-east-1.amazonaws.com
docker tag jga-os:1.0 [AWS_ACCOUNT_ID].dkr.ecr.us-east-1.amazonaws.com/jga-os:1.0
# Push
docker push [AWS_ACCOUNT_ID].dkr.ecr.us-east-1.amazonaws.com/jga-os:1.0
# Scan with AWS ECR
aws ecr start-image-scan \
--repository-name jga-os \
--image-id imageTag=1.0
# Wait for scan completion
aws ecr describe-image-scan-findings \
--repository-name jga-os \
--image-id imageTag=1.0
kubectl create namespace jga-os
# Create database secrets
kubectl create secret generic db-credentials \
--from-literal=ca-url=postgresql://user:pass@[CA_RDS_ENDPOINT]:5432/jga_os \
--from-literal=tx-url=postgresql://user:pass@[TX_RDS_ENDPOINT]:5432/jga_os \
-n jga-os
# Create compliance artifact secrets
kubectl create secret generic compliance-artifact \
--from-file=artifact.json=./compliance-artifact.json \
-n jga-os
# Update image references in k8s/deployment.yaml
sed -i 's|jga-os:1.0|[AWS_ACCOUNT_ID].dkr.ecr.us-east-1.amazonaws.com/jga-os:1.0|g' k8s/deployment.yaml
# Apply Kubernetes manifests
kubectl apply -f k8s/deployment.yaml
# Wait for rollout
kubectl rollout status statefulset/brics-raft-primary -n jga-os --timeout=10m
kubectl rollout status deployment/brics-public -n jga-os --timeout=10m
kubectl rollout status deployment/brics-system-b -n jga-os --timeout=10m
# Check pod status
kubectl get pods -n jga-os -w
# Check logs
kubectl logs -f deployment/brics-public -n jga-os
# Port forward for local testing
kubectl port-forward svc/brics-public 8080:80 -n jga-os
# Get NLB/ALB DNS name
kubectl get ingress -n jga-os
# Output will show: api.jga-os.example.com → [LOAD_BALANCER_ADDRESS]
# Create hosted zone (if not already done)
aws route53 create-hosted-zone --name api.jga-os.example.com --caller-reference $(date +%s)
# Get hosted zone ID
ZONE_ID=$(aws route53 list-hosted-zones-by-name \
--dns-name api.jga-os.example.com \
--query 'HostedZones[0].Id' --output text)
# Create DNS record (alias to load balancer)
aws route53 change-resource-record-sets \
--hosted-zone-id $ZONE_ID \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "api.jga-os.example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z35SXDOTRQ7X7K",
"DNSName": "[LOAD_BALANCER_DNS]",
"EvaluateTargetHealth": false
}
}
}]
}'
# Install cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml
# Create Let's Encrypt issuer
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@jga-os.example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
EOF
# Certificate will be auto-provisioned by ingress
# Verify with: kubectl get certificate -n jga-os
# Create CloudFront distribution
aws cloudfront create-distribution \
--origin-domain-name "[LOAD_BALANCER_DNS]" \
--default-root-object index.html \
--with-config-file cdn-config.json
# Create CNAME for CDN
aws route53 change-resource-record-sets \
--hosted-zone-id $ZONE_ID \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "cdn.jga-os.example.com",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [{"Value": "[CLOUDFRONT_DOMAIN_NAME]"}]
}
}]
}'
# Enable container insights
aws eks update-cluster-config \
--name jga-os-prod \
--logging '{"clusterLogging":[{"enabled":true,"types":["api","audit","authenticator","controllerManager","scheduler"]}]}'
# Install Prometheus
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/prometheus \
-n monitoring \
--create-namespace
# Install Grafana
helm install grafana grafana/grafana \
-n monitoring
# Create AlertManager rules
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 5m
annotations:
summary: "High error rate on "
- alert: RaftQuorumLoss
expr: brics_raft_healthy_nodes < 2
for: 1m
annotations:
summary: "Raft quorum lost - critical incident!"
- alert: DataCorruptionDetected
expr: brics_stitch_corruption_detected > 0
for: 1m
annotations:
summary: "Data corruption detected - auto-healing initiated"
npm run load-test
Expected Results:
✅ PASSED: System meets production performance targets
npm run security-audit
Audit Checklist:
# OWASP ZAP scan
docker run -t owasp/zap2docker-stable zap-baseline.py \
-t https://api.jga-os.example.com
# Manual security review
# - SSL/TLS configuration
# - API rate limiting
# - Input validation
# - Authorization checks
# Demo is already tested and passes all 6 scenarios
npm run test:demo
# Verify auto-healing works under production load
# Simulate credential leak detection
# 1. Inject test credential to repo
# 2. Run secret scanner
# 3. Verify detection and rotation
# 4. Confirm no false alarms on cleanup
# Test compliance gate closure
# 1. Trigger high-risk incident
# 2. Verify compliance gate closes business calls
# 3. Confirm escrow holds pending gate reopening
npm run launch
Expected Output:
✅ SYSTEM GO FOR LAUNCH
- All verification checks passed
- OS is fully operational
- Ready for production deployment
# Verify all systems operational
kubectl get pods -n jga-os
kubectl get svc -n jga-os
kubectl logs deployment/brics-raft-primary -n jga-os | tail -20
# Verify compliance artifact is valid
kubectl get secret compliance-artifact -n jga-os -o jsonpath='{.data.artifact\.json}' | base64 -d | jq .
# Check DNS resolution
dig api.jga-os.example.com
# Update DNS TTL to 60 seconds
# Deploy cutover traffic gradually:
# - 10% traffic → 1 hour
# - 50% traffic → 2 hours
# - 100% traffic → 4 hours
# Monitor metrics throughout
echo "JGA Enterprise OS is LIVE!"
If load exceeds 1k contractors:
If critical issues occur post-launch:
# Rollback to previous image
kubectl set image deployment/brics-public \
brics-public=[OLD_ECR_IMAGE] \
-n jga-os
# Scale down new deployment
kubectl scale deployment brics-public --replicas=0 -n jga-os
On-Call Rotation: ops-team@jga-os.example.com
Severity Levels:
Runbooks: See brics/april-keys/APRIL.KEYS.md
Last Updated: March 20, 2026
Status: Ready for Production Deployment
Next Review: Post-Launch + 2 weeks