Validation: feat: dev environment — ephemeral DB, shared Keycloak, dev URL, migration practices, port convention
Verdict: PASS
Ticket
ldraney/intelligentstaffingsystems#86 — Dev environment setup: shared Keycloak auth config, ephemeral DB via
make reset, dev URL hostname allowlisting, migration practices documentation, and port convention (9999 dev / 3000 prod).Merged PR: #94
Environment
Production cluster (k3s, archbox node), namespace
intelligentstaffingsystems. URL: https://intelligentstaffingsystems.ai. ArgoCD-managed deployment.Checks
| # | Criterion | How Verified | Result | Evidence |
|---|---|---|---|---|
| 1 | CI pipeline green for merge commit | Woodpecker pipeline #116 (push event, branch main) | PASS | Pipeline #116 status: success, message: "feat: dev environment — shared Keycloak, ephemeral DB, dev URL, migration docs (#94)" |
| 2 | Image tag propagated to running pod | <code>kubectl get pods -n intelligentstaffingsystems -o jsonpath='{.items[*].spec.containers[*].image}'</code> | PASS | <code>harbor.tail5b443a.ts.net/intelligentstaffingsystems/app:dc97ba0a017aad90140d68fcd41267197433e716</code> — matches merge commit dc97ba0 |
| 3 | Pod running and ready, 0 restarts | <code>kubectl get pods -n intelligentstaffingsystems</code> | PASS | intelligentstaffingsystems-5ddd4556dd-nbbjd 1/1 Running 0 6h53m |
| 4 | Health endpoint returns 200 | <code>curl -s -o /dev/null -w "%{http_code}" https://intelligentstaffingsystems.ai/up</code> | PASS | HTTP 200 |
| 5 | ArgoCD sync and health | <code>kubectl get application -n argocd intelligentstaffingsystems</code> | PASS | sync.status: Synced, health.status: Healthy |
| 6 | Production root URL responds | <code>curl -s -o /dev/null -w "%{http_code}" https://intelligentstaffingsystems.ai/</code> | PASS | HTTP 200 |
| 7 | dev.intelligentstaffingsystems.ai in config.hosts (production.rb) | File inspection: config/environments/production.rb line 88 | PASS | <code>config.hosts << "dev.intelligentstaffingsystems.ai"</code> present |
| 8 | Port convention: dev on 9999, prod on 3000 | docker-compose.yml port mapping + kubectl svc | PASS | docker-compose: ports 9999:9999; k8s svc: ClusterIP 3000/TCP |
| 9 | .env.development.example exists with Keycloak vars | File inspection | PASS | File present with KEYCLOAK_URL, KEYCLOAK_REALM, KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET placeholders |
| 10 | make reset target for ephemeral DB | Makefile inspection | PASS | <code>reset: $(RUN) rails db:drop db:create db:migrate db:seed</code> |
Tiers Executed
- Tier 1 (Local): SKIPPED — Docker tests hang locally (known issue #65). CI pipeline #116 green serves as equivalent (runs full test suite in containerized CI).
- Tier 3 (Production): PASS — Pod deployed with correct image, health endpoint healthy, ArgoCD synced and healthy.
Regression Check
Production app continues to serve at
https://intelligentstaffingsystems.ai/ (200). No crash loops, 0 restarts on the pod. ArgoCD reports Healthy state. The only production code change was a single line adding dev.intelligentstaffingsystems.ai to the Rails allowed hosts list — no logic changes that could regress existing functionality.Discovered Issues
dev.intelligentstaffingsystems.ai TLS handshake failure: DNS resolves correctly to 178.156.129.142 (Hetzner edge), but the TLS handshake fails with "tlsv1 alert internal error". The Caddy reverse proxy on the edge VPS does not have a certificate provisioned for this subdomain. HTTP returns 308 (redirect to HTTPS), confirming the vhost exists but lacks TLS. This is an infrastructure-level issue (Caddy cert config) outside the scope of this Rails ticket, which correctly added the hostname to
config.hosts. Recommend creating a separate infra ticket for Caddy TLS provisioning on the dev subdomain.