Setzt Teilprojekte 1-5 der Spec 2026-10-16 um: - Urkunden-Engine (lib/certificate): ein Layout fuer PDF, Vorschau und 3D-Textur, Vorlage classic@1, eingebettete OFL-Schriften, Testmatrix - Einmal-Patenschaft ueber Traegerprodukte (Kategorie PATENSCHAFT), Paket wird im Checkout in Patenschaft (Regelsatz) und Honig aufgeteilt, Kontopflicht, rein digitale Bestellungen (FulfillmentMethod DIGITAL) - Ausstellung nach Zahlung idempotent, Wiederholung im App-Prozess (instrumentation + background-jobs), Ablage in CERTIFICATE_DIR - Verkaufsseite /patenschaft mit Konfigurator und Live-Vorschau, Warenkorb mit Schluessel je Position - Kundenkonto: 3D-Ansicht von Urkunde und Medaille, Downloads, ZIP, Uebertragung per befristetem Einmal-Link, Treuestufen bis VIP - Admin: Angebote, Patenschaften, Druck, Korrektur mit Revisionen, Abos, Erntefenster, Deckung, SEPA-Frist, Treuestufen - Abo ueber Stripe Billing: Lieferung erst nach bezahlten Monaten, SEPA-Neukunden-Frist und Rueckbuchungsschutz, Honigreservierung, Kuendigungsbutton, Monatsrechnungen, Stripe-Einrichtungsskript Startangebote werden inaktiv angelegt; Livebetrieb erst nach Freigabe. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
163 lines
8.3 KiB
YAML
163 lines
8.3 KiB
YAML
# Nicht-geheime Konfiguration. Geheimnisse (Passwoerter, API-Schluessel)
|
|
# gehoeren in 02-secret.yaml, NIE hierher: eine ConfigMap ist unverschluesselt
|
|
# und in der Cluster-Oberflaeche im Klartext lesbar.
|
|
#
|
|
# ANPASSEN vor dem ersten Ausrollen: NEXT_PUBLIC_SITE_URL und SMTP_FROM. Alle
|
|
# uebrigen Werte sind sinnvolle Vorgaben und koennen so bleiben; die leeren
|
|
# ("") gehoeren zu optionalen Funktionen, die dann einfach ruhen.
|
|
#
|
|
# Zusammen mit 02-secret.yaml deckt diese Datei JEDE Umgebungsvariable ab, die
|
|
# die Anwendung liest. Die Vollstaendigkeit wird automatisch geprueft, siehe
|
|
# src/lib/k8s-manifest-env.test.ts — kommt im Code eine neue Variable dazu,
|
|
# faellt das beim naechsten "pnpm test" auf, nicht erst im Betrieb.
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: wabenhain-config
|
|
namespace: wabenhain
|
|
data:
|
|
# ---------------------------------------------------------------------
|
|
# ANPASSEN
|
|
# ---------------------------------------------------------------------
|
|
|
|
# Oeffentliche Adresse des Shops. Einzige Quelle fuer Sitemap,
|
|
# Canonical-Tags, JSON-LD und JEDEN Link in JEDER E-Mail (src/lib/url.ts).
|
|
# Muss zum "host" in 06-ingress.yaml passen — mit https, ohne
|
|
# abschliessenden Schraegstrich.
|
|
NEXT_PUBLIC_SITE_URL: "https://wabenhain.com"
|
|
|
|
# Absenderadresse aller Transaktions-E-Mails. Sollte auf einer eigenen
|
|
# Domain liegen, sonst landen die Mails regelmaessig im Spam-Ordner.
|
|
# Muss die Adresse des Postfachs aus SMTP_USER (Secret) sein — der Versand
|
|
# laeuft ueber Microsoft 365 mit OAuth 2.0, siehe README "E-Mail-Versand".
|
|
SMTP_FROM: "Wabenhain <[email protected]>"
|
|
|
|
# ---------------------------------------------------------------------
|
|
# VORGABEN — koennen so bleiben
|
|
# ---------------------------------------------------------------------
|
|
|
|
NODE_ENV: "production"
|
|
|
|
# "postgresql" oder "mysql" — muss zu dem Datenbank-Manifest passen, das du
|
|
# tatsaechlich ausrollst (03-postgres.yaml bzw. 03-mysql.yaml), UND zum
|
|
# Schema in DATABASE_URL im Secret. Ein einzelnes Image traegt beide
|
|
# Prisma-Client-Varianten, siehe src/lib/prisma.ts.
|
|
DATABASE_PROVIDER: "postgresql"
|
|
|
|
# Gleichzeitig offene Datenbankverbindungen JE INSTANZ. Leer = 20.
|
|
#
|
|
# Beim Hochskalieren mitdenken: der Wert multipliziert sich mit "replicas"
|
|
# in 05-app-deployment.yaml. Drei Instanzen mit je 20 belegen 60 der
|
|
# voreingestellt 100 Verbindungen von PostgreSQL — daneben brauchen der
|
|
# Aufraeum-CronJob, die Sicherung und gelegentlich eine Konsole noch
|
|
# welche. Entweder diesen Wert senken oder max_connections anheben.
|
|
DATABASE_POOL_SIZE: "20"
|
|
|
|
# Verzeichnis fuer hochgeladene Bilder und Videos. MUSS exakt dem mountPath
|
|
# des "uploads"-Volumes in 05-app-deployment.yaml entsprechen — die App
|
|
# weiss nicht, was dort gemountet ist, sie schreibt nur in diesen Pfad.
|
|
# Fehlt der Wert, schreibt die App nach "./uploads" relativ zum
|
|
# Arbeitsverzeichnis: das trifft im Image zufaellig denselben Ort, ist aber
|
|
# nirgends zugesichert. Deshalb hier ausdruecklich setzen.
|
|
UPLOAD_DIR: "/app/uploads"
|
|
|
|
# Ablage der Rechnungs-PDFs, nach Jahr und Kunde sortiert:
|
|
# /app/invoices/2026/mustermann-erika/RE-2026-A3F9C1B2.pdf
|
|
# Muss zum mountPath des "invoices"-Volumes in 05-app-deployment.yaml
|
|
# passen. BEWUSST ein anderes Verzeichnis als UPLOAD_DIR: auf die Uploads
|
|
# zeigt eine oeffentliche Route, auf dieses Verzeichnis keine. Siehe
|
|
# src/lib/invoice-storage.ts und 04-uploads-pvc.yaml.
|
|
INVOICE_DIR: "/app/invoices"
|
|
|
|
# Urkunden-PDFs der Bienenpatenschaft (src/lib/sponsorship/storage.ts):
|
|
# /app/invoices/urkunden/2026/WH-P-2026-00042/r1.pdf
|
|
# Unterordner des Rechnungs-Volumes: ebenso privat (keine oeffentliche Route
|
|
# zeigt dorthin), ebenso taeglich gesichert (07-backup-cronjob.yaml sichert
|
|
# das ganze Volume), und kein zweites ReadWriteOnce-Volume am App-Pod. Die
|
|
# Pfade der Rechnungen beginnen mit dem Jahr, "urkunden" kollidiert nicht.
|
|
CERTIFICATE_DIR: "/app/invoices/urkunden"
|
|
|
|
# Hintergrundaufgaben im App-Prozess (src/lib/background-jobs.ts): Urkunden
|
|
# nachholen, Abo-Lieferungen anlegen, Verzug nach Rueckbuchung beenden.
|
|
# Laufen im App-Pod, weil nur er das Volume mit CERTIFICATE_DIR einhaengt.
|
|
# "off" nur fuer zusaetzliche Instanzen, die keine Aufgaben uebernehmen sollen.
|
|
BACKGROUND_JOBS: "on"
|
|
|
|
# Stripe-Kundenportal fuer "Zahlungsart aendern" im Abo (bpc_..., kein
|
|
# Geheimnis). Legt scripts/stripe-setup.ts --apply an und gibt die ID aus.
|
|
# Leer lassen ist der Normalfall: dann sucht die App die Konfiguration ueber
|
|
# ihre Metadaten (wabenhain=abo-zahlungsart). Gibt es keine, bietet das Konto
|
|
# "Zahlungsart aendern" nicht an — die Standardkonfiguration von Stripe wird
|
|
# bewusst nie benutzt, weil sie Kuendigung oder Tarifwechsel erlauben koennte.
|
|
STRIPE_PORTAL_CONFIGURATION_ID: ""
|
|
|
|
# Umsatzsteuersatz in GANZEN Prozent, der auf der Rechnung ausgewiesen wird.
|
|
# 7 = ermaessigter Satz (Honig als Lebensmittel, Anlage 2 zum UStG)
|
|
# 19 = voller Satz
|
|
# 0 = Kleinunternehmerregelung; die Rechnung traegt dann statt der
|
|
# Steuerzeilen den Pflichthinweis nach § 19 UStG
|
|
#
|
|
# Die Shop-Preise sind BRUTTOPREISE (§ 1 PAngV). Die Steuer wird daraus
|
|
# herausgerechnet, nicht aufgeschlagen — der Endpreis bleibt also genau der,
|
|
# den die Kundschaft im Warenkorb gesehen hat.
|
|
#
|
|
# Der Satz wird bei jeder Rechnung FESTGESCHRIEBEN. Eine Aenderung hier gilt
|
|
# nur fuer kuenftige Rechnungen; bereits ausgestellte behalten ihren Satz.
|
|
VAT_RATE_PERCENT: "7"
|
|
|
|
# Satz je Kategorie. Der Steuersatz haengt an der Art der Ware: Honig ist
|
|
# ein Lebensmittel und ermaessigt besteuert, eine Bienenwachskerze nicht.
|
|
# Fehlt hier ein Wert, gilt VAT_RATE_PERCENT von oben.
|
|
#
|
|
# PROPOLIS bitte pruefen: als Lebensmittel waeren 7% richtig, als
|
|
# Nahrungsergaenzungs- oder Kosmetikprodukt 19%. Voreingestellt ist der
|
|
# volle Satz, weil er im Zweifel der sicherere ist.
|
|
VAT_RATE_PERCENT_HONIG: "7"
|
|
VAT_RATE_PERCENT_KERZEN: "19"
|
|
VAT_RATE_PERCENT_PROPOLIS: "19"
|
|
# Weitere Bienenprodukte (Kategorie SONSTIGES, z. B. Salben, Wachstuecher).
|
|
VAT_RATE_PERCENT_SONSTIGES: "19"
|
|
# Bienenpatenschaft (Urkunde, Namensgebung, Abo-Monatsbeitrag ohne
|
|
# Honiganteil): Leistung zum Regelsatz. Vor der Veroeffentlichung mit der
|
|
# Steuerberatung bestaetigen (Spec, "Geschaeftliche Konfiguration").
|
|
VAT_RATE_PERCENT_PATENSCHAFT: "19"
|
|
|
|
# Threads fuer das Umrechnen hochgeladener Videos (Admin -> Inhalte ->
|
|
# Hero-Video). NICHT ohne Not erhoehen: ffmpeg teilt sich das Speicherlimit
|
|
# dieses Pods mit dem Node-Prozess, und jeder zusaetzliche Thread haelt
|
|
# eigene Bildpuffer — bei 4K-Material rund 12 MB je Bild. Zu viele Threads
|
|
# bringen den Pod beim Video-Upload um. Siehe src/lib/video-transcode.ts.
|
|
VIDEO_TRANSCODE_THREADS: "2"
|
|
|
|
# "sandbox", bis die DHL-Versandmarken getestet sind, danach "production".
|
|
# Wirkt nur, wenn die DHL-Zugangsdaten im Secret gesetzt sind.
|
|
DHL_ENVIRONMENT: "sandbox"
|
|
|
|
# Oeffentlicher Stripe-Schluessel (pk_live_...) fuer das eingebettete
|
|
# Zahlungsformular. Nicht geheim — er steht ohnehin im HTML der Kasse.
|
|
# Muss zum STRIPE_SECRET_KEY im Secret passen (beide live). Leer = der
|
|
# Checkout nimmt keine Bestellungen an.
|
|
STRIPE_PUBLISHABLE_KEY: ""
|
|
|
|
# ---------------------------------------------------------------------
|
|
# OPTIONAL — leer lassen, solange die Funktion nicht genutzt wird
|
|
# ---------------------------------------------------------------------
|
|
|
|
# Oeffentlicher Teil von Cloudflare Turnstile (CAPTCHA). Der geheime
|
|
# Gegenpart TURNSTILE_SECRET_KEY steht im Secret — beide setzen oder beide
|
|
# leer lassen. Leer = kein CAPTCHA-Widget, die Formulare bleiben nutzbar.
|
|
NEXT_PUBLIC_TURNSTILE_SITE_KEY: ""
|
|
|
|
# Google-Eintrag, aus dem die echten Rezensionen auf der Startseite kommen.
|
|
# Die Place-ID ist oeffentlich (sie steckt in jeder Google-Maps-Adresse des
|
|
# Eintrags) und darf deshalb hier stehen; der abrechenbare
|
|
# GOOGLE_PLACES_API_KEY liegt im Secret. Leer = statische Beispiel-Stimmen.
|
|
GOOGLE_PLACE_ID: ""
|
|
|
|
# Adresse der ApiCore-API fuer den Stammdaten-Sync (Ernten, Produkte,
|
|
# Chargen — siehe src/lib/apicore-client.ts), mit dem globalen Praefix
|
|
# "api", z.B. "https://apicore.example.org/api". Nur die Adresse; die
|
|
# Zugangsdaten des Sync-Kontos liegen im Secret. Leer = der Sync-Knopf im
|
|
# Admin meldet einen Konfigurationsfehler.
|
|
APICORE_API_URL: ""
|