b069c9a12f
Master Prompts tenant- och rollmodell implementerad i den självhostade plattformen: - Registrering skapar organisation + systemadministratör (transaktion); admin skapar övriga användare (tekniker/arbetsledare/admin) i sin organisation via nytt UI och POST /api/anvandare. Roll + organisation ligger i JWT-anspråken och verifieras alltid på servern. - All ärendedata organisationsknuten: ärenden skapas i användarens organisation, händelse-API:t verifierar tillhörighet per anrop och GET /api/arenden listar bara egna organisationens ärenden. - Schemat flyttat till infra/k8s/postgres-init.sql och genereras in som ConfigMap via kustomize — samma fil används av integrationstestet. Nya tabeller: organisationer; anvandare med organisation_id + roll (check-constraint); arenden med organisation_id + index. - Integrationstest (services/plattform/integrationstest.sh) mot riktig Postgres, kört grönt lokalt och tillagt i CI: registrering, synk, idempotens (händelser skrivs aldrig över), append-only-triggern, organisationsisolering (404 över gränsen), publik delning med filtrering, rollstyrning (tekniker nekas användarhantering) och delad arbetsyta inom organisationen. - Klienten: registreringsformulär med organisationsfält, kontopanel med roll och organisation, admin-panel för användarhantering. Verifierat: integrationstestets 12 kontroller gröna mot Postgres 16, 28 vitest-tester gröna, produktionsbygge ok, YAML validerad, Playwright-röktest grönt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
79 lines
5.2 KiB
Markdown
79 lines
5.2 KiB
Markdown
# Guidad Felsökning – Drift i Kubernetes (helt självhostat)
|
||
|
||
Målarkitekturen ur [Master Prompt](MASTER-PROMPT.md) som kod: hela stacken körbar i eget kluster — webb, AI-orkester, plattformsbackend (auth + händelse-API + Live Share) och Postgres. Inga externa tjänstberoenden utöver Anthropic-API:et för AI-anropen.
|
||
|
||
## Arkitektur
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
T[Tekniker] -->|HTTPS| I[Ingress + TLS]
|
||
T2[Kund via delningslänk] -->|HTTPS| I
|
||
I -->|/| W[web\n2–10 pods, HPA]
|
||
I -->|/api/ai| A[ai-orkester\n2–10 pods, HPA]
|
||
I -->|/api, /halsa| P[plattform\n2–10 pods, HPA]
|
||
A -->|Claude API| C[(Anthropic)]
|
||
P --> DB[(Postgres\nStatefulSet + PVC)]
|
||
K[Secret: felsokning-hemligheter] --> A & P & DB
|
||
```
|
||
|
||
| Komponent | Vad | Var |
|
||
| --- | --- | --- |
|
||
| `web` | SPA:n bakom oprivilegierad nginx (`Dockerfile`, `docker/nginx.conf`) | Deployment + Service + HPA + PDB |
|
||
| `plattform` | Självhostad backend (`services/plattform`): **multi-tenant** — registrering skapar organisation + systemadministratör, admin hanterar användare (tekniker/arbetsledare/admin), all ärendedata organisationsisolerad. Inloggning (bcrypt via pgcrypto, HS256-JWT med roll + org i anspråken), append-only händelse-API, publik delningsendpoint | Deployment + Service + HPA + PDB |
|
||
| `ai-orkester` | AI-orkestern (`services/ai-orkester`): fyra uppgifter routade till Sonnet 5 / Opus 5 / Haiku 4.5 — verifierar plattformens JWT (delad hemlighet) | Deployment + Service + HPA + PDB |
|
||
| `postgres` | Händelselogg + användare; **append-only garanterat med databastriggers** — historik kan inte ändras eller raderas oavsett roll | StatefulSet + PVC (10 Gi). Produktion: CloudNativePG-operatorn för backup/failover/PITR |
|
||
| Hemligheter | `anthropic-api-key`, `jwt-secret` (delas av plattform + orkester), `postgres-losenord` | Secret `felsokning-hemligheter` — aldrig i bilder eller manifest |
|
||
|
||
**Klienten har två driftlägen**, valda vid bygget: med `VITE_PLATTFORM_URL` går inloggning, synk, Live Share och AI mot klustret (helt självhostat); utan den används Supabase-läget (edge-funktion + managerad Postgres/Auth) som tidigare. Samma händelsemodell, samma orkester — låst av paritetstester.
|
||
|
||
## Driftsätta
|
||
|
||
```sh
|
||
# 1. Bygg och publicera bilderna (ersätt registry i infra/k8s/*.yaml)
|
||
docker build -t ghcr.io/ORG/guidad-felsokning-web \
|
||
--build-arg VITE_PLATTFORM_URL=https://app.exempel.se .
|
||
docker build -t ghcr.io/ORG/guidad-felsokning-ai-orkester services/ai-orkester
|
||
docker build -t ghcr.io/ORG/guidad-felsokning-plattform services/plattform
|
||
docker push ghcr.io/ORG/guidad-felsokning-web
|
||
docker push ghcr.io/ORG/guidad-felsokning-ai-orkester
|
||
docker push ghcr.io/ORG/guidad-felsokning-plattform
|
||
|
||
# 2. Skapa secret:en (eller använd External Secrets/Sealed Secrets)
|
||
kubectl create namespace guidad-felsokning
|
||
kubectl -n guidad-felsokning create secret generic felsokning-hemligheter \
|
||
--from-literal=anthropic-api-key='sk-ant-…' \
|
||
--from-literal=jwt-secret="$(openssl rand -base64 48)" \
|
||
--from-literal=postgres-losenord="$(openssl rand -base64 24)"
|
||
|
||
# 3. Applicera manifesten (Postgres initieras med schema + append-only-triggers)
|
||
kubectl apply -k infra/k8s
|
||
|
||
# 4. Verifiera
|
||
kubectl -n guidad-felsokning get pods
|
||
curl https://app.exempel.se/halsa # → {"status":"ok"} (plattformen)
|
||
```
|
||
|
||
Byt domän och cert-issuer i `infra/k8s/ingress.yaml`. Att skapa nya organisationer är öppet i beta — stäng med `REGISTRERING_OPPEN=false` på plattformens Deployment; användare inom en organisation skapas alltid av dess systemadministratör.
|
||
|
||
## Multi-tenant och roller
|
||
|
||
Enligt Master Prompt: varje kund är en egen tenant, ingen data blandas mellan kunder.
|
||
|
||
- **Registrering skapar organisationen** och gör användaren till systemadministratör.
|
||
- **Admin skapar användare** (tekniker/arbetsledare/admin) i sin organisation — via UI:t eller `POST /api/anvandare`.
|
||
- **All ärendedata är organisationsknuten**: ärenden skapas i användarens organisation och händelse-API:t verifierar organisationstillhörighet på varje anrop — en annan organisations ärenden ger 404.
|
||
- **Rollen ligger i JWT:n** och verifieras på servern; klienten anpassar bara UI:t.
|
||
|
||
Integrationstestet (`services/plattform/integrationstest.sh`, körs även i CI mot riktig Postgres) verifierar hela kedjan: registrering, synk, idempotens, append-only-triggern, organisationsisolering, delningsfiltrering och rollstyrning.
|
||
|
||
## Säkerhet och robusthet
|
||
|
||
- **Append-only i tre lager:** klienten lägger bara till, API:t exponerar inga update/delete, och databastriggers avvisar ändringar även för en felkonfigurerad roll.
|
||
- **JWT-flödet är verifierat tvärs tjänsterna:** plattformen signerar, orkestern verifierar samma hemlighet; fel hemlighet och utgångna tokens avvisas (testat).
|
||
- Alla containrar kör **non-root** utan capabilities; backend-tjänsterna med read-only rotfilsystem. Båda failar closed utan sina hemligheter.
|
||
- **HPA** 2–10 pods per tjänst på 70 % CPU; **PDB** minst en pod uppe vid noddränering; readiness/liveness-prober överallt (`pg_isready` för Postgres).
|
||
|
||
## CI
|
||
|
||
`.github/workflows/ci.yml` kör tester + produktionsbygge och verifierar alla tre Dockerfilerna på varje push/PR. Publicering och `kubectl apply` läggs i ett separat behörighetsstyrt deploy-flöde (GitOps via Argo CD/Flux rekommenderas).
|