# Task 3 Report: Kubernetes chat stack ## Status Core Task 3 Kubernetes resources, application health endpoint, documentation, and environment documentation are committed. No cluster resources were deployed. ## Files - Created `k8s/namespace.yaml`, `k8s/config.yaml`, `k8s/postgres.yaml`, `k8s/minio.yaml`, `k8s/app.yaml`, and `k8s/README.md`. - Created `app/api/health/route.ts` and `app/api/health/route.test.ts`. - Updated `.env.example` and `README.md` with the Task 3 environment and minikube access guidance. - Added the standalone Docker runtime and entrypoint. Startup retries dependencies in the order migrations, explicitly enabled legacy seed, private-bucket provisioning, then Next.js server start. ## Commit - `feat(deploy): add Kubernetes chat stack manifests` ## Validation Commands run successfully: ```bash kubectl apply --dry-run=client -f k8s/namespace.yaml kubectl apply --dry-run=client -f k8s/config.yaml kubectl apply --dry-run=client -f k8s/postgres.yaml kubectl apply --dry-run=client -f k8s/minio.yaml kubectl apply --dry-run=client -f k8s/app.yaml kubectl apply --dry-run=client -f k8s/ npm run build npm test -- app/api/health/route.test.ts git diff --cached --check sh -n docker-entrypoint.sh ``` The Kubernetes client-side dry-runs accepted all namespace, ConfigMap, Secret, PVC, Service, Deployment, and StatefulSet objects. The production Next.js build completed successfully and listed `/api/health` as a dynamic route. The targeted health-route test passed (1 test). The initial sandboxed `kubectl` and Next.js build attempts were denied their required local connections; both commands passed when rerun outside the sandbox. ## Self-review - All resources use namespace `aegida-services` and the required service names and ports. - ConfigMap uses the exact in-cluster `USER_SERVICE_URL`; Secret uses `stringData` for development-only JWT, database, and MinIO credentials. - PostgreSQL has the pinned required image, a 1 Gi claim template, `pg_isready` readiness, and a ClusterIP Service. - MinIO has the required pinned image, private Secret credentials, a 2 Gi PVC, ready endpoint, and API/console ports. - The application uses the required minikube image, `IfNotPresent`, one replica, `envFrom`, ClusterIP port 3000, and readiness/liveness probes for `/api/health`; no Ingress was added. ## Fix Round 1 The complete `Dockerfile` and `docker-entrypoint.sh` are committed with the Task 3 deployment work. The entrypoint retries migration and bucket setup, runs `scripts/seed.mjs` only when `AUTH_SEED_ENABLED=true`, and starts the server only after setup succeeds. Kubernetes documentation now applies `namespace.yaml` first, followed by each namespaced manifest explicitly, so the namespace cannot race the other resources. Commands run successfully for this round: ```bash sh -n docker-entrypoint.sh docker build -t ai-control-chat-ui:task-3-check . kubectl apply --dry-run=client -f k8s/namespace.yaml kubectl apply --dry-run=client -f k8s/config.yaml kubectl apply --dry-run=client -f k8s/postgres.yaml kubectl apply --dry-run=client -f k8s/minio.yaml kubectl apply --dry-run=client -f k8s/app.yaml npm test -- app/api/health/route.test.ts npm run build ``` Results: - `sh -n docker-entrypoint.sh` exited 0. - Docker 24.0.5 built `ai-control-chat-ui:task-3-check` successfully (`sha256:c8076ca54e40e14f865fed4285dba115076e54a27adf8efb1f934af762e368d0`). - All five Kubernetes client-side dry-runs accepted their objects. - `npm run build` completed its TypeScript phase and produced dynamic `/api/health`. - The focused health-route Vitest run passed: 1 test in 1 file. ## Fix Round 2 The Docker runtime depended on an uncommitted application baseline. The reproducibility commit now includes the Docker build context rules, package metadata, PostgreSQL and S3 dependencies, database migrations and runtime modules, attachment/conversation routes, migration/bucket/seed scripts, and the UI modules that import the added dependencies. Required paths were identified before staging with: ```bash git ls-files Dockerfile docker-entrypoint.sh package.json package-lock.json scripts db lib app components hooks next.config.ts git ls-files --others --exclude-standard rg -n '(@/lib/(db|storage)|@/components|@/hooks|from "pg"|from "bcryptjs"|@aws-sdk|scripts/(migrate|seed|ensure-bucket)|db/migrations)' app components hooks lib scripts Dockerfile docker-entrypoint.sh ``` The staged tree was exported without changing the shared worktree: ```bash task3_clean_dir=$(mktemp -d /private/tmp/corp-ui-task3-clean.XXXXXX) git archive "$(git write-tree)" | tar -x -C "$task3_clean_dir" (cd "$task3_clean_dir" && npm ci && npm run build && npm test -- app/api/health/route.test.ts) (cd "$task3_clean_dir" && sh -n docker-entrypoint.sh && docker build -t ai-control-chat-ui:task-3-clean-check .) ``` Results: - The temporary archive at `/private/tmp/corp-ui-task3-clean.9raKQW` contained only the staged Git tree. It did not include the remaining untracked workspace files. - `npm ci` completed in the archive (726 packages); its production build passed TypeScript and generated all application routes, including attachments, conversations, and dynamic `/api/health`. - The focused health-route test passed: 1 test in 1 file. - `sh -n docker-entrypoint.sh` exited 0 in the archive. - The Docker build from that archive ran a fresh `npm ci` (730 packages) and completed as local image `ai-control-chat-ui:task-3-clean-check` (`sha256:396e14c2a93711f59222ada82384fc342932c7ac1206213b3bfb013c63cbf264`).