Enable auth-service/api-gateway on production, build their images in CI
This commit is contained in:
@@ -12,25 +12,30 @@ The former numbered `00–29` material and historical plans are retained in
|
||||
there until reviewed. See the canonical
|
||||
[documentation policy](docs/documentation-policy.md) for source precedence.
|
||||
|
||||
> **Status** (2026-08-11): **live in production at
|
||||
> [realvuxbaro.me](https://realvuxbaro.me)** — a real RAG chatbot over the
|
||||
> whole formulary, not a scaffold. What exists and what does not:
|
||||
> **Status** (2026-08-18): **live in production at
|
||||
> [realvuxbaro.me](https://realvuxbaro.me)**, running on **k3s + ArgoCD**
|
||||
> since the 2026-08-17 cutover — a real RAG chatbot over the whole
|
||||
> formulary, not a scaffold. What exists and what does not:
|
||||
>
|
||||
> | Part | State |
|
||||
> |---|---|
|
||||
> | `ingestion/` | Done — 15,100 chunks embedded and loaded into Qdrant `duocthu_v1` |
|
||||
> | `apps/ai-service/` | Done — live grounded RAG (retrieval, generation, grounding, abstention, citations, traces) |
|
||||
> | `apps/web/` | Done — chat UI with citation/evidence panel |
|
||||
> | `apps/api-gateway`, `auth-service`, `user-service`, `chat-service` | **Not built** — `README.md` + `package.json` only |
|
||||
> | `apps/web/` | Done — chat UI with citation/evidence panel, optional login |
|
||||
> | `apps/auth-service`, `apps/api-gateway` | **Built** (real NestJS: register/login/JWT, `/auth/*` proxy) but **disabled by default** in the Helm chart — not yet live on production. Seed accounts (`admin`/`demo`) use placeholder passwords not safe to expose publicly as-is |
|
||||
> | `apps/user-service`, `apps/chat-service` | **Not built** — `README.md` + `package.json` only |
|
||||
> | `apps/mobile/` | **Not built** — reserved |
|
||||
> | `infra/docker/` | Done — production runs Compose, including the Prometheus/Grafana/Tempo observability overlay |
|
||||
> | `infra/helm/medical-chatbot/` | Built and validated as an offline migration kit; **not deployed** to Docker Desktop, k3s or ArgoCD |
|
||||
> | `infra/k8s`, `terraform`, `argocd` | **Not built yet** — still the target (ADR 0002), not abandoned: the plan is the team's self-hosted Gitea + ArgoCD; the current EC2/Compose setup is an interim stopgap |
|
||||
> | `infra/docker/` | Compose is **stopped** (was production through 2026-08-17); still used for local dev (Postgres/Qdrant/observability), not for deploying anywhere |
|
||||
> | `infra/helm/medical-chatbot/` | **This is production.** Two ArgoCD Applications, `medical-chatbot-app` and `medical-chatbot-data`, both tracked in `infra/argocd/applications/` |
|
||||
> | Team's Gitea + ArgoCD (ADR 0002) | **Still not started**, not abandoned — the personal k3s/ArgoCD instance above is a separate, owner-operated cluster, not the team's shared infrastructure |
|
||||
>
|
||||
> Because the gateway and auth services do not exist, `apps/web` talks
|
||||
> **directly** to `apps/ai-service`; there is no authentication layer. See
|
||||
> `apps/web`'s chat/history/feedback/sections routes still call
|
||||
> `apps/ai-service` **directly** — auth-service/api-gateway exist but chat
|
||||
> traffic doesn't route through the gateway yet. Login is optional and only
|
||||
> gates `/admin`; anonymous chat is unaffected. See
|
||||
> [canonical architecture document](docs/architecture.md) for the implemented
|
||||
> topology and the explicit status of current, scaffolded and target components.
|
||||
> topology (not yet updated for this — verify against code, not that doc,
|
||||
> until it is).
|
||||
|
||||
## Directory map
|
||||
|
||||
@@ -56,8 +61,9 @@ docs-legacy/ raw notes, historical plans and ADRs pending review
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js + pnpm (JS workspace: `apps/web`, `packages/*`; the NestJS service
|
||||
directories are unbuilt placeholders)
|
||||
- Node.js + pnpm (JS workspace: `apps/web`, `apps/auth-service`,
|
||||
`apps/api-gateway`, `packages/*`; `apps/user-service`/`apps/chat-service`
|
||||
are still unbuilt placeholders)
|
||||
- Python 3.11+ (`apps/ai-service`, `ingestion`)
|
||||
- Docker (local Postgres + Qdrant via `infra/docker/docker-compose.yml`)
|
||||
- AWS credentials with Bedrock invoke permission, for anything that generates
|
||||
@@ -143,62 +149,51 @@ Local endpoints:
|
||||
| Tempo | `http://localhost:3200` | Trace backend; normally queried through Grafana |
|
||||
| ai-service metrics | `http://localhost:8079/metrics` | Raw OpenMetrics output when ai-service runs on port 8079 |
|
||||
|
||||
For the existing EC2 Compose deployment, the optional overlay is
|
||||
`infra/docker/docker-compose.observability.yml`. It leaves
|
||||
`docker-compose.prod.yml` unchanged. A deployment, when explicitly approved,
|
||||
uses both files:
|
||||
|
||||
```powershell
|
||||
docker compose `
|
||||
-f infra/docker/docker-compose.prod.yml `
|
||||
-f infra/docker/docker-compose.observability.yml `
|
||||
up -d
|
||||
```
|
||||
|
||||
Grafana is available directly through Caddy and the existing production TLS
|
||||
certificate at `https://realvuxbaro.me/grafana/`. Anonymous access is disabled;
|
||||
sign in with the Grafana admin account. A dedicated
|
||||
`grafana.realvuxbaro.me` hostname can replace this path after its Namecheap A
|
||||
record exists.
|
||||
|
||||
Grafana and Prometheus are also bound to EC2 loopback only. This keeps both SSH
|
||||
fallbacks available without exposing their native ports to the Internet:
|
||||
|
||||
```powershell
|
||||
ssh `
|
||||
-L 3002:127.0.0.1:3002 `
|
||||
-L 9090:127.0.0.1:9090 `
|
||||
<ssh-user>@52.0.158.61
|
||||
```
|
||||
|
||||
Keep that session open and use `http://localhost:3002/grafana/` for Grafana or
|
||||
`http://localhost:9090` for the raw Prometheus UI. The same Grafana account is
|
||||
used through both the public HTTPS path and the SSH tunnel. The production
|
||||
password lives in the GitHub Actions secret `GRAFANA_ADMIN_PASSWORD`; do not use
|
||||
the Compose fallback password in production.
|
||||
|
||||
Prometheus intentionally has no public URL. Normally use
|
||||
**Grafana -> Explore -> Prometheus**; use its SSH tunnel only for low-level
|
||||
target or PromQL diagnostics. To investigate a slow request, open the
|
||||
request-latency panel, follow its exemplar/trace link, or paste the returned
|
||||
`X-Trace-ID` into **Explore -> Tempo**.
|
||||
Grafana is served through the same k3s ingress as the app, at
|
||||
`https://realvuxbaro.me/grafana/`. Anonymous access is on but demoted to
|
||||
**Viewer** (dashboards load with no login; write actions need the admin
|
||||
account). Prometheus has no public URL — use **Grafana -> Explore ->
|
||||
Prometheus** for PromQL, or **Explore -> Tempo** with a returned
|
||||
`X-Trace-ID` to investigate a slow request.
|
||||
|
||||
## Production
|
||||
|
||||
Live at [realvuxbaro.me](https://realvuxbaro.me): a single EC2 `t3.large`
|
||||
running `infra/docker/docker-compose.prod.yml` (postgres, qdrant, ai-service,
|
||||
web, Caddy for automatic Let's Encrypt TLS). Bedrock is reached through an IAM
|
||||
instance role — there are no long-lived AWS keys on the box or in any env file.
|
||||
Live at [realvuxbaro.me](https://realvuxbaro.me), running on **k3s +
|
||||
ArgoCD** (a personal, owner-operated cluster — not the team's shared
|
||||
infrastructure) since the 2026-08-17 cutover. Two ArgoCD Applications:
|
||||
`medical-chatbot-app` (ai-service, web, observability) and
|
||||
`medical-chatbot-data` (PostgreSQL, Qdrant — a separate release so an app
|
||||
redeploy or prune can never touch persistent data). Both are tracked in
|
||||
`infra/argocd/applications/`; `infra/helm/medical-chatbot/` is the chart both
|
||||
render from. Bedrock is reached through an IAM instance role — no long-lived
|
||||
AWS keys on the box or in any manifest.
|
||||
|
||||
Pushing to `master` deploys: `.github/workflows/deploy.yml` SSHes in, resets to
|
||||
the pushed commit, rebuilds `ai-service`/`web`, reconciles the observability
|
||||
containers, reloads Caddy, runs migrations and verifies health, metrics and an
|
||||
exact request trace. Postgres and Qdrant data survive deploys because they live
|
||||
in named volumes rather than the containers.
|
||||
Two things deploy independently:
|
||||
|
||||
This is **interim infrastructure**, not the end state. The intended target is
|
||||
still the team's self-hosted **Gitea** (company domain) plus their **ArgoCD**
|
||||
instance, per `docs-legacy/adr/0002-argocd-gitops.md` — that work is *not started*,
|
||||
not cancelled. Until it is deliberately started, the project stays on private
|
||||
GitHub, and the team's existing `git.vinmec.tech/ai-team/gitops` repository is
|
||||
reference-only: never push this project into it.
|
||||
- **App code** (`apps/ai-service/**`, `apps/web/**`, `packages/**`) — a push
|
||||
to `master` triggers `.github/workflows/build-practice-images.yml`, which
|
||||
builds and pushes GHCR images tagged by commit SHA, then repoints
|
||||
`medical-chatbot-app` at the new tag. `ci.yml` runs in parallel and does
|
||||
**not** gate this — a red test suite does not block a deploy.
|
||||
- **Chart/config** (`infra/helm/**`) — `helm-chart.yml` lints and asserts
|
||||
render invariants on the PR; once merged, ArgoCD's own `selfHeal` picks up
|
||||
the change automatically. No CI step applies it directly.
|
||||
|
||||
Rollback is `.github/workflows/rollback-k3s.yml` (`workflow_dispatch`,
|
||||
`target_sha`) — see `docs/operations.md` for the full runbook, including its
|
||||
current gaps (no automated rollback for a config-only change, and the
|
||||
Grafana admin password still lives inline on the ArgoCD Application rather
|
||||
than in a real Kubernetes Secret).
|
||||
|
||||
The former EC2 Docker Compose deployment (`i-039fc8f6102467a54`) is
|
||||
**stopped**, not deleted — see `docs/operations.md` if it's ever needed as a
|
||||
manual DNS fallback again, though its corpus/schema will drift further out
|
||||
of date the longer it stays off.
|
||||
|
||||
The team's self-hosted **Gitea** + **ArgoCD** (per
|
||||
`docs-legacy/adr/0002-argocd-gitops.md`) remains the longer-term target for
|
||||
this project and is **still not started** — not abandoned, just a separate
|
||||
decision from the personal-cluster cutover above. Until it is deliberately
|
||||
started, the project stays on private GitHub, and the team's existing
|
||||
`git.vinmec.tech/ai-team/gitops` repository is reference-only: never push
|
||||
this project into it.
|
||||
|
||||
Reference in New Issue
Block a user