Files
alva/felsokning/infra/terraform/variables.tf
T
Claude 301c477e25 Merge main: Guidad Felsökning flyttar ur roten till felsokning/
Main är sedan den här grenen skapades en helt annan produkt — Semantika,
en mobilapp med egen CDK-infrastruktur. Den äger nu repots rot: en
npm-workspaces-monorepo med apps/mobile, services/api och infra.

För att båda ska rymmas i samma repo flyttar Guidad Felsökning in i en
egen katalog i stället för att göra anspråk på roten:

  felsokning/app        webbklienten (Vite, egen package.json och
                        eslint-/vitest-konfiguration)
  felsokning/services   plattformstjänsten och AI-orkestern
  felsokning/infra      Terraform och databasschemat
  felsokning/docs       vision, moduler, drift
  felsokning/supabase   edge-funktion och migrationer

Merge:n hade tagit bort 128 filer som Guidad Felsökning bygger på —
värdapplikationens komponenter, Supabase-klienten, tillgångar — eftersom
main raderat dem och den här grenen inte råkat ändra just dem. De är
återställda på sin nya plats. Utan dem gick varken bygget eller
testerna: ai.ts och synk.ts importerar Supabase-klienten.

Semantikas rotfiler är orörda: package.json, eslint.config.js och
.github/workflows/ är deras. Guidad Felsökning har egna motsvarigheter i
sin katalog.

CI flyttar samtidigt från GitHub Actions till .gitea/workflows — samma
syntax, egna runners. .github/workflows/ tillhör Semantika härefter.

Verifierat på den nya platsen: 96 vitest-tester, typkontroll, eslint på
både klient och tjänster, bygge, och integrationstest mot riktig Postgres.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-04 12:22:49 +00:00

312 lines
8.8 KiB
Terraform

# Allt som skiljer en installation från en annan. Inget annat ska
# behöva ändras i .tf-filerna för att driftsätta i en ny miljö.
# ---- Kluster -----------------------------------------------------------
variable "kubeconfig" {
description = "Sökväg till kubeconfig."
type = string
default = "~/.kube/config"
}
variable "kube_context" {
description = "Kubernetes-kontext att driftsätta i. Tom = kubeconfigens aktuella."
type = string
default = ""
}
variable "namnrymd" {
description = "Namnrymd för hela systemet."
type = string
default = "guidad-felsokning"
}
variable "miljo" {
description = "Miljöns namn (produktion, test, demo). Sätts som label på allt."
type = string
default = "produktion"
}
# ---- Domän och certifikat ---------------------------------------------
variable "doman" {
description = "Domänen klienten och API:t nås på, t.ex. app.exempel.se."
type = string
}
variable "cert_issuer" {
description = "cert-manager ClusterIssuer som utfärdar TLS-certifikatet."
type = string
default = "letsencrypt"
}
variable "ingress_klass" {
description = "IngressClass. Nätverkspolicyn öppnar för ingress-kontrollerns namnrymd nedan."
type = string
default = "nginx"
}
variable "ingress_namnrymd" {
description = "Namnrymd där ingress-kontrollern kör — behövs av nätverkspolicyn."
type = string
default = "ingress-nginx"
}
# ---- Bilder ------------------------------------------------------------
variable "register" {
description = "Containerregister, t.ex. ghcr.io/min-organisation."
type = string
}
variable "bildtagg" {
description = <<-TEXT
Taggen alla tre bilderna körs med — normalt git-SHA:t från
publiceringsflödet. "latest" duger för prov men gör en rullning
omöjlig att spåra.
TEXT
type = string
validation {
condition = var.bildtagg != ""
error_message = "Ange en bildtagg — helst git-SHA:t, aldrig tomt."
}
}
# ---- Hemligheter -------------------------------------------------------
#
# Sätts helst via en secrets-hanterare (External Secrets, Vault, molnets
# secret manager) i stället för tfvars. Lämnas de tomma genererar
# Terraform slumpvärden vid första körningen och behåller dem i
# tillståndet — bekvämt för prov, men då måste tillståndet skyddas
# därefter.
variable "anthropic_api_nyckel" {
description = "Claude API-nyckel. Ägs av plattformen, når aldrig klienten."
type = string
sensitive = true
}
variable "jwt_hemlighet" {
description = "HS256-hemlighet. Delas av plattformen och orkestern. Tom = genereras."
type = string
sensitive = true
default = ""
}
variable "postgres_losenord" {
description = "Databaslösenord. Tom = genereras."
type = string
sensitive = true
default = ""
}
variable "integration_nyckel" {
description = <<-TEXT
32 byte hex som krypterar kundernas leverantörsuppgifter i vila.
Tom = genereras. Byts nyckeln måste alla kopplingar sparas om —
tjänsten visar då inga värden i stället för att gissa.
TEXT
type = string
sensitive = true
default = ""
}
# ---- Drift -------------------------------------------------------------
variable "registrering_oppen" {
description = "Om vem som helst får skapa en ny organisation. Stäng i produktion."
type = bool
default = false
}
variable "tillat_interna_uppslag" {
description = <<-TEXT
Tillåter märkesspecifika uppslag mot privata nät. Behövs bara när
verkstaden har en OEM-server på sitt eget nät. Öppnar samtidigt en
väg från en tenant-administratör in i klustrets interna adresser —
lämna av om ni inte vet att ni behöver det.
TEXT
type = bool
default = false
}
variable "max_kropp_mb" {
description = <<-TEXT
Största tillåtna anropskropp. Foton och videoklipp följer med i
händelseloggen, så ingressens gräns måste minst motsvara tjänstens
egen (4 MB) — annars avvisas dokumentationen redan vid dörren.
TEXT
type = number
default = 8
}
variable "repliker" {
description = "Grundantal repliker per tjänst (autoskalning tar över uppåt)."
type = object({
web = number
plattform = number
orkester = number
})
default = {
web = 2
plattform = 2
orkester = 2
}
}
variable "max_repliker" {
description = "Tak för autoskalningen per tjänst."
type = object({
web = number
plattform = number
orkester = number
})
default = {
web = 10
plattform = 10
orkester = 10
}
}
# ---- Databas -----------------------------------------------------------
variable "databas_lage" {
description = <<-TEXT
Hur händelseloggen lagras. Inget standardvärde: valet avgör om det
finns säkerhetskopiering, och det är inte ett val någon ska göra av
misstag.
"extern" Managerad Postgres utanför klustret (Cloud SQL, RDS,
Neon, Azure Flexible Server). Leverantören sköter
backup, PITR, failover och kryptering. REKOMMENDERAT
i produktion. Kräver databas_url.
"cnpg" CloudNativePG i klustret: basbackup, WAL-arkivering och
PITR mot objektlagring. Kräver att operatorn redan är
installerad — Terraform slår upp dess CRD vid plan.
Kräver backup-uppgifterna nedan.
"inbyggd" En StatefulSet med en volym. INGEN säkerhetskopiering.
Går volymen förlorad är händelseloggen borta, och den
är hela produktens bevisvärde. Endast för prov och demo.
TEXT
type = string
validation {
condition = contains(["extern", "cnpg", "inbyggd"], var.databas_lage)
error_message = "databas_lage måste vara \"extern\", \"cnpg\" eller \"inbyggd\"."
}
}
variable "databas_url" {
description = "Anslutning till den externa databasen. Krävs när databas_lage = \"extern\"."
type = string
sensitive = true
default = ""
}
variable "backup" {
description = <<-TEXT
Objektlagring för CloudNativePG:s basbackup och WAL-arkiv. Används
bara när databas_lage = "cnpg". mal är en S3-URL, t.ex.
s3://verkstad-backup/felsokning.
TEXT
type = object({
mal = string
endpoint = optional(string, "")
behall_dagar = optional(number, 30)
})
default = {
mal = ""
}
}
variable "backup_nyckel_id" {
description = "Åtkomstnyckel till objektlagringen (databas_lage = \"cnpg\")."
type = string
sensitive = true
default = ""
}
variable "backup_nyckel" {
description = "Hemlig nyckel till objektlagringen (databas_lage = \"cnpg\")."
type = string
sensitive = true
default = ""
}
variable "databas_instanser" {
description = "Antal Postgres-instanser i CloudNativePG-klustret. 3 ger failover utan dataförlust."
type = number
default = 3
}
# ---- Bilagor -----------------------------------------------------------
variable "bilage_lage" {
description = <<-TEXT
Var foton och videoklipp lagras.
"databas" bytea i en egen tabell. Fungerar överallt och kräver
ingen konfiguration, men bilderna följer med databasens
säkerhetskopior och gör dem stora.
"s3" S3-kompatibel objektlagring (AWS, MinIO, Ceph). Loggen
och bilderna växer oberoende av varandra. Kräver
s3-uppgifterna nedan.
Innehållet är innehållsadresserat i båda lägena: samma foto lagras
en gång, och hashen står i händelseloggen så en utbytt bild går att
upptäcka.
TEXT
type = string
default = "databas"
validation {
condition = contains(["databas", "s3"], var.bilage_lage)
error_message = "bilage_lage måste vara \"databas\" eller \"s3\"."
}
}
variable "s3" {
description = "Objektlagring för bilagor. Används bara när bilage_lage = \"s3\"."
type = object({
endpoint = string
hink = string
region = string
prefix = optional(string, "bilagor")
})
default = {
endpoint = ""
hink = ""
region = ""
}
}
variable "s3_nyckel_id" {
description = "Åtkomstnyckel till bilagornas objektlagring."
type = string
sensitive = true
default = ""
}
variable "s3_nyckel" {
description = "Hemlig nyckel till bilagornas objektlagring."
type = string
sensitive = true
default = ""
}
variable "databas_storlek" {
description = "Volymstorlek för händelseloggen. Foton och video ligger inline i loggen."
type = string
default = "50Gi"
}
variable "lagringsklass" {
description = "StorageClass för databasvolymen. Tom = klustrets standard."
type = string
default = ""
}