3ddfd87408
Replace the Mistral + Ollama AI stack with a single Google Gemini provider backed by google.golang.org/genai. API key moves from env/Helm to the DB (AES-256-GCM, key derived from JWT_SECRET via HKDF) so it can be rotated via the admin UI without a pod restart. New: - pkg/crypto/secretbox — AES-256-GCM encrypt/decrypt for secrets at rest - pkg/ai/gemini — GeminiProvider with grounding, structured output, usage recording, and hot-reload (Reinitialize swaps client under mutex) - pkg/ai/usage — UsageRecorder interface + UsageEvent struct - domain/settings/store — DB-backed settings (model, grounding toggle, key) - domain/settings/usage — UsageRepo implementing UsageRecorder; ai_usage table - migrations 000021 (system_settings) + 000022 (ai_usage) - settings API: GET /ai, POST /ai/key, POST /ai/model, POST /ai/grounding, GET /ai/usage - admin UI: 4-card settings page — provider status, model selector, grounding toggle with quota, usage rollups + recent-calls table Removed: - pkg/ai/ollama, mistral_provider, ratelimiter (+ tests) - Helm AI_API_KEY, AI_PROVIDER, AI_MODEL_COMPLEX, AI_AGENT_DISCOVERY, AI_RATE_LIMIT_RPS env vars Call sites set Grounded+CallType: research (true/"research"), enrich Pass B (true/"enrich_b"), similarity (false/"similarity"). Integration test updated to use a stub ai.Provider instead of a fake Ollama HTTP server.
152 lines
3.2 KiB
YAML
152 lines
3.2 KiB
YAML
image:
|
|
repository: registry.itsh.dev/vikingowl/marktvogt.de/backend
|
|
tag: "latest"
|
|
pullPolicy: IfNotPresent
|
|
|
|
imagePullSecrets:
|
|
- name: itsh-registry
|
|
|
|
nameOverride: ""
|
|
fullnameOverride: ""
|
|
|
|
replicaCount: 1
|
|
|
|
service:
|
|
port: 80
|
|
targetPort: 8080
|
|
|
|
httpRoute:
|
|
enabled: true
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
hostname: api.marktvogt.de
|
|
gatewayName: default
|
|
gatewayNamespace: nginx-gateway
|
|
sectionName: https-api-marktvogt-de
|
|
|
|
resources:
|
|
requests:
|
|
cpu: 50m
|
|
memory: 64Mi
|
|
limits:
|
|
cpu: 200m
|
|
memory: 128Mi
|
|
|
|
autoscaling:
|
|
enabled: false
|
|
minReplicas: 1
|
|
maxReplicas: 3
|
|
targetCPUUtilizationPercentage: 80
|
|
|
|
# Only meaningful with replicaCount >= 2
|
|
pdb:
|
|
enabled: false
|
|
minAvailable: 1
|
|
|
|
podSecurityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 65534
|
|
fsGroup: 65534
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
|
|
# Non-sensitive configuration — rendered into a ConfigMap
|
|
config:
|
|
APP_ENV: production
|
|
APP_PORT: "8080"
|
|
APP_HOST: "0.0.0.0"
|
|
CORS_ORIGINS: "https://marktvogt.de"
|
|
DB_SSLMODE: "require"
|
|
DB_MAX_CONNS: "25"
|
|
DB_MIN_CONNS: "5"
|
|
VALKEY_DB: "0"
|
|
RATE_LIMIT_RPS: "10"
|
|
RATE_LIMIT_BURST: "20"
|
|
# Access TTL is short because the SvelteKit admin UI does not yet auto-refresh
|
|
# on 401. Bumped from 15m to 2h as a pragmatic interim. Proper fix is a
|
|
# client-side refresh-on-401 interceptor (tracked in Ship 2 handoff §4.12).
|
|
JWT_ACCESS_TTL: "2h"
|
|
JWT_SESSION_TTL: "720h"
|
|
MAGIC_LINK_TTL: "15m"
|
|
MAGIC_LINK_BASE_URL: "https://marktvogt.de/auth/magic-link/verify"
|
|
OAUTH_REDIRECT_BASE_URL: "https://api.marktvogt.de"
|
|
SMTP_PORT: "587"
|
|
SMTP_FROM: "noreply@marktvogt.de"
|
|
ADMIN_EMAIL: "contact@marktvogt.de"
|
|
FRONTEND_URL: "https://marktvogt.de"
|
|
# Name of the manually-created Secret containing:
|
|
# JWT_SECRET, SENTRY_DSN,
|
|
# OAUTH_{GOOGLE,APPLE,FACEBOOK,GITHUB}_{CLIENT_ID,CLIENT_SECRET}
|
|
secretName: marktvogt-backend-secrets
|
|
|
|
# SMTP credentials — passed via Woodpecker secrets during deploy.
|
|
# Rendered into a Helm-managed K8s Secret.
|
|
smtp:
|
|
host: ""
|
|
user: ""
|
|
password: ""
|
|
|
|
# Discovery cron — token passed via CI secrets during deploy.
|
|
discovery:
|
|
enabled: true
|
|
schedule: "0 4 * * *"
|
|
token: ""
|
|
batchSize: 4
|
|
forwardMonths: 12
|
|
|
|
# Cloudflare Turnstile — passed via Woodpecker secrets during deploy.
|
|
turnstile:
|
|
secretKey: ""
|
|
|
|
# CloudNativePG Postgres cluster
|
|
postgres:
|
|
enabled: false
|
|
name: marktvogt-pg
|
|
instances: 1
|
|
# PostGIS-enabled CNPG image — verify tag at ghcr.io/cloudnative-pg/postgis
|
|
image: ghcr.io/cloudnative-pg/postgis:17-3.5
|
|
storageSize: 5Gi
|
|
resources:
|
|
requests:
|
|
cpu: 15m
|
|
memory: 128Mi
|
|
limits:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
|
|
# DragonflyDB (Redis-compatible) — managed by the DragonflyDB operator
|
|
dragonfly:
|
|
enabled: true
|
|
name: marktvogt-cache
|
|
replicas: 1
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 72Mi
|
|
limits:
|
|
cpu: 150m
|
|
memory: 128Mi
|
|
|
|
# Migration job (Helm pre-install/pre-upgrade hook)
|
|
migrate:
|
|
enabled: true
|
|
|
|
networkPolicy:
|
|
enabled: false
|
|
|
|
serviceAccount:
|
|
create: true
|
|
name: ""
|
|
annotations: {}
|
|
|
|
nodeSelector: {}
|
|
tolerations: []
|
|
affinity: {}
|