Task 5: Schlüsselbund-Zweck voice (VOICE_ENCRYPTION_KEY), AES-256-GCM- Hilfen für Text und Bytes mit AAD capture:<id>:<art>, voice-config (Modell, Tageslimit, Aufnahme, Whisper-Grösse) und anthropic-config (nie geloggt, nur worker/all), Startprüfung verlangt den Schlüssel in Produktion in jeder Rolle, rekey versiegelt offene Sprachnotizen neu (Audio einzeln gelesen, CAS mit Status), Secret-Vorlagen und ensure-secrets.sh ergänzt. Task 6: Text-Normalisierung und Bereinigung (Steuer- und Formatzeichen, Codepoint-Kürzung), Zitatprüfung mit Dezimalzahlen als ein Wort (Ruling 7), Felderliste passend zu CreateInspectionDto, versiegeltes Transkript mit Grenzen, Fachwörter und Skalen mit Paritätstests. Rollout: Ein Image mit diesem Stand startet in Produktion nur mit VOICE_ENCRYPTION_KEY in apicore-backend-secret (ARCHITECTURE Annahme 22). Gates: Backend tsc, eslint, 922 Unit-Tests, e2e 100 Suites / 1004 Tests. Refs #27 #28 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
77 lines
3.9 KiB
YAML
77 lines
3.9 KiB
YAML
# Vorlage – keine echten Werte. Kopieren, echte Werte setzen, per `kubectl apply` außerhalb
|
||
# der Versionskontrolle anwenden (oder ueber Secret-Manager/Sealed-Secrets im Cluster).
|
||
apiVersion: v1
|
||
kind: Secret
|
||
metadata:
|
||
name: apicore-backend-secret
|
||
type: Opaque
|
||
stringData:
|
||
# Host ist der In-Cluster-Service aus deploy/k8s/base/postgres/service.yaml.
|
||
# Anderer Namespace als das Backend? Dann FQDN nutzen:
|
||
# apicore-postgres.<namespace>.svc.cluster.local
|
||
DATABASE_URL: "postgresql://apicore:change-me-postgres-password@apicore-postgres:5432/apicore?schema=public"
|
||
# Mindestens 32 Zeichen (server-seitig erzwungen, Start bricht sonst ab) -
|
||
# signiert jedes Access-/MFA-/SSO-Token. TOTP- und Webhook-Secrets aus der
|
||
# Zeit vor den eigenen Schluesseln (unten) sind noch damit verschluesselt:
|
||
# erst nach dem rekey-Job rotieren. Erzeugen z.B. mit: openssl rand -hex 32
|
||
JWT_ACCESS_SECRET: "change-me-to-a-random-value-at-least-32-characters-long"
|
||
JWT_REFRESH_SECRET: "change-me-refresh-secret"
|
||
# One encryption key per purpose (TOTP secrets, webhook signing secrets,
|
||
# backup files, voice notes). Required in production: at least 32 characters
|
||
# each, all four different from each other and from both JWT secrets.
|
||
# BACKUP_ENCRYPTION_KEY (with MFA_/WEBHOOK_ENCRYPTION_KEY for MFA and webhook
|
||
# secrets) is needed to restore backups on another deployment.
|
||
# Rotation: old value to <NAME>_PREVIOUS, new <NAME>, run the rekey job,
|
||
# then remove <NAME>_PREVIOUS (backup files are not resealed: keep
|
||
# BACKUP_ENCRYPTION_KEY_PREVIOUS while older files must restore).
|
||
MFA_ENCRYPTION_KEY: "change-me-to-a-third-random-value-at-least-32-characters"
|
||
WEBHOOK_ENCRYPTION_KEY: "change-me-to-a-fourth-random-value-at-least-32-characters"
|
||
BACKUP_ENCRYPTION_KEY: "change-me-to-another-random-value-at-least-32-characters"
|
||
# VOICE_ENCRYPTION_KEY seals audio, transcripts and suggestions of voice notes.
|
||
# It must exist before the T7 backend image rolls out (every role checks it).
|
||
VOICE_ENCRYPTION_KEY: "change-me-to-a-fifth-random-value-at-least-32-characters"
|
||
# MFA_ENCRYPTION_KEY_PREVIOUS: ""
|
||
# WEBHOOK_ENCRYPTION_KEY_PREVIOUS: ""
|
||
# BACKUP_ENCRYPTION_KEY_PREVIOUS: ""
|
||
# VOICE_ENCRYPTION_KEY_PREVIOUS: ""
|
||
# Entra ID App-Registrierung (SSO). Siehe configmap.example.yaml
|
||
# fuer OIDC_ISSUER_URL/OIDC_REDIRECT_URI. Wird auch fuer die
|
||
# M365-Kalender-Synchronisation wiederverwendet - dafuer in der
|
||
# App-Registrierung zusaetzlich die Application-Permission
|
||
# "Calendars.ReadWrite" hinzufuegen (Admin-Consent noetig).
|
||
OIDC_CLIENT_ID: "change-me-entra-client-id"
|
||
OIDC_CLIENT_SECRET: "change-me-entra-client-secret"
|
||
# Optionaler Schluessel der Open-Meteo-API (kommerzieller Tarif). Leer
|
||
# lassen, solange die freie API genutzt wird; dann wird kein apikey gesendet.
|
||
OPEN_METEO_API_KEY: ""
|
||
|
||
# Telegram-Bot-Token (optional) - NICHT in diesem Secret, sondern im eigenen
|
||
# Secret apicore-telegram, das nur der Worker einbindet (Secret mit
|
||
# TELEGRAM_BOT_TOKEN; einzelne secretKeyRef-Variable (optional: true), kein
|
||
# envFrom, kein Volume). Der API-Pod
|
||
# darf es nicht einbinden. Der Inhaber legt den Bot bei BotFather und das
|
||
# Secret selbst an; ohne Token laeuft Telegram nicht, alles andere schon.
|
||
#
|
||
# apiVersion: v1
|
||
# kind: Secret
|
||
# metadata:
|
||
# name: apicore-telegram
|
||
# type: Opaque
|
||
# stringData:
|
||
# TELEGRAM_BOT_TOKEN: "<token-from-botfather>"
|
||
|
||
# Anthropic-API-Schluessel fuer die Auswertung der Sprachnotizen (optional) -
|
||
# NICHT in diesem Secret, sondern im eigenen Secret apicore-anthropic, das nur
|
||
# der Worker einbindet (einzelne secretKeyRef-Variable ANTHROPIC_API_KEY mit
|
||
# optional: true, kein envFrom, kein Volume; Muster apicore-telegram). API- und
|
||
# Job-Pods lesen ihn nie. Der Inhaber legt das Secret selbst an; ohne
|
||
# Schluessel bleibt die Auswertung aus (EXTRACT_DISABLED), alles andere laeuft.
|
||
#
|
||
# apiVersion: v1
|
||
# kind: Secret
|
||
# metadata:
|
||
# name: apicore-anthropic
|
||
# type: Opaque
|
||
# stringData:
|
||
# ANTHROPIC_API_KEY: "<key-from-the-anthropic-console>"
|