initial wcag-ada

This commit is contained in:
Boki 2025-06-28 11:11:34 -04:00
parent 042b8cb83a
commit d52cfe7de2
112 changed files with 9069 additions and 0 deletions

View file

@ -0,0 +1,69 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: wcag-ada-api
namespace: wcag-ada
spec:
replicas: 3
selector:
matchLabels:
app: wcag-ada-api
template:
metadata:
labels:
app: wcag-ada-api
spec:
initContainers:
- name: wait-for-postgres
image: busybox:1.36
command: ['sh', '-c', 'until nc -z postgres-service 5432; do echo waiting for postgres; sleep 2; done']
- name: run-migrations
image: wcag-ada/api:latest
command: ["bunx", "prisma", "migrate", "deploy"]
envFrom:
- configMapRef:
name: wcag-ada-config
- secretRef:
name: wcag-ada-secrets
containers:
- name: api
image: wcag-ada/api:latest
ports:
- containerPort: 3001
envFrom:
- configMapRef:
name: wcag-ada-config
- secretRef:
name: wcag-ada-secrets
livenessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: wcag-ada-api-service
namespace: wcag-ada
spec:
selector:
app: wcag-ada-api
ports:
- port: 3001
targetPort: 3001
type: ClusterIP

View file

@ -0,0 +1,47 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: wcag-ada-config
namespace: wcag-ada
data:
NODE_ENV: "production"
APP_NAME: "wcag-ada"
# API Configuration
API_PORT: "3001"
API_CORS_ORIGIN: "https://wcag-ada.example.com"
API_JWT_EXPIRES_IN: "7d"
API_RATE_LIMIT: "100"
API_RATE_WINDOW: "60000"
# Worker Configuration
WORKER_PORT: "3002"
WORKER_CONCURRENCY: "5"
WORKER_QUEUE_NAME: "accessibility-scans"
# Redis Configuration
REDIS_HOST: "redis-service"
REDIS_PORT: "6379"
REDIS_DB: "0"
# Scanner Configuration
SCANNER_HEADLESS: "true"
SCANNER_TIMEOUT: "30000"
SCANNER_VIEWPORT_WIDTH: "1920"
SCANNER_VIEWPORT_HEIGHT: "1080"
SCANNER_BLOCK_RESOURCES: "true"
SCANNER_BLOCK_PATTERNS: "font,image"
# Features
FEATURES_SCREENSHOTS: "true"
FEATURES_FIX_SUGGESTIONS: "true"
FEATURES_CUSTOM_RULES: "true"
FEATURES_SCHEDULED_SCANS: "true"
FEATURES_BULK_SCANNING: "false"
FEATURES_API_ACCESS: "true"
# Scheduler
SCHEDULER_TIMEZONE: "America/New_York"
SCHEDULER_MAX_CONCURRENT_SCANS: "3"
SCHEDULER_RETRY_ATTEMPTS: "3"
SCHEDULER_RETRY_DELAY: "5000"

View file

@ -0,0 +1,52 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: wcag-ada-dashboard
namespace: wcag-ada
spec:
replicas: 2
selector:
matchLabels:
app: wcag-ada-dashboard
template:
metadata:
labels:
app: wcag-ada-dashboard
spec:
containers:
- name: dashboard
image: wcag-ada/dashboard:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
---
apiVersion: v1
kind: Service
metadata:
name: wcag-ada-dashboard-service
namespace: wcag-ada
spec:
selector:
app: wcag-ada-dashboard
ports:
- port: 80
targetPort: 8080
type: ClusterIP

View file

@ -0,0 +1,38 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wcag-ada-ingress
namespace: wcag-ada
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
spec:
ingressClassName: nginx
tls:
- hosts:
- wcag-ada.example.com
- api.wcag-ada.example.com
secretName: wcag-ada-tls
rules:
- host: wcag-ada.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wcag-ada-dashboard-service
port:
number: 80
- host: api.wcag-ada.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wcag-ada-api-service
port:
number: 3001

View file

@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
name: wcag-ada
labels:
name: wcag-ada

View file

@ -0,0 +1,84 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: wcag-ada
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: wcag-ada
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
env:
- name: POSTGRES_USER
value: wcag_user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: wcag-ada-secrets
key: DATABASE_URL
- name: POSTGRES_DB
value: wcag_ada
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
livenessProbe:
exec:
command:
- pg_isready
- -U
- wcag_user
- -d
- wcag_ada
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- pg_isready
- -U
- wcag_user
- -d
- wcag_ada
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: wcag-ada
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
type: ClusterIP

View file

@ -0,0 +1,77 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
namespace: wcag-ada
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: wcag-ada
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
command:
- redis-server
- --appendonly
- "yes"
ports:
- containerPort: 6379
volumeMounts:
- name: redis-storage
mountPath: /data
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "200m"
volumes:
- name: redis-storage
persistentVolumeClaim:
claimName: redis-pvc
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: wcag-ada
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
type: ClusterIP

View file

@ -0,0 +1,26 @@
apiVersion: v1
kind: Secret
metadata:
name: wcag-ada-secrets
namespace: wcag-ada
type: Opaque
stringData:
# Database
DATABASE_URL: "postgresql://wcag_user:wcag_password@postgres-service:5432/wcag_ada"
# Redis
REDIS_PASSWORD: ""
# API
API_JWT_SECRET: "your-super-secret-jwt-key-change-in-production"
# Email (optional)
SMTP_HOST: ""
SMTP_PORT: "587"
SMTP_USER: ""
SMTP_PASS: ""
SMTP_FROM: "noreply@wcag-ada.com"
# Slack (optional)
SLACK_WEBHOOK_URL: ""
SLACK_CHANNEL: "#wcag-alerts"

View file

@ -0,0 +1,67 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: wcag-ada-worker
namespace: wcag-ada
spec:
replicas: 2
selector:
matchLabels:
app: wcag-ada-worker
template:
metadata:
labels:
app: wcag-ada-worker
spec:
initContainers:
- name: wait-for-services
image: busybox:1.36
command: ['sh', '-c', 'until nc -z postgres-service 5432 && nc -z redis-service 6379 && nc -z wcag-ada-api-service 3001; do echo waiting for services; sleep 2; done']
containers:
- name: worker
image: wcag-ada/worker:latest
ports:
- containerPort: 3002
envFrom:
- configMapRef:
name: wcag-ada-config
- secretRef:
name: wcag-ada-secrets
livenessProbe:
httpGet:
path: /health
port: 3002
initialDelaySeconds: 40
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 3002
initialDelaySeconds: 10
periodSeconds: 5
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "1000m"
securityContext:
capabilities:
add:
- SYS_ADMIN
runAsUser: 1001
runAsGroup: 1001
---
apiVersion: v1
kind: Service
metadata:
name: wcag-ada-worker-service
namespace: wcag-ada
spec:
selector:
app: wcag-ada-worker
ports:
- port: 3002
targetPort: 3002
type: ClusterIP