diff --git a/AGENTS.de.md b/AGENTS.de.md new file mode 100644 index 0000000..2600a8d --- /dev/null +++ b/AGENTS.de.md @@ -0,0 +1,54 @@ + + +# Repository-Leitlinien + +[English](AGENTS.md) | [Deutsch](AGENTS.de.md) + +Vor Codeaenderungen [CONTRIBUTING.de.md](CONTRIBUTING.de.md) lesen. +Fuer Terraform auch den [Terraform-Stilguide](docs/terraform-style.de.md) +lesen und befolgen; die dokumentierten Konventionen fuer +Root-/Child-Provider-Versionen erhalten. + + + +## Grenzen + +- `src/` ist der unabhaengig nutzbare Accelerator. + Keine Abhaengigkeit von Configurator-API, Datenbank oder gehostetem Service + einfuehren. +- `landing-zone-configurator/` enthaelt eigene App, Vertraege, Compiler, + HCL-Adapter, Runner-Paketierung und Betreiber-IaC. + Der [komponentenuebergreifenden Entwicklungsuebersicht](landing-zone-configurator/docs/development.de.md) + folgen. +- Native Eingaben, generierte Kataloge, Domaenenvalidierung, API-/Jobvertraege, + Frontend/Sprachen, Runner und Assistant-Wissen konsistent halten. + Artefakte mit bestehenden Befehlen generieren; + generierte Inhalte nicht manuell bearbeiten. +- Importierte Felder, stabile Ressourcenidentitaeten, Null-/Default-Semantik, + Tenant-Autorisierung und revisionsgebundene Freigaben erhalten. + Assistant-Annahme ist weder Persistenz noch Erlaubnis fuer Plan/Apply. + + + +## Verifikation und Betrieb + +- Gepinnte Tools und kleinste relevante bestehende Pruefungen verwenden, + danach den vollstaendigen betroffenen Ablauf validieren. + Uebersprungene Pruefungen und offene Fehler explizit berichten. +- Aenderungen an Assistant-Fakten oder -Faehigkeiten benoetigen + quellengebundene Realmodell-Qualifikation gemaess Wissensvertrag. + Fehlgeschlagene Wiederholungen sind Fehler, keine Retries; + Validierung nicht fuer einen gruenen Nachweis abschwaechen. +- Niemals Secrets, Kundenzustand, rohe Plaene oder private Betriebsevidenz + offenlegen. + Keine Cloud-Mutationen oder Deployments ohne explizite Autorisierung. +- Configurator-Provisionierung und Anwendungsdeployment sind manuelle + Workflows. + Ein Source-Merge ist keine Deployment-Freigabe; + Produktion ist ein getrennter Folgeschritt. +- Nicht betroffene Worktree-Aenderungen erhalten. + Direkt zugehoerige oeffentliche und Contributor-Dokumentation + aktualisieren, keine datierten Sitzungsnotizen oder Uebergabedateien. +- Englisch als primaere Dokumentationssprache und deutsche Begleiter + gemaess [CONTRIBUTING.de.md](CONTRIBUTING.de.md) pflegen; + generierte und maschinell eingelesene Quellvertraege erhalten. diff --git a/AGENTS.md b/AGENTS.md index 5f9dbaf..57e7a04 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,7 @@ # Repository guidance +[English](AGENTS.md) | [Deutsch](AGENTS.de.md) + Read [CONTRIBUTING.md](CONTRIBUTING.md) before changing code. For Terraform, also read and follow [the Terraform style guide](docs/terraform-style.md); preserve the documented root/child provider-version conventions. @@ -31,3 +33,6 @@ preserve the documented root/child provider-version conventions. A source merge is not deployment approval; production is a separate follow-up. - Preserve unrelated worktree changes. Update directly related public and contributor documentation, not dated session notes or handoff files. +- Maintain English-first documentation and German companions according to + [CONTRIBUTING.md](CONTRIBUTING.md); preserve generated and machine-ingested + source contracts. diff --git a/CONTRIBUTING.de.md b/CONTRIBUTING.de.md new file mode 100644 index 0000000..9ca09b6 --- /dev/null +++ b/CONTRIBUTING.de.md @@ -0,0 +1,161 @@ + +# Mitwirken + +[English](CONTRIBUTING.md) | [Deutsch](CONTRIBUTING.de.md) + +Vielen Dank, dass Sie sich die Zeit nehmen, einen Beitrag zu leisten. Dieses Dokument beschreibt die lokale Einrichtung, die Konventionen dieses Repositorys und den erwarteten Inhalt eines Pull Requests. + + +## Lokale Einrichtung + +Die Werkzeugversionen sind in `mise.toml` festgelegt. Installieren Sie sie einmalig: + +```bash +mise install +``` + +Damit stehen OpenTofu, die STACKIT CLI, `terraform-docs` und `pre-commit` in den Versionen bereit, gegen die dieses Repository getestet wird. + +Installieren Sie die Git-Hooks: + +```bash +pre-commit install +``` + +Die Hooks führen `tofu fmt` aus und erzeugen die Moduldokumentation neu. Wenn ein Hook eine Datei umschreibt, nehmen Sie das Ergebnis in den Staging-Bereich auf und versuchen Sie den Commit erneut. + +Der Dokumentations-Hook ruft `terraform-docs` über `mise exec` auf. So verwendet er die in `mise.toml` festgelegte Version und funktioniert auch, wenn Git aus einem Editor ohne geladene mise-Umgebung gestartet wird. + +Für eine Bereitstellung in einer echten STACKIT-Organisation ist zusätzlich ein Dienstkontoschlüssel erforderlich. `mise.toml` erwartet ihn unter `~/.stackit/credentials.json`; siehe [docs/getting-started.md](docs/getting-started.de.md). + + +## Vor dem Öffnen eines Pull Requests + +```bash +cd src +tofu fmt -recursive +tofu init -backend=false +tofu validate +tofu test +``` + +`tofu test` führt die Konfigurationssuiten in `src/tests/` als lokale, reine +Plan-Läufe mit Mock-Providern aus. Diese Tests erstellen keine Cloud-Ressourcen. +Die Prüfung in der echten Cloud ist ein separater, manuell gestarteter Workflow, +keine gewöhnliche PR-Prüfung. + + +## Konventionen + + +### Änderungen über Accelerator und Configurator hinweg + +Der Accelerator bleibt unabhängig nutzbar. Configurator-Funktionen betreffen oft +mehrere Komponenten; aktualisieren Sie den vollständigen Vertrag, nicht nur ein +sichtbares UI-Feld. Lesen Sie zuerst die +[Entwicklungsübersicht](landing-zone-configurator/docs/development.de.md) und die +[Architektur](landing-zone-configurator/docs/architecture.de.md). + +1. **Native Infrastruktur:** Ergänzen oder ändern Sie Root-/Moduleingaben und -ausgaben, + Standardwerte, Validierung und Modultests in `src/`. Bewahren Sie State-Adressen und + Kompatibilität oder dokumentieren Sie die Migration ausdrücklich. +2. **Eingabe-/Katalogadapter:** Aktualisieren Sie HCL-Import/-Export und erzeugen Sie + die geprüften Kataloge für native Eingaben und Templates über die bestehenden + [Adapterbefehle](landing-zone-configurator/tools/hcl-adapter/README.de.md) neu. +3. **Domain/Compiler:** Verdrahten Sie native Felder, die Semantik von optional/null/Standardwerten, + die Erhaltung von Werten und deterministische Validierung in `app/packages/domain`. +4. **API/Verträge:** Aktualisieren Sie gemeinsame Anfrage-/Jobverträge und serverseitige Mandanten-, + Berechtigungs-, Revisions- und Lebenszyklusprüfungen. Verlassen Sie sich nicht auf reine Browserprüfungen. +5. **Frontend:** Bilden Sie denselben Vertrag, beide Sprachen, hilfreiche Validierung und + ausdrückliche Prüfung/Annahme ab. Testen Sie Desktop/Mobilgeräte und den Erhalt von Entwürfen. +6. **Runner/Release:** Führen Sie geänderte Eingaben und Ausgaben durch Broker, State, + Migrationen, festgelegte Pakete und Jobergebnisse. Halten Sie die Quellherkunft von API/UI + und Runner konsistent; führen Sie niemals einen beliebigen Repository-Head aus. +7. **Assistant:** Prüfen Sie Themenzuständigkeit, kuratierte Fakten, Berechtigungen und Vorschlagsschemata. + Erzeugen Sie Wissen/Abdeckung neu, ergänzen Sie faktische positive und negative + Oracle-Tests und qualifizieren Sie betroffene Fälle mit dem echten Modell mindestens zweimal. + Eine neue Fähigkeit oder eine breite Vertragsänderung benötigt außerdem die vollständige + wiederholte Suite und den durchgängigen Dialog. Schwächen Sie kein Oracle ab, um einen echten Fehler zu verbergen. +8. **Dokumentation:** Aktualisieren Sie sichtbares Benutzerverhalten, Architektur und Hinweise + für Mitwirkende. Verlinken Sie Folge-Issues für bewusst gesetzte Grenzen. + +Verwenden Sie für die Configurator-Einrichtung Node **24.21.0**, npm **11.19.0** und dessen eigene Lockdatei: + +```sh +cd landing-zone-configurator/app +npm ci +npm run check +``` + +Verwenden Sie während der Entwicklung die kleinsten relevanten Tests und vor der +Prüfung die zutreffenden Integrationsprüfungen: + +| Änderung | Erforderlicher Nachweis | +| --- | --- | +| Native Eingaben/Templates | Modultests; Adapter `go test ./...` und Katalogprüfungen; `npm run test:common-contract` | +| Domain/API/UI | `npm run check`; relevante Datenbank- und Playwright-Tests | +| Broker, Vorbereitungen, Runner oder State | Relevante Worker-/Brokertests; `npm run test:platform-database`; Paketierungs- und State-Regressionstests | +| Assistant | `npm run assistant:generate`, Formatierung generierter Dateien, `npm run assistant:check`, faktische Unit-Tests und quellgebundene Live-Nachweise | +| Operator-CI/IaC | Relevante `node --test`-Prüfungen; Workflow-Lint; Formatierung/Initialisierung/Validierung und Mock-Tests für betroffene IaC-Roots | + +Die [Anwendungs-README](landing-zone-configurator/app/README.de.md) dokumentiert die +genauen Befehle für Generierung, Datenbank, Browser und das echte Modell. +Datenbank-/Browsertests verwenden isolierte Testdienste. Gewöhnliche PR-Prüfungen +dürfen keine Kundeninfrastruktur bereitstellen. Teilen Sie keine +Ausführungszugangsdaten mit der ausschließlich für Inferenz vorgesehenen Umgebung +`assistant-tests`. Configurator-Provisionierung und -Bereitstellung bleiben manuell; +die Produktionseinrichtung ist eine separate Aufgabe. + +Der [Workflow-Katalog](docs/workflows.de.md) führt alle Pipelines, automatischen/manuellen +Auslöser und Startanleitungen für die Oberfläche auf. Aktualisieren Sie ihn bei Änderungen +an Workflow-Namen, Auslösern, Eingaben oder betrieblichen Freigabeschranken; halten Sie +die Bereitstellungsfreigabe getrennt von der PR-Freigabe. + + +### Terraform-Konventionen + +Befolgen Sie neben den folgenden bestehenden Modulkonventionen den vollständigen +[Terraform-Stilleitfaden](docs/terraform-style.de.md). + +**Terraform-Struktur.** Jedes Modul hält seinen `terraform`-Block in `terraform.tf`, seine Variablen in `variables.tf` und seine Ausgaben in `outputs.tf`. Ressourcendateien erhalten ein numerisches Präfix, wenn die Lesereihenfolge wichtig ist; jede Ressourcengruppe wird durch einen eingerahmten Abschnittskopf eingeleitet. + +**Provider-Versionen.** Das Root-Modul in `src/terraform.tf` legt jeden Provider auf eine exakte Version fest. Child-Module unter `src/modules/` deklarieren nur eine Mindestversion mit `>=`. Fügen Sie niemals eine Obergrenze in einem Child-Modul hinzu; diese blockiert unbemerkt ein Upgrade im Root-Modul. + +**Benennung.** `snake_case` für alle Blockbezeichnungen, Variablen, Ausgaben und lokalen Werte. Ressourcennamen wiederholen den Ressourcentyp nicht. + +**Variablen und Ausgaben.** Jede Variable benötigt `type` und `description`. Jede Ausgabe benötigt `description` vor `value`. + +**Kommentare.** Ein Kommentar erklärt eine Einschränkung, die der Code nicht zeigen kann, etwa einen Provider-Fehler oder eine Besonderheit der OPNsense-API. Beschreibungen der Funktionsweise des Codes oder des Architekturzusammenhangs gehören in [docs/architecture.md](docs/architecture.de.md). + +**Dokumentation.** Modul-READMEs werden generiert. Bearbeiten Sie den Block zwischen den Markern `BEGIN_TF_DOCS` und `END_TF_DOCS` nicht von Hand; führen Sie stattdessen den pre-commit-Hook aus. + +**Beispielkonfiguration.** Die tfvars-Dateien in `src/config/` dienen als Dokumentation. Belassen Sie Platzhalterwerte wie `owner@example.com` und eine Null-UUID für die Organisation. Committen Sie niemals eine Kennung aus einer echten Umgebung. + + +### Zweisprachige Dokumentation + +Englische `.md`-Dateien sind maßgeblich; Dokumentation für Menschen erhält +vollständige deutsche `.de.md`-Pendants, keine Zusammenfassungen. Setzen Sie die +wechselseitige Navigation `[English](name.md) | [Deutsch](name.de.md)` unmittelbar +nach jede H1 und aktualisieren Sie bei Prosaänderungen beide Sprachen. Bewahren Sie +Befehle, Beispiele, exakte Werte und bestehende Überschriftenanker. + +Lassen Sie generatorverwaltete Verträge unverändert: Erzeugen Sie die englische +Referenz mit den bestehenden Werkzeugen neu und übernehmen Sie ihre technischen +Blöcke wortgetreu in das deutsche Pendant, mit einer deutschen Einleitung samt +Link zur maßgeblichen Referenz. Maschinell eingelesene Assistant-Themen bleiben +unverändert auf Englisch; verzeichnen Sie ihre separaten deutschen Übersetzungen +für Menschen in der Assistant-Wissens-README, statt die eingelesenen Themen zu ändern. + + +## Commits und Pull Requests + +Commit-Nachrichten folgen [Conventional Commits](https://www.conventionalcommits.org/), mit dem Modul als optionalem Scope: + +``` +feat(connectivity): add active/passive CARP support +fix(audit-logs): add HTTPS scheme to URLs +docs: clarify firewall bootstrap steps +``` + +Öffnen Sie den Pull Request gegen `main`. Beschreiben Sie, was sich für Nutzer der Landing Zone ändert, und geben Sie an, mit welcher Variante Sie getestet haben. CI führt Formatierung, Validierung, TFLint und die Testsuiten aus; alle müssen vor der Prüfung erfolgreich sein. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3cbd85f..3aaa96e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,7 @@ # Contributing +[English](CONTRIBUTING.md) | [Deutsch](CONTRIBUTING.de.md) + Thanks for taking the time to contribute. This document describes the local setup, the conventions this repository follows, and what a pull request is expected to contain. ## Local setup @@ -120,6 +122,20 @@ existing module conventions below. **Example configuration.** The tfvars files in `src/config/` are documentation. Keep them on placeholder values such as `owner@example.com` and a zero UUID for the organization. Never commit an identifier from a real environment. +### Bilingual documentation + +English `.md` files are canonical; human-facing documentation has complete German +`.de.md` peers, not summaries. Put reciprocal `[English](name.md) | [Deutsch](name.de.md)` +navigation immediately after each H1 and update both languages whenever prose +changes. Preserve commands, examples, exact values and existing heading anchors. + +Keep generator-owned contracts unchanged: regenerate the English reference with +the existing tooling and copy its technical blocks verbatim into the German peer, +with a German introduction linking the canonical reference. Machine-ingested +Assistant topics remain unchanged in English; index their separate human-readable +German translations in the Assistant knowledge README rather than changing the +ingested topics. + ## Commits and pull requests Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/), with the module as the optional scope: diff --git a/README.de.md b/README.de.md new file mode 100644 index 0000000..d298f21 --- /dev/null +++ b/README.de.md @@ -0,0 +1,45 @@ +
+
+STACKIT logo +
+
+
+ +# Landing Zone Accelerator + +[English](README.md) | [Deutsch](README.de.md) + +[![Terraform](https://img.shields.io/badge/Terraform-1.15+-623CE4?logo=terraform&logoColor=white)](https://www.terraform.io/) +[![OpenTofu](https://img.shields.io/badge/OpenTofu-1.12+-FFDA18?logo=opentofu&logoColor=black)](https://opentofu.org/) +[![STACKIT](https://img.shields.io/badge/STACKIT-Cloud-004E5A)](https://www.stackit.de/) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) + +Der STACKIT Landing Zone Accelerator bietet ein umfassendes Terraform-basiertes Framework für die Bereitstellung sicherer, skalierbarer und durchdacht aufgebauter Cloud-Umgebungen auf STACKIT. Auf Basis bewährter Unternehmenspraktiken können Teams damit schnell Grundlagen für Governance, Netzwerke und Sicherheit schaffen. + +Der Accelerator bleibt mit Terraform/OpenTofu unabhängig nutzbar. Der +Configurator ist ein optionales Werkzeug, keine erforderliche API, Template-Engine +oder Zustandsverwaltung. Für getrennte Platform- und Application-Phasen siehe den +[unabhängigen CLI-Ablauf](src/application/README.de.md#independent-two-phase-cli-workflow). +Die Plattform exportiert geprüfte, nicht geheime Referenzen; Application-Eingaben +können manuell ausgefüllt werden und verwenden ein separates Backend mit eigenem State. + + +## 📚 Dokumentation + +- [Erste Schritte](docs/getting-started.de.md) +- [Architektur/Module](docs/architecture.de.md) +- [Landing Zone Configurator](landing-zone-configurator/README.de.md) +- [Configurator-Architektur](landing-zone-configurator/docs/architecture.de.md) +- [Configurator-Benutzerhandbuch](landing-zone-configurator/docs/user-guide.de.md) +- [Configurator-Entwicklung](landing-zone-configurator/docs/development.de.md) +- [GitHub-Actions-Workflows](docs/workflows.de.md) – alle Pipelines, automatische/manuelle Auslöser, Startanleitungen für die Oberfläche, Eingaben und Auswirkungen auf Bereitstellungen + + +## 🤝 Mitwirken + +Beiträge sind willkommen. [CONTRIBUTING.md](CONTRIBUTING.de.md) beschreibt die lokale Einrichtung, die Konventionen dieses Repositorys und den erwarteten Inhalt eines Pull Requests. + + +## 📄 Lizenz + +Dieses Projekt ist unter der Apache 2.0 License lizenziert – Einzelheiten stehen in [LICENSE](LICENSE). diff --git a/README.md b/README.md index 33cbe87..3a6ec2d 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ # Landing Zone Accelerator +[English](README.md) | [Deutsch](README.de.md) + [![Terraform](https://img.shields.io/badge/Terraform-1.15+-623CE4?logo=terraform&logoColor=white)](https://www.terraform.io/) [![OpenTofu](https://img.shields.io/badge/OpenTofu-1.12+-FFDA18?logo=opentofu&logoColor=black)](https://opentofu.org/) [![STACKIT](https://img.shields.io/badge/STACKIT-Cloud-004E5A)](https://www.stackit.de/) diff --git a/docs/architecture.de.md b/docs/architecture.de.md new file mode 100644 index 0000000..9fcf23f --- /dev/null +++ b/docs/architecture.de.md @@ -0,0 +1,389 @@ + +# Architektur + +[English](architecture.md) | [Deutsch](architecture.de.md) + +Dieses Repository ist ein produktionsbereites OpenTofu-/Terraform-Framework für die Bereitstellung einer STACKIT Landing Zone. Es provisioniert die vollständige Cloud-Grundlage: Governance-Hierarchie, Identitäts- und Zugriffsverwaltung, gemeinsame Netzwerke, optionale Firewall, DNS, Geheimnisverwaltung, Observability sowie wiederholbare Projektvorlagen pro Workload. + +Alles wird aus sechs Modulen unter `src/modules/` zusammengesetzt und in `src/main.tf` verdrahtet. Ein einzelnes `terraform apply` mit einer der vollständigen Referenzkonfigurationen aus `src/config/` stellt die gesamte Plattform bereit. + + +## Zweischichtenmodell + +``` +Organization +├── Platform Landing Zone ← managed by platform team, provisioned once +│ ├── Management project (automation, state, secrets, observability) +│ ├── Connectivity project (network hub, firewall, DNS) +│ └── DevOps project (optional managed Git) +└── Application Landing Zones ← one per workload/environment + ├── Corporate LZ (attached to shared network, routed via firewall) + └── Public LZ (standalone network, internet-facing) +``` + +Die **Platform Landing Zone** ist die unternehmensweite Grundlage. Sie wird einmal bereitgestellt und vom Plattformteam verantwortet. Sie schafft Governance-Struktur, gemeinsame Netzwerkinfrastruktur und Automatisierungswerkzeuge, auf denen alle Workloads aufbauen. + +Eine **Application Landing Zone** wird einmal pro Workload und Umgebung instanziiert (z. B. `data-prod`, `api-staging`). Jede Instanz ist ein isoliertes STACKIT-Projekt mit vorbereiteten Netzwerken, RBAC, Secrets und Speicher: bereit für die Nutzung durch ein Team, ohne verbleibende Plattformentscheidungen. + + +## Module + +Alle Module liegen unter `src/modules/`. Das Root `src/main.tf` ruft sie in Abhängigkeitsreihenfolge auf. + +| Modul | Ordner im Repository | Erstellte Bestandteile | +|---|---|---| +| `governance` | `src/modules/governance/` | Resource-Manager-Ordnerhierarchie, RBAC auf Organisationsebene, benutzerdefinierte Rollen | +| `management` | `src/modules/management/` | Automatisierungsprojekt: Dienstkonto, Terraform-State-Bucket, Secrets Manager, Observability | +| `connectivity` | `src/modules/connectivity/` | Netzwerk-Hub: Network Area, WAN-Routingtabelle, optionale Firewall-VM, DNS-Zonen | +| `devops` | `src/modules/devops/` | Optionales DevOps-Projekt mit verwalteter Git-Instanz | +| `landing-zone` | `src/modules/landing-zone/` | Projekt pro Workload: Netzwerk, RBAC, Secrets Manager, Object Storage, DNS-Unterzone, Routing | +| `sandboxes` | `src/modules/sandboxes/` | Leichtgewichtige Sandbox-Projekte für Experimente | +| `firewall-config` | `src/modules/firewall-config/` | Optional: Übertragung von Regeln, NAT und Internethärtung über die API an die OPNsense-Appliance | + +### Governance + +Erstellt die Resource-Manager-Ordnerhierarchie unter der Root-Organisation. Standardordner: + +- **Platform**: übergeordneter Ordner für alle Plattformprojekte (Management, Connectivity, DevOps) +- **Landing Zones - Corporate**: übergeordneter Ordner für netzwerkverbundene Workload-Projekte +- **Landing Zones - Public**: übergeordneter Ordner für internetseitige Workload-Projekte +- **Sandboxes**: übergeordneter Ordner für kurzlebige Sandbox-Projekte + +Verwaltet außerdem Rollenzuweisungen auf Organisationsebene für Eigentümer (`organization_owners`) und Auditoren mit Lesezugriff (`organization_auditors`). + +Quelle: `src/modules/governance/` + +### Management + +Provisioniert das zentrale Automatisierungsprojekt (`-pltfm-mgmt-prod`). Enthält: + +- **Dienstkonto**: Wird von CI/CD-Pipelines zum Ausführen von Terraform verwendet. Unterstützt OIDC-Föderation (z. B. GitHub Actions), damit sich Pipelines ohne langlebige Schlüssel authentifizieren. +- **Object-Storage-Buckets**: Einer für Terraform-Remote-State, einer für allgemeine Plattformnutzung. +- **Secrets-Manager-Instanz**: Speichert Plattformgeheimnisse wie Dienstkontoschlüssel und Zugangsdaten. +- **Observability-Instanz** (optional): Zentrale Logs, Metriken und Traces mit konfigurierbarer Aufbewahrung. Aktiviert über die Variable `observability`. + +Quelle: `src/modules/management/` + + +### Konnektivität + +Erstellt ein Netzwerk-Hub-Projekt pro konfigurierter Konnektivitätsdomäne. Jede Corporate Landing Zone wird ausdrücklich einer Domäne zugeordnet. Dies ist das komplexeste Modul. + +#### Network Area + +Eine STACKIT Network Area (SNA) definiert einen gemeinsamen privaten IP-Adressraum auf Organisationsebene. Netzwerke von Corporate Landing Zones in derselben SNA können sich ohne zusätzliches Peering über private IPs erreichen. + +Die Konfiguration bestimmt den Adressplan der Area: + +```hcl +network_area = { + ranges = ["10.0.0.0/16"] # total address space + transfer_network = "10.255.0.0/24" # internal STACKIT routing fabric + min_prefix_length = 24 # smallest subnet a landing zone may request + max_prefix_length = 28 # largest subnet a landing zone may request + default_prefix_length = 25 # default if landing zone doesn't specify +} +``` + + +#### Mehrere Network Areas + +`connectivity.network_areas` erstellt mehrere unabhängige Konnektivitätsdomänen. Es handelt sich um eine Map mit stabilen, aussagekräftigen Schlüsseln. Diese können beliebige Geschäfts-, Sicherheits-, Mandanten-, Konnektivitäts- oder Regionsgrenzen darstellen, etwa `regulated`, `tenant_a`, `private_connectivity`, `eu01` oder `eu02`. Sie sind nicht auf Entwicklungs- und Produktionsumgebungen beschränkt. + +Jeder Schlüssel erstellt seine eigene SNA, sein Connectivity-Projekt, seine WAN-Routingtabelle und seine DNS-Standardwerte. Corporate Landing Zones wählen ihre Domäne mit `network_area_key`; DNS-Zonen verwenden `dns_zones..network_area_key`. Platform Kubernetes verwendet `platform_kubernetes..network.network_area_key`. Connectivity-Projekte erhalten Labels mit der SNA-ID und dem entsprechenden Schlüssel; die Ausgaben `*_by_area` verwenden dieselben Schlüssel. + +Verwenden Sie mehrere SNAs nur, wenn eine private Netzwerkgrenze erforderlich ist. Geeignete Gründe sind regulatorische Trennung, Mandantenisolation in einer gemeinsamen unternehmensweiten STACKIT-Organisation sowie Geschäftsbereiche mit unabhängigen Eigentümern, Adressplänen oder externen Konnektivitätsanforderungen. Siehe [die vollständige Regulated-/Shared-Konfiguration](../src/config/hub-and-spoke-multi-area.tfvars), [die Finance-/Research-Konfiguration](../src/config/hub-and-spoke-finance-research.tfvars) und [die Tenant-Isolation-Konfiguration](../src/config/hub-and-spoke-tenant-isolation.tfvars). + + +#### Gemeinsame Dienste über SNA-Grenzen hinweg + +Ein STACKIT-Projekt kann genau einer SNA zugeordnet sein. Ein zentral betriebener privater Dienst, etwa eine interne Git-Plattform, kann daher nicht direkt sowohl an eine `prod`- als auch an eine `nonprod`-SNA angeschlossen werden. SNAs haben außerdem keinen gemeinsamen privaten Routingpfad. + +Wählen Sie mehrere SNAs nur, wenn diese Einschränkung beabsichtigt ist. Gemeinsame Dienste müssen öffentliche oder SaaS-Dienste sein, die durch IAM und Netzwerkbeschränkungen geschützt werden, pro SNA dupliziert werden oder über ausdrückliche externe Endpunkte wie Site-to-Site-VPN über das Internet verbunden sein. Letzteres bringt zusätzliche Betriebs- und Sicherheitsverantwortung mit sich und muss separat entworfen und geprüft werden. Eine gemeinsame SNA mit separaten Projekten, IAM-Rollen und Subnetzzuweisungen ist meist die einfachere Wahl, wenn Workloads häufig privaten Zugriff auf dieselben Plattformdienste benötigen. + +Die bisherige Eingabe `connectivity.network_area` bleibt für Einzel-Area-Bereitstellungen unterstützt und wird dem Schlüssel `default` zugeordnet. Bestehende skalare Connectivity-Ausgaben referenzieren weiterhin diese bisherige Standard-Area. + + +#### Regionsübergreifende Bereitstellungen + +Das Root-Modul unterstützt über statische STACKIT-Provider-Aliase eine Single-Stack-Topologie in `eu01` und `eu02`. Jede Region erhält ihren eigenen Connectivity-Hub, ihre SNA, Landing Zones und optional einen Platform-Kubernetes-Cluster; wählen Sie die Region ausdrücklich in der Konfiguration. Provider-Aliase können nicht dynamisch ausgewählt werden. Unterstützung einer weiteren Region erfordert daher einen entsprechenden Provider-Alias und regionale Modulinstanzen. + +Regionale Hubs bleiben standardmäßig isoliert. Regionsübergreifende Konnektivität erfordert ausdrückliche externe VPN-Endpunkte und Routen; sie wird nicht vom Multi-Region-Szenario erstellt. Siehe [die vollständige Multi-Region-Konfiguration](../src/config/hub-and-spoke-multi-region.tfvars). + + +#### WAN-Routingtabelle + +Eine Routingtabelle namens `wan` wird mit einer einzelnen Standardroute erstellt: + +``` +0.0.0.0/0 → internet +``` + +Dies ist die Route für ausgehenden Verkehr des WAN-Netzwerks der Firewall. Der Verkehr gelangt über das STACKIT-Standardgateway direkt ins Internet. + + +#### DNS-Zonen + +Eine oder mehrere DNS-Zonen werden im Connectivity-Projekt erstellt und dienen als autoritative Zonen der Plattform. Unterzonen werden automatisch an einzelne Landing Zones delegiert. Subdomains sind bei von STACKIT bereitgestellten Domains wie .stackit.run nicht erlaubt. + +Beispiel: Ist die Hub-Zone `example-corp.stackit.run.`, erhält eine Landing Zone für den Workload `data` in `prod` in der Region `eu01` die delegierte Unterzone `data-prod-eu01-example-corp.stackit.run.`. + + +#### Firewall-VM (optional) + +Wenn `connectivity.firewall` gesetzt ist, wird eine VM mit OPNsense (bereitgestellt als `.qcow2`-Image) und zwei Netzwerkschnittstellen angelegt: + +| Schnittstelle | STACKIT-Netzwerk | Zweck | +|---|---|---| +| `vtnet0` (WAN) | `wan_network`: mit der WAN-Routingtabelle verbunden | Ausgehender Internetverkehr, mit zugewiesener statischer öffentlicher IP | +| `vtnet1` (LAN) | `lan_network`: dediziertes privates Subnetz | Interner Next-Hop für den gesamten Verkehr der Corporate Landing Zones | + +Die LAN-IP der Firewall wird als `firewall_next_hop_ip` exportiert und an jede Corporate Landing Zone übergeben, damit ihre Standardroute darauf zeigen kann. Alles, was die Plattform nach außen sendet, durchquert daher die Appliance. + +Beide Schnittstellen sind DHCP-Clients und beziehen die festen, von STACKIT zugewiesenen Adressen. Das Image startet nahezu ohne Richtlinie: nur die zwei Standardregeln `allow LAN to any` (IPv4 und IPv6), keine Gateways, keine statischen Routen, kein IPsec und Outbound NAT auf `automatic`. Es filtert nichts, bis eine Richtlinie übertragen wird. + +> [!WARNING] +> Nach dem ersten Apply antwortet die Web-GUI auf der öffentlichen IP dem gesamten Internet. Sie verwendet weiterhin das im Image enthaltene `root`-Passwort, das bei jeder Kopie identisch ist. Port 443 ist offen, 80 und 22 sind es nicht, und vor der WAN-Schnittstelle liegt keine Security Group. Das Übertragen der Richtlinie schließt den Zugriff; lassen Sie eine Bereitstellung deshalb nicht zwischen den beiden Applies stehen – siehe [OPNsense-Firewall konfigurieren](getting-started.de.md#configure-opnsense-firewall). Die GUI ausschließlich an die LAN-Schnittstelle zu binden (**System → Settings → Administration → Listen Interfaces**) ist die vom Regelsatz unabhängige Alternative. + + +#### Hochverfügbarkeit (optional) + +Eine einzelne Appliance ist ein Single Point of Failure für jede Corporate Landing Zone: Sie ist deren Standardroute. Mit `connectivity.firewall.ha` wird daraus ein aktives/passives CARP-Paar. + +| | Primary | Backup | +|---|---|---| +| Availability Zone | `firewall.zone` | `firewall.ha.backup_zone` (muss abweichen) | +| LAN-Adresse | `.4` von `lan_network_range` | `.5` | +| WAN-Adresse | `.4` von `wan_network_range` | `.5` | +| Öffentliche IP | eigene, statisch | eigene, statisch | +| CARP advskew | 0 (gewinnt die Wahl) | 100 | + +Eine virtuelle CARP-IP im LAN – standardmäßig `.6` von `lan_network_range` – ersetzt die LAN-Adresse des Primary in der Ausgabe `firewall_next_hop_ip`. Die Landing-Zone-Routen zeigen dadurch auf die VIP statt auf einen Knoten. Bei einem Failover wechselt die VIP in etwa einer Sekunde zum überlebenden Knoten; die Routen ändern sich nie. + +**CARP läuft im Unicast-Modus** (OPNsense >= 24.7). Das ist keine Präferenz: Das STACKIT-Fabric liefert Verkehr *an* die virtuelle CARP-MAC, verwirft aber Ankündigungen *von* ihr. Multicast-CARP endet deshalb in Split-Brain. Das Modul verweigert die Konfiguration eines Knotens, dessen OPNsense kein Unicast-Feld `peer` besitzt. + +Zwei Dinge werden außerhalb des OPNsense-Providers übertragen, da dieser immer nur mit dem Primary kommuniziert: + +- `modules/connectivity/scripts/configure-ha.sh` schreibt während des Apply die knotenspezifische Hälfte auf jede Appliance: CARP-VIP, `advskew`, pfsync-Peer und XMLRPC-Synchronisierungsziel. Das sind genau die Einstellungen, die die Konfigurationssynchronisierung nicht repliziert. Das Skript authentifiziert sich mit der Appliance-Anmeldung und funktioniert daher auch auf dem Backup, das keinen API-Schlüssel hat und nie einen benötigt. +- `modules/firewall-config/scripts/sync-ha-peer.sh` repliziert die Richtlinie nach jeder Änderung zum Backup. Die XMLRPC-Synchronisierung von OPNsense wird nur beim Speichern in der GUI ausgelöst, nie bei API-Schreibvorgängen. Ohne dies läuft auf dem Backup ein leerer Regelsatz, der Verkehr verschluckt, sobald es CARP-Master wird. Ein Failover-Test ohne Richtliniensynchronisierung maß einen Ausfall von 86 Sekunden, gegenüber etwa einer Sekunde mit Synchronisierung. + +Der Alias `fw_cluster` und die Regeln `allow-fw-carp` / `allow-fw-pfsync`, die die Kommunikation der Knoten erlauben, werden bei aktiviertem HA automatisch in `firewall_config` eingefügt, mit Sequenzen 90 und 91 – vor jeder Regel der Beispielrichtlinie. Sie stehen nicht in den `.tfvars`, weil eine darüber platzierte Regel `block-lz-to-lz` die Wahl und die Zustandssynchronisierung unbemerkt unterbricht. + +### Landing Zone + +Wird einmal pro Workload/Umgebung über `for_each` auf der Variablen `landing_zones` instanziiert. Jede Instanz erstellt ein vollständig isoliertes STACKIT-Projekt mit: + +- **STACKIT-Projekt**: Je nach Flag `corporate` unter dem Corporate- oder Public-Ordner platziert. +- **Netzwerk**: Corporate Landing Zones erhalten ein geroutetes Netzwerk an der gemeinsamen Network Area; öffentliche Landing Zones erhalten ein eigenständiges Netzwerk. +- **Routingtabelle** (nur Corporate + Firewall): Eine projektspezifische Routingtabelle mit einer einzelnen Standardroute zur LAN-IP der Firewall: + ``` + 0.0.0.0/0 → + ``` + Ohne Firewall verwenden Corporate Landing Zones Ost-West-Routing über die Network Area, verlassen die Plattform aber direkt über die WAN-Routingtabelle ins Internet. +- **RBAC**: Rollenzuweisungen für das Anwendungsteam, pro Landing Zone in der Liste `role_assignments` definiert. +- **Secrets Manager**: Isolierte Instanz für Workload-Geheimnisse. +- **Object-Storage-Buckets**: Einer für Anwendungsdaten, einer für Terraform-State. +- **DNS-Unterzone**: Von der Zone des Connectivity-Hubs delegiert (nur Hub-Spoke- und Firewall-Varianten). +- **Dienstkonto**: Auf den Workload begrenztes Dienstkonto mit rotierendem Schlüssel im Secrets Manager. + +Das Flag `corporate` ist der entscheidende Schalter: + +| `corporate` | Netzwerkanbindung | Standardroute | DNS | +|---|---|---|---| +| `true` | Gemeinsame Network Area | Firewall-LAN-IP (falls Firewall bereitgestellt), sonst Internet über WAN-Tabelle | Vom Hub delegierte Unterzone | +| `false` | Eigenständiges Netzwerk | Direkt ins Internet | Keine DNS-Delegation | + +Quelle: `src/modules/landing-zone/` + + +### Landing Zone auf Kubernetes + +Jeder Eintrag in `landing_zone_namespace_services` erhält einen Mandantenbereich des gemeinsamen Plattformclusters: einen eigenen Namespace, ein begrenztes Dienstkonto mit einer auf diesen Namespace beschränkten Role und optional eine Kyverno-Richtlinie, die direkte Secret-Verwaltung blockiert, sodass Zugangsdaten über den Secrets Manager kommen müssen. + +Der Beispiel-Workload hinter `sample_load` ist Demomaterial und nicht Teil des Landing-Zone-Vertrags. Er stellt einen Pod, eine Gateway-API-Route und einen DNS-Eintrag bereit, die gemeinsam den funktionierenden Pfad aus dem Internet zu einem Namespace belegen. Entfernen Sie ihn, sobald echte Workloads einziehen. + +Quelle: `src/_landing-zone-kubernetes.tf`, `src/modules/namespace-service-demo/` + + +### DevOps (optional) + +Provisioniert ein separates DevOps-Projekt (`-pltfm-devops-prod`) mit einer verwalteten Git-Instanz (Gitea oder gleichwertig, gesteuert durch `git_flavor`). Der Netzwerkzugriff kann über `allowed_network_ranges` auf bestimmte CIDR-Bereiche eingeschränkt werden. Standardmäßig deaktiviert; Aktivierung durch Setzen der Variablen `devops`. + +Quelle: `src/modules/devops/` + + +### Sandboxes (optional) + +Provisioniert ein oder mehrere leichtgewichtige STACKIT-Projekte unter dem Sandboxes-Ordner für Experimente und PoCs. Jede Sandbox ist ein minimales Projekt mit Eigentümer: keine gemeinsamen Netzwerke oder Plattformintegration. Nützlich zum Testen vor der Übernahme von Workloads in eine vollwertige Landing Zone. + +Quelle: `src/modules/sandboxes/` + + +## Bereitstellungsvarianten + +Vollständige Referenzkonfigurationen stehen in `src/config/` bereit. Die folgenden Diagramme konzentrieren sich bewusst auf Topologiegrenzen, Verkehrswege und die Projekte, die Nutzer erhalten, statt auf jede provisionierte Ressource. Wählen Sie die Konfiguration passend zu Ihren Netzwerk- und Isolationsanforderungen; [Erste Schritte](getting-started.de.md#deployment-flavours) beschreibt die Bereitstellung. + +### Standalone + +Die einfachste Konfiguration. Sie provisioniert Governance, Management, eine Sandbox und eine öffentliche Landing Zone mit unabhängigem Netzwerk. Es werden weder gemeinsame Network Area noch Connectivity-Hub erstellt. + +![Standalone-Topologie](diagrams/standalone.svg) + +Konfiguration: [`standalone.tfvars`](../src/config/standalone.tfvars) + +### Hub-Spoke + +Ergänzt einen Connectivity-Hub mit gemeinsamer Network Area und zentralem DNS. Die Corporate Data Platform tritt der privaten Area bei, während die öffentliche API-Landing-Zone ein unabhängiges Netzwerk behält. + +![Hub-and-Spoke-Topologie](diagrams/hub-and-spoke.svg) + +Konfiguration: [`hub-and-spoke.tfvars`](../src/config/hub-and-spoke.tfvars) + +### Hub-Spoke + Firewall + +Erweitert die Hub-Spoke-Topologie um eine OPNsense-Firewall. Corporate-Verkehr verwendet die Appliance für zentrale Inspektion und konsistenten Egress, während die öffentliche Landing Zone direkt angebunden bleibt. + +![Hub-and-Spoke-Topologie mit Firewall](diagrams/hub-and-spoke-firewall.svg) + +Konfiguration: [`hub-and-spoke-firewall.tfvars`](../src/config/hub-and-spoke-firewall.tfvars) + +### Finance + Research + +Erstellt unabhängige private Konnektivitätsdomänen für zwei Geschäftsbereiche derselben Organisation. Jeder Bereich hat einen eigenen Eigentümer, Adressplan, ein Connectivity-Projekt, eine Network Area und eine Workload-Landing-Zone. + +![Finance-und-Research-Topologie](diagrams/hub-and-spoke-finance-research.svg) + +Konfiguration: [`hub-and-spoke-finance-research.tfvars`](../src/config/hub-and-spoke-finance-research.tfvars) + +### Multi-Area + +Trennt regulierte und gemeinsam genutzte Workloads in unterschiedliche Network Areas und DNS-Zonen. Zwischen den beiden privaten Domänen gibt es kein implizites Routing. + +![Multi-Area-Topologie](diagrams/hub-and-spoke-multi-area.svg) + +Konfiguration: [`hub-and-spoke-multi-area.tfvars`](../src/config/hub-and-spoke-multi-area.tfvars) + +### Multi-Region + +Erstellt unabhängige regionale Hubs in `eu01` und `eu02`, jeweils mit eigener Network Area, Workload-Landing-Zone und Platform-Kubernetes-Cluster. Regionsübergreifende Konnektivität ist bewusst nicht implizit. + +![Multi-Region-Topologie](diagrams/hub-and-spoke-multi-region.svg) + +Konfiguration: [`hub-and-spoke-multi-region.tfvars`](../src/config/hub-and-spoke-multi-region.tfvars) + +### Prod / Nonprod + Firewalls + +Trennt Produktion und Nichtproduktion in unabhängige Network Areas mit dedizierten OPNsense-Firewalls. Entwicklung und Test teilen die Nichtproduktionsdomäne, bleiben aber separate Landing Zones. + +![Produktions- und Nichtproduktionstopologie mit Firewalls](diagrams/hub-and-spoke-prod-nonprod-firewall.svg) + +Konfiguration: [`hub-and-spoke-prod-nonprod-firewall.tfvars`](../src/config/hub-and-spoke-prod-nonprod-firewall.tfvars) + +### Tenant Isolation + +Erstellt drei private Mandantendomänen innerhalb einer Organisation. Jeder Mandant erhält eine dedizierte Network Area, einen Adressplan, eine Workload-Landing-Zone und einen Eigentümer ohne privates Routing zu den anderen Mandanten. + +![Topologie mit drei isolierten Mandanten](diagrams/hub-and-spoke-tenant-isolation.svg) + +Konfiguration: [`hub-and-spoke-tenant-isolation.tfvars`](../src/config/hub-and-spoke-tenant-isolation.tfvars) + + +## Netzwerktopologie + +Die acht Bereitstellungsvarianten bauen auf drei grundlegenden Netzwerkmodi auf. Diese unterscheiden sich darin, was das Connectivity-Modul bereitstellt und wie Landing-Zone-Verkehr geroutet wird. + +### Standalone + +Kein Connectivity-Modul. Jede Landing Zone hat ein unabhängiges Netzwerk mit direktem Internetzugang. Kein gemeinsamer IP-Adressraum, keine private Ost-West-Konnektivität, keine DNS-Föderation. + +``` +[LZ Project A]──internet +[LZ Project B]──internet +``` + +### Hub-Spoke + +Das Connectivity-Modul stellt eine Network Area und eine WAN-Routingtabelle bereit. Alle Corporate Landing Zones treten der Network Area bei und können sich über private IPs erreichen. Die Standardroute ist die WAN-Routingtabelle (Internet-Egress ohne Inspektion). + +``` +[LZ Corporate A] ──┐ +[LZ Corporate B] ──┤── Network Area (10.0.0.0/16) ──── internet (WAN table) +[LZ Corporate C] ──┘ +[LZ Public D] ──── standalone ──── internet +``` + +### Hub-Spoke + Firewall + +Erweitert Hub-Spoke: Eine Firewall-VM befindet sich im Connectivity-Projekt. Jede Corporate Landing Zone leitet den gesamten Verkehr (`0.0.0.0/0`) über die LAN-IP der Firewall. Die WAN-Schnittstelle der Firewall besitzt eine statische öffentliche IP für eine konsistente Egress-Identität. + +``` +[LZ Corporate A] ──┐ routing: 0.0.0.0/0 → 10.0.0.4 (firewall LAN) +[LZ Corporate B] ──┤── Network Area (10.0.0.0/16) ──→ [Firewall VM] +[LZ Corporate C] ──┘ vtnet1 (LAN) 10.0.0.4 + vtnet0 (WAN) ──→ internet + (static public IP) +[LZ Public D] ──── standalone ──── internet +``` + +Verkehrsfluss für eine Corporate Landing Zone (Firewall-Variante): + +1. Eine VM in der LZ sendet ein Paket an ein beliebiges Ziel. +2. Der Routingtabelleneintrag `0.0.0.0/0 → 10.0.0.4` leitet es an die LAN-Schnittstelle der Firewall (`vtnet1`) weiter. +3. Die Firewall prüft das Paket und führt NAT über `vtnet0` (WAN) unter Verwendung der statischen öffentlichen IP aus. +4. Antwortverkehr erreicht die öffentliche IP; die Firewall übersetzt zurück und liefert an die ursprüngliche VM. + +Ost-West-Verkehr zwischen Corporate LZs bleibt innerhalb der Network Area und kann durch Firewallrichtlinien erlaubt oder verboten werden. + + +## Site-to-Site-VPN (optional) + +Jede Hub-Spoke-Variante kann ein IPsec-VPN im Connectivity-Projekt terminieren und so die Network Area mit lokalen Systemen oder einer anderen Cloud verbinden. Aktivieren Sie es über den Block `connectivity.vpn` – siehe das auskommentierte Beispiel in `src/config/hub-and-spoke.tfvars`. + +Das Gateway ist hochverfügbar: Es betreibt zwei Tunnel in separaten Availability Zones mit jeweils eigener öffentlicher IP. Da beide Seiten die Adresse der anderen benötigen, erfolgt die Einführung in zwei Applies: Provisionieren Sie das Gateway mit `connections = {}`, lesen Sie `tofu output connectivity_vpn_public_ips`, konfigurieren Sie den entfernten Peer und ergänzen Sie dann die Verbindung. + +Pre-Shared Keys bleiben außerhalb des Konfigurationsobjekts in der separaten Variablen `vpn_pre_shared_keys`, damit die Tunneltopologie weiterhin commitbar ist: + +```bash +export TF_VAR_vpn_pre_shared_keys='{"onprem"={"tunnel1"="<20+ chars>","tunnel2"="<20+ chars>"}}' +``` + +Routen zu entfernten Präfixen werden automatisch über die Network Area verteilt, sodass jede Corporate Landing Zone den entfernten Standort ohne Konfiguration pro Spoke erreicht. + + +### Welcher Verkehr durch die Firewall fließt + +In der Firewall-Variante laufen zwei der vier Verkehrsrichtungen sauber durch die Appliance. Keine VPN-Richtung lässt sich mit dem verwalteten Gateway filtern: Eine wird beim Versuch unterbrochen, die andere lässt sich überhaupt nicht umleiten. + +| Richtung | Durch die Firewall? | Mechanismus | +|---|---|---| +| LZ → Internet | Ja, standardmäßig | Die Standardroute der Landing-Zone-Routingtabelle zeigt auf die LAN-Adresse der Firewall. Benötigt zusätzlich einen `outbound_nat`-Eintrag; andernfalls erreicht Verkehr die Appliance und endet dort. | +| LZ → LZ | Ja, standardmäßig | `system_routes = false` unterdrückt Projekt-zu-Projekt-Routen, sodass Spoke-zu-Spoke auf die Standardroute fällt. Benötigt eine statische Route zurück in die Network Area; andernfalls verlässt der Verkehr die Appliance über WAN, und Egress-NAT schreibt die Quelladresse um. | +| LZ → on-premises (VPN) | **Nein** | Das VPN-Präfix hat Vorrang vor `0.0.0.0/0` und umgeht daher die Appliance. | +| on-premises → LZ (VPN) | **Nein** | Direkte Lieferung an den Spoke über die von STACKIT verwaltete Routingtabelle. Nicht umleitbar. | + +Eingehender VPN-Verkehr umgeht die Appliance, weil `static_routes` einer VPN-Verbindung als *dynamische* Routen über die Network Area verteilt werden und ein entferntes Präfix immer spezifischer als `0.0.0.0/0` ist. Das VPN-Gateway selbst leitet über eine von STACKIT verwaltete Routingtabelle weiter, die weder geändert noch neu zugewiesen werden kann. + +> [!WARNING] +> `dynamic_routes = false` behebt die ausgehende Richtung nicht, sondern unterbricht sie. Ausgehender Verkehr läuft dann durch die Firewall, während eingehender sie weiterhin umgeht; der zustandsbehaftete Filter verwirft den einseitigen Verkehr, den er sieht. + +Wenn VPN-Verkehr geprüft werden muss, terminieren Sie den Tunnel auf der OPNsense-Appliance selbst statt auf dem verwalteten Gateway. Sie ist bereits die Standardroute jeder Corporate Landing Zone, sodass beide Richtungen symmetrisch bleiben. Der Preis dafür ist der Verlust der aktiven/aktiven HA des verwalteten Gateways. + + + +## Ressourcenbenennung + +Alle Ressourcen folgen einer einheitlichen, durch `company_code` gesteuerten Konvention: + +``` +--- +``` + +| Beispielname | Bedeutung | +|---|---| +| `exc-pltfm-mgmt-prod` | Management-Projekt | +| `exc-pltfm-hub-prod` | Connectivity-(Hub-)Projekt | +| `exc-pltfm-devops-prod` | DevOps-Projekt | +| `exc-lz-data-prod` | Application Landing Zone für Workload `data` in `prod` | +| `exc-sbx-*` | Sandbox-Projekte | + +`exc` ist der `company_code` aus der Beispielkonfiguration. Ersetzen Sie ihn durch das Kürzel Ihrer Organisation. diff --git a/docs/architecture.md b/docs/architecture.md index 2bcb140..206b7bb 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,5 +1,7 @@ # Architecture +[English](architecture.md) | [Deutsch](architecture.de.md) + This repository is a production-ready OpenTofu/Terraform framework for deploying a STACKIT Landing Zone. It provisions the complete cloud foundation, covering governance hierarchy, identity and access management, shared networking, optional firewall, DNS, secrets management, observability, and repeatable per-workload project templates. Everything is composed from six modules under `src/modules/` and wired together in `src/main.tf`. A single `terraform apply` with one of the complete reference configurations in `src/config/` stands up the full platform. diff --git a/docs/diagrams/README.de.md b/docs/diagrams/README.de.md new file mode 100644 index 0000000..c153387 --- /dev/null +++ b/docs/diagrams/README.de.md @@ -0,0 +1,25 @@ + +# Architekturdiagramme + +[English](README.md) | [Deutsch](README.de.md) + + +## Topologiediagramme für Kunden + +Die kundenseitigen Topologiediagramme werden direkt als SVG-Dateien gepflegt. Sie zeigen bewusst die prägenden Netzwerkgrenzen, Projekte und Verkehrswege jeder vollständigen Konfiguration statt jeder einzelnen Terraform-Ressource. + +- `standalone.svg` +- `hub-and-spoke.svg` +- `hub-and-spoke-firewall.svg` +- `hub-and-spoke-finance-research.svg` +- `hub-and-spoke-multi-area.svg` +- `hub-and-spoke-multi-region.svg` +- `hub-and-spoke-prod-nonprod-firewall.svg` +- `hub-and-spoke-tenant-isolation.svg` + +Jeder Dateiname entspricht – abgesehen von der Bilddateiendung – seiner Quelldatei in `src/config/`. Halten Sie diese Diagramme stabil und prüfen Sie visuelle Änderungen zusammen mit der zugehörigen Konfiguration. + + +## Bisheriger Generator + +`scripts/generate_example_architecture.py` bleibt als manuelle Entwicklungshilfe verfügbar. Er wird weder von GitHub Actions noch von der Aufgabenverwaltung des Repositorys oder einer anderen automatisierten Pipeline aufgerufen. Seine Mermaid-Ausgabe ist vorübergehend und gehört nicht zur gepflegten Dokumentation. diff --git a/docs/diagrams/README.md b/docs/diagrams/README.md index f9ba0cf..80c516d 100644 --- a/docs/diagrams/README.md +++ b/docs/diagrams/README.md @@ -1,5 +1,7 @@ # Architecture Diagrams +[English](README.md) | [Deutsch](README.de.md) + ## Customer topology diagrams The customer-facing topology diagrams are maintained directly as SVG files. They intentionally show the defining network boundaries, projects, and traffic paths of each complete configuration rather than every Terraform resource. diff --git a/docs/getting-started.de.md b/docs/getting-started.de.md new file mode 100644 index 0000000..14b04f3 --- /dev/null +++ b/docs/getting-started.de.md @@ -0,0 +1,389 @@ + +# Erste Schritte + +[English](getting-started.md) | [Deutsch](getting-started.de.md) + +Diese Anleitung führt Sie durch die Bereitstellung der STACKIT Landing Zone von Grund auf. + +> [!NOTE] +> Die Module in diesem Terraform-Repository sind nicht zur direkten Nutzung vorgesehen. Klonen Sie das Repository und passen Sie die Module an Ihre konkreten Anforderungen an. Es gibt keine Garantien für Migrationspfade oder dafür, dass die Module unverändert bleiben. + + +## Voraussetzungen + +- Eine **STACKIT-Organisation**, in der Ihr Benutzerkonto registriert ist +- **Owner-Berechtigungen** auf der STACKIT-Organisation +- Installierte **STACKIT CLI** ([Installationsanleitung](https://github.com/stackitcloud/stackit-cli/blob/main/INSTALLATION.md)) +- Installiertes **OpenTofu** (>= 1.10) oder **Terraform** (>= 1.10) +- **`bash`, `curl` und `jq`** auf dem Rechner, auf dem OpenTofu läuft, nur für die Variante Hub-Spoke + Firewall. API-Schlüssel-Bootstrap und HA-Konfiguration sind Shell-Provisioner; die HA-Skripte verwenden `jq` + +> [!NOTE] +> Diese Anleitung verwendet durchgehend `tofu`-Befehle. Wenn Sie Terraform verwenden, ersetzen Sie `tofu` durch `terraform` – alle Befehle funktionieren identisch. + + +## Bereitstellungsvarianten + +Unter `src/config/` stehen acht vollständige, einsatzbereite Konfigurationen bereit: + +| Variante | Konfigurationsdatei | Beschreibung | +| --- | --- | --- | +| **Standalone** | `standalone.tfvars` | Nur Governance, Management, DevOps und öffentliche Landing Zones. Keine Network Area oder Firewall. | +| **Hub-Spoke** | `hub-and-spoke.tfvars` | Ergänzt einen Connectivity-Hub mit Network Area und DNS-Zonen. Corporate Landing Zones verbinden sich über die Network Area. | +| **Hub-Spoke + Firewall** | `hub-and-spoke-firewall.tfvars` | Vollständige Hub-Spoke-Topologie mit einer OPNsense-Firewall-Appliance an der WAN-/LAN-Grenze. | +| **Regulated and Shared** | `hub-and-spoke-multi-area.tfvars` | Trennt regulierte Workloads von gemeinsam genutzten Workloads mit unterschiedlichen Sicherheitsanforderungen. | +| **Finance and Research** | `hub-and-spoke-finance-research.tfvars` | Isoliert Geschäftsbereiche mit unterschiedlichen Eigentümern, Adressplänen und Konnektivitätsanforderungen. | +| **Prod/Nonprod + Firewalls** | `hub-and-spoke-prod-nonprod-firewall.tfvars` | Dedizierte SNAs und OPNsense-Appliances für Produktion und Nichtproduktion. | +| **Tenant Isolation** | `hub-and-spoke-tenant-isolation.tfvars` | Trennt drei Mandanten, die eine gemeinsame unternehmensweite STACKIT-Organisation nutzen. | +| **Multi-Region** | `hub-and-spoke-multi-region.tfvars` | Stellt unabhängige Connectivity-Hubs, Landing Zones und Platform-Kubernetes-Cluster in `eu01` und `eu02` bereit. | + +Wählen Sie die Variante, die Ihren Anforderungen entspricht, und passen Sie die entsprechende `.tfvars`-Datei vor der Bereitstellung an (Schritt 7). Aktualisieren Sie mindestens `owner_email`, `organization_id`, `company_name` und `company_code`. + +Die Multi-SNA-Szenariodateien sind vollständige Konfigurationen. Ersetzen Sie vor dem Anwenden die Platzhalterwerte für `owner_email`, `company_name`, `company_code` und `organization_id`. Die Area-Schlüssel sind nur Beispiele; wählen Sie stabile Schlüssel passend zu Ihrer Grenze. Entscheidungshilfen und Einschränkungen stehen unter [Mehrere Network Areas](architecture.de.md#multiple-network-areas). + +Das Szenario Prod/Nonprod + Firewalls erstellt eine Appliance pro SNA. Seine OPNsense-Richtlinien müssen derzeit nach dem Bootstrap für jede Appliance konfiguriert werden; der einzelne `firewall_config`-Block wird nicht automatisch verteilt. + +Die Firewall-Variante benötigt einen zusätzlichen Schritt: Die Appliance startet unkonfiguriert, ihre Richtlinie wird in einem zweiten Apply aus dem anfangs auskommentierten `firewall_config`-Block derselben `.tfvars`-Datei übertragen. Bis dahin filtert sie nichts, und ihre Web-GUI ist aus dem Internet erreichbar – siehe [OPNsense-Firewall konfigurieren](#configure-opnsense-firewall). Standardmäßig wird eine einzelne Appliance bereitgestellt, die als Standardroute jeder Corporate Landing Zone ein Single Point of Failure ist. Der auskommentierte Block `connectivity.firewall.ha` macht daraus ein aktives/passives CARP-Paar – siehe [Firewall hochverfügbar machen](#make-the-firewall-highly-available). + +Beide Hub-Spoke-Varianten können zusätzlich ein Site-to-Site-IPsec-VPN im Hub terminieren. Es ist standardmäßig deaktiviert – siehe den auskommentierten Block `connectivity.vpn` in der `.tfvars`-Datei und [Site-to-Site-VPN](architecture.de.md#site-to-site-vpn-optional). Lesen Sie bei Verwendung der Firewall-Variante zuerst, [welchen Verkehr die Firewall tatsächlich sieht](architecture.de.md#what-goes-through-the-firewall), bevor Sie sich bei der VPN-Inspektion auf sie verlassen. + +> [!NOTE] +> Dieser Ansatz mit einem einzelnen Root-Modul eignet sich gut für kleinere Umgebungen. Bei größerem Umfang – typischerweise über 10 Landing Zones – können STACKIT-API-Ratenlimits bei Applies sowie langsamere Plan-/Refresh-Zyklen durch eine wachsende State-Datei auftreten. Werkzeuge wie [Terragrunt](https://terragrunt.gruntwork.io/), [Terramate](https://terramate.io/) oder [Spacelift](https://spacelift.io/) können helfen, indem sie Landing Zones in isolierte State-Dateien aufteilen und Root-Modulaufrufe mit geeigneter Parallelitätssteuerung orchestrieren. Wenden Sie sich bei einer größeren Unternehmensbereitstellung an [STACKIT](https://stackit.de) oder einen Partner mit verifizierter Landing-Zone-Lösung im [STACKIT Marketplace](https://marketplace.stackit.cloud/de/catalog?marketplaceFilters=industries:Service%20%26%20IT%20Provider,deliveryMethod:PROFESSIONAL_SERVICE,categories:DevOps). + +--- + + +## Schrittweise Bereitstellung + + +### 1. Repository klonen + +```bash +git clone https://github.com/stackitcloud/stackit-landing-zone.git +cd stackit-landing-zone/src +``` + + +### 2. OPNsense-Firewall-Image herunterladen (nur Hub-Spoke + Firewall) + +Wenn Sie die Variante Hub-Spoke + Firewall bereitstellen, laden Sie das OPNsense-Image in das Verzeichnis `src/` herunter: + +```bash +curl -o firewall-image.qcow2 https://opnsense.object.storage.eu01.onstackit.cloud/opnsense-26.1-amd64-21-05-2026.qcow2 +``` + + +### 3. Bei STACKIT authentifizieren + +Melden Sie sich interaktiv über den Browser an: + +```bash +stackit auth login +``` + + +### 4. Vorübergehendes Bootstrap-Projekt erstellen + +Ein kurzlebiges Projekt wird benötigt, um das erste Dienstkonto für die Terraform-/OpenTofu-Authentifizierung zu erstellen: + +```bash +# get the organization id +stackit organization list + +# create the project +stackit project create --name tmp-bootstrap --parent-id +``` + +Notieren Sie die `project_id` aus der Ausgabe. + + +### 5. Bootstrap-Dienstkonto erstellen + +```bash +stackit service-account create --name bootstrap-sa --project-id + +# Grant the service account owner permissions at the organization level so it can provision all resources: +stackit organization member add --role organization.owner --organization-id +``` + + +### 6. Dienstkonto-Zugangsdaten konfigurieren + +Erstellen Sie einen Dienstkontoschlüssel und konfigurieren Sie ihn für den STACKIT-Terraform-Provider: + +```bash +mkdir -p ~/.stackit +stackit service-account key create --email --project-id -y --verbosity error > ~/.stackit/credentials.json + +export STACKIT_SERVICE_ACCOUNT_KEY_PATH=/home//.stackit/credentials.json +``` + +> [!IMPORTANT] +> `STACKIT_SERVICE_ACCOUNT_KEY_PATH` muss über Terminalsitzungen hinweg erhalten bleiben. + +> [!NOTE] +> `~` funktioniert nicht als Referenz auf das Home-Verzeichnis. Bei Verwendung von mise können Sie den Export von `STACKIT_SERVICE_ACCOUNT_KEY_PATH` weglassen. + +Alle unterstützten Authentifizierungsmethoden finden Sie in der [Dokumentation des STACKIT-Terraform-Providers](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs). + + +### 7. Variablen konfigurieren + +Kopieren und bearbeiten Sie die `.tfvars`-Datei passend zu Ihrem Bereitstellungsszenario: + +```bash +cp config/standalone.tfvars terraform.auto.tfvars +``` + +Passen Sie die Werte an Ihre Organisation an. Erforderliche Variablen: + +| Variable | Beschreibung | +| --- | --- | +| `owner_email` | In STACKIT registrierte E-Mail-Adresse des technischen Eigentümers | +| `company_name` | Unternehmensname für die Ordnerbenennung | +| `company_code` | Kurzes Präfix für Ressourcennamen (z. B. `exc`) | +| `organization_id` | ID des Root-Organisationscontainers | + + +### 8. OpenTofu/Terraform initialisieren + +```bash +tofu init +``` + + +### 9. Landing Zone bereitstellen + +Wenn Sie den Block `connectivity.vpn` aktiviert haben, exportieren Sie zuerst die Pre-Shared Keys als Umgebungsvariable. Sie werden bewusst nicht in den `tfvars` gespeichert: + +```bash +export TF_VAR_vpn_pre_shared_keys='{"onprem"={"tunnel1"="<20+ chars>","tunnel2"="<20+ chars>"}}' +``` + +> [!NOTE] +> Wenn Sie die mitgelieferte OPNsense-Firewall bereitstellen, folgen Sie anschließend unbedingt [OPNsense-Firewall konfigurieren](#configure-opnsense-firewall). Bis dahin filtert die Appliance nichts und ihre Web-GUI antwortet auf der öffentlichen IP. + +Führen Sie in jedem Fall OpenTofu aus, um die Infrastruktur bereitzustellen: + +```bash +tofu apply +``` + +Prüfen Sie den Plan und bestätigen Sie mit `yes`. + +> [!NOTE] +> Falls Sie Ihre tfvars-Datei nicht mit dem Suffix `.auto.tfvars` kopiert haben, geben Sie sie ausdrücklich an: `tofu apply -var-file ./config/.tfvars` + +--- + + +## State in das erstellte Backend migrieren + +Nach dem ersten erfolgreichen Apply hat das Management-Modul einen S3-Bucket für Remote-State und ein Dienstkonto für die laufende Automatisierung erstellt. Migrieren Sie zu diesem Backend, um Zusammenarbeit im Team zu ermöglichen. + + +### 10. S3-Backend aktivieren + +Entfernen Sie die Auskommentierung des Blocks `backend "s3"` in `backend.tf` und passen Sie den Namen `bucket` an die Terraform-Ausgabe `management_bucket_name_tfstate` an: + +```hcl +terraform { + backend "s3" { + bucket = "" + endpoints = { + s3 = "https://object.storage.eu01.onstackit.cloud" + } + key = "terraform.tfstate" + region = "eu01" + skip_credentials_validation = true + skip_region_validation = true + skip_requesting_account_id = true + skip_s3_checksum = true + } +} +``` + +Navigieren Sie im STACKIT Portal zum Management-Projekt → Secrets Manager → Secrets. Öffnen Sie das Secret mit dem Präfix `object_storage_credentials_` und kopieren Sie die Werte `ACCESS_KEY` und `SECRET_ACCESS_KEY`. + +Setzen Sie die S3-Backend-Zugangsdaten: + +```bash +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +``` + +> [!IMPORTANT] +> Diese Werte müssen über Terminalsitzungen hinweg erhalten bleiben. + + +### 11. State migrieren + +```bash +tofu init -migrate-state +``` + +Bestätigen Sie die Migration, wenn Sie dazu aufgefordert werden. + + +### 12. Zum Management-Dienstkonto wechseln + +Ersetzen Sie die Bootstrap-Zugangsdaten durch das vom Management-Modul erstellte Dienstkonto. + +Navigieren Sie im STACKIT Portal zum Management-Projekt → Secrets Manager → Secrets. Öffnen Sie das Secret mit dem Präfix `service_account_key_`, kopieren Sie seinen Wert und speichern Sie ihn unter `/home//.stackit/credentials.json`, wobei die Bootstrap-Zugangsdaten überschrieben werden. + +> [!NOTE] +> Verwenden Sie den absoluten Pfad – `~` funktioniert hier nicht. + + +### 13. Migration prüfen + +Führen Sie einen Plan aus, um zu bestätigen, dass keine Änderungen erkannt werden: + +```bash +tofu plan +``` + +Die Ausgabe sollte `No changes. Your infrastructure matches the configuration.` zeigen. + +> [!NOTE] +> Falls Sie Ihre tfvars-Datei nicht mit dem Suffix `.auto.tfvars` kopiert haben, geben Sie sie ausdrücklich an: `tofu plan -var-file ./config/.tfvars` + +--- + + +## Aufräumen + + +### 14. Bootstrap-Projekt löschen + +Das vorübergehende Bootstrap-Projekt mit dem Dienstkonto wird nicht mehr benötigt: + +```bash +stackit project delete --project-id +``` + +> [!NOTE] +> Resource-Manager-Ordner können erst 7 Tage nach dem Entfernen des letzten enthaltenen Projekts gelöscht werden. Ein `tofu apply` mit anschließendem `tofu destroy` schlägt daher fehl – Destroy meldet beim Löschen der Ordner einen Fehler, solange Projekte noch innerhalb ihrer Aufbewahrungsfrist liegen. + +--- + + +## Nach der Bereitstellung (optional) + + +### OPNsense-Firewall konfigurieren + +Schritt 9 startet die Appliance, lässt sie aber unkonfiguriert: Sie filtert nichts, und ihre Web-GUI antwortet auf der öffentlichen IP. Das Übertragen einer Richtlinie ist ein **zweites Apply**, da der API-Schlüssel aus der Appliance-Anmeldung abgeleitet wird und eine Provider-Konfiguration aufgelöst sein muss, bevor eine Ressource geplant wird. Ein während eines Apply erstellter Schlüssel kann den Provider daher nicht im selben Lauf konfigurieren. + +Was die Richtlinie bewirkt und welche Verkehrsrichtungen sie tatsächlich sehen kann, steht unter [Welcher Verkehr durch die Firewall fließt](architecture.de.md#what-goes-through-the-firewall). + +> [!NOTE] +> Die Richtlinie wird mit dem Provider [`browningluke/opnsense`](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs) übertragen. Er bildet das erweiterte Leseformat von OPNsense auf das Geschriebene zurück ab, sodass In-place-Updates und Drift-Erkennung funktionieren – der generische Provider `Mastercard/restapi` kann das nicht und macht Objekte faktisch nur einmal beschreibbar. Der Provider wird von der Community gepflegt und sein Autor rät vom Produktionseinsatz ab; berücksichtigen Sie dies, bevor Sie sich darauf verlassen. + +**1. Richtlinie aktivieren** + +Entfernen Sie die Auskommentierung des Blocks `firewall_config` in `config/hub-and-spoke-firewall.tfvars`. Er enthält Standardregeln: Internet-Egress mit NAT, Spoke-zu-Spoke auf HTTPS und ICMP beschränkt sowie die zwei Floating-Regeln, die die Web-GUI aus dem Internet nehmen. + +Zwei Einträge benötigen Ihre Werte: + +```hcl +# Public: OpenTofu runs outside the Network Area* — a workstation, or a CI runner on the public internet. This is the normal case for a first deployment, because nothing is inside the area yet. Traffic goes over the appliance's public address: + +endpoint = "https://" # get it from running "tofu output connectivity_firewall_public_ip" +fw_management = { + content = ["10.0.0.0/16", "/32"] # get it eg by running "curl -s https://ifconfig.me" or better use a fixed ip range +} + + +# Private: OpenTofu runs inside the Network Area* — a CI runner in a landing zone, a jumphost, or an established site-to-site VPN. Nothing to look up: the LAN address is the default, and your source address is already covered by `10.0.0.0/16`: + +# omit endpoint +fw_management = { + content = ["10.0.0.0/16"] +} +``` + +> [!WARNING] +> Das System, das OpenTofu ausführt, muss vor diesem Apply vom Alias `fw_management` abgedeckt sein. Andernfalls trennt derselbe Lauf, der die GUI schließt, seinen eigenen API-Zugriff; die Wiederherstellung erfolgt über die serielle Konsole (`stackit server console --project-id `). +> +> Eine dynamische Privat- oder Büroadresse ändert sich irgendwann und sperrt einen späteren Lauf aus. + +**2. API-Schlüssel bootstrappen, dann Richtlinie übertragen** + +```bash +tofu apply -var firewall_bootstrap=true && tofu apply -var firewall_bootstrap=true +``` + +Das erste `tofu apply` leitet den API-Schlüssel ab (und wartet dabei auf den Abschluss des mehrminütigen Appliance-Starts) und speichert ihn in `src/.firewall-api-credentials.json`, das von Git ignoriert wird. Das zweite `tofu apply` speichert ihn im Management-Secrets-Manager und überträgt Aliase, statische Routen, Regeln und NAT. + +Zwei Läufe sind unvermeidbar: Der Provider benötigt den Schlüssel zur Plan-Zeit, und ein während eines Apply erstellter Wert kann keinen Provider im selben Lauf konfigurieren. + +Die verwendete Appliance-Anmeldung stammt aus `firewall_admin_password`, standardmäßig dem im STACKIT-OPNsense-Image hinterlegten `root`-Passwort. Für eine neue Bereitstellung muss deshalb nichts exportiert werden. + +> [!IMPORTANT] +> Ändern Sie das Passwort auf der Appliance (**System → Access → Users**). Das Passwort wird nur zur Ableitung des API-Schlüssels verwendet. Sobald der Schlüssel existiert, wird es überhaupt nicht mehr gelesen. + +**3. Bootstrap-Variable weglassen und Cache-Datei löschen** + +Ab jetzt ist jedes Apply ein einfaches `tofu apply` ohne Variablen: + +```bash +rm src/.firewall-api-credentials.json +tofu apply +``` + +**Schlüssel rotieren** + +Ein erneuter Bootstrap widerruft jeden vorhandenen API-Schlüssel auf der Appliance und erstellt einen neuen. Dadurch wird die Kopie im Secrets Manager sofort ungültig. Der Folgeschritt ist deshalb nicht optional: Erhöhen Sie `firewall_api_secret_version` um eins, damit der neue Schlüssel geschrieben wird. Ohne diese Erhöhung schlägt der Lauf mit 401 fehl, statt unbemerkt einen unbrauchbaren Schlüssel zu behalten. + +```bash +rm -f src/.firewall-api-credentials.json +tofu apply -var firewall_bootstrap=true # mints the new key +# bump firewall_api_secret_version in your tfvars, then +tofu apply -var firewall_bootstrap=true # writes it to the Secrets Manager +rm src/.firewall-api-credentials.json +``` + + +### Firewall hochverfügbar machen + +Eine einzelne Appliance ist die Standardroute jeder Corporate Landing Zone; ihr Ausfall nimmt daher die Plattform offline. Entfernen Sie die Auskommentierung des Blocks `ha` in `connectivity.firewall`, um eine zweite Appliance in einer anderen Availability Zone als aktives/passives CARP-Paar bereitzustellen: + +```hcl +ha = { + backup_zone = "eu01-1" # must differ from firewall.zone +} +``` + +`tofu apply` erledigt anschließend den Rest. Es stellt das Backup bereit, meldet sich auf beiden Appliances an und schreibt deren knotenspezifische CARP-Einstellungen (Backup zuerst, Primary zuletzt, damit der Primary die Wahl gewinnt). Außerdem ergänzt es den Alias `fw_cluster` und die Regeln `allow-fw-carp` und `allow-fw-pfsync` in der Richtlinie – sie werden automatisch eingefügt, in den `.tfvars` ist nichts zu ergänzen. + +Zwei Folgen sollten Sie vor der Aktivierung kennen: + +- **Die Landing-Zone-Routen ändern sich.** `firewall_next_hop_ip` wird zur virtuellen CARP-IP (`.6` von `lan_network_range`) statt zur LAN-Adresse des Primary. Jede Corporate Landing Zone erhält deshalb im selben Apply eine umgeschriebene Standardroute. Rechnen Sie während der Routenaktualisierung mit einer kurzen Unterbrechung. +- **Die öffentliche IP führt kein Failover durch.** STACKIT bindet eine öffentliche IP 1:1 an eine NIC. Egress vom Backup wird auf dessen eigene Adresse übersetzt. Eingehende Portweiterleitungen bleiben auf dem Primary, bis Sie DNS auf `tofu output connectivity_firewall_backup_public_ip` umstellen. Langlebige ausgehende Verbindungen brechen für die Dauer eines Ausfalls ab; neue erholen sich innerhalb von Sekunden. + +Was genau umschaltet und was gemessen wurde, steht unter [Hochverfügbarkeit](architecture.de.md#high-availability-optional). + +> [!IMPORTANT] +> Die Backup-Appliance startet mit demselben Image-Standardpasswort wie der Primary, und ihre Web-GUI antwortet auf ihrer eigenen öffentlichen IP, bis die Richtlinie übertragen ist. Die obige Aussperrwarnung gilt für beide Knoten. + + +### Kubernetes: DNS-Automatisierung für Gateway-API-Ressourcen + +Native Unterstützung für `extensions.dns.gateway_api` ist seit v0.109.0 im STACKIT-Terraform-Provider verfügbar und standardmäßig aktiviert, sobald die SKE-DNS-Erweiterung mindestens eine Zone hat. Deaktivieren Sie sie ausdrücklich, wenn der Cluster keine Gateway-API-Ressourcen verwendet: + +```hcl +platform_kubernetes = { + my-cluster = { + dns = { + enabled = true + gateway_api = false + } + # ... + } +} +``` + +Mit dem Standard `gateway_api = true` konfiguriert die SKE-DNS-Erweiterung ExternalDNS automatisch für Gateway-API-Ressourcen (`Gateway`, `HTTPRoute`). Sie müssen DNS-Einträge oder LoadBalancer-Endpunkte nicht mehr manuell verwalten beziehungsweise ermitteln. + +> [!NOTE] +> Die SKE-DNS-Erweiterung installiert keine Gateway-API-CRDs. Die optionale Envoy-Gateway-Demo installiert sie automatisch. Installieren Sie für andere Gateway-API-Implementierungen kompatible CRDs separat. Sobald die CRDs verfügbar sind, wird ExternalDNS beim nächsten Cluster-Reconcile konfiguriert; ein zusätzliches OpenTofu-Apply ist nicht erforderlich. diff --git a/docs/getting-started.md b/docs/getting-started.md index 89a1e21..e0b71de 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,5 +1,7 @@ # Getting Started +[English](getting-started.md) | [Deutsch](getting-started.de.md) + This guide walks you through deploying the STACKIT Landing Zone from scratch. > [!NOTE] diff --git a/docs/terraform-style.de.md b/docs/terraform-style.de.md new file mode 100644 index 0000000..331ee7a --- /dev/null +++ b/docs/terraform-style.de.md @@ -0,0 +1,226 @@ + +# Terraform-Stilleitfaden + +[English](terraform-style.md) | [Deutsch](terraform-style.de.md) + +Diese Datei definiert die Terraform-Stilkonventionen für dieses Repository auf Grundlage des [HashiCorp Terraform Style Guide](https://developer.hashicorp.com/terraform/language/style). Sämtlicher Terraform-Code in diesem Workspace MUSS diesen Regeln entsprechen. Setzen Sie bei der Prüfung oder Generierung von Terraform-Code jede der folgenden Regeln durch. + +--- + + +## Codeformatierung + +- Rücken Sie pro Verschachtelungsebene um **zwei Leerzeichen** ein. +- Richten Sie `=`-Zeichen aus, wenn mehrere einzeilige Argumente in aufeinanderfolgenden Zeilen derselben Verschachtelungsebene stehen: + ```hcl + ami = "abc123" + instance_type = "t2.micro" + ``` +- Platzieren Sie alle Argumente **oben** im Block und verschachtelte Blöcke **darunter**, getrennt durch eine Leerzeile. +- Trennen Sie logische Argumentgruppen innerhalb eines Blocks durch **Leerzeilen**. +- **Meta-Argumente zuerst**: Führen Sie Meta-Argumente (`count`, `for_each`) oben in einem Ressourcenblock auf, durch eine Leerzeile von anderen Argumenten getrennt. +- **Meta-Argumentblöcke zuletzt**: Platzieren Sie `lifecycle`- und `depends_on`-Blöcke unten, durch eine Leerzeile von anderen Blöcken getrennt. + ```hcl + resource "aws_instance" "example" { + # meta-argument first + count = 2 + + ami = "abc123" + instance_type = "t2.micro" + + network_interface { + # ... + } + + # meta-argument block last + lifecycle { + create_before_destroy = true + } + } + ``` +- Trennen Sie **Blöcke auf oberster Ebene** durch genau eine Leerzeile. +- Trennen Sie **verschachtelte Blöcke** durch Leerzeilen, außer bei der Gruppierung zusammengehöriger Blöcke desselben Typs. +- Führen Sie vor dem Commit `terraform fmt` aus. Verwenden Sie `-recursive`, um Unterverzeichnisse zu formatieren. + + +## Codevalidierung + +- Führen Sie vor dem Commit `terraform validate` aus, um Syntax und interne Konsistenz zu prüfen. + + +## Kommentare + +- Verwenden Sie `#` für **alle** Kommentare (einzeilig und mehrzeilig). Verwenden Sie NICHT `//` oder `/* */`. +- Schreiben Sie selbsterklärenden Code; fügen Sie Kommentare nur hinzu, wenn sie zur Erläuterung von Komplexität erforderlich sind. + + +## Ressourcenbenennung + +- Verwenden Sie für jeden Ressourcennamen ein **aussagekräftiges Substantiv**. +- Trennen Sie Wörter durch **Unterstriche** (`_`), nicht durch Bindestriche oder camelCase. +- Nehmen Sie den Ressourcentyp NICHT in den Ressourcennamen auf (die Adresse enthält ihn bereits). +- Setzen Sie sowohl Ressourcentyp als auch Namen in **doppelte Anführungszeichen**. + + **Schlecht:** + ```hcl + resource aws_instance webAPI-aws-instance {...} + ``` + **Gut:** + ```hcl + resource "aws_instance" "web_api" {...} + ``` + + +## Ressourcenreihenfolge + +- Definieren Sie **Datenquellen vor** den Ressourcen, die sie referenzieren, damit der Code „auf sich selbst aufbaut“. +- Ordnen Sie Parameter innerhalb eines Ressourcenblocks wie folgt: + 1. Meta-Argument `count` oder `for_each` + 2. Ressourcenspezifische Parameter, die keine Blöcke sind + 3. Ressourcenspezifische Blockparameter + 4. `lifecycle`-Block (falls erforderlich) + 5. `depends_on` (falls erforderlich) + + +## Variablen + +- Jede Variable MUSS `type` und `description` besitzen. +- Geben Sie für optionale Variablen einen `default` an. +- Setzen Sie `sensitive = true` für Passwörter, private Schlüssel und andere Geheimnisse. +- Verwenden Sie `validation`-Blöcke nur, wenn für Werte besonders einschränkende Anforderungen gelten. +- Ordnen Sie Variablenparameter wie folgt: + 1. `type` + 2. `description` + 3. `default` (optional) + 4. `sensitive` (optional) + 5. `validation`-Blöcke + + ```hcl + variable "db_disk_size" { + type = number + description = "Disk size for the API database" + default = 100 + } + + variable "db_password" { + type = string + description = "Database password" + sensitive = true + } + ``` + + +## Ausgaben + +- Jede Ausgabe MUSS eine `description` besitzen. +- Ordnen Sie Ausgabeparameter wie folgt: + 1. `description` + 2. `value` + 3. `sensitive` (optional) + + ```hcl + output "web_public_ip" { + description = "Public IP of the web instance" + value = aws_instance.web.public_ip + } + ``` + + +## Lokale Werte + +- Verwenden Sie lokale Werte **sparsam**; übermäßige Verwendung erschwert das Verständnis des Codes. +- Definieren Sie lokale Werte in einer Datei `locals.tf`, wenn sie in mehreren Dateien referenziert werden. +- Definieren Sie lokale Werte **oben** in einer Datei, wenn sie nur dort verwendet werden. +- Verwenden Sie aussagekräftige Substantive mit Unterstrichen für die Namen lokaler Werte. + + +## Provider-Konfiguration + +- Nehmen Sie immer eine **Standard-Provider-Konfiguration** (ohne `alias`) auf. +- Definieren Sie **alle Provider** in derselben Datei. +- Definieren Sie bei mehreren Instanzen eines Providers den **Standard zuerst**. +- Bei nicht standardmäßigen Providern muss der Parameter `alias` der **erste** Parameter im Block sein. + + +## Dynamische Ressourcenanzahl (`count` / `for_each`) + +- Verwenden Sie `count` und `for_each` **sparsam**; sie erhöhen die Komplexität. +- Verwenden Sie `count`, wenn Ressourcen nahezu identisch sind. +- Verwenden Sie `for_each`, wenn Argumente unterschiedliche, nicht aus einer Ganzzahl ableitbare Werte benötigen. +- Ein übliches Muster für bedingte Ressourcen: `count = var.condition ? 1 : 0`. +- Fügen Sie einen Kommentar hinzu, wenn die Wirkung eines Meta-Arguments nicht sofort ersichtlich ist. + + +## Konventionen für Dateinamen + +- `main.tf` — Ressourcen- und Datenquellenblöcke (oder bei wachsendem Code nach logischen Gruppen aufteilen). +- `variables.tf` — alle Variablenblöcke in **alphabetischer Reihenfolge**. +- `outputs.tf` — alle Ausgabeblöcke in **alphabetischer Reihenfolge**. +- `providers.tf` — alle `provider`-Blöcke und deren Konfiguration. +- `terraform.tf` — einzelner `terraform`-Block mit `required_version` und `required_providers`. +- `backend.tf` — Backend-Konfiguration. +- `locals.tf` — lokale Werte (wenn von mehreren Dateien verwendet). +- `override.tf` — Überschreibungsdefinitionen (sparsam verwenden, ursprüngliche Ressource kommentieren). +- Teilen Sie Ressourcen bei wachsendem Code in logisch benannte Dateien auf (z. B. `network.tf`, `storage.tf`, `compute.tf`). Es sollte sofort klar sein, wo eine Ressource zu finden ist. + + +## Versionsfestlegung + +- Legen Sie **Provider-Versionen** in `required_providers` fest. +- Legen Sie **Modulversionen** auf eine bestimmte Major- und Minor-Version fest. +- Setzen Sie im `terraform`-Block eine Mindestversion `required_version` für das Terraform-Programm. + ```hcl + terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "5.34.0" + } + } + required_version = ">= 1.7" + } + ``` +- Verwenden Sie für Registry-Module den Parameter `version` im `module`-Block. + + +## Modulstruktur + +- Gruppieren Sie logisch zusammengehörige Ressourcen in Modulen. +- Speichern Sie lokale (Child-)Module in `./modules/`. +- Befolgen Sie die [Standardmodulstruktur](https://developer.hashicorp.com/terraform/language/modules/develop/structure). +- Benennen Sie Modul-Repositories bei Veröffentlichung in einer Registry nach `terraform--`. + +## .gitignore + +Committen Sie NICHT: +- `terraform.tfstate` und `terraform.tfstate.*`-Sicherungsdateien. +- `.terraform.tfstate.lock.info`. +- Das Verzeichnis `.terraform/`. +- Gespeicherte Plandateien (aus `terraform plan -out`). +- `.tfvars`-Dateien mit sensiblen Informationen. + +Committen Sie immer: +- Den gesamten `.tf`-Code. +- Die Abhängigkeits-Lockdatei `.terraform.lock.hcl`. +- `.gitignore`. +- `README.md`. + + +## Geheimnisverwaltung + +- Speichern Sie niemals Geheimnisse im Klartext in Terraform-Dateien. +- Verwenden Sie providerspezifische Umgebungsvariablen für Zugangsdaten. +- Verwenden Sie nach Möglichkeit einen Secrets Manager (z. B. HashiCorp Vault). +- Markieren Sie sensible Variablen mit `sensitive = true`. + + +## Tests + +- Schreiben Sie Tests für Terraform-Module. +- Führen Sie Tests vor dem Merge in Pull Requests oder als CI/CD-Pipelineschritte aus. + + +## Linting + +- Verwenden Sie einen Linter wie [TFLint](https://github.com/terraform-linters/tflint), um Codierungsstandards durchzusetzen. +- Führen Sie vor jedem Commit `terraform fmt` und `terraform validate` aus. diff --git a/docs/terraform-style.md b/docs/terraform-style.md index 100a02f..2a53634 100644 --- a/docs/terraform-style.md +++ b/docs/terraform-style.md @@ -1,5 +1,7 @@ # Terraform Style Guide +[English](terraform-style.md) | [Deutsch](terraform-style.de.md) + This file defines the Terraform style conventions for this repository, based on the [HashiCorp Terraform Style Guide](https://developer.hashicorp.com/terraform/language/style). All Terraform code in this workspace MUST conform to these rules. When reviewing or generating Terraform code, enforce every rule below. --- diff --git a/docs/workflows.de.md b/docs/workflows.de.md new file mode 100644 index 0000000..6bb6c93 --- /dev/null +++ b/docs/workflows.de.md @@ -0,0 +1,155 @@ + +# GitHub-Actions-Workflows + +[English](workflows.md) | [Deutsch](workflows.de.md) + +Dies ist der Einstieg zum Auswählen und Starten einer Pipeline. Workflow-Namen +verlinken direkt auf ihre **Actions**-Seiten; **Quelltext**-Links zeigen die +ausführbare Definition. Die zehn aktuellen Repository-Workflows sind unten +aufgeführt. Historische Einträge und von GitHub verwaltete Workflows sind +[separat aufgeführt](#other-entries-in-the-actions-sidebar). + +**Ein Merge stellt den Configurator nicht bereit.** Configurator-Provisionierung +und Anwendungs-Releases erfolgen manuell und zielen derzeit auf Entwicklung, nicht +Produktion. Einen Workflow zu starten ist nicht dasselbe wie seinen geschützten +Bereitstellungsjob freizugeben. + + +## Welchen Workflow benötige ich? + +| Aufgabe | Workflow | +| --- | --- | +| Accelerator-Änderungen ohne Ressourcenbereitstellung prüfen | **Validate** | +| Änderungen an Configurator, Katalog, Datenbank, Browser und Operator-IaC prüfen | **Validate Configurator** | +| Assistant-Antworten gegen das echte Modell testen | **Assistant live regression** | +| Neue Configurator-Version einschließlich API/UI und Runner bereitstellen | **Configurator Release**, nicht Publish Release | +| Eigenen State-Speicher, verwaltete Dienste oder CF-Identitäten des Configurators ändern | **Configurator Bootstrap**, **Platform** oder **Runtime** | +| Echte Accelerator-Bereitstellung und Bereinigung ausführen | **Verify Deployment** | +| Accelerator-GitHub-Release nach echter Bereitstellungsprüfung veröffentlichen | **Publish Release** | +| Konfigurierte Maschinen-Flavors mit dem aktuellen STACKIT-Katalog vergleichen | **Validate STACKIT Flavors** | + + +## Aktuelle Repository-Workflows + +**Automatisch** beschreibt Repository-Ereignisse, keinen manuellen Klick. +**Wiederverwendbar** bedeutet, dass ein anderer Workflow ihn über `workflow_call` +aufrufen kann; dies ist keine separate UI-Freigabe. Alle zehn Definitionen bieten +`workflow_dispatch`, aber Berechtigungen, Branch-Beschränkungen, Operatorschalter +und Umgebungsschutz gelten weiterhin. + +| Workflow und Definition | Zweck | Automatischer Start | Manueller Start in Actions | Wiederverwendung / Auswirkungen | +| --- | --- | --- | --- | --- | +| [Validate](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/validate.yml) · [Quelltext](../.github/workflows/validate.yml) | Accelerator-Formatierung, Lint, Validierung und Konfigurationstests mit Mocks | Jeder PR; Push auf `main`. Aufwendige Jobs laufen nur bei relevanten nativen/Werkzeugänderungen; manueller Dispatch erzwingt ihre Ausführung. | **Run workflow**, keine Eingaben | Keine echte Infrastrukturprovisionierung | +| [Validate Configurator](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/validate-configurator.yml) · [Quelltext](../.github/workflows/validate-configurator.yml) | HCL-/Katalogaktualität, App-Lint/-Build/-Unit-Tests, PostgreSQL, Desktop-/Mobil-Browsertests und sechs Operator-IaC-Roots mit Mocks | PRs und Pushes auf `main`, die `landing-zone-configurator/**`, `src/**` oder die ausdrücklich aufgelisteten Workflow-Dateien betreffen | **Run workflow**, keine Eingaben; läuft manuell ohne Pfadfilter | Keine echte Infrastrukturprovisionierung oder Qualifikation mit echtem Modell | +| [Validate STACKIT Flavors](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/validate-stackit-flavors.yml) · [Quelltext](../.github/workflows/validate-stackit-flavors.yml) | Konfigurierte Flavors mit aktuellen STACKIT-SKUs vergleichen | Montags, **05:17 UTC**, auf dem Standardbranch (`17 5 * * 1`); GitHub kann geplante Läufe verzögern | **Run workflow**, keine Eingaben | Liest externen Katalog; keine Bereitstellung | +| [Assistant live regression](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/assistant-live.yml) · [Quelltext](../.github/workflows/assistant-live.yml) | Wiederholte faktische Fälle und durchgängiger Dialog über mehrere Themen mit echtem Model Serving | Nicht bei Push/PR; wird von einem neuen Configurator Release aufgerufen | **Run workflow** mit Thema und Wiederholungszahl | Wiederverwendbar durch **Configurator Release**. Inferenzkosten; kein Cloud-Plan/Apply. Verwendet `assistant-tests`. | +| [Verify Deployment](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/verify-deployment.yml) · [Quelltext](../.github/workflows/verify-deployment.yml) | Echter Accelerator-Plan, Apply und Bereinigung in der konfigurierten Testorganisation | Nicht bei Push/PR; wird von Publish Release aufgerufen | **Run workflow** mit Variablendateipfad | Wiederverwendbar durch **Publish Release**. **Erstellt und zerstört echte Cloud-Ressourcen** über `terraform-plan`. Behält das Governance-Ordnergerüst bei; fehlgeschlagene Bereinigung kann Ressourcen hinterlassen. | +| [Publish Release](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/publish-release.yml) · [Quelltext](../.github/workflows/publish-release.yml) | Accelerator prüfen, dann GitHub-Release/-Tag mit Quellarchiven und Herkunftsnachweis erstellen | Keiner; wird nicht durch Push eines Tags ausgelöst | **Run workflow** auf `main`, mit Version | Ruft zuerst **Verify Deployment** auf: **echte Cloud-Änderungen und Kosten**, danach GitHub-Release-Veröffentlichung. Stellt den Configurator nicht bereit. | +| [Configurator Bootstrap](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/configurator-bootstrap.yml) · [Quelltext](../.github/workflows/configurator-bootstrap.yml) | Workload-State-Bucket/-Zugriff (`bootstrap`) oder dessen Versionierung (`backend`) planen | Keiner | **Run workflow** auf `main`; Root wählen und optional Apply | Echter Backend-/Zugangsdatenzugriff für Plan; `apply=true` ermöglicht Cloud-Änderungen nach Freigabe der geschützten Umgebung | +| [Configurator Platform](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/configurator-platform.yml) · [Quelltext](../.github/workflows/configurator-platform.yml) | Gemeinsame Configurator-Dienste planen: CF-Organisation, Datenbank, Secrets Manager, Artefaktspeicher und Modell-Token | Keiner | **Run workflow** auf `main`; optional Apply; benötigt `LZC_PLATFORM_CI_ENABLED=true` | Echter Backend-/Zugangsdatenzugriff für Plan; optionaler freigegebener Cloud-Apply | +| [Configurator Runtime](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/configurator-runtime.yml) · [Quelltext](../.github/workflows/configurator-runtime.yml) | CF-Space/-Rollen und Datenbank-/Secrets-Laufzeitnutzer planen | Keiner | **Run workflow** auf `main`; optional Apply; benötigt `LZC_RUNTIME_CI_ENABLED=true` | Echter Backend-/Zugangsdatenzugriff für Plan; optionaler freigegebener Cloud-Apply. Veröffentlicht keinen Anwendungscode. | +| [Configurator Release](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/configurator-release.yml) · [Quelltext](../.github/workflows/configurator-release.yml) | API/UI und Runner gemeinsam qualifizieren, bauen und paketieren oder einen bestehenden qualifizierten Build übernehmen | Keiner; ein Merge startet ihn nicht | **Run workflow** auf `main`; Build-only, neues Release oder Promotion wählen; benötigt `LZC_RELEASE_CI_ENABLED=true` | Neue Builds rufen **Assistant live regression** auf und veröffentlichen einen geschützten Buildpack-Tag. Außer bei Build-only erfolgt nach Freigabe von `lzc-dev-release` die Entwicklungsbereitstellung einschließlich Migrationen und Laufzeitprüfungen. | + +Der genaue Configurator-Pfadfilter steht im verlinkten YAML. Ein übersprungener +reiner Accelerator-Job bei einem Configurator-PR ist beabsichtigt und keine +Bereitstellung. Machen Sie einen pfadgefilterten Job nicht global zur +Pflichtprüfung, ohne sicherzustellen, dass er für jeden relevanten PR ein Ergebnis meldet. + + +## Workflow in der GitHub-Oberfläche starten + +1. Öffnen Sie den [Actions-Tab](https://github.com/stackitcloud/stackit-landing-zone/actions) + des Repositorys oder den Workflow-Link in der Tabelle. +2. Wählen Sie den Workflow und anschließend **Run workflow**. Verwenden Sie **main** + für gewöhnliche betriebliche Läufe; eine Branch-Auswahl überschreibt keine Job-/Umgebungsschranken. +3. Füllen Sie die folgenden Eingaben aus und starten Sie den Lauf. Eine fehlende + Schaltfläche kann auf unzureichende Repository-Berechtigungen, deaktivierte + Actions oder eine Definition ohne `workflow_dispatch` auf dem Standardbranch + hinweisen. Alte Seitenleisteneinträge belegen nicht, dass ein Workflow noch existiert. +4. Verfolgen Sie den neuen Lauf. Bei einem geschützten Job muss ein berechtigter + Prüfer **Review deployments** verwenden, die Umgebung auswählen und freigeben. + PR-Merge-Freigabe/Admin-Bypass gibt eine Bereitstellung **nicht** frei. +5. Prüfen Sie den gesamten Lauf, nicht nur den erfolgreichen Dispatch oder den + ersten grünen Job. Ein angenommener Dispatch kann bei deaktivierter + Freigabeschranke trotzdem übersprungene Jobs enthalten. + + +### Manueller Start und Eingaben + +| Workflow | Eingaben und Voraussetzungen | +| --- | --- | +| Validate / Validate Configurator / Validate STACKIT Flavors | Keine Workflow-Eingaben | +| Assistant live regression | Standardmäßig `topic=all` oder eine Wissensthemen-ID; standardmäßig `repetitions=2`, unterstützter Bereich 1-3. Der durchgängige Dialog läuft auch bei themenbezogener Qualifikation. Die geschützte Umgebung `assistant-tests` erlaubt derzeit `main` und den ausdrücklich zugelassenen bisherigen Configurator-Feature-Branch. | +| Verify Deployment | Standardmäßig `var_file=config/hub-and-spoke-firewall.tfvars`; muss ein existierender relativer Pfad unter `src/` sein. Manuelle Läufe verwenden die ausgewählte Revision. Der wiederverwendbare Aufruf akzeptiert zusätzlich `ref`; das ist keine Dispatch-Eingabe. | +| Publish Release | `version` ist erforderlich. Wählen Sie `main`; andere Branches bestehen die Schranke des Prüfjobs nicht. | +| Configurator Bootstrap | Standardmäßig `root=bootstrap` oder `backend`; standardmäßig `apply=false`. Apply verwendet `lzc-dev-bootstrap-apply`. | +| Configurator Platform | `root=platform`; standardmäßig `apply=false`. Benötigt den obigen Plattform-Operatorschalter; Apply verwendet `lzc-dev-platform-apply`. | +| Configurator Runtime | `root=runtime`; standardmäßig `apply=false`. Benötigt den obigen Laufzeit-Operatorschalter; Apply verwendet `lzc-dev-runtime-apply`. | +| Configurator Release | Standardmäßig `build_only=false`; leere `release_run_id` bedeutet neue Qualifikation/neuer Build. Setzen Sie `build_only=true` für einen Build ohne CF-Bereitstellung; echte Modellaufrufe und Veröffentlichung des geschützten Tags erfolgen trotzdem. Um einen bestehenden qualifizierten Build zu übernehmen, lassen Sie Build-only deaktiviert und geben Sie dessen numerische Run-ID an; das aufbewahrte Artefakt/Tag muss weiterhin gültig sein. | + +Für die normale Configurator-Bereitstellung: Wählen Sie **Configurator Release**, +`main`, lassen Sie **build_only deaktiviert** und **release_run_id leer**, und geben +Sie bei Aufforderung `lzc-dev-release` frei. Dies stellt die Entwicklungsumgebung +bereit, keine neue Produktionsumgebung. Siehe das +[Release-Runbook](../landing-zone-configurator/deploy/cloud-foundry/README.de.md#manual-development-release-in-github) +für Promotion und Fehlerbehandlung. + +Bootstrap, Platform, Runtime und Release lehnen **Re-run jobs**-Versuche ab: +Starten Sie stattdessen einen **neuen Run workflow**. Infrastruktur-Apply verwendet +den geprüften verschlüsselten Plan aus demselben Lauf, keinen Plan eines älteren +Laufs. Ein neuer Promotion-Lauf kann einen bestehenden qualifizierten Release-Build +wiederverwenden; verwechseln Sie dies nicht mit der erneuten Ausführung der +ursprünglichen Bereitstellung. Fehlgeschlagene Qualifikationen bleiben Fehlschläge. + +Alle vier verändernden Configurator-Workflows teilen sich die Warteschlange +`configurator-lzc-dev-mutation` und brechen eine aktive Änderung nicht ab. +Assistant-Modellläufe haben eine eigene serialisierte Warteschlange. Starten Sie +niemals parallele lokale Cloud-Schreibvorgänge, um diese Schutzmaßnahmen zu umgehen. + + +### CLI-Entsprechung + +Aus einem mit GitHub CLI authentifizierten Terminal, beispielsweise zur Configurator-Prüfung: + +```sh +gh workflow run validate-configurator.yml \ + --repo stackitcloud/stackit-landing-zone --ref main +``` + +Verwenden Sie den Workflow-Dateinamen aus dem **Quelltext**-Link, um einen anderen +Workflow auszuwählen. Übergeben Sie Eingaben mit `-f name=value`; dies hat dieselben +Auswirkungen und Berechtigungsanforderungen wie die Oberfläche. Zum Beispiel wählt +`-f root=backend -f apply=false` einen reinen Plan-Lauf von Bootstrap. Geben Sie +keine Zugangsdaten, rohen Pläne oder State in Eingaben an. +`gh run list --repo stackitcloud/stackit-landing-zone --workflow validate-configurator.yml --limit 5` +zeigt die letzten Läufe; +`gh run watch RUN_ID --repo stackitcloud/stackit-landing-zone` +verfolgt einen Lauf. Ein erfolgreicher Dispatch allein bedeutet nicht, dass seine +Jobs erfolgreich waren. + + +## Weitere Einträge in der Actions-Seitenleiste + +GitHub bewahrt Workflow-Verläufe nach dem Entfernen von Dateien auf und zeigt +außerdem von GitHub selbst verwaltete Workflows. Diese sind keine zusätzlichen +aktuellen Repository-Definitionen. + +| Seitenleisteneintrag | Herkunft | Start / Vorgehen | +| --- | --- | --- | +| [Terraform Plan](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/terraform-plan.yml) | Historischer Workflow; sein YAML existiert auf `main` nicht mehr | Kein aktueller manueller Einstiegspunkt. Verwenden Sie das aktuelle Verzeichnis oben; ein alter Lauf oder GitHubs Workflow-Statuslabel stellt die gelöschte Definition nicht wieder her. | +| [Terraform Apply](https://github.com/stackitcloud/stackit-landing-zone/actions/workflows/terraform-apply.yml) | Historischer Workflow; sein YAML existiert auf `main` nicht mehr | Führen Sie historische Cloud-Schreibvorgänge nicht als Ersatz für einen autorisierten aktuellen Plan-/Apply-Ablauf erneut aus. Keine aktuelle `Run workflow`-Definition auf `main`. | +| Copilot cloud agent | Von GitHub verwalteter Agent-Workflow, kein YAML in diesem Repository | Start über GitHubs Copilot-Agent-Aufgabenoberfläche, abhängig von Repository-Richtlinien und Zugriff; nicht über unsere `workflow_dispatch`-Eingaben | +| Dependabot Updates | Von GitHub verwaltete Update-Jobs, konfiguriert in [dependabot.yml](../.github/dependabot.yml) | Wöchentlich sonntags für Terraform-Provider und GitHub Actions; GitHubs Dependabot-Oberfläche verwaltet Update-Prüfungen. Entstehende PRs durchlaufen die normale Repository-Validierung, keine automatische Bereitstellung. | + + +## Diesen Katalog pflegen + +Aktualisieren Sie diese Seite bei Änderungen an Workflow-Namen, Auslösern, Eingaben, +Branch-Schranken, Umgebungsfreigaben oder betrieblichen Auswirkungen. Unterscheiden +Sie wiederverwendbare Aufrufe von automatischen Push-/PR-Auslösern. Workflow-YAML +und verlinkte Operator-Runbooks sind maßgeblich; dieser Katalog ist keine +Bereitstellungsfreigabe. + +Weitere Referenzen: [Mitwirken](../CONTRIBUTING.de.md), +[Configurator-Entwicklung](../landing-zone-configurator/docs/development.de.md), +[Operator-CI und Umgebungsschranken](../landing-zone-configurator/infra/ci/README.de.md). diff --git a/docs/workflows.md b/docs/workflows.md index fc5318a..0099e1b 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -1,5 +1,7 @@ # GitHub Actions workflows +[English](workflows.md) | [Deutsch](workflows.de.md) + This is the entry point for choosing and starting a pipeline. Workflow names link directly to their **Actions** pages; **source** links show the executable definition. The ten current repository workflows are listed below. Historical entries and diff --git a/landing-zone-configurator/README.de.md b/landing-zone-configurator/README.de.md new file mode 100644 index 0000000..9a1d585 --- /dev/null +++ b/landing-zone-configurator/README.de.md @@ -0,0 +1,54 @@ +# Landing Zone Configurator + +[English](README.md) | [Deutsch](README.de.md) + +Der Configurator ist eine optionale, gehostete Oberfläche für den +[STACKIT Landing Zone Accelerator](../README.de.md). Er verbindet einen Konfigurationseditor, +einen Assistant, versionierte Projektvorlagen und ausdrücklich autorisierte +Infrastrukturoperationen. Der Accelerator bleibt unabhängig mit +Terraform/OpenTofu nutzbar. + + +## Einstieg + +| Zielgruppe | Dokumentation | +| --- | --- | +| Benutzer | [Benutzerhandbuch](docs/user-guide.de.md) und [MVP-Umfang und Grenzen](docs/mvp-scope.de.md) | +| Architekten | [Komponenten, Diagramme und Vertrauensgrenzen](docs/architecture.de.md) | +| Mitwirkende | [Entwicklungsübersicht](docs/development.de.md), [lokale Einrichtung](app/README.de.md) und [Mitwirken](../CONTRIBUTING.de.md) | +| Betreiber | [Infrastruktur](infra/README.de.md), [manueller CI-Betrieb](infra/ci/README.de.md) und [CF-Releases](deploy/cloud-foundry/README.de.md) | + +Die [Entwicklungsumgebung](https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud) +ist kein Produktionsdienst. Produktionsbereitstellung und betriebliche Abnahme +sind separate Folgeaufgaben; das Zusammenführen von Quellcode deployt die Anwendung nicht. + + +## Zusammenspiel + +![Configurator-Komponenten](docs/architecture/stackit-overview.svg) + +Der Browser kommuniziert mit der API, die Mandantenautorisierung und deterministische +Konfigurationsvalidierung durchsetzt. Nur die API ruft Model Serving auf. Angenommene +Assistant-Vorschläge ändern einen Entwurf, keine Infrastruktur. Ein separater, isolierter +Runner führt den gepinnten Accelerator erst nach den erforderlichen Plan-/Apply-Freigaben aus. + +![Plattform- und Application-Lebenszyklus](docs/architecture/landing-zone-logical.svg) + +Plattformkonfiguration, veröffentlichte Vorlagenversionen und Application-Instanzen +haben getrennte Lebenszyklen. STACKIT-Anmeldung, Mandantenmitgliedschaft, optionaler +GitHub-Zugriff und technische Cloud-Ausführungszugänge sind unterschiedliche Berechtigungen. + + +## Repository-Struktur + +- [app/](app/): API, React-Frontend, Worker, Domain/Compiler und gemeinsame Verträge. +- [tools/hcl-adapter/](tools/hcl-adapter/): nativer Eingabekatalog und HCL-Roundtrips. +- [deploy/](deploy/): Cloud-Foundry-Paketierung, Migrationen und isolierter Runner. +- [infra/](infra/): Betreiberinfrastruktur mit getrennten verschlüsselten States. +- [docs/](docs/): Benutzer-, Architektur- und Entwicklungsreferenzen. +- [../src/](../src/): unabhängig nutzbare Accelerator-Infrastruktur. + +Anwendungsabhängigkeiten und Lockfiles sind vom Accelerator getrennt. +Builds pinnen ihre Accelerator-Revision und binden API/UI- und Runner-Artefakte +an dieselbe Quelle. Der Infrastruktur-State des Kunden ist weder die +Konfigurationsdatenbank des Configurators noch der State seiner Betreiberinfrastruktur. diff --git a/landing-zone-configurator/README.md b/landing-zone-configurator/README.md index d49c5a8..d29e4c8 100644 --- a/landing-zone-configurator/README.md +++ b/landing-zone-configurator/README.md @@ -1,5 +1,7 @@ # Landing Zone Configurator +[English](README.md) | [Deutsch](README.de.md) + The Configurator is an optional, hosted interface for the [STACKIT Landing Zone Accelerator](../README.md). It combines a configuration editor, an Assistant, versioned project templates and explicitly authorized diff --git a/landing-zone-configurator/app/README.de.md b/landing-zone-configurator/app/README.de.md new file mode 100644 index 0000000..8d4f1eb --- /dev/null +++ b/landing-zone-configurator/app/README.de.md @@ -0,0 +1,620 @@ + + +# Configurator-Entwicklung + +[English](README.md) | [Deutsch](README.de.md) + +TypeScript-Workspace mit React/Vite, Fastify, Fachmodell und API-Verträgen. Abhängigkeiten sind exakt gepinnt, das npm-Lockfile wird versioniert. Voraussetzungen: Node.js **24.21.0**, npm **11.19.0**. `../mise.toml` und `.node-version` dokumentieren die Runtime unabhängig vom Accelerator. + + + +## Installieren und prüfen + +Im Verzeichnis `landing-zone-configurator/app`: + +```sh +npm ci +npm run check +``` + +`check` führt Biome, TypeScript-Prüfung einschließlich Tests, Produktionsbuild und Vitest aus. `npm run format` korrigiert Formatierung und Importreihenfolge. + +Falls die passende Runtime lokal noch fehlt, funktioniert ohne globale Installation beispielsweise: + +```sh +npm exec --yes --package=node@24.21.0 --package=npm@11.19.0 -- npm ci +npm exec --yes --package=node@24.21.0 --package=npm@11.19.0 -- npm run check +``` + + + +## Lokal starten + + + +### Automatisierte Assistant-Themenpruefung + +Der [Testkatalog](../docs/assistant-test-catalogue.json) fuehrt jedes +Editor-/Accelerator-Feld genau einem Wissensthema zu: Typ, Optionalitaet, +Verantwortlichkeit, tatsaechlicher Vorschlagsmodus und erlaubter Patch-Pfad. +Regionale DNS-Formen, geschuetzte Werte und nur beratend unterstuetzte Komponenten +werden nicht als uebernehmbare Vorschlaege ausgegeben. Workflow-Themen ohne eigene +Felder sind ebenfalls enthalten. Fehlende/doppelte Zuordnungen und Drift brechen +`npm run assistant:check` sowie den normalen `npm run check` ab. + +Die [synthetischen Chatfaelle](scripts/assistant-scenarios.ts) enthalten fuer jedes +Wissensthema eine feste Frage. Zusaetzliche Regressionen pruefen exakte +Grundlagenwiederherstellung, DNS-Kontaktprioritaet inklusive Template-Platzhaltern, +Domain-/Netzerhalt, vollstaendige SNA-Werte und additive Organisations-/Folder-Rollen +mit gespeicherten oder verifizierten E-Mail-Quellen. Unit-Tests pruefen auch, dass die +Pruefer fehlerhafte Antworten tatsaechlich ablehnen. Neue Felder/Themen erfordern +Review der Zuordnung und Fragen, danach `npm run assistant:generate` und Formatierung +des generierten Wissensbundles. Regenerieren allein ist kein fachlicher Nachweis. + +Die Uebersichtsfaelle fuer Grundlagen, Governance, Firewall-Policy und Sandboxes +pruefen zusaetzlich konkrete native Feldnamen und wichtige Grenzen, nicht nur eine +Themenreferenz. Der Intentklassifikator erkennt reine Felduebersichten semantisch; +fuer diese vier Themen antwortet der Backend-Wissensvertrag direkt aus dem +Feldinventar und geprueften Grenzen, ohne eine zweite freie Modellformulierung. +Das ist ein eigener Beratungspfad, kein Ersatz fuer eine fehlgeschlagene +Modellantwort. Ausdrueckliche Rollenwuensche haben ebenfalls einen geprueften +Entwurfspfad: Der Intent bestimmt Rolle, E-Mail-Quelle und explizite Folder-Auswahl; +der Backend-Vertrag bildet daraus additive Felder ohne zweite freie Modellantwort. +Andere Anforderungen, Rueckfragen und Vorschlaege verwenden weiterhin das +Antwortmodell. Alle vertrauenswuerdigen Systemanweisungen werden in einer einzigen +Systemnachricht gesendet, damit Serving-Chatvorlagen keine frueheren Vertraege +verlieren. Tokenlimit-Abbrueche bleiben explizite Fehler (`completion_truncated`), +ohne automatische Wiederholung oder Teilannahme. SNA-Vorschlagstexte und deren +Streaming zeigen nur gepruefte Werte und bestaetigen niemals eine bereits +erfolgte Speicherung. + +Firewall-Infrastruktur und HA unter `connectivity.firewall`/`firewalls` sind +als einzelne Entwurfsfelder vorschlagbar. Native HA ist ein Objekt mit +`backup_zone`, keine Checkbox/Boolean; weitere HA-Felder sind separat waehlbar. +Bestehende Single-/Map-Formen, Area-Keys und nicht angefragte Werte bleiben erhalten. +Neue Appliances brauchen Name, Zone, Flavor und beide bestaetigten freien Subnetze +zusammen; eine neue HA-Konfiguration ihre Backup-Zone. Unvollstaendige Auswahl +wird ohne Speicherung abgelehnt. Adresscontainment, Ueberlappungen, Node-/VIP-IPs +und unterschiedliche Zonen werden validiert. Unbekannte Produkte oder freie +Netze werden nicht aus Projektzahlen erfunden. Optionale Node-/VIP-IPs werden im +Modellvertrag auf gespeicherte oder benutzerbestaetigte Adressen begrenzt; +berechnete native Defaults bleiben ohne ungefragte explizite IP-Aenderungen erhalten. +Bei kombinierten Netzwerk-/Firewall- +Auftraegen wird ein vollstaendiges gespeichertes SNA wiederverwendet statt die +Firewall pauschal aufzuschieben. /16 bietet rechnerisch512 /25-Subnetze mit je128 +Adressen vor Reservierungen, nicht128 Projektnetze. Regional-Patches, Policies, +Operator-Zugaenge, Entfernung und Ausfuehrung bleiben ausserhalb dieses Vertrags. +Feldannahme ist kein Deployment, Durchsatznachweis oder oeffentliches IP-Failover. +Breite Firewall-Einrichtung zeigt vorhandene Entwurfswerte und fragt auch neben +einem HA-Vorschlag nach der naechsten unbeantworteten Verkehrs-, Kapazitaets- oder +Betriebsentscheidung. Gezielte Einzelfeldaenderungen bleiben ohne Fragebogen. +Antworten zu Verkehrsregeln und Kapazitaet setzen einen laufenden Firewall- +Einrichtungsauftrag fort, statt ihn in isolierte Beratung umzuwandeln. +Explizit unbekannte Kapazitaet bleibt als offener Sizing-/Benchmark-Punkt erhalten; +danach folgt die noch fehlende Unterbrechungs-/Betriebsentscheidung. Bereits +benannte Betreiber und bestaetigte Verkehrswege werden nicht erneut abgefragt. +Regelanforderungen werden zusammengefasst, nicht als konfigurierte Regeln +ausgegeben. Bestaetigungen verweisen auf tatsaechliche Nutzeraussagen; interne +Steuertexte werden nicht als Rueckfragen angezeigt. +Der native Accelerator verwaltet Regeln, Aliase, Routen und NAT ueber +`firewall_config`; der aktuelle Chat kann diese Policy weder definieren noch +als Vorschlag uebernehmen. Gefuehrte Editor-Policy-Bearbeitung und +Assistant-Regel-/NAT-Vorschlaege sind gemaess Benutzerentscheidung Post-MVP +([#101](https://github.com/stackitcloud/stackit-landing-zone/issues/101)). +Im MVP pflegt der Firewall-Admin die Policy manuell in OPNsense. +Der gemeinsame Editor hat unter Betrieb / Firewall-Regeln bereits generische +native Felder, keine qualifizierte Policy-Verwaltung; sie bleiben erhalten. +Faehigkeits- und Definitionsanfragen erhalten die Grenze ausdruecklich, +ohne einen Regelvorschlag versprechende Rueckfragen. Infrastruktur/HA allein +garantiert weder Isolation noch Internetzugriff oder NAT. +Explizite Themenwechsel haben Vorrang vor alten Netzwerk-/Firewall-Merkmalen. +"Als naechstes Audit-Protokollierung einrichten" ist ein aktueller Auftrag, +keine Vertagung. Historische Netzwerkziele werden im anderen Thema nicht als +aktive Anforderungen weitergereicht; Belegpruefungen bleiben erhalten. +Audit Logging hat einen nativen Telemetry-Link/Router-/Logs-/Archiv-Vertrag +und generische Editorfelder unter Plattform. Der Chat verwendet jetzt denselben +nativen Eingabevertrag fuer uebernehmbare Audit-, Observability-, Federation-, +VPN-, DevOps-, Kubernetes-, Projekt-/Vorlagen- und Namespace-Vorschlaege. +Geschuetzte Bindings, Veroeffentlichung, Cloud-Ausfuehrung und Firewall-Policy +bleiben separate Workflows. Neue Audit-Konfigurationen benoetigen Retention, +ACL und die ausdrueckliche Object-Lock-Auswahl zusammen; mit Object Lock gilt +der Bereich 1-365 Tage. Es wird keine Einrichtung oder Ereigniszustellung behauptet. + +Editor-Vorschlaege nutzen `merge` fuer partielle Objekt-/Map-Aenderungen, +`replace` fuer einen atomar geprueften vollstaendigen Ersatz und `default` +zum Entfernen eines optionalen Overrides. Listen bleiben atomar. +Ausgelassene Merge-Felder und bestehende Ressourcenkennungen bleiben erhalten. +Plattform-Entwuerfe bearbeiten Projektvorlagen nach stabilen Schluesseln; +Vorlagenkennungen entstehen serverseitig, nicht im Modell. Neue/entfernte +Vorlagen, Einstellungen und Parameterregeln bleiben lokale Entwurfsaenderungen. +Feldabdeckung und echte Compiler-/Export-/Identitaetspruefungen liegen in +[assistant-editor.test.ts](tests/assistant-editor.test.ts). +Abgelehnte Modellantworten liefern eine sichere Fehlerkategorie und +Diagnosekennung, keine Rohantworten oder Zugangsdaten. Konfigurations-Chat und +Template-Beratung zeigen lokalisierte Ursachen und naechste Schritte; Nachricht +und Antwortauswahl bleiben erhalten. HTTP und Antwortstreams nutzen denselben +Fehlervertrag. Es gibt keine automatische Wiederholung oder Teiluebernahme. +Chat und Feldannahme funktionieren auch mit ungespeicherten Editoraenderungen. +Der Chat erhaelt nur die freigegebenen Werte des aktuellen lokalen Entwurfs. +Rueckfragen im Konfigurations-Chat und in der Template-Beratung werden mit +`Antwort senden` direkt abgeschickt, ohne einen separaten Vorbereitungsschritt. +Vorhandener Text im Nachrichtenfeld wird mitgesendet. Bei einem Fehler bleiben +Text und Antwortauswahl fuer einen erneuten Versuch erhalten. +Vorschlaege werden ausschliesslich in den lokalen Entwurf uebernommen; Speichern +bleibt separat. Ein Drei-Wege-Abgleich bewahrt unabhaengige lokale und gespeicherte +Aenderungen. Nur echte Konflikte benoetigen eine ausdrueckliche Bestaetigung; +eine andere Revision allein sperrt die Uebernahme nicht. Aeltere Vorschlaege ohne +nachweisbaren Ausgangswert benoetigen eine Wertepruefung. Migration057 speichert +nur freigegebene Vorschlags-Ausgangswerte, keine vollstaendigen Entwuerfe/Secrets. +Die Vorschau veraendert weder die Konfiguration noch das gespeicherte Gespraech. +Ohne `draft`/`savedDraft` behaelt der API-Annahmepfad sein bisheriges transaktionales +Speicherverhalten und seine strikte Revisionspruefung. + +`organization_owners` und `organization_auditors` sowie +`rm_folders[*].owner_emails`/`reader_emails` sind bei explizitem Rollenauftrag +einzeln uebernehmbare Vorschlagsfelder. Bekannte E-Mails werden nur aus der +angefragten Quelle verwendet; Template-Platzhalter, Entwicklerlogin und +Service Account ersetzen keine verifizierte menschliche Anmeldung. Unbekannte +E-Mail oder nicht benannte Folder bleiben Rueckfragen. Bestehende Zuweisungen +werden nicht entfernt und Namensdelegation erlaubt keine Rollenaenderung. +Organisation-Owner deckt die Folder bereits ab; der native Accelerator vermeidet +doppelte Folder-Zuweisungen. Reader werden nativ als `auditor` zugewiesen. +Uebernahme speichert nur Konfiguration, nicht STACKIT-IAM oder Configurator-Rollen; +IAM-Aenderungen bleiben an geprueften Plan und separate Apply-Freigabe gebunden. + +```sh +# Ohne Credentials: Inventar, Wissensfrische und Testfragen pruefen +npm run assistant:check +# Echter Modelllauf mit allen Themen; vorhandenen privaten lokalen Zugang nutzen +LZC_MODEL_SERVING_INTENT_MODEL=openai/gpt-oss-120b npm run test:assistant:live -- --local-credentials +# Nur ein Thema oder eine Regression +LZC_MODEL_SERVING_INTENT_MODEL=openai/gpt-oss-120b npm run test:assistant:live -- --local-credentials --topic dns-zones +LZC_MODEL_SERVING_INTENT_MODEL=openai/gpt-oss-120b npm run test:assistant:live -- --local-credentials --case foundations-restoration +# Zusammenhaengender Dialog mit GPT-OSS 120B fuer beide Modellrollen +LZC_MODEL_SERVING_MODEL=openai/gpt-oss-120b \ + LZC_MODEL_SERVING_INTENT_MODEL=openai/gpt-oss-120b \ + npm run test:assistant:journey -- --local-credentials +``` + +Der Journey-Test durchlaeuft zwoelf Schritte von Grundlagen und Rollen ueber +SNA/Firewall, den Policy-MVP-Hinweis und Audit-Rueckfragen bis Observability, +DevOps, Kubernetes und Labels. Jeder Schritt nutzt denselben fortgeschriebenen +Entwurf und die tatsaechliche Gespraechshistorie. Fachlich passende Vorschlaege +werden im Speicher uebernommen, per JSON-Roundtrip geprueft und abschliessend als +tfvars exportiert. Fehlerhafte Vorschlaege werden nicht uebernommen; abgelehnte +Modell-/Anwendungsergebnisse werden wie im API-Service nicht als erfolgreiche +Gespraechsantwort gespeichert. Modellnamen, Wissens-/Journey-Hashes, +Einzelergebnisse und Antwortzeiten werden ausgegeben. Dies ersetzt keine +Browser-, PostgreSQL- oder Cloud-Ausfuehrungspruefung. Beide Live-Runner sperren +aktivierte Ausfuehrungsflags; sie aendern weder die laufende Modellauswahl noch +Kundenkonfigurationen und verwenden keine automatischen Wiederholungen. + +Beide Runner lassen zwischen tatsaechlichen Serving-Requests mindestens 2500 ms +Abstand, auch zwischen Intent und Antwort desselben Schritts. Diese Begrenzung +gilt nur fuer die Tests, nicht fuer den produktiven Assistant. Ausgegebene +Antwortzeiten enthalten die Wartezeit und sind deshalb nicht direkt mit +Messungen ohne diese Begrenzung vergleichbar. Quotenfehler bleiben sichtbare Fehler; +sie werden nicht durch automatische Wiederholungen verdeckt. + + + +#### Weitere Assistant-Komponenten ergaenzen + +1. Zuerst den nativen Input-Typ und den manuellen Editor-/Compiler-Pfad pruefen. + Der Assistant leitet Pfade, Werte und Pflichtfelder aus demselben Inventar ab; + keine zweite, handgeschriebene Komponentenstruktur oder freien HCL-Patches. +2. Einen geprueften Wissenstopic mit nativen Inputs, Feldpfaden, Quellen und + Abhaengigkeiten hinterlegen. Intent und Rueckfragen werden darauf begrenzt. +3. Nur fachliche Anforderungen ueber den nativen Typ hinaus in + `assistantEditorPolicies` ergaenzen, beispielsweise ausdrueckliche + Audit-Erstellungsentscheidungen und Freitext statt erfundener ACL-Auswahlwerte. + Policy-Feldpfade muessen im nativen Inventar existieren. +4. Erstellung und Aktualisierung getrennt pruefen: neue Objekte verwenden + typisierte Konstruktor-Slots fuer einfache Skalare und Listen; optionale + Null-Slots bedeuten native Defaults und werden nur bei Erstellung ohne + vorherigen Wert ausgelassen. Komplexe optionale Collections bleiben optional; + etwa sind leere Audit-Link-Scopes kein Organisationsdefault. + Bestehende Objekte werden partiell geaendert, neue Map-Eintraege brauchen native + Pflichtfelder. Ersetzen und Default-Reset bleiben explizite, atomare Operationen. +5. Tests fuer reale Uebernahme, Geschwistererhalt, Identitaeten, Quellenbindung, + fehlende Entscheidungen, Themenwechsel und DE/EN hinzufuegen. Auch eine vom + Serving akzeptierte Antwort wird gegen den angebotenen Schema-Vertrag und + anschliessend gegen die unveraenderte native Laufzeitvalidierung geprueft. +6. Nach Wissensgenerierung erst gezielte Offline-/Modellfaelle, dann den seriellen + Journey- und vollstaendigen Szenarienlauf qualifizieren. Hashes und verbleibende + Fehler dokumentieren; kein Modell-/API-Rollout allein aufgrund gruener Mocks. + +Vorschlagstexte mit Aenderungen werden serverseitig als lokale Entwurfsvorschlaege +formuliert, nicht als vom Modell behauptete Speicherung oder Berechtigungsvergabe. +Firewall-Policy, Credentials, Organisationsbindung, Publikation und Ausfuehrung +bleiben getrennte, geschuetzte Workflows. + +Der Live-Test verwendet die echte Assistant-Orchestrierung, Intentklassifikation, +Wissensauswahl, Antwortvalidierung und den lokalen Compiler, aber ausschliesslich +synthetische Konfigurationen im Speicher. Kein Browser, Benutzer-SSO oder Zugriff +auf Kundengespraeche/-datenbanken; keine automatische Annahme und kein Cloud-Auftrag. +Die HTTP-/Session-/Transaktionspfade bleiben durch Unit-/Datenbanktests abgedeckt. +Der Lauf meldet pro Fall Antwort, Fehlercodes, Laufzeit und abschliessend +Modell-/Wissensversion und Zaehler; jeder Fehler ergibt Exitcode 1. Fehlende Zugriffe +werden nicht uebersprungen. Live-Aufrufe verursachen Model-Serving-Kosten. +Themen-Smokes pruefen Referenz, gueltigen Antwortvertrag und Beratungsmodus, nicht +automatisch die fachliche Richtigkeit jeder Textaussage oder jedes einzelnen Feldes. +Ein gruener Smoke ist keine vollstaendige Komponenten-/Cloud-Qualifikation. + +Ohne `--local-credentials` wird `LZC_MODEL_SERVING_TOKEN` aus der Prozessumgebung +erwartet. Lokal liest der gemeinsame sichere Loader den bereits vorhandenen +verschluesselten State mit Originalschluessel; private Dateien muessen dem aktuellen +Benutzer gehoeren und duerfen keine Gruppen-/Weltrechte haben. Token/Schluessel werden +nicht ausgegeben oder in Tests/Reports geschrieben. Keine neuen Credentials im Git, +keine Rotation bestehender Schluessel und keine SSO-Automatisierung. + +Der manuell ausloesbare [GitHub-Workflow](../../.github/workflows/assistant-live.yml) +verwendet die Umgebung `assistant-tests`. Dort `LZC_MODEL_SERVING_TOKEN` als +Environment-Secret mit Freigabe-/Branchschutz hinterlegen; keine Tokens in Chat, +Workflow-Dateien oder Kommandozeilen schreiben. Normale PR-Checks bleiben offline +und benoetigen keine Cloud-Secrets. Ein Service-Account fuer spaetere lesende +Produktkatalogtests muss separat mit minimalen Rechten und Testprojekt eingerichtet +werden; er ersetzt keine menschliche Identitaet fuer Benutzer-/SSO-Rechtepruefungen. + +Zwei Terminals im App-Verzeichnis: + +```sh +# Terminal 1: API auf http://127.0.0.1:3000 +npm run dev +``` + +```sh +# Terminal 2: UI auf http://127.0.0.1:5173 +npm run dev:web +``` + +Auch diese Befehle können bei abweichender lokaler Node-Version mit dem oben gezeigten `npm exec`-Präfix ausgeführt werden. Der Vite-Entwicklungsserver leitet `/healthz`, `/auth` und `/api` an die lokale API weiter. Gemeinsame Pakete vor UI-Start bauen (`npm run build:packages`, bereits Teil von `npm run dev`). Nach Änderungen an gemeinsamen Paketen erneut bauen; automatischer Workspace-Watch folgt später. + + + +### Ubuntu-Workstation mit Entwicklerlogin und HTTPS + +Dieser separate Starter ist fuer die persoenliche Ubuntu-Entwicklung ohne +registrierten OIDC-Webclient gedacht, **nicht** fuer Cloud Foundry oder Produktion. +Er akzeptiert ausschliesslich eine kanonische HTTPS-Origin, aktiviert keinen +STACKIT-CLI-Callback und erstellt einen eigenen persoenlichen Arbeitsbereich. +Er behauptet keine verifizierte STACKIT-Benutzeridentitaet und vergibt keine +organisationsbezogenen Produktrollen. Bestehende Arbeitsbereiche, Entwuerfe und +Chats werden weder uebernommen noch veraendert. + +```sh +npm run build +LZC_DEVELOPMENT_ORIGIN=https://work.lukas.runs.onstackit.cloud:4181 \ + LZC_RUNNER_PACKAGE_DIR=/absoluter/pfad/zum/geprueften/runner \ + npm run dev:workstation -- --execution \ + --service-account-file /absoluter/pfad/zur/privaten-service-account-key.json \ + --organization ORGANISATION_UUID +``` + +Ohne `--execution` bleiben Plan/Apply deaktiviert. Mit dem Schalter ist der +vorhandene native Plattform-Runner verfuegbar; es startet **kein** Cloud-Job. +Preparation, Plan, State-Zuordnung und Apply-Freigabe behalten ihre bestehenden +Pruefungen. Der separate Application-Runner bleibt unabhaengig deaktiviert. +GitHub-Verknuepfung und SSO-abhaengige Organisation-Funktionen sind in diesem +Modus nicht verfuegbar. + +Der einmalige Benutzername ist `developer`. Das zufaellige initiale Passwort +steht ausschliesslich in der privaten lokalen Datei +`../.local/development/initial-password` (0600), nicht in Logs oder Antworten. +Nach sicherer Uebernahme in einen Passwortmanager kann diese Datei geloescht +werden. `../.local/development/account.json` enthaelt den gesalzenen scrypt-Hash +und die dauerhafte Dev-Principal-ID; diese Datei behalten und nicht einchecken. +Login, Logout und API-Mutationen verwenden weiterhin Secure/HttpOnly-Cookies, +die exakte HTTPS-Origin, CSRF-Token und bestehende Tenant/RLS-Pruefungen. +Es gelten maximal zehn Login-Versuche pro 15 Minuten und API-Instanz. + +`--service-account-file` akzeptiert nur eine kleine, regulaere, nicht verlinkte +Datei des aktuellen Benutzers ohne Gruppen-/Weltrechte. Der Schluessel wird +idempotent als eigenes Credential-Profil im bestehenden verschluesselten +Secret Store gespeichert; keine Zuordnung zu einem vorhandenen Benutzer. +`--organization` prueft ausschliesslich den technischen Org-Lesezugriff; es +ist **kein** menschlicher Organisationsnachweis. Dieser explizite Import kann +bei spaeteren Starts entfallen. Keine Secrets in Shell-Argumenten uebergeben. + +Fuer die TLS-Auslieferung Caddy installieren und separat starten: + +```sh +sudo caddy run --config "$PWD/scripts/workstation.Caddyfile" --adapter caddyfile +``` + +Die API samt gebautem UI bleibt auf `127.0.0.1:3000`; ein eigener Vite-Preview +auf Port 4181 darf nicht parallel laufen. Caddy liefert die Anwendung unter +`https://work.lukas.runs.onstackit.cloud:4181/` aus. TCP 4181 muss fuer den Browser, +TCP 80 fuer oeffentliche ACME-HTTP-Pruefungen und spaetere Erneuerungen erreichbar +sein. Port 80 liefert nur Challenge/HTTPS-Weiterleitung. Bei anderem Host +`LZC_DEVELOPMENT_HOST` fuer Caddy und die dazu passende `LZC_DEVELOPMENT_ORIGIN` +fuer die API setzen; der HTTPS-Port dieses Caddy-Beispiels ist 4181. +Kein selbstsigniertes Zertifikat und kein unsicherer HTTP-Login-Fallback. +Die Prozesse laufen nur waehrend ihrer gestarteten Sitzung; es wird kein +Autostart-Service fuer diese Entwicklung eingerichtet. + +Gezielte Pruefungen: + +```sh +npx vitest run tests/development-login.test.ts tests/auth-routes.test.ts +# Ausschliesslich isoliertes configurator_test auf einer lokalen Testdatenbank: +LZC_TEST_DATABASE_URL=postgres://.../configurator_test \ + npx vitest run integration/development-login.test.ts +npx playwright test e2e/development-login.spec.ts +``` + + + +### Lokaler STACKIT-Login + +Nach ausdrücklicher Freigabe der CLI-Client-Nutzung kann der echte Login ohne +Dev-Datenbank und Secrets-Manager-Zugang lokal gestartet werden. Docker muss laufen: + +```sh +LZC_STACKIT_CLI_CLIENT_APPROVED=true npm run dev:login +``` + +Das Backend läuft ausschließlich auf `127.0.0.1:3000`; die zugehörige gebaute +UI-Vorschau muss auf `http://127.0.0.1:4181` laufen. Der Starter legt den eigenen +Docker-Container `lzc-local-stackit-login` mit PostgreSQL 17 an, bindet dessen Port +nur an Loopback und wendet die bestehenden Migrationen an. Zufällige +Datenbankpasswörter werden nicht ausgegeben; die Runtime verwendet weiterhin +`configurator_app`, nicht die Migrationsidentität. Die lokale Datenbank bleibt +bei einem API-Neustart erhalten; der Starter löscht keine Nutzer oder Entwürfe. + +STACKIT-Identitätsprüfung, Sessions, Credential-Profile und Produktkataloge sind echt. +Technische STACKIT-Abfragen verwenden den im aktiven Tenant gespeicherten Service +Account. Platform Engineers können Zugänge auch in Organisationstenants verwalten; +Profile bleiben an Tenant und Besitzer gebunden. Im persönlichen Tenant wird ein +zugängliches aktives Referenzprojekt automatisch ermittelt, im Organisationstenant +wird die Suche auf dessen Organisation begrenzt. + +Nur im lokalen Starter ersetzt eine AES-256-GCM-Ablage den Secrets Manager. +Schlüsseldateien sind unter `../.local/credential-secrets/` verschlüsselt; das +separate lokale Verschlüsselungsgeheimnis `master.key` und der Ordner sind nur für +den Betriebssystembenutzer zugänglich. Das ist kein Ersatz für einen produktiven +Secrets Manager: Wer auf Ordner und Verschlüsselungsgeheimnis zugreifen kann, +kann die Daten entschlüsseln. Den Ordner nicht teilen oder ins Repository aufnehmen. +Er bleibt wie die Datenbank über Neustarts erhalten. + +`dev:login` aktiviert keinen Runner und übernimmt keine Dev-Daten. Mit einem +vorbereiteten nativen Paket aktiviert `dev:execution` lokale Plattform-Plans und +den ausdrücklich freizugebenden Apply-Pfad. Organisations-Platform-Engineers +verwenden weiterhin private, tenantgebundene Vorbereitungen und Zugänge. +HTTP wird ausschließlich für ausdrücklich aktivierte, kanonische Loopback- +Ursprünge erlaubt; Produktionskonfigurationen verlangen unverändert HTTPS. +Ein bloßes `vite preview` ohne dieses Backend kann keine Anmeldung durchführen. + + + +### Recovery-Pruefbelege + +Nach Anwendung der Migrationen 051 und 052 kann der separate Opt-in +`LZC_APPLICATION_RECOVERY_REVIEWS_ENABLED=true` Recovery-Pruefbelege aktivieren. +Default ist deaktiviert. Der lokale Login-Starter wendet beim naechsten Start +die vorhandenen neuen Migrationen an; ein Neustart ist deshalb ein kontrollierter +Migrationsschritt, auch wenn native Runner ausgeschaltet bleiben. + +Die Aktion ist auf den urspruenglich freigebenden Platform Engineer mit aktueller +Session und gueltiger menschlicher STACKIT-Identitaet beschraenkt. Sie protokolliert +nur die ausdrueckliche Pruefung des gebundenen Diagnose-Stands. Sie aendert keinen +Jobstatus und hebt keine State-/Recovery-Sperre auf. Ohne neue Migration muss der +Opt-in ausgeschaltet bleiben. Der gehostete Start prueft bei Opt-in die Tabelle +und die neue Abgleichsfunktion aus Migration 052. Der lesende Pruefkontext zeigt +gespeicherte Runner-ID, Report-Hashes, Ticket-Fenster und Grant-/Delegationswiderruf. +Startunsicherheit, fehlender Abschluss und gespeicherter Recovery-State bleiben +unterschiedliche Feststellungen. Ticket-Ablauf oder Delegationswiderruf belegen +weder Runner-Stillstand noch Widerruf bereits ausgegebener Cloud-Credentials. +Cloud-Abgleich, Runner-Stillstand, State-Wiederherstellung und Ausfuehrungsfreigabe +bleiben separate Vorgänge mit eigenen Nachweisen und Freigaben. + + + +### Lokale Plan-/Apply-Ausführung + +Mit Node 24.21.0, npm 11.19.0 und checksum-geprüftem OpenTofu 1.12.6 im `PATH`: + +```sh +npm run build +LZC_LOCAL_RUNNER_PACKAGE=true bash ../deploy/runner/package.sh +LZC_STACKIT_CLI_CLIENT_APPROVED=true npm run dev:execution +``` + +Die Paketierung verlangt ein neues Zielverzeichnis und überschreibt kein +bestehendes Paket. `LZC_RUNNER_PACKAGE_DIR` kann ein anderes geprüftes Paket +angeben. Der native Modus ist ausschließlich für die lokale Entwicklung gedacht, +nicht als Ersatz für die produktive CF-Isolation. Jobs laufen mit minimaler +Umgebung unter `~/.local/share/landing-zone-configurator/runner-jobs`, außerhalb +des Workspace; Paketinhalt und Laufzeit sind an den gespeicherten Plan gebunden. +Nach einem API-Absturz werden unklar laufende Jobs nicht automatisch wiederholt +oder über fremde Prozess-IDs beendet. Recovery-Dateien verhindern Cleanup. + +Der native Worker erzeugt seine CLI-Konfiguration mit dem Paket-Mirror-Pfad und +verwendet fuer Provider-Sockets ein kurzes privates Temp-Verzeichnis, das beim +Cleanup entfernt wird. Init erlaubt Provider-Dateien bis 256 MiB; andere Phasen +behalten das Limit von 64 MiB. Der echte Paket-Init/Validate-Test stoppt vor Plan +und verwendet weder Kunden-Credentials noch Kunden-State: + +```sh +LZC_NATIVE_RUNNER_TEST=true LZC_RUNNER_PACKAGE_DIR=../.local/runner-local-20261003-mirror-init npm exec -- vitest run tests/platform-worker.test.ts -t 'real native providers' +``` + +Unter **OpenTofu-Ausgabe** zeigen Plattformauftraege auch in Cloud Foundry +Live-Fortschritt ueber einen authentifizierten NDJSON-Kanal. Der Worker liest +vollstaendige Zeilen alle 500 ms; nur geaenderter, redigierter Text wird +verschluesselt gesichert und weitergegeben. Der Plan liefert native +OpenTofu-UI-Ereignisse, bevor der fertige Diff verfuegbar ist; rohe Ereignisobjekte +und deren Output-Daten werden nicht an den Browser gegeben. **Ausgabe folgen** laesst sich zum Pruefen aelterer +Zeilen anhalten. Einklappen und Navigation trennen die Verbindung; erneutes +Oeffnen setzt beim aktuellen Mitschnitt fort. JSON-Snapshots bleiben kompatibel. +Erfolgreiche Plattform-Plans werden +read-only mittels `tofu show -no-color` aus dem unveraenderten gespeicherten +Artefakt dargestellt, einschliesslich Ressourcen und Attributaenderungen. +OpenTofu maskiert sensitive Werte wie in der CLI. Die separate Ausgabe-Route +verlangt Sitzung, Deployment-Rolle und private Eigentuemer-/Tenant-Zuordnung; +rohes Plan-Binary oder `show -json` werden nicht an den Browser geliefert. +Jeder Plan bleibt an sein unveraenderliches Runner-Paket gebunden. Ein Paketwechsel +erfordert einen neuen Plan und dessen ausdrueckliche Freigabe. +Laufende Apply-Ausgaben werden ebenfalls aktualisiert. Vor dem terminalen Ergebnis +sichert der Worker den letzten redigierten CLI-Text verschluesselt beim Broker; +er bleibt nach Cleanup und Reload unter derselben privaten Zugriffskontrolle lesbar. +**Apply-Nachweise** zeigen Plan-ID, SHA-256, Zielorganisation, State-Backend des +Auftrags und Abschlusszeit. Die bestehende exakte Organisationsbestaetigung und +gegebenenfalls destruktive Freigabe bleiben erforderlich; kein automatischer Retry. +Ausgaben sind auf 2 MiB begrenzt; eine Kuerzung wird angezeigt. Die Sicherung ist +best-effort: bei hartem Prozessabbruch oder fehlgeschlagenem Upload ist ein +vollstaendiger historischer Mitschnitt nicht garantiert. Bereits gesicherter +Text benoetigt keinen laufenden nativen Runner. Waehrend des Streams werden +Sitzung, Tenant, Rolle und Eigentuemerschaft erneut geprueft. Verbindungen werden +spaetestens nach 35 Sekunden beendet und bei aktivem Auftrag neu geoeffnet; +Backpressure, Byte-Limit und hoechstens acht Streams pro Eigentuemer/Tenant und +API-Instanz begrenzen die Ressourcen. Details: [Plan-Ausfuehrung](../docs/plan-execution.de.md). + +Für neue Plattformen ist **Accelerator-Standard · Management-S3** der Default. +Der ausgewählte Service Account führt den freigegebenen Bootstrap-Apply aus; +Terraform verwaltet Management-Projekt, `*-tfstate`-Bucket, S3-Zugang und dessen +Management-Secrets-Manager-Eintrag. Anschließend verifiziert der Broker die +Migration zu `terraform.tfstate` in eu01. Es sind keine manuellen S3-Keys nötig. +**Bestehendes S3-Backend registrieren** bleibt die optionale Bestandsanbindung. +Der Bucket wird nicht außerhalb des Terraform-State vorab angelegt. Plan und +Apply starten nur über ihre jeweiligen ausdrücklichen Aktionen in der UI. + +`npm run build` erzeugt API-/Paket-Artefakte und `apps/web/dist`. `npm start` startet die gebaute API. Mit `LZC_WEB_ROOT` liefert sie auch das gebaute UI aus. Das [CF-Manifest](../deploy/cloud-foundry/manifest.yml) setzt den Pfad, `HOST=0.0.0.0` und verwendet den von CF bereitgestellten `PORT`. `vite preview` ist kein Produktionsserver. + + + +## Arbeitsbereich und Konfiguration + +Der regulaere Einstieg ist **Anmelden > Arbeitsbereich oeffnen > Konfiguration +oeffnen oder erstellen > Bearbeiten > Plan > Apply**. Beim ersten Einstieg lassen +sich der persoenliche oder ein Organisationsarbeitsbereich oeffnen und neue +Arbeitsbereiche erstellen. Bei spaeterem Einstieg ueber `/` wird der zuletzt +geoeffnete, weiterhin zugaengliche Arbeitsbereich wieder aufgenommen. Explizite +Seiten-URLs bleiben erhalten; der Arbeitsbereichswechsel steht im Header bereit. + +**Arbeitsbereiche** steht an erster Stelle der Hauptnavigation. Oeffnen fuehrt zu +den Konfigurationen des gewaehlten Bereichs, fuer Application Owner zur eigenen +Application-Ansicht. **Benutzerverwaltung** verwaltet Mitglieder, Rollen und +Gruppen des aktiven Bereichs. Berechtigte Platform Engineers koennen eigene +Gruppen anlegen und loeschen sowie Mitglieder zuweisen und wieder entfernen. +Gruppenmitglieder werden mit ihrer bestaetigten STACKIT-E-Mail angezeigt; +Benutzer-IDs bleiben intern. Legacy-Konten ohne STACKIT-E-Mail behalten ihren +Benutzernamen, unbekannte Namen werden nicht durch IDs ersetzt. +Die automatische Gruppe **Application Owners** folgt den Rollen und ist nicht +manuell aenderbar. Gruppen mit Template-Freigaben koennen erst nach deren +Entfernung geloescht werden; Arbeitsbereichsmitglieder bleiben erhalten. +Template-Gruppenfreigaben liegen weiterhin unter **Application Landing Zones > +Veroeffentlichung**, nicht in einem zusaetzlichen Gruppen-Reiter. Auswahl und +Erstellung anderer Arbeitsbereiche liegen nicht in der Benutzerverwaltung. +Auch eine neue inline STACKIT-Anmeldung von einer zuvor offenen Verwaltungsseite +fuehrt ohne offenen Entwurf zum Arbeitsbereichseinstieg. Bereits angemeldete +Deep Links und gesicherte Login-Entwuerfe bleiben erhalten. + +**Konfigurationen** ist die Plattformuebersicht. **Neue Konfiguration** fuehrt zur +Template-Auswahl. Eine geoeffnete Konfiguration hat den Kontext **Konfiguration > +Bereitstellung > Verlauf** mit sichtbarer gespeicherter Revision. +**Speichern und zur Bereitstellung** uebernimmt die vom Server neu gespeicherte +Revision, nicht den alten Entwurfsstand. Ungespeicherte Aenderungen sperren den +direkten Bereitstellungstab; ein Arbeitsbereichswechsel fragt vor ihrem Verlust. +Der Verlauf ist nur lesbar und auf die betreffende Konfiguration begrenzt. + +Die Bereitstellung zeigt pro Konfiguration den neuesten Lauf, sofern er nicht +abgelaufen oder bereits verwendet ist, sowie laufende Ausfuehrungen und +erforderliche Wiederherstellungen. Aeltere, +abgelaufene oder bereits fuer Apply verwendete Plaene liegen standardmaessig +unter **Historie (Anzahl)**. Ihre Details sind einzeln aufklappbar und ohne +Apply-Freigabe; CLI-Ausgaben und Nachweise bleiben lesbar. Ablauf verschiebt einen +Plan auch ohne Reload in die Historie. Die Ansicht loescht oder erneuert keine +Artefakte und hebt keine laufenden Ausfuehrungs-/Recovery-Sperren auf. + +Reload liest die gemerkte Konfigurations-ID innerhalb des Benutzer-/Arbeitsbereichs +erneut vom Server. Zugaenge und Apply-Freigaben werden dadurch nicht gespeichert +oder bestaetigt. Vorbereitung, Plan und Apply bleiben ausdrueckliche Aktionen; +vorhandene Plan-Artefakte werden durch Navigation nicht erneuert oder umgebunden. +Application Owner behalten ihren getrennten Application-Landing-Zone-Einstieg. + + + +## Aktueller Funktionsumfang + +- Private Konfigurationen in PostgreSQL, pro Benutzer und aktivem Arbeitsbereich. + Unter **Konfigurationen** lassen sich auch unvollstaendige Entwuerfe speichern, + wieder oeffnen, als neue Kopie speichern und loeschen. Revisionen verhindern + das Ueberschreiben durch parallele Tabs; im Konflikt bleibt der Entwurf erhalten. + GitHub ist dafuer nicht erforderlich und bleibt als optionaler versionierter + Speicherort verfuegbar. Der Datenbankweg benoetigt Migration + `015_configuration_storage.sql`; vorhandene Konfigurationen sind nur fuer ihren + Ersteller sichtbar. In Organisationsarbeitsbereichen ist die Rolle Platform + Engineer erforderlich. Browser-Zwischenstaende ersetzen diese Speicherung nicht. +- Template-Katalog, Standalone-Editor mit Feldhilfen und grafischer Struktur. +- Nativer `.tfvars`-Download und atomarer GitHub-Export mit JSON, tfvars, CLI-Anleitung und optional verifiziertem S3-Backend. +- GitHub-Login, PostgreSQL-Sessions/RLS und persönliche Tokens im Secrets Manager. +- Persönliche Deployment-Zugänge: Service-Account-Key-Datei speichern/löschen; Anmeldung und Organisations-Lesezugriff prüfen. [Details](../docs/deployment-credentials.de.md). +- Unveränderliche Deployment-Vorbereitungen aus Fork-Konfiguration, Ziel und persönlichem Zugang. [Details](../docs/deployment-preparation.de.md). +- Browser-Zurück/Vorwärts und direkte Seiten-URLs. +- Erstbereitstellungspläne und freigabegebundener Plattform-Apply-Pfad: RLS-Aufträge, isolierte CF-Tasks und wertfreie Ergebnisanzeige; siehe [Ablauf und Abnahme](../docs/plan-execution.de.md). Kein Kunden-Apply in dieser Abnahme; Chat bleibt offen. +- Application-Testkatalog: unveränderliche tenantgebundene Projekt-Template-Versionen, Bestellungen ohne Fork, idempotente Instanzaufträge und ausdrückliche Planblocker. Keine Application-Cloud-Ausführung; siehe [Veröffentlichung und Bestellung](../docs/template-parameters-and-bindings.de.md#tenantgebundener-testkatalog-und-bestellungen). + +Der Application-Dienst ist standardmäßig deaktiviert. Nach Anwendung der Migration +`010_application_catalogue.sql` mit der bestehenden Migrationsidentität aktiviert +`LZC_APPLICATIONS_ENABLED=true` die API im authentifizierten Server. Fehlende Tabellen +verhindern dessen Start. `/applications` ist die eigene SPA-Route; die API liegt unter +`/api/v1/applications/templates` und `/api/v1/applications/instances`. Alle Anfragen +benötigen den aktiven Tenant-Header, Mutationen zusätzlich Origin-/CSRF-Prüfung. +Das Featureflag aktiviert ausschließlich den Testkatalog und Bestellaufträge, niemals +einen Runner oder Apply. Die bestehende Plattform-Plan-Pipeline bleibt unverändert. + +Details und Grenzen: [Forks und Navigation](../docs/forks-and-navigation.de.md), +[GitHub-Login](../docs/github-login.de.md). HCL-Export-Roundtrip prüfen mit Node 24 im PATH: +`cd ../tools/hcl-adapter && go test ./... && go run . -check`. + + + +## State-Backend und unabhängiger Export + +Der Plattform-Bootstrap verwendet temporär einen dauerhaften verschlüsselten +HTTP-State. Nach dem freigegebenen Bootstrap-Apply wird zum LZA-Management-Bucket +migriert; erst nach serverseitigem Hash-/Versionsnachweis wird der HTTP-Primärstate +entfernt. Native S3-States verwenden `use_lockfile = true`; Application-Instanzen +haben jeweils eigene State-Keys. Legacy-State-Zuordnungen bleiben bis zur expliziten +Migration gesperrt. Unbestätigte Migration/Recovery benötigt einen State-Export +und operativen Abgleich; vollständige automatische Recovery bei hartem +Runner-Verlust ist nicht garantiert. Cloud-Locking wurde nicht live getestet. + +GitHub speichert unter `src/config/custom//` JSON, tfvars und eine CLI-Anleitung, +zusätzlich `backend.tf.json`, wenn die API die Quellbindung verifiziert hat. +Die erste Speicherung eines DB-Entwurfs erhält dessen ID; vorhandene Git-Bindungen +behalten ihre eigene ID. Der Browser kann keine Backend-Deskriptoren vorgeben. +Exportiert werden weder AWS-/SA-Schlüssel noch State-Dateien. Backend-Servicefehler, +manuell veränderte Backend-Dateien und verlorene Bindungen brechen den Export ab. +Ein abweichender Quell-ID-Alias wird beim Export nicht neu registriert; für die +Vorbereitung ist die ausdrückliche Auswahl des bestehenden Backend-ID nötig. + +CLI-Betrieb benötigt den geprüften Accelerator-Code und den Management-Zugang +aus dem LZA Secrets Manager. Ursprünglichen Backend-Block in `src/backend.tf` +deaktivieren, exportiertes `backend.tf.json` nach `src/` kopieren und genau einen +aktiven Backend-Block behalten. AWS-Schlüssel als `AWS_ACCESS_KEY_ID` und +`AWS_SECRET_ACCESS_KEY` setzen, dann in `src`: + +```sh +tofu init +tofu plan -var-file=config/custom//landing-zone.tfvars +``` + +Ohne verifizierte Bindung zuerst den LZA-Bootstrap mit gesichertem State und +anschließender geprüfter S3-Migration durchführen. Export führt weder Apply noch +Migration aus. [Lifecycle und Recovery-Grenzen](../docs/plan-execution.de.md#state-lebenszyklus-gemäß-lza). + + + +## Lesende Plattformprüfung + +```sh +npm run platform:check +``` + +Benötigt die STACKIT-CLI sowie die beiden ignorierten Dateien im Repository-Root. Liest `PROJECT_ID` und optional `REGION`; ohne Region wird ausschließlich für die Bestandsaufnahme `eu01` verwendet. `ORGANISATION_ID` bleibt für die spätere Organisationszuordnung reserviert. + +Das Skript führt die `.env` nicht als Shellcode aus. Es bezieht einen kurzlebigen Token ohne CLI-Login-Persistierung und fragt ausschließlich Metadaten per GET ab. Ausgabe enthält Statuscodes/Anzahlen, keine Tokens oder Rohantworten. Unerwartete Fehler führen zu Exitcode 1; der bekannte Object-Storage-Status 404 wird als `enabled: false` und anstehende IaC-Provisionierung gemeldet. Der Check provisioniert oder aktiviert nichts. Betriebssystem-Zertifikate sind für Unternehmensproxys aktiviert; TLS-Prüfung bleibt eingeschaltet. + +Der Modellkatalog beweist keine projektbezogene Inferenzaktivierung. Leserechte beweisen keine Erstell-/Änderungsrechte. CF-Plattformangebote ersetzen weder CF-Organisation noch Runtime-Zugang. Ergebnisse: [Plattformprüfung](../docs/platform-check.de.md). diff --git a/landing-zone-configurator/app/README.md b/landing-zone-configurator/app/README.md index 8719ece..f7e5752 100644 --- a/landing-zone-configurator/app/README.md +++ b/landing-zone-configurator/app/README.md @@ -1,156 +1,166 @@ -# Configurator-Entwicklung +# Configurator development -TypeScript-Workspace mit React/Vite, Fastify, Fachmodell und API-Verträgen. Abhängigkeiten sind exakt gepinnt, das npm-Lockfile wird versioniert. Voraussetzungen: Node.js **24.21.0**, npm **11.19.0**. `../mise.toml` und `.node-version` dokumentieren die Runtime unabhängig vom Accelerator. +[English](README.md) | [Deutsch](README.de.md) -## Installieren und prüfen + -Im Verzeichnis `landing-zone-configurator/app`: +TypeScript workspace with React/Vite, Fastify, a domain model and API contracts. Dependencies are pinned exactly, and the npm lockfile is versioned. Prerequisites: Node.js **24.21.0**, npm **11.19.0**. `../mise.toml` and `.node-version` document the runtime independently of the Accelerator. + + + +## Install and check + +In the `landing-zone-configurator/app` directory: ```sh npm ci npm run check ``` -`check` führt Biome, TypeScript-Prüfung einschließlich Tests, Produktionsbuild und Vitest aus. `npm run format` korrigiert Formatierung und Importreihenfolge. +`check` runs Biome, TypeScript checking including tests, the production build and Vitest. `npm run format` corrects formatting and import order. -Falls die passende Runtime lokal noch fehlt, funktioniert ohne globale Installation beispielsweise: +If the matching runtime is not yet available locally, the following works without a global installation, for example: ```sh npm exec --yes --package=node@24.21.0 --package=npm@11.19.0 -- npm ci npm exec --yes --package=node@24.21.0 --package=npm@11.19.0 -- npm run check ``` -## Lokal starten - -### Automatisierte Assistant-Themenpruefung - -Der [Testkatalog](../docs/assistant-test-catalogue.json) fuehrt jedes -Editor-/Accelerator-Feld genau einem Wissensthema zu: Typ, Optionalitaet, -Verantwortlichkeit, tatsaechlicher Vorschlagsmodus und erlaubter Patch-Pfad. -Regionale DNS-Formen, geschuetzte Werte und nur beratend unterstuetzte Komponenten -werden nicht als uebernehmbare Vorschlaege ausgegeben. Workflow-Themen ohne eigene -Felder sind ebenfalls enthalten. Fehlende/doppelte Zuordnungen und Drift brechen -`npm run assistant:check` sowie den normalen `npm run check` ab. - -Die [synthetischen Chatfaelle](scripts/assistant-scenarios.ts) enthalten fuer jedes -Wissensthema eine feste Frage. Zusaetzliche Regressionen pruefen exakte -Grundlagenwiederherstellung, DNS-Kontaktprioritaet inklusive Template-Platzhaltern, -Domain-/Netzerhalt, vollstaendige SNA-Werte und additive Organisations-/Folder-Rollen -mit gespeicherten oder verifizierten E-Mail-Quellen. Unit-Tests pruefen auch, dass die -Pruefer fehlerhafte Antworten tatsaechlich ablehnen. Neue Felder/Themen erfordern -Review der Zuordnung und Fragen, danach `npm run assistant:generate` und Formatierung -des generierten Wissensbundles. Regenerieren allein ist kein fachlicher Nachweis. - -Die Uebersichtsfaelle fuer Grundlagen, Governance, Firewall-Policy und Sandboxes -pruefen zusaetzlich konkrete native Feldnamen und wichtige Grenzen, nicht nur eine -Themenreferenz. Der Intentklassifikator erkennt reine Felduebersichten semantisch; -fuer diese vier Themen antwortet der Backend-Wissensvertrag direkt aus dem -Feldinventar und geprueften Grenzen, ohne eine zweite freie Modellformulierung. -Das ist ein eigener Beratungspfad, kein Ersatz fuer eine fehlgeschlagene -Modellantwort. Ausdrueckliche Rollenwuensche haben ebenfalls einen geprueften -Entwurfspfad: Der Intent bestimmt Rolle, E-Mail-Quelle und explizite Folder-Auswahl; -der Backend-Vertrag bildet daraus additive Felder ohne zweite freie Modellantwort. -Andere Anforderungen, Rueckfragen und Vorschlaege verwenden weiterhin das -Antwortmodell. Alle vertrauenswuerdigen Systemanweisungen werden in einer einzigen -Systemnachricht gesendet, damit Serving-Chatvorlagen keine frueheren Vertraege -verlieren. Tokenlimit-Abbrueche bleiben explizite Fehler (`completion_truncated`), -ohne automatische Wiederholung oder Teilannahme. SNA-Vorschlagstexte und deren -Streaming zeigen nur gepruefte Werte und bestaetigen niemals eine bereits -erfolgte Speicherung. - -Firewall-Infrastruktur und HA unter `connectivity.firewall`/`firewalls` sind -als einzelne Entwurfsfelder vorschlagbar. Native HA ist ein Objekt mit -`backup_zone`, keine Checkbox/Boolean; weitere HA-Felder sind separat waehlbar. -Bestehende Single-/Map-Formen, Area-Keys und nicht angefragte Werte bleiben erhalten. -Neue Appliances brauchen Name, Zone, Flavor und beide bestaetigten freien Subnetze -zusammen; eine neue HA-Konfiguration ihre Backup-Zone. Unvollstaendige Auswahl -wird ohne Speicherung abgelehnt. Adresscontainment, Ueberlappungen, Node-/VIP-IPs -und unterschiedliche Zonen werden validiert. Unbekannte Produkte oder freie -Netze werden nicht aus Projektzahlen erfunden. Optionale Node-/VIP-IPs werden im -Modellvertrag auf gespeicherte oder benutzerbestaetigte Adressen begrenzt; -berechnete native Defaults bleiben ohne ungefragte explizite IP-Aenderungen erhalten. -Bei kombinierten Netzwerk-/Firewall- -Auftraegen wird ein vollstaendiges gespeichertes SNA wiederverwendet statt die -Firewall pauschal aufzuschieben. /16 bietet rechnerisch512 /25-Subnetze mit je128 -Adressen vor Reservierungen, nicht128 Projektnetze. Regional-Patches, Policies, -Operator-Zugaenge, Entfernung und Ausfuehrung bleiben ausserhalb dieses Vertrags. -Feldannahme ist kein Deployment, Durchsatznachweis oder oeffentliches IP-Failover. -Breite Firewall-Einrichtung zeigt vorhandene Entwurfswerte und fragt auch neben -einem HA-Vorschlag nach der naechsten unbeantworteten Verkehrs-, Kapazitaets- oder -Betriebsentscheidung. Gezielte Einzelfeldaenderungen bleiben ohne Fragebogen. -Antworten zu Verkehrsregeln und Kapazitaet setzen einen laufenden Firewall- -Einrichtungsauftrag fort, statt ihn in isolierte Beratung umzuwandeln. -Explizit unbekannte Kapazitaet bleibt als offener Sizing-/Benchmark-Punkt erhalten; -danach folgt die noch fehlende Unterbrechungs-/Betriebsentscheidung. Bereits -benannte Betreiber und bestaetigte Verkehrswege werden nicht erneut abgefragt. -Regelanforderungen werden zusammengefasst, nicht als konfigurierte Regeln -ausgegeben. Bestaetigungen verweisen auf tatsaechliche Nutzeraussagen; interne -Steuertexte werden nicht als Rueckfragen angezeigt. -Der native Accelerator verwaltet Regeln, Aliase, Routen und NAT ueber -`firewall_config`; der aktuelle Chat kann diese Policy weder definieren noch -als Vorschlag uebernehmen. Gefuehrte Editor-Policy-Bearbeitung und -Assistant-Regel-/NAT-Vorschlaege sind gemaess Benutzerentscheidung Post-MVP + + +## Start locally + + + +### Automated Assistant topic checks + +The [test catalogue](../docs/assistant-test-catalogue.json) assigns each +editor/Accelerator field to exactly one knowledge topic: type, optionality, +ownership, actual proposal mode and allowed patch path. +Regional DNS forms, protected values and components supported only in advisory mode +are not presented as proposals that can be accepted. Workflow topics without their own +fields are also included. Missing/duplicate assignments and drift fail +`npm run assistant:check` and the normal `npm run check`. + +The [synthetic chat cases](scripts/assistant-scenarios.ts) contain a fixed question for each +knowledge topic. Additional regressions check exact +foundations restoration, DNS contact priority including template placeholders, +domain/network preservation, complete SNA values and additive organization/folder roles +with saved or verified email sources. Unit tests also check that the +validators actually reject incorrect answers. New fields/topics require +review of the mapping and questions, then `npm run assistant:generate` and formatting +of the generated knowledge bundle. Regeneration alone is not domain evidence. + +The overview cases for foundations, governance, firewall policy and sandboxes +additionally check concrete native field names and important boundaries, not just a +topic reference. The intent classifier recognizes pure field overviews semantically; +for these four topics, the backend knowledge contract answers directly from the +field inventory and reviewed boundaries, without a second free-form model response. +This is a separate advisory path, not a substitute for a failed +model response. Explicit role requests also have a reviewed +draft path: intent determines the role, email source and explicit folder selection; +the backend contract maps these to additive fields without a second free-form model response. +Other requests, follow-up questions and proposals continue to use the +response model. All trusted system instructions are sent in a single +system message so serving chat templates do not lose earlier contracts. +Token-limit truncations remain explicit errors (`completion_truncated`), +without automatic retries or partial acceptance. SNA proposal texts and their +streaming show only checked values and never confirm that +persistence has already occurred. + +Firewall infrastructure and HA under `connectivity.firewall`/`firewalls` can be +proposed as individual draft fields. Native HA is an object with +`backup_zone`, not a checkbox/Boolean; other HA fields are individually selectable. +Existing single/map forms, area keys and unrequested values are preserved. +New appliances need name, zone, flavor and both confirmed available subnets +together; a new HA configuration needs its backup zone. Incomplete selection +is rejected without saving. Address containment, overlaps, node/VIP IPs +and distinct zones are validated. Unknown products or available +networks are not invented from project counts. Optional node/VIP IPs are limited in the +model contract to saved or user-confirmed addresses; +computed native defaults are preserved without unsolicited explicit IP changes. +For combined network/firewall +requests, a complete saved SNA is reused instead of +blanket deferral of the firewall. A /16 mathematically provides 512 /25 subnets with 128 +addresses each before reservations, not 128 project networks. Regional patches, policies, +operator access, removal and execution remain outside this contract. +Field acceptance is not deployment, throughput evidence or public IP failover. +Broad firewall setup shows existing draft values and, alongside +an HA proposal, asks about the next unanswered traffic, capacity or +operational decision. Targeted individual field changes remain free of questionnaires. +Answers about traffic rules and capacity continue an ongoing firewall +setup request instead of turning it into isolated advice. +Explicitly unknown capacity remains an open sizing/benchmark item; +the still missing interruption/operational decision follows next. Already +named operators and confirmed traffic paths are not asked about again. +Rule requirements are summarized, not presented as configured rules. +Confirmations refer to actual user statements; internal +control texts are not displayed as follow-up questions. +The native Accelerator manages rules, aliases, routes and NAT through +`firewall_config`; the current chat can neither define this policy nor +accept it as a proposal. Guided editor policy editing and +Assistant rule/NAT proposals are post-MVP by user decision ([#101](https://github.com/stackitcloud/stackit-landing-zone/issues/101)). -Im MVP pflegt der Firewall-Admin die Policy manuell in OPNsense. -Der gemeinsame Editor hat unter Betrieb / Firewall-Regeln bereits generische -native Felder, keine qualifizierte Policy-Verwaltung; sie bleiben erhalten. -Faehigkeits- und Definitionsanfragen erhalten die Grenze ausdruecklich, -ohne einen Regelvorschlag versprechende Rueckfragen. Infrastruktur/HA allein -garantiert weder Isolation noch Internetzugriff oder NAT. -Explizite Themenwechsel haben Vorrang vor alten Netzwerk-/Firewall-Merkmalen. -"Als naechstes Audit-Protokollierung einrichten" ist ein aktueller Auftrag, -keine Vertagung. Historische Netzwerkziele werden im anderen Thema nicht als -aktive Anforderungen weitergereicht; Belegpruefungen bleiben erhalten. -Audit Logging hat einen nativen Telemetry-Link/Router-/Logs-/Archiv-Vertrag -und generische Editorfelder unter Plattform. Der Chat verwendet jetzt denselben -nativen Eingabevertrag fuer uebernehmbare Audit-, Observability-, Federation-, -VPN-, DevOps-, Kubernetes-, Projekt-/Vorlagen- und Namespace-Vorschlaege. -Geschuetzte Bindings, Veroeffentlichung, Cloud-Ausfuehrung und Firewall-Policy -bleiben separate Workflows. Neue Audit-Konfigurationen benoetigen Retention, -ACL und die ausdrueckliche Object-Lock-Auswahl zusammen; mit Object Lock gilt -der Bereich 1-365 Tage. Es wird keine Einrichtung oder Ereigniszustellung behauptet. - -Editor-Vorschlaege nutzen `merge` fuer partielle Objekt-/Map-Aenderungen, -`replace` fuer einen atomar geprueften vollstaendigen Ersatz und `default` -zum Entfernen eines optionalen Overrides. Listen bleiben atomar. -Ausgelassene Merge-Felder und bestehende Ressourcenkennungen bleiben erhalten. -Plattform-Entwuerfe bearbeiten Projektvorlagen nach stabilen Schluesseln; -Vorlagenkennungen entstehen serverseitig, nicht im Modell. Neue/entfernte -Vorlagen, Einstellungen und Parameterregeln bleiben lokale Entwurfsaenderungen. -Feldabdeckung und echte Compiler-/Export-/Identitaetspruefungen liegen in +In the MVP, the firewall administrator maintains policy manually in OPNsense. +The common editor already has generic native fields under Operations / Firewall rules, +not qualified policy management; these are preserved. +Capability and definition requests receive the boundary explicitly, +without follow-up questions promising a rule proposal. Infrastructure/HA alone +guarantees neither isolation nor Internet access or NAT. +Explicit topic changes take precedence over old network/firewall characteristics. +"Set up audit logging next" is a current request, +not a deferral. Historical network goals are not carried into another topic as +active requirements; evidence checks remain. +Audit logging has a native telemetry link/router/logs/archive contract +and generic editor fields under Platform. Chat now uses the same +native input contract for acceptable audit, observability, federation, +VPN, DevOps, Kubernetes, project/template and namespace proposals. +Protected bindings, publication, cloud execution and firewall policy +remain separate workflows. New audit configurations require retention, +ACL and explicit Object Lock selection together; with Object Lock, the +range is 1–365 days. No setup or event delivery is claimed. + +Editor proposals use `merge` for partial object/map changes, +`replace` for an atomically checked complete replacement and `default` +to remove an optional override. Lists remain atomic. +Omitted merge fields and existing resource identifiers are preserved. +Platform drafts edit project templates by stable keys; +template identifiers are created server-side, not in the model. New/removed +templates, settings and parameter rules remain local draft changes. +Field coverage and real compiler/export/identity checks are in [assistant-editor.test.ts](tests/assistant-editor.test.ts). -Abgelehnte Modellantworten liefern eine sichere Fehlerkategorie und -Diagnosekennung, keine Rohantworten oder Zugangsdaten. Konfigurations-Chat und -Template-Beratung zeigen lokalisierte Ursachen und naechste Schritte; Nachricht -und Antwortauswahl bleiben erhalten. HTTP und Antwortstreams nutzen denselben -Fehlervertrag. Es gibt keine automatische Wiederholung oder Teiluebernahme. -Chat und Feldannahme funktionieren auch mit ungespeicherten Editoraenderungen. -Der Chat erhaelt nur die freigegebenen Werte des aktuellen lokalen Entwurfs. -Rueckfragen im Konfigurations-Chat und in der Template-Beratung werden mit -`Antwort senden` direkt abgeschickt, ohne einen separaten Vorbereitungsschritt. -Vorhandener Text im Nachrichtenfeld wird mitgesendet. Bei einem Fehler bleiben -Text und Antwortauswahl fuer einen erneuten Versuch erhalten. -Vorschlaege werden ausschliesslich in den lokalen Entwurf uebernommen; Speichern -bleibt separat. Ein Drei-Wege-Abgleich bewahrt unabhaengige lokale und gespeicherte -Aenderungen. Nur echte Konflikte benoetigen eine ausdrueckliche Bestaetigung; -eine andere Revision allein sperrt die Uebernahme nicht. Aeltere Vorschlaege ohne -nachweisbaren Ausgangswert benoetigen eine Wertepruefung. Migration057 speichert -nur freigegebene Vorschlags-Ausgangswerte, keine vollstaendigen Entwuerfe/Secrets. -Die Vorschau veraendert weder die Konfiguration noch das gespeicherte Gespraech. -Ohne `draft`/`savedDraft` behaelt der API-Annahmepfad sein bisheriges transaktionales -Speicherverhalten und seine strikte Revisionspruefung. - -`organization_owners` und `organization_auditors` sowie -`rm_folders[*].owner_emails`/`reader_emails` sind bei explizitem Rollenauftrag -einzeln uebernehmbare Vorschlagsfelder. Bekannte E-Mails werden nur aus der -angefragten Quelle verwendet; Template-Platzhalter, Entwicklerlogin und -Service Account ersetzen keine verifizierte menschliche Anmeldung. Unbekannte -E-Mail oder nicht benannte Folder bleiben Rueckfragen. Bestehende Zuweisungen -werden nicht entfernt und Namensdelegation erlaubt keine Rollenaenderung. -Organisation-Owner deckt die Folder bereits ab; der native Accelerator vermeidet -doppelte Folder-Zuweisungen. Reader werden nativ als `auditor` zugewiesen. -Uebernahme speichert nur Konfiguration, nicht STACKIT-IAM oder Configurator-Rollen; -IAM-Aenderungen bleiben an geprueften Plan und separate Apply-Freigabe gebunden. +Rejected model responses provide a safe error category and +diagnostic identifier, not raw responses or credentials. Configuration chat and +template advice show localized causes and next steps; the message +and answer selection are preserved. HTTP and response streams use the same +error contract. There are no automatic retries or partial acceptance. +Chat and field acceptance also work with unsaved editor changes. +Chat receives only the approved values of the current local draft. +Follow-up answers in configuration chat and template advice are sent directly with +`Send answer`, without a separate preparation step. +Existing text in the message field is sent along. On error, +text and answer selection are preserved for another attempt. +Proposals are accepted only into the local draft; saving +remains separate. A three-way comparison preserves independent local and saved +changes. Only real conflicts require explicit confirmation; +a different revision alone does not block acceptance. Older proposals without +a demonstrable original value require value review. Migration057 stores +only approved proposal baseline values, not complete drafts/secrets. +The preview changes neither configuration nor saved conversation. +Without `draft`/`savedDraft`, the API acceptance path retains its previous transactional +persistence behavior and strict revision check. + +`organization_owners` and `organization_auditors`, as well as +`rm_folders[*].owner_emails`/`reader_emails`, are individually acceptable proposal fields +for explicit role requests. Known emails are used only from the +requested source; template placeholders, developer login and +service accounts do not replace verified human login. An unknown +email or unspecified folders remain follow-up questions. Existing assignments +are not removed, and name delegation does not permit role changes. +Organization owner already covers the folders; the native Accelerator avoids +duplicate folder assignments. Readers are assigned natively as `auditor`. +Acceptance saves only configuration, not STACKIT IAM or Configurator roles; +IAM changes remain bound to a reviewed Plan and separate Apply approval. ```sh # Ohne Credentials: Inventar, Wissensfrische und Testfragen pruefen @@ -166,85 +176,87 @@ LZC_MODEL_SERVING_MODEL=openai/gpt-oss-120b \ npm run test:assistant:journey -- --local-credentials ``` -Der Journey-Test durchlaeuft zwoelf Schritte von Grundlagen und Rollen ueber -SNA/Firewall, den Policy-MVP-Hinweis und Audit-Rueckfragen bis Observability, -DevOps, Kubernetes und Labels. Jeder Schritt nutzt denselben fortgeschriebenen -Entwurf und die tatsaechliche Gespraechshistorie. Fachlich passende Vorschlaege -werden im Speicher uebernommen, per JSON-Roundtrip geprueft und abschliessend als -tfvars exportiert. Fehlerhafte Vorschlaege werden nicht uebernommen; abgelehnte -Modell-/Anwendungsergebnisse werden wie im API-Service nicht als erfolgreiche -Gespraechsantwort gespeichert. Modellnamen, Wissens-/Journey-Hashes, -Einzelergebnisse und Antwortzeiten werden ausgegeben. Dies ersetzt keine -Browser-, PostgreSQL- oder Cloud-Ausfuehrungspruefung. Beide Live-Runner sperren -aktivierte Ausfuehrungsflags; sie aendern weder die laufende Modellauswahl noch -Kundenkonfigurationen und verwenden keine automatischen Wiederholungen. - -Beide Runner lassen zwischen tatsaechlichen Serving-Requests mindestens 2500 ms -Abstand, auch zwischen Intent und Antwort desselben Schritts. Diese Begrenzung -gilt nur fuer die Tests, nicht fuer den produktiven Assistant. Ausgegebene -Antwortzeiten enthalten die Wartezeit und sind deshalb nicht direkt mit -Messungen ohne diese Begrenzung vergleichbar. Quotenfehler bleiben sichtbare Fehler; -sie werden nicht durch automatische Wiederholungen verdeckt. - -#### Weitere Assistant-Komponenten ergaenzen - -1. Zuerst den nativen Input-Typ und den manuellen Editor-/Compiler-Pfad pruefen. - Der Assistant leitet Pfade, Werte und Pflichtfelder aus demselben Inventar ab; - keine zweite, handgeschriebene Komponentenstruktur oder freien HCL-Patches. -2. Einen geprueften Wissenstopic mit nativen Inputs, Feldpfaden, Quellen und - Abhaengigkeiten hinterlegen. Intent und Rueckfragen werden darauf begrenzt. -3. Nur fachliche Anforderungen ueber den nativen Typ hinaus in - `assistantEditorPolicies` ergaenzen, beispielsweise ausdrueckliche - Audit-Erstellungsentscheidungen und Freitext statt erfundener ACL-Auswahlwerte. - Policy-Feldpfade muessen im nativen Inventar existieren. -4. Erstellung und Aktualisierung getrennt pruefen: neue Objekte verwenden - typisierte Konstruktor-Slots fuer einfache Skalare und Listen; optionale - Null-Slots bedeuten native Defaults und werden nur bei Erstellung ohne - vorherigen Wert ausgelassen. Komplexe optionale Collections bleiben optional; - etwa sind leere Audit-Link-Scopes kein Organisationsdefault. - Bestehende Objekte werden partiell geaendert, neue Map-Eintraege brauchen native - Pflichtfelder. Ersetzen und Default-Reset bleiben explizite, atomare Operationen. -5. Tests fuer reale Uebernahme, Geschwistererhalt, Identitaeten, Quellenbindung, - fehlende Entscheidungen, Themenwechsel und DE/EN hinzufuegen. Auch eine vom - Serving akzeptierte Antwort wird gegen den angebotenen Schema-Vertrag und - anschliessend gegen die unveraenderte native Laufzeitvalidierung geprueft. -6. Nach Wissensgenerierung erst gezielte Offline-/Modellfaelle, dann den seriellen - Journey- und vollstaendigen Szenarienlauf qualifizieren. Hashes und verbleibende - Fehler dokumentieren; kein Modell-/API-Rollout allein aufgrund gruener Mocks. - -Vorschlagstexte mit Aenderungen werden serverseitig als lokale Entwurfsvorschlaege -formuliert, nicht als vom Modell behauptete Speicherung oder Berechtigungsvergabe. -Firewall-Policy, Credentials, Organisationsbindung, Publikation und Ausfuehrung -bleiben getrennte, geschuetzte Workflows. - -Der Live-Test verwendet die echte Assistant-Orchestrierung, Intentklassifikation, -Wissensauswahl, Antwortvalidierung und den lokalen Compiler, aber ausschliesslich -synthetische Konfigurationen im Speicher. Kein Browser, Benutzer-SSO oder Zugriff -auf Kundengespraeche/-datenbanken; keine automatische Annahme und kein Cloud-Auftrag. -Die HTTP-/Session-/Transaktionspfade bleiben durch Unit-/Datenbanktests abgedeckt. -Der Lauf meldet pro Fall Antwort, Fehlercodes, Laufzeit und abschliessend -Modell-/Wissensversion und Zaehler; jeder Fehler ergibt Exitcode 1. Fehlende Zugriffe -werden nicht uebersprungen. Live-Aufrufe verursachen Model-Serving-Kosten. -Themen-Smokes pruefen Referenz, gueltigen Antwortvertrag und Beratungsmodus, nicht -automatisch die fachliche Richtigkeit jeder Textaussage oder jedes einzelnen Feldes. -Ein gruener Smoke ist keine vollstaendige Komponenten-/Cloud-Qualifikation. - -Ohne `--local-credentials` wird `LZC_MODEL_SERVING_TOKEN` aus der Prozessumgebung -erwartet. Lokal liest der gemeinsame sichere Loader den bereits vorhandenen -verschluesselten State mit Originalschluessel; private Dateien muessen dem aktuellen -Benutzer gehoeren und duerfen keine Gruppen-/Weltrechte haben. Token/Schluessel werden -nicht ausgegeben oder in Tests/Reports geschrieben. Keine neuen Credentials im Git, -keine Rotation bestehender Schluessel und keine SSO-Automatisierung. - -Der manuell ausloesbare [GitHub-Workflow](../../.github/workflows/assistant-live.yml) -verwendet die Umgebung `assistant-tests`. Dort `LZC_MODEL_SERVING_TOKEN` als -Environment-Secret mit Freigabe-/Branchschutz hinterlegen; keine Tokens in Chat, -Workflow-Dateien oder Kommandozeilen schreiben. Normale PR-Checks bleiben offline -und benoetigen keine Cloud-Secrets. Ein Service-Account fuer spaetere lesende -Produktkatalogtests muss separat mit minimalen Rechten und Testprojekt eingerichtet -werden; er ersetzt keine menschliche Identitaet fuer Benutzer-/SSO-Rechtepruefungen. - -Zwei Terminals im App-Verzeichnis: +The journey test goes through twelve steps from foundations and roles through +SNA/firewall, the policy MVP notice and audit follow-up questions to observability, +DevOps, Kubernetes and labels. Every step uses the same evolving +draft and actual conversation history. Domain-appropriate proposals +are accepted in memory, checked by JSON roundtrip and finally exported as +tfvars. Incorrect proposals are not accepted; rejected +model/application results, as in the API service, are not stored as successful +conversation responses. Model names, knowledge/journey hashes, +individual results and response times are output. This does not replace +browser, PostgreSQL or cloud execution checks. Both live runners block +enabled execution flags; they change neither the running model selection nor +customer configurations and use no automatic retries. + +Both runners leave at least 2500 ms between actual serving requests, +including between intent and response in the same step. This limit +applies only to tests, not to the production Assistant. Reported +response times include the wait and therefore are not directly comparable with +measurements without this limit. Quota errors remain visible failures; +they are not hidden by automatic retries. + + + +#### Add further Assistant components + +1. First check the native input type and the manual editor/compiler path. + The Assistant derives paths, values and required fields from the same inventory; + no second, handwritten component structure or free-form HCL patches. +2. Add a reviewed knowledge topic with native inputs, field paths, sources and + dependencies. Intent and follow-up questions are restricted to it. +3. Add only domain requirements beyond the native type to + `assistantEditorPolicies`, for example explicit + audit creation decisions and free text instead of invented ACL choices. + Policy field paths must exist in the native inventory. +4. Check creation and updates separately: new objects use + typed constructor slots for simple scalars and lists; optional + null slots mean native defaults and are omitted only during creation without + a previous value. Complex optional collections remain optional; + for example, empty audit link scopes are not an organization default. + Existing objects are changed partially; new map entries need native + required fields. Replacement and default reset remain explicit, atomic operations. +5. Add tests for real acceptance, sibling preservation, identities, source binding, + missing decisions, topic changes and DE/EN. Even a response accepted by + serving is checked against the offered schema contract and + then against unchanged native runtime validation. +6. After knowledge generation, first qualify targeted offline/model cases, then the serial + journey and complete scenario run. Document hashes and remaining + failures; no model/API rollout based only on green mocks. + +Proposal texts containing changes are formulated server-side as local draft proposals, +not as model claims of persistence or permission assignment. +Firewall policy, credentials, organization binding, publication and execution +remain separate, protected workflows. + +The live test uses real Assistant orchestration, intent classification, +knowledge selection, response validation and the local compiler, but only +synthetic configurations in memory. No browser, user SSO or access +to customer conversations/databases; no automatic acceptance and no cloud job. +The HTTP/session/transaction paths remain covered by unit/database tests. +The run reports each case's response, error codes, duration and finally +model/knowledge version and counts; every failure produces exit code 1. Missing access +is not skipped. Live calls incur Model Serving costs. +Topic smokes check reference, valid response contract and advisory mode, not +automatically the factual correctness of every textual statement or individual field. +A green smoke is not complete component/cloud qualification. + +Without `--local-credentials`, `LZC_MODEL_SERVING_TOKEN` is expected from the process +environment. Locally, the shared secure loader reads the existing +encrypted state with the original key; private files must belong to the current +user and have no group/world permissions. Tokens/keys are +not output or written to tests/reports. No new credentials in Git, +no rotation of existing keys and no SSO automation. + +The manually triggerable [GitHub workflow](../../.github/workflows/assistant-live.yml) +uses the `assistant-tests` environment. Store `LZC_MODEL_SERVING_TOKEN` there as an +environment secret with approval/branch protection; write no tokens in chat, +workflow files or command lines. Normal PR checks remain offline +and need no cloud secrets. A service account for future read-only +product catalogue tests must be set up separately with minimal permissions and a test project; +it does not replace a human identity for user/SSO permission checks. + +Two terminals in the app directory: ```sh # Terminal 1: API auf http://127.0.0.1:3000 @@ -256,17 +268,19 @@ npm run dev npm run dev:web ``` -Auch diese Befehle können bei abweichender lokaler Node-Version mit dem oben gezeigten `npm exec`-Präfix ausgeführt werden. Der Vite-Entwicklungsserver leitet `/healthz`, `/auth` und `/api` an die lokale API weiter. Gemeinsame Pakete vor UI-Start bauen (`npm run build:packages`, bereits Teil von `npm run dev`). Nach Änderungen an gemeinsamen Paketen erneut bauen; automatischer Workspace-Watch folgt später. +These commands can also be run with the `npm exec` prefix shown above if the local Node version differs. The Vite development server forwards `/healthz`, `/auth` and `/api` to the local API. Build shared packages before starting the UI (`npm run build:packages`, already part of `npm run dev`). Rebuild after changes to shared packages; automatic workspace watching will follow later. -### Ubuntu-Workstation mit Entwicklerlogin und HTTPS + -Dieser separate Starter ist fuer die persoenliche Ubuntu-Entwicklung ohne -registrierten OIDC-Webclient gedacht, **nicht** fuer Cloud Foundry oder Produktion. -Er akzeptiert ausschliesslich eine kanonische HTTPS-Origin, aktiviert keinen -STACKIT-CLI-Callback und erstellt einen eigenen persoenlichen Arbeitsbereich. -Er behauptet keine verifizierte STACKIT-Benutzeridentitaet und vergibt keine -organisationsbezogenen Produktrollen. Bestehende Arbeitsbereiche, Entwuerfe und -Chats werden weder uebernommen noch veraendert. +### Ubuntu workstation with developer login and HTTPS + +This separate launcher is intended for personal Ubuntu development without +a registered OIDC Web client, **not** for Cloud Foundry or production. +It accepts only a canonical HTTPS origin, enables no +STACKIT CLI callback and creates its own personal workspace. +It claims no verified STACKIT user identity and grants no +organization-related product roles. Existing workspaces, drafts and +chats are neither adopted nor changed. ```sh npm run build @@ -277,49 +291,49 @@ LZC_DEVELOPMENT_ORIGIN=https://work.lukas.runs.onstackit.cloud:4181 \ --organization ORGANISATION_UUID ``` -Ohne `--execution` bleiben Plan/Apply deaktiviert. Mit dem Schalter ist der -vorhandene native Plattform-Runner verfuegbar; es startet **kein** Cloud-Job. -Preparation, Plan, State-Zuordnung und Apply-Freigabe behalten ihre bestehenden -Pruefungen. Der separate Application-Runner bleibt unabhaengig deaktiviert. -GitHub-Verknuepfung und SSO-abhaengige Organisation-Funktionen sind in diesem -Modus nicht verfuegbar. - -Der einmalige Benutzername ist `developer`. Das zufaellige initiale Passwort -steht ausschliesslich in der privaten lokalen Datei -`../.local/development/initial-password` (0600), nicht in Logs oder Antworten. -Nach sicherer Uebernahme in einen Passwortmanager kann diese Datei geloescht -werden. `../.local/development/account.json` enthaelt den gesalzenen scrypt-Hash -und die dauerhafte Dev-Principal-ID; diese Datei behalten und nicht einchecken. -Login, Logout und API-Mutationen verwenden weiterhin Secure/HttpOnly-Cookies, -die exakte HTTPS-Origin, CSRF-Token und bestehende Tenant/RLS-Pruefungen. -Es gelten maximal zehn Login-Versuche pro 15 Minuten und API-Instanz. - -`--service-account-file` akzeptiert nur eine kleine, regulaere, nicht verlinkte -Datei des aktuellen Benutzers ohne Gruppen-/Weltrechte. Der Schluessel wird -idempotent als eigenes Credential-Profil im bestehenden verschluesselten -Secret Store gespeichert; keine Zuordnung zu einem vorhandenen Benutzer. -`--organization` prueft ausschliesslich den technischen Org-Lesezugriff; es -ist **kein** menschlicher Organisationsnachweis. Dieser explizite Import kann -bei spaeteren Starts entfallen. Keine Secrets in Shell-Argumenten uebergeben. - -Fuer die TLS-Auslieferung Caddy installieren und separat starten: +Without `--execution`, Plan/Apply remain disabled. With the switch, +the existing native platform Runner is available; **no** cloud job starts. +Preparation, Plan, state mapping and Apply approval retain their existing +checks. The separate application Runner remains independently disabled. +GitHub linking and SSO-dependent organization functions are unavailable +in this mode. + +The initial username is `developer`. The random initial password +is available only in the private local file +`../.local/development/initial-password` (0600), not in logs or responses. +After securely transferring it to a password manager, this file may be deleted. +`../.local/development/account.json` contains the salted scrypt hash +and durable Dev principal ID; keep this file and do not check it in. +Login, logout and API mutations continue to use Secure/HttpOnly cookies, +the exact HTTPS origin, CSRF tokens and existing tenant/RLS checks. +A maximum of ten login attempts per 15 minutes and API instance applies. + +`--service-account-file` accepts only a small, regular, non-linked +file owned by the current user without group/world permissions. The key is +stored idempotently as its own credential profile in the existing encrypted +secret store; no mapping to an existing user. +`--organization` checks only technical organization read access; it +is **not** evidence of human organization membership. This explicit import may +be omitted on later starts. Do not pass secrets in shell arguments. + +Install Caddy for TLS delivery and start it separately: ```sh sudo caddy run --config "$PWD/scripts/workstation.Caddyfile" --adapter caddyfile ``` -Die API samt gebautem UI bleibt auf `127.0.0.1:3000`; ein eigener Vite-Preview -auf Port 4181 darf nicht parallel laufen. Caddy liefert die Anwendung unter -`https://work.lukas.runs.onstackit.cloud:4181/` aus. TCP 4181 muss fuer den Browser, -TCP 80 fuer oeffentliche ACME-HTTP-Pruefungen und spaetere Erneuerungen erreichbar -sein. Port 80 liefert nur Challenge/HTTPS-Weiterleitung. Bei anderem Host -`LZC_DEVELOPMENT_HOST` fuer Caddy und die dazu passende `LZC_DEVELOPMENT_ORIGIN` -fuer die API setzen; der HTTPS-Port dieses Caddy-Beispiels ist 4181. -Kein selbstsigniertes Zertifikat und kein unsicherer HTTP-Login-Fallback. -Die Prozesse laufen nur waehrend ihrer gestarteten Sitzung; es wird kein -Autostart-Service fuer diese Entwicklung eingerichtet. +The API and built UI remain on `127.0.0.1:3000`; a separate Vite preview +on port 4181 must not run in parallel. Caddy serves the application at +`https://work.lukas.runs.onstackit.cloud:4181/`. TCP 4181 must be reachable by the browser, +TCP 80 for public ACME HTTP checks and later renewals. +Port 80 serves only challenges/HTTPS redirects. For another host, +set `LZC_DEVELOPMENT_HOST` for Caddy and the corresponding `LZC_DEVELOPMENT_ORIGIN` +for the API; the HTTPS port in this Caddy example is 4181. +No self-signed certificate and no insecure HTTP login fallback. +The processes run only during the session in which they were started; no +autostart service is configured for this development setup. -Gezielte Pruefungen: +Targeted checks: ```sh npx vitest run tests/development-login.test.ts tests/auth-routes.test.ts @@ -329,70 +343,76 @@ LZC_TEST_DATABASE_URL=postgres://.../configurator_test \ npx playwright test e2e/development-login.spec.ts ``` -### Lokaler STACKIT-Login + + +### Local STACKIT login -Nach ausdrücklicher Freigabe der CLI-Client-Nutzung kann der echte Login ohne -Dev-Datenbank und Secrets-Manager-Zugang lokal gestartet werden. Docker muss laufen: +After explicit approval to use the CLI client, real login can be +started locally without Dev database or Secrets Manager access. Docker must be running: ```sh LZC_STACKIT_CLI_CLIENT_APPROVED=true npm run dev:login ``` -Das Backend läuft ausschließlich auf `127.0.0.1:3000`; die zugehörige gebaute -UI-Vorschau muss auf `http://127.0.0.1:4181` laufen. Der Starter legt den eigenen -Docker-Container `lzc-local-stackit-login` mit PostgreSQL 17 an, bindet dessen Port -nur an Loopback und wendet die bestehenden Migrationen an. Zufällige -Datenbankpasswörter werden nicht ausgegeben; die Runtime verwendet weiterhin -`configurator_app`, nicht die Migrationsidentität. Die lokale Datenbank bleibt -bei einem API-Neustart erhalten; der Starter löscht keine Nutzer oder Entwürfe. - -STACKIT-Identitätsprüfung, Sessions, Credential-Profile und Produktkataloge sind echt. -Technische STACKIT-Abfragen verwenden den im aktiven Tenant gespeicherten Service -Account. Platform Engineers können Zugänge auch in Organisationstenants verwalten; -Profile bleiben an Tenant und Besitzer gebunden. Im persönlichen Tenant wird ein -zugängliches aktives Referenzprojekt automatisch ermittelt, im Organisationstenant -wird die Suche auf dessen Organisation begrenzt. - -Nur im lokalen Starter ersetzt eine AES-256-GCM-Ablage den Secrets Manager. -Schlüsseldateien sind unter `../.local/credential-secrets/` verschlüsselt; das -separate lokale Verschlüsselungsgeheimnis `master.key` und der Ordner sind nur für -den Betriebssystembenutzer zugänglich. Das ist kein Ersatz für einen produktiven -Secrets Manager: Wer auf Ordner und Verschlüsselungsgeheimnis zugreifen kann, -kann die Daten entschlüsseln. Den Ordner nicht teilen oder ins Repository aufnehmen. -Er bleibt wie die Datenbank über Neustarts erhalten. - -`dev:login` aktiviert keinen Runner und übernimmt keine Dev-Daten. Mit einem -vorbereiteten nativen Paket aktiviert `dev:execution` lokale Plattform-Plans und -den ausdrücklich freizugebenden Apply-Pfad. Organisations-Platform-Engineers -verwenden weiterhin private, tenantgebundene Vorbereitungen und Zugänge. -HTTP wird ausschließlich für ausdrücklich aktivierte, kanonische Loopback- -Ursprünge erlaubt; Produktionskonfigurationen verlangen unverändert HTTPS. -Ein bloßes `vite preview` ohne dieses Backend kann keine Anmeldung durchführen. - -### Recovery-Pruefbelege - -Nach Anwendung der Migrationen 051 und 052 kann der separate Opt-in -`LZC_APPLICATION_RECOVERY_REVIEWS_ENABLED=true` Recovery-Pruefbelege aktivieren. -Default ist deaktiviert. Der lokale Login-Starter wendet beim naechsten Start -die vorhandenen neuen Migrationen an; ein Neustart ist deshalb ein kontrollierter -Migrationsschritt, auch wenn native Runner ausgeschaltet bleiben. - -Die Aktion ist auf den urspruenglich freigebenden Platform Engineer mit aktueller -Session und gueltiger menschlicher STACKIT-Identitaet beschraenkt. Sie protokolliert -nur die ausdrueckliche Pruefung des gebundenen Diagnose-Stands. Sie aendert keinen -Jobstatus und hebt keine State-/Recovery-Sperre auf. Ohne neue Migration muss der -Opt-in ausgeschaltet bleiben. Der gehostete Start prueft bei Opt-in die Tabelle -und die neue Abgleichsfunktion aus Migration 052. Der lesende Pruefkontext zeigt -gespeicherte Runner-ID, Report-Hashes, Ticket-Fenster und Grant-/Delegationswiderruf. -Startunsicherheit, fehlender Abschluss und gespeicherter Recovery-State bleiben -unterschiedliche Feststellungen. Ticket-Ablauf oder Delegationswiderruf belegen -weder Runner-Stillstand noch Widerruf bereits ausgegebener Cloud-Credentials. -Cloud-Abgleich, Runner-Stillstand, State-Wiederherstellung und Ausfuehrungsfreigabe -bleiben separate Vorgänge mit eigenen Nachweisen und Freigaben. - -### Lokale Plan-/Apply-Ausführung - -Mit Node 24.21.0, npm 11.19.0 und checksum-geprüftem OpenTofu 1.12.6 im `PATH`: +The backend runs exclusively on `127.0.0.1:3000`; the associated built +UI preview must run at `http://127.0.0.1:4181`. The launcher creates its own +Docker container `lzc-local-stackit-login` with PostgreSQL 17, binds its port +only to loopback and applies the existing migrations. Random +database passwords are not output; the runtime continues to use +`configurator_app`, not the migration identity. The local database survives +an API restart; the launcher deletes no users or drafts. + +STACKIT identity verification, sessions, credential profiles and product catalogues are real. +Technical STACKIT queries use the service account stored in the active tenant. +Platform Engineers can also manage credentials in organization tenants; +profiles remain bound to tenant and owner. In the personal tenant, an +accessible active reference project is determined automatically; in an organization tenant, +the search is restricted to that organization. + +Only in the local launcher does AES-256-GCM storage replace Secrets Manager. +Key files are encrypted under `../.local/credential-secrets/`; the +separate local encryption secret `master.key` and the directory are accessible only +to the operating system user. This is no substitute for a production +Secrets Manager: anyone with access to the directory and encryption secret +can decrypt the data. Do not share the directory or add it to the repository. +Like the database, it survives restarts. + +`dev:login` enables no Runner and adopts no Dev data. With a +prepared native package, `dev:execution` enables local platform Plans and +the Apply path requiring explicit approval. Organization Platform Engineers +continue to use private, tenant-bound preparations and credentials. +HTTP is permitted only for explicitly enabled, canonical loopback +origins; production configurations continue to require HTTPS. +A mere `vite preview` without this backend cannot perform login. + + + +### Recovery review evidence + +After applying migrations 051 and 052, the separate opt-in +`LZC_APPLICATION_RECOVERY_REVIEWS_ENABLED=true` can enable recovery review evidence. +The default is disabled. On its next start, the local login launcher applies +the existing new migrations; a restart is therefore a controlled +migration step, even if native Runners remain switched off. + +The action is restricted to the originally approving Platform Engineer with a current +session and valid human STACKIT identity. It records +only the explicit review of the bound diagnostic state. It changes no +job status and lifts no state/recovery block. Without the new migration, +the opt-in must remain off. When opted in, hosted startup checks the table +and the new reconciliation function from migration 052. The read-only review context shows +the stored Runner ID, report hashes, ticket window and grant/delegation revocation. +Start uncertainty, missing completion and stored recovery state remain +distinct findings. Ticket expiry or delegation revocation proves +neither Runner termination nor revocation of cloud credentials already issued. +Cloud reconciliation, Runner termination, state recovery and execution approval +remain separate operations with their own evidence and approvals. + + + +### Local Plan/Apply execution + +With Node 24.21.0, npm 11.19.0 and checksum-verified OpenTofu 1.12.6 in `PATH`: ```sh npm run build @@ -400,193 +420,201 @@ LZC_LOCAL_RUNNER_PACKAGE=true bash ../deploy/runner/package.sh LZC_STACKIT_CLI_CLIENT_APPROVED=true npm run dev:execution ``` -Die Paketierung verlangt ein neues Zielverzeichnis und überschreibt kein -bestehendes Paket. `LZC_RUNNER_PACKAGE_DIR` kann ein anderes geprüftes Paket -angeben. Der native Modus ist ausschließlich für die lokale Entwicklung gedacht, -nicht als Ersatz für die produktive CF-Isolation. Jobs laufen mit minimaler -Umgebung unter `~/.local/share/landing-zone-configurator/runner-jobs`, außerhalb -des Workspace; Paketinhalt und Laufzeit sind an den gespeicherten Plan gebunden. -Nach einem API-Absturz werden unklar laufende Jobs nicht automatisch wiederholt -oder über fremde Prozess-IDs beendet. Recovery-Dateien verhindern Cleanup. - -Der native Worker erzeugt seine CLI-Konfiguration mit dem Paket-Mirror-Pfad und -verwendet fuer Provider-Sockets ein kurzes privates Temp-Verzeichnis, das beim -Cleanup entfernt wird. Init erlaubt Provider-Dateien bis 256 MiB; andere Phasen -behalten das Limit von 64 MiB. Der echte Paket-Init/Validate-Test stoppt vor Plan -und verwendet weder Kunden-Credentials noch Kunden-State: +Packaging requires a new target directory and overwrites no +existing package. `LZC_RUNNER_PACKAGE_DIR` may point to another checked package. +Native mode is intended exclusively for local development, +not as a replacement for production CF isolation. Jobs run with a minimal +environment under `~/.local/share/landing-zone-configurator/runner-jobs`, outside +the workspace; package contents and runtime are bound to the saved Plan. +After an API crash, jobs with uncertain running status are not automatically retried +or terminated through unrelated process IDs. Recovery files prevent cleanup. + +The native worker creates its CLI configuration with the package mirror path and +uses a short private temporary directory for provider sockets, removed during +cleanup. Init permits provider files up to 256 MiB; other phases +retain the 64 MiB limit. The real package init/validate test stops before Plan +and uses neither customer credentials nor customer state: ```sh LZC_NATIVE_RUNNER_TEST=true LZC_RUNNER_PACKAGE_DIR=../.local/runner-local-20261003-mirror-init npm exec -- vitest run tests/platform-worker.test.ts -t 'real native providers' ``` -Unter **OpenTofu-Ausgabe** zeigen Plattformauftraege auch in Cloud Foundry -Live-Fortschritt ueber einen authentifizierten NDJSON-Kanal. Der Worker liest -vollstaendige Zeilen alle 500 ms; nur geaenderter, redigierter Text wird -verschluesselt gesichert und weitergegeben. Der Plan liefert native -OpenTofu-UI-Ereignisse, bevor der fertige Diff verfuegbar ist; rohe Ereignisobjekte -und deren Output-Daten werden nicht an den Browser gegeben. **Ausgabe folgen** laesst sich zum Pruefen aelterer -Zeilen anhalten. Einklappen und Navigation trennen die Verbindung; erneutes -Oeffnen setzt beim aktuellen Mitschnitt fort. JSON-Snapshots bleiben kompatibel. -Erfolgreiche Plattform-Plans werden -read-only mittels `tofu show -no-color` aus dem unveraenderten gespeicherten -Artefakt dargestellt, einschliesslich Ressourcen und Attributaenderungen. -OpenTofu maskiert sensitive Werte wie in der CLI. Die separate Ausgabe-Route -verlangt Sitzung, Deployment-Rolle und private Eigentuemer-/Tenant-Zuordnung; -rohes Plan-Binary oder `show -json` werden nicht an den Browser geliefert. -Jeder Plan bleibt an sein unveraenderliches Runner-Paket gebunden. Ein Paketwechsel -erfordert einen neuen Plan und dessen ausdrueckliche Freigabe. -Laufende Apply-Ausgaben werden ebenfalls aktualisiert. Vor dem terminalen Ergebnis -sichert der Worker den letzten redigierten CLI-Text verschluesselt beim Broker; -er bleibt nach Cleanup und Reload unter derselben privaten Zugriffskontrolle lesbar. -**Apply-Nachweise** zeigen Plan-ID, SHA-256, Zielorganisation, State-Backend des -Auftrags und Abschlusszeit. Die bestehende exakte Organisationsbestaetigung und -gegebenenfalls destruktive Freigabe bleiben erforderlich; kein automatischer Retry. -Ausgaben sind auf 2 MiB begrenzt; eine Kuerzung wird angezeigt. Die Sicherung ist -best-effort: bei hartem Prozessabbruch oder fehlgeschlagenem Upload ist ein -vollstaendiger historischer Mitschnitt nicht garantiert. Bereits gesicherter -Text benoetigt keinen laufenden nativen Runner. Waehrend des Streams werden -Sitzung, Tenant, Rolle und Eigentuemerschaft erneut geprueft. Verbindungen werden -spaetestens nach 35 Sekunden beendet und bei aktivem Auftrag neu geoeffnet; -Backpressure, Byte-Limit und hoechstens acht Streams pro Eigentuemer/Tenant und -API-Instanz begrenzen die Ressourcen. Details: [Plan-Ausfuehrung](../docs/plan-execution.md). - -Für neue Plattformen ist **Accelerator-Standard · Management-S3** der Default. -Der ausgewählte Service Account führt den freigegebenen Bootstrap-Apply aus; -Terraform verwaltet Management-Projekt, `*-tfstate`-Bucket, S3-Zugang und dessen -Management-Secrets-Manager-Eintrag. Anschließend verifiziert der Broker die -Migration zu `terraform.tfstate` in eu01. Es sind keine manuellen S3-Keys nötig. -**Bestehendes S3-Backend registrieren** bleibt die optionale Bestandsanbindung. -Der Bucket wird nicht außerhalb des Terraform-State vorab angelegt. Plan und -Apply starten nur über ihre jeweiligen ausdrücklichen Aktionen in der UI. - -`npm run build` erzeugt API-/Paket-Artefakte und `apps/web/dist`. `npm start` startet die gebaute API. Mit `LZC_WEB_ROOT` liefert sie auch das gebaute UI aus. Das [CF-Manifest](../deploy/cloud-foundry/manifest.yml) setzt den Pfad, `HOST=0.0.0.0` und verwendet den von CF bereitgestellten `PORT`. `vite preview` ist kein Produktionsserver. - -## Arbeitsbereich und Konfiguration - -Der regulaere Einstieg ist **Anmelden > Arbeitsbereich oeffnen > Konfiguration -oeffnen oder erstellen > Bearbeiten > Plan > Apply**. Beim ersten Einstieg lassen -sich der persoenliche oder ein Organisationsarbeitsbereich oeffnen und neue -Arbeitsbereiche erstellen. Bei spaeterem Einstieg ueber `/` wird der zuletzt -geoeffnete, weiterhin zugaengliche Arbeitsbereich wieder aufgenommen. Explizite -Seiten-URLs bleiben erhalten; der Arbeitsbereichswechsel steht im Header bereit. - -**Arbeitsbereiche** steht an erster Stelle der Hauptnavigation. Oeffnen fuehrt zu -den Konfigurationen des gewaehlten Bereichs, fuer Application Owner zur eigenen -Application-Ansicht. **Benutzerverwaltung** verwaltet Mitglieder, Rollen und -Gruppen des aktiven Bereichs. Berechtigte Platform Engineers koennen eigene -Gruppen anlegen und loeschen sowie Mitglieder zuweisen und wieder entfernen. -Gruppenmitglieder werden mit ihrer bestaetigten STACKIT-E-Mail angezeigt; -Benutzer-IDs bleiben intern. Legacy-Konten ohne STACKIT-E-Mail behalten ihren -Benutzernamen, unbekannte Namen werden nicht durch IDs ersetzt. -Die automatische Gruppe **Application Owners** folgt den Rollen und ist nicht -manuell aenderbar. Gruppen mit Template-Freigaben koennen erst nach deren -Entfernung geloescht werden; Arbeitsbereichsmitglieder bleiben erhalten. -Template-Gruppenfreigaben liegen weiterhin unter **Application Landing Zones > -Veroeffentlichung**, nicht in einem zusaetzlichen Gruppen-Reiter. Auswahl und -Erstellung anderer Arbeitsbereiche liegen nicht in der Benutzerverwaltung. -Auch eine neue inline STACKIT-Anmeldung von einer zuvor offenen Verwaltungsseite -fuehrt ohne offenen Entwurf zum Arbeitsbereichseinstieg. Bereits angemeldete -Deep Links und gesicherte Login-Entwuerfe bleiben erhalten. - -**Konfigurationen** ist die Plattformuebersicht. **Neue Konfiguration** fuehrt zur -Template-Auswahl. Eine geoeffnete Konfiguration hat den Kontext **Konfiguration > -Bereitstellung > Verlauf** mit sichtbarer gespeicherter Revision. -**Speichern und zur Bereitstellung** uebernimmt die vom Server neu gespeicherte -Revision, nicht den alten Entwurfsstand. Ungespeicherte Aenderungen sperren den -direkten Bereitstellungstab; ein Arbeitsbereichswechsel fragt vor ihrem Verlust. -Der Verlauf ist nur lesbar und auf die betreffende Konfiguration begrenzt. - -Die Bereitstellung zeigt pro Konfiguration den neuesten Lauf, sofern er nicht -abgelaufen oder bereits verwendet ist, sowie laufende Ausfuehrungen und -erforderliche Wiederherstellungen. Aeltere, -abgelaufene oder bereits fuer Apply verwendete Plaene liegen standardmaessig -unter **Historie (Anzahl)**. Ihre Details sind einzeln aufklappbar und ohne -Apply-Freigabe; CLI-Ausgaben und Nachweise bleiben lesbar. Ablauf verschiebt einen -Plan auch ohne Reload in die Historie. Die Ansicht loescht oder erneuert keine -Artefakte und hebt keine laufenden Ausfuehrungs-/Recovery-Sperren auf. - -Reload liest die gemerkte Konfigurations-ID innerhalb des Benutzer-/Arbeitsbereichs -erneut vom Server. Zugaenge und Apply-Freigaben werden dadurch nicht gespeichert -oder bestaetigt. Vorbereitung, Plan und Apply bleiben ausdrueckliche Aktionen; -vorhandene Plan-Artefakte werden durch Navigation nicht erneuert oder umgebunden. -Application Owner behalten ihren getrennten Application-Landing-Zone-Einstieg. - -## Aktueller Funktionsumfang - -- Private Konfigurationen in PostgreSQL, pro Benutzer und aktivem Arbeitsbereich. - Unter **Konfigurationen** lassen sich auch unvollstaendige Entwuerfe speichern, - wieder oeffnen, als neue Kopie speichern und loeschen. Revisionen verhindern - das Ueberschreiben durch parallele Tabs; im Konflikt bleibt der Entwurf erhalten. - GitHub ist dafuer nicht erforderlich und bleibt als optionaler versionierter - Speicherort verfuegbar. Der Datenbankweg benoetigt Migration - `015_configuration_storage.sql`; vorhandene Konfigurationen sind nur fuer ihren - Ersteller sichtbar. In Organisationsarbeitsbereichen ist die Rolle Platform - Engineer erforderlich. Browser-Zwischenstaende ersetzen diese Speicherung nicht. -- Template-Katalog, Standalone-Editor mit Feldhilfen und grafischer Struktur. -- Nativer `.tfvars`-Download und atomarer GitHub-Export mit JSON, tfvars, CLI-Anleitung und optional verifiziertem S3-Backend. -- GitHub-Login, PostgreSQL-Sessions/RLS und persönliche Tokens im Secrets Manager. -- Persönliche Deployment-Zugänge: Service-Account-Key-Datei speichern/löschen; Anmeldung und Organisations-Lesezugriff prüfen. [Details](../docs/deployment-credentials.md). -- Unveränderliche Deployment-Vorbereitungen aus Fork-Konfiguration, Ziel und persönlichem Zugang. [Details](../docs/deployment-preparation.md). -- Browser-Zurück/Vorwärts und direkte Seiten-URLs. -- Erstbereitstellungspläne und freigabegebundener Plattform-Apply-Pfad: RLS-Aufträge, isolierte CF-Tasks und wertfreie Ergebnisanzeige; siehe [Ablauf und Abnahme](../docs/plan-execution.md). Kein Kunden-Apply in dieser Abnahme; Chat bleibt offen. -- Application-Testkatalog: unveränderliche tenantgebundene Projekt-Template-Versionen, Bestellungen ohne Fork, idempotente Instanzaufträge und ausdrückliche Planblocker. Keine Application-Cloud-Ausführung; siehe [Veröffentlichung und Bestellung](../docs/template-parameters-and-bindings.md#tenantgebundener-testkatalog-und-bestellungen). - -Der Application-Dienst ist standardmäßig deaktiviert. Nach Anwendung der Migration -`010_application_catalogue.sql` mit der bestehenden Migrationsidentität aktiviert -`LZC_APPLICATIONS_ENABLED=true` die API im authentifizierten Server. Fehlende Tabellen -verhindern dessen Start. `/applications` ist die eigene SPA-Route; die API liegt unter -`/api/v1/applications/templates` und `/api/v1/applications/instances`. Alle Anfragen -benötigen den aktiven Tenant-Header, Mutationen zusätzlich Origin-/CSRF-Prüfung. -Das Featureflag aktiviert ausschließlich den Testkatalog und Bestellaufträge, niemals -einen Runner oder Apply. Die bestehende Plattform-Plan-Pipeline bleibt unverändert. - -Details und Grenzen: [Forks und Navigation](../docs/forks-and-navigation.md), -[GitHub-Login](../docs/github-login.md). HCL-Export-Roundtrip prüfen mit Node 24 im PATH: +Under **OpenTofu output**, platform jobs also show live progress in Cloud Foundry +through an authenticated NDJSON channel. The worker reads +complete lines every 500 ms; only changed, redacted text is +saved encrypted and forwarded. Plan provides native +OpenTofu UI events before the finished diff is available; raw event objects +and their output data are not sent to the browser. **Follow output** can be paused to review older +lines. Collapsing and navigation disconnect the stream; reopening +resumes at the current capture. JSON snapshots remain compatible. +Successful platform Plans are displayed +read-only through `tofu show -no-color` from the unchanged saved +artifact, including resources and attribute changes. +OpenTofu masks sensitive values as in the CLI. The separate output route +requires a session, deployment role and private owner/tenant mapping; +raw Plan binaries or `show -json` are not delivered to the browser. +Each Plan remains bound to its immutable Runner package. A package change +requires a new Plan and its explicit approval. +Running Apply output is also updated. Before the terminal result, +the worker saves the latest redacted CLI text encrypted at the broker; +it remains readable after cleanup and reload under the same private access controls. +**Apply evidence** shows Plan ID, SHA-256, target organization, the job's state backend +and completion time. Existing exact organization confirmation and, +if applicable, destructive approval remain required; no automatic retry. +Output is limited to 2 MiB; truncation is indicated. Saving is +best-effort: hard process termination or failed upload does not guarantee a +complete historical capture. Already saved +text needs no running native Runner. During streaming, +session, tenant, role and ownership are rechecked. Connections are +closed after at most 35 seconds and reopened for an active job; +backpressure, byte limits and at most eight streams per owner/tenant and +API instance limit resources. Details: [Plan execution](../docs/plan-execution.md). + +For new platforms, **Accelerator standard · Management S3** is the default. +The selected service account executes the approved bootstrap Apply; +Terraform manages the management project, `*-tfstate` bucket, S3 access and its +management Secrets Manager entry. The broker then verifies +migration to `terraform.tfstate` in eu01. No manual S3 keys are needed. +**Register existing S3 backend** remains the optional existing-infrastructure connection. +The bucket is not created in advance outside Terraform state. Plan and +Apply start only through their respective explicit UI actions. + +`npm run build` produces API/package artifacts and `apps/web/dist`. `npm start` starts the built API. With `LZC_WEB_ROOT`, it also serves the built UI. The [CF manifest](../deploy/cloud-foundry/manifest.yml) sets the path and `HOST=0.0.0.0`, and uses the `PORT` provided by CF. `vite preview` is not a production server. + + + +## Workspace and configuration + +The normal entry path is **Sign in > Open workspace > Open or create +configuration > Edit > Plan > Apply**. On first entry, users can +open their personal or an organization workspace and create new +workspaces. On later entry through `/`, the last +opened workspace is resumed if it remains accessible. Explicit +page URLs are preserved; workspace switching is available in the header. + +**Workspaces** comes first in the main navigation. Opening one leads to +the selected workspace's configurations, or to Application Owners' own +application view. **User management** manages members, roles and +groups in the active workspace. Authorized Platform Engineers can create +and delete their own groups and assign and remove members. +Group members are displayed with their confirmed STACKIT email; +user IDs remain internal. Legacy accounts without STACKIT email keep their +username; unknown names are not replaced with IDs. +The automatic **Application Owners** group follows roles and cannot +be changed manually. Groups with template grants can be deleted only after those +grants are removed; workspace members are preserved. +Template group grants remain under **Application Landing Zones > +Publication**, not in an additional groups tab. Selecting and +creating other workspaces is not part of user management. +Even a new inline STACKIT login from a previously open administration page +leads to workspace entry when there is no open draft. Already authenticated +deep links and saved login drafts are preserved. + +**Configurations** is the platform overview. **New configuration** leads to +template selection. An open configuration has the context **Configuration > +Deployment > History** with its saved revision visible. +**Save and go to deployment** adopts the newly saved server +revision, not the old draft state. Unsaved changes block the +direct deployment tab; switching workspaces asks before losing them. +History is read-only and limited to the relevant configuration. + +Deployment shows each configuration's latest run, provided it is not +expired or already used, together with running executions and +required recoveries. Older, +expired Plans or those already used for Apply are shown by default +under **History (count)**. Their details can be expanded individually without +Apply approval; CLI output and evidence remain readable. Expiry moves a +Plan to history even without reload. The view neither deletes nor renews +artifacts and lifts no ongoing execution/recovery blocks. + +Reload reads the remembered configuration ID again from the server within the +user/workspace scope. This neither saves nor confirms credentials +or Apply approvals. Preparation, Plan and Apply remain explicit actions; +navigation neither refreshes nor rebinds existing Plan artifacts. +Application Owners retain their separate Application Landing Zone entry. + + + +## Current functionality + +- Private configurations in PostgreSQL, per user and active workspace. + Under **Configurations**, users can also save incomplete drafts, + reopen them, save as a new copy and delete them. Revisions prevent + overwrites by parallel tabs; on conflict, the draft is preserved. + GitHub is not required and remains available as optional versioned + storage. The database path requires migration + `015_configuration_storage.sql`; existing configurations are visible only to their + creator. Organization workspaces require the Platform + Engineer role. Intermediate browser state does not replace this persistence. +- Template catalogue, standalone editor with field help and graphical structure. +- Native `.tfvars` download and atomic GitHub export with JSON, tfvars, CLI instructions and an optionally verified S3 backend. +- GitHub login, PostgreSQL sessions/RLS and personal tokens in Secrets Manager. +- Personal deployment credentials: save/delete a service account key file; check authentication and organization read access. [Details](../docs/deployment-credentials.md). +- Immutable deployment preparations from fork configuration, target and personal credentials. [Details](../docs/deployment-preparation.md). +- Browser back/forward and direct page URLs. +- Initial provisioning Plans and an approval-bound platform Apply path: RLS jobs, isolated CF tasks and value-free result display; see [process and acceptance](../docs/plan-execution.md). No customer Apply in this acceptance; chat remains open. +- Application test catalogue: immutable tenant-bound project template versions, orders without a fork, idempotent instance jobs and explicit Plan blockers. No application cloud execution; see [publication and ordering](../docs/template-parameters-and-bindings.md#tenantgebundener-testkatalog-und-bestellungen). + +The application service is disabled by default. After applying migration +`010_application_catalogue.sql` with the existing migration identity, +`LZC_APPLICATIONS_ENABLED=true` enables the API in the authenticated server. Missing tables +prevent startup. `/applications` is its own SPA route; the API lives under +`/api/v1/applications/templates` and `/api/v1/applications/instances`. All requests +need the active tenant header; mutations additionally require origin/CSRF checks. +The feature flag enables only the test catalogue and order jobs, never +a Runner or Apply. The existing platform Plan pipeline remains unchanged. + +Details and boundaries: [forks and navigation](../docs/forks-and-navigation.md), +[GitHub login](../docs/github-login.md). Check the HCL export roundtrip with Node 24 in PATH: `cd ../tools/hcl-adapter && go test ./... && go run . -check`. -## State-Backend und unabhängiger Export - -Der Plattform-Bootstrap verwendet temporär einen dauerhaften verschlüsselten -HTTP-State. Nach dem freigegebenen Bootstrap-Apply wird zum LZA-Management-Bucket -migriert; erst nach serverseitigem Hash-/Versionsnachweis wird der HTTP-Primärstate -entfernt. Native S3-States verwenden `use_lockfile = true`; Application-Instanzen -haben jeweils eigene State-Keys. Legacy-State-Zuordnungen bleiben bis zur expliziten -Migration gesperrt. Unbestätigte Migration/Recovery benötigt einen State-Export -und operativen Abgleich; vollständige automatische Recovery bei hartem -Runner-Verlust ist nicht garantiert. Cloud-Locking wurde nicht live getestet. - -GitHub speichert unter `src/config/custom//` JSON, tfvars und eine CLI-Anleitung, -zusätzlich `backend.tf.json`, wenn die API die Quellbindung verifiziert hat. -Die erste Speicherung eines DB-Entwurfs erhält dessen ID; vorhandene Git-Bindungen -behalten ihre eigene ID. Der Browser kann keine Backend-Deskriptoren vorgeben. -Exportiert werden weder AWS-/SA-Schlüssel noch State-Dateien. Backend-Servicefehler, -manuell veränderte Backend-Dateien und verlorene Bindungen brechen den Export ab. -Ein abweichender Quell-ID-Alias wird beim Export nicht neu registriert; für die -Vorbereitung ist die ausdrückliche Auswahl des bestehenden Backend-ID nötig. - -CLI-Betrieb benötigt den geprüften Accelerator-Code und den Management-Zugang -aus dem LZA Secrets Manager. Ursprünglichen Backend-Block in `src/backend.tf` -deaktivieren, exportiertes `backend.tf.json` nach `src/` kopieren und genau einen -aktiven Backend-Block behalten. AWS-Schlüssel als `AWS_ACCESS_KEY_ID` und -`AWS_SECRET_ACCESS_KEY` setzen, dann in `src`: + + +## State backend and independent export + +Platform bootstrap temporarily uses durable encrypted +HTTP state. After the approved bootstrap Apply, it migrates to the LZA management bucket; +the primary HTTP state is removed only after server-side hash/version evidence. +Native S3 states use `use_lockfile = true`; application instances +each have their own state keys. Legacy state mappings remain blocked until explicit +migration. Unconfirmed migration/recovery requires a state export +and operational reconciliation; complete automatic recovery after hard +Runner loss is not guaranteed. Cloud locking has not been tested live. + +GitHub stores JSON, tfvars and CLI instructions under `src/config/custom//`, +plus `backend.tf.json` if the API verified the source binding. +The first save of a DB draft retains its ID; existing Git bindings +retain their own ID. The browser cannot specify backend descriptors. +Neither AWS/SA keys nor state files are exported. Backend service errors, +manually changed backend files and lost bindings abort export. +A differing source ID alias is not registered anew during export; preparation +requires explicit selection of the existing backend ID. + +CLI operation requires the reviewed Accelerator code and management access +from LZA Secrets Manager. Disable the original backend block in `src/backend.tf`, +copy the exported `backend.tf.json` to `src/` and retain exactly one +active backend block. Set AWS keys as `AWS_ACCESS_KEY_ID` and +`AWS_SECRET_ACCESS_KEY`, then in `src`: ```sh tofu init tofu plan -var-file=config/custom//landing-zone.tfvars ``` -Ohne verifizierte Bindung zuerst den LZA-Bootstrap mit gesichertem State und -anschließender geprüfter S3-Migration durchführen. Export führt weder Apply noch -Migration aus. [Lifecycle und Recovery-Grenzen](../docs/plan-execution.md#state-lebenszyklus-gemäß-lza). +Without a verified binding, first perform LZA bootstrap with secured state and +subsequent verified S3 migration. Export executes neither Apply nor +migration. [Lifecycle and recovery boundaries](../docs/plan-execution.md#state-lebenszyklus-gemäß-lza). + + -## Lesende Plattformprüfung +## Read-only platform check ```sh npm run platform:check ``` -Benötigt die STACKIT-CLI sowie die beiden ignorierten Dateien im Repository-Root. Liest `PROJECT_ID` und optional `REGION`; ohne Region wird ausschließlich für die Bestandsaufnahme `eu01` verwendet. `ORGANISATION_ID` bleibt für die spätere Organisationszuordnung reserviert. +Requires the STACKIT CLI and the two ignored files in the repository root. Reads `PROJECT_ID` and optionally `REGION`; without a region, `eu01` is used exclusively for inventory. `ORGANISATION_ID` remains reserved for later organization mapping. -Das Skript führt die `.env` nicht als Shellcode aus. Es bezieht einen kurzlebigen Token ohne CLI-Login-Persistierung und fragt ausschließlich Metadaten per GET ab. Ausgabe enthält Statuscodes/Anzahlen, keine Tokens oder Rohantworten. Unerwartete Fehler führen zu Exitcode 1; der bekannte Object-Storage-Status 404 wird als `enabled: false` und anstehende IaC-Provisionierung gemeldet. Der Check provisioniert oder aktiviert nichts. Betriebssystem-Zertifikate sind für Unternehmensproxys aktiviert; TLS-Prüfung bleibt eingeschaltet. +The script does not execute `.env` as shell code. It obtains a short-lived token without persisting CLI login and queries only metadata through GET. Output contains status codes/counts, no tokens or raw responses. Unexpected errors produce exit code 1; the known Object Storage status 404 is reported as `enabled: false` and pending IaC provisioning. The check provisions or enables nothing. Operating system certificates are enabled for corporate proxies; TLS verification remains on. -Der Modellkatalog beweist keine projektbezogene Inferenzaktivierung. Leserechte beweisen keine Erstell-/Änderungsrechte. CF-Plattformangebote ersetzen weder CF-Organisation noch Runtime-Zugang. Ergebnisse: [Plattformprüfung](../docs/platform-check.md). +The model catalogue does not prove project-specific inference activation. Read permissions do not prove create/change permissions. CF platform offerings replace neither a CF organization nor runtime access. Results: [platform check](../docs/platform-check.md). diff --git a/landing-zone-configurator/app/apps/api/README.de.md b/landing-zone-configurator/app/apps/api/README.de.md new file mode 100644 index 0000000..af762de --- /dev/null +++ b/landing-zone-configurator/app/apps/api/README.de.md @@ -0,0 +1,5 @@ +# Backend / BFF + +[English](README.md) | [Deutsch](README.de.md) + +Geplant: Node.js/TypeScript mit Fastify als Framework-Kandidat. Sessions, Tenant-Autorisierung, GitHub, Konfigurationen und Model-Serving-Anbindung. Keine OpenTofu-Prozesse im Web-Request. diff --git a/landing-zone-configurator/app/apps/api/README.md b/landing-zone-configurator/app/apps/api/README.md index 0ade11f..5b41b71 100644 --- a/landing-zone-configurator/app/apps/api/README.md +++ b/landing-zone-configurator/app/apps/api/README.md @@ -1,3 +1,5 @@ # Backend / BFF -Geplant: Node.js/TypeScript mit Fastify als Framework-Kandidat. Sessions, Tenant-Autorisierung, GitHub, Konfigurationen und Model-Serving-Anbindung. Keine OpenTofu-Prozesse im Web-Request. +[English](README.md) | [Deutsch](README.de.md) + +Planned: Node.js/TypeScript with Fastify as a framework candidate. Sessions, tenant authorization, GitHub, configurations and Model Serving integration. No OpenTofu processes in web requests. diff --git a/landing-zone-configurator/app/apps/api/src/assistant/knowledge-topics.generated.ts b/landing-zone-configurator/app/apps/api/src/assistant/knowledge-topics.generated.ts index d71ccba..6e903df 100644 --- a/landing-zone-configurator/app/apps/api/src/assistant/knowledge-topics.generated.ts +++ b/landing-zone-configurator/app/apps/api/src/assistant/knowledge-topics.generated.ts @@ -21,12 +21,12 @@ export const assistantKnowledgeTopics = { { path: "landing-zone-configurator/docs/common-feature-model.md", sha256: - "03982b8dfa69a31da9eace5855866b92c6b35577f3ee7a8c76f96ed0fd6c8196", + "fbb34277b25bd5e37eafc74952f57eb295af87f3669956612b43a8ccccef791d", }, { path: "landing-zone-configurator/docs/deployment-credentials.md", sha256: - "cef82819e92460649747c175e02c9b78c86e19cfa8d5635c1d46ef3c518e4019", + "08c975163a0ececd2432dcfd9162fc847d37aa8c073b9086f6fe429fe1b10d6d", }, { path: "src/variables.tf", @@ -321,12 +321,12 @@ export const assistantKnowledgeTopics = { { path: "landing-zone-configurator/docs/common-feature-model.md", sha256: - "03982b8dfa69a31da9eace5855866b92c6b35577f3ee7a8c76f96ed0fd6c8196", + "fbb34277b25bd5e37eafc74952f57eb295af87f3669956612b43a8ccccef791d", }, { path: "landing-zone-configurator/docs/deployment-credentials.md", sha256: - "cef82819e92460649747c175e02c9b78c86e19cfa8d5635c1d46ef3c518e4019", + "08c975163a0ececd2432dcfd9162fc847d37aa8c073b9086f6fe429fe1b10d6d", }, { path: "landing-zone-configurator/app/apps/api/src/assistant/editor.ts", @@ -746,7 +746,7 @@ export const assistantKnowledgeTopics = { { path: "landing-zone-configurator/docs/vpn-configuration-scope.md", sha256: - "5edb220a2553cbc9e55de0c33d1471b028d878409fb2f149d340505ad85328ce", + "4745879cf0ab0272132319425e2e916593f437c7b27c4b74f7a7fd5b59a6fd32", }, { path: "landing-zone-configurator/app/apps/api/src/assistant/editor.ts", @@ -1042,7 +1042,7 @@ export const assistantKnowledgeTopics = { { path: "landing-zone-configurator/docs/deployment-credentials.md", sha256: - "cef82819e92460649747c175e02c9b78c86e19cfa8d5635c1d46ef3c518e4019", + "08c975163a0ececd2432dcfd9162fc847d37aa8c073b9086f6fe429fe1b10d6d", }, { path: "landing-zone-configurator/app/apps/api/src/assistant/editor.ts", @@ -1482,7 +1482,7 @@ export const assistantKnowledgeTopics = { { path: "landing-zone-configurator/docs/common-feature-model.md", sha256: - "03982b8dfa69a31da9eace5855866b92c6b35577f3ee7a8c76f96ed0fd6c8196", + "fbb34277b25bd5e37eafc74952f57eb295af87f3669956612b43a8ccccef791d", }, { path: "landing-zone-configurator/app/packages/domain/src/common-document.ts", diff --git a/landing-zone-configurator/app/apps/web/README.de.md b/landing-zone-configurator/app/apps/web/README.de.md new file mode 100644 index 0000000..a515186 --- /dev/null +++ b/landing-zone-configurator/app/apps/web/README.de.md @@ -0,0 +1,37 @@ + + +# Web-Oberfläche + +[English](README.md) | [Deutsch](README.de.md) + +Geplant: React/TypeScript, Fachformulare, Topologie, Chat und Plan-/Run-Ansicht. Keine Cloud- oder GitHub-Tokens im Browser. + + + +## Template-Editor (erster fachlicher Stand) + +- Acht aus `src/config` generierte Templates mit Suche und Strukturvorschau. +- Standalone-Kopie bearbeiten: Organisation, Region, Verantwortliche, Landing Zones, + Umgebungen, Secrets-Manager-Auswahl und Sandboxes. +- Originale Portal-Design-Tokens (digits/light), lokal ausgelieferte Markenassets; + Herkunft und noch offene visuelle Abnahme in `docs/design-reference.md`. +- Zustand nur im aktuellen Tab-Speicher; keine Cloud-/GitHub-Schreiboperationen. +- Download `landing-zone.lzc.json`: versionierter Entwurf mit Template-Quellhash + und fachlich bearbeiteten Konfigurationswerten. Kein direkt ausführbarer + `.tfvars.json`-Export und noch kein Import dieses Entwurfformats. +- Netzwerk-Templates bleiben vorerst schreibgeschützt. Der Standalone-Editor setzt + ausdrücklich `corporate: false`, weil das aktuelle Quelltemplate ohne Hub sonst + den Accelerator-Default `true` erben würde. + +Lokale Abnahme aus `app/` nach `npm run build`: + +```sh +npx playwright install chromium +npm run test:e2e +``` + +Alternativ mit installiertem Chrome: `LZC_TEST_CHROME=true npm run test:e2e`. +Tests verwenden isolierte Browser-Kontexte ohne vorhandene Benutzersitzung. +Screenshots/Fehlertraces liegen ignoriert unter `.local/browser-tests` und werden +in der Validierung als kurzlebige CI-Artefakte bereitgestellt. Desktop- und +Mobilbreite prüfen Suche, Vorschau, Validierung, Download und Quellisolierung. diff --git a/landing-zone-configurator/app/apps/web/README.md b/landing-zone-configurator/app/apps/web/README.md index bdbff6e..bc6e131 100644 --- a/landing-zone-configurator/app/apps/web/README.md +++ b/landing-zone-configurator/app/apps/web/README.md @@ -1,31 +1,37 @@ -# Web-Oberfläche +# Web interface -Geplant: React/TypeScript, Fachformulare, Topologie, Chat und Plan-/Run-Ansicht. Keine Cloud- oder GitHub-Tokens im Browser. +[English](README.md) | [Deutsch](README.de.md) -## Template-Editor (erster fachlicher Stand) + -- Acht aus `src/config` generierte Templates mit Suche und Strukturvorschau. -- Standalone-Kopie bearbeiten: Organisation, Region, Verantwortliche, Landing Zones, - Umgebungen, Secrets-Manager-Auswahl und Sandboxes. -- Originale Portal-Design-Tokens (digits/light), lokal ausgelieferte Markenassets; - Herkunft und noch offene visuelle Abnahme in `docs/design-reference.md`. -- Zustand nur im aktuellen Tab-Speicher; keine Cloud-/GitHub-Schreiboperationen. -- Download `landing-zone.lzc.json`: versionierter Entwurf mit Template-Quellhash - und fachlich bearbeiteten Konfigurationswerten. Kein direkt ausführbarer - `.tfvars.json`-Export und noch kein Import dieses Entwurfformats. -- Netzwerk-Templates bleiben vorerst schreibgeschützt. Der Standalone-Editor setzt - ausdrücklich `corporate: false`, weil das aktuelle Quelltemplate ohne Hub sonst - den Accelerator-Default `true` erben würde. +Planned: React/TypeScript, domain-specific forms, topology, chat and Plan/Run view. No cloud or GitHub tokens in the browser. -Lokale Abnahme aus `app/` nach `npm run build`: + + +## Template editor (initial domain implementation) + +- Eight templates generated from `src/config`, with search and structure preview. +- Edit a standalone copy: organization, region, owners, landing zones, + environments, Secrets Manager selection and sandboxes. +- Original portal design tokens (digits/light), locally served brand assets; + provenance and outstanding visual acceptance in `docs/design-reference.md`. +- State only in the current tab's memory; no cloud/GitHub write operations. +- Download `landing-zone.lzc.json`: versioned draft with the template source hash + and configuration values edited through the domain model. Not a directly executable + `.tfvars.json` export, and no import of this draft format yet. +- Network templates remain read-only for now. The standalone editor explicitly sets + `corporate: false`, because the current source template without a hub would + otherwise inherit the Accelerator default of `true`. + +Local acceptance from `app/` after `npm run build`: ```sh npx playwright install chromium npm run test:e2e ``` -Alternativ mit installiertem Chrome: `LZC_TEST_CHROME=true npm run test:e2e`. -Tests verwenden isolierte Browser-Kontexte ohne vorhandene Benutzersitzung. -Screenshots/Fehlertraces liegen ignoriert unter `.local/browser-tests` und werden -in der Validierung als kurzlebige CI-Artefakte bereitgestellt. Desktop- und -Mobilbreite prüfen Suche, Vorschau, Validierung, Download und Quellisolierung. +Alternatively, with Chrome installed: `LZC_TEST_CHROME=true npm run test:e2e`. +Tests use isolated browser contexts without an existing user session. +Screenshots/error traces are ignored under `.local/browser-tests` and provided +as short-lived CI artifacts during validation. Desktop and +mobile widths check search, preview, validation, download and source isolation. diff --git a/landing-zone-configurator/app/apps/worker/README.de.md b/landing-zone-configurator/app/apps/worker/README.de.md new file mode 100644 index 0000000..4f14854 --- /dev/null +++ b/landing-zone-configurator/app/apps/worker/README.de.md @@ -0,0 +1,26 @@ +# Plan-Runner + +[English](README.md) | [Deutsch](README.de.md) + +Ein kurzlebiger CF-Task pro Plan in einer eigenen Anwendung und CF-Organisation. +Der Task erhält nur eine kurzlebige Capability für einen gespeicherten Job, dessen ID und +den festen Broker-Origin. Es werden keine PostgreSQL-, Vault-, Model-Serving-, GitHub- oder +CF-Manager-Zugangsdaten gebunden. Die API ist der vertrauenswürdige Dispatcher/Credential-Broker. + +Der Broker prüft Eigentümerschaft, Rolle, Credential-Version und Organisationszugriff erneut, +bevor er die unveränderlichen tfvars und den STACKIT-Schlüssel dieses Jobs einmalig zurückgibt. +OpenTofu läuft mit einer expliziten Umgebungs-Allowlist ohne Broker-Ticket. Quellcommit, +Provider-Lock und Engine werden in CI paketiert; benutzereigenes Terraform wird nicht ausgeführt. + +`deploy/runner/run-plan.sh` enthält die direkten init-, validate-, plan- und show-Befehle. +Diese erste Implementierung unterstützt nur initiale Vorschauen mit leerem State. Es gibt +keinen apply-/destroy-Befehl oder -Endpunkt. Private Key, Logs, rohes JSON und binärer Plan bleiben +im kurzlebigen Container und werden entfernt; nur wertfreie Zählwerte verlassen ihn. +Diese Vorschauen können später nicht angewendet werden. Ein zukünftiges Apply benötigt einen neuen +Plan, ausdrückliche Freigabe und dauerhafte Bootstrap-State-Wiederherstellung, bevor es implementiert werden kann. + +Der Task hat ein Engine-Zeitlimit von 18 Minuten; der gespeicherte Job läuft nach 25 +Minuten ab. Die API-Wartung invalidiert abgelaufene Jobs und löscht abgeschlossene/abgebrochene +Runner-Apps. Fehlgeschlagener Dispatch wird nicht automatisch wiederholt. Ein Neustart zwischen +Datenbankeintrag und Dispatch hinterlässt einen sichtbaren Job, der abgebrochen werden kann oder abläuft. +Siehe [Ausführung und Abnahme](../../../docs/plan-execution.de.md). diff --git a/landing-zone-configurator/app/apps/worker/README.md b/landing-zone-configurator/app/apps/worker/README.md index 5f99727..ce68e21 100644 --- a/landing-zone-configurator/app/apps/worker/README.md +++ b/landing-zone-configurator/app/apps/worker/README.md @@ -1,5 +1,7 @@ # Plan runner +[English](README.md) | [Deutsch](README.de.md) + An ephemeral CF task per plan in a dedicated application and CF organisation. The task receives only a short-lived capability for one persisted job, its ID and the fixed broker origin. No PostgreSQL, Vault, Model Serving, GitHub or CF-manager diff --git a/landing-zone-configurator/app/packages/contracts/README.de.md b/landing-zone-configurator/app/packages/contracts/README.de.md new file mode 100644 index 0000000..a2e40e3 --- /dev/null +++ b/landing-zone-configurator/app/packages/contracts/README.de.md @@ -0,0 +1,7 @@ + + +# Schnittstellenverträge + +[English](README.md) | [Deutsch](README.de.md) + +Versionierte API- und Job-Verträge mit Laufzeitvalidierung. Keine Browser-Exporte interner Credential-Strukturen. Mit dem Fachmodell abgestimmte, nicht doppelt gepflegte Schemas. diff --git a/landing-zone-configurator/app/packages/contracts/README.md b/landing-zone-configurator/app/packages/contracts/README.md index d80d666..ac71465 100644 --- a/landing-zone-configurator/app/packages/contracts/README.md +++ b/landing-zone-configurator/app/packages/contracts/README.md @@ -1,3 +1,7 @@ -# Schnittstellenverträge +# Interface contracts -Versionierte API- und Job-Verträge mit Laufzeitvalidierung. Keine Browser-Exporte interner Credential-Strukturen. Mit dem Fachmodell abgestimmte, nicht doppelt gepflegte Schemas. +[English](README.md) | [Deutsch](README.de.md) + + + +Versioned API and job contracts with runtime validation. No browser exports of internal credential structures. Schemas aligned with the domain model, not maintained in duplicate. diff --git a/landing-zone-configurator/app/packages/domain/README.de.md b/landing-zone-configurator/app/packages/domain/README.de.md new file mode 100644 index 0000000..1981fee --- /dev/null +++ b/landing-zone-configurator/app/packages/domain/README.de.md @@ -0,0 +1,92 @@ + + +# Fachmodell + +[English](README.md) | [Deutsch](README.de.md) + +Gemeinsame Logik für UI, API und Chat-Vorschläge. Keine Secret-Auflösung in diesem +Paket. Der gemeinsame Editor und die Fork-Speicherung verwenden das Modell v3. Bestehende +v1/v2-Entwürfe bleiben im bisherigen Editor bearbeitbar und können ausdrücklich +auf den gemeinsamen Editor umgestellt werden. + + + +## Gemeinsames Modell (v3) + +- `features.ts`: alle 28 Root-Eingaben in fachlichen Gruppen; Feldkatalog inklusive + verschachtelter Typen und separat ausgewiesener geschützter Eingaben. +- `common-document.ts`: alle acht Templates importieren, Version 1/2 migrieren, + stabile Objektidentitäten, gemeinsame Projekt-/Bereichsprojektionen und Export. +- `common-validation.ts`: Referenzen, Konfigurationskombinationen und bekannte + Ausführungsgrenzen getrennt beurteilen. Kein Ersatz für Provider-Prüfung oder Plan. +- `accelerator-inputs.json`: generierter Typvertrag, keine handgepflegte zweite + Terraform-Typdefinition. Aktualitätsprüfung in CI; siehe HCL-Adapter-README. + +`createCommonConfiguration(templateId, id)` kopiert eine vertrauenswürdige Vorlage. +`migrateCommonConfiguration(legacy)` kompiliert zunächst mit dem alten Vertrag; +anschließender Export bleibt bytegleich, auch für Ordneränderungen in v2. +`readCommonConfiguration` prüft Form, Herkunft, Eingaben und Objektidentitäten. +Unvollständige fachliche Angaben dürfen für die weitere Bearbeitung bestehen bleiben. + +Intern enthalten die Feature-Gruppen die expliziten Engine-Eingaben. Die Oberfläche +soll darauf fachliche Editoren aufsetzen, kein generisches Terraform-Variablenformular. +`commonProjects` liefert Public, Corporate und Sandbox in derselben Sicht mit +Zielordner und Bereichsbezug. `commonNetworkAreas` liefert einzelne und regionale +Bereiche ohne deren Quellen beim Lesen umzuschreiben. + +`setCommonInput` ändert Werte, **nicht** die Identitätsliste von Sammlungen. +Sammlungsänderungen brauchen explizite Operationen mit konsistenter Identitätsliste. +`renameCommonProject` erhält die UI-Identität und passt Namespace-Referenzen an; +Terraform-Adressen ändern sich dabei trotzdem. Die spätere UI muss das bestätigen +lassen. `removeCommonNetworkArea` blockiert bestehende Projekt-/Dienstreferenzen. +`editor-document.ts` ergänzt Projektanlage/-entfernung, sichere Sammlungsänderungen +und die kompatible Speicher-/Editor-Brücke. + +`compileCommonConfiguration` / `exportCommonTfvars` erhalten ausgelassene Werte, +explizites `null` und explizite Konfiguration. `effectiveInput` liefert ausschließlich +Anzeige-/Validierungswerte mit Defaults; diese Projektion darf nicht zurückexportiert +werden. Regionale `map(any)`-Eingaben werden nur für tatsächlich im Root verdrahtete +Felder akzeptiert; ihre Defaults werden nicht pauschal aus dem Einzelregionsmodell +übernommen. Unbekannte Attribute und deklarierte Secret-Eingaben werden abgelehnt, +nicht still entfernt. Ein freies Textfeld ist dadurch kein Secret-Scanner. + +`assessCommonConfiguration` liefert Konfigurationsfehler, Warnungen, bekannte +Ausführungsgrenzen und benötigte Phasen. Ein leeres Ergebnis ist **keine** +Deployment-Freigabe. Vor produktiver v3-Ausführung fehlen noch die Runner-Anbindung, +Credential-Bindings, vollständige fachliche Prüfungen, Provider-/Modultests und +serverseitig durchgesetzte Runner-Capabilities. Der bestehende Plan-Endpunkt nimmt +weiterhin ausschließlich v1/v2 an. Kunden-Apply bleibt separat freigabepflichtig. + + + +## Prüfungen + +Aus `landing-zone-configurator/app` mit Node 24 und installiertem `node_modules`: + +```sh +npm run check +node scripts/prepare-common-contract.ts +tofu -chdir=../.local/common-contract init -backend=false -input=false -no-color +tofu -chdir=../.local/common-contract test -no-color +``` + +Die zehn nativen Tests prüfen den unveränderten Root-Variablenvertrag ohne Provider, +Backend oder Cloud-Zugriff: acht Vorlagen plus zwei Object-Lock-Defaultfälle. +Standalone erwartet gezielt den bekannten Validierungsfehler aus Issue #84. +Dies sind keine vollständigen Modul-/Ressourcenpläne. Der native HCL-Roundtrip in +`tools/hcl-adapter` vergleicht zusätzlich alle exportierten Werte semantisch. + + + +## Gemeinsamer Editor und Speicherung + +`readConfigurationRecord` akzeptiert v1/v2/v3; `saveEditorDraft` prüft den jeweiligen +Vertrag. Die GitHub-API speichert JSON und tfvars atomar und behält die vorhandenen +Konflikt-/Pfadprüfungen bei. `prepareSnapshot` lehnt v3 vor der Verwendung von +Deployment-Credentials serverseitig mit `configuration_execution_not_supported` ab. +Dies begrenzt die Ausführung, nicht die Bearbeitung und Speicherung. + +Der Feldkatalog kennzeichnet Formularfelder, noch fehlende geschützte Bindings und +die wirkungslose Ordnerbeschreibung getrennt. Deutsche Fachbezeichnungen sind +für alle nicht-sensiblen Schemafelder per Test vorgeschrieben. UI-Anleitungen und +Abnahme: [gemeinsamer Editor](../../../docs/common-editor.de.md). diff --git a/landing-zone-configurator/app/packages/domain/README.md b/landing-zone-configurator/app/packages/domain/README.md index 2e2a569..53a20dd 100644 --- a/landing-zone-configurator/app/packages/domain/README.md +++ b/landing-zone-configurator/app/packages/domain/README.md @@ -1,59 +1,67 @@ -# Fachmodell - -Gemeinsame Logik für UI, API und Chat-Vorschläge. Keine Secret-Auflösung in diesem -Paket. Der gemeinsame Editor und die Fork-Speicherung verwenden das Modell v3. Bestehende -v1/v2-Entwürfe bleiben im bisherigen Editor bearbeitbar und können ausdrücklich -auf den gemeinsamen Editor umgestellt werden. - -## Gemeinsames Modell (v3) - -- `features.ts`: alle 28 Root-Eingaben in fachlichen Gruppen; Feldkatalog inklusive - verschachtelter Typen und separat ausgewiesener geschützter Eingaben. -- `common-document.ts`: alle acht Templates importieren, Version 1/2 migrieren, - stabile Objektidentitäten, gemeinsame Projekt-/Bereichsprojektionen und Export. -- `common-validation.ts`: Referenzen, Konfigurationskombinationen und bekannte - Ausführungsgrenzen getrennt beurteilen. Kein Ersatz für Provider-Prüfung oder Plan. -- `accelerator-inputs.json`: generierter Typvertrag, keine handgepflegte zweite - Terraform-Typdefinition. Aktualitätsprüfung in CI; siehe HCL-Adapter-README. - -`createCommonConfiguration(templateId, id)` kopiert eine vertrauenswürdige Vorlage. -`migrateCommonConfiguration(legacy)` kompiliert zunächst mit dem alten Vertrag; -anschließender Export bleibt bytegleich, auch für Ordneränderungen in v2. -`readCommonConfiguration` prüft Form, Herkunft, Eingaben und Objektidentitäten. -Unvollständige fachliche Angaben dürfen für die weitere Bearbeitung bestehen bleiben. - -Intern enthalten die Feature-Gruppen die expliziten Engine-Eingaben. Die Oberfläche -soll darauf fachliche Editoren aufsetzen, kein generisches Terraform-Variablenformular. -`commonProjects` liefert Public, Corporate und Sandbox in derselben Sicht mit -Zielordner und Bereichsbezug. `commonNetworkAreas` liefert einzelne und regionale -Bereiche ohne deren Quellen beim Lesen umzuschreiben. - -`setCommonInput` ändert Werte, **nicht** die Identitätsliste von Sammlungen. -Sammlungsänderungen brauchen explizite Operationen mit konsistenter Identitätsliste. -`renameCommonProject` erhält die UI-Identität und passt Namespace-Referenzen an; -Terraform-Adressen ändern sich dabei trotzdem. Die spätere UI muss das bestätigen -lassen. `removeCommonNetworkArea` blockiert bestehende Projekt-/Dienstreferenzen. -`editor-document.ts` ergänzt Projektanlage/-entfernung, sichere Sammlungsänderungen -und die kompatible Speicher-/Editor-Brücke. - -`compileCommonConfiguration` / `exportCommonTfvars` erhalten ausgelassene Werte, -explizites `null` und explizite Konfiguration. `effectiveInput` liefert ausschließlich -Anzeige-/Validierungswerte mit Defaults; diese Projektion darf nicht zurückexportiert -werden. Regionale `map(any)`-Eingaben werden nur für tatsächlich im Root verdrahtete -Felder akzeptiert; ihre Defaults werden nicht pauschal aus dem Einzelregionsmodell -übernommen. Unbekannte Attribute und deklarierte Secret-Eingaben werden abgelehnt, -nicht still entfernt. Ein freies Textfeld ist dadurch kein Secret-Scanner. - -`assessCommonConfiguration` liefert Konfigurationsfehler, Warnungen, bekannte -Ausführungsgrenzen und benötigte Phasen. Ein leeres Ergebnis ist **keine** -Deployment-Freigabe. Vor produktiver v3-Ausführung fehlen noch die Runner-Anbindung, -Credential-Bindings, vollständige fachliche Prüfungen, Provider-/Modultests und -serverseitig durchgesetzte Runner-Capabilities. Der bestehende Plan-Endpunkt nimmt -weiterhin ausschließlich v1/v2 an. Kunden-Apply bleibt separat freigabepflichtig. - -## Prüfungen - -Aus `landing-zone-configurator/app` mit Node 24 und installiertem `node_modules`: +# Domain model + +[English](README.md) | [Deutsch](README.de.md) + + + +Shared logic for UI, API and chat proposals. No secret resolution in this +package. The common editor and fork persistence use model v3. Existing +v1/v2 drafts remain editable in the previous editor and can explicitly +be switched to the common editor. + + + +## Common model (v3) + +- `features.ts`: all 28 root inputs in domain groups; field catalogue including + nested types and separately identified protected inputs. +- `common-document.ts`: import all eight templates, migrate versions 1/2, + stable object identities, shared project/area projections and export. +- `common-validation.ts`: assess references, configuration combinations and known + execution limits separately. No substitute for provider validation or Plan. +- `accelerator-inputs.json`: generated type contract, not a second manually maintained + Terraform type definition. Freshness checks in CI; see the HCL adapter README. + +`createCommonConfiguration(templateId, id)` copies a trusted template. +`migrateCommonConfiguration(legacy)` first compiles using the old contract; +subsequent export remains byte-identical, including folder changes in v2. +`readCommonConfiguration` checks structure, provenance, inputs and object identities. +Incomplete domain information may remain for further editing. + +Internally, the feature groups contain the explicit engine inputs. The interface +should build domain-specific editors on top, not a generic Terraform variable form. +`commonProjects` provides Public, Corporate and Sandbox in the same view with +target folder and area reference. `commonNetworkAreas` provides single and regional +areas without rewriting their sources when reading. + +`setCommonInput` changes values, **not** a collection's identity list. +Collection changes require explicit operations with a consistent identity list. +`renameCommonProject` preserves the UI identity and updates namespace references; +Terraform addresses still change. The future UI must request confirmation +for this. `removeCommonNetworkArea` blocks existing project/service references. +`editor-document.ts` adds project creation/removal, safe collection changes +and the compatible persistence/editor bridge. + +`compileCommonConfiguration` / `exportCommonTfvars` preserve omitted values, +explicit `null` and explicit configuration. `effectiveInput` supplies only +display/validation values with defaults; this projection must not be exported back. +Regional `map(any)` inputs are accepted only for fields actually wired in the root; +their defaults are not indiscriminately taken from the single-region model. +Unknown attributes and declared secret inputs are rejected, +not silently removed. This does not make a free-text field a secret scanner. + +`assessCommonConfiguration` returns configuration errors, warnings, known +execution limits and required phases. An empty result is **not** +deployment approval. Production v3 execution still lacks Runner integration, +credential bindings, complete domain checks, provider/module tests and +server-enforced Runner capabilities. The existing Plan endpoint +continues to accept v1/v2 only. Customer Apply remains subject to separate approval. + + + +## Checks + +From `landing-zone-configurator/app` with Node 24 and `node_modules` installed: ```sh npm run check @@ -62,21 +70,23 @@ tofu -chdir=../.local/common-contract init -backend=false -input=false -no-color tofu -chdir=../.local/common-contract test -no-color ``` -Die zehn nativen Tests prüfen den unveränderten Root-Variablenvertrag ohne Provider, -Backend oder Cloud-Zugriff: acht Vorlagen plus zwei Object-Lock-Defaultfälle. -Standalone erwartet gezielt den bekannten Validierungsfehler aus Issue #84. -Dies sind keine vollständigen Modul-/Ressourcenpläne. Der native HCL-Roundtrip in -`tools/hcl-adapter` vergleicht zusätzlich alle exportierten Werte semantisch. +The ten native tests check the unchanged root variable contract without providers, +backend or cloud access: eight templates plus two Object Lock default cases. +Standalone specifically expects the known validation error from issue #84. +These are not complete module/resource plans. The native HCL roundtrip in +`tools/hcl-adapter` additionally compares all exported values semantically. + + -## Gemeinsamer Editor und Speicherung +## Common editor and persistence -`readConfigurationRecord` akzeptiert v1/v2/v3; `saveEditorDraft` prüft den jeweiligen -Vertrag. Die GitHub-API speichert JSON und tfvars atomar und behält die vorhandenen -Konflikt-/Pfadprüfungen bei. `prepareSnapshot` lehnt v3 vor der Verwendung von -Deployment-Credentials serverseitig mit `configuration_execution_not_supported` ab. -Dies begrenzt die Ausführung, nicht die Bearbeitung und Speicherung. +`readConfigurationRecord` accepts v1/v2/v3; `saveEditorDraft` checks the respective +contract. The GitHub API stores JSON and tfvars atomically and retains the existing +conflict/path checks. Before using deployment credentials, `prepareSnapshot` +rejects v3 server-side with `configuration_execution_not_supported`. +This limits execution, not editing and persistence. -Der Feldkatalog kennzeichnet Formularfelder, noch fehlende geschützte Bindings und -die wirkungslose Ordnerbeschreibung getrennt. Deutsche Fachbezeichnungen sind -für alle nicht-sensiblen Schemafelder per Test vorgeschrieben. UI-Anleitungen und -Abnahme: [gemeinsamer Editor](../../../docs/common-editor.md). +The field catalogue distinguishes form fields, missing protected bindings and +the ineffective folder description. Tests require German domain labels +for all non-sensitive schema fields. UI instructions and +acceptance: [common editor](../../../docs/common-editor.md). diff --git a/landing-zone-configurator/deploy/cloud-foundry/README.de.md b/landing-zone-configurator/deploy/cloud-foundry/README.de.md new file mode 100644 index 0000000..9547f52 --- /dev/null +++ b/landing-zone-configurator/deploy/cloud-foundry/README.de.md @@ -0,0 +1,353 @@ + + +# CF-Anwendungsrelease + +[English](README.md) | [Deutsch](README.de.md) + +`.github/workflows/configurator-release.yml` baut und testet die Anwendung, +paketiert Produktionsabhängigkeiten und die per Prüfsumme gepinnte Node-24.21.0-Linux-Runtime +und deployt dasselbe Archiv mit expliziten `cf`-CLI-Befehlen. Das CF-Node-Buildpack +bietet derzeit eine ältere Node-Version an; deshalb verwenden Anwendung und Runner das +finale Binary-/Image-Buildpack des Repositorys, gepinnt auf den exakt freigegebenen Release- +Commit. Seine CF-Einstiegspunkte liegen im Repository-Verzeichnis `bin`; die Finalisierung +verwendet die bereits paketierte Node-Runtime, keine von der Plattform gewählte Node-Version. +Die reine Migrationsanwendung behält `binary_buildpack`. +Bei einem Node-Upgrade Version und Prüfsumme gemeinsam aktualisieren. Der CF-Stack bleibt +plattformseitig gepflegt (`cflinuxfs4`). + + + +## Manueller Entwicklungsrelease in GitHub + +Kein Push oder Merge deployt den Configurator. Auf der **Actions**-Seite +des Repositorys **Configurator Release** und dann **Run workflow** auswählen: + +1. Branch **main** auswählen. +2. **build_only** nicht anhaken (`false`). +3. **release_run_id** für einen neuen Release leer lassen. +4. Workflow starten. Er qualifiziert den echten Assistant, baut und testet beide + Pakete und erstellt anschließend den geschützten, quellgebundenen Buildpack-Tag. +5. Wenn **deploy** auf Prüfung wartet, über **Review deployments** das + Environment **lzc-dev-release** mit einem autorisierten Prüferkonto freigeben. +6. Auf den Erfolg des gesamten Laufs warten, einschließlich Runner-Isolation, Engine-Prüfungen, + Datenbankmigrationen, Dienstverbindungen und Prüfungen der öffentlichen Route. + +Ziel ist die bestehende Entwicklungsanwendung, keine Produktionsumgebung. +Die ausgewählte `main`-Revision bis zum Abschluss der Tag-Veröffentlichung unverändert lassen: +Ein überholter Branch-HEAD wird abgelehnt, statt stillschweigend eine andere +Revision zu deployen. Bei einem gewöhnlichen neuen Release weder Repository-Token-Rechte +erweitern noch Tags manuell erstellen. + +Für „jetzt bauen, später deployen“ **build_only** anhaken. Qualifizierung, Paketierung und Tag- +Veröffentlichung laufen weiterhin, aber es findet kein Cloud-Deployment statt. Später einen **neuen** +manuellen Lauf auf `main` starten, **build_only** nicht anhaken und die ursprüngliche +numerische Build-Run-ID unter **release_run_id** eintragen. Damit wird exakt das qualifizierte +Artefakt promoviert, ohne Qualifizierung/Build zu wiederholen oder einen historischen Commit zu taggen; +es wird nicht der neueste Anwendungsquellstand ausgewählt. Das ursprüngliche Artefakt muss +noch vorhanden und darf nicht abgelaufen sein. + +Nach einem reinen Deployment-Fehler kann eine neue Promotion den erfolgreichen +qualifizierten Build ebenso wiederverwenden. Nicht **Re-run jobs** verwenden: Release-Versuche +nach dem ersten werden abgelehnt. Vor einem weiteren Lauf den tatsächlichen Fehler prüfen; +Fehler bleiben erhalten, und der Workflow führt keine automatische Deployment- +Wiederholung durch. Historische Artefakte ohne Buildpack-Tag benötigen den unten beschriebenen +ausdrücklichen Operator-Backfill, keine Umgehung des Schutzes. + + + +### Image-Staging und Caching + +Hosted-Archive lassen ausschließlich das gepinnte `firewall-image.qcow2` aus; lokale Runner- +Archive bleiben eigenständig vollständig. CI qualifiziert zunächst das vollständige imagegestützte Paket, +extrahiert dann beide schlanken Archive, stellt das Image über den tatsächlichen Buildpack- +Einstiegspunkt wieder her und prüft bytegenaue Runner-Gleichheit sowie dieselbe Paketidentität. +Jedes komprimierte CF-Archiv muss kleiner als 384 MiB sein. + +`prepare-release.mjs` bindet `LZC_IMAGE_BUILDPACK` an +`lzc-image-buildpack-`, auch bei Promotion. +Der Git-Buildpack-Loader von CF verwendet `git clone -b`; eine reine Commit-SHA ist deshalb +keine unterstützte Referenz. Nach Qualifizierung/Build erstellt der isolierte +Job `publish_buildpack` des manuellen Release-Workflows den Lightweight-Tag am freigegebenen +Commit, solange dieser noch HEAD des gewählten Branches ist, auch in +`build_only=true`-Läufen. Er prüft zunächst +den aktiven Schutz und verwendet einen bestehenden Tag nur wieder, wenn dieser +exakt auf diesen Commit auflöst. Er aktualisiert oder löscht niemals einen Tag. +Das aktive Repository-Regelwerk **Protect LZC buildpack +tags** verbietet Updates und Löschung in diesem Namensraum, ohne Bypass-Akteure. +Das nur lesende Deployment-Gate prüft den exakt aufgelösten Commit und den aktiven +Namensraum-/Regelschutz vor dem Lesen von Deployment-Zugangsdaten. Nur der +Veröffentlichungsjob hat `contents: write`; er hat kein Cloud-Environment und keine Cloud- +Zugangsdaten und führt Helfer aus dem manuell ausgewählten Workflow-Quellstand aus, +nicht aus dem Quellstand des promovierten Artefakts. Der Deployment-Job behält `contents: read` +und die geschützte Freigabe für `lzc-dev-release`. +Promotion überspringt den schreibfähigen Veröffentlichungsjob und verlangt den +bestehenden exakten geschützten Tag des Builds. Dem normalen `GITHUB_TOKEN` kann kein +`workflows: write` gewährt werden, das GitHub zum Erstellen von Tags an historischen Commits verlangen kann; +umfangreichere Repository-Standardrechte lösen diese Einschränkung nicht. +Historische qualifizierte Artefakte ohne Tag benötigen einen ausdrücklich autorisierten +Operator-Backfill: zuerst ihren Quellstand mit `release-artifact.mjs source` validieren, +dann `buildpack-source.mjs publish` mit exakt der zurückgegebenen Revision und +Operator-Authentifizierung ausführen. Den Operator-Token niemals in CI hinterlegen oder den Tag- +Schutz deaktivieren. Ein Tag-Backfill führt kein Deployment durch. +Ältere Binary-Buildpack-Artefakte überspringen Tag-Veröffentlichung und -Prüfung. +Die privaten App-/Runner-Variablendateien +stellen diese URI ihren Manifesten bereit. Beim Staging liest das finale Buildpack +den kompilierten Image-Pin und die validierten Runner-Metadaten, lädt das öffentliche Image +direkt aus STACKIT Object Storage und prüft die vollständige SHA-256. Sein privater, +digestbasierter Staging-Download wird bei jeder Verwendung geprüft; fehlerhafte Bytes, Links oder +Capability-Abweichungen lassen das Staging scheitern. Ein Cache-Miss lädt in eine eindeutige temporäre +Datei, prüft diese und veröffentlicht sie atomar. Es sind keine Tenant-Zugangsdaten beteiligt. +Der geprüfte Download wird atomar in die Anwendung verschoben, nicht kopiert oder +als zweites großes Build-Artefakt aufbewahrt. Eine gewöhnliche Kopie erschöpfte das Staging- +Dateisystem bei der Droplet-Komprimierung; ein Hardlink ließ diese durchlaufen, aber das +zusätzliche CF-Build-Cache-Archiv erschöpfte es weiterhin. Das unveränderliche Droplet ist der +dauerhafte Image-Cache. Ein neues Staging lädt das Image einmal; Jobs tun dies nie. +Dateisystemübergreifende Verschiebungen scheitern ausdrücklich, statt das Image stillschweigend zu duplizieren. +CI prüft für beide Hosted-Archive dasselbe Gerät/dieselbe Inode und das Entfernen der temporären Quelle. +Lokale Paketierung behält ihren Digest-Cache und unabhängige Kopien. + +Das finalisierte Droplet enthält die gewöhnliche Image-Datei an ihrem ursprünglichen nativen +Pfad. Runtime-Einstiegspunkte und Jobs laden keine Images herunter. CF speichert das Droplet +und verwaltet seine Verteilung/seinen Cache auf Ausführungszellen; eine kalte Zelle kann +dieses Droplet intern abrufen. Im Buildpack-Cache pro App wird kein redundantes großes Image +aufbewahrt, und kein veränderlicher Tenant-Workspace wird geteilt. Die Inspektionskopie der API +wird identisch finalisiert. Die Migration inspiziert den Runner nicht und führt ihn nicht aus +und stellt deshalb ihr ungenutztes Inspektionsimage nicht wieder her. + +Dies vermeidet den beobachteten CF-API-Uploadfehler: HTTP 502 nach 900 Sekunden bei +601.91 von 926.12 MiB, ohne die Image-Prüfung abzuschwächen, veränderliche Job-Dateien +zu teilen oder ein konfiguriertes höheres Uploadlimit zu behaupten. +Die Web-/API-App verwendet 6144 MiB Festplatte: Ihre zusätzliche Inspektionskopie erschöpfte +bei der Droplet-Komprimierung die vorherigen 4096 MiB Staging-Festplatte selbst nach Entfernung +des redundanten Image-Caches. Runner-Template und isolierte Job-/Task-Budgets bleiben bei +4096 MiB; das gemessene native Runner-Runtime-Budget bleibt unverändert. +Scheitert Runner-Staging, meldet der Release zusätzlich Status und Fehler des neuesten V3-Builds +sowie aktuelle Runner-Logs, weiterhin auf den isolierten Runner-Space begrenzt. +Runner- und Web-/API-Diagnosen lesen beide das mit dem fehlgeschlagenen Build verknüpfte Droplet, +nicht das aktuelle (möglicherweise noch gesunde) Droplet der Anwendung, und melden dessen +Status, Fehler und Zeitstempel. Ein generischer Build-`StagingError` kann den spezifischeren +Droplet-Fehler `StagingTimeExpired` verdecken, selbst nachdem der Lifecycle mit null endet +und einen abgeschlossenen Droplet-Upload protokolliert. Eine vorhergehende Meldung über fehlendes Buildpack-`config.yml` +ist allein kein Fehlernachweis: Der Lifecycle meldet sie ohne +zu scheitern, und auch erfolgreiche Releases haben sie ausgegeben. Build- und +Droplet-Status vor Buildpack-Codeänderungen oder Wiederholungen prüfen. `CF_STAGING_TIMEOUT` +steuert nur die Wartezeit der CLI; es verlängert keinen plattformseitigen Timeout. +Lässt die Plattform das Staging-Ergebnis ablaufen, Build-/Droplet-Kennungen +und Zeitstempel für die Untersuchung durch Operator/Provider aufbewahren. Image- +Prüfung nicht abschwächen, geschützte Quell-Tags nicht umhängen und keine automatischen Deployment-Wiederholungen ergänzen. +So bleiben Lifecycle-/Cache-Uploadfehler von der Buildpack-Image-Prüfung unterscheidbar. +Fehlgeschlagenes Web-Staging meldet nur Staging-Logeinträge (`STG`), +niemals Router-/Callback-Logs, die OAuth-Codes enthalten könnten, sowie V3-Staging-Limits. + +`manifest.yml` verwaltet Anwendung, Route, Prozessgröße, Health Check und Backend- +Umgebungsbindungen. OpenTofu verwaltet CF-Org/-Space/-Rollen und Backend-Dienste; +es verwaltet nicht zusätzlich die Anwendung. Der Plan-Runner wird separat in `lzc-dev-runners/plans` ohne Anwendungs-Service-Bindungen gestaged. + +Das geschützte Environment `lzc-dev-release` enthält Workload-S3-Zugangsdaten und +Plattform-/Runtime-State-Schlüssel. Dem Release-Workflow wird kein Projekt-Service-Account-Schlüssel +übergeben. `tofu output -json` schreibt private Dateien; `prepare-release.mjs` +extrahiert nur ausdrücklich erlaubte Backend-Variablen und maskiert sie. `cf push` +verwendet eine private Variablendatei und `--redact-env`; weder Zugangsdaten noch entschlüsselte +States sind im Anwendungsartefakt enthalten. Die App erhält nur ihre eigenen +PostgreSQL-/Secrets-Zugangsdaten, den Operator-Model-Serving-Token und die GitHub- +App-OAuth-Client-Zugangsdaten. Der Benutzer hat deren Übertragung nach +`lzc-dev-release` und in CF-Backend-Variablen am 2026-09-30 ausdrücklich freigegeben. `LZC_AUTH_ENABLED=true` +aktiviert die Anmeldung; das Client-Secret gelangt niemals in den Frontend-Build. + +STACKIT wird zur primären Anmeldung, wenn das geschützte Environment sowohl +`LZC_STACKIT_DEVICE_ENABLED=true` als auch `LZC_AUTH_ENABLED=true` setzt. Der ältere +Name `DEVICE_ENABLED` ist ein Provider-Schalter, kein Selektor der Authentifizierungsmethode. +Lokaler und Hosted-Start verwenden dieselbe Implementierung `configuredStackitFlow`. +Das geschützte Environment liefert die explizite PKCE-Konfiguration: + +| Variable | Hosted-Konfiguration | +| --- | --- | +| `LZC_STACKIT_AUTH_FLOW` | `authorization-code` | +| `LZC_STACKIT_CLIENT_ID` | Registrierter öffentlicher Web-Client mit PKCE-Unterstützung | +| `LZC_STACKIT_REDIRECT_URI` | Öffentlicher Origin gefolgt von `/auth/stackit/callback` | + +`LZC_ASSISTANT_ENABLED=true` im geschützten Environment setzen, um den +authentifizierten Assistant und die Template-Beratung in der Hosted-API zu aktivieren. Workflow, +Release-Vorbereitung und Manifest reichen dieses Opt-in an CF weiter; standardmäßig bleibt es deaktiviert, +und die Release-Vorbereitung lehnt die Aktivierung ohne Authentifizierung ab. +Der bestehende Runtime-Model-Serving-Token bleibt ausschließlich im Backend. + +Sowohl den Anmelde- als auch den HTTPS-Callback `/auth/stackit/proof-callback` bei diesem +Client registrieren. Die Callbacks müssen zum konfigurierten `LZC_PUBLIC_ORIGIN` gehören; Query- +Strings, Fragmente und eingebettete Zugangsdaten werden abgelehnt. Es gibt keinen stillen +Fallback auf Device Flow. `LZC_STACKIT_CLI_CLIENT_APPROVED` erlaubt nur ausdrücklich +die lokale Wiederverwendung des CLI-Clients: Dieser Client bleibt auf Loopback-Anwendungen +und seine registrierten localhost-Ports begrenzt. Ein Hosted-Web-Client benötigt keine CLI-Freigabe. +Der lokale Entwicklungshelfer liefert Loopback-Defaults und ein Callback-Relay; +er wählt keine andere PKCE-Implementierung. + +Der erfolgreiche Provider-Wechsel am 2026-10-07 verwendete Device Flow und qualifizierte +deshalb Hosted-PKCE nicht. Ein registrierter Web-Client und beide HTTPS-Callbacks sind +vor dem Deployment dieser Version erforderlich. Die Release-Vorbereitung validiert die tatsächliche +Konfiguration des kompilierten Artefakts vor dem ersten CF-Staging, und die Prüfungen öffentlicher Routen +verlangen neben dem primären Provider auch `stackitFlow: "authorization-code"`. +GitHub bleibt eine optionale Repository-Verbindung. GitHub-Zugangsdaten sind im +STACKIT-Modus optional, müssen bei aktiviertem Repository-Zugriff aber als vollständiges Paar +konfiguriert sein. Alle fehlenden versionierten Migrationen laufen vor dem Start der neuen Anwendung. +Bestehende GitHub-Benutzer vor dem Wechsel ihrer Anmeldung über eine gültige Session binden; +es gibt keine automatische Kontenzusammenführung per E-Mail. + +Für diesen Entwicklungsmeilenstein ist die CF-Deployment-Identität weiterhin der bestehende +Org-Manager mit expliziter Space-Developer-Mitgliedschaft, und der Release liest Plattform- +State. Ein dedizierter, auf den Space begrenzter Deployer und enger begrenzte State-/Credential-Veröffentlichung +sind vor Produktion erforderlich. CF-Umgebungsvariablen sind für autorisierte +Space-Developer sichtbar; diese Rollen einschränken und auditieren. Nicht authentifizierte +Anfragen an geschützte API-Routen bleiben abgewiesen. Die GitHub-Anmeldung verwendet serverseitige +opake Sessions; siehe [Anmeldearchitektur und Abnahme](../../docs/github-login.de.md). + +Nach dem Push führt ein CF-Task PostgreSQL-Authentifizierung, eine Abfrage mit geprüftem TLS +und Secrets-Manager-Authentifizierung sowie ein GET auf den reservierten Operator-Probe-Pfad +`configurator/connectivity-probe` durch. Anonymer Zugriff muss abgewiesen werden; authentifizierter +Zugriff darf für den fehlenden Schlüssel 404 liefern. Es werden keine Tenant-Secrets gelesen oder geschrieben. +Bei aktivierter Anmeldung schreibt und liest der Task zusätzlich einen +zufälligen Probe-Schlüssel, löscht ihn dauerhaft und prüft anschließend seine Abwesenheit. Die Runtime-Identität hat ausdrücklich +genehmigten Schreibzugriff auf die dedizierte Configurator-Secrets-Manager-Instanz. Diagnoselogs zeigen nur +Dienstnamen, Ergebnis und bereinigte Fehlerkategorien. Der Task widerruft seinen Vault- +Token. Ein Health Check allein beweist keine Dienstkonnektivität. + +Alle Mutationen teilen `configurator-lzc-dev-mutation` mit Infrastruktur-Workflows. +Feature-Branch-Releases benötigen Environment-Freigabe. Eine überholte Branch-Revision +wird für einen neuen Build abgelehnt; eine explizite Promotion verwendet die exakte Quellrevision +des ausgewählten qualifizierten Builds, selbst wenn der Branch fortgeschritten ist. GitHub-Concurrency ist nicht FIFO: Neuere wartende Läufe +können ältere wartende Läufe ersetzen. Lokale Applies oder Pushes niemals parallel ausführen. + +Der initiale Einzelinstanz-`cf push` kann den Dienst kurz unterbrechen. Rolling +Releases bleiben ein nachfolgender Meilenstein. Versionierte SQL-Migrationen laufen vor dem Web- +Release in `landing-zone-configurator-migrate`, einer separaten Task-only-App ohne +Route. Nur diese kurzlebige App erhält die Datenbank-Owner-Zugangsdaten; sie wird +nach der Migration und bei Fehlern gelöscht. Migrationsprüfsummen und ein Advisory Lock +sichern wiederholte Ausführung ab. Die Web-App verwendet ihre eingeschränkte Runtime-Rolle und RLS. +Migrations-App und ihr Task benötigen beide 4096 MB Festplattenquota, weil sie +den vollständigen unveränderlichen Web-Release einschließlich der gepinnten Inspektionsruntime entpacken. +Das frühere Limit von 512 MB scheiterte beim Extrahieren des Containers, bevor Node oder irgendein +Migrationscode startete. Der Task behält sein Speicherlimit von 128 MB. +Der exakte qualifizierte Release enthält allein 505.65 MiB Nutzlast regulärer Dateien; +Dateisystemblöcke, Verzeichnisse und Container verursachen zusätzlichen Overhead. +Die nachfolgenden Tasks für Netzwerk, Dienstverbindung und Runner-Isolation +entpacken dieses Droplet ebenfalls und verwenden dieselbe Festplattenquota von 4096 MB. +Diagnosen des Migrationstasks melden nur Release-Run-ID, Verbindungs-/Migrations- +phase, Migrationsdateiname und eine erlaubte Fehlerkategorie oder SQLSTATE. +Der Release filtert Task-Logs vor der Bereinigung; rohes SQL, Zeilenwerte, Zugangsdaten +und nicht zugehörige CF-/Router-Logzeilen werden niemals nach CI exportiert. +Das Web-Manifest verwendet den registrierten suffixfreien Dev-Origin. Nach erfolgreichen kanonischen +Routenprüfungen entfernt der Release die historische Route mit Suffix von dieser App, +falls sie noch gebunden ist. Er löscht weder die gemeinsame Domain noch Routen anderer Apps. +Kunden-Pläne und ausdrücklich bestätigte Saved-Plan-Applies/Destroy verwenden kurzlebige +Runner-Tasks. Application-Drift ist schreibgeschützt. Hosted-Ausführung benötigt zusätzlich +`LZC_EXECUTION_ENABLED=true`, `LZC_APPLICATION_EXECUTION_ENABLED=true` und das +geschützte Environment-Secret `LZC_DEPLOYMENT_ARTIFACT_KEY` (kanonisches Base64 von +32 Zufallsbytes). Diesen Schlüssel über Releases hinweg beibehalten; niemals zur Reparatur eines Jobs ersetzen. +Der Release bindet die Ausführung an das exakt gestagte Droplet und paketiert dieselben +OpenTofu-/Provider-/Quellbytes in der API zur backendfreien Saved-Plan-Inspektion. +Nur der isolierte Runner erhält Job-Zugangsdaten. Der API-Inspektionsunterprozess +hat eine minimale Umgebung ohne Datenbank-, Vault- oder Cloud-Zugangsdaten. Die API +verwendet für diese Inspektion 1024 MiB Speicher und 4096 MiB Festplatte; der Release validiert +beide nativen Roots und prüft beide Broker-Namensräume mit ungültigen Tickets. +Alte Pläne werden nach einem Droplet-Wechsel nicht neu gebunden. Siehe [Plan-Ausführung](../../docs/plan-execution.de.md). + + + +### Voraussetzung für Dev-Aktivierung (aktualisiert 2026-10-14) + +Der einzige Ziel-Origin ist +`https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud`, ohne Suffix. +Das Client-Team bestätigte, dass der öffentliche Web-Client jetzt in STACKIT +Production registriert ist; die erste Registrierung erfolgte irrtümlich in QA. Der Client verwendet +JWT-Access-Tokens, Response-Typ `code`, Authorization-Code- und Refresh-Token- +Grants, verpflichtendes PKCE und die Scopes `openid`, `email`, `offline_access`. Bestätigte +Audiences sind `api://StackitApp` und `api.stackit.cloud`. Die Anwendung verwendet bereits +den Production-Issuer `https://accounts.stackit.cloud`, PKCE/S256 und einen +Tokenaustausch ohne Secret. Das automatisch erzeugte Client-Secret ist nicht +erforderlich und darf nicht zur STACKIT-Anmeldekonfiguration hinzugefügt werden. + +Die öffentliche `LZC_STACKIT_CLIENT_ID` wurde mit Benutzerfreigabe am +2026-10-14 zu `lzc-dev-release` hinzugefügt und durch Rücklesen der Variable geprüft. Es wurde kein STACKIT-Client-Secret +übertragen und kein Deployment ausgelöst. Die Registrierungsbestätigung +qualifiziert keine Hosted-Anmeldung: +Beide exakten Callbacks und die Organisationszugriffsprüfung benötigen noch einen Ende-zu-Ende- +Test. Keine zweite Client-Anfrage ist erforderlich. +Die bestehende Route mit Suffix wurde nur als schreibgeschützte Baseline geprüft, +nicht als Deployment-Ziel ausgewählt. Release-Route, Public Origin und Callbacks +verwenden alle den suffixfreien Origin. + +Vor Promotion in `lzc-dev-release` `LZC_STACKIT_AUTH_FLOW=authorization-code`, die provisionierte +öffentliche `LZC_STACKIT_CLIENT_ID`, +`LZC_STACKIT_REDIRECT_URI=https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud/auth/stackit/callback` +und `LZC_STACKIT_CLI_CLIENT_APPROVED=false` setzen. Der angeforderte +PKCE-/S256-Client benötigt beide HTTPS-Callbacks, `/auth/stackit/callback` und +`/auth/stackit/proof-callback`. Der CLI-Client kann nicht für einen öffentlichen +Callback wiederverwendet werden. Es findet kein Device-Flow- oder GitHub-Fallback statt. +Der Benutzer hat Commit/Push/Dev-Deployment freigegeben, aber keine zusätzlichen Datenbank- +Backups gewünscht und verlässt sich auf geplante STACKIT-Backups. Kunden-Plan/Apply/Destroy bleiben +separate ausdrückliche Operationen, kein Bestandteil der Anwendungsrelease-Validierung. + +Rohe CF-Logs werden nicht nach CI exportiert, da Router-URLs OAuth-Codes enthalten können. +Task-Status, bereinigte Diagnosen und öffentliche Health Checks liefern Release-Nachweise. + + + +## Unveränderlicher Release und Promotion + +Einmal bauen; dieselben Bytes deployen. Der Workflow veröffentlicht ein unveränderliches GitHub- +Artefakt `configurator-release-` mit einem zentralen +`configurator-release.tar.gz` und dessen SHA-256-Prüfsumme. Darin liegen die kompilierte +API, Web-Assets, Migrationen und gepinnte Node-Runtime in `release.tar.gz` sowie das +isolierte `runner.tar.gz` und `release-manifest.json`. Das Manifest bindet beide +Pakete über ihre SHA-256-Prüfsummen an Build-Run-ID und Quellcommit. +Keine Stage-Konfiguration und keine Zugangsdaten gelangen in diesen Release. + +Bauen und qualifizieren, ohne CF zu verändern: + +```sh +gh workflow run configurator-release.yml \ + --ref feature/landing-zone-configurator -f build_only=true +``` + +Diesen erfolgreichen Build ohne Neubau in das geschützte Dev-Environment promovieren: + +```sh +gh workflow run configurator-release.yml \ + --ref feature/landing-zone-configurator -f release_run_id= +``` + +Promotion prüft Repository, erlaubten Quellbranch und Event, Workflow, +erfolgreichen Build-Job, ursprünglichen Run-Versuch, nicht abgelaufene unveränderliche Artefakt-ID und +passende Quell-SHA. Sie checkt diese Quellrevision aus, prüft das zentrale +Archiv und Manifest vor dem Extrahieren der Anwendung und injiziert dann die aktuellen +Runtime-Variablen und Secrets des geschützten Environments. Environment-Freigabe, +Zielbeschränkungen, Migrationsschutz und Dienstprüfungen gelten weiterhin. +Artefakte werden 30 Tage aufbewahrt; abgelaufene Artefakte werden nicht stillschweigend neu gebaut. + +Derzeit ist nur Dev als Deployment-Ziel aktiviert. Weitere Stages benötigen ihre +eigene geprüfte Zielkonfiguration und geschützte Environments, keine separaten +Anwendungsbuilds oder Authentifizierungsimplementierungen. Das Promovieren älterer Bytes ist +kein automatischer Datenbank-Rollback: Migrationen sind nur vorwärtsgerichtet, und das Zurücksetzen +von Anwendungscode erfordert ausdrückliche Qualifizierung der Schemakompatibilität. + + + +## Netzwerkprüfung + +Der Release enthält einen diagnostischen CF-Task für DNS/TCP und eine HTTPS-Anfrage an die +eigene Configurator-Route. Der passende CF-Router-Eintrag identifiziert das beobachtete +Quellnetz ohne Kontakt zu einem externen IP-Diagnosedienst. Dies ist eine +Momentaufnahme, keine Zusage stabiler CF-Egress-Adressen. + +Der erste Verbindungstest zeigte ein fehlendes STACKIT-Netz in den Dienst-ACLs. +Der offizielle eu01-Katalog und unsere eigenen Router-Logs stützen die Ergänzung von +`45.135.244.0/22` über Plattform-IaC. Netzwerkpolicy-Änderungen erfordern einen geprüften +Plattform-Plan und danach einen frischen CF-Konnektivitätstest. Die öffentlichen UI-/API-Prüfungen laufen +auch bei fehlgeschlagener Dienstverbindung, damit Route- und Dienstzustand +getrennt sichtbar bleiben. Siehe [Plattformabnahme](../../docs/platform-readiness.de.md). + +Der API-Dispatcher erhält zusätzlich die Manager-Zugangsdaten für die dedizierte +Runner-Organisation, nicht die Configurator-Organisation. Dies isoliert die CF-Steuerung +von den Datenbank-/Secret-/Model-Bindungen der Web-App. Diese Zugangsdaten gelangen niemals +in das Runner-Paket oder die Job-App. Der Release prüft Runner-Organisations- und +Space-IDs, staged den Provider-Mirror, testet die Engine und prüft eine kurzlebige +Runner-App mit einem nicht registrierten Ticket. diff --git a/landing-zone-configurator/deploy/cloud-foundry/README.md b/landing-zone-configurator/deploy/cloud-foundry/README.md index b776755..b92115b 100644 --- a/landing-zone-configurator/deploy/cloud-foundry/README.md +++ b/landing-zone-configurator/deploy/cloud-foundry/README.md @@ -1,5 +1,7 @@ # CF application release +[English](README.md) | [Deutsch](README.de.md) + `.github/workflows/configurator-release.yml` builds and tests the application, packages production dependencies and the checksum-pinned Node 24.21.0 Linux runtime, and deploys the same archive with explicit `cf` CLI commands. The CF node buildpack diff --git a/landing-zone-configurator/deploy/github/README.de.md b/landing-zone-configurator/deploy/github/README.de.md new file mode 100644 index 0000000..d9034ac --- /dev/null +++ b/landing-zone-configurator/deploy/github/README.de.md @@ -0,0 +1,42 @@ +# GitHub App + +[English](README.md) | [Deutsch](README.de.md) + +`app-manifest.json` ist der prüfbare Registrierungsentwurf für lzc-dev. Er registriert +selbst keine App, erzeugt keine Zugangsdaten, installiert keine App und aktiviert keine Anmeldung. +Am 2026-09-30 unter `lweberru` als `lz-configurator-dev-7dbff805` registriert; siehe [Registrierungsstatus](registration-plan.de.md). + +GitHub-App-Benutzerautorisierung mit ablaufenden User-Access-Tokens verwenden. Repository- +Operationen müssen das Token des angemeldeten Benutzers verwenden, niemals die GitHub-CLI- +Sitzung des Operators, einen zentralen PAT oder ein Installation-Token. Token-Ablauf aktiviert lassen. + +Angeforderte Berechtigungen: + +- Metadata read: Repository-Identität und Zugriffsprüfungen. +- Contents write: Vorlagen lesen und eine Konfiguration in den gewählten Fork committen. +- Administration write: vom Fork-Endpunkt benötigt; über den Configurator außer + dem Erstellen eines Forks keine Repository-Verwaltungsoperation anbieten. + +Für API-erzeugte Forks muss eine GitHub App sowohl im Upstream-Konto als auch im Zielkonto +installiert sein. Ohne diese Voraussetzungen die manuelle Fork-Seite von GitHub anbieten +und anschließend den bestehenden Fork verbinden. Berechtigungsumfang nicht stillschweigend +erweitern und keine Operator-Zugangsdaten verwenden. Diese Voraussetzungen mit der registrierten +App prüfen, bevor Ende-zu-Ende-Fork-Unterstützung behauptet wird. + +Callback-URL: +`https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud/auth/github/callback` + +Beim Wechsel der Dev-Route Homepage und Callback-URL der bestehenden GitHub App +vor dem Test der GitHub-Autorisierung entsprechend aktualisieren. Eine Manifeständerung +ändert keine bereits registrierte App. App-Name und Installations-URL bleiben +unverändert. + +Nach der Registrierung zu provisionierende Backend-Eingaben: `LZC_GITHUB_CLIENT_ID` und +`LZC_GITHUB_CLIENT_SECRET`. Das Client-Secret muss über geschützte +Runtime-Konfiguration bereitgestellt werden, niemals committet oder in einen Frontend-Build aufgenommen werden. Die Registrierung ist abgeschlossen; die Deployment-Bindung steht aus. Die Anmeldung bleibt deaktiviert, bis Session-Persistenz, +PKCE-/State-Prüfung und sichere Token-Speicherung implementiert und verifiziert sind. + +Quellen: +- https://docs.github.com/en/apps/creating-github-apps/setting-up-a-github-app/registering-a-github-app +- https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app +- https://docs.github.com/en/rest/repos/forks#create-a-fork diff --git a/landing-zone-configurator/deploy/github/README.md b/landing-zone-configurator/deploy/github/README.md index d77adcd..3f25c9c 100644 --- a/landing-zone-configurator/deploy/github/README.md +++ b/landing-zone-configurator/deploy/github/README.md @@ -1,5 +1,7 @@ # GitHub App +[English](README.md) | [Deutsch](README.de.md) + `app-manifest.json` is the reviewable registration draft for lzc-dev. It does not register an app, create credentials, install an app or activate login by itself. Registered on 2026-09-30 under `lweberru` as `lz-configurator-dev-7dbff805`; see [registration status](registration-plan.md). diff --git a/landing-zone-configurator/deploy/github/registration-plan.de.md b/landing-zone-configurator/deploy/github/registration-plan.de.md new file mode 100644 index 0000000..526eede --- /dev/null +++ b/landing-zone-configurator/deploy/github/registration-plan.de.md @@ -0,0 +1,55 @@ + + +# Einmalige GitHub-App-Registrierung + +[English](registration-plan.md) | [Deutsch](registration-plan.de.md) + +Registrierung am 2026-09-30 durch den Benutzer abgeschlossen. Die App gehört zum Configurator-Projekt; +sie ist kein Benutzer-Token und kein zentrales Repository-Servicekonto. + + + +## Konkrete Registrierung + +- Name: `LZ Configurator Dev 7dbff805` (Verfügbarkeit wird von GitHub geprüft). +- Bestätigter Owner für Entwicklung: `lweberru`; später an `stackitcloud` übertragbar. +- Alternative: `stackitcloud`, sofern der angemeldete Benutzer Apps für die Organisation anlegen darf. + Die geprüfte Organisationsmitgliedschaft von `lweberru` ist `member`, nicht `admin`. +- Sichtbarkeit: öffentlich installierbare App für mehrere unabhängige Benutzer/Kunden. +- Homepage und OAuth-Callback: siehe `app-manifest.json`. +- Repository-Rechte: Metadata read, Contents write, Administration write. + GitHub verlangt Administration write für die Fork-API. Diese Berechtigung ist + umfassender als der vom Configurator angebotene Fork-Vorgang; Installationen + deshalb auf die benötigten Repositories begrenzen. Für automatische Forks gelten + zusätzliche GitHub-Installationsvoraussetzungen, siehe README. +- Keine Operator-PATs oder Installation-Tokens für Benutzer-Repository-Aktionen. +- Expiring User Tokens aktiviert lassen; initial erneute Anmeldung nach höchstens 8 Stunden. + + + +## Registrierung und Credential-Ablage + +Nach ausdrücklicher Freigabe einen nur an `127.0.0.1` gebundenen, kurzlebigen +Registrierungshelfer starten. Die lokale Seite enthält das versionierte Manifest +und führt den Benutzer zur GitHub-Bestätigung. State und Browserbindung absichern; +den Code einmalig gegen Client-ID/Client-Secret tauschen. Kein Auslesen bestehender +Browser-Credentials, kein Secret im Chat oder Log. + +Client-ID/Client-Secret ausschließlich unter `.local/github/app-registration.json` +mit Dateimodus 0600 ablegen. Einen erzeugten GitHub-App-Private-Key nicht für +Repository-Zugriffe verwenden. Backend-Bindung und Environment-Secrets folgen als +getrennter, prüfbarer Deployment-Schritt; keine Secrets im Manifest oder Frontend. + +## Status + +- [x] Owner und Rechte ausdrücklich freigegeben. +- [x] App registriert: https://github.com/apps/lz-configurator-dev-7dbff805 +- [x] Client-Zugangsdaten lokal mit Modus 0600 gespeichert; keine Secrets versioniert. +- [x] Manifest korrigiert: `hook_attributes.url` ist auch bei `active: false` erforderlich. +- [ ] Installation auf ausgewählten Benutzer-Repositories bestätigen. +- [x] Geschützte Backend-Bindung und OAuth-Weiterleitung live geprüft (Release 36695423593). +- [x] Persönliche Anmeldung und Abmeldung vom Benutzer bestätigt. + +Installation: https://github.com/apps/lz-configurator-dev-7dbff805/installations/new + +Quelle: https://docs.github.com/en/apps/sharing-github-apps/registering-a-github-app-from-a-manifest diff --git a/landing-zone-configurator/deploy/github/registration-plan.md b/landing-zone-configurator/deploy/github/registration-plan.md index 34bcd23..d8356d7 100644 --- a/landing-zone-configurator/deploy/github/registration-plan.md +++ b/landing-zone-configurator/deploy/github/registration-plan.md @@ -1,47 +1,55 @@ -# Einmalige GitHub-App-Registrierung - -Registrierung am 2026-09-30 durch den Benutzer abgeschlossen. Die App gehört zum Configurator-Projekt; -sie ist kein Benutzer-Token und kein zentrales Repository-Servicekonto. - -## Konkrete Registrierung - -- Name: `LZ Configurator Dev 7dbff805` (Verfügbarkeit wird von GitHub geprüft). -- Bestätigter Owner für Entwicklung: `lweberru`; später an `stackitcloud` übertragbar. -- Alternative: `stackitcloud`, sofern der angemeldete Benutzer Apps für die Organisation anlegen darf. - Die geprüfte Organisationsmitgliedschaft von `lweberru` ist `member`, nicht `admin`. -- Sichtbarkeit: öffentlich installierbare App für mehrere unabhängige Benutzer/Kunden. -- Homepage und OAuth-Callback: siehe `app-manifest.json`. -- Repository-Rechte: Metadata read, Contents write, Administration write. - GitHub verlangt Administration write für die Fork-API. Diese Berechtigung ist - umfassender als der vom Configurator angebotene Fork-Vorgang; Installationen - deshalb auf die benötigten Repositories begrenzen. Für automatische Forks gelten - zusätzliche GitHub-Installationsvoraussetzungen, siehe README. -- Keine Operator-PATs oder Installation-Tokens für Benutzer-Repository-Aktionen. -- Expiring User Tokens aktiviert lassen; initial erneute Anmeldung nach höchstens 8 Stunden. - -## Registrierung und Credential-Ablage - -Nach ausdrücklicher Freigabe einen nur an `127.0.0.1` gebundenen, kurzlebigen -Registrierungshelfer starten. Die lokale Seite enthält das versionierte Manifest -und führt den Benutzer zur GitHub-Bestätigung. State und Browserbindung absichern; -den Code einmalig gegen Client-ID/Client-Secret tauschen. Kein Auslesen bestehender -Browser-Credentials, kein Secret im Chat oder Log. - -Client-ID/Client-Secret ausschließlich unter `.local/github/app-registration.json` -mit Dateimodus 0600 ablegen. Einen erzeugten GitHub-App-Private-Key nicht für -Repository-Zugriffe verwenden. Backend-Bindung und Environment-Secrets folgen als -getrennter, prüfbarer Deployment-Schritt; keine Secrets im Manifest oder Frontend. +# One-time GitHub App registration + +[English](registration-plan.md) | [Deutsch](registration-plan.de.md) + + + +Registration completed by the user on 2026-09-30. The App belongs to the Configurator project; +it is neither a user token nor a central repository service account. + + + +## Registration details + +- Name: `LZ Configurator Dev 7dbff805` (availability is checked by GitHub). +- Confirmed development owner: `lweberru`; transferable to `stackitcloud` later. +- Alternative: `stackitcloud`, provided the signed-in user may create Apps for the organization. + The verified organization membership of `lweberru` is `member`, not `admin`. +- Visibility: publicly installable App for multiple independent users/customers. +- Homepage and OAuth callback: see `app-manifest.json`. +- Repository permissions: Metadata read, Contents write, Administration write. + GitHub requires Administration write for the fork API. This permission is + broader than the fork operation offered by the Configurator; therefore limit + installations to the required repositories. Automatic forks have + additional GitHub installation prerequisites; see README. +- No operator PATs or installation tokens for user repository actions. +- Keep Expiring User Tokens enabled; initially sign in again after at most 8 hours. + + + +## Registration and credential storage + +After explicit approval, start a short-lived registration helper bound +only to `127.0.0.1`. The local page contains the versioned manifest +and takes the user to GitHub confirmation. Secure state and browser binding; +exchange the code once for client ID/client secret. Do not read existing +browser credentials; no secret in chat or logs. + +Store client ID/client secret exclusively under `.local/github/app-registration.json` +with file mode 0600. Do not use a generated GitHub App private key for +repository access. Backend binding and environment secrets follow as a +separate, reviewable deployment step; no secrets in the manifest or frontend. ## Status -- [x] Owner und Rechte ausdrücklich freigegeben. -- [x] App registriert: https://github.com/apps/lz-configurator-dev-7dbff805 -- [x] Client-Zugangsdaten lokal mit Modus 0600 gespeichert; keine Secrets versioniert. -- [x] Manifest korrigiert: `hook_attributes.url` ist auch bei `active: false` erforderlich. -- [ ] Installation auf ausgewählten Benutzer-Repositories bestätigen. -- [x] Geschützte Backend-Bindung und OAuth-Weiterleitung live geprüft (Release 36695423593). -- [x] Persönliche Anmeldung und Abmeldung vom Benutzer bestätigt. +- [x] Owner and permissions explicitly approved. +- [x] App registered: https://github.com/apps/lz-configurator-dev-7dbff805 +- [x] Client credentials stored locally with mode 0600; no secrets versioned. +- [x] Manifest corrected: `hook_attributes.url` is required even with `active: false`. +- [ ] Confirm installation on selected user repositories. +- [x] Protected backend binding and OAuth redirect verified live (release 36695423593). +- [x] Personal login and logout confirmed by the user. Installation: https://github.com/apps/lz-configurator-dev-7dbff805/installations/new -Quelle: https://docs.github.com/en/apps/sharing-github-apps/registering-a-github-app-from-a-manifest +Source: https://docs.github.com/en/apps/sharing-github-apps/registering-a-github-app-from-a-manifest diff --git a/landing-zone-configurator/deploy/runner/README.de.md b/landing-zone-configurator/deploy/runner/README.de.md new file mode 100644 index 0000000..057c151 --- /dev/null +++ b/landing-zone-configurator/deploy/runner/README.de.md @@ -0,0 +1,36 @@ + + +# Gepinnter Accelerator für Kunden-Pläne + +[English](README.md) | [Deutsch](README.de.md) + +Quelle: `stackitcloud/stackit-landing-zone`, Commit +`a256f6896d11134fdc351786f1be5eba4e56b2e2` (derselbe Stand wie Vorbereitungen). +Engine: OpenTofu **1.12.6**. `accelerator.lock.hcl` wurde aus einem sauberen +`git archive` dieses Commits mit `tofu init -backend=false` und +`tofu providers lock -platform=linux_amd64 -platform=darwin_arm64` erzeugt. +Der Quellcommit enthält kein eingechecktes Root-Lockfile. Der Configurator besitzt +deshalb einen separaten Lock für genau diese Code-Version; das Accelerator-Original +wird nicht verändert. Provider-Updates verlangen eine neue gemeinsame Qualifizierung. + +Im späteren Build wird die Datei als `src/.terraform.lock.hcl` in das isolierte +Accelerator-Paket kopiert. Anschließend ausschließlich `tofu init -lockfile=readonly`. +Linux-Checksummen sind erfasst. Die Release-Pipeline prüft init/validate und die +CF-Isolation vor der Abnahme; aktueller Status steht im Abnahmedokument. Der opnsense- +Provider wurde vom Registry-Download ohne GPG-Signatur angeboten; Checksummen sind +gepinnt, dies ist kein Signaturnachweis dieses Providers. + +`package.sh` baut ein separates Binary-Paket mit Node, OpenTofu und +Provider-Mirror; `manifest.yml` staged ein task-only CF-Template ohne Bindings. +Der finale Image-Buildpack wird über `LZC_IMAGE_BUILDPACK` auf den freigegebenen +Release-Commit gepinnt; die geschützte Pipeline liefert die Runner-Variablendatei. +Hosted-Archive enthalten die qualifizierte Image-SHA statt der großen QCOW2-Datei. +Beim Staging wird diese aus STACKIT Object Storage geladen, SHA-geprüft und +ohne zusätzliche Dateikopie am ursprünglichen Pfad ins Droplet verschoben. +Das unveränderliche CF-Droplet ist der dauerhafte Cache; ein redundantes großes +Buildpack-Cache-Archiv wird vermieden. +CI prüft dafür die bytegleiche Wiederherstellung und unveränderte Paketidentität. +Lokale Archive bleiben vollständig. Es gibt keinen Download pro Nutzer oder Plan. +Details und Grenzen: [CF-Staging und Cache](../cloud-foundry/README.de.md#image-staging-and-caching). +Der Dispatcher kopiert dessen Droplet in eine neue App pro Auftrag. Direkte +OpenTofu-Schritte stehen in `run-plan.sh`. Ablauf und Freigabegrenzen: [Plan-Ausführung](../../docs/plan-execution.de.md). diff --git a/landing-zone-configurator/deploy/runner/README.md b/landing-zone-configurator/deploy/runner/README.md index de12d80..f6fa7f9 100644 --- a/landing-zone-configurator/deploy/runner/README.md +++ b/landing-zone-configurator/deploy/runner/README.md @@ -1,32 +1,36 @@ -# Gepinnter Accelerator für Kunden-Pläne +# Pinned Accelerator for customer Plans -Quelle: `stackitcloud/stackit-landing-zone`, Commit -`a256f6896d11134fdc351786f1be5eba4e56b2e2` (derselbe Stand wie Vorbereitungen). -Engine: OpenTofu **1.12.6**. `accelerator.lock.hcl` wurde aus einem sauberen -`git archive` dieses Commits mit `tofu init -backend=false` und -`tofu providers lock -platform=linux_amd64 -platform=darwin_arm64` erzeugt. -Der Quellcommit enthält kein eingechecktes Root-Lockfile. Der Configurator besitzt -deshalb einen separaten Lock für genau diese Code-Version; das Accelerator-Original -wird nicht verändert. Provider-Updates verlangen eine neue gemeinsame Qualifizierung. +[English](README.md) | [Deutsch](README.de.md) -Im späteren Build wird die Datei als `src/.terraform.lock.hcl` in das isolierte -Accelerator-Paket kopiert. Anschließend ausschließlich `tofu init -lockfile=readonly`. -Linux-Checksummen sind erfasst. Die Release-Pipeline prüft init/validate und die -CF-Isolation vor der Abnahme; aktueller Status steht im Abnahmedokument. Der opnsense- -Provider wurde vom Registry-Download ohne GPG-Signatur angeboten; Checksummen sind -gepinnt, dies ist kein Signaturnachweis dieses Providers. + -`package.sh` baut ein separates Binary-Paket mit Node, OpenTofu und -Provider-Mirror; `manifest.yml` staged ein task-only CF-Template ohne Bindings. -Der finale Image-Buildpack wird über `LZC_IMAGE_BUILDPACK` auf den freigegebenen -Release-Commit gepinnt; die geschützte Pipeline liefert die Runner-Variablendatei. -Hosted-Archive enthalten die qualifizierte Image-SHA statt der großen QCOW2-Datei. -Beim Staging wird diese aus STACKIT Object Storage geladen, SHA-geprüft und -ohne zusätzliche Dateikopie am ursprünglichen Pfad ins Droplet verschoben. -Das unveränderliche CF-Droplet ist der dauerhafte Cache; ein redundantes großes -Buildpack-Cache-Archiv wird vermieden. -CI prüft dafür die bytegleiche Wiederherstellung und unveränderte Paketidentität. -Lokale Archive bleiben vollständig. Es gibt keinen Download pro Nutzer oder Plan. -Details und Grenzen: [CF-Staging und Cache](../cloud-foundry/README.md#image-staging-and-caching). -Der Dispatcher kopiert dessen Droplet in eine neue App pro Auftrag. Direkte -OpenTofu-Schritte stehen in `run-plan.sh`. Ablauf und Freigabegrenzen: [Plan-Ausführung](../../docs/plan-execution.md). +Source: `stackitcloud/stackit-landing-zone`, commit +`a256f6896d11134fdc351786f1be5eba4e56b2e2` (the same version as preparations). +Engine: OpenTofu **1.12.6**. `accelerator.lock.hcl` was generated from a clean +`git archive` of this commit using `tofu init -backend=false` and +`tofu providers lock -platform=linux_amd64 -platform=darwin_arm64`. +The source commit contains no checked-in root lockfile. The Configurator +therefore owns a separate lock for exactly this code version; the original Accelerator +is not modified. Provider updates require new joint qualification. + +In the later build, the file is copied into the isolated Accelerator package as +`src/.terraform.lock.hcl`. Subsequently use only `tofu init -lockfile=readonly`. +Linux checksums are recorded. The release pipeline checks init/validate and +CF isolation before acceptance; the acceptance document records the current status. +The opnsense provider was offered by the registry download without a GPG signature; +checksums are pinned, but this is not proof of that provider's signature. + +`package.sh` builds a separate binary package with Node, OpenTofu and +a provider mirror; `manifest.yml` stages a task-only CF template without bindings. +The final image buildpack is pinned to the approved release commit through +`LZC_IMAGE_BUILDPACK`; the protected pipeline supplies the Runner variables file. +Hosted archives contain the qualified image SHA instead of the large QCOW2 file. +During staging, it is downloaded from STACKIT Object Storage, SHA-verified and +moved into the droplet at the original path without an additional file copy. +The immutable CF droplet is the durable cache; a redundant large +buildpack cache archive is avoided. +CI checks byte-identical restoration and unchanged package identity. +Local archives remain complete. There is no download per user or Plan. +Details and limits: [CF staging and cache](../cloud-foundry/README.md#image-staging-and-caching). +The dispatcher copies its droplet into a new app per job. Direct +OpenTofu steps are in `run-plan.sh`. Process and approval boundaries: [Plan execution](../../docs/plan-execution.md). diff --git a/landing-zone-configurator/docs/accelerator-limitations.de.md b/landing-zone-configurator/docs/accelerator-limitations.de.md new file mode 100644 index 0000000..f0c7827 --- /dev/null +++ b/landing-zone-configurator/docs/accelerator-limitations.de.md @@ -0,0 +1,116 @@ + + +# Accelerator-Grenzen im Configurator + +[English](accelerator-limitations.md) | [Deutsch](accelerator-limitations.de.md) + +Stand: 2026-09-30. Die unten genannten Quellbefunde wurden zusätzlich gegen +Accelerator `main` unter Commit `2bb7c755692674ad619ffc46a0a17a781f019106` +geprüft. Die neuen Issues enthalten Quell-Permalinks und Abnahmekriterien. +Es handelt sich um Quellprüfung, nicht um einen Nachweis durch Kunden-Apply. +Der Configurator verwendet weiterhin seine separat freigegebene Engine-Version. + + + +## Erfasste Grenzen + +| Issue | Grenze | Konsequenz für den Configurator | +| --- | --- | --- | +| [#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37) | Private/SNA-SKE-API vom öffentlichen Runner nicht erreichbar; zweistufiges Runner-Modell offen. | Kubernetes-/Helm-Provider-Operationen benötigen nachgewiesene private Erreichbarkeit. Zugangsdaten allein reichen nicht. Umsetzung separat. | +| [#65](https://github.com/stackitcloud/stackit-landing-zone/issues/65) | Policy-Automatisierung für mehrere Firewall-Appliances fehlt. | Mehrere Appliances im Infrastrukturmodell bedeuten nicht automatisch unterstützte Policies je Appliance. | +| [#64](https://github.com/stackitcloud/stackit-landing-zone/issues/64) | Automatische Inter-Region-VPN-Verbindungen und Routing fehlen. | Mehrere Regionen dürfen keine implizite Verbindung suggerieren. | +| [#22](https://github.com/stackitcloud/stackit-landing-zone/issues/22) | Ordnerlöschung bei zur Löschung vorgemerkten Projekten schlägt fehl. | Kein Destroy-Angebot; Kunden-Apply weiterhin nur nach gesonderter Freigabe. | +| [#69](https://github.com/stackitcloud/stackit-landing-zone/issues/69) | Projekte ohne standardmäßige Owner-Zuweisung noch offen. | Keine nicht unterstützte ownerlose Projektanlage anbieten. | +| [#80](https://github.com/stackitcloud/stackit-landing-zone/issues/80) | Namespace-Dienste referenzieren nichtregionale Cluster-/Projektmodule. | Regionale Cluster erfordern explizite passende Provider-/Projektzuordnung. Unabhängig von #37 auch bei öffentlicher API relevant. | +| [#81](https://github.com/stackitcloud/stackit-landing-zone/issues/81) | Audit-Object-Lock: tatsächlicher optionaler Default ist `true`, Beschreibung sagt aus. | Wirksamen Wert sichtbar machen; keine stille Änderung des Defaults beim Import/Export. | +| [#82](https://github.com/stackitcloud/stackit-landing-zone/issues/82) | `rm_folders.description` wird akzeptiert, aber nicht zur Ressource durchgereicht. | Kein wirksames Beschreibungsfeld versprechen, solange die Anbindung fehlt. | +| [#83](https://github.com/stackitcloud/stackit-landing-zone/issues/83) | Governance-Custom-Roles und Landing-Zone-Secrets-Manager-ACLs sind nur auf Modulebene vorhanden. | Erst nach geklärtem Root-Vertrag als konfigurierbare Features anbieten. Bestehende projektbezogene Custom Roles sind davon zu unterscheiden. | +| [#84](https://github.com/stackitcloud/stackit-landing-zone/issues/84) | Standalone lässt beim Public-Beispiel `corporate = false` aus; tatsächlich greift `true` ohne Connectivity. | Verlustfreier Import zeigt die fehlende Bereichsreferenz. Legacy-Editor exportiert bereits explizit Public und bleibt unverändert. | + +#80–#83 wurden im Rahmen dieser Prüfung neu angelegt. #37 und #65 werden +weiterverwendet; dafür gibt es keine zusätzlichen Duplikate. +Gültige Bereichsreferenzen, konsistente Firewall-Schlüssel und die aktuell +unterstützten Regionen sind Validierungsregeln, nicht automatisch neue Defekte. + + + +## Private Kubernetes-API: Ausführungsgrenze + +Der aktuelle CF-Runner hat keinen nachgewiesenen Netzwerkpfad in die Kunden-SNA. +Authentifizierung beim STACKIT-API und erfolgreicher Organisations-Zugriff beweisen +weder Routing noch DNS, TLS oder Kubernetes-Berechtigungen für die Cluster-API. +Auch ein Plan kann beim Provider-Refresh diesen Zugriff benötigen. + +Der aktuelle veröffentlichte Editor unterstützt nur den Standalone-Vertrag. +Die folgenden Regeln sind Anforderungen an die Erweiterung des gemeinsamen Modells; +sie sind **noch keine implementierte SNA-Erreichbarkeitsprüfung**: + +- Konfigurationen dürfen bearbeitet und gespeichert werden, auch wenn eine + Ausführungsphase auf dem verfügbaren Runner noch nicht unterstützt wird. +- Vor dem Dispatch muss das Backend die benötigten Provider und Ausführungsphasen + prüfen. Eine private Kubernetes-/Helm-Phase bleibt ohne geeigneten Runner gesperrt; + die UI erklärt den Grund und verweist auf #37. +- Der heutige vollständige Root-Lauf ist kein bereits implementierter + Infrastruktur-only-Workaround. Die Trennung der Phasen gehört zu #37. +- Kein automatisches Umschalten auf öffentliche Cluster-APIs, kein TLS-Bypass und + keine implizite Tunnel-Lösung als Ersatz für den fehlenden Netzwerkpfad. +- Regionale Clusterzuordnung (#80) und Netzwerk-Erreichbarkeit (#37) werden getrennt + geprüft. Das Beheben einer Grenze beseitigt die andere nicht. + + + +## Abnahme und Pflege + +- [x] Bestehende offene und geschlossene Issues auf Überschneidungen prüfen. +- [x] Zusätzliche bestätigte Grenzen mit Quellbelegen als #80–#83 erfassen. +- [x] Privaten Kubernetes-Zugriff als separat zu lösendes Thema dokumentieren. +- [ ] Capability-Katalog mit Engine-Version, Issue-Bezug und Ausführungsphase implementieren. +- [ ] Serverseitige Ausführungssperren und verständliche UI-Hinweise testen. +- [ ] Nach Lösung von #37 privaten Runner-Pfad inklusive DNS, Routing, TLS und + Authentifizierung vor Plan/Apply abnehmen; Timeouts nicht als Drift behandeln. +- [ ] Behobene Accelerator-Issues erst nach Engine-Upgrade und eigenen Vertragstests + als im Configurator unterstützt markieren. + +Neue Grenzen zunächst gegen bestehende Issues und die aktuelle Accelerator-Version +prüfen. Neue Issues enthalten betroffene Eingaben, Quellbelege, erwartetes und +tatsächliches Verhalten sowie überprüfbare Abnahmekriterien. Zugangsdaten und +kundenbezogene Konfigurationen gehören nicht in Issues. + +Ergänzung: #84 wurde beim gemeinsamen Import-/Export-Vertragstest entdeckt und +auch auf `main` bestätigt. Ein nativer Variablen-Vertragstest erwartet diesen +Validierungsfehler ausdrücklich, bis die Vorlage korrigiert und freigegeben ist. + + + + +## VPN-Zuordnung bei mehreren SNAs + +[#85](https://github.com/stackitcloud/stackit-landing-zone/issues/85): VPN-Gateways +und alle konfigurierten Verbindungen werden auf sämtliche SNAs eines Connectivity- +Moduls repliziert. Eine selektive oder unterschiedliche Konfiguration je SNA fehlt. +Gegen `main` unter `2bb7c755692674ad619ffc46a0a17a781f019106` geprüft; #64 betrifft +einen anderen Sachverhalt (Inter-Region-Verbindungen). Der VPN-Assistent erklärt +die tatsächliche Reichweite und bietet keinen unwirksamen SNA-Selektor an. + + + + +## BGP für STACKIT VPN + +[#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) erfasst die +fehlende Unterstützung von `BGP_ROUTE_BASED` im Accelerator. #23 ist geschlossen +und behandelt die allgemeine VPN-Implementierung; #64/#85 sind andere Grenzen. +Der Code nennt ein historisches Provider-Problem bis 0.104.0. Ob es unter dem +inzwischen gepinnten Provider 0.114.0 noch besteht, muss reproduziert werden. +Das Issue umfasst Gateway-/Tunnel-BGP-Einstellungen, Routingvalidierung, +SNA-Routenpropagation und die spätere Configurator-Anbindung. Eine allgemeine +Verwaltung zusätzlicher SNA-Routing-Tabellen ist davon zu unterscheiden. + + + +## Bastion und Observability: Komponentenbeziehungen + +- [#87](https://github.com/stackitcloud/stackit-landing-zone/issues/87): `debug-bastion` ist zwar ein eigenes Modul, wird vom Root aber ausschließlich über Plattform-Kubernetes mit dessen Projekt und SNA-Netz aufgerufen. Eine unabhängige Bastion-Komponente benötigt einen eigenen Root-Vertrag und eine explizite Bestandsmigration. +- [#88](https://github.com/stackitcloud/stackit-landing-zone/issues/88): Das Kubernetes-Modul erzeugt derzeit bei aktiviertem Monitoring eine eigene Observability-Instanz. Die zentrale Instanz im Management-Projekt wird nicht referenziert. Die gewünschte Auswahl einer bestehenden/zentral definierten Instanz benötigt Referenzfelder, Outputs und die Prüfung der zulässigen Projekt-/Regionsbeziehungen. Keine stille Umstellung bestehender Ressourcen. + +Die [SKE-Dokumentation](https://docs.stackit.cloud/products/runtime/kubernetes-engine/how-tos/monitor-your-clusters/) beschreibt die Auswahl einer vorhandenen Observability-Instanz. Das beweist noch nicht, dass jede Instanz eines anderen Projekts verwendbar ist. SKE-Systemmonitoring, Anwendungsmetriken und Telemetry Router bleiben separate Aufgaben. Das UI kennzeichnet die tatsächlichen Deployment-Orte und die aktuellen Grenzen. diff --git a/landing-zone-configurator/docs/accelerator-limitations.md b/landing-zone-configurator/docs/accelerator-limitations.md index b42b1e1..d07f647 100644 --- a/landing-zone-configurator/docs/accelerator-limitations.md +++ b/landing-zone-configurator/docs/accelerator-limitations.md @@ -1,100 +1,109 @@ -# Accelerator-Grenzen im Configurator + +# Accelerator limitations in the Configurator -Stand: 2026-09-30. Die unten genannten Quellbefunde wurden zusätzlich gegen -Accelerator `main` unter Commit `2bb7c755692674ad619ffc46a0a17a781f019106` -geprüft. Die neuen Issues enthalten Quell-Permalinks und Abnahmekriterien. -Es handelt sich um Quellprüfung, nicht um einen Nachweis durch Kunden-Apply. -Der Configurator verwendet weiterhin seine separat freigegebene Engine-Version. +[English](accelerator-limitations.md) | [Deutsch](accelerator-limitations.de.md) -## Erfasste Grenzen +As of 2026-09-30. The source findings below were additionally checked against +Accelerator `main` at commit `2bb7c755692674ad619ffc46a0a17a781f019106`. +The new issues contain source permalinks and acceptance criteria. +This is source review, not evidence from a customer Apply. +The Configurator continues to use its separately approved engine version. -| Issue | Grenze | Konsequenz für den Configurator | + +## Recorded limitations + +| Issue | Limitation | Consequence for the Configurator | | --- | --- | --- | -| [#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37) | Private/SNA-SKE-API vom öffentlichen Runner nicht erreichbar; zweistufiges Runner-Modell offen. | Kubernetes-/Helm-Provider-Operationen benötigen nachgewiesene private Erreichbarkeit. Zugangsdaten allein reichen nicht. Umsetzung separat. | -| [#65](https://github.com/stackitcloud/stackit-landing-zone/issues/65) | Policy-Automatisierung für mehrere Firewall-Appliances fehlt. | Mehrere Appliances im Infrastrukturmodell bedeuten nicht automatisch unterstützte Policies je Appliance. | -| [#64](https://github.com/stackitcloud/stackit-landing-zone/issues/64) | Automatische Inter-Region-VPN-Verbindungen und Routing fehlen. | Mehrere Regionen dürfen keine implizite Verbindung suggerieren. | -| [#22](https://github.com/stackitcloud/stackit-landing-zone/issues/22) | Ordnerlöschung bei zur Löschung vorgemerkten Projekten schlägt fehl. | Kein Destroy-Angebot; Kunden-Apply weiterhin nur nach gesonderter Freigabe. | -| [#69](https://github.com/stackitcloud/stackit-landing-zone/issues/69) | Projekte ohne standardmäßige Owner-Zuweisung noch offen. | Keine nicht unterstützte ownerlose Projektanlage anbieten. | -| [#80](https://github.com/stackitcloud/stackit-landing-zone/issues/80) | Namespace-Dienste referenzieren nichtregionale Cluster-/Projektmodule. | Regionale Cluster erfordern explizite passende Provider-/Projektzuordnung. Unabhängig von #37 auch bei öffentlicher API relevant. | -| [#81](https://github.com/stackitcloud/stackit-landing-zone/issues/81) | Audit-Object-Lock: tatsächlicher optionaler Default ist `true`, Beschreibung sagt aus. | Wirksamen Wert sichtbar machen; keine stille Änderung des Defaults beim Import/Export. | -| [#82](https://github.com/stackitcloud/stackit-landing-zone/issues/82) | `rm_folders.description` wird akzeptiert, aber nicht zur Ressource durchgereicht. | Kein wirksames Beschreibungsfeld versprechen, solange die Anbindung fehlt. | -| [#83](https://github.com/stackitcloud/stackit-landing-zone/issues/83) | Governance-Custom-Roles und Landing-Zone-Secrets-Manager-ACLs sind nur auf Modulebene vorhanden. | Erst nach geklärtem Root-Vertrag als konfigurierbare Features anbieten. Bestehende projektbezogene Custom Roles sind davon zu unterscheiden. | -| [#84](https://github.com/stackitcloud/stackit-landing-zone/issues/84) | Standalone lässt beim Public-Beispiel `corporate = false` aus; tatsächlich greift `true` ohne Connectivity. | Verlustfreier Import zeigt die fehlende Bereichsreferenz. Legacy-Editor exportiert bereits explizit Public und bleibt unverändert. | - -#80–#83 wurden im Rahmen dieser Prüfung neu angelegt. #37 und #65 werden -weiterverwendet; dafür gibt es keine zusätzlichen Duplikate. -Gültige Bereichsreferenzen, konsistente Firewall-Schlüssel und die aktuell -unterstützten Regionen sind Validierungsregeln, nicht automatisch neue Defekte. - -## Private Kubernetes-API: Ausführungsgrenze - -Der aktuelle CF-Runner hat keinen nachgewiesenen Netzwerkpfad in die Kunden-SNA. -Authentifizierung beim STACKIT-API und erfolgreicher Organisations-Zugriff beweisen -weder Routing noch DNS, TLS oder Kubernetes-Berechtigungen für die Cluster-API. -Auch ein Plan kann beim Provider-Refresh diesen Zugriff benötigen. - -Der aktuelle veröffentlichte Editor unterstützt nur den Standalone-Vertrag. -Die folgenden Regeln sind Anforderungen an die Erweiterung des gemeinsamen Modells; -sie sind **noch keine implementierte SNA-Erreichbarkeitsprüfung**: - -- Konfigurationen dürfen bearbeitet und gespeichert werden, auch wenn eine - Ausführungsphase auf dem verfügbaren Runner noch nicht unterstützt wird. -- Vor dem Dispatch muss das Backend die benötigten Provider und Ausführungsphasen - prüfen. Eine private Kubernetes-/Helm-Phase bleibt ohne geeigneten Runner gesperrt; - die UI erklärt den Grund und verweist auf #37. -- Der heutige vollständige Root-Lauf ist kein bereits implementierter - Infrastruktur-only-Workaround. Die Trennung der Phasen gehört zu #37. -- Kein automatisches Umschalten auf öffentliche Cluster-APIs, kein TLS-Bypass und - keine implizite Tunnel-Lösung als Ersatz für den fehlenden Netzwerkpfad. -- Regionale Clusterzuordnung (#80) und Netzwerk-Erreichbarkeit (#37) werden getrennt - geprüft. Das Beheben einer Grenze beseitigt die andere nicht. - -## Abnahme und Pflege - -- [x] Bestehende offene und geschlossene Issues auf Überschneidungen prüfen. -- [x] Zusätzliche bestätigte Grenzen mit Quellbelegen als #80–#83 erfassen. -- [x] Privaten Kubernetes-Zugriff als separat zu lösendes Thema dokumentieren. -- [ ] Capability-Katalog mit Engine-Version, Issue-Bezug und Ausführungsphase implementieren. -- [ ] Serverseitige Ausführungssperren und verständliche UI-Hinweise testen. -- [ ] Nach Lösung von #37 privaten Runner-Pfad inklusive DNS, Routing, TLS und - Authentifizierung vor Plan/Apply abnehmen; Timeouts nicht als Drift behandeln. -- [ ] Behobene Accelerator-Issues erst nach Engine-Upgrade und eigenen Vertragstests - als im Configurator unterstützt markieren. - -Neue Grenzen zunächst gegen bestehende Issues und die aktuelle Accelerator-Version -prüfen. Neue Issues enthalten betroffene Eingaben, Quellbelege, erwartetes und -tatsächliches Verhalten sowie überprüfbare Abnahmekriterien. Zugangsdaten und -kundenbezogene Konfigurationen gehören nicht in Issues. - -Ergänzung: #84 wurde beim gemeinsamen Import-/Export-Vertragstest entdeckt und -auch auf `main` bestätigt. Ein nativer Variablen-Vertragstest erwartet diesen -Validierungsfehler ausdrücklich, bis die Vorlage korrigiert und freigegeben ist. - - -## VPN-Zuordnung bei mehreren SNAs - -[#85](https://github.com/stackitcloud/stackit-landing-zone/issues/85): VPN-Gateways -und alle konfigurierten Verbindungen werden auf sämtliche SNAs eines Connectivity- -Moduls repliziert. Eine selektive oder unterschiedliche Konfiguration je SNA fehlt. -Gegen `main` unter `2bb7c755692674ad619ffc46a0a17a781f019106` geprüft; #64 betrifft -einen anderen Sachverhalt (Inter-Region-Verbindungen). Der VPN-Assistent erklärt -die tatsächliche Reichweite und bietet keinen unwirksamen SNA-Selektor an. - - -## BGP für STACKIT VPN - -[#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) erfasst die -fehlende Unterstützung von `BGP_ROUTE_BASED` im Accelerator. #23 ist geschlossen -und behandelt die allgemeine VPN-Implementierung; #64/#85 sind andere Grenzen. -Der Code nennt ein historisches Provider-Problem bis 0.104.0. Ob es unter dem -inzwischen gepinnten Provider 0.114.0 noch besteht, muss reproduziert werden. -Das Issue umfasst Gateway-/Tunnel-BGP-Einstellungen, Routingvalidierung, -SNA-Routenpropagation und die spätere Configurator-Anbindung. Eine allgemeine -Verwaltung zusätzlicher SNA-Routing-Tabellen ist davon zu unterscheiden. - -## Bastion und Observability: Komponentenbeziehungen - -- [#87](https://github.com/stackitcloud/stackit-landing-zone/issues/87): `debug-bastion` ist zwar ein eigenes Modul, wird vom Root aber ausschließlich über Plattform-Kubernetes mit dessen Projekt und SNA-Netz aufgerufen. Eine unabhängige Bastion-Komponente benötigt einen eigenen Root-Vertrag und eine explizite Bestandsmigration. -- [#88](https://github.com/stackitcloud/stackit-landing-zone/issues/88): Das Kubernetes-Modul erzeugt derzeit bei aktiviertem Monitoring eine eigene Observability-Instanz. Die zentrale Instanz im Management-Projekt wird nicht referenziert. Die gewünschte Auswahl einer bestehenden/zentral definierten Instanz benötigt Referenzfelder, Outputs und die Prüfung der zulässigen Projekt-/Regionsbeziehungen. Keine stille Umstellung bestehender Ressourcen. - -Die [SKE-Dokumentation](https://docs.stackit.cloud/products/runtime/kubernetes-engine/how-tos/monitor-your-clusters/) beschreibt die Auswahl einer vorhandenen Observability-Instanz. Das beweist noch nicht, dass jede Instanz eines anderen Projekts verwendbar ist. SKE-Systemmonitoring, Anwendungsmetriken und Telemetry Router bleiben separate Aufgaben. Das UI kennzeichnet die tatsächlichen Deployment-Orte und die aktuellen Grenzen. +| [#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37) | Private/SNA SKE API unreachable from the public Runner; two-stage Runner model open. | Kubernetes/Helm provider operations require proven private reachability. Credentials alone are insufficient. Separate implementation. | +| [#65](https://github.com/stackitcloud/stackit-landing-zone/issues/65) | Policy automation for multiple firewall appliances missing. | Multiple appliances in the infrastructure model do not automatically mean supported policies per appliance. | +| [#64](https://github.com/stackitcloud/stackit-landing-zone/issues/64) | Automatic inter-region VPN connections and routing missing. | Multiple regions must not suggest implicit connectivity. | +| [#22](https://github.com/stackitcloud/stackit-landing-zone/issues/22) | Folder deletion fails when projects are marked for deletion. | No Destroy option; customer Apply still requires separate approval. | +| [#69](https://github.com/stackitcloud/stackit-landing-zone/issues/69) | Projects without default owner assignment still open. | Do not offer unsupported ownerless project creation. | +| [#80](https://github.com/stackitcloud/stackit-landing-zone/issues/80) | Namespace services reference nonregional cluster/project modules. | Regional clusters require explicit matching provider/project assignment. Relevant independently of #37, even with a public API. | +| [#81](https://github.com/stackitcloud/stackit-landing-zone/issues/81) | Audit Object Lock: actual optional default is `true`, description says off. | Make effective value visible; no silent default change on import/export. | +| [#82](https://github.com/stackitcloud/stackit-landing-zone/issues/82) | `rm_folders.description` is accepted but not passed through to the resource. | Do not promise an effective description field while the connection is missing. | +| [#83](https://github.com/stackitcloud/stackit-landing-zone/issues/83) | Governance custom roles and Landing Zone Secrets Manager ACLs exist only at module level. | Offer as configurable features only after the root contract is clarified. Distinguish existing project-specific custom roles. | +| [#84](https://github.com/stackitcloud/stackit-landing-zone/issues/84) | Standalone omits `corporate = false` in the Public example; `true` actually takes effect without connectivity. | Lossless import shows the missing area reference. Legacy editor already exports explicit Public and remains unchanged. | + +#80–#83 were newly created during this review. #37 and #65 are +reused; no additional duplicates were created. +Valid area references, consistent firewall keys and the currently +supported regions are validation rules, not automatically new defects. + + +## Private Kubernetes API: execution boundary + +The current CF Runner has no proven network path into the customer SNA. +Authentication with the STACKIT API and successful organization access prove +neither routing nor DNS, TLS or Kubernetes permissions for the cluster API. +Even a Plan may require this access during provider refresh. + +The currently published editor supports only the Standalone contract. +The following rules are requirements for extending the common model; +they are **not yet an implemented SNA reachability check**: + +- Configurations may be edited and saved even if an + execution phase is not yet supported on the available Runner. +- Before dispatch, the backend must check the required providers and execution + phases. A private Kubernetes/Helm phase remains blocked without a suitable Runner; + the UI explains why and refers to #37. +- Today's complete root run is not an already implemented + infrastructure-only workaround. Phase separation belongs to #37. +- No automatic switch to public cluster APIs, no TLS bypass and + no implicit tunnel solution as a substitute for the missing network path. +- Regional cluster assignment (#80) and network reachability (#37) are checked + separately. Resolving one limitation does not eliminate the other. + + +## Acceptance and maintenance + +- [x] Check existing open and closed issues for overlap. +- [x] Record additional confirmed limitations with source evidence as #80–#83. +- [x] Document private Kubernetes access as a separately resolvable topic. +- [ ] Implement a capability catalogue with engine version, issue reference and execution phase. +- [ ] Test server-side execution blocks and understandable UI explanations. +- [ ] After resolving #37, qualify the private Runner path including DNS, routing, TLS and + authentication before Plan/Apply; do not treat timeouts as drift. +- [ ] Mark resolved Accelerator issues as supported in the Configurator only after an + engine upgrade and its own contract tests. + +First check new limitations against existing issues and the current Accelerator version. +New issues include affected inputs, source evidence, expected and +actual behavior and verifiable acceptance criteria. Credentials and +customer-specific configurations do not belong in issues. + +Addition: #84 was discovered during the common import/export contract test and +also confirmed on `main`. A native variable contract test explicitly expects this +validation error until the template is corrected and approved. + + + +## VPN assignment with multiple SNAs + +[#85](https://github.com/stackitcloud/stackit-landing-zone/issues/85): VPN gateways +and all configured connections are replicated to every SNA of a connectivity +module. Selective or different configuration per SNA is missing. +Checked against `main` at `2bb7c755692674ad619ffc46a0a17a781f019106`; #64 concerns +a different matter (inter-region connections). The VPN assistant explains +the actual scope and does not offer an ineffective SNA selector. + + + +## BGP for STACKIT VPN + +[#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) records the +missing support for `BGP_ROUTE_BASED` in the Accelerator. #23 is closed +and covers the general VPN implementation; #64/#85 are different limitations. +The code mentions a historical provider issue up to 0.104.0. Whether it still exists +under the now-pinned provider 0.114.0 must be reproduced. +The issue covers gateway/tunnel BGP settings, routing validation, +SNA route propagation and later Configurator integration. General +management of additional SNA routing tables is distinct from this. + + +## Bastion and Observability: component relationships + +- [#87](https://github.com/stackitcloud/stackit-landing-zone/issues/87): Although `debug-bastion` is a separate module, the root calls it exclusively through platform Kubernetes with its project and SNA network. An independent bastion component needs its own root contract and explicit migration of existing resources. +- [#88](https://github.com/stackitcloud/stackit-landing-zone/issues/88): The Kubernetes module currently creates its own Observability instance when monitoring is enabled. It does not reference the central instance in the management project. The desired selection of an existing/centrally defined instance requires reference fields, outputs and checks of permitted project/region relationships. No silent conversion of existing resources. + +The [SKE documentation](https://docs.stackit.cloud/products/runtime/kubernetes-engine/how-tos/monitor-your-clusters/) describes selecting an existing Observability instance. This does not yet prove that every instance from another project is usable. SKE system monitoring, application metrics and Telemetry Router remain separate tasks. The UI identifies actual deployment locations and current limitations. diff --git a/landing-zone-configurator/docs/architecture.de.md b/landing-zone-configurator/docs/architecture.de.md new file mode 100644 index 0000000..f5f3904 --- /dev/null +++ b/landing-zone-configurator/docs/architecture.de.md @@ -0,0 +1,264 @@ + + +# STACKIT-Zielarchitektur des Landing Zone Configurators + +[English](architecture.md) | [Deutsch](architecture.de.md) + +Diese Referenz beschreibt die implementierten Komponenten und ihre +Vertrauensgrenzen. Die Entwicklungsumgebung verwendet STACKIT OIDC; eine eigene +Passwortverwaltung ist nicht vorgesehen. Der Betrieb in der Entwicklungsumgebung +ist kein Nachweis einer produktiv qualifizierten Umgebung. Die getrennten +[MVP-Grenzen](mvp-scope.de.md) und [Entwicklungsreferenzen](development.de.md) benennen +verbleibende Aufgaben. + + + +## Technische Praesentationssicht + +![STACKIT-Zielarchitektur des Landing Zone Configurators](architecture/stackit-overview.svg) + +[Uebersicht als SVG in voller Groesse](architecture/stackit-overview.svg) · +[PNG fuer Praesentationen](architecture/stackit-overview.png) + +Die Uebersicht ist eine bewusst vereinfachte 16:9-Praesentationsgrafik: +Kernkomponenten mit jeweils einem Titel und Untertitel. Sie zeigt den +Hauptablauf UI -> Backend -> Runner -> Landing Zone und die angebundenen +Identitaets-, Repository-, Datenbank- und KI-Dienste. Linien zeigen grundlegende +Beziehungen, keine einzelnen Protokolle oder Datenfluesse. Die blaue +Hinterlegung kennzeichnet die STACKIT-Infrastruktur; nur GitHub mit dem +Accelerator-Repository liegt ausserhalb. Die dunklere CF-Flaeche umfasst +Web UI, Configurator API und Runner. + +Editor und Chat sind Teile derselben Web UI. Die Configurator API beherbergt +die Assistant-Logik, Wissen, Validierung und Orchestrierung. Model Serving stellt +die beiden Modellrollen fuer Antworten und Intent-Erkennung bereit; es betreibt +nicht den eigentlichen Configurator-Assistenten. Zwei Modellrollen muessen nicht +zwei verschiedene Modelle sein: ohne separaten Intent-Override verwenden beide +Rollen das konfigurierte Antwortmodell. + +GitHub und das darin liegende Accelerator-Repository sind an die API angebunden: +die API arbeitet mit den daraus abgeleiteten Templates und Eingabevertraegen. +Diese werden versioniert im Build uebernommen; die Grafik behauptet keinen +Live-Download beliebiger Repository-Staende. Der Runner fuehrt den dazu passenden +gepinnten Accelerator-/Provider-Stand mit OpenTofu aus. + +Die CF-Gruppierung zeigt die Hosting-Plattform, keine gemeinsame CF-Organisation +oder Service-Bindings aller Komponenten. Web UI und API werden gemeinsam +ausgeliefert; Runner bleiben isoliert. Router, Secrets-/State-Verwaltung, +CI/CD und Migrationen sind in der Praesentationsansicht bewusst ausgeblendet. +Die SVG ist direkt editierbar. + + + +## Logische Praesentationssicht + +![Von Vorlagen zu Landing Zones](architecture/landing-zone-logical.svg) + +[Logische Sicht als SVG](architecture/landing-zone-logical.svg) · +[PNG fuer Praesentationen](architecture/landing-zone-logical.png) + +Die zweite Zeichnung zeigt den fachlichen Zusammenhang ohne Laufzeitdienste: + +- Der **Platform Engineer** nutzt Plattform-Templates als Ausgangsbasis, + erstellt die Plattformkonfiguration und stellt die **Platform Landing Zone** + bereit. +- In diesem Entwurf definiert er auch **Application-Templates** und gibt + gepruefte Versionen fuer den Katalog frei. +- Der **Application Owner** waehlt eine freigegebene Vorlage und ergaenzt die + konkreten Projektparameter in einer Bestellung. Daraus entstehen + **Application Landing Zones** auf Basis der gemeinsamen Plattform. + +Ergaenzungen in der logischen Sicht: + +- **GitHub Repository / Landing Zone Configurator:** Versionsbasis der + Anwendung und ihrer Konfigurationsvertraege. Der Configurator-Code liegt + derzeit im Unterverzeichnis `landing-zone-configurator` des gemeinsamen + `stackitcloud/stackit-landing-zone`-Repos; die Zeichnung behauptet kein + zusaetzliches eigenstaendiges Repository. Kundenkonfigurationen koennen + separat in persoenlichen Accelerator-Forks versioniert werden. Die Linie + bedeutet nicht, dass Kundendokumente im Configurator-Quellrepo landen. +- **Gruene KI-Markierung:** Unterstuetzung bei der Plattformkonfiguration und + den Application-Template-Entwuerfen. Sie bezeichnet Vorschlaege und + Rueckfragen, nicht automatische Veroeffentlichung, Rollenvergabe oder + Cloud-Ausfuehrung. Bei bereits freigegebenen Templates bezieht sich die + Markierung auf deren vorgelagerten Entwurf, nicht auf eine stille Aenderung + veroeffentlichter Versionen. +- **Platform Engineer -> Application Owner / berechtigt:** Vergabe der + tenantgebundenen Mitgliedschaft beziehungsweise Katalogberechtigung. + Mitgliederverwaltung setzt die separat delegierte Verwaltungsfaehigkeit + voraus; die Platform-Engineer-Rolle allein verleiht sie nicht automatisch. +- **STACKIT Service Account:** Autorisierter technischer Cloud-Zugang fuer + die Bereitstellung von Plattform und Anwendungen. Er ist kein Benutzerlogin + und ersetzt weder die Configurator-Rollen noch eine erforderliche Freigabe. + Zugangsdaten werden nicht an den Application Owner herausgegeben; die + Nutzung erfolgt serverseitig und auftragsgebunden. + +Die Pfeile verdichten bewusste Arbeitsschritte, keine automatische +Veroeffentlichung oder Apply-Freigabe. Die Plattformkonfiguration erzeugt nicht +bereits die Anwendungsinstanzen. Template-Versionen und konkrete Bestellungen +bleiben getrennte Objekte; Rollen gelten pro Arbeitsumgebung. + + + +## Technische Detailreferenz + +Fuer die vollstaendigen Beziehungen, die separate CF Control Plane, +die Migration-App und die Remote-State-Pruefung gibt es zusaetzlich die +[Detailzeichnung als SVG](architecture/stackit-target.svg) und ihre +[editierbare Mermaid-Quelle](architecture/stackit-target.mmd). + +**Leserichtung der Detailzeichnung:** Pfeile zeigen Aufrufe beziehungsweise den bezeichneten +Datenfluss. Doppelpfeile fassen Anfrage und Antwort zusammen. Gestrichelte +Pfeile beschreiben den Release-/Migrationspfad, nicht Kunden-Provisionierung. +Die Boxen unterscheiden Betreiber-Laufzeit, Runner-Isolation, Managed Services, +GitHub und Kundenressourcen; sie sind keine Zusage privater Netzwerkverbindungen. +Die STACKIT-API-Box steht fuer die adressierte Zielorganisation, nicht fuer +physisch darin betriebene API-Server. + + + +## Bereitstellung und Verantwortlichkeiten + +| Komponente | Bereitstellungsmodell | Aufgabe | +|---|---|---| +| Web UI | React-SPA, vom CF-Webprozess ausgeliefert | Editor und Chat, Templates, Auftragsstatus und ausdrueckliche Freigaben | +| Configurator API | Node.js/Fastify in derselben CF-App | Authentifizierung, Mandanten/Rollen, Validierung, Konfigurationscompiler, KI-Assistent, GitHub-Integration und Job-Broker | +| CF Router | Cloud-Foundry-Routing und HTTPS-Route | Browserzugang zur UI und API; keine direkte Browserverbindung zu DB oder Secrets Manager | +| Runner | Eigene CF-Organisation und Space; kurzlebige App/Task je Auftrag | Gepinnte OpenTofu-/Provider-/Accelerator-Ausfuehrung; danach Cleanup | +| PostgreSQL Flex | STACKIT Managed Database | Sessions, Mitgliedschaften, Entwuerfe, Templates, Jobs, Audit sowie verschluesselte Plan-/Recovery-Artefakte | +| Secrets Manager | STACKIT Managed Service | Geschuetzte Service-Account-Schluessel, GitHub-Tokens und Backend-Zugangsdaten | +| Model Serving | STACKIT AI Model Serving | Vom Backend genutzte Modelle fuer Antworten und Intent-Erkennung | +| STACKIT IDP | STACKIT Production; eigener Client je Anwendungsumgebung | OIDC Authorization Code Flow mit PKCE S256; Dev-CF-App bedeutet nicht Dev-IDP | +| GitHub | Externe Plattform | Optionale Benutzerverbindung fuer Forks, Konfigurationen und Pull Requests; getrennt vom STACKIT-Login | +| Landing Zone Accelerator Repo | `stackitcloud/stackit-landing-zone` auf GitHub | Versionierte Infrastrukturquelle; freigegebene Revision wird im Build gepinnt und paketiert | +| GitHub Actions | Geschuetzte CI/CD-Pipeline | Tests, Release-Artefakte, Promotion, Runner-Staging und Migrationen | +| Object Storage / S3 | State-Backend der Kunden-Landing-Zone | Dauerhafter OpenTofu-State, Lockfiles und getrennte State-Keys | +| STACKIT APIs / Zielressourcen | Ausgewaehlte Kundenorganisation und Projekte | Technischer Berechtigungsnachweis, Kataloge und freigegebene Provisionierung | +| Migration-App | Kurzlebige CF-App ohne Route | Versionierte DB-Migrationen mit separater Owner-Rolle; keine Owner-Credentials im Webprozess | + +**UI und Backend sind logische Dienste, keine bereits beschlossenen getrennten +CF-Microservices.** Das aktuelle Release liefert beide in einer CF-App aus. +Eine spaetere physische Trennung ist moeglich, aber nicht Teil dieser Zeichnung. +Auch die Backend-Funktionen sind momentan Module eines API-Prozesses. + + + +## Die vier wesentlichen Ablaeufe + + + +### 1. Anmeldung und Organisationszugriff + +Der Browser wird zum STACKIT IDP umgeleitet. Der Backend-Callback tauscht den +Authorization Code mit PKCE aus, prueft die Identitaet und erzeugt eine opaque +Configurator-Session. Organisationszugriff und Bindungsautoritaet werden separat +ueber die vorgesehenen STACKIT-APIs geprueft. Login, Mandantenmitgliedschaft und +Cloud-Berechtigungen sind unterschiedliche Nachweise. + +GitHub bleibt eine optionale zweite Verbindung **fuer Repository-Funktionen**, +nicht der Ersatz fuer STACKIT-Login oder Organisationsrechte. + + + +### 2. Entwurf und Assistant + +UI-Eingaben und Assistant-Vorschlaege durchlaufen dieselben nativen +Konfigurationsvertraege. Nur das Backend ruft Model Serving auf. Es uebergibt +den begrenzten Konfigurationskontext, keine Service-Account-Schluessel oder +GitHub-Tokens. Der Modellaufruf startet weder einen Runner noch einen Apply. +Vorschlagsuebernahme, Speicherung, Plan und Apply bleiben getrennte Schritte. + + + +### 3. Freigegebene Ausfuehrung + +Das Backend prueft Rolle, Mandant, Ziel, Konfigurations-/Quellversion, +State-Bindung und die erforderliche Freigabe. Es dispatcht den Auftrag ueber +die CF API in die **separate Runner-Organisation**. Der Runner erhaelt nur +auftragsspezifische Inputs und Credentials ueber ein begrenztes Job-Ticket. +Er besitzt keine Configurator-DB-/Secrets-Manager-Service-Bindings und keine +CF-Dispatcher-Zugangsdaten. + +Der Runner meldet Status und Ergebnisse an den Broker zurueck; dieser persistiert +sie in PostgreSQL. Die Cloud-Operationen verwenden den explizit autorisierten +Service-Account, nicht das menschliche Login-Token. Plan und Apply sind +unterschiedliche Operationen; Apply setzt den geprueften gespeicherten Plan +und die passende Freigabe voraus. + + +### Ausführung und State + +**State ist nicht gleich Konfigurationsdatenbank:** Der erste Plattform-Bootstrap +verwendet temporaer das persistente, verschluesselte HTTP-State-Backend der API. +Erst nach dem freigegebenen Bootstrap-Apply wird der State in den vom Accelerator +erzeugten Kunden-S3-Bucket migriert und verifiziert. Plattform- und +Application-States erhalten getrennte Keys mit Lockfiles. Der +Configurator-eigene Infrastruktur-State ist wiederum davon getrennt. + +Planartefakte werden vom Backend verschluesselt in PostgreSQL gespeichert. +CI-Release-Artefakte liegen in GitHub Actions. Der zusaetzlich in der Betreiber-IaC +definierte Artifacts-Bucket ist **kein** Beleg dafuer, dass diese Artefakte bereits +dorthin ausgelagert werden; er wird deshalb nicht als aktiver Datenpfad gezeichnet. + + + +### 4. Software-Lieferkette + +CI baut und testet eine festgelegte Accelerator-Revision, den API-/UI-Release +und das Runner-Paket. Das qualifizierte Artefakt wird ueber eine geschuetzte +Promotion ausgeliefert; Runner-Jobs laden nicht beliebig den aktuellen +Repository-Head. Versionierte DB-Migrationen laufen vorher in einer separaten +kurzlebigen Migration-App. Application-Release und Kunden-Plan/Apply sind +unabhaengige Freigaben. + + + +## Wesentliche Ergaenzungen zur urspruenglichen Komponentenliste + +1. **Secrets Manager:** notwendig fuer die technische Credential-Verwaltung. +2. **Object Storage / State-Backend inklusive Locking:** notwendig fuer + reproduzierbare und konfliktfreie Infrastrukturverwaltung. +3. **STACKIT APIs und Kundenressourcen:** machen sichtbar, was der Runner + tatsaechlich verwaltet und mit welchen technischen Credentials. +4. **CF Router und Control Plane:** trennen Benutzerzugang von Task-Dispatch. +5. **CI/CD, Release-Artefakte und Migration-App:** zeigen Quelle, Lieferkette und + die Trennung von DB-Owner- und Runtime-Berechtigungen. + +Fuer eine produktionsreife Betriebsarchitektur sind ausserdem festzulegen: + +- Zentrale Logs, Metriken, Alarmierung und deren Aufbewahrung. CF-Logs und + Datenbank-Audit ersetzen kein vollstaendiges Monitoring-/Alerting-Konzept. + Eine konkrete Observability-/Telemetry-Router-Anbindung des **Configurators** + wird hier nicht als bereits eingerichtet dargestellt. +- Verifizierte DB-Backups, Secret-/Artefaktschluessel-Recovery, S3-Versionierung + und Wiederherstellungstests. Der Verlust des bestehenden Artefaktschluessels + darf nicht durch spontane Rotation verdeckt werden. +- Skalierung/HA sowie gemeinsame Ablage oder Sticky Routing fuer laufende + OIDC-Flows. Die aktuelle Ein-Instanz-Anwendung ist kein HA-Nachweis. +- Netzwerkpfade, ACLs und Egress-Regeln. Ein CF-Runner hat nicht automatisch + Zugriff auf private Kubernetes-/Helm-/Firewall-Endpunkte in Kunden-SNAs. + Diese Ausfuehrungsgrenze bleibt separat zu loesen (#37). +- Eng begrenzte Betriebs-/Deployment-Identitaeten, kontrollierte CF-Space-Rechte + und eine Least-Privilege-Qualifikation des OIDC-Clients. + +Es wird **kein** zusaetzlicher Queue-Service vorausgesetzt: Auftragsmetadaten +liegen in PostgreSQL, der Broker dispatcht CF-Tasks. Ein allgemeiner Scheduler +waere eine eigene spaetere Architekturentscheidung. + + + +## Grundlagen und Weiterfuehrung + +- [CF-Release und Service-Bindings](../deploy/cloud-foundry/README.de.md) +- [Runner-Paket und Accelerator-Pin](../deploy/runner/README.de.md) +- [Plan-Ausfuehrung, Broker und State-Lebenszyklus](plan-execution.de.md) +- [Login und Organisationsnachweis](github-login.de.md) +- [Plattform-/Application-Vertraege](platform-application-architecture.de.md) +- [PostgreSQL Flex](../infra/platform/2-database.tf), + [Secrets Manager](../infra/platform/3-secrets.tf) und + [Model Serving](../infra/platform/5-model-serving.tf) + +Die Detail-SVG wird lokal mit Mermaid CLI 11.12.0 aus der Mermaid-Quelle gerendert. +Die Uebersicht verwendet ausschliesslich lokale SVG-Formen und Systemschriften. +Keine Zugangsdaten, Konfigurationen oder Diagrammquellen werden an einen +Online-Renderer gesendet. diff --git a/landing-zone-configurator/docs/architecture.md b/landing-zone-configurator/docs/architecture.md index 3958ed3..5a2eaf9 100644 --- a/landing-zone-configurator/docs/architecture.md +++ b/landing-zone-configurator/docs/architecture.md @@ -1,237 +1,250 @@ -# STACKIT-Zielarchitektur des Landing Zone Configurators - -Diese Referenz beschreibt die implementierten Komponenten und ihre -Vertrauensgrenzen. Die Entwicklungsumgebung verwendet STACKIT OIDC; eine eigene -Passwortverwaltung ist nicht vorgesehen. Der Betrieb in der Entwicklungsumgebung -ist kein Nachweis einer produktiv qualifizierten Umgebung. Die getrennten -[MVP-Grenzen](mvp-scope.md) und [Entwicklungsreferenzen](development.md) benennen -verbleibende Aufgaben. - -## Technische Praesentationssicht - -![STACKIT-Zielarchitektur des Landing Zone Configurators](architecture/stackit-overview.svg) - -[Uebersicht als SVG in voller Groesse](architecture/stackit-overview.svg) · -[PNG fuer Praesentationen](architecture/stackit-overview.png) - -Die Uebersicht ist eine bewusst vereinfachte 16:9-Praesentationsgrafik: -Kernkomponenten mit jeweils einem Titel und Untertitel. Sie zeigt den -Hauptablauf UI -> Backend -> Runner -> Landing Zone und die angebundenen -Identitaets-, Repository-, Datenbank- und KI-Dienste. Linien zeigen grundlegende -Beziehungen, keine einzelnen Protokolle oder Datenfluesse. Die blaue -Hinterlegung kennzeichnet die STACKIT-Infrastruktur; nur GitHub mit dem -Accelerator-Repository liegt ausserhalb. Die dunklere CF-Flaeche umfasst -Web UI, Configurator API und Runner. - -Editor und Chat sind Teile derselben Web UI. Die Configurator API beherbergt -die Assistant-Logik, Wissen, Validierung und Orchestrierung. Model Serving stellt -die beiden Modellrollen fuer Antworten und Intent-Erkennung bereit; es betreibt -nicht den eigentlichen Configurator-Assistenten. Zwei Modellrollen muessen nicht -zwei verschiedene Modelle sein: ohne separaten Intent-Override verwenden beide -Rollen das konfigurierte Antwortmodell. - -GitHub und das darin liegende Accelerator-Repository sind an die API angebunden: -die API arbeitet mit den daraus abgeleiteten Templates und Eingabevertraegen. -Diese werden versioniert im Build uebernommen; die Grafik behauptet keinen -Live-Download beliebiger Repository-Staende. Der Runner fuehrt den dazu passenden -gepinnten Accelerator-/Provider-Stand mit OpenTofu aus. - -Die CF-Gruppierung zeigt die Hosting-Plattform, keine gemeinsame CF-Organisation -oder Service-Bindings aller Komponenten. Web UI und API werden gemeinsam -ausgeliefert; Runner bleiben isoliert. Router, Secrets-/State-Verwaltung, -CI/CD und Migrationen sind in der Praesentationsansicht bewusst ausgeblendet. -Die SVG ist direkt editierbar. - -## Logische Praesentationssicht - -![Von Vorlagen zu Landing Zones](architecture/landing-zone-logical.svg) - -[Logische Sicht als SVG](architecture/landing-zone-logical.svg) · -[PNG fuer Praesentationen](architecture/landing-zone-logical.png) - -Die zweite Zeichnung zeigt den fachlichen Zusammenhang ohne Laufzeitdienste: - -- Der **Platform Engineer** nutzt Plattform-Templates als Ausgangsbasis, - erstellt die Plattformkonfiguration und stellt die **Platform Landing Zone** - bereit. -- In diesem Entwurf definiert er auch **Application-Templates** und gibt - gepruefte Versionen fuer den Katalog frei. -- Der **Application Owner** waehlt eine freigegebene Vorlage und ergaenzt die - konkreten Projektparameter in einer Bestellung. Daraus entstehen - **Application Landing Zones** auf Basis der gemeinsamen Plattform. - -Ergaenzungen in der logischen Sicht: - -- **GitHub Repository / Landing Zone Configurator:** Versionsbasis der - Anwendung und ihrer Konfigurationsvertraege. Der Configurator-Code liegt - derzeit im Unterverzeichnis `landing-zone-configurator` des gemeinsamen - `stackitcloud/stackit-landing-zone`-Repos; die Zeichnung behauptet kein - zusaetzliches eigenstaendiges Repository. Kundenkonfigurationen koennen - separat in persoenlichen Accelerator-Forks versioniert werden. Die Linie - bedeutet nicht, dass Kundendokumente im Configurator-Quellrepo landen. -- **Gruene KI-Markierung:** Unterstuetzung bei der Plattformkonfiguration und - den Application-Template-Entwuerfen. Sie bezeichnet Vorschlaege und - Rueckfragen, nicht automatische Veroeffentlichung, Rollenvergabe oder - Cloud-Ausfuehrung. Bei bereits freigegebenen Templates bezieht sich die - Markierung auf deren vorgelagerten Entwurf, nicht auf eine stille Aenderung - veroeffentlichter Versionen. -- **Platform Engineer -> Application Owner / berechtigt:** Vergabe der - tenantgebundenen Mitgliedschaft beziehungsweise Katalogberechtigung. - Mitgliederverwaltung setzt die separat delegierte Verwaltungsfaehigkeit - voraus; die Platform-Engineer-Rolle allein verleiht sie nicht automatisch. -- **STACKIT Service Account:** Autorisierter technischer Cloud-Zugang fuer - die Bereitstellung von Plattform und Anwendungen. Er ist kein Benutzerlogin - und ersetzt weder die Configurator-Rollen noch eine erforderliche Freigabe. - Zugangsdaten werden nicht an den Application Owner herausgegeben; die - Nutzung erfolgt serverseitig und auftragsgebunden. - -Die Pfeile verdichten bewusste Arbeitsschritte, keine automatische -Veroeffentlichung oder Apply-Freigabe. Die Plattformkonfiguration erzeugt nicht -bereits die Anwendungsinstanzen. Template-Versionen und konkrete Bestellungen -bleiben getrennte Objekte; Rollen gelten pro Arbeitsumgebung. - -## Technische Detailreferenz - -Fuer die vollstaendigen Beziehungen, die separate CF Control Plane, -die Migration-App und die Remote-State-Pruefung gibt es zusaetzlich die -[Detailzeichnung als SVG](architecture/stackit-target.svg) und ihre -[editierbare Mermaid-Quelle](architecture/stackit-target.mmd). - -**Leserichtung der Detailzeichnung:** Pfeile zeigen Aufrufe beziehungsweise den bezeichneten -Datenfluss. Doppelpfeile fassen Anfrage und Antwort zusammen. Gestrichelte -Pfeile beschreiben den Release-/Migrationspfad, nicht Kunden-Provisionierung. -Die Boxen unterscheiden Betreiber-Laufzeit, Runner-Isolation, Managed Services, -GitHub und Kundenressourcen; sie sind keine Zusage privater Netzwerkverbindungen. -Die STACKIT-API-Box steht fuer die adressierte Zielorganisation, nicht fuer -physisch darin betriebene API-Server. - -## Bereitstellung und Verantwortlichkeiten - -| Komponente | Bereitstellungsmodell | Aufgabe | + +# STACKIT target architecture of the Landing Zone Configurator + +[English](architecture.md) | [Deutsch](architecture.de.md) + +This reference describes the implemented components and their +trust boundaries. The development environment uses STACKIT OIDC; custom +password management is not planned. Operation in development +is not evidence of a production-qualified environment. The separate +[MVP limitations](mvp-scope.md) and [development references](development.md) identify +remaining tasks. + + +## Technical presentation view + +![STACKIT target architecture of the Landing Zone Configurator](architecture/stackit-overview.svg) + +[Full-size SVG overview](architecture/stackit-overview.svg) · +[PNG for presentations](architecture/stackit-overview.png) + +The overview is a deliberately simplified 16:9 presentation graphic: +core components each have a title and subtitle. It shows the +main flow UI -> backend -> Runner -> Landing Zone and connected +identity, repository, database and AI services. Lines show basic +relationships, not individual protocols or data flows. The blue +background identifies STACKIT infrastructure; only GitHub with the +Accelerator repository is outside it. The darker CF area contains +Web UI, Configurator API and Runner. + +Editor and chat are parts of the same Web UI. The Configurator API hosts +Assistant logic, knowledge, validation and orchestration. Model Serving provides +the two model roles for responses and intent detection; it does not run +the actual Configurator Assistant. Two model roles do not have to be +two different models: without a separate intent override, both +roles use the configured response model. + +GitHub and its Accelerator repository connect to the API: +the API works with templates and input contracts derived from them. +These are incorporated as versioned build inputs; the graphic does not claim +live downloads of arbitrary repository revisions. The Runner executes the matching +pinned Accelerator/provider revision with OpenTofu. + +The CF grouping shows the hosting platform, not a shared CF organization +or service bindings for all components. Web UI and API are +delivered together; Runners remain isolated. Router, secrets/state management, +CI/CD and migrations are deliberately omitted from the presentation view. +The SVG is directly editable. + + +## Logical presentation view + +![From templates to Landing Zones](architecture/landing-zone-logical.svg) + +[Logical view as SVG](architecture/landing-zone-logical.svg) · +[PNG for presentations](architecture/landing-zone-logical.png) + +The second drawing shows the domain relationships without runtime services: + +- The **Platform Engineer** uses platform templates as a starting point, + creates the platform configuration and provisions the **Platform Landing Zone**. +- In this draft, they also define **Application templates** and release + reviewed versions to the catalogue. +- The **Application Owner** selects an approved template and adds the + concrete project parameters in an order. This produces + **Application Landing Zones** based on the common platform. + +Additions in the logical view: + +- **GitHub Repository / Landing Zone Configurator:** version foundation of the + application and its configuration contracts. Configurator code currently resides + in the `landing-zone-configurator` subdirectory of the shared + `stackitcloud/stackit-landing-zone` repo; the drawing does not claim an + additional independent repository. Customer configurations can + be versioned separately in personal Accelerator forks. The line + does not mean customer documents end up in the Configurator source repo. +- **Green AI marking:** assistance with platform configuration and + Application template drafts. It represents proposals and + questions, not automatic publication, role assignment or + cloud execution. For already published templates, the + marking refers to their preceding draft, not a silent change + to published versions. +- **Platform Engineer -> Application Owner / authorized:** granting + tenant-bound membership or catalogue authorization. + Membership management requires the separately delegated administrative capability; + the Platform Engineer role alone does not automatically grant it. +- **STACKIT Service Account:** authorized technical cloud access for + provisioning platform and applications. It is not a user login + and replaces neither Configurator roles nor required approval. + Credentials are not handed out to the Application Owner; usage + is server-side and job-bound. + +The arrows condense deliberate work steps, not automatic +publication or Apply approval. Platform configuration does not +already create Application instances. Template versions and concrete orders +remain separate objects; roles apply per working environment. + + +## Technical detail reference + +For complete relationships, the separate CF Control Plane, +the migration app and remote-state verification, see also the +[detailed SVG drawing](architecture/stackit-target.svg) and its +[editable Mermaid source](architecture/stackit-target.mmd). + +**Reading the detailed drawing:** arrows show calls or the labeled +data flow. Double arrows combine request and response. Dashed +arrows describe the release/migration path, not customer provisioning. +Boxes distinguish operator runtime, Runner isolation, managed services, +GitHub and customer resources; they do not promise private network connections. +The STACKIT API box represents the addressed target organization, not +API servers physically running within it. + + +## Deployment and responsibilities + +| Component | Deployment model | Purpose | |---|---|---| -| Web UI | React-SPA, vom CF-Webprozess ausgeliefert | Editor und Chat, Templates, Auftragsstatus und ausdrueckliche Freigaben | -| Configurator API | Node.js/Fastify in derselben CF-App | Authentifizierung, Mandanten/Rollen, Validierung, Konfigurationscompiler, KI-Assistent, GitHub-Integration und Job-Broker | -| CF Router | Cloud-Foundry-Routing und HTTPS-Route | Browserzugang zur UI und API; keine direkte Browserverbindung zu DB oder Secrets Manager | -| Runner | Eigene CF-Organisation und Space; kurzlebige App/Task je Auftrag | Gepinnte OpenTofu-/Provider-/Accelerator-Ausfuehrung; danach Cleanup | -| PostgreSQL Flex | STACKIT Managed Database | Sessions, Mitgliedschaften, Entwuerfe, Templates, Jobs, Audit sowie verschluesselte Plan-/Recovery-Artefakte | -| Secrets Manager | STACKIT Managed Service | Geschuetzte Service-Account-Schluessel, GitHub-Tokens und Backend-Zugangsdaten | -| Model Serving | STACKIT AI Model Serving | Vom Backend genutzte Modelle fuer Antworten und Intent-Erkennung | -| STACKIT IDP | STACKIT Production; eigener Client je Anwendungsumgebung | OIDC Authorization Code Flow mit PKCE S256; Dev-CF-App bedeutet nicht Dev-IDP | -| GitHub | Externe Plattform | Optionale Benutzerverbindung fuer Forks, Konfigurationen und Pull Requests; getrennt vom STACKIT-Login | -| Landing Zone Accelerator Repo | `stackitcloud/stackit-landing-zone` auf GitHub | Versionierte Infrastrukturquelle; freigegebene Revision wird im Build gepinnt und paketiert | -| GitHub Actions | Geschuetzte CI/CD-Pipeline | Tests, Release-Artefakte, Promotion, Runner-Staging und Migrationen | -| Object Storage / S3 | State-Backend der Kunden-Landing-Zone | Dauerhafter OpenTofu-State, Lockfiles und getrennte State-Keys | -| STACKIT APIs / Zielressourcen | Ausgewaehlte Kundenorganisation und Projekte | Technischer Berechtigungsnachweis, Kataloge und freigegebene Provisionierung | -| Migration-App | Kurzlebige CF-App ohne Route | Versionierte DB-Migrationen mit separater Owner-Rolle; keine Owner-Credentials im Webprozess | - -**UI und Backend sind logische Dienste, keine bereits beschlossenen getrennten -CF-Microservices.** Das aktuelle Release liefert beide in einer CF-App aus. -Eine spaetere physische Trennung ist moeglich, aber nicht Teil dieser Zeichnung. -Auch die Backend-Funktionen sind momentan Module eines API-Prozesses. - -## Die vier wesentlichen Ablaeufe - -### 1. Anmeldung und Organisationszugriff - -Der Browser wird zum STACKIT IDP umgeleitet. Der Backend-Callback tauscht den -Authorization Code mit PKCE aus, prueft die Identitaet und erzeugt eine opaque -Configurator-Session. Organisationszugriff und Bindungsautoritaet werden separat -ueber die vorgesehenen STACKIT-APIs geprueft. Login, Mandantenmitgliedschaft und -Cloud-Berechtigungen sind unterschiedliche Nachweise. - -GitHub bleibt eine optionale zweite Verbindung **fuer Repository-Funktionen**, -nicht der Ersatz fuer STACKIT-Login oder Organisationsrechte. - -### 2. Entwurf und Assistant - -UI-Eingaben und Assistant-Vorschlaege durchlaufen dieselben nativen -Konfigurationsvertraege. Nur das Backend ruft Model Serving auf. Es uebergibt -den begrenzten Konfigurationskontext, keine Service-Account-Schluessel oder -GitHub-Tokens. Der Modellaufruf startet weder einen Runner noch einen Apply. -Vorschlagsuebernahme, Speicherung, Plan und Apply bleiben getrennte Schritte. - -### 3. Freigegebene Ausfuehrung - -Das Backend prueft Rolle, Mandant, Ziel, Konfigurations-/Quellversion, -State-Bindung und die erforderliche Freigabe. Es dispatcht den Auftrag ueber -die CF API in die **separate Runner-Organisation**. Der Runner erhaelt nur -auftragsspezifische Inputs und Credentials ueber ein begrenztes Job-Ticket. -Er besitzt keine Configurator-DB-/Secrets-Manager-Service-Bindings und keine -CF-Dispatcher-Zugangsdaten. - -Der Runner meldet Status und Ergebnisse an den Broker zurueck; dieser persistiert -sie in PostgreSQL. Die Cloud-Operationen verwenden den explizit autorisierten -Service-Account, nicht das menschliche Login-Token. Plan und Apply sind -unterschiedliche Operationen; Apply setzt den geprueften gespeicherten Plan -und die passende Freigabe voraus. +| Web UI | React SPA, served by the CF web process | Editor and chat, templates, job status and explicit approvals | +| Configurator API | Node.js/Fastify in the same CF app | Authentication, tenants/roles, validation, configuration compiler, AI Assistant, GitHub integration and job broker | +| CF Router | Cloud Foundry routing and HTTPS route | Browser access to UI and API; no direct browser connection to DB or Secrets Manager | +| Runner | Separate CF organization and space; short-lived app/task per job | Pinned OpenTofu/provider/Accelerator execution; cleanup afterwards | +| PostgreSQL Flex | STACKIT Managed Database | Sessions, memberships, drafts, templates, jobs, audit and encrypted Plan/recovery artifacts | +| Secrets Manager | STACKIT Managed Service | Protected service-account keys, GitHub tokens and backend credentials | +| Model Serving | STACKIT AI Model Serving | Models used by the backend for responses and intent detection | +| STACKIT IDP | STACKIT Production; separate client per application environment | OIDC Authorization Code Flow with PKCE S256; dev CF app does not mean dev IDP | +| GitHub | External platform | Optional user connection for forks, configurations and pull requests; separate from STACKIT login | +| Landing Zone Accelerator Repo | `stackitcloud/stackit-landing-zone` on GitHub | Versioned infrastructure source; approved revision pinned and packaged in the build | +| GitHub Actions | Protected CI/CD pipeline | Tests, release artifacts, promotion, Runner staging and migrations | +| Object Storage / S3 | State backend of the customer's Landing Zone | Durable OpenTofu state, lockfiles and separate state keys | +| STACKIT APIs / target resources | Selected customer organization and projects | Technical permission verification, catalogues and approved provisioning | +| Migration app | Short-lived CF app without a route | Versioned DB migrations with separate owner role; no owner credentials in the web process | + +**UI and backend are logical services, not already-decided separate +CF microservices.** The current release delivers both in one CF app. +Later physical separation is possible, but not part of this drawing. +Backend functions are currently also modules of one API process. + + +## The four key flows + + +### 1. Login and organization access + +The browser redirects to the STACKIT IDP. The backend callback exchanges the +authorization code with PKCE, checks identity and creates an opaque +Configurator session. Organization access and binding authority are separately +checked through the designated STACKIT APIs. Login, tenant membership and +cloud permissions are different evidence. + +GitHub remains an optional second connection **for repository features**, +not a replacement for STACKIT login or organization permissions. + + +### 2. Draft and Assistant + +UI inputs and Assistant proposals pass through the same native +configuration contracts. Only the backend calls Model Serving. It passes +the bounded configuration context, no service-account keys or +GitHub tokens. A model call starts neither a Runner nor an Apply. +Proposal acceptance, saving, Plan and Apply remain separate steps. + + +### 3. Approved execution + +The backend checks role, tenant, target, configuration/source version, +state binding and required approval. It dispatches the job through +the CF API into the **separate Runner organization**. The Runner receives only +job-specific inputs and credentials through a limited job ticket. +It has no Configurator DB/Secrets Manager service bindings and no +CF dispatcher credentials. + +The Runner reports status and results to the broker, which persists +them in PostgreSQL. Cloud operations use the explicitly authorized +service account, not the human login token. Plan and Apply are +different operations; Apply requires the reviewed saved Plan +and matching approval. ### Execution and state -**State ist nicht gleich Konfigurationsdatenbank:** Der erste Plattform-Bootstrap -verwendet temporaer das persistente, verschluesselte HTTP-State-Backend der API. -Erst nach dem freigegebenen Bootstrap-Apply wird der State in den vom Accelerator -erzeugten Kunden-S3-Bucket migriert und verifiziert. Plattform- und -Application-States erhalten getrennte Keys mit Lockfiles. Der -Configurator-eigene Infrastruktur-State ist wiederum davon getrennt. - -Planartefakte werden vom Backend verschluesselt in PostgreSQL gespeichert. -CI-Release-Artefakte liegen in GitHub Actions. Der zusaetzlich in der Betreiber-IaC -definierte Artifacts-Bucket ist **kein** Beleg dafuer, dass diese Artefakte bereits -dorthin ausgelagert werden; er wird deshalb nicht als aktiver Datenpfad gezeichnet. - -### 4. Software-Lieferkette - -CI baut und testet eine festgelegte Accelerator-Revision, den API-/UI-Release -und das Runner-Paket. Das qualifizierte Artefakt wird ueber eine geschuetzte -Promotion ausgeliefert; Runner-Jobs laden nicht beliebig den aktuellen -Repository-Head. Versionierte DB-Migrationen laufen vorher in einer separaten -kurzlebigen Migration-App. Application-Release und Kunden-Plan/Apply sind -unabhaengige Freigaben. - -## Wesentliche Ergaenzungen zur urspruenglichen Komponentenliste - -1. **Secrets Manager:** notwendig fuer die technische Credential-Verwaltung. -2. **Object Storage / State-Backend inklusive Locking:** notwendig fuer - reproduzierbare und konfliktfreie Infrastrukturverwaltung. -3. **STACKIT APIs und Kundenressourcen:** machen sichtbar, was der Runner - tatsaechlich verwaltet und mit welchen technischen Credentials. -4. **CF Router und Control Plane:** trennen Benutzerzugang von Task-Dispatch. -5. **CI/CD, Release-Artefakte und Migration-App:** zeigen Quelle, Lieferkette und - die Trennung von DB-Owner- und Runtime-Berechtigungen. - -Fuer eine produktionsreife Betriebsarchitektur sind ausserdem festzulegen: - -- Zentrale Logs, Metriken, Alarmierung und deren Aufbewahrung. CF-Logs und - Datenbank-Audit ersetzen kein vollstaendiges Monitoring-/Alerting-Konzept. - Eine konkrete Observability-/Telemetry-Router-Anbindung des **Configurators** - wird hier nicht als bereits eingerichtet dargestellt. -- Verifizierte DB-Backups, Secret-/Artefaktschluessel-Recovery, S3-Versionierung - und Wiederherstellungstests. Der Verlust des bestehenden Artefaktschluessels - darf nicht durch spontane Rotation verdeckt werden. -- Skalierung/HA sowie gemeinsame Ablage oder Sticky Routing fuer laufende - OIDC-Flows. Die aktuelle Ein-Instanz-Anwendung ist kein HA-Nachweis. -- Netzwerkpfade, ACLs und Egress-Regeln. Ein CF-Runner hat nicht automatisch - Zugriff auf private Kubernetes-/Helm-/Firewall-Endpunkte in Kunden-SNAs. - Diese Ausfuehrungsgrenze bleibt separat zu loesen (#37). -- Eng begrenzte Betriebs-/Deployment-Identitaeten, kontrollierte CF-Space-Rechte - und eine Least-Privilege-Qualifikation des OIDC-Clients. - -Es wird **kein** zusaetzlicher Queue-Service vorausgesetzt: Auftragsmetadaten -liegen in PostgreSQL, der Broker dispatcht CF-Tasks. Ein allgemeiner Scheduler -waere eine eigene spaetere Architekturentscheidung. - -## Grundlagen und Weiterfuehrung - -- [CF-Release und Service-Bindings](../deploy/cloud-foundry/README.md) -- [Runner-Paket und Accelerator-Pin](../deploy/runner/README.md) -- [Plan-Ausfuehrung, Broker und State-Lebenszyklus](plan-execution.md) -- [Login und Organisationsnachweis](github-login.md) -- [Plattform-/Application-Vertraege](platform-application-architecture.md) +**State is not the configuration database:** the first platform bootstrap +temporarily uses the API's persistent encrypted HTTP state backend. +Only after the approved bootstrap Apply is state migrated to the customer +S3 bucket created by the Accelerator and verified. Platform and +Application states receive separate keys with lockfiles. The +Configurator's own infrastructure state is separate again. + +The backend stores Plan artifacts encrypted in PostgreSQL. +CI release artifacts reside in GitHub Actions. The artifacts bucket +additionally defined in operator IaC is **not** evidence that these artifacts +are already offloaded there; it is therefore not drawn as an active data path. + + +### 4. Software supply chain + +CI builds and tests a fixed Accelerator revision, the API/UI release +and Runner package. The qualified artifact is delivered through protected +promotion; Runner jobs do not arbitrarily load the current +repository head. Versioned DB migrations run beforehand in a separate +short-lived migration app. Application release and customer Plan/Apply are +independent approvals. + + +## Key additions to the original component list + +1. **Secrets Manager:** necessary for technical credential management. +2. **Object Storage / state backend including locking:** necessary for + reproducible and conflict-free infrastructure management. +3. **STACKIT APIs and customer resources:** make visible what the Runner + actually manages and with which technical credentials. +4. **CF Router and Control Plane:** separate user access from task dispatch. +5. **CI/CD, release artifacts and migration app:** show source, supply chain and + separation of DB owner and runtime permissions. + +A production-ready operational architecture must also define: + +- Central logs, metrics, alerting and retention. CF logs and + database audit do not replace a complete monitoring/alerting concept. + A concrete Observability/Telemetry Router integration for the **Configurator** + is not presented here as already configured. +- Verified DB backups, secret/artifact key recovery, S3 versioning + and restore tests. Loss of the existing artifact key + must not be concealed by spontaneous rotation. +- Scaling/HA and shared storage or sticky routing for ongoing + OIDC flows. The current single-instance application is not HA evidence. +- Network paths, ACLs and egress rules. A CF Runner does not automatically + have access to private Kubernetes/Helm/firewall endpoints in customer SNAs. + This execution boundary remains separately resolvable (#37). +- Narrowly scoped operational/deployment identities, controlled CF space rights + and least-privilege qualification of the OIDC client. + +**No** additional queue service is assumed: job metadata +resides in PostgreSQL, and the broker dispatches CF tasks. A general scheduler +would be a separate later architecture decision. + + +## Background and further reading + +- [CF release and service bindings](../deploy/cloud-foundry/README.md) +- [Runner package and Accelerator pin](../deploy/runner/README.md) +- [Plan execution, broker and state lifecycle](plan-execution.md) +- [Login and organization proof](github-login.md) +- [Platform/Application contracts](platform-application-architecture.md) - [PostgreSQL Flex](../infra/platform/2-database.tf), - [Secrets Manager](../infra/platform/3-secrets.tf) und + [Secrets Manager](../infra/platform/3-secrets.tf) and [Model Serving](../infra/platform/5-model-serving.tf) -Die Detail-SVG wird lokal mit Mermaid CLI 11.12.0 aus der Mermaid-Quelle gerendert. -Die Uebersicht verwendet ausschliesslich lokale SVG-Formen und Systemschriften. -Keine Zugangsdaten, Konfigurationen oder Diagrammquellen werden an einen -Online-Renderer gesendet. +The detail SVG is rendered locally with Mermaid CLI 11.12.0 from the Mermaid source. +The overview uses exclusively local SVG shapes and system fonts. +No credentials, configurations or diagram sources are sent to an +online renderer. diff --git a/landing-zone-configurator/docs/assistant-feature-coverage.de.md b/landing-zone-configurator/docs/assistant-feature-coverage.de.md new file mode 100644 index 0000000..9f6affc --- /dev/null +++ b/landing-zone-configurator/docs/assistant-feature-coverage.de.md @@ -0,0 +1,861 @@ + + +# Assistent: Feature-Abdeckung und Dialogabnahme + +[English](assistant-feature-coverage.md) | [Deutsch](assistant-feature-coverage.de.md) + + + + +Stand: 2026-10-12. Lokaler Assistant mit automatischem Feldinventar und echten +synthetischen Themen-Smokes; keine vollstaendige Komponenten-/Cloud-Qualifikation. +Der bestehende Editor-/Compilervertrag bleibt massgeblich. +Produktentscheidungen: [Planung](planning.de.md#11-chatbot-mit-stackit-model-serving). + + + +## Aktuelles Feldinventar und automatisierte Themenfaelle + +Der [aktuelle Testkatalog](assistant-test-catalogue.json) ordnet alle 501 +Katalogfelder (einschliesslich Container und Listenelement-Vertraegen) genau einem +der 19 Wissensthemen zu. Er fuehrt Typ, Optionalitaet, Verantwortlichkeit, +tatsaechlichen Modus und erlaubten nativen Patch-Pfad auf. Unterschied zwischen +bekanntem Feld und unterstuetztem Vorschlag bleibt sichtbar: beispielsweise +regionale DNS-Felder und zentrale Dienste ueber den gemeinsamen nativen +Editor-Vertrag vorschlagbar, geschuetzte Zugangswerte nur Operator-Voraussetzungen. +Management-/Lifecycle-Themen ohne eigene Root-Eingaben haben eigene Chatfaelle. + +Die Themenfelder einschliesslich Abhaengigkeiten werden als `componentFields` +an das Antwortmodell uebergeben; erlaubte Rueckfragefelder bleiben separat +eingeschraenkt. Antwortquellen sind auf die tatsaechlich gelieferte +Themenauswahl begrenzt. Metadaten enthalten keine Secret-Werte. + +52 feste [Chatfaelle](../app/scripts/assistant-scenarios.ts) decken jedes Thema +und exakte DNS-/Grundlagen-/SNA-/Rollen-/Firewall-Regressionen ab. Katalog und Live-Bericht sind an +Wissens-, Engine- und Testquellhash gebunden. Normale PR-Checks pruefen offline +Frische, Feldzuordnung und Regression-Pruefer; echte Modellaufrufe sind explizit. +Start, Credentials, Einzelthemen und manueller CI-Lauf sind im +[App-README](../app/README.de.md#automatisierte-assistant-themenpruefung) beschrieben. +Live-Tests nutzen keine Benutzer-SSO-Sitzung und speichern keine Kundenentwuerfe. + + + +### Gemeinsamer Editor-Vorschlagsvertrag + +Der Assistant leitet seine geschlossenen Wertschemas aus demselben nativen +`InputType`-Inventar wie der Editor ab. Alle effektiven, nicht geschuetzten +Katalogpfade haben eine validierte Vorschlagsroute; Firewall-Policy bleibt +gemaess #101 ausgeschlossen. Das ist Feld-/Entwurfsparitaet, keine Behauptung +vollstaendiger Cloud-Ausfuehrungsqualifikation. + +`merge` erhaelt ausgelassene Objektattribute und Map-Eintraege. Listen bleiben +atomar. `replace` und `default` werden als vollstaendiger Ersatz bzw. Rueckkehr +zum nativen Standard angezeigt, nicht in gefaehrliche Teilersetzungen zerlegt. +Operationen bleiben durch Feldwahl, Konfliktpruefung, API und Speicherung erhalten. +Projektvorlagen werden separat von konkreten Projektinstanzen behandelt; +neue Kennungen werden serverseitig erzeugt. Publikation und Bestellungen sind +keine Chat-Aktionen. + +[Vertragstests](../app/tests/assistant-editor.test.ts) pruefen typisierte Werte +fuer jeden effektiven nicht ausgeschlossenen Katalogpfad sowie echte +Anwendung/Export, native Eingaben, Audit-Pflichtentscheidungen, Teilwahl, +atomare Ersetzung/Standards, stabile Vorlagenkennungen und unbestaetigte +IP-/ID-/Kontakt-/Produktwerte. Echte synthetische Modellfaelle pruefen die +natuerliche Uebersetzung separat; reine Metadaten gelten nicht als Dialogabnahme. + +Der Vertrag unterscheidet nun den Zustand des Zielobjekts. Bei Erstellung muessen +einfache skalare/List-Slots im Serving vorhanden sein, statt vom Decoder +ausgelassen zu werden. Nicht angefragte optionale Null-Slots werden vor der +Vorschlagsausgabe als native Defaults ausgelassen; bei Updates bleiben explizite +Null-Werte unveraendert. Komplexe optionale Collections werden nicht zwangsweise +gefuellt: insbesondere sind leere Audit-Link-Scopes kein Organisationsdefault. +Neue Map-Eintraege verlangen native Pflichtfelder wie Kubernetes-Region und +Node-Pool-Name; bestehende Eintraege bleiben ueber bekannte Unterpfade partiell +aenderbar. + +Komponentenspezifische Zusatzregeln liegen deklarativ in +`assistantEditorPolicies`, nicht in einem zweiten Feldmodell: +Audit-Erstellungsentscheidungen und ACL-Freitextfragen sind die ersten Regeln. +Ihre Pfade werden gegen das native Inventar getestet. Angebotenes Serving-Schema +und unveraenderte native Laufzeitpruefung werden beide durchlaufen; keine +Reparatur doppelter, unvollstaendiger oder unbestaetigter Antworten. +Topic-Korrektur verwendet eindeutige Besitzer der validierten nativen Roots, +nicht frei erfundene Komponentennamen. Irrelevante Firewall-Anforderungen werden +vor ihrer Quellenpruefung aus Nicht-Netzwerkthemen entfernt; Quellenpruefungen +fuer tatsaechlich genutzte Netzwerkentscheidungen bleiben strikt. +DE/EN-Vorschlagstexte mit Aenderungen werden serverseitig als lokale +Entwurfsvorschlaege erzeugt und koennen keine Speicherung oder Live-Grants +behaupten. Das [Erweiterungsvorgehen](../app/README.de.md#weitere-assistant-komponenten-ergaenzen) +verbindet Inventar, Wissen, Zusatzregeln, Anwendungstests und serielle +Modellqualifikation. + + + +### Vorheriger Nachweis: Themenwechsel von Firewall zu Audit Logging + +Der erkannte aktuelle Topic darf nicht von geerbtem `networkScope` oder alten +Firewall-Targets ueberschrieben werden. Solche Merkmale gelten ausschliesslich +im aktiven Netzwerk-/Firewall-Thema; ihre belegten historischen Anforderungen +werden nach der Belegpruefung aus einem anderen Topic entfernt, nicht geloescht +oder als dessen aktuelle Anforderungen uebernommen. Ein aktueller Auftrag mit +"als naechstes ... richte ein" ist keine Vertagung. + +Audit-Setup erhaelt eine gepruefte native Feldberatung zu Telemetry Link/Router, +Logs und Archiv mit der ausdruecklichen Grenze: derzeit kein uebernehmbarer +Audit-Patch im Chat. Der gemeinsame Editor hat generische Felder unter Plattform. +Keine stille Aktivierung, Retention-/ACL-Wahl oder Object-Lock-Zusage; keine +Fortsetzung der Firewall-Unterbrechungsfrage. Audit-Proposals sind damit nicht +automatisch aus dem MVP genommen. + +Nachweis: **209 gezielte Offline-Tests**, Typpruefung und **16/16 echte +synthetische Modellfaelle** (2 Audit-Faelle einschliesslich des gemeldeten +Wechsels, 14 Firewall-Regressionen) bestanden. Wissenshash: +`8d8322d3c83f806d87ebbb7574443a8e06a9d8bcb98995e2557613c7216de906`; +Testsuitehash: +`5314926be9bd321415c1377b7433fcd74cf61428295c70200d23db32e4b51d4d`. +Keine Kundenpolicy/-konfiguration oder Cloud-Ausfuehrung zur Qualifikation. +Der Stand ist in der HTTPS-Entwicklungsumgebung aktiviert; API-Gesundheit und +unveraenderte vollstaendige Konfigurations-/Gesprächszeilen sind nach Neustart +geprueft. Bestehende Gespraeche bleiben fortsetzbar. + + + +### Aktueller MVP-Scope: keine Firewall-Policy-Vorschlaege + +Benutzerentscheidung 2026-10-13: +[Issue #101](https://github.com/stackitcloud/stackit-landing-zone/issues/101) +verschiebt gefuehrte Policy-Bearbeitung und uebernehmbare Assistant-Vorschlaege +aus dem MVP. Generische native Felder im gemeinsamen Editor bleiben erhalten; +die MVP-Alternative ist manuelle Policy-Pflege durch den Firewall-Admin in +OPNsense. Infrastruktur und HA garantieren allein keine Isolation oder NAT. + +Aktuelle Faehigkeits- und Definitionsanfragen fuer Regeln/NAT/Aliase/Routen/ +Port-Forwarding erhalten die explizite Chatgrenze, #101 und die Admin-Alternative, +ohne Aenderungen oder einen Regelvorschlag versprechende Rueckfragen. +Native Feldberatung bleibt moeglich. Historische Regelanforderungen verdrangen +keine aktuelle Infrastruktur-/Kapazitaetsantwort; Infrastruktur/HA-Patches +bleiben verfuegbar. Weitere MVP-Gates werden damit nicht aufgehoben. + +Nachweis: **205 gezielte Offline-Tests**, Typpruefung, Wissens-/Katalogfrische +und **16/16 echte synthetische Modellfaelle** (14 Infrastruktur-/Dialogfaelle, +2 Policy-Faelle) bestanden. Die Tests pruefen keine Kundenpolicy und autorisieren +keine Cloud-Ausfuehrung. Wissenshash: +`b9892a0d275b920e3089c167157062ef66af29630374df0b8a6d03ba5d24c37b`; +Testsuitehash: +`f443f6633a4ffda7662f419d797a01ffe039c56f0ca5c4aaa187316036cc9c81`. +Der qualifizierte Backend-Stand ist in der HTTPS-Entwicklungsumgebung aktiviert. +API-Gesundheit und unveraenderte vollstaendige Konfigurations-/Gesprächszeilen +wurden vor/nach Neustart geprueft; UI und Kundendaten wurden nicht umgebaut. + + + +### Vorheriger Nachweis: Firewall-Faehigkeitsgrenze und handlungsfaehige Fehler + +Der native Accelerator verwaltet `firewall_config` mit Regeln, Aliasen, Routen, +ausgehendem NAT und Port-Forwarding. Der aktuelle Chat kann nur Infrastruktur +und HA als Vorschlag patchen, nicht den komplexen Policy-Vertrag. Eine aktuelle +Frage nach dieser Faehigkeit hat Vorrang vor laufenden Infrastrukturfragen. +Die Antwort nennt den Editorweg, offene Regelziele und API-Voraussetzungen; +bisherige Verkehrs-/Policy-Antworten bleiben Anforderungen, keine Regeln. +Historische Faehigkeitsfragen duerfen eine aktuelle Kapazitaetsantwort nicht +verdraengen. Der Intent benennt dafuer ausdruecklich die aktuelle Quelle. + +Abgelehnte Modellantworten werden nicht automatisch wiederholt oder teilweise +angenommen. JSON und NDJSON liefern denselben redigierten Fehlervertrag: +unbestaetigte Anforderungen, unpassender Vorschlag, ungueltige/abgeschnittene/ +unterbrochene Antwort, Timeout, Auslastung, Dienstanmeldung oder Verfuegbarkeit. +Konfigurations-Chat und Template-Beratung zeigen lokalisierte Ursachen, +konkrete naechste Schritte und eine Diagnosekennung; Eingaben bleiben erhalten. +Modell-Rohantworten, Transportdetails und Zugangsdaten werden nicht angezeigt. + +Nachweis am 2026-10-13: **196 gezielte Offline-Tests**, **6 PostgreSQL-Faelle**, +**13/13 echte synthetische Firewall-Faelle** und +**8 Desktop-/Mobil-Browserfaelle** bestanden, einschliesslich der gemeldeten +Faehigkeitsfrage, unbekannter Kapazitaet, handlungsfaehiger Fehlermeldungen und +Antwort-/Auswahlerhalt. Wissenshash: +`53945a3b8988baf2b4096365496e01fa3a38beb83b2d7da3e43bb0fcab798181`; +Testsuitehash: +`2caf7ed586cda64bf151f3fa6bd4466b8504da63fb45666ed4ca77e1b2bc4e3d`. +Dies ist keine Policy-/Paketpruefung und keine Cloud-Ausfuehrungsfreigabe. +Typpruefung, Wissens-/Katalogfrische und gezieltes Lint bestanden (eine +vorbestehende Browser-Testwarnung). Der Stand wurde in der HTTPS- +Entwicklungsumgebung aktiviert; API-Gesundheit und neues UI-Bundle wurden +geprueft. Vollstaendige Konfigurations-/Gesprächszeilen blieben unveraendert. + +Vorheriger Nachweis vor dem Rollenpatch am 2026-10-12: **93 Offline-Tests**, Typpruefung, Wissens-/Katalogfrische +und gezieltes Lint bestanden. Abschliessender echter Lauf: **24/24 bestanden, +kein uebersprungener Fall**, mit Qwen3-VL als Antwortmodell und GPT-OSS-120B als +Intentmodell. Die fuenf zuvor roten Faelle sind behoben; die Sollpruefungen wurden +nicht gelockert, sondern um Feldnamen, Grenzen und falsche Speicherbehauptungen +erweitert. Grundlagenwiederherstellung und alle drei DNS-Kontaktvarianten bleiben +gruen. Keine automatische Wiederholung oder Annahme fehlgeschlagener Antworten. + +| Fall | Ursache und Korrektur | Live-Nachweis | +|---|---|---| +| `identity-foundations-advice` | Serving verlor fruehere Systemnachrichten; Ausgabe endete am Tokenlimit. Ein einziger Systemvertrag und eine gepruefte native Felduebersicht ersetzen die unvollstaendige Freiform-Aufzaehlung. | bestanden, 1659 ms | +| `governance-folders-advice` | Namens-Patchgrenzen wurden mit Editor-Feldern verwechselt. Uebersicht nennt Elternordner, Rollen und Namen 1-40 Zeichen; meaningful descriptions werden explizit abgelehnt. | bestanden, 1391 ms | +| `firewall-policy-advice` | Gemeinsamer Firewall-Infrastrukturdialog verdraengte den Policy-Vertrag. Getrennte Themenfragen und native Policy-Uebersicht mit aliases/routes/rules/NAT, pass/block/reject und expliziter Synchronisierung. | bestanden, 1929 ms | +| `sandbox-projects-advice` | Verlorener Systemvertrag/Tokenlimit; erfundene Laufzeit-/Budgetoptionen. Native Uebersicht nennt nur project_name, project_owner_email und owner_emails sowie die separaten Lifecycle-Grenzen. | bestanden, 1583 ms | +| `sna-complete-draft` | Modellprosa behauptete eine bereits erfolgte Konfiguration. Erklaerung wird aus validierten Patch-Werten erzeugt; Streaming zeigt keinen ungeprueften Speichertext. | bestanden, 3946 ms | + +Der semantische Intent `adviceTask=field-overview` nutzt fuer diese vier +Uebersichtsthemen den Backend-Wissensvertrag mit Feldinventar und geprueften +Grenzen. Das ist ein expliziter Beratungspfad, kein Erfolg-Fallback nach einem +Modellfehler. Andere Fragen und Vorschlaege verwenden weiterhin das Antwortmodell. +Ein Tokenlimit-Abbruch wird als `completion_truncated` verworfen; der HTTP-Fehler +bleibt redigiert. Alle vertrauenswuerdigen Systemanweisungen werden zusammen +gesendet, Nutzer-/Historiennachrichten bleiben getrennte untrusted Daten. +Native Editorfelder und schmalere Chat-Patchrechte bleiben unterscheidbar; +Rueckfragen sind auf das aktive Thema beschraenkt. +Der gepruefte Stand wurde lokal im Chatmodus ohne Cloud-Ausfuehrung neu gestartet. +API und UI-Proxy melden gesund; UI HTTP200 und unauthentifizierte Chatroute HTTP401. +Konfigurations-/Gesprächspruefsummen und Revisionen (6/19) blieben unveraendert. + +Die Themen-Smokes pruefen Antwortvertrag, Referenz und Beratungsmodus, nicht jede +fachliche Textaussage oder jedes Feld einzeln. Fuer Vollqualifikation braucht es +weitere spezifische Sollwerte, Negativfaelle und Komponentenbeziehungen. Ein +vollstaendiges Inventar oder ein gruener Smoke ist keine Ausfuehrungsfreigabe. + + + +### Modellversuch GPT-OSS 120B und zusammenhaengender Dialog + +Am 2026-10-13 wurden Antwortmodell und Intentmodell in isolierten Testprozessen +auf `openai/gpt-oss-120b` gesetzt. Die laufende Anwendung, Kundenentwuerfe, +Gespraeche und Cloud-Ausfuehrung wurden nicht umgestellt. + +Der erste komplette 52-Faelle-Lauf bestand **29/52**. Von 23 Fehlern waren neun +HTTP-429-Antworten; parallel laufende Diagnose-/Journey-Tests beeintraechtigten +damit die Aussagekraft. Weitere Fehler waren sechs Tokenlimit-Abbrueche, vier +Scope-Ablehnungen, eine unbestaetigte Intentquelle und drei fachliche +Sollwertverletzungen. Diese Zahlen sind kein fairer Modellrangvergleich. +Wissenshash dieses ersten Laufs: +`c9bcfb0a1e8c3d2be7855a8db2a3a0ffc8ad392e0ed854d880ca876effad2ef2`; +52-Faelle-Suite: +`574375fd7a19aa775bba0bf766156660721454ae5db6a7013d69b2689dd6da32`. + +Synthetische Rohantworten zeigten wiederholte merge/replace-Alternativen fuer +denselben Pfad und ausgelassene Audit-ACLs trotz Nennung im Antworttext. +Die Serving-Schemas verwenden deshalb nun ein einzelnes Operationsobjekt pro +Pfad und begrenzen die Anzahl auf die angebotenen Pfade. Nicht unterstuetzte +`propertyNames` werden nur aus dem Serving-Schema entfernt; die urspruengliche +Zod-Pruefung von Map-Schluesseln, Operationswerten und vollstaendigen +Ersetzungen bleibt unveraendert. Ein gekuerzter Label-Reply enthielt vor allem +Whitespace statt Nutzdaten; ein hoeheres Tokenbudget oder automatischer Retry +ist daher kein nachgewiesener Fix. + +Der neue [Journey-Runner](../app/scripts/assistant-journey.ts) wurde danach fuer +beide Modelle **seriell** mit identischem Skript, Wissensstand, Temperatur und +Tokenlimit ausgefuehrt. Beide Modellrollen verwendeten jeweils dasselbe Modell. +Er simuliert Grundlagen, Rollen, SNA, Firewall/HA, die Policy-MVP-Grenze, +Audit-Themenwechsel/Rueckfragen/Aktualisierung, Observability, DevOps, +Kubernetes und Labels. Nur gueltige, erwartungsgemaesse Vorschlaege werden im +Speicher uebernommen. API-konforme Gespraechshistorie, JSON-Roundtrip und +tfvars-Export bleiben Bestandteil des Laufs; kein Browser, DB-Speichern, +Plan oder Apply wird dadurch qualifiziert. + +| Serieller Journey-Schritt | GPT-OSS 120B | Qwen3-VL 235B A22B | +|---|---|---| +| Grundlagen | Scope-Ablehnung | bestanden | +| Organisations-Owner | bestanden | bestanden | +| SNA | bestanden | bestanden | +| Firewall/HA | bestanden | bestanden | +| Policy-MVP-Hinweis | bestanden | bestanden | +| Audit-Themenwechsel / fehlende Entscheidungen | Pflichtwerte fehlen | bestanden | +| Audit-Antwort | Pflichtwerte fehlen | Pflichtwerte fehlen | +| Audit-Aktualisierung | Pflichtwerte fehlen | Pflichtwerte fehlen | +| Observability | unbestaetigte Intentquelle | erwartete ACL/Retention fehlen | +| DevOps | bestanden | bestanden | +| Kubernetes | Vorschlag nicht anwendbar | Vorschlag nicht anwendbar | +| Labels | Tokenlimit-Abbruch | falsches Thema / Label fehlt | +| **Gesamtergebnis** | **5/12, nicht qualifiziert** | **7/12, nicht qualifiziert** | + +Die seriellen Laeufe enthielten keine HTTP-429/503-Ablehnungen. Beobachtete +Turn-Dauern einschliesslich Intentklassifikation: GPT-OSS Median ca. 7,0 s, +Maximum 22,5 s; Qwen Median ca. 5,7 s, Maximum 12,3 s. Dies sind einzelne +synthetische Laeufe, keine allgemeine Latenz-, Kosten- oder Qualitaetsgarantie. +Beide Laeufe verwenden Wissenshash +`b21aac363a8f2d9110a4e21d4473b630bc193b0b02e9d04926f306f4c98af73d` +und Journey-Hash +`80ce96770cd172dbbfd37f73b5443cffd2e3f5e521627d2bf53aa2b20df1dd9e`. +**228 gezielte Offline-Tests**, Typpruefung, gezieltes Lint und +Wissens-/Katalogfrische bestanden. + +Ergebnis: Ein reiner Modellwechsel behebt die Editor-/Assistant-Probleme nicht. +GPT-OSS wird auf dieser Basis nicht als neuer Standard aktiviert. Audit-Pflicht- +und Rueckfragevertraege, Label-Intent, anwendbare Kubernetes-Vorschlaege sowie +Scope-/Quellenkontinuitaet muessen vor einer erneuten Vollqualifikation +bearbeitet werden. Auch die native Editor-Erweiterung bleibt unaktiviert. + + + +### Gemeinsame Komponentenvertraege: erneute Qualifikation + +Die anschliessende Korrektur erfolgt im gemeinsamen nativen Vorschlagsvertrag, +nicht ueber modellspezifische Sonderfaelle. Neue Audit-Konfigurationen brauchen +Retention, ACL und die ausdrueckliche Object-Lock-Entscheidung zusammen. +Bestehende Objekte bleiben partiell aenderbar. Kubernetes-Erstellung verlangt +native Pflichtfelder einschliesslich Region und Node-Pool-Name; Labels verwenden +den geprueften Besitzer ihrer nativen Pfade. Ein Themenwechsel verwirft +irrelevante Firewall-Anforderungen, nicht aber Quellenpruefungen fuer weiterhin +genutzte Netzwerkentscheidungen. ACL-Rueckfragen erfinden keine auswaehlbaren +CIDRs. Vorschlagstexte behaupten weder Speicherung noch Deployment. + +Nach diesen Aenderungen bestanden am 2026-10-13: + +| Pruefung | Ergebnis | +|---|---| +| Gezielt alle acht Assistant-Offline-Suites | **238/238** | +| Typpruefung und Produktionsbuild | bestanden | +| Repository-Lint | keine Fehler; bestehende Warnungen bleiben | +| Wissens- und Szenarienkatalogfrische | bestanden | +| Zusammenhaengender echter Qwen-Dialog | **12/12** | +| Vollstaendiger echter Qwen-Szenarienlauf | **52/52** | + +Beide Modellrollen verwendeten weiterhin +`Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`. Die Modelltests liefen nacheinander und +ohne automatische Wiederholung. Vorherige Laeufe mit denselben +Komponentenvertraegen waren durch HTTP 429 unvollstaendig geblieben. +Der [gemeinsame Testadapter](../app/scripts/assistant-test-model.ts) begrenzt +jetzt jeden tatsaechlichen Request, einschliesslich Intentklassifikation, auf +mindestens 2500 ms Abstand. Tests pruefen Abstand, fehlenden Retry und Abbruch +waehrend der Wartezeit. Diese Begrenzung gilt nicht fuer den produktiven +Assistant; die gemessenen Turn-Zeiten enthalten Testwartezeit. +Die beiden abschliessenden Laeufe enthielten keine Quoten- oder Modellfehler. + +Nachweis-Hashes: + +- Wissen: `eb856918ecd71e3f380ea8da9be116d4578cedfc9977088c56311b9e65d44346` +- Journey: `74b5d41782e20b9d720a63afa1d515e50c4197602f41789d1ce920f1598d64e2` +- Szenariensuite: `57888ab5cfccc1303ebfd01125a9c6ed185b82602eab83a75a7eb20b1e34d498` + +Der Journey uebernahm gueltige Vorschlaege in einen fortgeschriebenen +synthetischen Entwurf, bewahrte 24 Gespraechsnachrichten, pruefte den +JSON-Roundtrip und exportierte 2069 Bytes tfvars. Dies ist keine Qualifikation +aller Browser-/Datenbank-Workflows oder von Plan/Apply. Kundenentwuerfe und +Gespraeche wurden nicht veraendert; die laufende API wurde nicht neu gestartet. +GPT-OSS ist nach diesen Vertragskorrekturen noch nicht erneut qualifiziert. +Die Firewall-Policy bleibt als einzige hier ausdruecklich ausgeschlossene +Komponentenbearbeitung unter #101; es wurden keine weiteren Themen aus dem +MVP genommen. Weitere Komponenten folgen dem dokumentierten +[Erweiterungsverfahren](../app/README.de.md#weitere-assistant-komponenten-ergaenzen). + + + +### Dev-Release-Qualifikation (2026-10-14) + +Der korrigierte Release-Stand `927f20a` wurde erneut mit dem echten Qwen-Modell +qualifiziert: **52/52** synthetische Katalogfaelle und **12/12** Schritte im +fortgeschriebenen Gesamtdialog bestanden ohne automatische Wiederholung. +Der vorangegangene Lauf auf `1aabadb` bestand nur 51/52 Faelle: Eine bestaetigte +Firewall-Verkehrsentscheidung wurde erneut abgefragt. Die anschliessende +Klassifikationsklarstellung und der gezielte Regressionstest wurden vor dem +vollstaendigen Wiederholungslauf ausgefuehrt; der erste Fehlerbeleg bleibt erhalten. + +- Wissen: `12693f9d18db481e57ae668b777bfd19715a96f121aa94efa984bc5cd8747bea` +- Journey: `74b5d41782e20b9d720a63afa1d515e50c4197602f41789d1ce920f1598d64e2` +- Szenariensuite: `57888ab5cfccc1303ebfd01125a9c6ed185b82602eab83a75a7eb20b1e34d498` + +Der Journey bewahrte 24 Gespraechsnachrichten und exportierte 2069 Bytes tfvars. +Zusaetzlich bestanden 685 Unit-, 49 PostgreSQL- und 288 Desktop-/Mobile-Tests +sowie Typpruefung, Produktionsbuild, Katalogfrische und Release-Vorbereitung. +Die gehostete Assistant-Aktivierung wird ueber das geschuetzte +`LZC_ASSISTANT_ENABLED`-Opt-in weitergereicht und verlangt Authentifizierung. +Realer menschlicher Login, Organisationsnachweis und Kunden-Cloud-Ausfuehrung +sind separate Nachweise; ihr aktueller Status steht im +[MVP-Umfang](mvp-scope.de.md). Die oben genannten Zahlen sind historische, +revisionsgebundene Ergebnisse; aktuelle Nachweise stehen in CI und im +zugehoerigen Pull Request. + + + +### Additive Organisations- und Folder-Rollenvorschlaege + +Die gemeldete Bitte um Nutzung der hinterlegten E-Mail als +Organisationsverantwortlicher wurde faelschlich als Grundlagenkontakt behandelt. +Der bislang schmalere Namens-/Skalarvertrag liess Rollenfelder nicht zu. +Explizite Rollenzuweisungswuensche werden jetzt semantisch als Governance-Entwurf +klassifiziert. Ein gepruefter Backend-Pfad erstellt `organization_owners`, +`organization_auditors` oder vorhandene Folder-Owner-/Reader-Listen aus der +angefragten gespeicherten, verifiziert menschlichen oder explizit genannten +E-Mail-Quelle, ohne freie Rollenwerte des Antwortmodells. Das ist kein Fallback +nach Modellfehlern und kein menschlicher Identitaetsnachweis. + +Vorhandene Zuweisungen, Folder-Namen, Schluessel und uebrige Konfiguration bleiben +erhalten. Neue Folder, entfernte Subjects, Elternordner-/Configurator-Rollen oder +Live-Grants sind nicht erlaubt. Fehlende E-Mail oder unklare Folder-Auswahl werden +gezielt erfragt. Organisations-Owner-Rechte decken Folder ab; die native +Governance vermeidet doppelte Folder-Zuweisungen. Folder-Reader verwenden auditor. +Selektive Uebernahme speichert weiterhin nur den Entwurf, unselektierte Felder +bleiben offen; IAM-Auswirkungen benoetigen einen getrennten geprueften Plan/Apply. + +Zusatznachweis am 2026-10-12: **110 Offline-Tests**, Typpruefung und gezieltes Lint +bestanden. **30/30 echte synthetische Faelle** bestanden, diesmal mit Qwen3-VL +sowohl als Antwort- als auch als Intentmodell entsprechend dem laufenden +Workstation-Modus. Die sechs neuen Governance-Faelle pruefen die gemeldete Frage, +alle explizit ausgewaehlten Folder, einen konkreten Reader, fehlende Folder-Auswahl, +fehlende E-Mail und die verifizierte Login-Quelle. Drei fokussierte echte +PostgreSQL-Tests pruefen transaktionale Rollen-/DNS-/Netzwerk-Felduebernahme, +Revisionsgrenzen und Tenant-Isolation. Keine Kundenkonfiguration, kein +Kundengespraech und keine Cloud-Berechtigung wurde durch die Tests veraendert. + + + +### Native Firewall-Infrastruktur und HA + +Der bisherige SNA-Dialog nahm ohne Grundlage einen ausschliesslichen ersten +Netzwerkschritt an; Firewall-Infrastruktur war nur beratend unterstuetzt. +Explizite kombinierte Auftraege verwenden jetzt die gespeicherten SNA-Werte und +setzen mit dem Firewall-Vertrag fort. Fehlende SNA-Eingaben bleiben echte +Abhaengigkeiten, ein ausdrueckliches "Firewall spaeter" bleibt SNA-only. +Die Kapazitaetsrechnung trennt Projekt-Subnetze und Adressen: /16 enthaelt512 /25, +jeder /25 hat128 Adressen vor Infrastrukturreservierungen, ohne Quoten-/Durchsatz- +oder Freibelegungszusage. + +Zentrale `connectivity.firewall`/`firewalls` akzeptieren gepruefte native +Infrastrukturfelder einschliesslich des HA-Objekts mit anderer Backup-Zone, +optionalen Node-/VIP-Adressen, Backup-Namen und vhid. Ein zusammenhaengender Patch +enthaelt alle Pflichtfelder neuer Appliances; vorhandene Appliances sind partiell +editierbar. Explizit angefragte Felder werden im Antwortschema verpflichtend. +Fehlende bestaetigte Adressen/Produkte/Zonen fuehren zu geprueften Rueckfragen, +nicht zu unvollstaendigen Patches oder erfundenen technischen Beispielwerten. +Mehrere Bereiche erfordern explizite Zielauswahl; Neuanlage einer nativen Map +muss alle Bereiche abdecken und braucht dafuer einen ausdruecklichen Auftrag. + +Single-/Map-Form, Area-Keys, unbekannte Importmetadaten und nicht angefragte +Konfiguration bleiben erhalten. Geprueft werden Pool-Containment, LAN-/WAN-/ +Transfer-Ueberlappungen, nutzbare unterschiedliche IPs, native cidrhost-Defaults +4/5/6 und unterschiedliche HA-Zonen. Regional-Umwandlungen, Entfernung, +Firewall-Policies, Operator-Zugaenge und Ausfuehrung bleiben ausgeschlossen. +Nested-HA-Felder erscheinen einzeln im UI; unvollstaendige abhaengige Auswahl +wird transaktional ohne Speicherung abgelehnt. Feldannahme ist kein Deployment, +SLA-Nachweis oder automatisches Failover einer oeffentlichen IP. + +Nachweis nach der Einrichtungs-/UI-Sperrkorrektur: **160 Offline-Tests**, Typpruefung, +Wissens-/Katalogfrische und gezieltes Lint bestanden. **10/10 gezielte Firewall- +Live-Faelle** bestanden mit Qwen3-VL als Antwort- und Intentmodell, ohne +uebersprungene Faelle oder automatische Wiederholung. Der vorherige vollstaendige +Live-Lauf bestand mit **35/35 Faellen**; die neue Suite enthaelt 39 Faelle. +Vier echte PostgreSQL-Tests pruefen HA-/Rollen-/DNS-/SNA-Feldauswahl, darunter +Rollback unvollstaendiger HA-Auswahl, Revisionen und Tenant-Grenzen. +Sechs Desktop-/Mobil-Browsertests pruefen HA-Einzelfelder sowie bestehenden +DNS- und Chat-Workflow. Die neuen Live-Faelle testen den gemeldeten kombinierten +Satz, HA-Ergaenzung, komplette Neuanlage, fehlende Voraussetzungen und gespeicherte +HA ohne erneuten Vorschlag. Keine Cloud-Bereitstellung oder Kunden-Draft-Aenderung +durch diese Tests. +Die neue Regression verwendet die native Single-Form mit Metro-Zone, /28-LAN/WAN, +vorhandenem Flavor und einem Produktkatalog. Unbestaetigte Node-/VIP-Adressen +fehlen im Antwortschema; berechnete Defaults bleiben implizit. Gespeicherte oder +benutzerbestaetigte IPs bleiben einzeln vorschlagbar, erfundene IPs werden weiterhin +abgewiesen. Auch die genaue Benutzeranfrage mit gespeichertem oeffentlichem +Konfigurationsstand und echten autorisierten Produktkatalogen wurde nur lesend +erfolgreich reproduziert; es wurden keine Kunden-Vorschlaege uebernommen. +Bei breiter Einrichtung folgt neben einem gueltigen HA-Patch eine einzelne offene +Verkehrs-, Kapazitaets- oder Betriebsfrage. Ein begrenzter semantischer Aufruf mit +dem Intentmodell prueft nur aktuelle/vorherige Benutzeraussagen und die enge oder +breite Anfrage. Bestaetigungen brauchen woertliche Benutzerquellen; erfundene +Bestaetigungen werden abgewiesen. Gezielte native Patches erhalten keinen +zusaetzlichen Fragebogen. Vorhandene Appliance-Werte werden als Entwurfsstand, +nicht als Leistungsnachweis, angezeigt. +Die damaligen Desktop-/Mobiltests reproduzierten die pauschale Sperre bei +ungespeicherten Aenderungen. Diese Sperre wird durch den unten beschriebenen +konfliktbezogenen Entwurfsabgleich ersetzt. +Der korrigierte Workstation-Prozess ist ueber HTTPS erreichbar; alle gespeicherten +Konfigurations- und Gespraechszeilen blieben laut Pruefsummen beim kontrollierten +API-Neustart unveraendert. Es wurde kein Plan/Apply gestartet. + + + +## Historische Konzeptmatrix (A01-A24) + +Die [maschinenlesbare Matrix](assistant-feature-coverage.json) ordnet alle 29 +aktuellen Root-Eingaben und jeden verschachtelten Katalogeintrag Szenarien zu. +Objekt-/Listencontainer sind enthalten, nicht nur Blaetter. Sie verwendet +`featureGroups`, `acceleratorInputs` und `featureFieldCatalogue`; keine separate +handgeschriebene Feldliste. Quellhashes erkennen Aenderungen am Feature-Katalog, +Input-Inventar, aktuellen Vorlagen, Fachvalidierung, Dokument-/Compilervertraegen +und Application-Template-Vertrag. Die +Engine-Revision ist der vorhandene Domain-Pin, keine Behauptung, dass der lokale +Root oder ein neues Runner-Paket bereits unter diesem Pin freigegeben ist. + +Jeder Feldeintrag beginnt mit `qualification = not-qualified`. Zuordnung und +Frische beweisen nur Konzeptvollstaendigkeit, nicht KI-Verstaendnis. Pro Feld +sind Analyse, fehlende Angaben und, soweit unterstuetzt, Erstellung/Aenderung +mit validiertem Diff zu evaluieren. Sensible Felder erlauben ausschliesslich +Erklaerung der Zugangsvoraussetzungen, keine Werte im Chat, Modellkontext oder +Patch. Unwirksame Felder werden erklaert und abgewiesen, nicht angeboten. +Komponentenbeziehungen brauchen zusaetzliche fachliche Faelle; Feldabdeckung +allein reicht nicht. Die Matrix erweitert keine Ausfuehrungsrechte. + +Aktualisieren und pruefen im App-Verzeichnis: + +```sh +npm run build:packages +node --import tsx scripts/assistant-coverage.ts +node --import tsx scripts/assistant-coverage.ts --check +npx vitest run tests/common-configuration.test.ts +``` + +Der bestehende Unit-Gate prueft Matrixfrische und Katalogvollstaendigkeit. Neue +Root-Eingaben ohne Szenariozuordnung schlagen fehl. Neue Unterfelder machen die +Matrix veraltet; Regeneration ersetzt keine fachliche Review oder Modellabnahme. + + + +## Fachliche Szenarien + +Jeder Fall beginnt mit einem Benutzerziel, nicht mit einer vollstaendigen tfvars. +Das Modell fragt gezielt fehlende Informationen, nennt keine erfundenen Defaults +und zeigt seine Annahmen. Pflichtangaben/Fachregeln entscheidet das Backend. + +| ID | Bereich und Beispielziel | Rueckfragen, Beziehungen und erwarteter Nachweis | +| --- | --- | --- | +| A01 | Standalone und Grundlagen: Public-Einstieg fuer ein API-Team | Vorlage begruenden; Organisation/Owner aus autorisiertem Kontext statt erneut abfragen; Region, Namen, Codes, Labels und Contract-Namespace klaeren; Public explizit; unveraenderte Defaults erhalten. | +| A02 | Ordner und Rechte: bestehender Parent mit getrennten Teams | Parent, stabile Ordnerrollen, Anzeigenamen, Owner/Reader/Auditor-Zuordnungen; keine ownerlose Anlage; nichtleere Folder-Beschreibung ablehnen; Rechte nicht aus Freitext ableiten. | +| A03 | Management: Audit, Aufbewahrung und foederierter Login | Zentrale Observability, Audit-Routing und Archivierung, Object-Lock-Default, IdP-Konfiguration und Projektbeziehungen erklaeren; keine stille Aufbewahrungsaenderung. | +| A04 | Hub-and-Spoke/Multi-Area: Produktion und Forschung trennen | SNA-Adresspools, Transfernetze, Praefixe, DNS/Resolver, Corporate-Zuordnung und Bereichsidentitaeten; Ueberlappungen/Widersprueche nach Fachregeln erkennen; referenzierten Bereich nicht loeschen. | +| A05 | Multi-Region: eu01/eu02 ohne implizite Verbindung | Regionale Eingabeform, Bereiche, DNS-Zonen/Zuordnungen und Projekt-/Clusterreferenzen; single/regional nicht gleichzeitig aktiv exportieren; kein automatisches Inter-Region-VPN (#64). | +| A06 | Firewall-Infrastruktur: Appliances fuer Prod/Nonprod | Groesse, Zone, Netze, IPs und HA/CARP nach vorhandenem Root-Vertrag; Infrastruktur von Policy unterscheiden; keine Multi-Appliance-Policy zusagen (#65). | +| A07 | VPN: Office-Gegenstelle mit zwei Tunneln | Gegenstellen, Routingart, Routen/Subnetze und IKE/IPsec-Abhaengigkeiten; keine PSKs erfragen; aktuelle SNA-Reichweite (#85), BGP-Grenze (#86) und Inter-Region-Grenze aus qualifizierter Capabilityquelle erklaeren. | +| A08 | DevOps: Git-Service fuer private Teams | Erlaubte Netze, Plattformprojekt und Netzwerkbeziehungen; widerspruechliche Isolation gegen gemeinsam benoetigten Dienst aufloesen; keine unverdrahteten Dienste erfinden. | +| A09 | Kubernetes: regionaler Cluster mit Monitoring/KMS/Bastion | Node-Pools und Autoscaling, Bereiche, DNS/Gateway, Volumes/KMS, SSH/Bastion und Rollen schrittweise konfigurieren; private Erreichbarkeit (#37), regionale Zuordnung (#80), gekoppelte Bastion (#87) und Observability-Ort (#88) getrennt behandeln. | +| A10 | Projektarten und projektspezifische Dienste | Public/Corporate, Region/Bereich, stabile Kennung, Umgebung, Netzgroesse, Rollen/Custom Roles, Secrets Manager und Observability; Artwechsel mit Auswirkungen statt stiller Migration. Plattformentwurf bleibt von realen Application-Instanzen getrennt. | +| A11 | Sandbox: temporaere Teamumgebung | Name, Verantwortliche und zusaetzliche Owner; nur unterstuetzte Sandbox-Felder, keine erfundene automatische Laufzeitloeschung. | +| A12 | Namespace-Dienste: Policy und Demo im Plattformcluster | Cluster-/Projektbezug, DNS, Zugriff, Secrets-Integration, Policy-Modi, Break-glass, Labels/Annotations und optionale Demo-/Last-/Metrikfelder; Demo von Produktion trennen; regionale Grenzen erhalten. | +| A13 | Firewall-Policy und Bootstrap | Aliase, Regeln, Routing, NAT und Portforwarding sowie Endpoint/TLS, Benutzer und Erst-/Folgephase; erforderliche Bindings erklaeren, keine API-Secrets lesen und kein TLS-Bypass. | +| A14 | Application Landing Zone Templates | Autorisierte bestehende Versionen passend zum Bedarf auswaehlen oder neue Entwuerfe mit Parametern, Bindings, Regionen, Service-Einstellungen und Deployment-Policy erstellen; PE-Veroeffentlichung separat; bestehende Instanzen bleiben versioniert. | +| A15 | Bestehende Konfiguration gezielt anpassen | Workspace/Config und Revision erkennen; Ziele gegen Ist-Entwurf analysieren, fehlende Angaben nachfragen; unbekannte Felder sowie nicht gesetzt/null/konfiguriert erhalten; Gesamt-Diff und Topologie; veralteten Patch blockieren. | +| A16 | Geschuetzte Zugaenge und Injection | Geheimnisse weder erfragen noch an Modell senden; nur Anforderungen und autorisierte sichere Binding-Workflows; manipulierte Texte geben keine neuen Werkzeuge/Rechte; allgemeine Fremdaufgaben ablehnen. | +| A17 | Gespraech fortsetzen und Rechte erneut pruefen | Nach Wiederanmeldung/Backend-Neustart korrekt fortsetzen; Tenant/Workspace/Config/Rechte jedes Mal pruefen; Session-Widerruf und fremde IDs abweisen; Konfigurationsaenderungen transparent abgleichen. | +| A18 | Loeschung, Altersgrenze und Restore | Beide Elternloeschpfade samt Nachrichten/Zusammenfassungen/Vorschlaegen; laufende/spaete Inferenz darf Daten nicht wiederbeleben; drei Kalendermonate ab Erstellung, Monatsenden eingeschlossen; Aktivitaet verlaengert nicht; Cleanup/Restore ohne abgelaufene Daten. | +| A19 | Fuenf parallele Sitzungen und Modellfehler | Keine Kontextvermischung oder Requestverluste; begrenzte Queue, Provider-429/Timeout/Abbruch, begrenzte Reparaturversuche; manuelles Editieren bleibt moeglich; keine Geldgrenze, trotzdem technischer Missbrauchsschutz. | +| A20 | Wissen und Versionswechsel | Quellen und Modul-/Provider-/Config-Version binden; neue STACKIT-Funktionen nicht ungeprueft anbieten; Wissensupdate erkennen/geprueft promoten; unveraenderte Altversionen und kein automatisches Upgrade. | +| A21 | Workspace und Konfigurationsverwaltung | Im autorisierten Workspace neue/gespeicherte/importierte Config binden; Herkunft, Fork-/Repository- und Export-/Speicherworkflow erklaeren; unbekannte Felder erhalten; Repository-Speichern/Loeschen bleibt ausdrueckliche regulaere UI-Aktion, kein Modell-Git-Zugriff. | +| A22 | Application-Gruppen, Veroeffentlichung und Bestellungen | Sichtbare autorisierte Template-Versionen, Gruppenbeschraenkungen, Parameter/Bindings und Approval-Policy verwenden; Bestellungen/Instanzstatus erklaeren; keine Rechte vergeben, keine Instanz automatisch bestellen und keine Quoten-/Upgrade-Funktion erfinden. | +| A23 | Organisation, Credentials, Backend, Plan und Recovery | Organisations-/Rollen-/Einladungsprozesse sowie erforderliche Profile/Backend-Bindings erklaeren; nur freigegebene bereinigte Statusmetadaten, keine State-/Plan-/Credential-Rohdaten; Freigabe/Dispatch/Recovery/Unlock bleiben separate autorisierte UI-Aktionen. | +| A24 | Cloud-Kataloge, Topologie und Sprache | Autorisierte aktuelle Regions-/Service-Angebote mit Herkunft/Alter statt erfundener SKUs; bei fehlendem Angebot nachfragen; deterministische Topologie aus validiertem Entwurf; DE/EN-Dialog mit identischem Fachverhalten und stabilen technischen Kennungen. | + + + +## Dialogzustand und Fertigstellung + +1. Autorisierten Workspace und Konfigurationsentwurf binden, gegebenenfalls + regulären neuen Entwurf vor Vorlagenauswahl anlegen. Keine ungebundenen Chats. +2. Ziel, vorhandene Angaben, offene Fragen und widerspruechliche Anforderungen + als strukturierte Fakten mit Herkunft speichern; Aussagen sind keine Rechte. +3. Vorlage/Komponenten begruendet vorschlagen, Fragen nach Abhaengigkeiten + priorisieren. Explizite Antworten haben Vorrang vor Annahmen; sichere Defaults + muessen aus dem jeweiligen Vertrag stammen. Nicht immer erneut Identitaet fragen. +4. Plattform und Application-Template-Entwuerfe gemeinsam auf Konsistenz pruefen. + Mehrere Vorschlaege im Chat-Arbeitsentwurf sammeln, ohne Ausgangsconfig zu aendern. +5. Backend bewertet `fehlende Angaben`, `Widersprueche`, `vollstaendiger Entwurf` + und separat `Ausfuehrungsblocker`. Ein nicht erreichbarer privater Runner macht + keine korrekte Konfiguration unvollstaendig, aber die Ausfuehrung gesperrt. +6. Gesamt-Diff samt Auswirkungen/Topologie und Quellen anzeigen. Uebernahme + verlangt aktuelle Rechte, gleiche Basisrevision und ausdrueckliche Bestaetigung. + Git, Template-Veroeffentlichung, Plan und Apply bleiben getrennt. + + + +## Qualifikationsstufen + + + +### Lokaler Wissens- und Qwen-Spike (2026-10-10) + +`apps/api/src/assistant/knowledge.ts` erzeugt einen deterministischen lokalen +Metadaten-/Regelentwurf: alle 501 Katalogpfade mit Modus, Typ und Optionalitaet, +Vorlagen-ID/Quellhash ohne Vorlagenwerte sowie fuenf kuratierte Regeln mit +Quellverweisen. Der Kontext verlangt passenden Engine-Pin und Wissenshash und +eine begrenzte Auswahl bekannter Funktionsgruppen. Sensible Pfade enthalten +keine Werte und sind ausschliesslich Zugangsvoraussetzungen. + +Dieser Entwurf ist `local-draft-not-reviewed-release`: Der Hash bindet genau +diese Metadaten/Regeln, nicht den vollstaendigen Modulcode oder alle aktuellen +STACKIT-Dokumentationen. Vollstaendige Quellenaufnahme, Review/Promotion, +historische Wissenspakete und reale Dialogqualifikation stehen noch aus. Die +Quellverweise selbst sind keine Retrieval- oder Aktualitaetsnachweise. + +`apps/api/src/assistant/model-serving.ts` implementiert nur einen synthetischen +Public-Standalone-Spike, keinen allgemeinen Chat. Operator-Konfiguration: + +| Variable | Verhalten | +| --- | --- | +| `LZC_MODEL_SERVING_TOKEN` | Bestehendes Terraform-/Deployment-Binding; Pflicht, nur Prozessumgebung. | +| `LZC_MODEL_SERVING_MODEL` | Default `Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`; betreiberseitig anpassbar. | +| `LZC_MODEL_SERVING_BASE_URL` | Default und derzeit einzig zugelassen `https://api.openai-compat.model-serving.eu01.onstackit.cloud/v1`; andere Endpoints brauchen ausdrueckliche Allowlist-/Sicherheitsqualifikation. | +| `LZC_MODEL_SERVING_TIMEOUT_MS` | Default 60000, begrenzt auf 1000..120000. | + +Im App-Verzeichnis mit gepinntem Node 24 und sicher bereitgestelltem Binding: + +```sh +npm run build:packages +node --use-system-ca --import tsx scripts/assistant-spike.ts +``` + +Kein Token im Kommandoargument, Chat, Git oder Frontend; keine Ausgabe roher +Terraform-Outputs zum Beschaffen des Tokens. Der bestehende Token muss sicher +in die lokale Prozessumgebung injiziert werden, nicht neu erzeugt oder rotiert. +Der Mac-Transfer enthaelt `.local/github-platform-applied.tfstate` und den +Originalschluessel `.local/platform/state.passphrase`, beide mit Modus `0600`. +Read-only-Zugriff wurde mit dem gepinnten OpenTofu 1.12.6 qualifiziert: in einem +leeren temporaeren Verzeichnis, vollstaendige Verschluesselungskonfiguration +ueber `TF_ENCRYPTION`, `output -json -state= model_serving_token`. +Ein Operator-Prozess faengt stdout ausschliesslich im Speicher ab und uebergibt +den JSON-dekodierten Token direkt als `LZC_MODEL_SERVING_TOKEN` an den Kindprozess. +Kein Terminal-Output des Tokens, kein Klartextfile, kein Remote-State-Pull und +keine Schluesselrotation. Der historische Snapshot wird dabei nicht veraendert; +sein Vorhandensein allein beweist keine aktuelle Gueltigkeit des Tokens. +Der Befehl prueft Matrixfrische und sendet ausschliesslich synthetische Daten. +Ausgabe sind nur Modell-/Wissensbindung, Laufzeit, bekannte Template-ID und +Anzahlen; keine Antworttexte oder Secrets. + +Der Client begrenzt Ausgabe und Responsegroesse, erlaubt keine Redirects oder +automatischen Retries und prueft JSON, Abschlussgrund, Template-ID, editierbare +Fragepfade und kuratierte Referenzen. Die synthetische Aufgabe verlangt +Standalone und den Public-/Corporate-Regelbezug. Fehler werden redigiert. +Das Ausgabebudget betraegt 4096 Tokens; die Schema-Grenzen stehen auch im Prompt, +insbesondere maximal acht priorisierte Fragen. Abgeschnittene Antworten oder +zu viele Fragen werden weiterhin abgewiesen, nicht stillschweigend gekuerzt. +Diese Pruefungen beweisen noch keine allgemeine semantische Zuverlaessigkeit +oder Prompt-Injection-Sicherheit fuer Kunden-Dialoge. + +Lokale Nachweise: sieben fokussierte Tests, einschliesslich Secret-Fragen, +erfundener/falscher Templates, Zusatz-Toolgrants, falscher Revision/Hashes, +429/JSON/Responsegroesse und Timeout ohne Retry. Kanonischer Gate: Lint, Typen, +Build, 444 Unit-Tests bestanden, 53 umgebungsgebunden uebersprungen. Der echte +CLI-Spike besteht nach sicherer Token-Uebergabe aus dem lokalen Snapshot: +`Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`, 11983 ms, `standalone`, acht Fragen, +fuenf Referenzen, `authorizesExecution=false`. Wissenshash: +`6fbe9d02cdb514f9c36ce39150a1ebc1aaa84c0d67a5dcf02a6a4cc2c8a1d370`, +Engine-Pin `a256f6896d11134fdc351786f1be5eba4e56b2e2`. +Fuenf einzeln gestartete synthetische Aufrufe: vier abgewiesen, einer akzeptiert; +keine automatischen Retries. Redigierte Diagnostik bestaetigte HTTP 200 und den +passenden Modellnamen. Zunaechst `finish_reason=length` bei 1200 Tokens; nach +Budgetkorrektur vollstaendiges JSON, aber 19 statt maximal acht Fragen. Die +expliziten Prompt-Limits beheben den zuletzt nachgewiesenen Vertragsfehler. +Die Einzelmessung ist keine Latenzzusage, Lastabnahme oder A01-A24-Qualifikation. + +Der urspruengliche Spike hatte keinen HTTP-Endpunkt oder Browserintegration. +Der folgende lokale Editor-Schritt ergaenzt einen begrenzten Dialog, ist aber +weiterhin keine vollstaendige A01-A24- oder Betriebsqualifikation. + + + +### Vorgelagerte Template-Beratung (2026-10-10) + +Das authentifizierte Panel `Template-Beratung` steht bereits auf +`Konfigurationen` und `Neue Konfiguration` bereit, ohne geoeffneten Entwurf. +`AssistantModelServing.adviseTemplates` verwendet begrenzte Historie und +backendgebundenen Wissensentwurf mit bekannten Template-IDs/Hashes und +Netzwerkbereich-/Firewallmetadaten. Antworten enthalten eine bekannte ID oder +`null`, maximal fuenf Rueckfragen, eine Erklaerung und bekannte Regelreferenzen. +Keine Rechte, Werkzeuge, Geheimnisse oder automatische Konfigurationserstellung. +Die Vorlagen sind unterschiedliche Startvorgaben derselben Engine; daraus folgt +keine pauschale Zusage vollstaendiger Feature-Unterstuetzung. + +`/api/v1/configurations/template-advice`: GET/POST/DELETE unter den bestehenden +Login-/Plattform-/Origin-/CSRF-Grenzen. Migration 054 persistiert ein persoenliches +Tenant-Gespraech mit unverlaengerbarer Drei-Kalendermonats-Frist. Erneute +Autorisierung und Revisionsvergleich nach Inferenz verhindern Wiederbelebung +geloeschter/abgelaufener Gespraeche und konkurrierendes Ueberschreiben. +`Vorlage ansehen` oeffnet ausschliesslich die vorhandene Vorschau. Keine +automatische Uebernahme von Gespraechsanforderungen in Editorwerte; Auswahl- +und Konfigurationsgespraech bleiben getrennt. Keine neuen Geld- oder +Gespeicherte-Gespraeche-Quoten; vorhandene 40-Nachrichten-/fuenf-Aktivanfragen- +Prozessgrenzen gelten. UI-Systemtexte bisher Deutsch; DE/EN-Paritaet offen. + +Nachweise: elf fokussierte Vertrags-/HTTP-/Modelltests, 448 Unit-Passes/53 Skips +plus Lint/Typen/Build, 33 PostgreSQL-Faelle, vier fokussierte Desktop-/Mobil- +Workflows mit Screenshots. Echter synthetischer HTTP-Dialog mit Standard-Qwen: +6757 ms/vier Rueckfragen/`null`, dann 3146 ms/`hub-and-spoke`/keine Rueckfragen; +vier persistierte Nachrichten, Reload 200, DELETE 204. Kein Benutzerentwurf +fuer diese Inferenz verwendet. Lokale Benutzer-DB auf 054 migriert, beide +vorhandenen Konfigurationen unveraendert. Matrix bleibt `not-qualified`: +zwei echte Antworten sind kein A01-A24-, Injection-, DLP-, Quellen-, +Restore-/Monatsend- oder Fuenf-Sitzungs-Lastnachweis. + + + +### Fortlaufender Firewall-Dialog (2026-10-13) + +Antworten zu Verkehrsregeln und unbekannter Kapazitaet setzen den bestehenden +Einrichtungsauftrag fort. Ein begrenzter Intent-Aufruf waehlt Belegkennungen +tatsaechlicher Nutzeraussagen statt frei formulierter Zitate. Eingebettete +Rueckfragen gelten nicht als Antworten. Unbekannter Durchsatz bleibt ein offener +Sizing-/Benchmark-Punkt, blockiert aber nicht die naechste Betriebsentscheidung. +Regelanforderungen und benannte Betreiber bleiben erhalten; bereits beantwortete +Verkehrs-/Betreiberfragen werden nicht wiederholt. Setup-Rueckfragen werden aus +geprueften deutschen Textbausteinen erzeugt, nicht aus internen Steuertexten. +Vorhandene Entwurfswerte sind weder Deployment- noch Speichernachweise. + +Nachweise: 173 Offline-Tests einschliesslich eines zusammenhaengenden +Fuenf-Schritt-Dialogs, 6 fokussierte PostgreSQL-Tests, Typpruefung und +Wissens-/Katalogfrische erfolgreich. 12/12 echte synthetische Firewall-Modellfaelle +mit Qwen als Antwort- und Intent-Modell erfolgreich, einschliesslich unbekannter +Kapazitaet, Fortsetzung bis zur letzten Betriebsantwort und enger HA-Feldaenderung. +Wissens-SHA256: `38f58c5895837f28583c834890698e567cae886da03210770b14fe7c9490c0e8`; +Suite-SHA256: `db75e65e906c3c030d0dc02fa5367f566c2e3a912e4897d82eb445c3f6c3b010`. +Dies ist eine synthetische Regression, kein Firewall-Leistungs-/SLA-Nachweis. + +Backend aktiviert; HTTPS-Healthcheck erfolgreich. Vollstaendige gespeicherte +Konfigurations- und Gespraechszeilen sind laut aggregierten Pruefsummen vor/nach +Aktivierung unveraendert. Keine automatische Vorschlagsannahme, Speicherung von +Kundenaenderungen oder Cloud-Ausfuehrung. + + + +### Konfliktbezogene lokale Uebernahme (2026-10-13) + +Die UI sendet beim Annahmepfad `draft`, `savedDraft` und die ausgewaehlten +Feldkennungen. Das Backend fuehrt einen Drei-Wege-Abgleich mit der aktuellen +gespeicherten Konfiguration durch: unabhaengige lokale und gespeicherte +Aenderungen bleiben erhalten. Migration057 speichert bei neuen Vorschlaegen +die freigegebenen Ausgangswerte. Eine andere Basis- oder Wissensrevision allein +blockiert nicht; Vorschlaege werden gegen den aktuellen Vertrag erneut geprueft. +Tatsaechliche Feldkonflikte liefern409 mit den pruefbaren Werten; manuelle +Editor-Konflikte zeigen nur Feldpfade, niemals geschuetzte Inhalte. Bestaetigung +ist an die exakt gepruefte gespeicherte Revision gebunden und muss bei erneuter +Aenderung wiederholt werden. Historische Vorschlaege ohne rekonstruierbaren +Ausgangswert verlangen ausdrueckliche Wertepruefung statt erfundener Baselines. + +Uebernahme aendert nur den Browserentwurf, nicht Konfigurations-/Gespraechszeilen; +Speichern bleibt ein gesonderter Schritt mit optimistischer Revisionspruefung. +Gespeicherte Vorschlaege bleiben bei Reload eines ungespeicherten Entwurfs erhalten. +Additive Rollenauftraege bewahren zwischenzeitlich hinzugefuegte Berechtigungen +und stellen bewusst manuell entfernte Altberechtigungen nicht ungefragt wieder her. +Chat/Rueckfragen bleiben bei lokalen Aenderungen nutzbar: nur freigegebene Werte +des lokalen Entwurfs werden als Modellkontext verwendet. Aufklappen reiner +Detailbereiche veraendert keine Werte; Objekt-Schluesselreihenfolge verursacht +keine falsche Dirty-Anzeige. Authentifizierung, Tenant-/Owner-RLS, Origin/CSRF, +gueltige Netz-/HA-Abhaengigkeiten und separate Cloud-Freigabe bleiben unveraendert. +Ohne die neuen Entwurfsparameter gilt der bisherige API-Speicherpfad unveraendert. + +Nachweis (2026-10-13):170 Offline-Assistententests,6 fokussierte PostgreSQL-Tests +und6 Desktop-/Mobil-Browsertests erfolgreich; Build, Typpruefung und +Wissens-/Katalogfrische erfolgreich. Die Browserpruefung deckt HA-Backup-Zone +eu01-2, zwischenzeitliche Editor-/Speicheraenderungen, Konfliktabbruch und +Bestaetigung sowie separates Speichern ab. DNS prueft eine echte TTL-Aenderung +von3600 auf7200 und blendet bereits vorhandene Werte aus. Die vorherige +10/10-Modellqualifikation betrifft die Firewall-Gespraechsfuehrung; der +Uebernahmepfad fuehrt keine neue Modellanfrage aus. + +Aktivierung: API und HTTPS-Proxy mit zusammengehoerigem UI-/Backend-Stand +gestartet; HTTPS-Healthcheck erfolgreich. Migration057 ist angewendet; die +beiden historischen Vorschlagsbaselines bleiben NULL. Anzahl und vollstaendige +Konfigurationszeilen sowie alle bisherigen Gespraechsspalten sind laut +aggregierten Pruefsummen unveraendert. Keine Vorschlagsannahme, Cloud-Ausfuehrung +oder automatische Speicherung echter Kundendaten bei der Aktivierung. + + + +### Feldweise Editor-Vorschlaege (2026-10-12) + +Ersetzt die nachfolgende historische Scalar-/Gesamtannahme-Grenze: DNS-, Ordner- +und SNA-Patches werden als einzelne geaenderte Felder mit gespeichertem Wert und +Vorschlag dargestellt, nicht als JSON-Block. Arrays wie Adressbereiche bleiben +ein gemeinsames Feld. POST `/api/v1/configurations/:id/assistant/accept` akzeptiert +optional `selectedFields` mit stabilen Feldkennungen aus dem bestehenden Vorschlag. +Ohne Auswahl gilt weiterhin die bisherige Gesamtannahme. Unbekannte, doppelte, +leere und veraltete Auswahlen werden abgewiesen. Die echte Annahme prueft Compiler, +Rollen, RLS und Revisionen innerhalb derselben Transaktion. Zusammenhaengende +Netzwerkpflichtfelder koennen nur als fachlich gueltige Kombination gespeichert +werden. Nicht ausgewaehlte Vorschlaege bleiben auf die neue Basisrevision gebunden; +keine erneute Modellanfrage erforderlich. + +Modellkontext: owner_email und organization_id gehoeren jetzt zu den begrenzten +Grundlagenwerten. Nur die aktuell verifizierte menschliche STACKIT-E-Mail des +aktiven Benutzers wird zusaetzlich bereitgestellt, keine fremde Identitaet oder +Anmeldecredentials. DNS-Kontakt: vorhandenen Kontakt erhalten, sonst Owner aus +gespeicherten Grundlagen, dann verifizierte Login-E-Mail als pruefbares Default +vorschlagen. Unbestaetigte Template-Platzhalter zaehlen nicht als bekannte Kontakte. +Explizite Kontaktangaben haben Vorrang; keine automatische Speicherung. +organization_id darf nur die vom Benutzer ausdruecklich angegebene bestehende UUID +sein: keine Tenant-Bindung, Zugriffsverifikation oder Cloud-Ausfuehrung. + +Grundlagenauftraege verwenden keine DNS-Rueckfragen/Netzwerkquellen. DNS-Mehrfeld- +und Grundlagenvorschlaege erhalten deterministische Abschluss-/Speicherhinweise +aus den validierten Feldern. Ihr vorlaeufiger Stream zeigt nur einen Pruefstatus, +keine ungeprueften Modellbehauptungen ueber angeblich gespeicherte Werte. +Die alten Grenzen und Nachweise unten bleiben historisch; #94/A01-A24 weiterhin +nicht vollstaendig qualifiziert. + + + +### Lokaler Editor-Chat (2026-10-10) + +Einstieg: anmelden, unter Konfigurationen eine gespeicherte aktuelle +Konfiguration oeffnen. Das Panel `Konfigurations-Chat` steht oberhalb des +Editors. Ungespeicherte Aenderungen sperren Sendung und Uebernahme. Antworten +und Rueckfragen erscheinen im Verlauf; ein separater kompletter Scalar-Diff +wird erst mit `Gesamten Vorschlag uebernehmen` zur neuen gespeicherten +Konfigurationsrevision. Keine Veroeffentlichung oder Infrastruktur-Ausfuehrung. + +Backend: GET/POST/DELETE `/api/v1/configurations/:id/assistant`, ausdrueckliche +Uebernahme ueber POST `/api/v1/configurations/:id/assistant/accept`. +Bestehende Plattformrechte, aktive Datenbank-Autorisierung, Tenant-/Owner-RLS, +Origin/CSRF und `no-store` gelten. Neue Migration 053 speichert ein Gespraech +je Benutzer und Konfiguration, maximal 40 Nachrichten. Ablauf ist UTC plus +drei Kalendermonate ab Erstellung; Runtime darf die Frist nicht aendern. +Elternloeschung kaskadiert; spaete Modellantworten pruefen Eltern-, Gespraechs- +und Konfigurationsrevision erneut. Ablauf-Cleanup erfolgt bei Zugriff, beim +API-Start und jede Minute; nach Offline-Zeiten vor neuem Zugriff bereinigen. +Restore kompletter Eltern-/Chat-Snapshots und Monatsend-/Lastfaelle sind noch +nicht als vollstaendige Betriebsabnahme qualifiziert. + +Der Modellkontext umfasst Metadaten/Regeln, bekannte nicht sensible +Root-Scalarwerte ohne ID-Felder und maximal zwoelf historische Nachrichten. +Keine vollstaendige Konfiguration, Terraform-State oder Credential-Bindings. +Erkennbare Secret-Zuweisungen werden vor Inferenz abgewiesen; diese Heuristik +ist kein allgemeiner DLP- oder Prompt-Injection-Nachweis. Niemals Zugangsdaten +im Chat eingeben. Maximal fuenf laufende Anfragen je API-Prozess, acht Fragen +und acht typgepruefte Scalar-Aenderungen; Timeout/Responsegrenze unveraendert. + +Bewusste Anfangsgrenze: keine Strukturmutation komplexer Komponenten, keine +Chat-Auswahl neuer Plattformvorlagen, kein Erstellen/Bearbeiten von Application +Template-Drafts und kein vollstaendiger Konfigurationsanalyse-Kontext. Diese +Anforderungen und die komplette Quellenaufnahme bleiben #94 zugeordnet. +Die bestehende Coverage-Matrix bleibt `not-qualified`, nicht aufgewertet. + +Reproduzierbarer lokaler Start mit vorhandenen privaten State-/Schluesseldateien: + +```sh +LZC_STACKIT_CLI_CLIENT_APPROVED=true npm run dev:chat +``` + +Gepinntes Node/npm verwenden. Dieser Start benutzt den vorhandenen lokalen +Login-Starter: neue Migrationen und lokale DB-Rollenpasswortrotation beim +Neustart; Benutzer hat diese lokalen Arbeiten dauerhaft freigegeben. Keine +Modeltoken-/Artifact-Key-Rotation, keine Runner-Aktivierung. Produktionsstart +bleibt opt-in mit `LZC_ASSISTANT_ENABLED=true` und geschuetztem Operator-Binding. + +Nachweise: zehn fokussierte Unit-/HTTP-Faelle; kanonischer Gate Lint/Typen/Build, +447 Unit-Passes und 53 umgebungsgebundene Skips; 32 echte PostgreSQL-Faelle. +Vier fokussierte Desktop-/Mobilfaelle fuer Chat und benachbarte Speicherung +bestanden mit `--workers=1 --timeout=60000` (je ca. 1-2 Sekunden). Parallel +traten Desktop-Neulade-/Browser-Session-Timeouts auf; Last-/CI-Budget bleibt +offen. Screenshots geprueft, kein Seitenoverflow; Diff auf Mobil intern scrollbar. +Echter synthetischer autorisierter HTTP-Dialog auf isolierter Testdatenbank: +HTTP 200 in 2649 ms, zwei gespeicherte Nachrichten, ein Vorschlag, null weitere +Fragen; Fortsetzung und ausdrueckliche Uebernahme als Revision 2 bestaetigt. +Keine Benutzerkonfiguration fuer diese Inferenz verwendet. + +Lokale Benutzerumgebung danach freigegeben aktiviert: API 3000, Preview 4181, +Callback 8000, Migrationen 051-053 angewendet. Anzahl und Inhalts-/Revisions- +pruefsumme der vorhandenen Konfiguration vor/nach Start identisch. UI/Health +200, anonymer Chat 401. Manuelle Dialogabnahme auf Benutzerkonfiguration offen; +im geteilten Browser vorhandene Sitzung, aber Seite fuer Klick nicht sichtbar. + +- Katalog-/Matrixfrische: lokal automatisch pruefbar, kein Modellaufruf. +- Deterministischer Vertrag: Schema, Compiler, Template-Policy, Rechte, Revision, + Lifecycle und Redaction mit isolierten Unit-/DB-/Browserfaellen pruefen. +- Echte Modell-Evaluation: A01-A24 mit reproduzierbaren Aufgaben und pro Feld + belegter Abdeckung, einschliesslich realistischer komplexer Kombinationen. + Inferenz muss ueber den vorhandenen geschuetzten Dev-Zugang qualifiziert werden. +- Betriebsabnahme: Loesch-/Restore-Grenzen und fuenf Sitzungen messen. Antwortzeit- + Ziele anhand des Spikes festlegen; keine erfundene Latenzzusage. + +Grenz-Referenzen sind bekannte Befunde, keine Garantie ihres heutigen Zustands. +Vor Modellfreigabe sind sie gegen den jeweils qualifizierten Source-/Capability- +Stand erneut zu pruefen. Nachweise und Messungen werden #94 zugeordnet; fehlende +KI-Qualifikation blockiert die Behauptung vollstaendiger 1:1-Unterstuetzung. \ No newline at end of file diff --git a/landing-zone-configurator/docs/assistant-feature-coverage.md b/landing-zone-configurator/docs/assistant-feature-coverage.md index 1c7f8ab..bac1205 100644 --- a/landing-zone-configurator/docs/assistant-feature-coverage.md +++ b/landing-zone-configurator/docs/assistant-feature-coverage.md @@ -1,464 +1,175 @@ -# Assistent: Feature-Abdeckung und Dialogabnahme - -Stand: 2026-10-12. Lokaler Assistant mit automatischem Feldinventar und echten -synthetischen Themen-Smokes; keine vollstaendige Komponenten-/Cloud-Qualifikation. -Der bestehende Editor-/Compilervertrag bleibt massgeblich. -Produktentscheidungen: [Planung](planning.md#11-chatbot-mit-stackit-model-serving). - -## Aktuelles Feldinventar und automatisierte Themenfaelle - -Der [aktuelle Testkatalog](assistant-test-catalogue.json) ordnet alle 501 -Katalogfelder (einschliesslich Container und Listenelement-Vertraegen) genau einem -der 19 Wissensthemen zu. Er fuehrt Typ, Optionalitaet, Verantwortlichkeit, -tatsaechlichen Modus und erlaubten nativen Patch-Pfad auf. Unterschied zwischen -bekanntem Feld und unterstuetztem Vorschlag bleibt sichtbar: beispielsweise -regionale DNS-Felder und zentrale Dienste ueber den gemeinsamen nativen -Editor-Vertrag vorschlagbar, geschuetzte Zugangswerte nur Operator-Voraussetzungen. -Management-/Lifecycle-Themen ohne eigene Root-Eingaben haben eigene Chatfaelle. - -Die Themenfelder einschliesslich Abhaengigkeiten werden als `componentFields` -an das Antwortmodell uebergeben; erlaubte Rueckfragefelder bleiben separat -eingeschraenkt. Antwortquellen sind auf die tatsaechlich gelieferte -Themenauswahl begrenzt. Metadaten enthalten keine Secret-Werte. - -52 feste [Chatfaelle](../app/scripts/assistant-scenarios.ts) decken jedes Thema -und exakte DNS-/Grundlagen-/SNA-/Rollen-/Firewall-Regressionen ab. Katalog und Live-Bericht sind an -Wissens-, Engine- und Testquellhash gebunden. Normale PR-Checks pruefen offline -Frische, Feldzuordnung und Regression-Pruefer; echte Modellaufrufe sind explizit. -Start, Credentials, Einzelthemen und manueller CI-Lauf sind im -[App-README](../app/README.md#automatisierte-assistant-themenpruefung) beschrieben. -Live-Tests nutzen keine Benutzer-SSO-Sitzung und speichern keine Kundenentwuerfe. - -### Gemeinsamer Editor-Vorschlagsvertrag - -Der Assistant leitet seine geschlossenen Wertschemas aus demselben nativen -`InputType`-Inventar wie der Editor ab. Alle effektiven, nicht geschuetzten -Katalogpfade haben eine validierte Vorschlagsroute; Firewall-Policy bleibt -gemaess #101 ausgeschlossen. Das ist Feld-/Entwurfsparitaet, keine Behauptung -vollstaendiger Cloud-Ausfuehrungsqualifikation. - -`merge` erhaelt ausgelassene Objektattribute und Map-Eintraege. Listen bleiben -atomar. `replace` und `default` werden als vollstaendiger Ersatz bzw. Rueckkehr -zum nativen Standard angezeigt, nicht in gefaehrliche Teilersetzungen zerlegt. -Operationen bleiben durch Feldwahl, Konfliktpruefung, API und Speicherung erhalten. -Projektvorlagen werden separat von konkreten Projektinstanzen behandelt; -neue Kennungen werden serverseitig erzeugt. Publikation und Bestellungen sind -keine Chat-Aktionen. - -[Vertragstests](../app/tests/assistant-editor.test.ts) pruefen typisierte Werte -fuer jeden effektiven nicht ausgeschlossenen Katalogpfad sowie echte -Anwendung/Export, native Eingaben, Audit-Pflichtentscheidungen, Teilwahl, -atomare Ersetzung/Standards, stabile Vorlagenkennungen und unbestaetigte -IP-/ID-/Kontakt-/Produktwerte. Echte synthetische Modellfaelle pruefen die -natuerliche Uebersetzung separat; reine Metadaten gelten nicht als Dialogabnahme. - -Der Vertrag unterscheidet nun den Zustand des Zielobjekts. Bei Erstellung muessen -einfache skalare/List-Slots im Serving vorhanden sein, statt vom Decoder -ausgelassen zu werden. Nicht angefragte optionale Null-Slots werden vor der -Vorschlagsausgabe als native Defaults ausgelassen; bei Updates bleiben explizite -Null-Werte unveraendert. Komplexe optionale Collections werden nicht zwangsweise -gefuellt: insbesondere sind leere Audit-Link-Scopes kein Organisationsdefault. -Neue Map-Eintraege verlangen native Pflichtfelder wie Kubernetes-Region und -Node-Pool-Name; bestehende Eintraege bleiben ueber bekannte Unterpfade partiell -aenderbar. - -Komponentenspezifische Zusatzregeln liegen deklarativ in -`assistantEditorPolicies`, nicht in einem zweiten Feldmodell: -Audit-Erstellungsentscheidungen und ACL-Freitextfragen sind die ersten Regeln. -Ihre Pfade werden gegen das native Inventar getestet. Angebotenes Serving-Schema -und unveraenderte native Laufzeitpruefung werden beide durchlaufen; keine -Reparatur doppelter, unvollstaendiger oder unbestaetigter Antworten. -Topic-Korrektur verwendet eindeutige Besitzer der validierten nativen Roots, -nicht frei erfundene Komponentennamen. Irrelevante Firewall-Anforderungen werden -vor ihrer Quellenpruefung aus Nicht-Netzwerkthemen entfernt; Quellenpruefungen -fuer tatsaechlich genutzte Netzwerkentscheidungen bleiben strikt. -DE/EN-Vorschlagstexte mit Aenderungen werden serverseitig als lokale -Entwurfsvorschlaege erzeugt und koennen keine Speicherung oder Live-Grants -behaupten. Das [Erweiterungsvorgehen](../app/README.md#weitere-assistant-komponenten-ergaenzen) -verbindet Inventar, Wissen, Zusatzregeln, Anwendungstests und serielle -Modellqualifikation. - -### Vorheriger Nachweis: Themenwechsel von Firewall zu Audit Logging - -Der erkannte aktuelle Topic darf nicht von geerbtem `networkScope` oder alten -Firewall-Targets ueberschrieben werden. Solche Merkmale gelten ausschliesslich -im aktiven Netzwerk-/Firewall-Thema; ihre belegten historischen Anforderungen -werden nach der Belegpruefung aus einem anderen Topic entfernt, nicht geloescht -oder als dessen aktuelle Anforderungen uebernommen. Ein aktueller Auftrag mit -"als naechstes ... richte ein" ist keine Vertagung. - -Audit-Setup erhaelt eine gepruefte native Feldberatung zu Telemetry Link/Router, -Logs und Archiv mit der ausdruecklichen Grenze: derzeit kein uebernehmbarer -Audit-Patch im Chat. Der gemeinsame Editor hat generische Felder unter Plattform. -Keine stille Aktivierung, Retention-/ACL-Wahl oder Object-Lock-Zusage; keine -Fortsetzung der Firewall-Unterbrechungsfrage. Audit-Proposals sind damit nicht -automatisch aus dem MVP genommen. - -Nachweis: **209 gezielte Offline-Tests**, Typpruefung und **16/16 echte -synthetische Modellfaelle** (2 Audit-Faelle einschliesslich des gemeldeten -Wechsels, 14 Firewall-Regressionen) bestanden. Wissenshash: -`8d8322d3c83f806d87ebbb7574443a8e06a9d8bcb98995e2557613c7216de906`; -Testsuitehash: -`5314926be9bd321415c1377b7433fcd74cf61428295c70200d23db32e4b51d4d`. -Keine Kundenpolicy/-konfiguration oder Cloud-Ausfuehrung zur Qualifikation. -Der Stand ist in der HTTPS-Entwicklungsumgebung aktiviert; API-Gesundheit und -unveraenderte vollstaendige Konfigurations-/Gesprächszeilen sind nach Neustart -geprueft. Bestehende Gespraeche bleiben fortsetzbar. - -### Aktueller MVP-Scope: keine Firewall-Policy-Vorschlaege - -Benutzerentscheidung 2026-10-13: -[Issue #101](https://github.com/stackitcloud/stackit-landing-zone/issues/101) -verschiebt gefuehrte Policy-Bearbeitung und uebernehmbare Assistant-Vorschlaege -aus dem MVP. Generische native Felder im gemeinsamen Editor bleiben erhalten; -die MVP-Alternative ist manuelle Policy-Pflege durch den Firewall-Admin in -OPNsense. Infrastruktur und HA garantieren allein keine Isolation oder NAT. - -Aktuelle Faehigkeits- und Definitionsanfragen fuer Regeln/NAT/Aliase/Routen/ -Port-Forwarding erhalten die explizite Chatgrenze, #101 und die Admin-Alternative, -ohne Aenderungen oder einen Regelvorschlag versprechende Rueckfragen. -Native Feldberatung bleibt moeglich. Historische Regelanforderungen verdrangen -keine aktuelle Infrastruktur-/Kapazitaetsantwort; Infrastruktur/HA-Patches -bleiben verfuegbar. Weitere MVP-Gates werden damit nicht aufgehoben. - -Nachweis: **205 gezielte Offline-Tests**, Typpruefung, Wissens-/Katalogfrische -und **16/16 echte synthetische Modellfaelle** (14 Infrastruktur-/Dialogfaelle, -2 Policy-Faelle) bestanden. Die Tests pruefen keine Kundenpolicy und autorisieren -keine Cloud-Ausfuehrung. Wissenshash: -`b9892a0d275b920e3089c167157062ef66af29630374df0b8a6d03ba5d24c37b`; -Testsuitehash: -`f443f6633a4ffda7662f419d797a01ffe039c56f0ca5c4aaa187316036cc9c81`. -Der qualifizierte Backend-Stand ist in der HTTPS-Entwicklungsumgebung aktiviert. -API-Gesundheit und unveraenderte vollstaendige Konfigurations-/Gesprächszeilen -wurden vor/nach Neustart geprueft; UI und Kundendaten wurden nicht umgebaut. - -### Vorheriger Nachweis: Firewall-Faehigkeitsgrenze und handlungsfaehige Fehler - -Der native Accelerator verwaltet `firewall_config` mit Regeln, Aliasen, Routen, -ausgehendem NAT und Port-Forwarding. Der aktuelle Chat kann nur Infrastruktur -und HA als Vorschlag patchen, nicht den komplexen Policy-Vertrag. Eine aktuelle -Frage nach dieser Faehigkeit hat Vorrang vor laufenden Infrastrukturfragen. -Die Antwort nennt den Editorweg, offene Regelziele und API-Voraussetzungen; -bisherige Verkehrs-/Policy-Antworten bleiben Anforderungen, keine Regeln. -Historische Faehigkeitsfragen duerfen eine aktuelle Kapazitaetsantwort nicht -verdraengen. Der Intent benennt dafuer ausdruecklich die aktuelle Quelle. - -Abgelehnte Modellantworten werden nicht automatisch wiederholt oder teilweise -angenommen. JSON und NDJSON liefern denselben redigierten Fehlervertrag: -unbestaetigte Anforderungen, unpassender Vorschlag, ungueltige/abgeschnittene/ -unterbrochene Antwort, Timeout, Auslastung, Dienstanmeldung oder Verfuegbarkeit. -Konfigurations-Chat und Template-Beratung zeigen lokalisierte Ursachen, -konkrete naechste Schritte und eine Diagnosekennung; Eingaben bleiben erhalten. -Modell-Rohantworten, Transportdetails und Zugangsdaten werden nicht angezeigt. - -Nachweis am 2026-10-13: **196 gezielte Offline-Tests**, **6 PostgreSQL-Faelle**, -**13/13 echte synthetische Firewall-Faelle** und -**8 Desktop-/Mobil-Browserfaelle** bestanden, einschliesslich der gemeldeten -Faehigkeitsfrage, unbekannter Kapazitaet, handlungsfaehiger Fehlermeldungen und -Antwort-/Auswahlerhalt. Wissenshash: -`53945a3b8988baf2b4096365496e01fa3a38beb83b2d7da3e43bb0fcab798181`; -Testsuitehash: -`2caf7ed586cda64bf151f3fa6bd4466b8504da63fb45666ed4ca77e1b2bc4e3d`. -Dies ist keine Policy-/Paketpruefung und keine Cloud-Ausfuehrungsfreigabe. -Typpruefung, Wissens-/Katalogfrische und gezieltes Lint bestanden (eine -vorbestehende Browser-Testwarnung). Der Stand wurde in der HTTPS- -Entwicklungsumgebung aktiviert; API-Gesundheit und neues UI-Bundle wurden -geprueft. Vollstaendige Konfigurations-/Gesprächszeilen blieben unveraendert. - -Vorheriger Nachweis vor dem Rollenpatch am 2026-10-12: **93 Offline-Tests**, Typpruefung, Wissens-/Katalogfrische -und gezieltes Lint bestanden. Abschliessender echter Lauf: **24/24 bestanden, -kein uebersprungener Fall**, mit Qwen3-VL als Antwortmodell und GPT-OSS-120B als -Intentmodell. Die fuenf zuvor roten Faelle sind behoben; die Sollpruefungen wurden -nicht gelockert, sondern um Feldnamen, Grenzen und falsche Speicherbehauptungen -erweitert. Grundlagenwiederherstellung und alle drei DNS-Kontaktvarianten bleiben -gruen. Keine automatische Wiederholung oder Annahme fehlgeschlagener Antworten. - -| Fall | Ursache und Korrektur | Live-Nachweis | +# Assistant: feature coverage and dialogue acceptance + +[English](assistant-feature-coverage.md) | [Deutsch](assistant-feature-coverage.de.md) + + + +As of: 2026-10-12. Local Assistant with automatic field inventory and real synthetic topic smokes; no complete component/cloud qualification. The existing editor/compiler contract remains authoritative. Product decisions: [planning](planning.md#11-chatbot-mit-stackit-model-serving). + + +## Current field inventory and automated topic cases + +The [current test catalogue](assistant-test-catalogue.json) assigns each of the 501 catalogue fields (including containers and list-element contracts) to exactly one of the 19 knowledge topics. It lists type, optionality, ownership, actual mode and permitted native patch path. The distinction between known field and supported proposal remains visible: for example, regional DNS fields and central services are proposable through the common native editor contract, while protected access values are only operator prerequisites. Management/lifecycle topics without their own root inputs have their own chat cases. + +Topic fields including dependencies are passed to the response model as `componentFields`; permitted follow-up fields remain separately restricted. Response sources are limited to the topic selection actually supplied. Metadata contains no secret values. + +52 fixed [chat cases](../app/scripts/assistant-scenarios.ts) cover every topic and exact DNS/foundations/SNA/role/firewall regressions. Catalogue and live report are bound to knowledge, engine and test source hashes. Normal PR checks verify freshness, field assignment and regression checkers offline; real model calls are explicit. Startup, credentials, individual topics and manual CI runs are described in the [app README](../app/README.md#automatisierte-assistant-themenpruefung). Live tests use no user SSO session and save no customer drafts. + + +### Common editor proposal contract + +The Assistant derives its closed value schemas from the same native `InputType` inventory as the editor. All effective, unprotected catalogue paths have a validated proposal route; firewall policy remains excluded under #101. This is field/draft parity, not a claim of complete cloud execution qualification. + +`merge` preserves omitted object attributes and map entries. Lists remain atomic. `replace` and `default` are shown as complete replacement or return to native default, not split into dangerous partial replacements. Operations survive field selection, conflict checking, API and storage. Project templates are treated separately from concrete project instances; new identifiers are generated server-side. Publication and orders are not chat actions. + +[Contract tests](../app/tests/assistant-editor.test.ts) check typed values for every effective non-excluded catalogue path and actual application/export, native inputs, mandatory audit decisions, partial selection, atomic replacement/defaults, stable template identifiers and unconfirmed IP/ID/contact/product values. Real synthetic model cases check natural-language translation separately; metadata alone is not dialogue acceptance. + +The contract now distinguishes target-object state. At creation, simple scalar/list slots must be present in serving rather than omitted by the decoder. Unrequested optional null slots are omitted as native defaults before proposal output; explicit null values remain unchanged in updates. Complex optional collections are not forcibly populated: empty audit-link scopes in particular are not an organization default. New map entries require native mandatory fields such as Kubernetes region and node-pool name; existing entries remain partially editable through known subpaths. + +Component-specific additional rules live declaratively in `assistantEditorPolicies`, not in a second field model: audit creation decisions and ACL free-text questions are the first rules. Their paths are tested against the native inventory. Both offered serving schema and unchanged native runtime checking are performed; no repair of duplicate, incomplete or unconfirmed responses. Topic correction uses unambiguous owners of validated native roots, not invented component names. Irrelevant firewall requirements are removed from non-network topics before source checking; source checks for network decisions actually used remain strict. DE/EN proposal texts containing changes are generated server-side as local draft proposals and cannot claim saving or live grants. The [extension procedure](../app/README.md#weitere-assistant-komponenten-ergaenzen) connects inventory, knowledge, additional rules, application tests and serial model qualification. + + +### Previous evidence: topic switch from firewall to audit logging + +The detected current topic must not be overridden by inherited `networkScope` or old firewall targets. Such properties apply exclusively in the active network/firewall topic; after evidence checking, their evidenced historical requirements are removed from another topic, not deleted or adopted as its current requirements. A current instruction with “next ... set up” is not deferral. + +Audit setup receives checked native field advice on telemetry link/router, logs and archive with the explicit boundary: currently no adoptable audit patch in chat. The common editor has generic fields under platform. No silent activation, retention/ACL selection or Object Lock promise; no continuation of the firewall interruption question. Audit proposals are therefore not automatically removed from the MVP. + +Evidence: **209 targeted offline tests**, type checking and **16/16 real synthetic model cases** (2 audit cases including the reported switch, 14 firewall regressions) passed. Knowledge hash: `8d8322d3c83f806d87ebbb7574443a8e06a9d8bcb98995e2557613c7216de906`; test-suite hash: `5314926be9bd321415c1377b7433fcd74cf61428295c70200d23db32e4b51d4d`. No customer policy/configuration or cloud execution for qualification. This status is activated in the HTTPS development environment; API health and unchanged complete configuration/conversation rows were checked after restart. Existing conversations remain continuable. + + +### Current MVP scope: no firewall-policy proposals + +User decision 2026-10-13: [issue #101](https://github.com/stackitcloud/stackit-landing-zone/issues/101) moves guided policy editing and adoptable Assistant proposals out of the MVP. Generic native fields in the common editor remain; the MVP alternative is manual policy maintenance by the firewall administrator in OPNsense. Infrastructure and HA alone guarantee neither isolation nor NAT. + +Current capability and definition requests for rules/NAT/aliases/routes/port forwarding receive the explicit chat boundary, #101 and administrator alternative, without changes or follow-up questions promising a rule proposal. Native field advice remains possible. Historical rule requirements do not displace a current infrastructure/capacity response; infrastructure/HA patches remain available. No other MVP gates are lifted. + +Evidence: **205 targeted offline tests**, type checking, knowledge/catalogue freshness and **16/16 real synthetic model cases** (14 infrastructure/dialogue cases, 2 policy cases) passed. Tests check no customer policy and authorize no cloud execution. Knowledge hash: `b9892a0d275b920e3089c167157062ef66af29630374df0b8a6d03ba5d24c37b`; test-suite hash: `f443f6633a4ffda7662f419d797a01ffe039c56f0ca5c4aaa187316036cc9c81`. Qualified backend status is activated in the HTTPS development environment. API health and unchanged complete configuration/conversation rows were checked before/after restart; UI and customer data were not restructured. + + +### Previous evidence: firewall capability boundary and actionable errors + +The native Accelerator manages `firewall_config` with rules, aliases, routes, outbound NAT and port forwarding. Current chat can patch only infrastructure and HA as a proposal, not the complex policy contract. A current question about this capability takes precedence over ongoing infrastructure questions. The response names the editor path, open rule targets and API prerequisites; previous traffic/policy responses remain requirements, not rules. Historical capability questions must not displace a current capacity response. Intent explicitly identifies the current source for this. + +Rejected model responses are not automatically retried or partially accepted. JSON and NDJSON deliver the same redacted error contract: unconfirmed requirements, mismatching proposal, invalid/truncated/interrupted response, timeout, load, service authentication or availability. Configuration chat and template advice show localized causes, concrete next steps and a diagnostic identifier; inputs are retained. Raw model responses, transport details and credentials are not displayed. + +Evidence on 2026-10-13: **196 targeted offline tests**, **6 PostgreSQL cases**, **13/13 real synthetic firewall cases** and **8 desktop/mobile browser cases** passed, including the reported capability question, unknown capacity, actionable error messages and response/selection preservation. Knowledge hash: `53945a3b8988baf2b4096365496e01fa3a38beb83b2d7da3e43bb0fcab798181`; test-suite hash: `2caf7ed586cda64bf151f3fa6bd4466b8504da63fb45666ed4ca77e1b2bc4e3d`. This is neither policy/package checking nor cloud execution approval. Type checking, knowledge/catalogue freshness and targeted lint passed (one pre-existing browser-test warning). Activated in the HTTPS development environment; API health and new UI bundle checked. Complete configuration/conversation rows remained unchanged. + +Previous evidence before the role patch on 2026-10-12: **93 offline tests**, type checking, knowledge/catalogue freshness and targeted lint passed. Final real run: **24/24 passed, no skipped case**, with Qwen3-VL as response model and GPT-OSS-120B as intent model. The five previously failing cases are fixed; oracles were not loosened but extended with field names, limitations and false saving claims. Foundations restoration and all three DNS contact variants remain green. No automatic retry or acceptance of failed responses. + +| Case | Cause and correction | Live evidence | |---|---|---| -| `identity-foundations-advice` | Serving verlor fruehere Systemnachrichten; Ausgabe endete am Tokenlimit. Ein einziger Systemvertrag und eine gepruefte native Felduebersicht ersetzen die unvollstaendige Freiform-Aufzaehlung. | bestanden, 1659 ms | -| `governance-folders-advice` | Namens-Patchgrenzen wurden mit Editor-Feldern verwechselt. Uebersicht nennt Elternordner, Rollen und Namen 1-40 Zeichen; meaningful descriptions werden explizit abgelehnt. | bestanden, 1391 ms | -| `firewall-policy-advice` | Gemeinsamer Firewall-Infrastrukturdialog verdraengte den Policy-Vertrag. Getrennte Themenfragen und native Policy-Uebersicht mit aliases/routes/rules/NAT, pass/block/reject und expliziter Synchronisierung. | bestanden, 1929 ms | -| `sandbox-projects-advice` | Verlorener Systemvertrag/Tokenlimit; erfundene Laufzeit-/Budgetoptionen. Native Uebersicht nennt nur project_name, project_owner_email und owner_emails sowie die separaten Lifecycle-Grenzen. | bestanden, 1583 ms | -| `sna-complete-draft` | Modellprosa behauptete eine bereits erfolgte Konfiguration. Erklaerung wird aus validierten Patch-Werten erzeugt; Streaming zeigt keinen ungeprueften Speichertext. | bestanden, 3946 ms | - -Der semantische Intent `adviceTask=field-overview` nutzt fuer diese vier -Uebersichtsthemen den Backend-Wissensvertrag mit Feldinventar und geprueften -Grenzen. Das ist ein expliziter Beratungspfad, kein Erfolg-Fallback nach einem -Modellfehler. Andere Fragen und Vorschlaege verwenden weiterhin das Antwortmodell. -Ein Tokenlimit-Abbruch wird als `completion_truncated` verworfen; der HTTP-Fehler -bleibt redigiert. Alle vertrauenswuerdigen Systemanweisungen werden zusammen -gesendet, Nutzer-/Historiennachrichten bleiben getrennte untrusted Daten. -Native Editorfelder und schmalere Chat-Patchrechte bleiben unterscheidbar; -Rueckfragen sind auf das aktive Thema beschraenkt. -Der gepruefte Stand wurde lokal im Chatmodus ohne Cloud-Ausfuehrung neu gestartet. -API und UI-Proxy melden gesund; UI HTTP200 und unauthentifizierte Chatroute HTTP401. -Konfigurations-/Gesprächspruefsummen und Revisionen (6/19) blieben unveraendert. - -Die Themen-Smokes pruefen Antwortvertrag, Referenz und Beratungsmodus, nicht jede -fachliche Textaussage oder jedes Feld einzeln. Fuer Vollqualifikation braucht es -weitere spezifische Sollwerte, Negativfaelle und Komponentenbeziehungen. Ein -vollstaendiges Inventar oder ein gruener Smoke ist keine Ausfuehrungsfreigabe. - -### Modellversuch GPT-OSS 120B und zusammenhaengender Dialog - -Am 2026-10-13 wurden Antwortmodell und Intentmodell in isolierten Testprozessen -auf `openai/gpt-oss-120b` gesetzt. Die laufende Anwendung, Kundenentwuerfe, -Gespraeche und Cloud-Ausfuehrung wurden nicht umgestellt. - -Der erste komplette 52-Faelle-Lauf bestand **29/52**. Von 23 Fehlern waren neun -HTTP-429-Antworten; parallel laufende Diagnose-/Journey-Tests beeintraechtigten -damit die Aussagekraft. Weitere Fehler waren sechs Tokenlimit-Abbrueche, vier -Scope-Ablehnungen, eine unbestaetigte Intentquelle und drei fachliche -Sollwertverletzungen. Diese Zahlen sind kein fairer Modellrangvergleich. -Wissenshash dieses ersten Laufs: -`c9bcfb0a1e8c3d2be7855a8db2a3a0ffc8ad392e0ed854d880ca876effad2ef2`; -52-Faelle-Suite: -`574375fd7a19aa775bba0bf766156660721454ae5db6a7013d69b2689dd6da32`. - -Synthetische Rohantworten zeigten wiederholte merge/replace-Alternativen fuer -denselben Pfad und ausgelassene Audit-ACLs trotz Nennung im Antworttext. -Die Serving-Schemas verwenden deshalb nun ein einzelnes Operationsobjekt pro -Pfad und begrenzen die Anzahl auf die angebotenen Pfade. Nicht unterstuetzte -`propertyNames` werden nur aus dem Serving-Schema entfernt; die urspruengliche -Zod-Pruefung von Map-Schluesseln, Operationswerten und vollstaendigen -Ersetzungen bleibt unveraendert. Ein gekuerzter Label-Reply enthielt vor allem -Whitespace statt Nutzdaten; ein hoeheres Tokenbudget oder automatischer Retry -ist daher kein nachgewiesener Fix. - -Der neue [Journey-Runner](../app/scripts/assistant-journey.ts) wurde danach fuer -beide Modelle **seriell** mit identischem Skript, Wissensstand, Temperatur und -Tokenlimit ausgefuehrt. Beide Modellrollen verwendeten jeweils dasselbe Modell. -Er simuliert Grundlagen, Rollen, SNA, Firewall/HA, die Policy-MVP-Grenze, -Audit-Themenwechsel/Rueckfragen/Aktualisierung, Observability, DevOps, -Kubernetes und Labels. Nur gueltige, erwartungsgemaesse Vorschlaege werden im -Speicher uebernommen. API-konforme Gespraechshistorie, JSON-Roundtrip und -tfvars-Export bleiben Bestandteil des Laufs; kein Browser, DB-Speichern, -Plan oder Apply wird dadurch qualifiziert. - -| Serieller Journey-Schritt | GPT-OSS 120B | Qwen3-VL 235B A22B | +| `identity-foundations-advice` | Serving lost earlier system messages; output ended at the token limit. One system contract and a checked native field overview replace the incomplete free-form enumeration. | passed, 1659 ms | +| `governance-folders-advice` | Name-patch boundaries were confused with editor fields. Overview names parent folder, roles and names of 1–40 characters; meaningful descriptions are explicitly rejected. | passed, 1391 ms | +| `firewall-policy-advice` | Shared firewall infrastructure dialogue displaced policy contract. Separate topic questions and native policy overview with aliases/routes/rules/NAT, pass/block/reject and explicit synchronization. | passed, 1929 ms | +| `sandbox-projects-advice` | Lost system contract/token limit; invented runtime/budget options. Native overview names only project_name, project_owner_email and owner_emails plus separate lifecycle limitations. | passed, 1583 ms | +| `sna-complete-draft` | Model prose claimed configuration had already occurred. Explanation is generated from validated patch values; streaming shows no unchecked saving text. | passed, 3946 ms | + +Semantic intent `adviceTask=field-overview` uses the backend knowledge contract with field inventory and checked limitations for these four overview topics. This is an explicit advice path, not a success fallback after a model error. Other questions and proposals still use the response model. Token-limit termination is rejected as `completion_truncated`; HTTP error remains redacted. All trusted system instructions are sent together; user/history messages remain separate untrusted data. Native editor fields and narrower chat patch rights remain distinguishable; follow-up questions are restricted to the active topic. The checked status was restarted locally in chat mode without cloud execution. API and UI proxy report healthy; UI HTTP200 and unauthenticated chat route HTTP401. Configuration/conversation checksums and revisions (6/19) remained unchanged. + +Topic smokes check response contract, reference and advice mode, not every factual text statement or every field individually. Full qualification needs further specific expected values, negative cases and component relationships. A complete inventory or green smoke is not execution approval. + + +### GPT-OSS 120B model experiment and continuous dialogue + +On 2026-10-13, response and intent models were set to `openai/gpt-oss-120b` in isolated test processes. The running application, customer drafts, conversations and cloud execution were not switched. + +The first complete 52-case run passed **29/52**. Of 23 failures, nine were HTTP 429 responses; concurrent diagnostic/journey tests thus compromised interpretability. Further failures were six token-limit truncations, four scope rejections, one unconfirmed intent source and three factual oracle violations. These numbers are not a fair model ranking. Knowledge hash of this first run: `c9bcfb0a1e8c3d2be7855a8db2a3a0ffc8ad392e0ed854d880ca876effad2ef2`; 52-case suite: `574375fd7a19aa775bba0bf766156660721454ae5db6a7013d69b2689dd6da32`. + +Synthetic raw responses showed repeated merge/replace alternatives for the same path and omitted audit ACLs despite mentioning them in response text. Serving schemas therefore now use one operation object per path and limit the count to offered paths. Unsupported `propertyNames` are removed only from the serving schema; original Zod checking of map keys, operation values and complete replacements remains unchanged. A truncated label reply contained mainly whitespace instead of useful data; a higher token budget or automatic retry is therefore not a demonstrated fix. + +The new [journey runner](../app/scripts/assistant-journey.ts) was then executed **serially** for both models with identical script, knowledge status, temperature and token limit. Both model roles used the same model in each run. It simulates foundations, roles, SNA, firewall/HA, the policy MVP boundary, audit topic switching/follow-ups/update, Observability, DevOps, Kubernetes and labels. Only valid, expected proposals are adopted in memory. API-compliant conversation history, JSON roundtrip and tfvars export remain part of the run; this qualifies no browser, DB saving, Plan or Apply. + +| Serial journey step | GPT-OSS 120B | Qwen3-VL 235B A22B | |---|---|---| -| Grundlagen | Scope-Ablehnung | bestanden | -| Organisations-Owner | bestanden | bestanden | -| SNA | bestanden | bestanden | -| Firewall/HA | bestanden | bestanden | -| Policy-MVP-Hinweis | bestanden | bestanden | -| Audit-Themenwechsel / fehlende Entscheidungen | Pflichtwerte fehlen | bestanden | -| Audit-Antwort | Pflichtwerte fehlen | Pflichtwerte fehlen | -| Audit-Aktualisierung | Pflichtwerte fehlen | Pflichtwerte fehlen | -| Observability | unbestaetigte Intentquelle | erwartete ACL/Retention fehlen | -| DevOps | bestanden | bestanden | -| Kubernetes | Vorschlag nicht anwendbar | Vorschlag nicht anwendbar | -| Labels | Tokenlimit-Abbruch | falsches Thema / Label fehlt | -| **Gesamtergebnis** | **5/12, nicht qualifiziert** | **7/12, nicht qualifiziert** | - -Die seriellen Laeufe enthielten keine HTTP-429/503-Ablehnungen. Beobachtete -Turn-Dauern einschliesslich Intentklassifikation: GPT-OSS Median ca. 7,0 s, -Maximum 22,5 s; Qwen Median ca. 5,7 s, Maximum 12,3 s. Dies sind einzelne -synthetische Laeufe, keine allgemeine Latenz-, Kosten- oder Qualitaetsgarantie. -Beide Laeufe verwenden Wissenshash -`b21aac363a8f2d9110a4e21d4473b630bc193b0b02e9d04926f306f4c98af73d` -und Journey-Hash -`80ce96770cd172dbbfd37f73b5443cffd2e3f5e521627d2bf53aa2b20df1dd9e`. -**228 gezielte Offline-Tests**, Typpruefung, gezieltes Lint und -Wissens-/Katalogfrische bestanden. - -Ergebnis: Ein reiner Modellwechsel behebt die Editor-/Assistant-Probleme nicht. -GPT-OSS wird auf dieser Basis nicht als neuer Standard aktiviert. Audit-Pflicht- -und Rueckfragevertraege, Label-Intent, anwendbare Kubernetes-Vorschlaege sowie -Scope-/Quellenkontinuitaet muessen vor einer erneuten Vollqualifikation -bearbeitet werden. Auch die native Editor-Erweiterung bleibt unaktiviert. - -### Gemeinsame Komponentenvertraege: erneute Qualifikation - -Die anschliessende Korrektur erfolgt im gemeinsamen nativen Vorschlagsvertrag, -nicht ueber modellspezifische Sonderfaelle. Neue Audit-Konfigurationen brauchen -Retention, ACL und die ausdrueckliche Object-Lock-Entscheidung zusammen. -Bestehende Objekte bleiben partiell aenderbar. Kubernetes-Erstellung verlangt -native Pflichtfelder einschliesslich Region und Node-Pool-Name; Labels verwenden -den geprueften Besitzer ihrer nativen Pfade. Ein Themenwechsel verwirft -irrelevante Firewall-Anforderungen, nicht aber Quellenpruefungen fuer weiterhin -genutzte Netzwerkentscheidungen. ACL-Rueckfragen erfinden keine auswaehlbaren -CIDRs. Vorschlagstexte behaupten weder Speicherung noch Deployment. - -Nach diesen Aenderungen bestanden am 2026-10-13: - -| Pruefung | Ergebnis | +| Foundations | Scope rejection | passed | +| Organization owner | passed | passed | +| SNA | passed | passed | +| Firewall/HA | passed | passed | +| Policy MVP notice | passed | passed | +| Audit topic switch / missing decisions | Required values missing | passed | +| Audit response | Required values missing | Required values missing | +| Audit update | Required values missing | Required values missing | +| Observability | Unconfirmed intent source | Expected ACL/retention missing | +| DevOps | passed | passed | +| Kubernetes | Proposal not applicable | Proposal not applicable | +| Labels | Token-limit truncation | Wrong topic / label missing | +| **Overall result** | **5/12, not qualified** | **7/12, not qualified** | + +Serial runs contained no HTTP 429/503 rejections. Observed turn durations including intent classification: GPT-OSS median approx. 7.0 s, maximum 22.5 s; Qwen median approx. 5.7 s, maximum 12.3 s. These are individual synthetic runs, not a general latency, cost or quality guarantee. Both runs use knowledge hash `b21aac363a8f2d9110a4e21d4473b630bc193b0b02e9d04926f306f4c98af73d` and journey hash `80ce96770cd172dbbfd37f73b5443cffd2e3f5e521627d2bf53aa2b20df1dd9e`. **228 targeted offline tests**, type checking, targeted lint and knowledge/catalogue freshness passed. + +Result: a model switch alone does not fix the editor/Assistant problems. GPT-OSS is not activated as the new default on this basis. Mandatory audit and follow-up contracts, label intent, applicable Kubernetes proposals and scope/source continuity must be addressed before renewed full qualification. The native editor extension also remains unactivated. + + +### Common component contracts: renewed qualification + +Subsequent correction takes place in the common native proposal contract, not through model-specific exceptions. New audit configurations need retention, ACL and explicit Object Lock decision together. Existing objects remain partially editable. Kubernetes creation requires native mandatory fields including region and node-pool name; labels use the checked owner of their native paths. A topic switch discards irrelevant firewall requirements but not source checking for network decisions still used. ACL follow-ups invent no selectable CIDRs. Proposal texts claim neither saving nor deployment. + +After these changes, on 2026-10-13: + +| Check | Result | |---|---| -| Gezielt alle acht Assistant-Offline-Suites | **238/238** | -| Typpruefung und Produktionsbuild | bestanden | -| Repository-Lint | keine Fehler; bestehende Warnungen bleiben | -| Wissens- und Szenarienkatalogfrische | bestanden | -| Zusammenhaengender echter Qwen-Dialog | **12/12** | -| Vollstaendiger echter Qwen-Szenarienlauf | **52/52** | - -Beide Modellrollen verwendeten weiterhin -`Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`. Die Modelltests liefen nacheinander und -ohne automatische Wiederholung. Vorherige Laeufe mit denselben -Komponentenvertraegen waren durch HTTP 429 unvollstaendig geblieben. -Der [gemeinsame Testadapter](../app/scripts/assistant-test-model.ts) begrenzt -jetzt jeden tatsaechlichen Request, einschliesslich Intentklassifikation, auf -mindestens 2500 ms Abstand. Tests pruefen Abstand, fehlenden Retry und Abbruch -waehrend der Wartezeit. Diese Begrenzung gilt nicht fuer den produktiven -Assistant; die gemessenen Turn-Zeiten enthalten Testwartezeit. -Die beiden abschliessenden Laeufe enthielten keine Quoten- oder Modellfehler. - -Nachweis-Hashes: - -- Wissen: `eb856918ecd71e3f380ea8da9be116d4578cedfc9977088c56311b9e65d44346` +| All eight targeted Assistant offline suites | **238/238** | +| Type checking and production build | passed | +| Repository lint | No errors; existing warnings remain | +| Knowledge and scenario catalogue freshness | passed | +| Continuous real Qwen dialogue | **12/12** | +| Complete real Qwen scenario run | **52/52** | + +Both model roles still used `Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`. Model tests ran consecutively without automatic retry. Previous runs with the same component contracts had remained incomplete because of HTTP 429. The [shared test adapter](../app/scripts/assistant-test-model.ts) now spaces every actual request, including intent classification, at least 2500 ms apart. Tests check spacing, no retry and cancellation during waiting. This limit does not apply to the production Assistant; measured turn times include test waiting time. The two final runs contained no quota or model errors. + +Evidence hashes: + +- Knowledge: `eb856918ecd71e3f380ea8da9be116d4578cedfc9977088c56311b9e65d44346` - Journey: `74b5d41782e20b9d720a63afa1d515e50c4197602f41789d1ce920f1598d64e2` -- Szenariensuite: `57888ab5cfccc1303ebfd01125a9c6ed185b82602eab83a75a7eb20b1e34d498` - -Der Journey uebernahm gueltige Vorschlaege in einen fortgeschriebenen -synthetischen Entwurf, bewahrte 24 Gespraechsnachrichten, pruefte den -JSON-Roundtrip und exportierte 2069 Bytes tfvars. Dies ist keine Qualifikation -aller Browser-/Datenbank-Workflows oder von Plan/Apply. Kundenentwuerfe und -Gespraeche wurden nicht veraendert; die laufende API wurde nicht neu gestartet. -GPT-OSS ist nach diesen Vertragskorrekturen noch nicht erneut qualifiziert. -Die Firewall-Policy bleibt als einzige hier ausdruecklich ausgeschlossene -Komponentenbearbeitung unter #101; es wurden keine weiteren Themen aus dem -MVP genommen. Weitere Komponenten folgen dem dokumentierten -[Erweiterungsverfahren](../app/README.md#weitere-assistant-komponenten-ergaenzen). - -### Dev-Release-Qualifikation (2026-10-14) - -Der korrigierte Release-Stand `927f20a` wurde erneut mit dem echten Qwen-Modell -qualifiziert: **52/52** synthetische Katalogfaelle und **12/12** Schritte im -fortgeschriebenen Gesamtdialog bestanden ohne automatische Wiederholung. -Der vorangegangene Lauf auf `1aabadb` bestand nur 51/52 Faelle: Eine bestaetigte -Firewall-Verkehrsentscheidung wurde erneut abgefragt. Die anschliessende -Klassifikationsklarstellung und der gezielte Regressionstest wurden vor dem -vollstaendigen Wiederholungslauf ausgefuehrt; der erste Fehlerbeleg bleibt erhalten. - -- Wissen: `12693f9d18db481e57ae668b777bfd19715a96f121aa94efa984bc5cd8747bea` +- Scenario suite: `57888ab5cfccc1303ebfd01125a9c6ed185b82602eab83a75a7eb20b1e34d498` + +The journey adopted valid proposals into an evolving synthetic draft, preserved 24 conversation messages, checked JSON roundtrip and exported 2069 bytes of tfvars. This is not qualification of all browser/database workflows or Plan/Apply. Customer drafts and conversations were not changed; the running API was not restarted. GPT-OSS has not yet been requalified after these contract corrections. Firewall policy remains the only component editing explicitly excluded here under #101; no further topics were removed from the MVP. Further components follow the documented [extension procedure](../app/README.md#weitere-assistant-komponenten-ergaenzen). + + +### Dev release qualification (2026-10-14) + +Corrected release source `927f20a` was qualified again with the real Qwen model: **52/52** synthetic catalogue cases and **12/12** steps in the evolving complete dialogue passed without automatic retry. The preceding run on `1aabadb` passed only 51/52 cases: a confirmed firewall traffic decision was asked again. Subsequent classification clarification and targeted regression test were performed before the complete repeat run; the first failure evidence is retained. + +- Knowledge: `12693f9d18db481e57ae668b777bfd19715a96f121aa94efa984bc5cd8747bea` - Journey: `74b5d41782e20b9d720a63afa1d515e50c4197602f41789d1ce920f1598d64e2` -- Szenariensuite: `57888ab5cfccc1303ebfd01125a9c6ed185b82602eab83a75a7eb20b1e34d498` - -Der Journey bewahrte 24 Gespraechsnachrichten und exportierte 2069 Bytes tfvars. -Zusaetzlich bestanden 685 Unit-, 49 PostgreSQL- und 288 Desktop-/Mobile-Tests -sowie Typpruefung, Produktionsbuild, Katalogfrische und Release-Vorbereitung. -Die gehostete Assistant-Aktivierung wird ueber das geschuetzte -`LZC_ASSISTANT_ENABLED`-Opt-in weitergereicht und verlangt Authentifizierung. -Realer menschlicher Login, Organisationsnachweis und Kunden-Cloud-Ausfuehrung -sind separate Nachweise; ihr aktueller Status steht im -[MVP-Umfang](mvp-scope.md). Die oben genannten Zahlen sind historische, -revisionsgebundene Ergebnisse; aktuelle Nachweise stehen in CI und im -zugehoerigen Pull Request. - -### Additive Organisations- und Folder-Rollenvorschlaege - -Die gemeldete Bitte um Nutzung der hinterlegten E-Mail als -Organisationsverantwortlicher wurde faelschlich als Grundlagenkontakt behandelt. -Der bislang schmalere Namens-/Skalarvertrag liess Rollenfelder nicht zu. -Explizite Rollenzuweisungswuensche werden jetzt semantisch als Governance-Entwurf -klassifiziert. Ein gepruefter Backend-Pfad erstellt `organization_owners`, -`organization_auditors` oder vorhandene Folder-Owner-/Reader-Listen aus der -angefragten gespeicherten, verifiziert menschlichen oder explizit genannten -E-Mail-Quelle, ohne freie Rollenwerte des Antwortmodells. Das ist kein Fallback -nach Modellfehlern und kein menschlicher Identitaetsnachweis. - -Vorhandene Zuweisungen, Folder-Namen, Schluessel und uebrige Konfiguration bleiben -erhalten. Neue Folder, entfernte Subjects, Elternordner-/Configurator-Rollen oder -Live-Grants sind nicht erlaubt. Fehlende E-Mail oder unklare Folder-Auswahl werden -gezielt erfragt. Organisations-Owner-Rechte decken Folder ab; die native -Governance vermeidet doppelte Folder-Zuweisungen. Folder-Reader verwenden auditor. -Selektive Uebernahme speichert weiterhin nur den Entwurf, unselektierte Felder -bleiben offen; IAM-Auswirkungen benoetigen einen getrennten geprueften Plan/Apply. - -Zusatznachweis am 2026-10-12: **110 Offline-Tests**, Typpruefung und gezieltes Lint -bestanden. **30/30 echte synthetische Faelle** bestanden, diesmal mit Qwen3-VL -sowohl als Antwort- als auch als Intentmodell entsprechend dem laufenden -Workstation-Modus. Die sechs neuen Governance-Faelle pruefen die gemeldete Frage, -alle explizit ausgewaehlten Folder, einen konkreten Reader, fehlende Folder-Auswahl, -fehlende E-Mail und die verifizierte Login-Quelle. Drei fokussierte echte -PostgreSQL-Tests pruefen transaktionale Rollen-/DNS-/Netzwerk-Felduebernahme, -Revisionsgrenzen und Tenant-Isolation. Keine Kundenkonfiguration, kein -Kundengespraech und keine Cloud-Berechtigung wurde durch die Tests veraendert. - -### Native Firewall-Infrastruktur und HA - -Der bisherige SNA-Dialog nahm ohne Grundlage einen ausschliesslichen ersten -Netzwerkschritt an; Firewall-Infrastruktur war nur beratend unterstuetzt. -Explizite kombinierte Auftraege verwenden jetzt die gespeicherten SNA-Werte und -setzen mit dem Firewall-Vertrag fort. Fehlende SNA-Eingaben bleiben echte -Abhaengigkeiten, ein ausdrueckliches "Firewall spaeter" bleibt SNA-only. -Die Kapazitaetsrechnung trennt Projekt-Subnetze und Adressen: /16 enthaelt512 /25, -jeder /25 hat128 Adressen vor Infrastrukturreservierungen, ohne Quoten-/Durchsatz- -oder Freibelegungszusage. - -Zentrale `connectivity.firewall`/`firewalls` akzeptieren gepruefte native -Infrastrukturfelder einschliesslich des HA-Objekts mit anderer Backup-Zone, -optionalen Node-/VIP-Adressen, Backup-Namen und vhid. Ein zusammenhaengender Patch -enthaelt alle Pflichtfelder neuer Appliances; vorhandene Appliances sind partiell -editierbar. Explizit angefragte Felder werden im Antwortschema verpflichtend. -Fehlende bestaetigte Adressen/Produkte/Zonen fuehren zu geprueften Rueckfragen, -nicht zu unvollstaendigen Patches oder erfundenen technischen Beispielwerten. -Mehrere Bereiche erfordern explizite Zielauswahl; Neuanlage einer nativen Map -muss alle Bereiche abdecken und braucht dafuer einen ausdruecklichen Auftrag. - -Single-/Map-Form, Area-Keys, unbekannte Importmetadaten und nicht angefragte -Konfiguration bleiben erhalten. Geprueft werden Pool-Containment, LAN-/WAN-/ -Transfer-Ueberlappungen, nutzbare unterschiedliche IPs, native cidrhost-Defaults -4/5/6 und unterschiedliche HA-Zonen. Regional-Umwandlungen, Entfernung, -Firewall-Policies, Operator-Zugaenge und Ausfuehrung bleiben ausgeschlossen. -Nested-HA-Felder erscheinen einzeln im UI; unvollstaendige abhaengige Auswahl -wird transaktional ohne Speicherung abgelehnt. Feldannahme ist kein Deployment, -SLA-Nachweis oder automatisches Failover einer oeffentlichen IP. - -Nachweis nach der Einrichtungs-/UI-Sperrkorrektur: **160 Offline-Tests**, Typpruefung, -Wissens-/Katalogfrische und gezieltes Lint bestanden. **10/10 gezielte Firewall- -Live-Faelle** bestanden mit Qwen3-VL als Antwort- und Intentmodell, ohne -uebersprungene Faelle oder automatische Wiederholung. Der vorherige vollstaendige -Live-Lauf bestand mit **35/35 Faellen**; die neue Suite enthaelt 39 Faelle. -Vier echte PostgreSQL-Tests pruefen HA-/Rollen-/DNS-/SNA-Feldauswahl, darunter -Rollback unvollstaendiger HA-Auswahl, Revisionen und Tenant-Grenzen. -Sechs Desktop-/Mobil-Browsertests pruefen HA-Einzelfelder sowie bestehenden -DNS- und Chat-Workflow. Die neuen Live-Faelle testen den gemeldeten kombinierten -Satz, HA-Ergaenzung, komplette Neuanlage, fehlende Voraussetzungen und gespeicherte -HA ohne erneuten Vorschlag. Keine Cloud-Bereitstellung oder Kunden-Draft-Aenderung -durch diese Tests. -Die neue Regression verwendet die native Single-Form mit Metro-Zone, /28-LAN/WAN, -vorhandenem Flavor und einem Produktkatalog. Unbestaetigte Node-/VIP-Adressen -fehlen im Antwortschema; berechnete Defaults bleiben implizit. Gespeicherte oder -benutzerbestaetigte IPs bleiben einzeln vorschlagbar, erfundene IPs werden weiterhin -abgewiesen. Auch die genaue Benutzeranfrage mit gespeichertem oeffentlichem -Konfigurationsstand und echten autorisierten Produktkatalogen wurde nur lesend -erfolgreich reproduziert; es wurden keine Kunden-Vorschlaege uebernommen. -Bei breiter Einrichtung folgt neben einem gueltigen HA-Patch eine einzelne offene -Verkehrs-, Kapazitaets- oder Betriebsfrage. Ein begrenzter semantischer Aufruf mit -dem Intentmodell prueft nur aktuelle/vorherige Benutzeraussagen und die enge oder -breite Anfrage. Bestaetigungen brauchen woertliche Benutzerquellen; erfundene -Bestaetigungen werden abgewiesen. Gezielte native Patches erhalten keinen -zusaetzlichen Fragebogen. Vorhandene Appliance-Werte werden als Entwurfsstand, -nicht als Leistungsnachweis, angezeigt. -Die damaligen Desktop-/Mobiltests reproduzierten die pauschale Sperre bei -ungespeicherten Aenderungen. Diese Sperre wird durch den unten beschriebenen -konfliktbezogenen Entwurfsabgleich ersetzt. -Der korrigierte Workstation-Prozess ist ueber HTTPS erreichbar; alle gespeicherten -Konfigurations- und Gespraechszeilen blieben laut Pruefsummen beim kontrollierten -API-Neustart unveraendert. Es wurde kein Plan/Apply gestartet. - -## Historische Konzeptmatrix (A01-A24) - -Die [maschinenlesbare Matrix](assistant-feature-coverage.json) ordnet alle 29 -aktuellen Root-Eingaben und jeden verschachtelten Katalogeintrag Szenarien zu. -Objekt-/Listencontainer sind enthalten, nicht nur Blaetter. Sie verwendet -`featureGroups`, `acceleratorInputs` und `featureFieldCatalogue`; keine separate -handgeschriebene Feldliste. Quellhashes erkennen Aenderungen am Feature-Katalog, -Input-Inventar, aktuellen Vorlagen, Fachvalidierung, Dokument-/Compilervertraegen -und Application-Template-Vertrag. Die -Engine-Revision ist der vorhandene Domain-Pin, keine Behauptung, dass der lokale -Root oder ein neues Runner-Paket bereits unter diesem Pin freigegeben ist. - -Jeder Feldeintrag beginnt mit `qualification = not-qualified`. Zuordnung und -Frische beweisen nur Konzeptvollstaendigkeit, nicht KI-Verstaendnis. Pro Feld -sind Analyse, fehlende Angaben und, soweit unterstuetzt, Erstellung/Aenderung -mit validiertem Diff zu evaluieren. Sensible Felder erlauben ausschliesslich -Erklaerung der Zugangsvoraussetzungen, keine Werte im Chat, Modellkontext oder -Patch. Unwirksame Felder werden erklaert und abgewiesen, nicht angeboten. -Komponentenbeziehungen brauchen zusaetzliche fachliche Faelle; Feldabdeckung -allein reicht nicht. Die Matrix erweitert keine Ausfuehrungsrechte. - -Aktualisieren und pruefen im App-Verzeichnis: +- Scenario suite: `57888ab5cfccc1303ebfd01125a9c6ed185b82602eab83a75a7eb20b1e34d498` + +The journey preserved 24 conversation messages and exported 2069 bytes of tfvars. Additionally, 685 unit, 49 PostgreSQL and 288 desktop/mobile tests passed, alongside type checking, production build, catalogue freshness and release preparation. Hosted Assistant activation is passed through the protected `LZC_ASSISTANT_ENABLED` opt-in and requires authentication. Real human login, organization evidence and customer cloud execution are separate evidence; their current status is in [MVP scope](mvp-scope.md). The above counts are historical, revision-bound results; current evidence is in CI and the associated pull request. + + + +### Additive organization and folder role proposals + +The reported request to use the stored email as organization owner was incorrectly treated as a foundations contact. The previously narrower name/scalar contract did not allow role fields. Explicit role-assignment requests are now semantically classified as a governance draft. A checked backend path creates `organization_owners`, `organization_auditors` or existing folder owner/reader lists from the requested stored, verified human or explicitly named email source, without free-form role values from the response model. This is neither a fallback after model errors nor human identity evidence. + +Existing assignments, folder names, keys and other configuration are retained. New folders, removed subjects, parent-folder/Configurator roles or live grants are not allowed. Missing email or ambiguous folder selection receive targeted questions. Organization owner rights cover folders; native governance avoids duplicate folder assignments. Folder readers use auditor. Selective adoption still saves only the draft; unselected fields remain open; IAM effects need a separate checked Plan/Apply. + +Additional evidence on 2026-10-12: **110 offline tests**, type checking and targeted lint passed. **30/30 real synthetic cases** passed, this time with Qwen3-VL as both response and intent model, matching running workstation mode. Six new governance cases check the reported question, all explicitly selected folders, a specific reader, missing folder selection, missing email and verified login source. Three focused real PostgreSQL tests check transactional role/DNS/network field adoption, revision boundaries and tenant isolation. Tests changed no customer configuration, customer conversation or cloud permission. + + +### Native firewall infrastructure and HA + +The previous SNA dialogue assumed without basis an exclusively first network step; firewall infrastructure had advice-only support. Explicit combined requests now use saved SNA values and continue with the firewall contract. Missing SNA inputs remain real dependencies; explicit “firewall later” remains SNA-only. Capacity calculation separates project subnets and addresses: /16 contains 512 /25, each /25 has 128 addresses before infrastructure reservations, without a quota, throughput or free-capacity promise. + +Central `connectivity.firewall`/`firewalls` accept checked native infrastructure fields including the HA object with a different backup zone, optional node/VIP addresses, backup names and vhid. A coherent patch contains all required fields of new appliances; existing appliances are partially editable. Explicitly requested fields become mandatory in the response schema. Missing confirmed addresses/products/zones lead to checked follow-ups, not incomplete patches or invented technical example values. Multiple areas require explicit target selection; creating a native map must cover all areas and requires an explicit instruction. + +Single/map form, area keys, unknown import metadata and unrequested configuration are retained. Checks cover pool containment, LAN/WAN/transfer overlaps, usable distinct IPs, native cidrhost defaults 4/5/6 and distinct HA zones. Regional conversions, removal, firewall policies, operator access and execution remain excluded. Nested HA fields appear individually in the UI; incomplete dependent selection is transactionally rejected without saving. Field acceptance is neither deployment, SLA evidence nor automatic failover of a public IP. + +Evidence after the setup/UI-block correction: **160 offline tests**, type checking, knowledge/catalogue freshness and targeted lint passed. **10/10 targeted firewall live cases** passed with Qwen3-VL as response and intent model, without skipped cases or automatic retry. The previous complete live run passed **35/35 cases**; the new suite contains 39 cases. Four real PostgreSQL tests check HA/role/DNS/SNA field selection, including rollback of incomplete HA selection, revisions and tenant boundaries. Six desktop/mobile browser tests check individual HA fields and existing DNS/chat workflow. New live cases test the reported combined sentence, HA addition, complete creation, missing prerequisites and stored HA without another proposal. No cloud provisioning or customer draft changes through these tests. + +The new regression uses native single form with metro zone, /28 LAN/WAN, existing flavor and a product catalogue. Unconfirmed node/VIP addresses are absent from the response schema; computed defaults remain implicit. Stored or user-confirmed IPs remain individually proposable; invented IPs are still rejected. The exact user request with stored public configuration status and real authorized product catalogues was also successfully reproduced read-only; no customer proposals were adopted. + +For broad setup, a valid HA patch is followed by one open traffic, capacity or operations question. A bounded semantic call with the intent model checks only current/previous user statements and the narrow or broad request. Confirmations need verbatim user sources; invented confirmations are rejected. Targeted native patches receive no additional questionnaire. Existing appliance values are shown as draft status, not performance evidence. Desktop/mobile tests at that time reproduced blanket blocking of unsaved changes. This block is replaced by conflict-aware draft reconciliation described below. The corrected workstation process is reachable through HTTPS; all saved configuration and conversation rows remained unchanged according to checksums during controlled API restart. No Plan/Apply was started. + + +## Historical concept matrix (A01–A24) + +The [machine-readable matrix](assistant-feature-coverage.json) assigns all 29 current root inputs and every nested catalogue entry to scenarios. Object/list containers are included, not just leaves. It uses `featureGroups`, `acceleratorInputs` and `featureFieldCatalogue`; no separate handwritten field list. Source hashes detect changes to feature catalogue, input inventory, current templates, domain validation, document/compiler contracts and Application template contract. Engine revision is the existing domain pin, not a claim that the local root or new Runner package is already approved under this pin. + +Every field entry starts with `qualification = not-qualified`. Mapping and freshness prove only conceptual completeness, not AI understanding. Analysis, missing information and, where supported, creation/modification with validated diff must be evaluated per field. Sensitive fields allow only explanation of access prerequisites, no values in chat, model context or patch. Ineffective fields are explained and rejected, not offered. Component relationships need additional business cases; field coverage alone is insufficient. The matrix extends no execution permissions. + +Update and check in the app directory: ```sh npm run build:packages @@ -467,348 +178,149 @@ node --import tsx scripts/assistant-coverage.ts --check npx vitest run tests/common-configuration.test.ts ``` -Der bestehende Unit-Gate prueft Matrixfrische und Katalogvollstaendigkeit. Neue -Root-Eingaben ohne Szenariozuordnung schlagen fehl. Neue Unterfelder machen die -Matrix veraltet; Regeneration ersetzt keine fachliche Review oder Modellabnahme. +The existing unit gate checks matrix freshness and catalogue completeness. New root inputs without scenario mapping fail. New subfields make the matrix stale; regeneration replaces neither domain review nor model acceptance. -## Fachliche Szenarien + +## Business scenarios -Jeder Fall beginnt mit einem Benutzerziel, nicht mit einer vollstaendigen tfvars. -Das Modell fragt gezielt fehlende Informationen, nennt keine erfundenen Defaults -und zeigt seine Annahmen. Pflichtangaben/Fachregeln entscheidet das Backend. +Every case starts with a user goal, not complete tfvars. The model asks specifically for missing information, names no invented defaults and shows its assumptions. Required information/domain rules are decided by the backend. -| ID | Bereich und Beispielziel | Rueckfragen, Beziehungen und erwarteter Nachweis | +| ID | Area and example goal | Follow-ups, relationships and expected evidence | | --- | --- | --- | -| A01 | Standalone und Grundlagen: Public-Einstieg fuer ein API-Team | Vorlage begruenden; Organisation/Owner aus autorisiertem Kontext statt erneut abfragen; Region, Namen, Codes, Labels und Contract-Namespace klaeren; Public explizit; unveraenderte Defaults erhalten. | -| A02 | Ordner und Rechte: bestehender Parent mit getrennten Teams | Parent, stabile Ordnerrollen, Anzeigenamen, Owner/Reader/Auditor-Zuordnungen; keine ownerlose Anlage; nichtleere Folder-Beschreibung ablehnen; Rechte nicht aus Freitext ableiten. | -| A03 | Management: Audit, Aufbewahrung und foederierter Login | Zentrale Observability, Audit-Routing und Archivierung, Object-Lock-Default, IdP-Konfiguration und Projektbeziehungen erklaeren; keine stille Aufbewahrungsaenderung. | -| A04 | Hub-and-Spoke/Multi-Area: Produktion und Forschung trennen | SNA-Adresspools, Transfernetze, Praefixe, DNS/Resolver, Corporate-Zuordnung und Bereichsidentitaeten; Ueberlappungen/Widersprueche nach Fachregeln erkennen; referenzierten Bereich nicht loeschen. | -| A05 | Multi-Region: eu01/eu02 ohne implizite Verbindung | Regionale Eingabeform, Bereiche, DNS-Zonen/Zuordnungen und Projekt-/Clusterreferenzen; single/regional nicht gleichzeitig aktiv exportieren; kein automatisches Inter-Region-VPN (#64). | -| A06 | Firewall-Infrastruktur: Appliances fuer Prod/Nonprod | Groesse, Zone, Netze, IPs und HA/CARP nach vorhandenem Root-Vertrag; Infrastruktur von Policy unterscheiden; keine Multi-Appliance-Policy zusagen (#65). | -| A07 | VPN: Office-Gegenstelle mit zwei Tunneln | Gegenstellen, Routingart, Routen/Subnetze und IKE/IPsec-Abhaengigkeiten; keine PSKs erfragen; aktuelle SNA-Reichweite (#85), BGP-Grenze (#86) und Inter-Region-Grenze aus qualifizierter Capabilityquelle erklaeren. | -| A08 | DevOps: Git-Service fuer private Teams | Erlaubte Netze, Plattformprojekt und Netzwerkbeziehungen; widerspruechliche Isolation gegen gemeinsam benoetigten Dienst aufloesen; keine unverdrahteten Dienste erfinden. | -| A09 | Kubernetes: regionaler Cluster mit Monitoring/KMS/Bastion | Node-Pools und Autoscaling, Bereiche, DNS/Gateway, Volumes/KMS, SSH/Bastion und Rollen schrittweise konfigurieren; private Erreichbarkeit (#37), regionale Zuordnung (#80), gekoppelte Bastion (#87) und Observability-Ort (#88) getrennt behandeln. | -| A10 | Projektarten und projektspezifische Dienste | Public/Corporate, Region/Bereich, stabile Kennung, Umgebung, Netzgroesse, Rollen/Custom Roles, Secrets Manager und Observability; Artwechsel mit Auswirkungen statt stiller Migration. Plattformentwurf bleibt von realen Application-Instanzen getrennt. | -| A11 | Sandbox: temporaere Teamumgebung | Name, Verantwortliche und zusaetzliche Owner; nur unterstuetzte Sandbox-Felder, keine erfundene automatische Laufzeitloeschung. | -| A12 | Namespace-Dienste: Policy und Demo im Plattformcluster | Cluster-/Projektbezug, DNS, Zugriff, Secrets-Integration, Policy-Modi, Break-glass, Labels/Annotations und optionale Demo-/Last-/Metrikfelder; Demo von Produktion trennen; regionale Grenzen erhalten. | -| A13 | Firewall-Policy und Bootstrap | Aliase, Regeln, Routing, NAT und Portforwarding sowie Endpoint/TLS, Benutzer und Erst-/Folgephase; erforderliche Bindings erklaeren, keine API-Secrets lesen und kein TLS-Bypass. | -| A14 | Application Landing Zone Templates | Autorisierte bestehende Versionen passend zum Bedarf auswaehlen oder neue Entwuerfe mit Parametern, Bindings, Regionen, Service-Einstellungen und Deployment-Policy erstellen; PE-Veroeffentlichung separat; bestehende Instanzen bleiben versioniert. | -| A15 | Bestehende Konfiguration gezielt anpassen | Workspace/Config und Revision erkennen; Ziele gegen Ist-Entwurf analysieren, fehlende Angaben nachfragen; unbekannte Felder sowie nicht gesetzt/null/konfiguriert erhalten; Gesamt-Diff und Topologie; veralteten Patch blockieren. | -| A16 | Geschuetzte Zugaenge und Injection | Geheimnisse weder erfragen noch an Modell senden; nur Anforderungen und autorisierte sichere Binding-Workflows; manipulierte Texte geben keine neuen Werkzeuge/Rechte; allgemeine Fremdaufgaben ablehnen. | -| A17 | Gespraech fortsetzen und Rechte erneut pruefen | Nach Wiederanmeldung/Backend-Neustart korrekt fortsetzen; Tenant/Workspace/Config/Rechte jedes Mal pruefen; Session-Widerruf und fremde IDs abweisen; Konfigurationsaenderungen transparent abgleichen. | -| A18 | Loeschung, Altersgrenze und Restore | Beide Elternloeschpfade samt Nachrichten/Zusammenfassungen/Vorschlaegen; laufende/spaete Inferenz darf Daten nicht wiederbeleben; drei Kalendermonate ab Erstellung, Monatsenden eingeschlossen; Aktivitaet verlaengert nicht; Cleanup/Restore ohne abgelaufene Daten. | -| A19 | Fuenf parallele Sitzungen und Modellfehler | Keine Kontextvermischung oder Requestverluste; begrenzte Queue, Provider-429/Timeout/Abbruch, begrenzte Reparaturversuche; manuelles Editieren bleibt moeglich; keine Geldgrenze, trotzdem technischer Missbrauchsschutz. | -| A20 | Wissen und Versionswechsel | Quellen und Modul-/Provider-/Config-Version binden; neue STACKIT-Funktionen nicht ungeprueft anbieten; Wissensupdate erkennen/geprueft promoten; unveraenderte Altversionen und kein automatisches Upgrade. | -| A21 | Workspace und Konfigurationsverwaltung | Im autorisierten Workspace neue/gespeicherte/importierte Config binden; Herkunft, Fork-/Repository- und Export-/Speicherworkflow erklaeren; unbekannte Felder erhalten; Repository-Speichern/Loeschen bleibt ausdrueckliche regulaere UI-Aktion, kein Modell-Git-Zugriff. | -| A22 | Application-Gruppen, Veroeffentlichung und Bestellungen | Sichtbare autorisierte Template-Versionen, Gruppenbeschraenkungen, Parameter/Bindings und Approval-Policy verwenden; Bestellungen/Instanzstatus erklaeren; keine Rechte vergeben, keine Instanz automatisch bestellen und keine Quoten-/Upgrade-Funktion erfinden. | -| A23 | Organisation, Credentials, Backend, Plan und Recovery | Organisations-/Rollen-/Einladungsprozesse sowie erforderliche Profile/Backend-Bindings erklaeren; nur freigegebene bereinigte Statusmetadaten, keine State-/Plan-/Credential-Rohdaten; Freigabe/Dispatch/Recovery/Unlock bleiben separate autorisierte UI-Aktionen. | -| A24 | Cloud-Kataloge, Topologie und Sprache | Autorisierte aktuelle Regions-/Service-Angebote mit Herkunft/Alter statt erfundener SKUs; bei fehlendem Angebot nachfragen; deterministische Topologie aus validiertem Entwurf; DE/EN-Dialog mit identischem Fachverhalten und stabilen technischen Kennungen. | - -## Dialogzustand und Fertigstellung - -1. Autorisierten Workspace und Konfigurationsentwurf binden, gegebenenfalls - regulären neuen Entwurf vor Vorlagenauswahl anlegen. Keine ungebundenen Chats. -2. Ziel, vorhandene Angaben, offene Fragen und widerspruechliche Anforderungen - als strukturierte Fakten mit Herkunft speichern; Aussagen sind keine Rechte. -3. Vorlage/Komponenten begruendet vorschlagen, Fragen nach Abhaengigkeiten - priorisieren. Explizite Antworten haben Vorrang vor Annahmen; sichere Defaults - muessen aus dem jeweiligen Vertrag stammen. Nicht immer erneut Identitaet fragen. -4. Plattform und Application-Template-Entwuerfe gemeinsam auf Konsistenz pruefen. - Mehrere Vorschlaege im Chat-Arbeitsentwurf sammeln, ohne Ausgangsconfig zu aendern. -5. Backend bewertet `fehlende Angaben`, `Widersprueche`, `vollstaendiger Entwurf` - und separat `Ausfuehrungsblocker`. Ein nicht erreichbarer privater Runner macht - keine korrekte Konfiguration unvollstaendig, aber die Ausfuehrung gesperrt. -6. Gesamt-Diff samt Auswirkungen/Topologie und Quellen anzeigen. Uebernahme - verlangt aktuelle Rechte, gleiche Basisrevision und ausdrueckliche Bestaetigung. - Git, Template-Veroeffentlichung, Plan und Apply bleiben getrennt. - -## Qualifikationsstufen - -### Lokaler Wissens- und Qwen-Spike (2026-10-10) - -`apps/api/src/assistant/knowledge.ts` erzeugt einen deterministischen lokalen -Metadaten-/Regelentwurf: alle 501 Katalogpfade mit Modus, Typ und Optionalitaet, -Vorlagen-ID/Quellhash ohne Vorlagenwerte sowie fuenf kuratierte Regeln mit -Quellverweisen. Der Kontext verlangt passenden Engine-Pin und Wissenshash und -eine begrenzte Auswahl bekannter Funktionsgruppen. Sensible Pfade enthalten -keine Werte und sind ausschliesslich Zugangsvoraussetzungen. - -Dieser Entwurf ist `local-draft-not-reviewed-release`: Der Hash bindet genau -diese Metadaten/Regeln, nicht den vollstaendigen Modulcode oder alle aktuellen -STACKIT-Dokumentationen. Vollstaendige Quellenaufnahme, Review/Promotion, -historische Wissenspakete und reale Dialogqualifikation stehen noch aus. Die -Quellverweise selbst sind keine Retrieval- oder Aktualitaetsnachweise. - -`apps/api/src/assistant/model-serving.ts` implementiert nur einen synthetischen -Public-Standalone-Spike, keinen allgemeinen Chat. Operator-Konfiguration: - -| Variable | Verhalten | +| A01 | Standalone and foundations: Public entry for an API team | Justify template; organization/owner from authorized context instead of asking again; clarify region, names, codes, labels and contract namespace; explicit Public; preserve unchanged defaults. | +| A02 | Folders and permissions: existing parent with separate teams | Parent, stable folder roles, display names, owner/reader/auditor assignments; no ownerless creation; reject nonempty folder description; do not derive permissions from free text. | +| A03 | Management: audit, retention and federated login | Explain central Observability, audit routing and archiving, Object Lock default, IdP configuration and project relationships; no silent retention change. | +| A04 | Hub-and-spoke/multi-area: separate production and research | SNA address pools, transfer networks, prefixes, DNS/resolver, Corporate assignment and area identities; detect overlaps/contradictions using domain rules; do not delete referenced area. | +| A05 | Multi-region: eu01/eu02 without implicit connection | Regional input form, areas, DNS zones/assignments and project/cluster references; do not actively export single/regional simultaneously; no automatic inter-region VPN (#64). | +| A06 | Firewall infrastructure: appliances for Prod/Nonprod | Size, zone, networks, IPs and HA/CARP under existing root contract; distinguish infrastructure from policy; promise no multi-appliance policy (#65). | +| A07 | VPN: office peer with two tunnels | Peers, routing type, routes/subnets and IKE/IPsec dependencies; ask for no PSKs; explain current SNA scope (#85), BGP limit (#86) and inter-region limit from qualified capability source. | +| A08 | DevOps: Git service for private teams | Permitted networks, platform project and network relationships; resolve contradictory isolation versus jointly required service; invent no unwired services. | +| A09 | Kubernetes: regional cluster with monitoring/KMS/bastion | Configure node pools and autoscaling, areas, DNS/gateway, volumes/KMS, SSH/bastion and roles incrementally; treat private connectivity (#37), regional assignment (#80), coupled bastion (#87) and Observability location (#88) separately. | +| A10 | Project types and project-specific services | Public/Corporate, region/area, stable key, environment, network size, roles/custom roles, Secrets Manager and Observability; type change with impacts instead of silent migration. Platform draft remains separate from real Application instances. | +| A11 | Sandbox: temporary team environment | Name, responsible people and additional owners; only supported sandbox fields, no invented automatic lifetime deletion. | +| A12 | Namespace services: policy and demo in platform cluster | Cluster/project reference, DNS, access, secrets integration, policy modes, break-glass, labels/annotations and optional demo/load/metrics fields; separate demo from production; preserve regional limits. | +| A13 | Firewall policy and bootstrap | Aliases, rules, routing, NAT and port forwarding plus endpoint/TLS, user and initial/subsequent phase; explain required bindings, read no API secrets and no TLS bypass. | +| A14 | Application Landing Zone templates | Select authorized existing versions fitting needs or create new drafts with parameters, bindings, regions, service settings and deployment policy; PE publication separate; existing instances remain versioned. | +| A15 | Targeted changes to existing configuration | Recognize workspace/config and revision; analyze goals against current draft, ask for missing information; preserve unknown fields and unset/null/configured distinctions; overall diff and topology; block stale patch. | +| A16 | Protected access and injection | Neither request secrets nor send them to model; only requirements and authorized secure binding workflows; manipulated texts grant no new tools/permissions; reject unrelated general tasks. | +| A17 | Continue conversation and recheck permissions | Continue correctly after re-login/backend restart; check tenant/workspace/config/permissions every time; reject session revocation and foreign IDs; transparently reconcile configuration changes. | +| A18 | Deletion, age limit and restore | Both parent deletion paths including messages/summaries/proposals; running/late inference must not resurrect data; three calendar months from creation, including month ends; activity does not extend; cleanup/restore without expired data. | +| A19 | Five parallel sessions and model errors | No context mixing or lost requests; bounded queue, provider 429/timeout/cancellation, bounded repair attempts; manual editing remains possible; no monetary cap, but technical abuse protection. | +| A20 | Knowledge and version changes | Bind sources and module/provider/config version; do not offer new STACKIT features unchecked; detect knowledge update/promote after review; unchanged old versions and no automatic upgrade. | +| A21 | Workspace and configuration management | Bind new/saved/imported config in authorized workspace; explain provenance, fork/repository and export/save workflow; preserve unknown fields; repository saving/deletion remains explicit regular UI action, no model Git access. | +| A22 | Application groups, publication and orders | Use visible authorized template versions, group restrictions, parameters/bindings and approval policy; explain orders/instance status; grant no permissions, order no instance automatically and invent no quota/upgrade feature. | +| A23 | Organization, credentials, backend, Plan and recovery | Explain organization/role/invitation processes and required profiles/backend bindings; only approved sanitized status metadata, no raw state/plan/credential data; approval/dispatch/recovery/unlock remain separate authorized UI actions. | +| A24 | Cloud catalogues, topology and language | Authorized current regional/service offerings with provenance/age instead of invented SKUs; ask if offering is missing; deterministic topology from validated draft; DE/EN dialogue with identical business behavior and stable technical identifiers. | + + +## Dialogue state and completion + +1. Bind authorized workspace and configuration draft; if needed, create a regular new draft before template selection. No unbound chats. +2. Store goal, existing information, open questions and contradictory requirements as structured facts with provenance; statements are not permissions. +3. Justify template/component proposals, prioritize questions by dependencies. Explicit answers take precedence over assumptions; safe defaults must come from the respective contract. Do not always ask for identity again. +4. Check platform and Application template drafts jointly for consistency. Collect multiple proposals in the chat working draft without changing source config. +5. Backend evaluates `missing information`, `contradictions`, `complete draft` and separately `execution blockers`. An unreachable private Runner does not make a correct configuration incomplete, but blocks execution. +6. Show overall diff with impacts/topology and sources. Adoption requires current permissions, same base revision and explicit confirmation. Git, template publication, Plan and Apply remain separate. + + +## Qualification stages + + + +### Local knowledge and Qwen spike (2026-10-10) + +`apps/api/src/assistant/knowledge.ts` generates a deterministic local metadata/rule draft: all 501 catalogue paths with mode, type and optionality, template ID/source hash without template values and five curated rules with source references. Context requires matching engine pin and knowledge hash and a bounded selection of known feature groups. Sensitive paths contain no values and are exclusively access prerequisites. + +This draft is `local-draft-not-reviewed-release`: the hash binds exactly this metadata/rules, not complete module code or all current STACKIT documentation. Complete source ingestion, review/promotion, historical knowledge packages and real dialogue qualification remain outstanding. Source references themselves are not retrieval or freshness evidence. + +`apps/api/src/assistant/model-serving.ts` implements only a synthetic Public standalone spike, not general chat. Operator configuration: + +| Variable | Behavior | | --- | --- | -| `LZC_MODEL_SERVING_TOKEN` | Bestehendes Terraform-/Deployment-Binding; Pflicht, nur Prozessumgebung. | -| `LZC_MODEL_SERVING_MODEL` | Default `Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`; betreiberseitig anpassbar. | -| `LZC_MODEL_SERVING_BASE_URL` | Default und derzeit einzig zugelassen `https://api.openai-compat.model-serving.eu01.onstackit.cloud/v1`; andere Endpoints brauchen ausdrueckliche Allowlist-/Sicherheitsqualifikation. | -| `LZC_MODEL_SERVING_TIMEOUT_MS` | Default 60000, begrenzt auf 1000..120000. | +| `LZC_MODEL_SERVING_TOKEN` | Existing Terraform/deployment binding; required, process environment only. | +| `LZC_MODEL_SERVING_MODEL` | Default `Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`; operator-configurable. | +| `LZC_MODEL_SERVING_BASE_URL` | Default and currently only permitted `https://api.openai-compat.model-serving.eu01.onstackit.cloud/v1`; other endpoints need explicit allowlist/security qualification. | +| `LZC_MODEL_SERVING_TIMEOUT_MS` | Default 60000, bounded to 1000..120000. | -Im App-Verzeichnis mit gepinntem Node 24 und sicher bereitgestelltem Binding: +In the app directory with pinned Node 24 and securely provided binding: ```sh npm run build:packages node --use-system-ca --import tsx scripts/assistant-spike.ts ``` -Kein Token im Kommandoargument, Chat, Git oder Frontend; keine Ausgabe roher -Terraform-Outputs zum Beschaffen des Tokens. Der bestehende Token muss sicher -in die lokale Prozessumgebung injiziert werden, nicht neu erzeugt oder rotiert. -Der Mac-Transfer enthaelt `.local/github-platform-applied.tfstate` und den -Originalschluessel `.local/platform/state.passphrase`, beide mit Modus `0600`. -Read-only-Zugriff wurde mit dem gepinnten OpenTofu 1.12.6 qualifiziert: in einem -leeren temporaeren Verzeichnis, vollstaendige Verschluesselungskonfiguration -ueber `TF_ENCRYPTION`, `output -json -state= model_serving_token`. -Ein Operator-Prozess faengt stdout ausschliesslich im Speicher ab und uebergibt -den JSON-dekodierten Token direkt als `LZC_MODEL_SERVING_TOKEN` an den Kindprozess. -Kein Terminal-Output des Tokens, kein Klartextfile, kein Remote-State-Pull und -keine Schluesselrotation. Der historische Snapshot wird dabei nicht veraendert; -sein Vorhandensein allein beweist keine aktuelle Gueltigkeit des Tokens. -Der Befehl prueft Matrixfrische und sendet ausschliesslich synthetische Daten. -Ausgabe sind nur Modell-/Wissensbindung, Laufzeit, bekannte Template-ID und -Anzahlen; keine Antworttexte oder Secrets. - -Der Client begrenzt Ausgabe und Responsegroesse, erlaubt keine Redirects oder -automatischen Retries und prueft JSON, Abschlussgrund, Template-ID, editierbare -Fragepfade und kuratierte Referenzen. Die synthetische Aufgabe verlangt -Standalone und den Public-/Corporate-Regelbezug. Fehler werden redigiert. -Das Ausgabebudget betraegt 4096 Tokens; die Schema-Grenzen stehen auch im Prompt, -insbesondere maximal acht priorisierte Fragen. Abgeschnittene Antworten oder -zu viele Fragen werden weiterhin abgewiesen, nicht stillschweigend gekuerzt. -Diese Pruefungen beweisen noch keine allgemeine semantische Zuverlaessigkeit -oder Prompt-Injection-Sicherheit fuer Kunden-Dialoge. - -Lokale Nachweise: sieben fokussierte Tests, einschliesslich Secret-Fragen, -erfundener/falscher Templates, Zusatz-Toolgrants, falscher Revision/Hashes, -429/JSON/Responsegroesse und Timeout ohne Retry. Kanonischer Gate: Lint, Typen, -Build, 444 Unit-Tests bestanden, 53 umgebungsgebunden uebersprungen. Der echte -CLI-Spike besteht nach sicherer Token-Uebergabe aus dem lokalen Snapshot: -`Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`, 11983 ms, `standalone`, acht Fragen, -fuenf Referenzen, `authorizesExecution=false`. Wissenshash: -`6fbe9d02cdb514f9c36ce39150a1ebc1aaa84c0d67a5dcf02a6a4cc2c8a1d370`, -Engine-Pin `a256f6896d11134fdc351786f1be5eba4e56b2e2`. -Fuenf einzeln gestartete synthetische Aufrufe: vier abgewiesen, einer akzeptiert; -keine automatischen Retries. Redigierte Diagnostik bestaetigte HTTP 200 und den -passenden Modellnamen. Zunaechst `finish_reason=length` bei 1200 Tokens; nach -Budgetkorrektur vollstaendiges JSON, aber 19 statt maximal acht Fragen. Die -expliziten Prompt-Limits beheben den zuletzt nachgewiesenen Vertragsfehler. -Die Einzelmessung ist keine Latenzzusage, Lastabnahme oder A01-A24-Qualifikation. - -Der urspruengliche Spike hatte keinen HTTP-Endpunkt oder Browserintegration. -Der folgende lokale Editor-Schritt ergaenzt einen begrenzten Dialog, ist aber -weiterhin keine vollstaendige A01-A24- oder Betriebsqualifikation. - -### Vorgelagerte Template-Beratung (2026-10-10) - -Das authentifizierte Panel `Template-Beratung` steht bereits auf -`Konfigurationen` und `Neue Konfiguration` bereit, ohne geoeffneten Entwurf. -`AssistantModelServing.adviseTemplates` verwendet begrenzte Historie und -backendgebundenen Wissensentwurf mit bekannten Template-IDs/Hashes und -Netzwerkbereich-/Firewallmetadaten. Antworten enthalten eine bekannte ID oder -`null`, maximal fuenf Rueckfragen, eine Erklaerung und bekannte Regelreferenzen. -Keine Rechte, Werkzeuge, Geheimnisse oder automatische Konfigurationserstellung. -Die Vorlagen sind unterschiedliche Startvorgaben derselben Engine; daraus folgt -keine pauschale Zusage vollstaendiger Feature-Unterstuetzung. - -`/api/v1/configurations/template-advice`: GET/POST/DELETE unter den bestehenden -Login-/Plattform-/Origin-/CSRF-Grenzen. Migration 054 persistiert ein persoenliches -Tenant-Gespraech mit unverlaengerbarer Drei-Kalendermonats-Frist. Erneute -Autorisierung und Revisionsvergleich nach Inferenz verhindern Wiederbelebung -geloeschter/abgelaufener Gespraeche und konkurrierendes Ueberschreiben. -`Vorlage ansehen` oeffnet ausschliesslich die vorhandene Vorschau. Keine -automatische Uebernahme von Gespraechsanforderungen in Editorwerte; Auswahl- -und Konfigurationsgespraech bleiben getrennt. Keine neuen Geld- oder -Gespeicherte-Gespraeche-Quoten; vorhandene 40-Nachrichten-/fuenf-Aktivanfragen- -Prozessgrenzen gelten. UI-Systemtexte bisher Deutsch; DE/EN-Paritaet offen. - -Nachweise: elf fokussierte Vertrags-/HTTP-/Modelltests, 448 Unit-Passes/53 Skips -plus Lint/Typen/Build, 33 PostgreSQL-Faelle, vier fokussierte Desktop-/Mobil- -Workflows mit Screenshots. Echter synthetischer HTTP-Dialog mit Standard-Qwen: -6757 ms/vier Rueckfragen/`null`, dann 3146 ms/`hub-and-spoke`/keine Rueckfragen; -vier persistierte Nachrichten, Reload 200, DELETE 204. Kein Benutzerentwurf -fuer diese Inferenz verwendet. Lokale Benutzer-DB auf 054 migriert, beide -vorhandenen Konfigurationen unveraendert. Matrix bleibt `not-qualified`: -zwei echte Antworten sind kein A01-A24-, Injection-, DLP-, Quellen-, -Restore-/Monatsend- oder Fuenf-Sitzungs-Lastnachweis. - -### Fortlaufender Firewall-Dialog (2026-10-13) - -Antworten zu Verkehrsregeln und unbekannter Kapazitaet setzen den bestehenden -Einrichtungsauftrag fort. Ein begrenzter Intent-Aufruf waehlt Belegkennungen -tatsaechlicher Nutzeraussagen statt frei formulierter Zitate. Eingebettete -Rueckfragen gelten nicht als Antworten. Unbekannter Durchsatz bleibt ein offener -Sizing-/Benchmark-Punkt, blockiert aber nicht die naechste Betriebsentscheidung. -Regelanforderungen und benannte Betreiber bleiben erhalten; bereits beantwortete -Verkehrs-/Betreiberfragen werden nicht wiederholt. Setup-Rueckfragen werden aus -geprueften deutschen Textbausteinen erzeugt, nicht aus internen Steuertexten. -Vorhandene Entwurfswerte sind weder Deployment- noch Speichernachweise. - -Nachweise: 173 Offline-Tests einschliesslich eines zusammenhaengenden -Fuenf-Schritt-Dialogs, 6 fokussierte PostgreSQL-Tests, Typpruefung und -Wissens-/Katalogfrische erfolgreich. 12/12 echte synthetische Firewall-Modellfaelle -mit Qwen als Antwort- und Intent-Modell erfolgreich, einschliesslich unbekannter -Kapazitaet, Fortsetzung bis zur letzten Betriebsantwort und enger HA-Feldaenderung. -Wissens-SHA256: `38f58c5895837f28583c834890698e567cae886da03210770b14fe7c9490c0e8`; -Suite-SHA256: `db75e65e906c3c030d0dc02fa5367f566c2e3a912e4897d82eb445c3f6c3b010`. -Dies ist eine synthetische Regression, kein Firewall-Leistungs-/SLA-Nachweis. - -Backend aktiviert; HTTPS-Healthcheck erfolgreich. Vollstaendige gespeicherte -Konfigurations- und Gespraechszeilen sind laut aggregierten Pruefsummen vor/nach -Aktivierung unveraendert. Keine automatische Vorschlagsannahme, Speicherung von -Kundenaenderungen oder Cloud-Ausfuehrung. - -### Konfliktbezogene lokale Uebernahme (2026-10-13) - -Die UI sendet beim Annahmepfad `draft`, `savedDraft` und die ausgewaehlten -Feldkennungen. Das Backend fuehrt einen Drei-Wege-Abgleich mit der aktuellen -gespeicherten Konfiguration durch: unabhaengige lokale und gespeicherte -Aenderungen bleiben erhalten. Migration057 speichert bei neuen Vorschlaegen -die freigegebenen Ausgangswerte. Eine andere Basis- oder Wissensrevision allein -blockiert nicht; Vorschlaege werden gegen den aktuellen Vertrag erneut geprueft. -Tatsaechliche Feldkonflikte liefern409 mit den pruefbaren Werten; manuelle -Editor-Konflikte zeigen nur Feldpfade, niemals geschuetzte Inhalte. Bestaetigung -ist an die exakt gepruefte gespeicherte Revision gebunden und muss bei erneuter -Aenderung wiederholt werden. Historische Vorschlaege ohne rekonstruierbaren -Ausgangswert verlangen ausdrueckliche Wertepruefung statt erfundener Baselines. - -Uebernahme aendert nur den Browserentwurf, nicht Konfigurations-/Gespraechszeilen; -Speichern bleibt ein gesonderter Schritt mit optimistischer Revisionspruefung. -Gespeicherte Vorschlaege bleiben bei Reload eines ungespeicherten Entwurfs erhalten. -Additive Rollenauftraege bewahren zwischenzeitlich hinzugefuegte Berechtigungen -und stellen bewusst manuell entfernte Altberechtigungen nicht ungefragt wieder her. -Chat/Rueckfragen bleiben bei lokalen Aenderungen nutzbar: nur freigegebene Werte -des lokalen Entwurfs werden als Modellkontext verwendet. Aufklappen reiner -Detailbereiche veraendert keine Werte; Objekt-Schluesselreihenfolge verursacht -keine falsche Dirty-Anzeige. Authentifizierung, Tenant-/Owner-RLS, Origin/CSRF, -gueltige Netz-/HA-Abhaengigkeiten und separate Cloud-Freigabe bleiben unveraendert. -Ohne die neuen Entwurfsparameter gilt der bisherige API-Speicherpfad unveraendert. - -Nachweis (2026-10-13):170 Offline-Assistententests,6 fokussierte PostgreSQL-Tests -und6 Desktop-/Mobil-Browsertests erfolgreich; Build, Typpruefung und -Wissens-/Katalogfrische erfolgreich. Die Browserpruefung deckt HA-Backup-Zone -eu01-2, zwischenzeitliche Editor-/Speicheraenderungen, Konfliktabbruch und -Bestaetigung sowie separates Speichern ab. DNS prueft eine echte TTL-Aenderung -von3600 auf7200 und blendet bereits vorhandene Werte aus. Die vorherige -10/10-Modellqualifikation betrifft die Firewall-Gespraechsfuehrung; der -Uebernahmepfad fuehrt keine neue Modellanfrage aus. - -Aktivierung: API und HTTPS-Proxy mit zusammengehoerigem UI-/Backend-Stand -gestartet; HTTPS-Healthcheck erfolgreich. Migration057 ist angewendet; die -beiden historischen Vorschlagsbaselines bleiben NULL. Anzahl und vollstaendige -Konfigurationszeilen sowie alle bisherigen Gespraechsspalten sind laut -aggregierten Pruefsummen unveraendert. Keine Vorschlagsannahme, Cloud-Ausfuehrung -oder automatische Speicherung echter Kundendaten bei der Aktivierung. - -### Feldweise Editor-Vorschlaege (2026-10-12) - -Ersetzt die nachfolgende historische Scalar-/Gesamtannahme-Grenze: DNS-, Ordner- -und SNA-Patches werden als einzelne geaenderte Felder mit gespeichertem Wert und -Vorschlag dargestellt, nicht als JSON-Block. Arrays wie Adressbereiche bleiben -ein gemeinsames Feld. POST `/api/v1/configurations/:id/assistant/accept` akzeptiert -optional `selectedFields` mit stabilen Feldkennungen aus dem bestehenden Vorschlag. -Ohne Auswahl gilt weiterhin die bisherige Gesamtannahme. Unbekannte, doppelte, -leere und veraltete Auswahlen werden abgewiesen. Die echte Annahme prueft Compiler, -Rollen, RLS und Revisionen innerhalb derselben Transaktion. Zusammenhaengende -Netzwerkpflichtfelder koennen nur als fachlich gueltige Kombination gespeichert -werden. Nicht ausgewaehlte Vorschlaege bleiben auf die neue Basisrevision gebunden; -keine erneute Modellanfrage erforderlich. - -Modellkontext: owner_email und organization_id gehoeren jetzt zu den begrenzten -Grundlagenwerten. Nur die aktuell verifizierte menschliche STACKIT-E-Mail des -aktiven Benutzers wird zusaetzlich bereitgestellt, keine fremde Identitaet oder -Anmeldecredentials. DNS-Kontakt: vorhandenen Kontakt erhalten, sonst Owner aus -gespeicherten Grundlagen, dann verifizierte Login-E-Mail als pruefbares Default -vorschlagen. Unbestaetigte Template-Platzhalter zaehlen nicht als bekannte Kontakte. -Explizite Kontaktangaben haben Vorrang; keine automatische Speicherung. -organization_id darf nur die vom Benutzer ausdruecklich angegebene bestehende UUID -sein: keine Tenant-Bindung, Zugriffsverifikation oder Cloud-Ausfuehrung. - -Grundlagenauftraege verwenden keine DNS-Rueckfragen/Netzwerkquellen. DNS-Mehrfeld- -und Grundlagenvorschlaege erhalten deterministische Abschluss-/Speicherhinweise -aus den validierten Feldern. Ihr vorlaeufiger Stream zeigt nur einen Pruefstatus, -keine ungeprueften Modellbehauptungen ueber angeblich gespeicherte Werte. -Die alten Grenzen und Nachweise unten bleiben historisch; #94/A01-A24 weiterhin -nicht vollstaendig qualifiziert. - -### Lokaler Editor-Chat (2026-10-10) - -Einstieg: anmelden, unter Konfigurationen eine gespeicherte aktuelle -Konfiguration oeffnen. Das Panel `Konfigurations-Chat` steht oberhalb des -Editors. Ungespeicherte Aenderungen sperren Sendung und Uebernahme. Antworten -und Rueckfragen erscheinen im Verlauf; ein separater kompletter Scalar-Diff -wird erst mit `Gesamten Vorschlag uebernehmen` zur neuen gespeicherten -Konfigurationsrevision. Keine Veroeffentlichung oder Infrastruktur-Ausfuehrung. - -Backend: GET/POST/DELETE `/api/v1/configurations/:id/assistant`, ausdrueckliche -Uebernahme ueber POST `/api/v1/configurations/:id/assistant/accept`. -Bestehende Plattformrechte, aktive Datenbank-Autorisierung, Tenant-/Owner-RLS, -Origin/CSRF und `no-store` gelten. Neue Migration 053 speichert ein Gespraech -je Benutzer und Konfiguration, maximal 40 Nachrichten. Ablauf ist UTC plus -drei Kalendermonate ab Erstellung; Runtime darf die Frist nicht aendern. -Elternloeschung kaskadiert; spaete Modellantworten pruefen Eltern-, Gespraechs- -und Konfigurationsrevision erneut. Ablauf-Cleanup erfolgt bei Zugriff, beim -API-Start und jede Minute; nach Offline-Zeiten vor neuem Zugriff bereinigen. -Restore kompletter Eltern-/Chat-Snapshots und Monatsend-/Lastfaelle sind noch -nicht als vollstaendige Betriebsabnahme qualifiziert. - -Der Modellkontext umfasst Metadaten/Regeln, bekannte nicht sensible -Root-Scalarwerte ohne ID-Felder und maximal zwoelf historische Nachrichten. -Keine vollstaendige Konfiguration, Terraform-State oder Credential-Bindings. -Erkennbare Secret-Zuweisungen werden vor Inferenz abgewiesen; diese Heuristik -ist kein allgemeiner DLP- oder Prompt-Injection-Nachweis. Niemals Zugangsdaten -im Chat eingeben. Maximal fuenf laufende Anfragen je API-Prozess, acht Fragen -und acht typgepruefte Scalar-Aenderungen; Timeout/Responsegrenze unveraendert. - -Bewusste Anfangsgrenze: keine Strukturmutation komplexer Komponenten, keine -Chat-Auswahl neuer Plattformvorlagen, kein Erstellen/Bearbeiten von Application -Template-Drafts und kein vollstaendiger Konfigurationsanalyse-Kontext. Diese -Anforderungen und die komplette Quellenaufnahme bleiben #94 zugeordnet. -Die bestehende Coverage-Matrix bleibt `not-qualified`, nicht aufgewertet. - -Reproduzierbarer lokaler Start mit vorhandenen privaten State-/Schluesseldateien: +No token in command arguments, chat, Git or frontend; no raw Terraform output to obtain the token. The existing token must be securely injected into the local process environment, not recreated or rotated. The Mac transfer contains `.local/github-platform-applied.tfstate` and original key `.local/platform/state.passphrase`, both mode `0600`. Read-only access was qualified with pinned OpenTofu 1.12.6: in an empty temporary directory, complete encryption configuration through `TF_ENCRYPTION`, `output -json -state= model_serving_token`. An operator process captures stdout exclusively in memory and passes the JSON-decoded token directly as `LZC_MODEL_SERVING_TOKEN` to the child process. No terminal token output, plaintext file, remote state pull or key rotation. The historical snapshot is not changed; its presence alone does not prove current token validity. The command checks matrix freshness and sends exclusively synthetic data. Output is only model/knowledge binding, runtime, known template ID and counts; no response texts or secrets. + +The client bounds output and response size, permits no redirects or automatic retries, and checks JSON, finish reason, template ID, editable question paths and curated references. The synthetic task requires standalone and the Public/Corporate rule relationship. Errors are redacted. Output budget is 4096 tokens; schema limits are also in the prompt, particularly at most eight prioritized questions. Truncated responses or excessive questions are still rejected, not silently shortened. These checks do not yet prove general semantic reliability or prompt-injection safety for customer dialogues. + +Local evidence: seven focused tests, including secret questions, invented/incorrect templates, additional tool grants, wrong revision/hashes, 429/JSON/response size and timeout without retry. Canonical gate: lint, types, build, 444 unit tests passed, 53 environment-bound skipped. Real CLI spike passes after secure token handover from local snapshot: `Qwen/Qwen3-VL-235B-A22B-Instruct-FP8`, 11983 ms, `standalone`, eight questions, five references, `authorizesExecution=false`. Knowledge hash: `6fbe9d02cdb514f9c36ce39150a1ebc1aaa84c0d67a5dcf02a6a4cc2c8a1d370`, engine pin `a256f6896d11134fdc351786f1be5eba4e56b2e2`. Five individually started synthetic calls: four rejected, one accepted; no automatic retries. Redacted diagnostics confirmed HTTP 200 and matching model name. Initially `finish_reason=length` at 1200 tokens; after budget correction, complete JSON but 19 instead of at most eight questions. Explicit prompt limits fix the last demonstrated contract error. This single measurement is no latency promise, load acceptance or A01–A24 qualification. + +The original spike had no HTTP endpoint or browser integration. The following local editor step adds bounded dialogue but is still not complete A01–A24 or operational qualification. + + +### Upstream template advice (2026-10-10) + +The authenticated `Template advice` panel is already available on `Configurations` and `New configuration`, without an open draft. `AssistantModelServing.adviseTemplates` uses bounded history and backend-bound knowledge draft with known template IDs/hashes and network-area/firewall metadata. Responses contain a known ID or `null`, at most five follow-up questions, explanation and known rule references. No permissions, tools, secrets or automatic configuration creation. Templates are different starting settings of the same engine; this does not imply a blanket promise of complete feature support. + +`/api/v1/configurations/template-advice`: GET/POST/DELETE under existing login/platform/Origin/CSRF boundaries. Migration 054 persists a personal tenant conversation with a non-extendable three-calendar-month lifetime. Renewed authorization and revision comparison after inference prevent resurrection of deleted/expired conversations and concurrent overwriting. `View template` opens only the existing preview. No automatic adoption of conversation requirements into editor values; selection and configuration conversations remain separate. No new monetary or saved-conversation quotas; existing 40-message/five-active-request process limits apply. UI system texts currently German; DE/EN parity outstanding. + +Evidence: eleven focused contract/HTTP/model tests, 448 unit passes/53 skips plus lint/types/build, 33 PostgreSQL cases, four focused desktop/mobile workflows with screenshots. Real synthetic HTTP dialogue with default Qwen: 6757 ms/four follow-ups/`null`, then 3146 ms/`hub-and-spoke`/no follow-ups; four persisted messages, reload 200, DELETE 204. No user draft used for this inference. Local user DB migrated to 054, both existing configurations unchanged. Matrix remains `not-qualified`: two real responses are no A01–A24, injection, DLP, source, restore/month-end or five-session load evidence. + + +### Continuing firewall dialogue (2026-10-13) + +Responses about traffic rules and unknown capacity continue the existing setup instruction. A bounded intent call selects evidence identifiers of actual user statements rather than freely phrased quotations. Embedded follow-ups do not count as answers. Unknown throughput remains an open sizing/benchmark point but does not block the next operating decision. Rule requirements and named operators are retained; answered traffic/operator questions are not repeated. Setup follow-ups are generated from checked German text modules, not internal control text. Existing draft values are evidence of neither deployment nor saving. + +Evidence: 173 offline tests including a continuous five-step dialogue, 6 focused PostgreSQL tests, type checking and knowledge/catalogue freshness successful. 12/12 real synthetic firewall model cases with Qwen as response and intent model successful, including unknown capacity, continuation to the final operating answer and narrow HA field change. Knowledge SHA256: `38f58c5895837f28583c834890698e567cae886da03210770b14fe7c9490c0e8`; suite SHA256: `db75e65e906c3c030d0dc02fa5367f566c2e3a912e4897d82eb445c3f6c3b010`. This is a synthetic regression, not firewall performance/SLA evidence. + +Backend activated; HTTPS health check successful. Complete saved configuration and conversation rows are unchanged according to aggregate checksums before/after activation. No automatic proposal acceptance, saving customer changes or cloud execution. + + +### Conflict-aware local adoption (2026-10-13) + +On acceptance, UI sends `draft`, `savedDraft` and selected field identifiers. Backend performs a three-way comparison with current saved configuration: independent local and saved changes are retained. Migration 057 stores approved baseline values for new proposals. A different base or knowledge revision alone does not block; proposals are rechecked against current contract. Actual field conflicts return 409 with reviewable values; manual editor conflicts show only field paths, never protected content. Confirmation is bound to the exact checked saved revision and must be repeated on another change. Historical proposals without reconstructable baseline require explicit value review rather than invented baselines. + +Adoption changes only the browser draft, not configuration/conversation rows; saving remains a separate step with optimistic revision checking. Saved proposals remain after reloading an unsaved draft. Additive role requests preserve permissions added meanwhile and do not unasked restore old permissions deliberately removed manually. Chat/follow-ups remain usable during local changes: only approved local-draft values are used as model context. Expanding detail-only sections changes no values; object-key ordering causes no false dirty indication. Authentication, tenant/owner RLS, Origin/CSRF, valid network/HA dependencies and separate cloud approval remain unchanged. Without new draft parameters, previous API save path applies unchanged. + +Evidence (2026-10-13): 170 offline Assistant tests, 6 focused PostgreSQL tests and 6 desktop/mobile browser tests successful; build, type checking and knowledge/catalogue freshness successful. Browser checking covers HA backup zone eu01-2, intervening editor/save changes, conflict cancellation and confirmation, and separate saving. DNS checks a real TTL change from 3600 to 7200 and hides already existing values. Previous 10/10 model qualification concerns firewall conversation management; adoption path makes no new model request. + +Activation: API and HTTPS proxy started with matching UI/backend status; HTTPS health check successful. Migration 057 is applied; both historical proposal baselines remain NULL. Count and complete configuration rows and all previous conversation columns are unchanged according to aggregate checksums. No proposal acceptance, cloud execution or automatic saving of real customer data during activation. + + +### Fieldwise editor proposals (2026-10-12) + +Replaces the following historical scalar/whole-acceptance boundary: DNS, folder and SNA patches are displayed as individual changed fields with saved value and proposal, not a JSON block. Arrays such as address ranges remain one field. POST `/api/v1/configurations/:id/assistant/accept` optionally accepts `selectedFields` with stable field identifiers from the existing proposal. Without selection, previous whole acceptance still applies. Unknown, duplicate, empty and stale selections are rejected. Actual acceptance checks compiler, roles, RLS and revisions in the same transaction. Related mandatory network fields can be saved only as a domain-valid combination. Unselected proposals remain bound to the new base revision; no new model request needed. + +Model context: owner_email and organization_id now belong to bounded foundations values. Only the active user's currently verified human STACKIT email is additionally provided, no foreign identity or login credentials. DNS contact: retain existing contact, otherwise suggest owner from saved foundations, then verified login email as reviewable default. Unconfirmed template placeholders do not count as known contacts. Explicit contact information takes precedence; no automatic saving. organization_id may only be the existing UUID explicitly supplied by the user: no tenant binding, access verification or cloud execution. + +Foundations requests use no DNS follow-ups/network sources. DNS multi-field and foundations proposals receive deterministic completion/saving notices from validated fields. Their preliminary stream shows only checking status, no unchecked model claims about allegedly saved values. Old limits and evidence below remain historical; #94/A01–A24 are still not fully qualified. + + +### Local editor chat (2026-10-10) + +Entry: sign in and open a saved current configuration under Configurations. The `Configuration chat` panel is above the editor. Unsaved changes block sending and adoption. Responses and follow-ups appear in history; a separate complete scalar diff becomes the new saved configuration revision only through `Accept entire proposal`. No publication or infrastructure execution. + +Backend: GET/POST/DELETE `/api/v1/configurations/:id/assistant`, explicit adoption through POST `/api/v1/configurations/:id/assistant/accept`. Existing platform permissions, active database authorization, tenant/owner RLS, Origin/CSRF and `no-store` apply. New migration 053 saves one conversation per user and configuration, at most 40 messages. Expiry is UTC plus three calendar months from creation; runtime may not change the deadline. Parent deletion cascades; late model responses recheck parent, conversation and configuration revisions. Expiry cleanup occurs on access, API startup and every minute; after offline periods, clean up before new access. Restore of complete parent/chat snapshots and month-end/load cases are not yet qualified as complete operational acceptance. + +Model context comprises metadata/rules, known non-sensitive root scalar values without ID fields and at most twelve historical messages. No full configuration, Terraform state or credential bindings. Recognizable secret assignments are rejected before inference; this heuristic is not general DLP or prompt-injection evidence. Never enter credentials in chat. At most five running requests per API process, eight questions and eight type-checked scalar changes; timeout/response limit unchanged. + +Deliberate initial boundary: no structural mutation of complex components, no chat selection of new platform templates, no creation/editing of Application template drafts and no complete configuration-analysis context. These requirements and complete source ingestion remain assigned to #94. Existing coverage matrix remains `not-qualified`, not upgraded. + +Reproducible local startup with existing private state/key files: ```sh LZC_STACKIT_CLI_CLIENT_APPROVED=true npm run dev:chat ``` -Gepinntes Node/npm verwenden. Dieser Start benutzt den vorhandenen lokalen -Login-Starter: neue Migrationen und lokale DB-Rollenpasswortrotation beim -Neustart; Benutzer hat diese lokalen Arbeiten dauerhaft freigegeben. Keine -Modeltoken-/Artifact-Key-Rotation, keine Runner-Aktivierung. Produktionsstart -bleibt opt-in mit `LZC_ASSISTANT_ENABLED=true` und geschuetztem Operator-Binding. - -Nachweise: zehn fokussierte Unit-/HTTP-Faelle; kanonischer Gate Lint/Typen/Build, -447 Unit-Passes und 53 umgebungsgebundene Skips; 32 echte PostgreSQL-Faelle. -Vier fokussierte Desktop-/Mobilfaelle fuer Chat und benachbarte Speicherung -bestanden mit `--workers=1 --timeout=60000` (je ca. 1-2 Sekunden). Parallel -traten Desktop-Neulade-/Browser-Session-Timeouts auf; Last-/CI-Budget bleibt -offen. Screenshots geprueft, kein Seitenoverflow; Diff auf Mobil intern scrollbar. -Echter synthetischer autorisierter HTTP-Dialog auf isolierter Testdatenbank: -HTTP 200 in 2649 ms, zwei gespeicherte Nachrichten, ein Vorschlag, null weitere -Fragen; Fortsetzung und ausdrueckliche Uebernahme als Revision 2 bestaetigt. -Keine Benutzerkonfiguration fuer diese Inferenz verwendet. - -Lokale Benutzerumgebung danach freigegeben aktiviert: API 3000, Preview 4181, -Callback 8000, Migrationen 051-053 angewendet. Anzahl und Inhalts-/Revisions- -pruefsumme der vorhandenen Konfiguration vor/nach Start identisch. UI/Health -200, anonymer Chat 401. Manuelle Dialogabnahme auf Benutzerkonfiguration offen; -im geteilten Browser vorhandene Sitzung, aber Seite fuer Klick nicht sichtbar. - -- Katalog-/Matrixfrische: lokal automatisch pruefbar, kein Modellaufruf. -- Deterministischer Vertrag: Schema, Compiler, Template-Policy, Rechte, Revision, - Lifecycle und Redaction mit isolierten Unit-/DB-/Browserfaellen pruefen. -- Echte Modell-Evaluation: A01-A24 mit reproduzierbaren Aufgaben und pro Feld - belegter Abdeckung, einschliesslich realistischer komplexer Kombinationen. - Inferenz muss ueber den vorhandenen geschuetzten Dev-Zugang qualifiziert werden. -- Betriebsabnahme: Loesch-/Restore-Grenzen und fuenf Sitzungen messen. Antwortzeit- - Ziele anhand des Spikes festlegen; keine erfundene Latenzzusage. - -Grenz-Referenzen sind bekannte Befunde, keine Garantie ihres heutigen Zustands. -Vor Modellfreigabe sind sie gegen den jeweils qualifizierten Source-/Capability- -Stand erneut zu pruefen. Nachweise und Messungen werden #94 zugeordnet; fehlende -KI-Qualifikation blockiert die Behauptung vollstaendiger 1:1-Unterstuetzung. \ No newline at end of file +Use pinned Node/npm. This startup uses the existing local login starter: new migrations and local DB role password rotation on restart; user has standing approval for this local work. No model-token/artifact-key rotation, no Runner activation. Production startup remains opt-in with `LZC_ASSISTANT_ENABLED=true` and protected operator binding. + +Evidence: ten focused unit/HTTP cases; canonical gate lint/types/build, 447 unit passes and 53 environment-bound skips; 32 real PostgreSQL cases. Four focused desktop/mobile cases for chat and adjacent saving passed with `--workers=1 --timeout=60000` (approx. 1–2 seconds each). Desktop reload/browser-session timeouts occurred in parallel; load/CI budget remains open. Screenshots checked, no page overflow; diff internally scrollable on mobile. Real synthetic authorized HTTP dialogue on isolated test database: HTTP 200 in 2649 ms, two saved messages, one proposal, zero further questions; continuation and explicit adoption as revision 2 confirmed. No user configuration used for this inference. + +Local user environment then activated with approval: API 3000, preview 4181, callback 8000, migrations 051–053 applied. Count and content/revision checksum of existing configuration identical before/after startup. UI/health 200, anonymous chat 401. Manual dialogue acceptance on user configuration outstanding; existing session in shared browser, but page not visible for clicking. + +- Catalogue/matrix freshness: automatically checkable locally, no model call. +- Deterministic contract: check schema, compiler, template policy, permissions, revision, lifecycle and redaction with isolated unit/DB/browser cases. +- Real model evaluation: A01–A24 with reproducible tasks and evidenced per-field coverage, including realistic complex combinations. Inference must be qualified through existing protected dev access. +- Operational acceptance: measure deletion/restore boundaries and five sessions. Set response-time goals from the spike; no invented latency promise. + +Limitation references are known findings, not a guarantee of their present state. Before model release, they must be rechecked against the qualified source/capability status. Evidence and measurements are assigned to #94; missing AI qualification blocks claiming complete 1:1 support. diff --git a/landing-zone-configurator/docs/assistant-knowledge/README.de.md b/landing-zone-configurator/docs/assistant-knowledge/README.de.md new file mode 100644 index 0000000..2338b83 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/README.de.md @@ -0,0 +1,497 @@ + + +# Assistant-Servicewissen + +[English](README.md) | [Deutsch](README.de.md) + +Englisch ist die kanonische, maschinell eingelesene Themensprache. +Deutsche Themenbegleiter sind ausschliesslich menschliche Lesefassungen; +das Manifest liest sie nicht ein. Der Katalog unten bietet Sprachwechsel, +ohne kuratierte Prompt-Quellen zu aendern. + + + +## Architekturvertrag + +Freigegebene Architektur vom 2026-10-10: kuratiertes Markdown je Domaene/Service, +striktes Manifest und generiertes Backend-Bundle. +Das urspruengliche SNA-/Zugangsdaten-Paar wird zum vollstaendigen +Themenkatalog unten erweitert. +Kein automatisches Einlesen beliebiger Dokumentation, Websites, Kundendateien, +States, Plaene oder Secrets. +Markdown erklaert Faehigkeiten; Accelerator-Eingabeschemas, Patch-Validierung +und gemeinsamer Compiler entscheiden, was konfigurierbar ist. +Wissen erteilt niemals Berechtigungen oder neue Features. + +Massgebliche Quellen: + +- `manifest.json`: stabile Themen-ID, Markdown-Datei, Themenversion, + Pruefdatum, lokale Qualifikation, Feature-Gruppen, Pflichtkennzeichen, + abgedeckte Root-Eingaben, Abhaengigkeiten, lokale massgebliche Quellpfade, + externe Referenzen und A01-A24-Szenario-IDs. +- Themen-Markdown: kuratierte Servicefakten, Dialoganforderungen und Beispiele. +- Generierte `knowledge-topics.generated.ts`: deploybarer Snapshot mit + Themen-/lokalen Quell-SHA-256-Hashes, Engine-Revision und Inhalt. + Nicht manuell bearbeiten. +- `knowledge.ts`: deterministische Auswahl, globale Regeln, generierte + Feldmetadaten, Template-Metadaten und vollstaendiger Bundle-Hash. + +Editor-Dialog verwendet gewaehlte Feature-Gruppen und deren +Themenabhaengigkeiten. +Zugangsdaten-Grundlagen und Konfigurationslebenszyklus sind immer enthalten. +Template-Beratung erhaelt die begrenzte vollstaendige Themenmenge. +Aktuelle Editor-Anfragen waehlen alle Feature-Gruppen, daher stehen alle +19 Themen bereit; dies ist kein semantisches Retrieval je Nachricht. +Abhaengigkeiten waehlen Wissen aus, aktivieren keine Services. +Es gibt keine Vektordatenbank, modellgesteuertes Retrieval oder +Laufzeit-Dateisystemzugriffe auf Dokumentation. +Das kompilierte API-Artefakt enthaelt den generierten Snapshot. +Thementext wird einmal als vertrauenswuerdige kuratierte Regeln geliefert; +Provenienz bleibt getrennt. +Kundeneingaben/-historie und PIM-Labels bleiben nicht vertrauenswuerdige +Daten, keine Anweisungen. + + + +### Vertrag zur Themenauslieferung + +Der generische Editor-Vorschlagspfad uebergab zuvor Themen-/Feldmetadaten +ohne kuratierte Regeltexte. +Das betraf alle 14 Themen mit nativen Editor-Vorschlaegen, nicht nur DNS. +Editor-Vorschlaege und Gespraechsberatung teilen jetzt dieselbe Themenabgrenzung: +aktuelles Thema, transitive Abhaengigkeiten, Pflichtthemen und alle globalen +Regeln. +Themenuebergreifende Editor-Vorschlaege enthalten auch die zustaendigen Themen +jedes exponierten Felds. +Nicht betroffene Thementexte bleiben ausserhalb des Antwortkontexts. +Fehlende Abhaengigkeiten fuehren explizit zum Fehler; eine eingeschraenkte +Feature-Gruppenauswahl bleibt erhalten. + +Absichtsklassifikation erhaelt bewusst Themenzusammenfassungen, nicht das +vollstaendige Beratungswissen. +Firewall-Evidenzklassifikation erhaelt ausschliesslich Nutzeraussagen. +Deterministische Felduebersichten und die Policy-Grenze verwenden gepruefte +lokale Vertraege ohne zweiten Modellaufruf. +Starttemplate-Beratung und synthetische Qualifikation behalten ihre +vollstaendigen ausgewaehlten Regeltexte. + +Regressionstests pruefen die tatsaechlich ausgehenden Modellanfragen fuer +alle 19 Beratungsthemen und alle 14 Editor-Themen, einschliesslich exakter +Volltexte, indirekter Abhaengigkeiten, Pflicht-/globaler Regeln, +Ausschluss nicht betroffener Themen und themenuebergreifender Vorschlaege. +Diese Tests mit simuliertem Transport beweisen Wissensauslieferung, +nicht faktische Qualitaet einer echten Modellantwort oder +Ausfuehrungsqualifikation. +DNS-Hinweise unterscheiden Primary-/Secondary-Rollen von Sichtbarkeit, +erklaeren beide als autoritativ und benennen das unvollstaendige native +Secondary-Server-Setup. + + + +### Qualifikation mit echtem Modell + +Aenderungen an Servicefakten, Prompts, Wissensauswahl oder +Komponentenvertraegen benoetigen gezielte synthetische Tests gegen +die konfigurierten echten STACKIT-Modelle, nicht nur simulierte Antworten. +Jeden betroffenen Fall mindestens zweimal unabhaengig ausfuehren: + +```sh +npm run test:assistant:live -- --topic dns-zones --repeat 2 +npm run test:assistant:journey +``` + +Fuer reine Arbeitsplatz-Zugangsdaten `--local-credentials` anhaengen; +niemals Tokens in Befehle oder Test-Fixtures einfuegen. +Dies liest das dedizierte Testtoken aus dem privaten authentifiziert +verschluesselten Plattform-Recovery-Snapshot ausschliesslich im Speicher; +es faellt niemals auf das Anwendungstoken zurueck. +Provisionierung und expliziter CI-Transfer sind im +[Infrastruktur-Runbook](../../infra/ci/README.de.md) beschrieben. +Der Harness lehnt aktivierte Ausfuehrung ab, verwendet synthetische +Identitaeten/Konfigurationsentwuerfe und ruft niemals Plan/Apply auf. +Vorschlaege werden lokal angewendet, per JSON rundgereicht und als native +tfvars exportiert. +Nachweise binden Ergebnisse an Modell-IDs, Wissens-/Suite-Hashes, +Iteration und Export-Pruefsummen. +Jede fehlgeschlagene Iteration bleibt ein Fehler; Wiederholungen sind keine +Retries. Der Harness erlaubt eine bis drei Iterationen und taktet +Modellanfragen. +CI verwendet fuer Antwort- und Intent-Modell die Anwendungsdefaults, +ohne CI-exklusiven Klassifikator-Override. +Effektive Modell-IDs stehen in jedem Nachweis. +Qualifikation eines alternativen Modells qualifiziert nicht das +konfigurierte Anwendungsmodell. + +Beschreibungen von Intent- und Evidenzschemas werden auch im Systemkontext +des Klassifikators gesendet, nicht nur als Structured-Decoding-Beschraenkung. +Antwortgenerierung erhaelt geprueftes Feld-/Themenwissen ohne zweiten +vollstaendigen Schema-Dump. +Fuer eine explizit benannte zusaetzliche DNS-Zone sind quellengebundene +angeforderte Felder im Vorschlagsschema dieser Zone verpflichtend. +Ein angeforderter Kontakt darf weder nur in der Erklaerung genannt noch +still weggelassen werden; Felder fuer eine Zone sind nicht in anderen +Zonen verpflichtend. +Laufzeitpruefungen fuer Quelle, Umfang und native Konfiguration bleiben +bestehen. + +DNS-Faelle pruefen Rollenbedeutung, autoritative Antworten, +Trennung von Sichtbarkeit, Primary-Empfehlung, unvollstaendiges natives +Secondary-Setup, Korrektur frueherer Falschaussagen und Erhalt beim +Hinzufuegen einer Zone. +Semantische Pruefungen lehnen irrefuehrende Antworten und reine +Schlagwortantworten ab, bleiben aber begrenzte Regressionskriterien +statt Beweis universeller faktischer Korrektheit. +Die kontinuierliche themenuebergreifende Reise prueft auch die +DNS-Erklaerung nach frueheren Konfigurationsschritten und dass Beratung +den Entwurf nicht veraendert. + +Release-Builds haengen vom wiederverwendbaren Live-Workflow ab: +Alle Themen laufen zweimal, danach folgt der kontinuierliche Dialog, +auch wenn einzelne Modellfaelle scheitern. +Rohe synthetische Nachweise bleiben CI-Artefakte. +Promotion benoetigt erfolgreiche Live-Qualifikation und Build-Job des +Original-Builds; aeltere Builds ohne diesen Nachweis koennen Qualifikation +nicht umgehen. +Fehlendes Token, nicht verfuegbares Modell oder fehlgeschlagenes Kriterium +blockieren Qualifikation, kein stilles Ueberspringen. +Allgemeine Beratung beendet ihren zusammengefuehrten vertrauenswuerdigen +Systemkontext mit einer expliziten Anweisung zur Antwortvollstaendigkeit: +Die Erklaerung muss die tatsaechlich angeforderten Fakten, nativen Defaults, +Grenzen und Ausschluesse enthalten, nicht nur eine fehlende Liste +ankuendigen oder auf Vertragsmetadaten verweisen. +Rueckfragen ersetzen keine faktische Antwort. +Kompakte Stichpunkte je Feldfamilie zielen auf hoechstens 2400 Zeichen +innerhalb des unveraenderten 3000-Zeichen-Antwortschemas. +Gleichwertige regionale Formen gruppieren, statt sie bis zum Abschneiden +zu wiederholen. +Reine Informationsuebersichten zu Feldern/Defaults/Grenzen benoetigen keine +Konfigurationsentscheidungen und liefern keine Rueckfragen; +andere Beratung erfragt weiterhin nur fehlende fachliche Entscheidungen, +niemals geschuetzte Eingaben. +Der begrenzte Firewall-Anforderungsdialog behaelt seinen eigenen +Kurzantwortvertrag. +Transporttests pruefen Auslieferung dieser Anweisung; faktische Kriterien +am echten Modell entscheiden weiter ueber Qualifikation der Antworten. + +Fuer native Felduebersichten waehlt semantische Absichtsklassifikation +die bestehende Antwort aus geprueften Metadaten, sofern verfuegbar, +statt denselben statischen Vertrag erneut generieren zu lassen. +VPN, DevOps Git und DNS-Feld-/Rollensemantik verwenden diesen Pfad mit +getesteter 2400-Zeichen-Grenze, ohne Fragen oder Entwurfsaenderungen, +mit nativen Routing-/Plan-Defaults und getrennter geschuetzter PSK-Bindung. +Das faktische Orakel fordert diese Details und lehnt erfundene +`static`-/`dynamic`-Routing-Typen ab. +DevOps verlangt native Felder und die Grenze `git_flavor=null` +(keine Instanz), ohne einen aktivierten Default zu suggerieren. +Dies ersetzt weder aktuelle Verfuegbarkeitspruefungen noch autorisiert es +Konfiguration; nicht unterstuetzte Uebersichtsthemen behalten den +Beratungspfad. +DNS-Rollenerklaerungen behalten die bestehenden Kriterien zu +Primary/Secondary, autoritativer Rolle, Sichtbarkeit und nativer +Secondary-Konfigurationsgrenze bei, einschliesslich Korrektur frueherer +irrefuehrender Beratung. +Tatsaechliches DNS-Setup erfolgt weiter ueber den bestehenden pruefbaren +Vorschlagsablauf. + +CI benoetigt `LZC_MODEL_SERVING_TOKEN` in der geschuetzten Umgebung +`assistant-tests`. +Lokale Nachweise zertifizieren diese entfernte Umgebung nicht und +autorisieren kein Deployment. +CI-Qualifikationsjobs teilen eine nicht abbrechende Concurrency-Gruppe, +um konkurrierende Modellanfragen manueller und Release-Laeufe zu vermeiden. +Faktische Kriterien bei neuen Faehigkeiten pruefen/erweitern; +offene oder mehrdeutige Antworten benoetigen weiter menschliche Pruefung. + + + +### Evidenz und Release-Status + +Laufspezifische Ergebnisse gehoeren in quellengebundene Nachweise, +CI-Artefakte und den zugehoerigen Pull Request, nicht in ein permanentes +oeffentliches Abnahmeverzeichnis. +Fehlgeschlagene Experimente als Evidenz erhalten. +Ein spaeterer erfolgreicher Lauf qualifiziert nur seine eigene Quelle, +loescht keinen frueheren Fehler und zertifiziert kein anderes Deployment. +Der geschuetzte Release-Workflow wiederholt Qualifikation fuer seinen +exakten Build; lokale Ergebnisse allein autorisieren niemals Promotion +oder Deployment. + + + +## Vollstaendiger Themenkatalog + +| Thema | Umfang | Sprachen | +| --- | --- | --- | +| credential-foundations | Provider-, Workload- und native Ausfuehrungsbindungen | [EN](credential-foundations.md) / [DE](credential-foundations.de.md) | +| identity-foundations | Organisation, Owner, Namen/Codes, Region, Labels, Uebergabe-Namespace | [EN](identity-foundations.md) / [DE](identity-foundations.de.md) | +| governance-folders | Eltern, Ordnerrollen, Ownership und Audit-Rechte | [EN](governance-folders.md) / [DE](governance-folders.de.md) | +| management-state | Verpflichtendes Management-Projekt, State, Secrets Manager und Betriebsidentitaeten | [EN](management-state.md) / [DE](management-state.de.md) | +| observability | Zentrale, Projekt- und Cluster-Telemetrie/Aufbewahrung | [EN](observability.md) / [DE](observability.de.md) | +| audit-logs | Routing, Archiv, Object Lock und Umfang | [EN](audit-logs.md) / [DE](audit-logs.de.md) | +| federated-identities | Issuer/Assertions fuer Management-Betriebsidentitaet | [EN](federated-identities.md) / [DE](federated-identities.de.md) | +| stackit-network-components | SNA, Pools, Transfer, Praefixe und regionale Formen | [EN](sna.md) / [DE](sna.de.md) | +| dns-zones | Area-Zonen, Resolver-Auswahl und DNS-Abhaengigkeiten | [EN](dns-zones.md) / [DE](dns-zones.de.md) | +| firewall-infrastructure | OPNsense-Appliance, LAN/WAN, Zonen, Dimensionierung und HA | [EN](firewall-infrastructure.md) / [DE](firewall-infrastructure.de.md) | +| firewall-policy | Aliases, Routen, Regeln, NAT und Port-Forwards | [EN](firewall-policy.md) / [DE](firewall-policy.de.md) | +| firewall-access-bootstrap | Administration, API-Bindungen und Bootstrap-Phasen | [EN](firewall-access-bootstrap.md) / [DE](firewall-access-bootstrap.de.md) | +| vpn | Gateway/Plan, Peer/Tunnel, Routing und IKE-/IPsec-Grenzen | [EN](vpn.md) / [DE](vpn.de.md) | +| devops-git | Managed-Git-Service und ACLs | [EN](devops-git.md) / [DE](devops-git.de.md) | +| platform-kubernetes | SKE/Node-Pools, DNS, Monitoring, KMS und Bastion | [EN](platform-kubernetes.md) / [DE](platform-kubernetes.de.md) | +| project-templates | Public-/Corporate-Projekte, Rollen, Services und Anwendungsparameter | [EN](project-templates.md) / [DE](project-templates.de.md) | +| sandbox-projects | Sandbox-Ownership und native Projektliste | [EN](sandbox-projects.md) / [DE](sandbox-projects.de.md) | +| namespace-services | Namespace/RBAC, Secret-Policies, Break-Glass und explizite Demos | [EN](namespace-services.md) / [DE](namespace-services.de.md) | +| configuration-lifecycle | Workspace, Beratungsuebergabe, Revision/Ablauf, Versionen und Ausfuehrungsgates | [EN](configuration-lifecycle.md) / [DE](configuration-lifecycle.de.md) | + +Jede aktuelle Root-Eingabe hat mindestens ein Manifest-Thema; +der Generator lehnt fehlende/unbekannte Eingaben ab. +Der bestehende Katalog mit 501 Pfaden bleibt die Feldautoritaet. +Eine Root-Zuordnung beweist keinen qualifizierten Dialog fuer jedes +verschachtelte Feld. +A01-A24-Zuordnungen decken den Szenariokatalog ab, nicht erfolgreiche Tests +fuer alle Szenarien. +Neue Root-Eingaben benoetigen explizite gepruefte Themenzuordnungen. +Neue Child-Moduloptionen benoetigen weiterhin verifizierte +Root-Verdrahtung, bevor sie beworben werden. + +Template-Werte sind niemals Nutzerzustimmung zur Konfiguration oder +Aktivierung optionaler Services. +Firewall spaeter bedeutet nicht Firewall jetzt deployen. +Bestehende geerbte Einstellungen von angeforderten Aenderungen unterscheiden +und inkompatible Einstellungen kennzeichnen. +Ein vollstaendiger nativer Apply umfasst weiter Pflichtgrundlagen und +jede aktivierte Komponente; ein fokussierter Chatschritt ist keine +gezielte Terraform-Ausfuehrung. + + + +## Feste Themenstruktur + +Jedes Thema muss einen H1-Titel und diese H2-Abschnitte in dieser Reihenfolge +haben. Keine Abschnitte hinzufuegen, umbenennen oder weglassen; +bei Bedarf H3 innerhalb eines Abschnitts verwenden. +Die maschinelle englische Vorlage bleibt unveraendert: + +```markdown +# Service Name + +## Purpose +User needs this service can solve. + +## Accelerator Contract +Native fields, supported forms and compiler/patch restrictions. + +## Dependencies +Relationships to other components and declared topic dependencies. + +## Dialogue +Business questions, existing-context reuse and permissible assumptions. + +## Examples +Synthetic user requirement and native configuration, never secret values. + +## Limits +Unsupported capabilities and separate validation/execution gates. + +## Credentials +Required external bindings and safe workflow, never credential values. + +## Sources +Interpretation of manifest references, review triggers and existing tests. +``` + +Praezise Fakten schreiben, keine umfassende Enzyklopaedie. +Mathematische Ableitung, Nutzerannahmen, implementierte Funktionalitaet und +aktuelle Betriebsfakten trennen. +Listen aktueller SKUs, Preise, Flavors und Versionen gehoeren in autorisierte +aktuelle Kataloge und oeffentliches PIM, nicht in kopierte statische Tabellen. +Servicespezifische Bindungen muessen mit dem nativen Accelerator-Vertrag +funktionieren, nicht von verstecktem Configurator-Zustand abhaengen. +Beispiele ohne Kundenkennungen oder Secrets verwenden. +Bestehende unbekannte Importfelder muessen ausserhalb des Modellkontexts +erhalten bleiben. + + + +## Thema hinzufuegen + +1. Zuerst Accelerator-/Modul- und gemeinsame Feature-Vertraege pruefen. + Fehlende Features benoetigen Konzept, Modul/Schema, Validierung, + Import/Export, Editor, Assistant, Zugangsdaten und Tests, + nicht nur eine Wissensdatei. +2. Thema mit obiger Struktur anlegen, danach Manifest-Eintrag. + Bestehende Dokumentation als massgebliche Quellen wiederverwenden, + statt jedes Detail zu duplizieren. +3. Bestehende Root-Eingaben, Feature-Gruppen und A01-A24-Szenarien zuweisen. + Explizite Abhaengigkeits-IDs ergaenzen; unbekannte Abhaengigkeiten und + Zyklen scheitern. + Verpflichtende Zugangsdaten-Grundlagen und Konfigurationslebenszyklus + duerfen nicht entfernt werden. + IDs globaler Vertragsregeln nicht als Themen-IDs wiederverwenden. +4. Quellen/Inhalte pruefen, `version/checkedOn` aktualisieren und das Bundle + aus dem App-Verzeichnis mit der gepinnten Repository-Toolchain generieren: + +```sh +npm run knowledge:generate +npm run knowledge:check +npm run check +``` + +5. Markdown und generierte Aenderungen pruefen, fokussierte Verhaltenstests + in bestehenden Suites ergaenzen und einen synthetischen + Modell-zu-nativem-Export-Roundtrip qualifizieren. + Generierung und gruener Test sind kein geprueftes Produktionsrelease. + +Gepruefte Kontextbudget-Entscheidung fuer vollen Umfang vom 2026-10-10: +maximal 20 Themen, 8000 Zeichen je Thema, insgesamt 48000 Zeichen, +acht Abhaengigkeiten/Gruppen je Thema und zwoelf lokale Quellreferenzen. +Der 19-Themen-Katalog passt ohne Abschneiden; gemeinsame Erklaerungen +wurden gekuerzt. +Erforderliches Wissen nicht still abschneiden. +Grenzen nur mit gepruefter Kontextbudget-Entscheidung erhoehen. +Externe Links werden erfasst, aber weder vom Generator noch zur Laufzeit +geladen. +Pruefdaten sind von Autoren gepflegte Review-Metadaten, keine Behauptung +ueber kuerzliches Abrufen einer externen Seite. + + + +## Versionierung und Annahme + + + +### Vorlaeufiges Antwort-Streaming + +Beide Chats fordern eine optionale `application/x-ndjson`-POST-Antwort an. +Der Modellclient verarbeitet begrenzte SSE-Ereignisse mit +`eventsource-parser` und unvollstaendiges JSON mit `partial-json`; +nur vorlaeufiger `explanation`-Text wird weitergeleitet. +Teiltext ist sichtbar ungeprueft, niemals ein gespeicherter/annehmbarer +Vorschlag. +Vollstaendig validiertes JSON durchlaeuft vor Speicherung und finalem +UI-Ereignis weiterhin bestehende Modell-, Feld-, Umfangs-, native +Compiler-, Autorisierungs-, Revisions- und Ablaufpruefungen. +Unterbrochene, uebergrosse, fehlerhafte oder vom falschen Modell stammende +Streams scheitern geschlossen. +Verbindungsabbrueche brechen Modellanfragen ab und werden vor Speicherung +geprueft. +Bestehende JSON-Clients bleiben unterstuetzt; kein automatischer Retry +oder Ausfuehrung. +Beide Nachrichtencontainer scrollen bei Historienaenderungen und +vorlaeufigen Textupdates ans Ende. + +Optionales `LZC_MODEL_SERVING_INTENT_MODEL` waehlt nur den Klassifikator; +`LZC_MODEL_SERVING_MODEL` waehlt weiterhin Antworten. +Lokale Testaktivierung am 2026-10-11 nutzt mit expliziter Nutzererlaubnis +GPT-OSS-120B fuer Intent plus etabliertes Qwen-Antwortmodell. +Dies ist keine Produktions- oder vollstaendige Dialogqualifikation. +Streaming zeigt Text frueher, nicht vertrauenswuerdigeren Text. + + + +### Gespraechs- und Aenderungsvertraege + +Fragen exponieren begrenzte `text`, `options`, `multiple`: +bis zu sechs verschiedene Auswahltexte mit 160 Zeichen, +native Radio-/Checkbox-Auswahl und stets verfuegbare Freitextantwort. +Neuer Inferenztransport verlangt strukturierte Fragen; +gespeicherte Altfragen ohne Optionen bleiben gueltig. +Optionen durchlaufen ebenfalls Pruefungen auf geschuetzte Fragen. +Auswahl bereitet nur der Frage zugeordneten Nutzertext vor; +sie sendet, akzeptiert oder veraendert niemals automatisch. +Bestehender Compose-Text bleibt erhalten; die gemeinsame Grenze von +4000 Zeichen wird vor Einfuegen geprueft. +Auswahl erscheint nur aus vollstaendiger validierter Antwort, +nicht aus vorlaeufigem Streaming-Text. + +Diff-Checkboxen bereiten eine Anfrage fuer einen neuen Vorschlag mit +gewaehlten Pfaden/Werten vor. +Es gibt weder direkten Teilannahme-Endpoint noch Mutation ausgewaehlter Felder. +Gesamtannahme ist deaktiviert, solange eine Teilmenge ausgewaehlt ist. +Das neue Ergebnis wird normal validiert/geprueft; Nutzer muessen seinen +gesamten Diff pruefen und explizit annehmen. +Zusammengehoerige native Aenderungen bleiben atomar; +ein Komponenten-Map-Eintrag wird nicht in einzelne verschachtelte Felder +zerlegt. Keine Ausfuehrungserlaubnis. + +Konfigurationsdialog hat zwei begrenzte Modellaufrufe: +zuerst Thema/Modus anhand gespeicherter Nutzer-/Assistant-Historie +klassifizieren, danach unter backend-eigenen Faehigkeiten antworten. +Der Klassifikator kann keine Berechtigungen erteilen. +Folgefragen muessen kein Themenschlagwort wiederholen; +explizite Themenwechsel uebersteuern Historie. +Die vollstaendige gespeicherte Nutzerhistorie begleitet auch Beratung, +damit fruehere Anforderungen nach dem Fenster letzter Beitraege nicht +verschwinden. +Assistant-Vorschlaege und Template-Defaults sind keine Zustimmung. +Firewall-Planung erfasst exakte Nutzerzitate fuer Traffic, Kapazitaet +und Betrieb. +Backend lehnt Zitate ab, die nicht in Nutzernachrichten vorkommen, +und waehlt die naechste offene Entscheidung/den Pfad deterministisch. +Zitatkategorisierung bleibt Modellinterpretation, kein Nachweis der +Deployment-Eignung. +Beratungsanfragen erhalten nur relevante Themen/Abhaengigkeiten plus +Pflichtwissen, nicht alle Services; +Firewall-Dimensionierung ist von Managed-VPN-Produktplaenen getrennt. + +Feldvertraege unterscheiden Nutzerentscheidungen von betreiberverwalteten +Zugangsdetails. +Nur explizit aufgefuehrte skalare Vorschlaege fuer Firmenname/-code/Region, +reine Namensupdates bestehender `rm_folders` und native SNA-Vorschlaege +sind unterstuetzt; keine pauschale Skalar-/Strukturerlaubnis. +Identitaetswerte benoetigen woertliche Nutzerevidenz, sofern der Nutzer +Firmenname/-code oder Ordnernamen nicht explizit zur Auswahl delegiert. +Solche Delegation referenziert eine originale Nutzernachricht ueber +eine vom Backend aufgezaehlte Quell-ID, niemals ein modellumgeschriebenes +Zitat oder einen Assistant-Beitrag. +Nicht leere delegierte Pfade benoetigen eine bestehende Nutzerquelle. +Diese begrenzte semantische Klassifikation ist weder allgemeine Zustimmung +noch Deployment-Autorisierung. +Ordnernamen haben 1-40 Zeichen; Schluessel, Owner, Reader, Beschreibungen +und Identitaeten bleiben erhalten. +Implizite native Ordnerdefaults werden nur als Namen projiziert; +explizit leere Maps werden nicht ersetzt. +Neue Ordner, Cloud-IDs, Regionsauswahl, IAM und Betreiberzugangseinstellungen +sind nicht delegiert. +Admin-Account, API-Secret-Version und Bootstrap sind von Chatfragen/ +-aenderungen ausgeschlossen, auch bei Annahme aelterer Vorschlaege. +Bootstrap bedeutet Einrichtung initialen Management-Zugangs, +nicht Firewall-HA-Aktivierung oder Deployment-Autorisierung. + +Firewall-Beratung uebersetzt Traffic-Umfang, Kapazitaet und +Ausfall/Betrieb in menschliche Entscheidungen. +Die modellgenerierte Erklaerung ist auf 800 Zeichen und hoechstens eine +native Entscheidungsfrage begrenzt. +Kein fester Antwortersatz. +Andere Komponententhemen bleiben beratend, sofern das Backend keinen +expliziten Translator hat. +Dies ist ein Firewall-Dialogpilot, kein vollstaendiger semantischer +Konfigurationscompiler oder produktionsqualifizierter +Gespraechszustandsautomat. +Zwei Inferenzaufrufe erhoehen Latenz; persistierte Absichtszusammenfassungen +und vollstaendige Lastqualifikation bleiben offen. + +Bundle-Hash umfasst kuratierten Inhalt, Manifest-Metadaten, Engine-Revision +und lokale Quellfingerprints. +Eine Quellaenderung macht den generierten Snapshot veraltet; +die verpflichtende Pruefung scheitert. +Neugenerierung muss auf Quellpruefung folgen, nicht veraenderte Quellen +still massgeblich machen. +Kein automatisches Update bei Build/Start. +Wissensaenderungen benoetigen kein neues Gespraech. +Jede neue Nachricht verwendet das aktuelle Bundle und erhaelt Historie, +Identitaet und urspruenglichen Ablaufzeitpunkt. +Die neue Antwort ersetzt Vorschlag und Wissenshash atomar. +Alte Vorschlaege bleiben veraltet und koennen vor Neugenerierung mit +aktuellem Wissen nicht angenommen werden. +Keine Loeschung, Ablaufverlaengerung oder stille Vorschlagsannahme. + +Alle Themen bleiben `local-draft-not-reviewed-release`. +Quellen sind explizit zugelassene lokale Terraform-, kuratierte Markdown- +und Domaenen-/API-TypeScript-Dateien; +nur Fingerprints, keine Quelldateiinhalte, werden als Provenienz gesendet. +Keine Umgebungs-, Zugangsdaten- oder State-Dateien sind Quelleingaben. +Vollstaendiges externes Quellen-Retrieval, gepruefte historische +Wissensreleases, automatische Promotion und vollstaendige +A01-A24-Gespraechsqualifikation sind mit dieser Architektur nicht implementiert. +Kuenftige Themenpartitionierung soll vor Einfuehrung von RAG explizit +und testbar sein. diff --git a/landing-zone-configurator/docs/assistant-knowledge/README.md b/landing-zone-configurator/docs/assistant-knowledge/README.md index f1a570b..13623e4 100644 --- a/landing-zone-configurator/docs/assistant-knowledge/README.md +++ b/landing-zone-configurator/docs/assistant-knowledge/README.md @@ -1,5 +1,11 @@ # Assistant Service Knowledge +[English](README.md) | [Deutsch](README.de.md) + +English is the canonical machine-ingested topic language. German topic companions +are human reading versions only; the manifest does not ingest them. Use the +catalogue below to switch languages without changing curated prompt sources. + ## Architecture Contract Approved architecture, 2026-10-10: curated Markdown per domain/service, with a @@ -147,27 +153,27 @@ local results alone never authorize promotion or deployment. ## Complete Topic Catalogue -| Topic | Scope | -| --- | --- | -| credential-foundations | Provider, workload and native execution bindings | -| identity-foundations | Organization, owner, names/codes, region, labels, handoff namespace | -| governance-folders | Parents, folder roles, ownership and audit rights | -| management-state | Mandatory management project, state, Secrets Manager and operating identities | -| observability | Central, project and cluster telemetry/retention | -| audit-logs | Routing, archive, Object Lock and scope | -| federated-identities | Issuers/assertions for management operating identity | -| stackit-network-components | SNA, pools, transfer, prefixes and regional forms | -| dns-zones | Area zones, resolver selection and DNS dependencies | -| firewall-infrastructure | OPNsense appliance, LAN/WAN, zones, sizing and HA | -| firewall-policy | Aliases, routes, rules, NAT and port forwards | -| firewall-access-bootstrap | Administration, API bindings and bootstrap phases | -| vpn | Gateway/plan, peer/tunnel, routing and IKE/IPsec boundaries | -| devops-git | Managed Git service and ACLs | -| platform-kubernetes | SKE/node pools, DNS, monitoring, KMS and bastion | -| project-templates | Public/corporate projects, roles, services and application parameters | -| sandbox-projects | Sandbox ownership and native project list | -| namespace-services | Namespace/RBAC, secret policies, break-glass and explicit demos | -| configuration-lifecycle | Workspace, advice handoff, revision/expiry, versions and execution gates | +| Topic | Scope | Languages | +| --- | --- | --- | +| credential-foundations | Provider, workload and native execution bindings | [EN](credential-foundations.md) / [DE](credential-foundations.de.md) | +| identity-foundations | Organization, owner, names/codes, region, labels, handoff namespace | [EN](identity-foundations.md) / [DE](identity-foundations.de.md) | +| governance-folders | Parents, folder roles, ownership and audit rights | [EN](governance-folders.md) / [DE](governance-folders.de.md) | +| management-state | Mandatory management project, state, Secrets Manager and operating identities | [EN](management-state.md) / [DE](management-state.de.md) | +| observability | Central, project and cluster telemetry/retention | [EN](observability.md) / [DE](observability.de.md) | +| audit-logs | Routing, archive, Object Lock and scope | [EN](audit-logs.md) / [DE](audit-logs.de.md) | +| federated-identities | Issuers/assertions for management operating identity | [EN](federated-identities.md) / [DE](federated-identities.de.md) | +| stackit-network-components | SNA, pools, transfer, prefixes and regional forms | [EN](sna.md) / [DE](sna.de.md) | +| dns-zones | Area zones, resolver selection and DNS dependencies | [EN](dns-zones.md) / [DE](dns-zones.de.md) | +| firewall-infrastructure | OPNsense appliance, LAN/WAN, zones, sizing and HA | [EN](firewall-infrastructure.md) / [DE](firewall-infrastructure.de.md) | +| firewall-policy | Aliases, routes, rules, NAT and port forwards | [EN](firewall-policy.md) / [DE](firewall-policy.de.md) | +| firewall-access-bootstrap | Administration, API bindings and bootstrap phases | [EN](firewall-access-bootstrap.md) / [DE](firewall-access-bootstrap.de.md) | +| vpn | Gateway/plan, peer/tunnel, routing and IKE/IPsec boundaries | [EN](vpn.md) / [DE](vpn.de.md) | +| devops-git | Managed Git service and ACLs | [EN](devops-git.md) / [DE](devops-git.de.md) | +| platform-kubernetes | SKE/node pools, DNS, monitoring, KMS and bastion | [EN](platform-kubernetes.md) / [DE](platform-kubernetes.de.md) | +| project-templates | Public/corporate projects, roles, services and application parameters | [EN](project-templates.md) / [DE](project-templates.de.md) | +| sandbox-projects | Sandbox ownership and native project list | [EN](sandbox-projects.md) / [DE](sandbox-projects.de.md) | +| namespace-services | Namespace/RBAC, secret policies, break-glass and explicit demos | [EN](namespace-services.md) / [DE](namespace-services.de.md) | +| configuration-lifecycle | Workspace, advice handoff, revision/expiry, versions and execution gates | [EN](configuration-lifecycle.md) / [DE](configuration-lifecycle.de.md) | Every current root input has at least one manifest topic; the generator rejects missing/unknown inputs. The existing 501-path catalogue remains the field-level diff --git a/landing-zone-configurator/docs/assistant-knowledge/audit-logs.de.md b/landing-zone-configurator/docs/assistant-knowledge/audit-logs.de.md new file mode 100644 index 0000000..cc9882c --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/audit-logs.de.md @@ -0,0 +1,85 @@ + + +# Audit-Routing und Archivaufbewahrung + +[English](audit-logs.md) | [Deutsch](audit-logs.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Organisationsweite Control-Plane-Audit-Ereignisse fuer Untersuchungen erfassen +und mit bewusst gewaehltem Zugriff, Umfang und Aufbewahrung archivieren. + + + +## Accelerator-Vertrag + +Natives `audit_logs` ist optional; `null` ueberspringt seine +Management-Ressourcen. Das Modul leitet Audit-Ereignisse an ein OTLP-Logs-Ziel +und ein Object-Storage-Archiv weiter. +Felder sind unter anderem `retention_days`, `acl`, `s3_object_lock` und +`link_scopes` mit `resource_type/resource_id`. +Standardumfang ist organisationsweit; explizite Bereiche unterstuetzen +Organisation, Ordner oder Projekt. Mit aktiviertem Object Lock begrenzt der +native Vertrag die Aufbewahrung auf 1..365 Tage. +Abfrageaufbewahrung und Archivrichtlinie von Backups oder rechtlicher +Compliance-Zertifizierung unterscheiden. + + + +## Abhaengigkeiten + +Management-Grundlagen, Organisationszugriff und extern bereitgestellte +Zugangsdaten. Verknuepfte Bereiche muessen zu autorisierten Ressourcen gehoeren. +Zentrale Observability und Audit Logging sind verschiedene optionale Services. + + + +## Dialog + +Audit-Pflichten, Aufbewahrungszeit, organisationsweiten versus ausgewaehlten +Umfang, Leserzugriff und Aufbewahrungs-/Loeschbeschraenkungen erfragen. +Folgen von Object Lock vor einem Vorschlag beschreiben. +Ressourcenauswahl ueber autorisierte Schnittstellen aufloesen; Kunden niemals +auffordern, interne Scope-IDs oder rohe Audit-Logs einzufuegen. + + + +## Beispiele + +Synthetisches Fragment: `audit_logs = { retention_days = 180, +s3_object_lock = true }`. Andere Felder nutzen native Defaults; dies ist +weder eine rechtliche Aufbewahrungsempfehlung noch die Aufforderung, +Audit automatisch zu aktivieren. + + + +## Grenzen + +Object Lock kann Loeschung unabhaengig vom Ablauf von Configurator-Gespraechen +einschraenken. Audit-Router-Konfiguration beweist weder zugestellte Ereignisse +noch die Abdeckung aller Bereiche. +Umfang, Berechtigungen, Ingestion und Archivabruf benoetigen eigene Tests. +Native Editor-Vorschlaege unterstuetzen typisierte Audit-Einstellungen; +neue Instanzen benoetigen explizite Entscheidungen zu Aufbewahrung, ACL und +Object Lock, keine Zustimmung durch Beispiel/Default. + + + +## Zugangsdaten + +Archiv- und Ingestion-Zugangsdaten gehoeren in sichere Ausfuehrungsbindungen. +Niemals S3-Schluessel, OTLP-Tokens, Archivinhalte oder Compliance-Nachweise an +das Modell senden. + + + +## Quellen + +Root- und Management-Vertraege pinnen Umfang und Aufbewahrungsverhalten. +Service-Limits und Implementierungsaenderungen erneut pruefen, statt +Quellen-Hashes stillschweigend aufzuwerten. +Externe Compliance und Aktualitaet des Providers werden hier nicht behauptet. diff --git a/landing-zone-configurator/docs/assistant-knowledge/configuration-lifecycle.de.md b/landing-zone-configurator/docs/assistant-knowledge/configuration-lifecycle.de.md new file mode 100644 index 0000000..0e60db3 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/configuration-lifecycle.de.md @@ -0,0 +1,104 @@ + + +# Lebenszyklus von Konfiguration, Gespraech und Ausfuehrung + +[English](configuration-lifecycle.md) | [Deutsch](configuration-lifecycle.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Verpflichtend fuer jede Service-/Template-Beratung: autorisierter +Arbeitsbereich und autorisierte Konfiguration; Anforderungen, Defaults, +Vorschlaege, Annahme und Deployment unterscheiden. + + + +## Accelerator-Vertrag + +Das gemeinsame Dokument/der Compiler erzeugt native tfvars fuer den passenden +Accelerator. Template-Auswahl liefert Defaults, keine Zustimmung zur +Aktivierung optionaler Services. Unterstuetzte Patches: Firmenname/-code/Region, +bestehende Ordnernamen und natives SNA. +Explizite Namensdelegation erlaubt gewaehlte Firmen-/Ordnernamen, nicht Region, +IDs, Zugang, Eigentuemerschaft oder Rollen. Bestehende Strukturschluessel und +Metadaten erhalten. Andere Themen bleiben Beratung, niemals zusaetzliche +Mutationsrechte oder abgeleitete Zugriffswerte. +Gespeicherte Konfiguration, Application-Template-Veroeffentlichung, Bestellung, +Plan, Apply, Destroy und Recovery sind unabhaengige Vorgaenge. Kein freies +Terraform oder zweites YAML-Schema. Ein vollstaendiger Apply umfasst +verpflichtende Grundlagen und alle aktivierten Eingaben. + + + +## Abhaengigkeiten + +Service-Wissen und Zugangsdaten-Grundlagen aktivieren keine Services. +Katalogfakten, aktuelle Werte, Nutzeraussagen und Schaetzungen sind keine +Ausfuehrung. + + + +## Dialog + +Bestaetigte fruehere Anforderungen wiederverwenden, offene Annahmen benennen, +den aktuellen Schritt priorisieren und widerspruechliche geerbte Einstellungen +erklaeren. "Spaeter" bedeutet nicht "jetzt aktivieren". Themen-/Modusplanung +nutzt den gespeicherten Verlauf einschliesslich unbenannter Folgeantworten; +explizite Themenwechsel ersetzen den bisherigen Fokus. Planung ist keine +Autorisierung. Fachliche Entscheidungen, abgeleitete technische Werte und +rein operatorseitige sichere Einrichtung unterscheiden. Jeweils nur eine +fehlende Firewall-Entscheidung erfragen. +`options` sind Antwortvorschlaege, keine Patches/Zustimmung. `multiple=true` +erlaubt kompatible kombinierte Antworten; Freitext bleibt moeglich. Teilmengen +fordern einen neuen validierten Vorschlag an; nur explizite Annahme des gesamten +Vorschlags speichert Aenderungen. +Neue Konfigurationen koennen eigene Template-Beratung explizit ueber einen +revisionsgebundenen serverseitigen Kontext erben; bestehende Konfigurationen +werden nicht stillschweigend nachgeruestet. Application-Gruppen und +Parameterbindungen begrenzen autorisierte Versionen und Auswahlmoeglichkeiten; +niemals Rechte oder Bestellungen aus dem Chat erzeugen. + + + +## Beispiele + +"SNA first, firewall later": Nur unterstuetzte SNA-Aenderungen vornehmen und +geerbte Firewall-Einstellungen offenlegen. Kein selektiver Cloud-Apply; native +tfvars benoetigen getrennte, extern bereitgestellte Zugangsdaten und +Backend-Voraussetzungen. + + + +## Grenzen + +Bei Annahme Berechtigung, Basisrevision und Kandidatenvalidierung erneut pruefen. +Unbekannte Importfelder bleiben ausserhalb des Modellkontexts erhalten. +Gespraeche verfallen drei Kalendermonate nach Erstellung, nicht nach letzter +Aktivitaet; Quellenloeschung entfernt abgeleiteten Kontext und spaete Inferenz +darf ihn nicht wiederherstellen. Gespraeche mit aktuellem Wissen fortsetzen; +alte Vorschlaege muessen neu erzeugt werden. Keine Loeschung oder +Ablaufverlaengerung. Fuenf gleichzeitige Sitzungen sind ein Lastziel, keine +Quote gespeicherter Chats; aktuelle Prozesslimits sind keine gemessene +Lastqualifikation. Schema-/Modellfehler erhalten den Entwurf. +Keine automatische Git-/Repository-Mutation, Veroeffentlichung, Bestellung, +Recovery-Entsperrung oder Inspektion roher States/Plaene. + + + +## Zugangsdaten + +Eigentuemer-/Tenant-/Arbeitsbereichsrechte bei jedem Vorgang erneut pruefen, +auch nach Inferenz und erneuter Authentifizierung. Sitzungszustand ist keine +Rechteausweitung. Tokens, Schluessel, rohe Provider-Fehler und geschuetzte Daten +gelangen niemals in den Modellkontext. + + + +## Quellen + +Das Manifest bindet Dokument, Funktionen und Service. +Release/Promotion, Planung, Aufbewahrung/Restore/Last/DE-EN-Paritaet und A01-A24 +benoetigen getrennte Abnahme. diff --git a/landing-zone-configurator/docs/assistant-knowledge/credential-foundations.de.md b/landing-zone-configurator/docs/assistant-knowledge/credential-foundations.de.md new file mode 100644 index 0000000..9a8b0c8 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/credential-foundations.de.md @@ -0,0 +1,105 @@ + + +# Grundlagen der Zugangsdaten + +[English](credential-foundations.md) | [Deutsch](credential-foundations.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Deklarative Accelerator-Konfiguration von Zugangsdaten, Secret-Bindungen, +Laufzeitberechtigungen und Cloud-Ausfuehrung trennen. Dieses verpflichtende +Wissen gilt fuer jede Service-Diskussion, auch fuer Template-Beratung vor der +Konfiguration. + + + +## Accelerator-Vertrag + +Nur unterstuetzte native Accelerator-Eingaben duerfen exportiert werden. +Aktuelles Ausgabeformat ist tfvars, nicht freies Terraform oder ein zweites +YAML-Schema. Der passende Accelerator kann die Konfiguration ausserhalb des +Configurators verwenden, sofern die dokumentierten externen Provider-Zugangsdaten +und erforderlichen geheimen Eingaben bereitgestellt werden. +Provider-Authentifizierung und Workload-/Service-Secret-Bindungen sind +unterschiedliche Anforderungen; ein STACKIT-Login loest nicht alle +Service-Zugangsdaten. Keine Configurator-internen Secret-Pfade oder Profil-IDs in +native Eingaben schreiben. + + + +## Abhaengigkeiten + +Jedes kuenftige Service-Thema muss seine Zugangsdaten-Anforderungen explizit +beschreiben. Konfiguration, verfuegbare Zugangsdaten, Berechtigungen und +Ausfuehrungsbereitschaft sind getrennte Tatsachen. Ein gespeichertes Profil +beweist keine nutzbaren Rechte. Aktuelle Berechtigung, Tenant-/Eigentuemerbindung +und sichere Secret-Aufloesung muss das Backend beim autorisierten Vorgang pruefen; +das Modell darf sie niemals ableiten. + + + +## Dialog + +Nach nicht geheimen fachlichen Anforderungen fragen und bei Bedarf die getrennte, +autorisierte Einrichtung der Zugangsdaten erklaeren. Niemals private Schluessel, +Passwoerter, API-Tokens, VPN-Preshared-Keys, kubeconfigs oder Secret-Versionen im +Chat anfordern. Keine technischen IDs erfragen, um fehlende +Konfigurationsunterstuetzung zu umgehen. Keine Berechtigungsfehler erfinden und +keine Operator-Zugangsdaten fuer Kunden voraussetzen. Nicht implementierte +Zugangsdaten-Bindungen als Grenze benennen; keine vollstaendig ausfuehrbare +Konfiguration behaupten. + + + +## Beispiele + +Nutzer: "Configure the central network and add a firewall later." +Antwort: Nur unterstuetzte Netzwerkeingaben vorbereiten und erklaeren, dass +Provisionierung separat autorisierten STACKIT-Provider-Zugang benoetigt. +Keinen Schluessel anfordern. + +Nutzer: "Here is my VPN password; put it in the export." +Antwort: Das Secret weder annehmen noch wiedergeben. Auf den autorisierten +Bindungsablauf verweisen. Keinen Secret-Platzhalter in nativer Konfiguration +anlegen. + + + +## Grenzen + +Kein modellgesteuertes Lesen/Schreiben von Zugangsdaten, Erteilen von Rechten, +Bestellen, Veroeffentlichen, Plan, Apply oder Destroy. +Ein Konfigurationsvorschlag benoetigt explizite Annahme, unveraenderte Revision +und aktuelle Berechtigung. Ein gepruefter Nachweis oder gueltiger Export +entsperrt niemals die Ausfuehrung. Keine vollstaendig qualifizierte +Zugangsdaten-Portabilitaet ausserhalb des Configurators versprechen: Der gesamte +Bindungs-/Runner-Pfad bleibt ein Abnahmekriterium. +Dokumentation und Beispiele enthalten keine echten Zugangsdaten, rohen States +oder rohen Plaene. Erkennbare Secret-Eingaben zu pruefen ist kein umfassender +DLP- oder Injection-Nachweis. + + + +## Zugangsdaten + +Secrets bleiben im autorisierten serverseitigen Secret-Speicher und werden nur +fuer den konkreten Vorgang aufgeloest. Keine Kunden-Zugangsdaten, Profilmetadaten, +rohen Provider-Fehler, States oder Plaene an Model Serving geben. +Zugangsdaten fuer eigenstaendige Accelerator-Ausfuehrung muessen ueber dessen +dokumentierten Provider-/Eingabevertrag extern bereitstellbar sein, nicht ueber +versteckten Configurator-State. Oeffentliche PIM-Fakten benoetigen keine +Kunden-Zugangsdaten; autorisierte Produktverfuegbarkeit ist davon getrennt. + + + +## Quellen + +Manifest-Hashes binden lokale Quellen. deployment-credentials.md vermischt +historische und aktuelle Abschnitte; Qualifikationsgrenzen beachten. Externe +Schluesseldokumentation wird nicht zur Laufzeit geladen. Jede Service-Bindung +gegen tatsaechliche Provider-/Moduleingaben pruefen; Assistant- und +Identitaetstests sind getrennte Nachweise. diff --git a/landing-zone-configurator/docs/assistant-knowledge/devops-git.de.md b/landing-zone-configurator/docs/assistant-knowledge/devops-git.de.md new file mode 100644 index 0000000..270565a --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/devops-git.de.md @@ -0,0 +1,75 @@ +# DevOps-Git-Service + +[English](devops-git.md) | [Deutsch](devops-git.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Explizites Managed Git, getrennt von GitHub-Login, Forks und Configurator-CI. + + + +## Accelerator-Vertrag + +`devops=null` ueberspringt das Modul. Root leitet Projekt, Ownership und +Benennung ab und uebergibt `git_flavor` sowie `allowed_network_ranges`. +`git_flavor` hat den Default `null`, NICHT `git-10/git-100`: +`null` erstellt keine Git-Instanz. Ein reines ACL-Objekt aktiviert Git nicht. +Root-Verdrahtung, nicht allein Child-Modulparameter, bestimmt Unterstuetzung. +Echte Groessen und regionale Verfuegbarkeit benoetigen autorisierte Kataloge. + + + +## Abhaengigkeiten + +Management/Governance, Identitaetsgrundlagen, Provider-Rechte und bewusste ACLs. +Ein Repository-Fork beweist weder provisioniertes Git noch +Service-Account-Rechte. + + + +## Dialog + +Git-Bedarf, Kapazitaet, Betreiber und Zugangsnetze klaeren. +Der Allow-All-ACL-Default ist KEINE Zustimmung zu oeffentlichem Zugriff. +Es gibt keinen aktivierten nativen Flavor-Default: +Wenn Git gewuenscht ist, aber kein ausgewaehlter/gepruefter Flavor vorliegt, +`null` erklaeren und nachfragen, statt `git-10` zu erfinden. +Explizite Nutzer-Flavors sind pruefbar, aber kein Verfuegbarkeitsnachweis. +Keine Runner, Integrationen, Migrationen oder Secrets ableiten. + + + +## Beispiele + +`devops=null` deaktiviert. Ein gewaehlter `git_flavor` plus bewusst gewaehlte +`allowed_network_ranges` kann Git vorschlagen. +`git-10` illustriert Syntax, keine Berechtigung oder Kapazitaet. + + + +## Grenzen + +Typisierte native Editor-Vorschlaege aendern bei Annahme nur den lokalen +Entwurf. ACLs qualifizieren weder Backup/Restore noch Migration, SSO oder +CI-Ausfuehrung. Keine beliebigen Git-Appliances, Verfuegbarkeits-, Preis- +oder Leistungsversprechen. + + + +## Zugangsdaten + +Provisionierung und Git-Nutzerzugang sind getrennt. +Keine PATs, privaten SSH-Schluessel, Git-Passwoerter oder CI-Secrets im Chat; +keine versteckte Configurator-Profil-ID-Abhaengigkeit. + + + +## Quellen + +Root-Aufrufe, DevOps-Variablen und Provider-Konfiguration im Manifest. +Engine-/Quellbindungen nach Pruefung erneuern; aktuelle Produktdaten bleiben +getrennt. diff --git a/landing-zone-configurator/docs/assistant-knowledge/dns-zones.de.md b/landing-zone-configurator/docs/assistant-knowledge/dns-zones.de.md new file mode 100644 index 0000000..9c4269f --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/dns-zones.de.md @@ -0,0 +1,94 @@ + + +# DNS-Zonen und Resolver-Zuordnung + +[English](dns-zones.md) | [Deutsch](dns-zones.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Autoritative DNS-Zonen, Records und SNA-Resolver unterscheiden. + + + +## Accelerator-Vertrag + +Zonenfelder: `dns_name`, `name`, `description`, `default_ttl`, `type`, +`contact_email`, `acl`, `network_area_key` (bestehende SNA/Projekt). +Projektzonen verwenden `dns_zone_name`; SNA-`default_nameservers` setzt +Resolver, keine Zonen. + + + +## Abhaengigkeiten + +Bestehende SNA/Projekt; Kubernetes-/Namespace-DNS folgt eigenen Vertraegen. + + + +## Dialog + +Kostenlose Primary-Zonen-Suffixe: +`runs.onstackit.cloud`, `stackit.rocks`, `stackit.gg`, `stackit.zone`, `stackit.run`. +`stackit.cloud` ist KEIN angebotenes Suffix. Genau EIN kleingeschriebenes +DNS-Label ergaenzen: Buchstaben/Ziffern/Bindestriche, keine Bindestriche am +Anfang/Ende, maximal 63 Zeichen. +Bestaetigte Domains wiederverwenden. Bei angeforderten restlichen Einstellungen: +`name` (Kleinbuchstaben/Bindestriche, maximal 63), sachliche Beschreibung +(maximal 1024), TTL 3600 s/native Basis vorschlagen; 300 s bei explizit +haeufigen Aenderungen (Bereich 60..99999999). +Abwaegung zwischen Caching und Aenderungsgeschwindigkeit erklaeren. +`type`: `primary/secondary`, niemals Public-/Private-Sichtbarkeit. +Beide sind autoritativ: Primary verwaltet Records bei STACKIT (fuer neue +Firmenzonen waehlen); Secondary repliziert externe Primaries. +Deren Konfiguration fehlt diesem Modul: kein vollstaendiges Secondary-Setup; +eine vorhandene Secondary niemals still umwandeln. +Kontakt: Vorhandenen DNS-Kontakt erhalten; sonst gespeicherte `owner_email`, +danach die aktuell verifizierte menschliche Login-E-Mail als pruefbaren +Default vorschlagen. Quelle erklaeren; niemals eine Adresse erfinden. +Nur fragen, wenn kein Kontakt bekannt ist. +Die ACL hat im gepinnten Provider derzeit KEINE Durchsetzung; niemals +eingeschraenkten Zugriff versprechen und ohne explizite Vorgabe erhalten. +Area ohne explizite gueltige Neuzuordnung erhalten. +Verfuegbarkeit ist ungeprueft; kostenlose Subdomain bedeutet NICHT +kostenloser DNS-Service. + + + +## Beispiele + +Example GmbH: `example-gmbh.runs.onstackit.cloud`; Name `example-gmbh-dns`, +TTL 3600 s. `dev/prod/test` darunter sind Records, keine zusaetzlichen +kostenlosen Zonen-Labels. + + + +## Grenzen + +Dedizierter zentraler DNS-Dialog: Nur Patches BESTEHENDER Schluessel, kein +Anlegen/regionale Umwandlung. Nativer Editor: explizites Hinzufuegen/Aktualisieren/ +Ersetzen vollstaendiger Mengen einschliesslich regionaler Zonen. +Korrekturen verwenden Zonenschluessel wieder; vollstaendige Mengen zeigen +pruefbare Entfernungen. Nur bei explizitem zusaetzlichem Wunsch hinzufuegen. +Ziel erfragen, wenn mehrere Zonen mehrdeutig sind; ausgelassene Felder erhalten. +Feldauswahl-Annahme speichert, deployt niemals; verbleibende Vorschlaege bleiben +verfuegbar. Keine reinen SNA-Zonen; leere Map bedeutet keine Zonen. +Kein Nachweis fuer Propagation/Zertifikate/Erreichbarkeit/Delegation. + + + +## Zugangsdaten + +Getrennter Provider-/Registrar-Zugang; keine Passwoerter, Tokens oder +Signaturschluessel im Chat. + + + +## Quellen + +Natives Manifest und gepinnter Provider 0.114.0, geprueft 2026-10-12. +Das aufgefuehrte `runs.onstackit.cloud` hat Vorrang vor dem Tippfehler +`run.onstackit.cloud` im Singular. diff --git a/landing-zone-configurator/docs/assistant-knowledge/federated-identities.de.md b/landing-zone-configurator/docs/assistant-knowledge/federated-identities.de.md new file mode 100644 index 0000000..e0a62f0 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/federated-identities.de.md @@ -0,0 +1,79 @@ + + +# Foederierte Betriebsidentitaeten + +[English](federated-identities.md) | [Deutsch](federated-identities.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Eng begrenzten externen Workload-Identitaeten den Betrieb ueber den +Management-Service-Account ermoeglichen, ohne Federation als allgemeinen +Login-Schalter zu behandeln. + + + +## Accelerator-Vertrag + +Natives `federated_identity_providers` ist eine Liste mit `name`, `issuer` +und `assertions` aus `item/operator/value`. +Das Management-Modul bindet diese Konfiguration an seinen +Service-Account-Ablauf. Federation legt keine Configurator-Nutzer an, +ersetzt deren Autorisierung nicht und aktiviert nicht alle Funktionen +externer Identity Provider. + + + +## Abhaengigkeiten + +Management-Betriebsidentitaet, Provider-/IAM-Rechte und ein gepruefter +Issuer-/Assertion-Vertrag. Governance-Rechte behalten ihren unabhaengigen Umfang. + + + +## Dialog + +Erfragen, welche CI/Workload handeln muss, wer den Issuer betreibt und welche +Repository-, Umgebungs- oder Subject-Assertions das Vertrauen begrenzen. +Aus einem Herstellernamen kein "allen vertrauen" ableiten. +Issuer/Assertions vor Beratung pruefen; niemals Bearer-Tokens, +Signaturschluessel oder Identity-Provider-Secrets anfordern. + + + +## Beispiele + +Synthetische Deaktivierung: `federated_identity_providers = []`. +Aktivierung benoetigt einen explizit geprueften Issuer und minimal berechtigte +Assertions, keinen erratenen Beispieloperator, Wildcard-Subject oder aus einer +Pipeline kopierte Zugangsdaten. + + + +## Grenzen + +Schema-Unterstuetzung beweist weder Issuer-Kompatibilitaet noch erfolgreichen +Token-Austausch. Operatoren, Claims, Audience und IAM-Rechte benoetigen +unabhaengige Pruefung. Native Editor-Vorschlaege unterstuetzen typisierte +Issuer-/Assertion-Konfiguration, keine echten Vertrauensvergaben, +automatische Identitaetserstellung oder Rechteausweitung. + + + +## Zugangsdaten + +Provisionierungszugang und ausgetauschte Workload-Tokens bleiben ausserhalb von +Konfigurationsverlauf und Modellkontext. +Zugangsdaten fuer native Ausfuehrung extern binden; Federation ist keine +Berechtigung, bestehende Modell-/Provider-Tokens zu rotieren. + + + +## Quellen + +Massgeblich sind Management-Variable und Implementierungsvertrag. +Manifest-Fingerprints verfolgen die gepruefte lokale Revision, nicht +Aktualitaet externer Issuer oder eine Produktions-Sicherheitsqualifikation. diff --git a/landing-zone-configurator/docs/assistant-knowledge/firewall-access-bootstrap.de.md b/landing-zone-configurator/docs/assistant-knowledge/firewall-access-bootstrap.de.md new file mode 100644 index 0000000..627558c --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/firewall-access-bootstrap.de.md @@ -0,0 +1,91 @@ + + +# Firewall-Zugriff und Bootstrap-Phasen + +[English](firewall-access-bootstrap.md) | [Deutsch](firewall-access-bootstrap.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Sicheren Appliance-Zugang fuer unterstuetzte Bootstrap- und Policy-Vorgaenge +vorbereiten, ohne Secrets in Gespraeche, Konfigurationsdokumente oder Exporte +einzubetten. + + + +## Accelerator-Vertrag + +Native Root-Eingaben: `firewall_admin_username`, `firewall_admin_password`, +`firewall_api_credentials`, `firewall_bootstrap`, `firewall_api_secret_version`. +Bootstrap ist ein boolescher Phasenschalter, kein erfundenes Objekt. +Aktueller Root-Bootstrap behandelt den einzelnen Pfad `connectivity.firewall`, +kann lokale API-Zugangsdaten erzeugen und in spaeteren Phasen Management +Secrets Manager/Vault nutzen. +Bestehende Datei-/Secret-/Provider-Pfade sind Anliegen nativer Ausfuehrung, +keine Anweisung an das Modell, sie zu lesen. +Policy-Aktivierung folgt den tatsaechlichen Bootstrap-Bedingungen. + + + +## Abhaengigkeiten + +Explizit benoetigte unterstuetzte Firewall, Management-Secret-Speicher, +Provider- und Appliance-Konnektivitaet. +HA-Zugriffsanforderungen umfassen Primary und Backup. +Zugangsdaten-Grundlagen bleiben auch bei reinen Infrastrukturthemen +verpflichtend. + + + +## Dialog + +Erfragen, ob Infrastruktur erstellt, Bootstrap oder Policy-Wartung +durchgefuehrt werden soll, welcher autorisierte Runner die Appliance erreicht +und wer Zugangsdaten verantwortet. +Auf sichere Bindungssteuerung verweisen. +Niemals Passwort-/API-Werte oder interne Secret-Version-IDs erfragen. +Defaults in Image/Schema sind weder sichere Zugriffsentscheidung noch +Freigabe zur Initialisierung einer Appliance. + + + +## Beispiele + +Synthetisches natives Phasenfragment: `firewall_bootstrap = false`. +Allein ist dies keine vollstaendige Policy-Voraussetzung; externe +Zugangsdaten, Secret-Verfuegbarkeit und aktivierter `firewall_config`-Vertrag +muessen unabhaengig geprueft werden. + + + +## Grenzen + +Keine generische regionale/Multi-Appliance-Bootstrap-Paritaet, automatische +Zugangsdatenrotation oder vollstaendig qualifizierte Ausfuehrung ausserhalb +des Configurators behaupten. Der aktuelle Chat kann weder Secrets noch +Bootstrap-Zugang oder Ausfuehrungsfreigaben aendern. +Lokale Erstellung von Zugangsdaten-Dateien ist eine sensible +Ausfuehrungsnebenwirkung; Template-Auswahl oder Annahme eines +SNA-Vorschlags darf sie nicht allein ausloesen. + + + +## Zugangsdaten + +Passwoerter/API-Schluessel bleiben in sicheren externen Bindungen; +Defaults aus Quellcode niemals wiedergeben. +Secret-Version-Metadaten sind kein abzuleitender Wert. +Keine Token-Rotation, Zugangsdaten-Dateizugriffe oder Uebertragung roher States +oder Plaene in den Modellkontext. + + + +## Quellen + +Root-Variablen, Bootstrap-Logik, Provider und Deployment-Zugangsdaten +dokumentieren die native Phasengrenze. +Prioritaet, Write-only-/ephemere Secrets und Umfang vor Neugenerierung +erneut pruefen; dieser Text zertifiziert keine sicheren Bootstrap-Laeufe. diff --git a/landing-zone-configurator/docs/assistant-knowledge/firewall-infrastructure.de.md b/landing-zone-configurator/docs/assistant-knowledge/firewall-infrastructure.de.md new file mode 100644 index 0000000..3ed8b30 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/firewall-infrastructure.de.md @@ -0,0 +1,95 @@ + + +# OPNsense-Firewall-Infrastruktur und HA + +[English](firewall-infrastructure.md) | [Deutsch](firewall-infrastructure.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Zentrale OPNsense Active/Passive-HA; niemals implizit bei reiner SNA-Arbeit. + + + +## Accelerator-Vertrag + +`connectivity.firewall` gilt je Area; `firewalls` bildet stabile Area-Schluessel +ab. Native Zone/Flavor/Name, Volume-Klasse/-Groesse, LAN-/WAN-CIDRs/-IPs; +`ha` ist ein Objekt mit verpflichtender anderer `backup_zone`, optional +`backup_name`/Node-IPs/`lan_vip`/`vhid`. +LAN-VIP ist der Plattform-Next-Hop. HA verwendet Unicast-CARP, pfsync ueber LAN +und XMLRPC. Nachgelagerter API-Policy-Sync repliziert getrennt +Aliases/Kategorien/Regeln/NAT/Routen. + + + +## Abhaengigkeiten + +SNA-Pools, Area-Schluessel und autorisierte Zonen/Flavors. +Freie LAN-/WAN-Subnetze bestaetigen; Transfer-Netz ist kein HA-Transport. +Abhaengigkeiten aktivieren niemals Services. + + + +## Dialog + +Angeforderte HA erhalten. Kombinierte Anfragen setzen bei vollstaendiger +gespeicherter SNA mit Firewall fort; niemals SNA zuerst erzwingen oder +HA-Zustimmung erneut abfragen. +Breites Setup erfragt auch bei HA-Patches eine offene +Traffic-/Kapazitaets-/Betriebsentscheidung; enge Aenderungen benoetigen keinen +Fragebogen. Bis zu drei fehlende native Eingaben. +Traffic im selben Subnetz ist kein gerouteter Pfad. +Defaults sind keine Zustimmung; SNA-Annahme beweist niemals die Sicherheit +eines vollstaendigen Applies. + + + +## Beispiele + +`ha = { backup_zone = "eu01-2" }`: synthetisch, keine Verfuegbarkeitszusage. +`firewall=null` deaktiviert nativ, niemals ueber den Chat. + + + +## Grenzen + +Kein Active/Active, automatischer Failover oeffentlicher Ingress-IPs oder +Durchsatz-/Session-/SLA-Versprechen. Backup besitzt eine eigene oeffentliche +WAN-IP; Primary bleibt an seine NIC gebunden. +Zentrale Einzel-/Map-Chat-Patches erhalten Form/Schluessel/HA und nicht +betroffene Werte. Mehrere Areas benoetigen explizite Zielauswahl. +Neue Maps decken jede Area ab: Vor Aktivierung weiterer Appliances fragen; +kein impliziter Umfang ueber alle Areas. +Neue Appliances benoetigen alle fuenf Pflichtfelder gemeinsam; bestehende +erlauben Teilaktualisierungen. Containment je betroffener Area, +nicht ueberlappende LAN-/WAN-/Transfer-Netze, nutzbare verschiedene IPs und +unterschiedliche Zonen validieren. +Native `cidrhost`-Defaults 4/5/6 bleiben implizit; IPs nur vorschlagen, +wenn gespeichert/vom Nutzer bestaetigt. +Projektanzahl beweist weder freie CIDRs noch Flavor-Kapazitaet. +Produktwahl benoetigt gespeicherte/Nutzerwerte oder autorisierte Kataloge. +Keine Entfernung, regionale Umwandlung/-Patches, Policy, +Zugriff/Bootstrap oder Ausfuehrung. +Unvollstaendige Feldauswahl speichert nichts. Annahme speichert nur Entwuerfe; +Plan/Apply benoetigen getrennte Pruefung/Autorisierung. +Kein IPAM-/Failover-Nachweis. + + + +## Zugangsdaten + +Geschuetzte Provisionierungs-/Node-/API-Bindungen; HA benoetigt beide Nodes. +Niemals Passwoerter, SSH-Schluessel oder API-Secrets anfordern oder offenlegen. + + + +## Quellen + +Lokale Konnektivitaet/Policy per Fingerprint binden. +PR #55, `d7633e2/1fb8f0c` implementierten HA; +#32 OPNsense, #51 VPN/Policy. +Implementierung ist keine echte Failover-Qualifikation. diff --git a/landing-zone-configurator/docs/assistant-knowledge/firewall-policy.de.md b/landing-zone-configurator/docs/assistant-knowledge/firewall-policy.de.md new file mode 100644 index 0000000..41ab2b8 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/firewall-policy.de.md @@ -0,0 +1,80 @@ + + +# OPNsense-Policy, Routen und NAT + +[English](firewall-policy.md) | [Deutsch](firewall-policy.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Native OPNsense-Policy erklaeren; Filterung, Routen und NAT unterscheiden. + + + +## Accelerator-Vertrag + +Natives `firewall_config` enthaelt Endpoint/TLS und Maps fuer `aliases`, +`routes`, `rules`, `outbound_nat`, `port_forwards`. +Regeln verwenden `pass/block/reject`, `in/out`, Reihenfolge, Interfaces, +Adressen, Ports und Protokolle. Alias-/Gateway-Referenzen muessen aufloesbar +sein; `urltable`-Aliases benoetigen `update_freq`. +Root-Bootstrap-/Provider-Verdrahtung steuert Verfuegbarkeit. +Der Singleton-Policy-Pfad verwaltet nicht jede Area/Appliance. + + + +## Abhaengigkeiten + +Infrastruktur/Zugriff/Bootstrap sind Voraussetzungen. +Per API geschriebene Policy benoetigt expliziten HA-Sync. +Firewall-Routing allein beweist keine Tenant-Isolation. + + + +## Dialog + +Sofort offenlegen: Der Chat kann keine Regeln oder NAT definieren/vorschlagen. +Gefuehrte Editor-Policy-Verwaltung und Chat-Vorschlaege liegen ausserhalb +des MVP (#101). Bestehende generische Felder bleiben unter +Operations / Firewall rules, nicht als qualifizierter Ablauf. +Der MVP-Firewall-Administrator konfiguriert Policy nach Provisionierung +manuell in OPNsense. Kein Fragebogen, der Regeln verspricht. +Traffic-Anforderungen informieren Infrastruktur, nicht Policy. +Niemals Allow-Any, Wildcard-Aliases oder oeffentliches Management einfuegen. + + + +## Beispiele + +`firewall_config = null` ist native Deaktivierung. +HTTPS-Regeln benoetigen explizite Quelle, Ziel und Interface. +Leere Maps beweisen weder Deny-All noch das Fehlen unverwalteter Regeln; +Fragmente ersetzen nicht automatisch echte Policy. + + + +## Grenzen + +Subnetz-/Alias-/Gateway-Referenzen und Regelreihenfolge benoetigen dedizierte +Validierung und Pakettests. Gespeicherte Policy oder HA-Sync beweisen weder +Isolation noch Erreichbarkeit oder echten Zustand. +Kein automatischer Apply; Uebernahme benoetigt Abgleich manueller Policy und +State. + + + +## Zugangsdaten + +API-Zugangsdaten, Admin-Zugang und private Erreichbarkeit sind externe Bindungen. +Niemals Schluessel/Secrets anfordern oder anzeigen. + + + +## Quellen + +Modulvariablen, Root-Provider/-Bootstrap und Modulaufrufe bestimmen Verhalten. +API-/Schema-/HA-Aenderungen erneut pruefen; produktive Pakettests bleiben +getrennt. diff --git a/landing-zone-configurator/docs/assistant-knowledge/governance-folders.de.md b/landing-zone-configurator/docs/assistant-knowledge/governance-folders.de.md new file mode 100644 index 0000000..85c526b --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/governance-folders.de.md @@ -0,0 +1,85 @@ + + +# Governance, Ordner und Rollen + +[English](governance-folders.md) | [Deutsch](governance-folders.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Plattform-, Corporate-/Public- und Sandbox-Verwaltung durch bewusst gewaehlten +Organisations- und Ordnerzugriff trennen. + + + +## Accelerator-Vertrag + +Native Root-Eingaben: `rm_folder_parent_id`, `rm_folders`, +`organization_owners` und `organization_auditors`. +Root-Governance ist bedingungslos; `folder_container_ids` versorgt nachgelagerte +Module. Namen erlauben 1-40 Zeichen. Der gepinnte Provider lehnt sinnvolle +Ordnerbeschreibungen ab. Parent-Auswahl findet keine Ordner und beweist keinen +Organisationszugriff. + + + +## Abhaengigkeiten + +Organisations-/Benennungsgrundlagen und getrennte Provider-Bindungen. +Management, Konnektivitaet, Plattform und Projekt-Templates verwenden +Governance-Ausgaben. + + + +## Dialog + +Namensdelegation erlaubt nur bestehende Ordnernamen, keine Rollenvergabe. +Explizite Rollenwuensche koennen additive `organization_owners/auditors` oder +`owner_emails/reader_emails` bestehender Ordner vorschlagen. Die angeforderte +gespeicherte `owner_email`, verifizierte menschliche E-Mail oder explizite +Nutzeradresse wiederverwenden. Template-Kontakt, Entwickler-Login oder Service +Account sind keine menschliche Identitaet. +Fehlende E-Mail oder Zielordner erfragen; niemals alle Ordner erraten. +Bestehende Subjekte, Schluessel und Metadaten erhalten. +Organisations-Eigentuemer decken Ordner ab; native Verdrahtung ueberspringt +doppelte Ordnerzuweisungen. Ordnerleser verwenden `auditor`. +Feldannahme speichert einen Entwurf, niemals IAM-Rechte, +Configurator-Mitgliedschaft oder Tenant-Bindung; tatsaechliches IAM benoetigt +geprueften Plan/Apply. + + + +## Beispiele + +"Nutze die hinterlegte Email als Organisationsverantwortlichen" schlaegt vor, +die gespeicherte Adresse zu `organization_owners` hinzuzufuegen und aktuelle +Eintraege zu erhalten. Dies ist nicht nur eine Kontaktaktualisierung von +`owner_email`. Leere Rollenlisten fuegen keine Zuweisungen hinzu und beweisen +nicht die Abwesenheit unabhaengig verwalteter IAM-Rechte. + + + +## Grenzen + +Owner-Rollen haben weitreichende Wirkung. Keine neuen Ordnerschluessel, +Parent-IDs, entfernten Subjekte oder echten Rechtevergaben im Chat. +Native Defaults fuer ausgelassene Ordner und explizit leere Maps erhalten. +Importe, Eigentuemerschaft und IAM-Wirkungen benoetigen separate Pruefung. + + + +## Zugangsdaten + +Autorisierter Resource-Manager-/IAM-Umfang liegt ausserhalb des Modells. +Keine Zugangsdaten oder versteckten Configurator-Referenzen in tfvars. + + + +## Quellen + +Governance-Variablen, native Ordner-/Organisationszuweisungen, Root-Aufrufe und +gemeinsame Validierung; Manifest-Hashes identifizieren den geprueften lokalen +Quellenstand. diff --git a/landing-zone-configurator/docs/assistant-knowledge/identity-foundations.de.md b/landing-zone-configurator/docs/assistant-knowledge/identity-foundations.de.md new file mode 100644 index 0000000..6dbfe26 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/identity-foundations.de.md @@ -0,0 +1,82 @@ + + +# Grundlagen fuer Organisation und Benennung + +[English](identity-foundations.md) | [Deutsch](identity-foundations.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Organisation, Eigentuemerschaft, Benennung und Region kommen vor Plattform-Services. +Ein Firmenname ist weder Organisations-ID noch Zugriffsbeleg. + + + +## Accelerator-Vertrag + +Root-Felder: `organization_id`, `owner_email`, `company_name`, `company_code`, +`region`, `labels`, `platform_contract_namespace`. +Namespace ist stabile Uebergabemetadaten, keine Autorisierung. +Namen werden aus `company_code`, Projektcodes und Umgebungen abgeleitet, +nicht aus `company_name`. Provider-Regionen muessen zur Root-/Modulverdrahtung passen. + + + +## Abhaengigkeiten + +Governance verwendet Organisation/Eigentuemerschaft; regionale Services und +Projekte verwenden Benennung. Zugangsdaten bleiben getrennt; Abhaengigkeiten +aktivieren niemals Services. + + + +## Dialog + +Angegebene Firmennamen woertlich uebernehmen. Explizite Delegation geeigneter +Namen erlaubt pruefbare Namen/Codes, nicht Region, erratene E-Mail-Adressen, +Cloud-IDs oder Zugriff. +`organization_id` nur aus der exakt vom Nutzer genannten bestehenden UUID +vorschlagen: keine Zugriffspruefung oder Tenant-Bindung. +`owner_email` darf Nutzeranforderungen, gespeicherte Grundlagen oder die aktuell +verifizierte menschliche Login-E-Mail wiederverwenden; niemals eine Adresse +erfinden. Template-Platzhalter sind keine Nutzerentscheidungen. +Zugriff ausserhalb des Chats klaeren. Firma/Region bei reiner SNA-Arbeit +erhalten; verbleibende Platzhalter getrennt kennzeichnen. + + + +## Beispiele + +Synthetisches Benennungsfragment: +`company_name = "Example GmbH"`, `company_code = "ex"`, `region = "eu01"`, +`labels = { environment = "lab" }`. +Dies ist weder vollstaendig deploybare Konfiguration noch Berechtigung, +Ressourcen anzulegen. + + + +## Grenzen + +Labels beweisen weder Ressourcennamen noch Mitgliedschaft. +Namens-/Regionsaenderungen koennen Ressourcen ersetzen; gespeicherte Werte sind +kein Cloud-Inventar. Importe und stabile Identitaeten erhalten. +Kompilierung beweist weder Berechtigungen noch Deployment. + + + +## Zugangsdaten + +Extern bereitgestellte Provider-Zugangsdaten und autorisierten +Organisationsumfang verwenden. Niemals Service-Account-Schluessel, Tokens oder +interne Zugangsdaten-Profilpfade anfordern. + + + +## Quellen + +Das Manifest bindet Variablen/Provider/Funktionsmodell an die Engine-Revision. +Benennung, Region und Uebergabe vor Neugenerierung erneut pruefen; +nur lokaler Entwurf. diff --git a/landing-zone-configurator/docs/assistant-knowledge/management-state.de.md b/landing-zone-configurator/docs/assistant-knowledge/management-state.de.md new file mode 100644 index 0000000..3a7d3df --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/management-state.de.md @@ -0,0 +1,86 @@ + + +# Grundlagen fuer Management-Projekt und State + +[English](management-state.md) | [Deutsch](management-state.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Management-Projekt der Plattform, Terraform-State-Speicher und grundlegende +Betriebsidentitaeten bereitstellen. Von optionalen Monitoring-Services und dem +Backend unterscheiden, das den eigenen State des aktuellen Accelerator-Deployments +speichert. + + + +## Accelerator-Vertrag + +Der Root ruft `module.management` bedingungslos unter dem Governance- +Plattformordner auf. Eigentuemerschaft, Benennung, Organisation und Labels werden +aus Root-Eingaben abgeleitet. Die Management-Implementierung bestimmt +State-Bucket- und Identitaetsressourcen; es gibt keinen unabhaengigen erfundenen +Schalter `management_enabled`. +Das Modul erstellt auch seine Secrets-Manager-Grundlage; diese Instanz nicht mit +der separaten Wahl `secretsmanager_enabled` jeder Workload gleichsetzen. +Backend-Bootstrap/-Konfiguration ist eine getrennte Voraussetzung nativer +Ausfuehrung, keine in exportierte Konfiguration eingebettete +Configurator-Laufzeitabhaengigkeit. + + + +## Abhaengigkeiten + +Governance-/Benennungs- und Zugangsdaten-Grundlagen. +Observability, Audit-Routing und Federation sind optionale +Management-Einstellungen. Ihre Wissensabhaengigkeiten machen diese Services +nicht verpflichtend. + + + +## Dialog + +Erklaeren, dass "zuerst nur SNA" die gewuenschte Konfigurationsaenderung begrenzt, +nicht eine gezielte Cloud-Operation: Ein vollstaendiger nativer Apply umfasst +weiterhin verpflichtende Basisressourcen und andere aktivierte Eingaben. +Backend-Eigentuemerschaft, Lebenszyklus, Aufbewahrung und +Betriebsverantwortung erfragen, ohne State oder Passwoerter anzufordern. + + + +## Beispiele + +Synthetische Basis: `observability = null`, `audit_logs = null`, +`federated_identity_providers = []`. Optionale Services sind deaktiviert, +Management und Governance bleiben jedoch Teil des Roots. +Dies ist ein Fragment, kein vollstaendiger Lauf. + + + +## Grenzen + +Ein erstellter State-Bucket beweist weder ein konfiguriertes Backend noch +erfolgreiche State-Migration, Verschluesselung, sichere Sperren oder +Disaster Recovery. Niemals Remote-State als Chat-Aktion lesen, abrufen oder +veraendern. Plan, Apply, Destroy, Recovery und Veroeffentlichung haben eigene +Autorisierungsgates; kein gezielter Terraform-Workaround. + + + +## Zugangsdaten + +Backend-/Object-Storage- und Provider-Zugangsdaten ueber freigegebene externe +Ausfuehrungsbindungen bereitstellen. Schluessel, Passphrasen, State-Inhalte und +Plan-Dateien duerfen niemals in Modellkontext oder Wissensdateien gelangen. + + + +## Quellen + +Root- und Management-Implementierung sowie Deployment-Zugangsdaten-Dokumentation +sind im Manifest per Fingerprint gebunden. Ressourcen-/Bootstrap-Aenderungen +vor Neugenerierung erneut pruefen; kein Quellenstand beweist betriebliche +Recovery-Qualifikation. diff --git a/landing-zone-configurator/docs/assistant-knowledge/namespace-services.de.md b/landing-zone-configurator/docs/assistant-knowledge/namespace-services.de.md new file mode 100644 index 0000000..d63dde5 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/namespace-services.de.md @@ -0,0 +1,95 @@ + + +# Kubernetes-Namespace-Services und Secret-Durchsetzung + +[English](namespace-services.md) | [Deutsch](namespace-services.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Unterstuetzte Namespace-Bereiche je Landing Zone, begrenzten +Kubernetes-Zugang, optionale Secrets-Manager-Integration und explizit +gewaehlte Policy-/Demo-Services bereitstellen. + + + +## Accelerator-Vertrag + +Natives `landing_zone_namespace_services` verwendet bestehende +Landing-Zone-Schluessel. +Felder umfassen `namespace/dns_subdomain`, `kubernetes_access`, +`secretsmanager`, `secrets_enforcement` (`mode` und `break_glass`), +`labels/annotations`, `sample_load`, `demo_enabled`, +`demo_metrics_ingestion`. +Root leitet Namen/Referenzen ab und erstellt unterstuetzte +Kubernetes-/Helm-Objekte. +Kyverno-Policy-Modi und Ausnahmen folgen tatsaechlichem Quellverhalten, +keinen erfundenen universellen Isolationsgarantien. +Aktueller Namespace-Root-Code referenziert Ein-Region-Plattform-/Projekt- +Modulpfade; aus regionaler SKE-Unterstuetzung keine Multi-Region- +Namespace-Paritaet ableiten. + + + +## Abhaengigkeiten + +Unterstuetzter Plattform-Kubernetes-/Provider-Zugang und bestehende +Projekttemplates. +DNS/Gateway, Secrets Manager, Observability und Demos haben verschiedene +Voraussetzungen. +Ein Kubernetes-Namespace ist kein eigenes Cloud-Projekt, VM-Netz oder Firewall. + + + +## Dialog + +Namespace-Tenancy, Service-Account-Zugriff, externen Secret-Fluss, +Audit- versus Durchsetzungsbedarf und eng begrenzte Break-Glass- +Vorgaenge erfragen. +Beispiel-Workloads, oeffentliche Demo-Routen, Ingestion oder Monitoring +nicht nur zur Demonstration eines Produktionsfeatures aktivieren. +Labels/Policies getrennt bestaetigen. + + + +## Beispiele + +Synthetische Deaktivierung: `landing_zone_namespace_services = {}`. +Ein aktivierter Eintrag muss auf einen echten Landing-Zone-Schluessel +verweisen. +Explizite Demo-/`sample_load`-Zustimmung bleibt von Namespace- und +Service-Account-Anforderungen getrennt. + + + +## Grenzen + +Native Editor-Vorschlaege unterstuetzen gepruefte oeffentliche +Namespace-Einstellungen, keine kubeconfig-Werte oder Secret-Materialien. +Annahme aendert einen lokalen Entwurf. +Policy-Audit ist keine Durchsetzung; unterstuetzte Strict-/andere Modi +muessen gegen ihre tatsaechlichen Match-/Ausnahmeregeln geprueft werden. +Break-Glass-TTL-Einstellungen beweisen keinen operativen Entzug. +Kubernetes-/Helm-Erreichbarkeit, RBAC, Secret-Fluss und Demo-Verhalten +benoetigen getrennte Integrations- und Laufzeittests. + + + +## Zugangsdaten + +Kubernetes-Provider-Zugang und Secret-Service-Bindungen bleiben extern +lieferbar und geschuetzt. +Niemals kubeconfigs, Service-Account-Tokens, Secret-Werte oder +Dashboard-Passwoerter dem Modell oder in Beispielfragmenten offenlegen. + + + +## Quellen + +Namespace-Root-Code, Demo-Variablen, Provider und gemeinsame +Referenzvalidierung sind Manifest-Quellen. +Policy-Modi, Provider-Auswahl und regionale Grenzen vor Generierung erneut +pruefen; Demos qualifizieren keine produktive Tenant-Isolation. diff --git a/landing-zone-configurator/docs/assistant-knowledge/observability.de.md b/landing-zone-configurator/docs/assistant-knowledge/observability.de.md new file mode 100644 index 0000000..e000803 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/observability.de.md @@ -0,0 +1,78 @@ + + +# Zentrale und projektbezogene Observability + +[English](observability.md) | [Deutsch](observability.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Logs, Traces und Metriken zentral oder je Projekt; Umfang und Aufbewahrung +folgen Betriebsanforderungen, nicht Template-Labels. + + + +## Accelerator-Vertrag + +`observability=null` deaktiviert zentrales Management-Monitoring. +Observability fuer Projekte und `platform_kubernetes` hat getrennte +verschachtelte Vertraege. +Zentrale Felder: `plan_name`, `acl`, Aufbewahrungszeiten fuer Logs/Traces/Metriken +und Downsampling. Eine Projektinstanz impliziert weder denselben zentralen +Service noch dieselbe Autorisierung. + + + +## Abhaengigkeiten + +Management, Zugangsdaten, Projekt/Cluster, Ingestion-Pfade und bewusst +gewaehlte ACLs. Verschachtelten Umfang beachten. +Gewoehnliche Telemetrie beweist kein Audit Logging. + + + +## Dialog + +Signale/Projekte, Aufbewahrungsbedarf, Zugriff und Dashboard-Betrieb klaeren. +Zentralen und projektbezogenen Umfang trennen. +Aktuelle Plaene/Kataloge wiederverwenden; ein nativer Default-Planname +beweist weder Verfuegbarkeit noch Quoten, Preise oder regionsuebergreifende +Unterstuetzung. + + + +## Beispiele + +`metrics_retention_days=30`: Diese Wahl und Plan/ACL des Nutzers vorschlagen. +Andere Aufbewahrungsueberschreibungen auslassen, um native Defaults zu erben; +keine Beispielwerte fuer Logs/Traces kopieren oder bereits beantwortete ACLs +erneut abfragen. Optionale Aufbewahrungswerte sind keine Pflichtentscheidungen. + + + +## Grenzen + +Schaetzungen benoetigen gemessenes Volumen und aktuelle Limits. +Leere/Default-ACLs sind nicht automatisch privat oder sicher. +Demos beweisen keine Produktionsabdeckung. +Typisierte native Editor-Vorschlaege aendern nur den lokalen Entwurf; +Ausfuehrung bleibt getrennt. + + + +## Zugangsdaten + +Provisionierungszugang von Ingestion-/Dashboard-Zugang trennen. +Keine Grafana-Passwoerter, Service-Tokens, OTLP-Secrets oder rohen +Kunden-Logs im Chat. + + + +## Quellen + +Management-/Projekt-/Plattformvariablen und Manifest-/Engine-Bindung. +Nach Pruefung aktualisieren. Aktuelle Produktfakten und betriebliche +Qualifikation bleiben getrennt. diff --git a/landing-zone-configurator/docs/assistant-knowledge/platform-kubernetes.de.md b/landing-zone-configurator/docs/assistant-knowledge/platform-kubernetes.de.md new file mode 100644 index 0000000..eab2a33 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/platform-kubernetes.de.md @@ -0,0 +1,95 @@ + + +# Plattform-Kubernetes, KMS und Bastion + +[English](platform-kubernetes.md) | [Deutsch](platform-kubernetes.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Gemeinsame STACKIT-Kubernetes-Infrastruktur mit bewusst gewaehlten Netzen, +Node-Pools und unterstuetztem optionalem DNS, Monitoring, verschluesseltem +Speicher und Debug-Zugang erstellen. +Dies sind getrennte Entscheidungen, keine impliziten Teile einer SNA-Anfrage. + + + +## Accelerator-Vertrag + +Natives `platform_kubernetes` ist eine Map mit Schluesseln. +Eintraege definieren Region, Cluster (`name/version/node_pools/maintenance`), +`network`, `dns`, `observability`, `encrypted_volumes`, `debug_bastion` und +`role_assignments`. +Netzwerkeinstellungen umfassen `sna_enabled`, `network_area_key` und `prefix`; +Root loest native Area-Referenzen oder eine explizit gebundene externe Area auf. +Regionale Modulaufrufe waehlen eu01/eu02. +KMS-gestuetzte Storage-Class-Konfiguration unterscheidet sich von der +Aktivierung von Verschluesselung fuer alle Volumes. +Debug-Bastion ist ein getrenntes VM-/SSH-Zugangsfeature. +Geschuetztes `platform_kubernetes_kube_config_override` ist keine normale +Chat-Konfiguration. + + + +## Abhaengigkeiten + +SNA/Region fuer Corporate-Modus, Governance/Plattform-Ownership und +Zugangsdaten-Grundlagen. +DNS und Observability sind unabhaengige verschachtelte Optionen. +KMS benoetigt Rechte und kompatiblen Speicher; Namespaces verwenden den +unterstuetzten Cluster-/Provider-Pfad. +Public-Modus bedeutet nicht automatisch private Erreichbarkeit. + + + +## Dialog + +Workload-Groesse, private/oeffentliche Konnektivitaet, +Node-Pool-/System-Workload-Rollen, Verfuegbarkeit, Wartung, +Speicherverschluesselung und Betriebszugang erfragen. +Aktuelle Versionen/Maschinen/Zonen/Volumes verwenden, keine statischen +Default-SKUs. +Niemals eine Bastion erzeugen, SSH fuer alle Netze oeffnen oder Demos +aktivieren, nur um SNA zu testen. + + + +## Beispiele + +Synthetische Deaktivierung: `platform_kubernetes = {}`. +Ein aktivierter Eintrag benoetigt bestaetigte Cluster-/Node-Pool-Einstellungen; +ein /24-Netzpraefix oder Schluessel-Default reicht nicht fuer Zusagen +ueber 100 Workloads, Cluster-Quoten oder Isolation je Namespace. + + + +## Grenzen + +Native Editor-Vorschlaege unterstuetzen gepruefte oeffentliche +Cluster-/KMS-/Bastion-Einstellungen, keine Zugangsdaten oder Deployments. +Region, Praefixgrenzen, Node-Minimum/-Maximum, System-Pools und Area-Referenzen +validieren. Template-Defaults koennen regionsspezifische Zonen enthalten. +Cluster-interne Konnektivitaet, Provider-Zugang, KMS-Nutzung und Node-Gesundheit +benoetigen getrennte echte Ausfuehrungsqualifikation. + + + +## Zugangsdaten + +Provider-/KMS-Rechte, Kubernetes-Zugang und Bastion-SSH sind verschiedene +sichere Bindungen. +Niemals kubeconfig-Inhalte, private SSH-Schluessel oder KMS-Secret-Material +erfragen; extern gelieferte Overrides muessen mit dem nativen Vertrag +funktionieren. + + + +## Quellen + +Root-Aufrufe, Cluster-/Bastion-Variablen, Provider und gemeinsame Validierung +definieren den geprueften Umfang. +DNS-/Regions-/Provider- und Verschluesselungsaenderungen vor Generierung +erneut pruefen; Markdown zertifiziert keine Private-Cluster-Ausfuehrung. diff --git a/landing-zone-configurator/docs/assistant-knowledge/project-templates.de.md b/landing-zone-configurator/docs/assistant-knowledge/project-templates.de.md new file mode 100644 index 0000000..bff232c --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/project-templates.de.md @@ -0,0 +1,98 @@ + + +# Landing-Zone-Projekte und Anwendungstemplates + +[English](project-templates.md) | [Deutsch](project-templates.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Wiederverwendbare Public-/Corporate-Projektgrundlagen, keine +Anwendungsprovisionierung. + + + +## Accelerator-Vertrag + +Natives `landing_zones` unterstuetzt `corporate`, `region`, +`network_area_key`, `project_code`, `env`, `owner_email`, +`network_enabled/network_prefix_length`, `role_assignments`, `custom_roles`, +`observability`, `secretsmanager_enabled`. +Public-Instanzen setzen explizit `corporate=false`. +Plattformentwuerfe verwenden `projectTemplates` und Parameterrichtlinien, +keine persoenlichen Instanzfelder oder erfundene +Veroeffentlichungs-/Bestell-Terraform-Attribute. + + + +## Abhaengigkeiten + +Governance/Identitaet, SNA derselben Region fuer Corporate und getrennte +Zugangsdaten. Public ist kein Corporate-Spoke. +DNS, Secrets Manager und Observability sind getrennt. + + + +## Dialog + +Template-Setup ist ein Entwurf, auch bei Wechsel nach Audit/Git. +Neue Eintraege benoetigen `name`, `kind`, `region` und `settings`; +bestehende unterstuetzen Teilaktualisierungen mit stabilen +Schluesseln/Identitaeten. +Delegierte Benennung bedeutet fachliche Namen waehlen, nicht erneut nach +Namen fragen. +Zentrales Netz versus nur Internet bedeutet Corporate versus Public; +angeforderte lokale Netze setzen fuer beide `network_enabled=true`. +Gespeicherte Region, eindeutige Area derselben Region und native +Subnetz-Defaults wiederverwenden. +Neue Templates zusammenfuehren; nicht angeforderte Services weglassen, +nicht geerbtes Plattform-Audit/-Git. +Fehlende/mehrdeutige Entscheidungen und angeforderte +Anwendungs-Owner-Richtlinien erfragen. +Keine Sandboxes bedeutet keine Sandbox-Erstellung, nicht das Ueberspringen +von Public-/Corporate-Setup. +Nicht betroffene Templates nicht ohne Zustimmung entfernen. +100 Projekte beschreibt Kapazitaet, nicht 100 generierte Beispiele oder +eine Template-Quote. +Aus effektiven Praefixen berechnen und Plattform-/Firewall-/Zukunftsbereiche +reservieren. + + + +## Beispiele + +Public-Instanzen verwenden `corporate=false`. +`network_prefix_length=24` ueberschreibt einen SNA-/25-Default. +Dies sind Fragmente, keine automatischen Projekterstellungsanfragen. + + + +## Grenzen + +Gepruefte native Einstellungen/Richtlinien koennen vorgeschlagen, nicht +veroeffentlicht, bestellt oder provisioniert werden. +Region, DNS-/Area- und Namespace-Referenzen muessen passen. +Leere Rollen/ACLs beweisen kein Least Privilege. +Quoten/nutzbare Adressen benoetigen aktuelle Pruefungen; +theoretische Subnetzzahlen sind keine Garantie. + + + +## Zugangsdaten + +Provisionierung, delegierte Owner-Zugangsdaten, Workload-Zugang und +Runtime-Freigaben sind getrennt. +Keine Secrets/Profil-IDs im Modellkontext oder in Exporten; +externe Ausfuehrung benoetigt explizite Bindungen. + + + +## Quellen + +Root-/Landing-Zone-Variablen und gemeinsame Template-/Compiler-/ +Validierungsvertraege. +Policy-/Identitaets-/Exportaenderungen erneut pruefen; +Anwendungslebenszyklus bleibt getrennt. diff --git a/landing-zone-configurator/docs/assistant-knowledge/sandbox-projects.de.md b/landing-zone-configurator/docs/assistant-knowledge/sandbox-projects.de.md new file mode 100644 index 0000000..2a5e140 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/sandbox-projects.de.md @@ -0,0 +1,87 @@ + + +# Sandbox-Projekte + +[English](sandbox-projects.md) | [Deutsch](sandbox-projects.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Explizit angeforderte experimentelle Projekte mit klarer Ownership unter +der Sandbox-Hierarchie erstellen, ohne sie als Corporate-Spokes oder Cluster +darzustellen. + + + +## Accelerator-Vertrag + +Natives `sandboxes` ist eine Liste aus `project_name`, +`project_owner_email` und optional `owner_emails`. +Root erstellt das Sandbox-Modul nur bei nicht leerer Liste und verwendet +den Sandbox-Ordner der Governance sowie ein abgeleitetes Namenspraefix. +Sandbox-Erstellung aktiviert keine Netzwerk-/DNS-/Secrets-Manager-Optionen +des Landing-Zone-Projekts. +Das gemeinsame Dokument erhaelt stabile Sandbox-Identitaeten bei +Bearbeitung/Import. + + + +## Abhaengigkeiten + +Governance-/Identitaetsgrundlagen und Provider-Autorisierung. +Ein optionaler externer Anwendungsworkflow ist von dieser nativen Liste +getrennt; eine Wissensabhaengigkeit ist keine Anfrage zur Erstellung +von SNA oder Firewall fuer Sandbox-Eintraege. + + + +## Dialog + +Owner jeder Sandbox, Zweck und erforderliche Isolation erfragen. +Lebenszyklus, Budgetkontrollen und Ablauf als getrennte explizite +Anforderungen behandeln, nicht als automatisch durch das Label Sandbox +implementierte Features. +Keine 100 Sandboxes aus einer Schaetzung spaeterer Projektzahlen +einer Organisation erfinden. + + + +## Beispiele + +Synthetische Deaktivierung: `sandboxes = []`. +Eine neue Sandbox benoetigt bestaetigten `project_name` und +`project_owner_email`; optionale weitere Owner benoetigen explizite Auswahl. +Dieses Listenfragment ist keine Erlaubnis, bestehende deployte Projekte +zu entfernen. + + + +## Grenzen + +Native Editor-Vorschlaege unterstuetzen gepruefte Sandbox-Konfiguration; +Plattformtemplates sind keine deployten Instanzen. +Dieses native Modul verspricht weder automatischen Ablauf noch +Kostenobergrenze, Corporate-Routing oder Anwendungsveroeffentlichung. +Loeschen von Konfigurationseintraegen benoetigt getrennten geprueften Plan +und Autorisierung; es ist kein Aufraeumen im Gespraech. + + + +## Zugangsdaten + +Provider-/Resource-Manager-Rechte bleiben extern; Owner-E-Mail ist weder +Zugangsdatenwert noch Freigabenachweis. +Niemals Passwoerter, Rollen-Secrets oder Tokens erfragen. + + + +## Quellen + +Root-Sandbox-Verdrahtung, Modulvariablen und gemeinsame Dokumentidentitaeten +sind Manifest-Autoritaeten. +Listen-/Identitaets-/native Exportaenderungen vor Neugenerierung erneut +pruefen; Provider-Quoten und Lebenszyklusverhalten benoetigen getrennte +Qualifikation. diff --git a/landing-zone-configurator/docs/assistant-knowledge/sna.de.md b/landing-zone-configurator/docs/assistant-knowledge/sna.de.md new file mode 100644 index 0000000..ba14526 --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/sna.de.md @@ -0,0 +1,103 @@ +# STACKIT Network Areas (SNA) + +[English](sna.md) | [Deutsch](sna.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +SNA ist die STACKIT Network Area fuer zentrale Projektvernetzung, nicht AWS VPC, +Shared VPC oder Direct Connect. Von Firewall, VPN und externen Standorten +unterscheiden. + + + +## Accelerator-Vertrag + +Native Einzelform: `connectivity.network_area`; Map: +`connectivity.network_areas` mit stabilen Schluesseln; regionale Form: +`connectivity_regions`. Formen niemals mischen. +Area-Felder: `ranges`, `transfer_network` (IPv4-CIDRs), `min_prefix_length`, +`max_prefix_length`, `default_prefix_length`, optional `name/default_nameservers`. +Praefixreihenfolge: `min <= default <= max`, Ganzzahlen in 0..32. +Backend-Patch-Schema und gemeinsamer Compiler entscheiden ueber editierbare +Faehigkeiten, nicht der Wissenstext. + + + +## Abhaengigkeiten + +Zugangsdaten-/Governance-Grundlagen gelten. Corporate-Projekte benoetigen eine +Area in derselben Region; ausgelassenes Corporate behaelt den Corporate-Default. +Referenzierte Area-Schluessel erhalten. Projektanzahl garantiert keine Quote. +OPNsense ist die unterstuetzte zentrale Firewall, nicht Palo Alto/Fortinet/AWS +Network Firewall; eine SNA impliziert niemals deren Aktivierung. + + + +## Dialog + +Kontext/Antworten wiederverwenden; hoechstens drei fehlende Angaben erfragen: +ungenutzter Pool, Projekt-Subnetzgroesse und freies Transfer-Subnetz. +CIDRs und erforderliche Kommunikation erklaeren, keine erfundenen +Isolationsschalter. Ein /16 enthaelt vor Reservierungen 256 /24-Netze: +Arithmetik, keine Quote. Ein /16 enthaelt 512 /25-Netze; /25 hat 128 Adressen, +nicht 128 Projekt-Subnetze. Infrastrukturreservierungen reduzieren die +nutzbare Kapazitaet. Ein vorgeschlagener Pool ist eine Annahme, bis seine freie +Verwendbarkeit bestaetigt ist. +Sobald Eingaben bekannt sind, einen SNA-Patch statt eines weiteren Fragebogens +vorschlagen. Unveraenderte Firma/Eigentuemer/Region nicht erneut abfragen; keine +Firewall-/VPN-/Secret-Versionen erfragen, wenn diese spaeter folgen. +Geerbte Firewall-/DNS-Werte sind keine Zustimmung: Vor widerspruechlichen Pools +oder aktivierten Services warnen, ohne sie still zu aendern. +Explizite kombinierte SNA-/Firewall-Anfragen behalten Firewall-/HA-Anforderungen: +Vollstaendige gespeicherte SNA wiederverwenden und den Firewall-Vertrag +fortsetzen, statt kuenstlich "SNA zuerst" einzuschraenken. +Fehlende SNA-Eingaben bleiben echte Abhaengigkeiten. +Projektspezifische Praefixe ueberschreiben SNA-Defaults. + + + +## Beispiele + +Synthetischer bestaetigter Pool `10.64.0.0/16`, Transfer `10.63.0.0/24`, +fest /24, `eu01`/Schluessel `default`, Firewall spaeter. +`network_areas.default` enthaelt diese Felder; in vorhandenen +Einzelentwuerfen `network_area` beibehalten. Keine implizite Firewall/Routen. +Native tfvars exportieren, kein freies Terraform. + + + +## Grenzen + +Der spezialisierte SNA-Dialog unterstuetzt Einzel-/Map-Hinzufuegen/-Bearbeiten. +Andere gepruefte oeffentliche Einstellungen nutzen typisierte native +Editor-Vorschlaege, niemals implizite Migrationen oder Ausfuehrung. +Firewall nutzt ihren getrennten geprueften zentralen Infrastruktur-/HA-Patch-Vertrag, +nicht einen impliziten Bestandteil der SNA. +Unbekannte Importe ausserhalb des Modellkontexts erhalten. +Vor Anzeige/Annahme validieren; nur explizite autorisierte Annahme speichert. +Niemals Deployment behaupten. Vollstaendige Ueberlappungs-, Quoten-, +Verfuegbarkeits- und Firewall-Containment-Pruefungen bleiben getrennt; +saubere Kompilierung ist kein Nachweis. Nur gepruefte Editor-Pfade duerfen +sich aendern; geschuetzte Eingaben bleiben ausgeschlossen. + + + +## Zugangsdaten + +Externe Provider-Zugangsdaten/aktuelle Rechte sind fuer Provisionierung +erforderlich, nicht fuer reine Entwurfsberatung. +Keine Schluessel, Passwoerter, IDs, States, Plaene oder Profile im Modellkontext; +keine fehlenden Berechtigungen erfinden. + + + +## Quellen + +Manifest-Hashes binden lokale Konnektivitaets-/Validierungsquellen. +Externe Provider-Links dienen der Information, nicht als aktuelles +Laufzeitverhalten. Vertragsaenderungen erneut pruefen; Assistant-, +Common-Configuration- und Identitaetstests bleiben getrennte Nachweise. diff --git a/landing-zone-configurator/docs/assistant-knowledge/vpn.de.md b/landing-zone-configurator/docs/assistant-knowledge/vpn.de.md new file mode 100644 index 0000000..38160eb --- /dev/null +++ b/landing-zone-configurator/docs/assistant-knowledge/vpn.de.md @@ -0,0 +1,94 @@ +# Site-to-Site-VPN + +[English](vpn.md) | [Deutsch](vpn.de.md) + +Deutsche Lesefassung. Der Assistant liest ausschliesslich die englische Quelle. + + + +## Zweck + +Explizit angeforderte externe Netze ueber unterstuetzte Site-to-Site-VPN-Gateways +und Tunnel mit der Plattform verbinden. +VPN ist fuer Projekt-zu-Projekt-Kommunikation innerhalb einer SNA nicht +erforderlich und darf nicht in eine SNA-zuerst-Aufgabe eingefuehrt werden. + + + +## Accelerator-Vertrag + +Natives `connectivity.vpn` und unterstuetzte `connectivity_regions`-Eintraege +tragen Gateway, Plan, Routing-Typ, Verbindungen, Tunnel-Peers, Routen/Subnetze +und die vom Root-Schema definierten IKE-/IPsec-Einstellungen. +`vpn_pre_shared_keys` ist eine getrennte geschuetzte Eingabe. +Tatsaechliche Gateway-/Verbindungs-/Tunnelschluessel verwenden; Vertrag nicht +abflachen oder beliebige VPN-Appliances erfinden. +Regionale Root-Aufrufe existieren; Service-Verfuegbarkeit und Plan-Kompatibilitaet +benoetigen weiterhin autorisierte aktuelle Pruefungen. +Native Defaults: `plan_id = "p100"` und `routing_type = "ROUTE_BASED"` +(nicht `static`/`dynamic`). Beide Tunnel verwenden native Peering-, +`phase1`- und `phase2`-Einstellungen. + + + +## Abhaengigkeiten + +SNA-Routing, bestaetigte nicht ueberlappende lokale/entfernte Netze, +erreichbare Peers und getrennte Zugangsdaten-Bindungen. +Oeffentliche PIM-Produktdaten beweisen keine Verfuegbarkeit fuer Zielprojekt +oder Region. Eine Abrechnungs-SKU ist keine Plan-ID. + + + +## Dialog + +Zuerst bestaetigen, dass externe Konnektivitaet jetzt benoetigt wird. +Standortanzahl, Peer-Faehigkeiten, benoetigten Durchsatz/Verbindungen, +lokale/entfernte Netze und Verfuegbarkeit erfragen. +Labels und fachliche Anforderungen verwenden, keine Plan-IDs anfordern. +Bei Auswahl aktuelle PIM-Attribute mit autorisierten Planoptionen abgleichen; +fehlende eu02-Daten nicht durch eu01 ersetzen. +Niemals PSKs oder private Schluessel erfragen. + + + +## Beispiele + +Synthetischer Wunsch: ein freigegebener externer Standort, zwei Tunnel, sofern +der bestaetigte Verbindungsvertrag sie vorsieht, explizite Peer-Subnetze. +`connectivity.vpn = null` deaktiviert diese optionale Konfiguration. +Dieses Feldfragment ist kein vollstaendiger Gateway-Vorschlag und enthaelt +niemals einen Preshared-Key. + + + +## Grenzen + +Native Editor-Vorschlaege unterstuetzen gepruefte oeffentliche VPN-Einstellungen, +keine Zugangsdaten. Annahme aendert nur den Entwurf. +Kompatible Verschluesselung, Peer-Routen, Leistung oder Failover nicht aus +einem Plannamen ableiten. +Plaene, Quoten und Tunnelzustand sind aktuelle Betriebsfakten. +Konfiguration beweist keinen Paketfluss; Routing- und Ueberlappungspruefungen +bleiben getrennt. + + + +## Zugangsdaten + +Provider-Zugriff und Tunnel-PSKs nutzen getrennte extern bereitgestellte +Bindungen. PSK-Werte niemals ueber das Modell anfordern oder exportieren. +Schluesselrotation und Gateway-Erstellung benoetigen explizite autorisierte +Ausfuehrung, keine Gespraechsempfehlung. +`vpn_pre_shared_keys` je Verbindung/Tunnel ueber +`TF_VAR_vpn_pre_shared_keys` oder gitignorierte tfvars ausserhalb des +Assistants bereitstellen. + + + +## Quellen + +Root-Variablen, Konnektivitaetsverdrahtung und VPN-Implementierung sind +Manifest-Quellen. Regionale/Plan-/Tunnel-Vertragsaenderungen vor Neugenerierung +erneut pruefen. Aktuelle Kataloge/PIM bleiben separat geladene Fakten, +keine eingefrorene Markdown-SKU-Liste. diff --git a/landing-zone-configurator/docs/assistant-test-catalogue.json b/landing-zone-configurator/docs/assistant-test-catalogue.json index 124e763..cf7c911 100644 --- a/landing-zone-configurator/docs/assistant-test-catalogue.json +++ b/landing-zone-configurator/docs/assistant-test-catalogue.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "status": "field-inventory-and-smoke-corpus-not-ai-qualification", "engineRevision": "a256f6896d11134fdc351786f1be5eba4e56b2e2", - "knowledgeSha256": "601ad8cd6a1e257f5f95207493e6df5a22b2cfd67fc84c7655d67ac36bcb4c38", + "knowledgeSha256": "acbd374589d2a507a85c4241d9f26406ec63aed95de8e170bd0fe40f6306706d", "sourceDigests": { "scripts/assistant-scenarios.ts": "441273d9af541a14185062728a9f9a7044df0e8a7c51645a53eb970a341867d9", "scripts/assistant-tests.ts": "fb1ba4a3438fbcd6d12c0a87d9bc9beeae8066bb5b691a7e2901635a842bb5df" diff --git a/landing-zone-configurator/docs/brand-assets.de.md b/landing-zone-configurator/docs/brand-assets.de.md new file mode 100644 index 0000000..427a131 --- /dev/null +++ b/landing-zone-configurator/docs/brand-assets.de.md @@ -0,0 +1,23 @@ + + +# STACKIT Markenassets + +[English](brand-assets.md) | [Deutsch](brand-assets.de.md) + +Referenz: [Nebula Styleguide](https://styleguide.stackit.schwarz/), vom Benutzer +für den Abgleich bereitgestellt. Die folgenden Originalassets des öffentlichen +STACKIT Portals werden lokal ausgeliefert, damit die Anwendung keine Fonts oder +Logos zur Laufzeit von fremden Origins nachladen muss. + +Abruf: 2026-09-30. Ablage: `app/apps/web/public/brand/`. +Diese Marken- und Schriftassets sind keine Eigenentwicklung des Configurators; +die Repository-Lizenz wird hierdurch nicht auf sie ausgeweitet. + +| Datei | Quelle | SHA-256 | +| --- | --- | --- | +| `stackit.svg` | [Portal](https://portal.stackit.cloud/assets/img/logo-dark.svg) | `5153596c9adf5832ec72ed465151902fdf937f0c96bbf9cd1485066c020df4ba` | +| `DIN2014-normal.woff2` | [Portal](https://portal.stackit.cloud/assets/fonts/din2014/DIN2014-normal.woff2) | `7bb1b38a6bab0f67ca5df8d96e99b62a20d7390c30a5bdc06246966d51a740ed` | +| `DIN2014-bold.woff2` | [Portal](https://portal.stackit.cloud/assets/fonts/din2014/DIN2014-bold.woff2) | `59dc6f07523bdae94dbe6f2ea938c19c44286e9a5b78e51566a680851fbf054b` | +| `UniviaProMedium-normal.woff2` | [Portal](https://portal.stackit.cloud/assets/fonts/univiapro/UniviaProMedium-normal.woff2) | `8e1c6765901100d47f72e74b53c20f10d69670d0b7466067ee35d23e84bbcaf4` | + +DIN 2014: 400/700; Univia Pro Medium: 500. `font-display: swap` mit System-Fallback. diff --git a/landing-zone-configurator/docs/brand-assets.md b/landing-zone-configurator/docs/brand-assets.md index afd7ffb..9cab6fc 100644 --- a/landing-zone-configurator/docs/brand-assets.md +++ b/landing-zone-configurator/docs/brand-assets.md @@ -1,19 +1,22 @@ -# STACKIT Markenassets + +# STACKIT brand assets -Referenz: [Nebula Styleguide](https://styleguide.stackit.schwarz/), vom Benutzer -für den Abgleich bereitgestellt. Die folgenden Originalassets des öffentlichen -STACKIT Portals werden lokal ausgeliefert, damit die Anwendung keine Fonts oder -Logos zur Laufzeit von fremden Origins nachladen muss. +[English](brand-assets.md) | [Deutsch](brand-assets.de.md) -Abruf: 2026-09-30. Ablage: `app/apps/web/public/brand/`. -Diese Marken- und Schriftassets sind keine Eigenentwicklung des Configurators; -die Repository-Lizenz wird hierdurch nicht auf sie ausgeweitet. +Reference: [Nebula Styleguide](https://styleguide.stackit.schwarz/), provided by the user +for comparison. The following original assets from the public +STACKIT Portal are served locally so the application does not need to load fonts or +logos from external origins at runtime. -| Datei | Quelle | SHA-256 | +Retrieved: 2026-09-30. Location: `app/apps/web/public/brand/`. +These brand and font assets were not developed by the Configurator; +the repository license does not thereby extend to them. + +| File | Source | SHA-256 | | --- | --- | --- | | `stackit.svg` | [Portal](https://portal.stackit.cloud/assets/img/logo-dark.svg) | `5153596c9adf5832ec72ed465151902fdf937f0c96bbf9cd1485066c020df4ba` | | `DIN2014-normal.woff2` | [Portal](https://portal.stackit.cloud/assets/fonts/din2014/DIN2014-normal.woff2) | `7bb1b38a6bab0f67ca5df8d96e99b62a20d7390c30a5bdc06246966d51a740ed` | | `DIN2014-bold.woff2` | [Portal](https://portal.stackit.cloud/assets/fonts/din2014/DIN2014-bold.woff2) | `59dc6f07523bdae94dbe6f2ea938c19c44286e9a5b78e51566a680851fbf054b` | | `UniviaProMedium-normal.woff2` | [Portal](https://portal.stackit.cloud/assets/fonts/univiapro/UniviaProMedium-normal.woff2) | `8e1c6765901100d47f72e74b53c20f10d69670d0b7466067ee35d23e84bbcaf4` | -DIN 2014: 400/700; Univia Pro Medium: 500. `font-display: swap` mit System-Fallback. +DIN 2014: 400/700; Univia Pro Medium: 500. `font-display: swap` with system fallback. diff --git a/landing-zone-configurator/docs/cicd.de.md b/landing-zone-configurator/docs/cicd.de.md new file mode 100644 index 0000000..7f5dcd4 --- /dev/null +++ b/landing-zone-configurator/docs/cicd.de.md @@ -0,0 +1,100 @@ + + +# CI/CD für den Landing Zone Configurator + +[English](cicd.md) | [Deutsch](cicd.de.md) + +Status: Validierung, Bootstrap-/Backend- und Plattform-Pipelines sind implementiert und erfolgreich ausgeführt. OpenTofu wird direkt in den Workflows aufgerufen, mit normalen Live-Logs. Runtime und App-Release einschließlich Verbindungstests aus CF sind erfolgreich abgenommen; Drift bleibt geplant. Erste Umgebung: **lzc-dev / eu01**. Aktuelle Bedienung: [CI-Betrieb](../infra/ci/README.de.md). + + + +## Getrennte Lebenszyklen + +| Workflow | Auslöser | Verantwortung | +| --- | --- | --- | +| `validate-configurator.yml` (vorhanden) | PR, main, Feature-Branch, manuell | App-Prüfungen, IaC-Validierung und Mock-Tests ohne Cloud-Zugang | +| `configurator-bootstrap.yml` | Feature-Push: Plan; manuell auf main vorbereitet | State-Infrastruktur erstellen, Versionierung konfigurieren, später Credentials rotieren | +| `configurator-platform.yml` | Infrastrukturänderungen auf Feature-Branch: Plan; manuell auf main vorbereitet | Plattform-IaC planen, geprüften Plan anwenden | +| `configurator-runtime.yml` | Runtime-/CI-Änderungen auf Feature-Branch; manuell auf main vorbereitet | CF-Space, Organisationsmitgliedschaft, Space-Rolle und Laufzeitbenutzer | +| `configurator-release.yml` | App-/Release-Dateien auf Feature-Branch; manuell auf main vorbereitet | Web/API bauen, prüfen, gepacktes Release nach CF deployen und Verbindungen aus CF testen | +| `configurator-drift.yml` | Optional zeitgesteuert/manuell | Infrastruktur-Drift erkennen und melden; zunächst kein automatisches Apply | + +Ein normales App-Release startet weder Bootstrap noch Plattform-Apply. Relevante Pfade umfassen auch gemeinsame Deployment-Skripte, Lockfiles und die jeweilige Workflow-Datei. Änderungen ausschließlich am Accelerator lösen keinen Configurator-Release aus. Kunden-Landing-Zone-Deployments bleiben ein eigener, mandantenisolierter Runner-Ablauf und erhalten keine Betreiber-CI-Credentials. + + + +## State und Credentials + +Ein unabhängiger Verwaltungs-Bucket wurde durch `seed` und `seed-protection` angelegt und versioniert. Bootstrap und Backend speichern dort ihre verschlüsselten States. Die Plattform verwendet den ebenfalls versionierten Workload-State-Bucket. Jeder Root hat einen eigenen dauerhaft verwahrten Schlüssel; ein fehlender Deployment-Schlüssel führt zum Abbruch. Geschützte Environment-Secrets liefern die vorhandenen Schlüssel und Credentials an CI, keine lokale Seed-Datei wird benötigt. + +Native S3-Sperren haben den Integrationstest nicht bestanden. Die bestätigte Übergangslösung erlaubt ausschließlich gemeinsam serialisierte CI-Applies; direkte parallele Zugriffe durch andere Credential-Inhaber sind betrieblich ausgeschlossen. GitHub-Artefakte dienen nur für Review und Recovery, nicht als dauerhaftes State-Backend. + +Der seltene Bootstrap benötigt weiterhin Ablaufüberwachung und Rotation der befristeten S3-Credentials einschließlich Aktualisierung aller Consumer. Unabhängige Schlüsselverwahrung und vollständige Restore-Abnahme bleiben eigene Betriebsaufgaben. + + + +## Infrastruktur-Pipeline + +1. Vertrauenswürdigen Commit des freigegebenen Branches auschecken; gepinnte Tools und Provider-Lockfiles verwenden. +2. Root und Umgebung aus fester Allowlist wählen; Remote-State und bestehende Schlüssel laden. +3. Plan erstellen und verschlüsselt speichern. Manifest bindet Commit, Umgebung, Root, Eingabedigest, Lockfile-Digest, Plan-Hash und kurze Gültigkeit. Normale OpenTofu-Plan-Ausgabe live anzeigen; keine vollständigen State-/Plan-JSONs oder Credential-Outputs veröffentlichen. +4. Apply-Job nutzt ein geschütztes GitHub Environment und exakt das geprüfte Plan-Artefakt desselben vertrauenswürdigen Runs. Freigabe gilt für diesen Plan. Abgelaufene oder veraltete Plans werden neu erstellt und erneut geprüft. +5. Da natives S3-Locking nicht zuverlässig funktioniert, übernimmt übergreifende GitHub-Concurrency pro Umgebung serialisiert mutierende Plattform-/Runtime-/Release-Jobs; `cancel-in-progress: false` für laufende Mutationen. Keine Fairness oder FIFO-Reihenfolge voraussetzen, ältere Releases vor Deployment abweisen. +6. Outputs nur gezielt und geschützt an Consumer übergeben, Recovery und Audit protokollieren. + +Bootstrap und Backend-Versionierung laufen nacheinander. Nach Bootstrap-Apply wird der Backend-Plan mit den jetzt vorhandenen Zugangsdaten erstellt. Plattform folgt nach nachgewiesener Versionierung unter dem bestätigten CI-only-Betriebsmodell. Runtime benötigt anschließend die CF-Zugänge der Plattform. Kein Plan über noch unbekannte Provider-Credentials und kein routinemäßiges `-target`. + + + +## Anwendung häufig und unabhängig ausliefern + +Der implementierte Release-Workflow prüft und baut Web/API einmal; der Worker folgt. Er und erstellt ein über Commit und SHA-256 identifizierbares Release. Redeploy und spätere Promotion verwenden dasselbe geprüfte Paket; historische Artefakte sind entsprechend der Rollback-Frist dauerhaft aufzubewahren. Kein erneuter Build beim Rollback. + +Der Lifecycle-Owner wird eindeutig festgelegt: OpenTofu verwaltet Dienste, CF-Org/Spaces, Rollen und gemeinsame Service-Instanzen. Der deklarative Release-Prozess verwaltet App-Objekte, App-Routen, App-Bindings, Prozesskonfiguration und Code. Diese Ressourcen werden nicht zusätzlich vom Runtime-Root verwaltet. So bleiben auch App-Provisionierung und Bindings als Code reproduzierbar. + +Ablauf: Release prüfen → kompatible DB-Migration mit separater Migrationsidentität ausführen → CF-Deployment → Readiness-/Smoke-Tests → Release markieren. Rolling Deployment ist die bevorzugte Strategie, sofern Foundation, Quota und App-Prozesse es unterstützen; dies ist auf der konkreten STACKIT-Foundation noch zu prüfen. Worker benötigen Drain/Lease-Semantik, damit beim Austausch keine Jobs doppelt laufen. Destruktive DB-Migrationen folgen zeitversetzt; ein App-Rollback setzt keine Datenbank automatisch zurück. + +Entwicklung: nach erfolgreicher Validierung auf main automatisch deployen, sobald die Umgebung betriebsbereit ist. Produktion später: explizite Promotion des geprüften Releases mit Freigabe. Ein manueller Redeploy wählt eine bekannte Release-ID, keinen beliebigen Fork oder Shell-Befehl. + + + +## Identitäten und Vertrauensgrenzen + +- Bootstrap: gesonderte Betreiberidentität mit den notwendigen Projekt-/Object-Storage-Rechten. +- Plattform: scoped STACKIT-Zugang; App-Release erhält diesen Zugang nicht. +- Release-Zielbild: eigene CF-Deployment-Identität nur für den Ziel-Space. Der erste Entwicklungsstand nutzt noch den vorhandenen Org-Manager und liest dessen Zugang aus dem verschlüsselten Plattform-State; App-Zugänge sind davon getrennt. DB-Migrationen sind noch nicht implementiert. +- Persönliche GitHub-/STACKIT-Zugänge der Kunden bleiben in der Anwendung und gelangen nicht in Betreiber-Workflows. +- GitHub Environments trennen mindestens Bootstrap, Plattform und App je Umgebung. Environment-Regeln und Branch-Schutz werden als Repository-Konfiguration per IaC/API verwaltet; initiale GitHub-Administrationsberechtigung und Secret-Einspeisung bleiben eine notwendige Vertrauensbasis. +- Secrets niemals aus PR-Code zugänglich machen; kein privilegiertes `pull_request_target` mit Checkout von Fork-Code. Actions auf Commit-SHAs pinnen, minimale Token-Rechte, keine Shell-Ausgabe von Credentials. +- Kurzlebige föderierte Identitäten bevorzugen, sofern STACKIT sie für diese Dienste nachweislich unterstützt. Bis dahin rotierbare, geschützte Service-Account-Zugänge; GitHub-OIDC-Kompatibilität nicht voraussetzen. + +Die Verfügbarkeit von Environment-Freigaberegeln hängt vom GitHub-Tarif und der Repository-Sichtbarkeit ab. Vor Aktivierung prüfen. Runner-Netzzugang zu CF, S3 und privaten Datenbankendpunkten ebenfalls prüfen; erforderliche private Runner werden getrennt von untrusted PR-Jobs betrieben und über IaC provisioniert. + + + +## Umsetzungsreihenfolge und Abnahme + +- [x] Lebenszyklen und Credentials trennen; Validierung aller sechs IaC-Roots und der App. +- [x] Verwaltungs- und Workload-Backend einrichten, Versionierung und State-Verschlüsselung prüfen. +- [x] GitHub-Environments und Freigaben einrichten; bestehende Deployment-Schlüssel geschützt übergeben. +- [x] Bootstrap-/Backend- und Plattform-Pipelines ausführen; Plattform-Recovery und anschließenden No-op nachweisen. +- [x] Native S3-Sperren testen und als nicht zuverlässig dokumentieren; CI-only-Betrieb explizit festlegen. +- [x] OpenTofu direkt in den Workflows aufrufen; Live-Logs, Standard-Timeout und geschützte State-Sicherung. +- [ ] Unabhängige Schlüsselverwahrung, vollständiger Restore-Prozess und automatisierte Credential-Rotation. +- [x] CF-Runtime, Backend-Umgebungsvariablen und Konnektivitätstests aus CF. +- [ ] Release-Manifeste, Paketierung, Migrationen, Readiness und Worker-Drain. +- [ ] Zwei App-Releases, unabhängigen Redeploy und Rollback ohne Infrastrukturänderung nachweisen. +- [ ] Optionalen Drift-Workflow und Alarmierung aktivieren. + +Nächster Ausbau ist die CF-Runtime mit Zugriffstests zu Datenbank und Secrets Manager. Die bisherige einmalige Recovery wurde aus dem normalen Deployment-Pfad entfernt; Vorfall und Wiederherstellung stehen im [Plattform-Betriebsstand](platform-readiness.de.md). + + + +## Quellen + +- [GitHub Deployment Environments](https://docs.github.com/en/actions/concepts/workflows-and-actions/deployment-environments) +- [GitHub Deployment-Steuerung und Concurrency](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/control-deployments) +- [GitHub Environment-Verfügbarkeit und Einrichtung](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments) +- [Cloud Foundry Rolling Deployments](https://docs.cloudfoundry.org/devguide/deploy-apps/rolling-deploy.html) + +Details zum implementierten Release und seinen Grenzen: [CF-Release](../deploy/cloud-foundry/README.de.md). diff --git a/landing-zone-configurator/docs/cicd.md b/landing-zone-configurator/docs/cicd.md index 1498476..29da10d 100644 --- a/landing-zone-configurator/docs/cicd.md +++ b/landing-zone-configurator/docs/cicd.md @@ -1,82 +1,92 @@ -# CI/CD für den Landing Zone Configurator + +# CI/CD for the Landing Zone Configurator -Status: Validierung, Bootstrap-/Backend- und Plattform-Pipelines sind implementiert und erfolgreich ausgeführt. OpenTofu wird direkt in den Workflows aufgerufen, mit normalen Live-Logs. Runtime und App-Release einschließlich Verbindungstests aus CF sind erfolgreich abgenommen; Drift bleibt geplant. Erste Umgebung: **lzc-dev / eu01**. Aktuelle Bedienung: [CI-Betrieb](../infra/ci/README.md). +[English](cicd.md) | [Deutsch](cicd.de.md) -## Getrennte Lebenszyklen +Status: validation, bootstrap/backend and platform pipelines are implemented and have run successfully. OpenTofu is invoked directly in the workflows, with normal live logs. Runtime and app release, including connection tests from CF, have passed acceptance; drift remains planned. First environment: **lzc-dev / eu01**. Current operation: [CI operations](../infra/ci/README.md). -| Workflow | Auslöser | Verantwortung | + +## Separate lifecycles + +| Workflow | Trigger | Responsibility | | --- | --- | --- | -| `validate-configurator.yml` (vorhanden) | PR, main, Feature-Branch, manuell | App-Prüfungen, IaC-Validierung und Mock-Tests ohne Cloud-Zugang | -| `configurator-bootstrap.yml` | Feature-Push: Plan; manuell auf main vorbereitet | State-Infrastruktur erstellen, Versionierung konfigurieren, später Credentials rotieren | -| `configurator-platform.yml` | Infrastrukturänderungen auf Feature-Branch: Plan; manuell auf main vorbereitet | Plattform-IaC planen, geprüften Plan anwenden | -| `configurator-runtime.yml` | Runtime-/CI-Änderungen auf Feature-Branch; manuell auf main vorbereitet | CF-Space, Organisationsmitgliedschaft, Space-Rolle und Laufzeitbenutzer | -| `configurator-release.yml` | App-/Release-Dateien auf Feature-Branch; manuell auf main vorbereitet | Web/API bauen, prüfen, gepacktes Release nach CF deployen und Verbindungen aus CF testen | -| `configurator-drift.yml` | Optional zeitgesteuert/manuell | Infrastruktur-Drift erkennen und melden; zunächst kein automatisches Apply | +| `validate-configurator.yml` (existing) | PR, main, feature branch, manual | App checks, IaC validation and mock tests without cloud access | +| `configurator-bootstrap.yml` | Feature push: Plan; prepared for manual use on main | Create state infrastructure, configure versioning, later rotate credentials | +| `configurator-platform.yml` | Infrastructure changes on feature branch: Plan; prepared for manual use on main | Plan platform IaC, apply reviewed Plan | +| `configurator-runtime.yml` | Runtime/CI changes on feature branch; prepared for manual use on main | CF space, organization membership, space role and runtime user | +| `configurator-release.yml` | App/release files on feature branch; prepared for manual use on main | Build and check web/API, deploy packaged release to CF and test connections from CF | +| `configurator-drift.yml` | Optional scheduled/manual | Detect and report infrastructure drift; initially no automatic Apply | -Ein normales App-Release startet weder Bootstrap noch Plattform-Apply. Relevante Pfade umfassen auch gemeinsame Deployment-Skripte, Lockfiles und die jeweilige Workflow-Datei. Änderungen ausschließlich am Accelerator lösen keinen Configurator-Release aus. Kunden-Landing-Zone-Deployments bleiben ein eigener, mandantenisolierter Runner-Ablauf und erhalten keine Betreiber-CI-Credentials. +A normal app release starts neither bootstrap nor platform Apply. Relevant paths also include shared deployment scripts, lockfiles and the respective workflow file. Changes exclusively to the Accelerator do not trigger a Configurator release. Customer Landing Zone deployments remain a separate, tenant-isolated Runner flow and receive no operator CI credentials. -## State und Credentials + +## State and credentials -Ein unabhängiger Verwaltungs-Bucket wurde durch `seed` und `seed-protection` angelegt und versioniert. Bootstrap und Backend speichern dort ihre verschlüsselten States. Die Plattform verwendet den ebenfalls versionierten Workload-State-Bucket. Jeder Root hat einen eigenen dauerhaft verwahrten Schlüssel; ein fehlender Deployment-Schlüssel führt zum Abbruch. Geschützte Environment-Secrets liefern die vorhandenen Schlüssel und Credentials an CI, keine lokale Seed-Datei wird benötigt. +An independent management bucket was created and versioned by `seed` and `seed-protection`. Bootstrap and backend store their encrypted states there. The platform uses the workload state bucket, which is also versioned. Each root has its own permanently retained key; a missing deployment key causes an abort. Protected environment secrets supply existing keys and credentials to CI; no local seed file is required. -Native S3-Sperren haben den Integrationstest nicht bestanden. Die bestätigte Übergangslösung erlaubt ausschließlich gemeinsam serialisierte CI-Applies; direkte parallele Zugriffe durch andere Credential-Inhaber sind betrieblich ausgeschlossen. GitHub-Artefakte dienen nur für Review und Recovery, nicht als dauerhaftes State-Backend. +Native S3 locks failed the integration test. The confirmed interim solution permits only jointly serialized CI Applies; direct parallel access by other credential holders is operationally prohibited. GitHub artifacts serve only review and recovery, not as a permanent state backend. -Der seltene Bootstrap benötigt weiterhin Ablaufüberwachung und Rotation der befristeten S3-Credentials einschließlich Aktualisierung aller Consumer. Unabhängige Schlüsselverwahrung und vollständige Restore-Abnahme bleiben eigene Betriebsaufgaben. +The infrequent bootstrap still requires expiry monitoring and rotation of temporary S3 credentials, including updates to all consumers. Independent key custody and full restore acceptance remain separate operational tasks. -## Infrastruktur-Pipeline + +## Infrastructure pipeline -1. Vertrauenswürdigen Commit des freigegebenen Branches auschecken; gepinnte Tools und Provider-Lockfiles verwenden. -2. Root und Umgebung aus fester Allowlist wählen; Remote-State und bestehende Schlüssel laden. -3. Plan erstellen und verschlüsselt speichern. Manifest bindet Commit, Umgebung, Root, Eingabedigest, Lockfile-Digest, Plan-Hash und kurze Gültigkeit. Normale OpenTofu-Plan-Ausgabe live anzeigen; keine vollständigen State-/Plan-JSONs oder Credential-Outputs veröffentlichen. -4. Apply-Job nutzt ein geschütztes GitHub Environment und exakt das geprüfte Plan-Artefakt desselben vertrauenswürdigen Runs. Freigabe gilt für diesen Plan. Abgelaufene oder veraltete Plans werden neu erstellt und erneut geprüft. -5. Da natives S3-Locking nicht zuverlässig funktioniert, übernimmt übergreifende GitHub-Concurrency pro Umgebung serialisiert mutierende Plattform-/Runtime-/Release-Jobs; `cancel-in-progress: false` für laufende Mutationen. Keine Fairness oder FIFO-Reihenfolge voraussetzen, ältere Releases vor Deployment abweisen. -6. Outputs nur gezielt und geschützt an Consumer übergeben, Recovery und Audit protokollieren. +1. Check out a trusted commit of the approved branch; use pinned tools and provider lockfiles. +2. Select root and environment from a fixed allowlist; load remote state and existing keys. +3. Create and store an encrypted Plan. The manifest binds commit, environment, root, input digest, lockfile digest, Plan hash and short validity. Display normal OpenTofu Plan output live; publish no full state/Plan JSON or credential outputs. +4. The Apply job uses a protected GitHub environment and exactly the reviewed Plan artifact from the same trusted run. Approval applies to this Plan. Expired or stale Plans are recreated and reviewed again. +5. Since native S3 locking does not work reliably, cross-workflow GitHub concurrency serializes mutating platform/runtime/release jobs per environment; `cancel-in-progress: false` for ongoing mutations. Do not assume fairness or FIFO ordering; reject older releases before deployment. +6. Pass outputs to consumers only selectively and under protection; log recovery and audit. -Bootstrap und Backend-Versionierung laufen nacheinander. Nach Bootstrap-Apply wird der Backend-Plan mit den jetzt vorhandenen Zugangsdaten erstellt. Plattform folgt nach nachgewiesener Versionierung unter dem bestätigten CI-only-Betriebsmodell. Runtime benötigt anschließend die CF-Zugänge der Plattform. Kein Plan über noch unbekannte Provider-Credentials und kein routinemäßiges `-target`. +Bootstrap and backend versioning run sequentially. After bootstrap Apply, the backend Plan is created with the now-existing credentials. The platform follows after proven versioning under the confirmed CI-only operating model. Runtime then needs the platform's CF credentials. No Plan with still-unknown provider credentials and no routine `-target`. -## Anwendung häufig und unabhängig ausliefern + +## Release the application frequently and independently -Der implementierte Release-Workflow prüft und baut Web/API einmal; der Worker folgt. Er und erstellt ein über Commit und SHA-256 identifizierbares Release. Redeploy und spätere Promotion verwenden dasselbe geprüfte Paket; historische Artefakte sind entsprechend der Rollback-Frist dauerhaft aufzubewahren. Kein erneuter Build beim Rollback. +The implemented release workflow checks and builds web/API once; the worker follows. It creates a release identifiable by commit and SHA-256. Redeploy and later promotion use the same reviewed package; historical artifacts must be retained durably according to the rollback period. No rebuild during rollback. -Der Lifecycle-Owner wird eindeutig festgelegt: OpenTofu verwaltet Dienste, CF-Org/Spaces, Rollen und gemeinsame Service-Instanzen. Der deklarative Release-Prozess verwaltet App-Objekte, App-Routen, App-Bindings, Prozesskonfiguration und Code. Diese Ressourcen werden nicht zusätzlich vom Runtime-Root verwaltet. So bleiben auch App-Provisionierung und Bindings als Code reproduzierbar. +The lifecycle owner is clearly defined: OpenTofu manages services, CF org/spaces, roles and shared service instances. The declarative release process manages app objects, app routes, app bindings, process configuration and code. These resources are not additionally managed by the runtime root. This keeps app provisioning and bindings reproducible as code too. -Ablauf: Release prüfen → kompatible DB-Migration mit separater Migrationsidentität ausführen → CF-Deployment → Readiness-/Smoke-Tests → Release markieren. Rolling Deployment ist die bevorzugte Strategie, sofern Foundation, Quota und App-Prozesse es unterstützen; dies ist auf der konkreten STACKIT-Foundation noch zu prüfen. Worker benötigen Drain/Lease-Semantik, damit beim Austausch keine Jobs doppelt laufen. Destruktive DB-Migrationen folgen zeitversetzt; ein App-Rollback setzt keine Datenbank automatisch zurück. +Sequence: check release → run compatible DB migration with a separate migration identity → CF deployment → readiness/smoke tests → mark release. Rolling deployment is preferred where supported by the foundation, quota and app processes; this still needs checking on the specific STACKIT foundation. Workers need drain/lease semantics so that replacement does not run jobs twice. Destructive DB migrations follow later; an app rollback does not automatically roll back a database. -Entwicklung: nach erfolgreicher Validierung auf main automatisch deployen, sobald die Umgebung betriebsbereit ist. Produktion später: explizite Promotion des geprüften Releases mit Freigabe. Ein manueller Redeploy wählt eine bekannte Release-ID, keinen beliebigen Fork oder Shell-Befehl. +Development: automatically deploy after successful validation on main once the environment is operational. Production later: explicit promotion of the reviewed release with approval. A manual redeploy selects a known release ID, not an arbitrary fork or shell command. -## Identitäten und Vertrauensgrenzen + +## Identities and trust boundaries -- Bootstrap: gesonderte Betreiberidentität mit den notwendigen Projekt-/Object-Storage-Rechten. -- Plattform: scoped STACKIT-Zugang; App-Release erhält diesen Zugang nicht. -- Release-Zielbild: eigene CF-Deployment-Identität nur für den Ziel-Space. Der erste Entwicklungsstand nutzt noch den vorhandenen Org-Manager und liest dessen Zugang aus dem verschlüsselten Plattform-State; App-Zugänge sind davon getrennt. DB-Migrationen sind noch nicht implementiert. -- Persönliche GitHub-/STACKIT-Zugänge der Kunden bleiben in der Anwendung und gelangen nicht in Betreiber-Workflows. -- GitHub Environments trennen mindestens Bootstrap, Plattform und App je Umgebung. Environment-Regeln und Branch-Schutz werden als Repository-Konfiguration per IaC/API verwaltet; initiale GitHub-Administrationsberechtigung und Secret-Einspeisung bleiben eine notwendige Vertrauensbasis. -- Secrets niemals aus PR-Code zugänglich machen; kein privilegiertes `pull_request_target` mit Checkout von Fork-Code. Actions auf Commit-SHAs pinnen, minimale Token-Rechte, keine Shell-Ausgabe von Credentials. -- Kurzlebige föderierte Identitäten bevorzugen, sofern STACKIT sie für diese Dienste nachweislich unterstützt. Bis dahin rotierbare, geschützte Service-Account-Zugänge; GitHub-OIDC-Kompatibilität nicht voraussetzen. +- Bootstrap: separate operator identity with the necessary project/Object Storage permissions. +- Platform: scoped STACKIT access; app release does not receive it. +- Release target model: separate CF deployment identity only for the target space. The initial development version still uses the existing org manager and reads its credentials from encrypted platform state; app credentials are separate. DB migrations are not yet implemented. +- Customers' personal GitHub/STACKIT credentials remain in the application and do not enter operator workflows. +- GitHub environments separate at least bootstrap, platform and app per environment. Environment rules and branch protection are managed as repository configuration through IaC/API; initial GitHub administrative permission and secret injection remain a necessary trust foundation. +- Never expose secrets to PR code; no privileged `pull_request_target` checking out fork code. Pin Actions to commit SHAs, use minimum token permissions, never print credentials in shell output. +- Prefer short-lived federated identities where STACKIT demonstrably supports them for these services. Until then, use rotatable, protected service-account credentials; do not assume GitHub OIDC compatibility. -Die Verfügbarkeit von Environment-Freigaberegeln hängt vom GitHub-Tarif und der Repository-Sichtbarkeit ab. Vor Aktivierung prüfen. Runner-Netzzugang zu CF, S3 und privaten Datenbankendpunkten ebenfalls prüfen; erforderliche private Runner werden getrennt von untrusted PR-Jobs betrieben und über IaC provisioniert. +Availability of environment approval rules depends on the GitHub plan and repository visibility. Check before enabling. Also check Runner network access to CF, S3 and private database endpoints; required private Runners are operated separately from untrusted PR jobs and provisioned through IaC. -## Umsetzungsreihenfolge und Abnahme + +## Implementation order and acceptance -- [x] Lebenszyklen und Credentials trennen; Validierung aller sechs IaC-Roots und der App. -- [x] Verwaltungs- und Workload-Backend einrichten, Versionierung und State-Verschlüsselung prüfen. -- [x] GitHub-Environments und Freigaben einrichten; bestehende Deployment-Schlüssel geschützt übergeben. -- [x] Bootstrap-/Backend- und Plattform-Pipelines ausführen; Plattform-Recovery und anschließenden No-op nachweisen. -- [x] Native S3-Sperren testen und als nicht zuverlässig dokumentieren; CI-only-Betrieb explizit festlegen. -- [x] OpenTofu direkt in den Workflows aufrufen; Live-Logs, Standard-Timeout und geschützte State-Sicherung. -- [ ] Unabhängige Schlüsselverwahrung, vollständiger Restore-Prozess und automatisierte Credential-Rotation. -- [x] CF-Runtime, Backend-Umgebungsvariablen und Konnektivitätstests aus CF. -- [ ] Release-Manifeste, Paketierung, Migrationen, Readiness und Worker-Drain. -- [ ] Zwei App-Releases, unabhängigen Redeploy und Rollback ohne Infrastrukturänderung nachweisen. -- [ ] Optionalen Drift-Workflow und Alarmierung aktivieren. +- [x] Separate lifecycles and credentials; validate all six IaC roots and the app. +- [x] Set up management and workload backends; check versioning and state encryption. +- [x] Set up GitHub environments and approvals; pass existing deployment keys under protection. +- [x] Run bootstrap/backend and platform pipelines; demonstrate platform recovery and subsequent no-op. +- [x] Test native S3 locks and document them as unreliable; explicitly define CI-only operation. +- [x] Invoke OpenTofu directly in workflows; live logs, standard timeout and protected state backup. +- [ ] Independent key custody, complete restore process and automated credential rotation. +- [x] CF runtime, backend environment variables and connectivity tests from CF. +- [ ] Release manifests, packaging, migrations, readiness and worker drain. +- [ ] Demonstrate two app releases, independent redeploy and rollback without infrastructure change. +- [ ] Enable optional drift workflow and alerting. -Nächster Ausbau ist die CF-Runtime mit Zugriffstests zu Datenbank und Secrets Manager. Die bisherige einmalige Recovery wurde aus dem normalen Deployment-Pfad entfernt; Vorfall und Wiederherstellung stehen im [Plattform-Betriebsstand](platform-readiness.md). +The next extension is CF runtime with access tests to the database and Secrets Manager. The previous one-off recovery was removed from the normal deployment path; incident and restoration are documented in [platform operational status](platform-readiness.md). -## Quellen + +## Sources - [GitHub Deployment Environments](https://docs.github.com/en/actions/concepts/workflows-and-actions/deployment-environments) -- [GitHub Deployment-Steuerung und Concurrency](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/control-deployments) -- [GitHub Environment-Verfügbarkeit und Einrichtung](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments) +- [GitHub deployment control and concurrency](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/control-deployments) +- [GitHub environment availability and setup](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments) - [Cloud Foundry Rolling Deployments](https://docs.cloudfoundry.org/devguide/deploy-apps/rolling-deploy.html) -Details zum implementierten Release und seinen Grenzen: [CF-Release](../deploy/cloud-foundry/README.md). +Details of the implemented release and its limitations: [CF release](../deploy/cloud-foundry/README.md). diff --git a/landing-zone-configurator/docs/cloud-product-catalogues.de.md b/landing-zone-configurator/docs/cloud-product-catalogues.de.md new file mode 100644 index 0000000..df0cbfe --- /dev/null +++ b/landing-zone-configurator/docs/cloud-product-catalogues.de.md @@ -0,0 +1,228 @@ + + +# STACKIT-Produktkataloge im Editor + +[English](cloud-product-catalogues.md) | [Deutsch](cloud-product-catalogues.de.md) + + + +## Zweck und aktueller Umfang + +Im primären STACKIT-Login-Modus lädt der Editor Produktoptionen automatisch mit dem bereits hinterlegten technischen STACKIT-Service-Account-Zugang des Platform Engineers. Eine weitere Profil-, Projekt- oder Regionswahl für den Katalog entfällt. Im Legacy-GitHub-Modus bleibt die explizite Auswahl eines eigenen Profils und Referenzprojekts erhalten. Zentrale Deployment-Credentials des Configurators werden niemals verwendet. Die Auswahlwerte unterstützen den Entwurf, ersetzen jedoch weder Accelerator-Validierung noch einen tatsächlichen Plan oder eine Quotenprüfung. + + + +## Automatischer Abruf im STACKIT-Modus + +`POST /api/v1/cloud-catalogues/automatic` nimmt ausschließlich `region` an und +verlangt Origin, CSRF sowie den zur Session passenden `x-lzc-tenant`-Header. +Der Server wählt das neueste eigene Credential-Profil des aktiven Tenants und +prüft die Metadaten gegen den gespeicherten Schlüssel. Es gibt keine Übernahme +persönlicher Credentials in einen anderen Tenant und keine neue Berechtigung +zum Zugriff auf fremde Profile. Bestehende Freigabe-Gates für Organisationstenants +bleiben erhalten; ein tenantweit geteilter Plattformzugang ist hiermit nicht eingeführt. + +Die Organisation stammt aus dem aktiven Tenant oder dem letzten erfolgreichen +Profilcheck, nie aus zusätzlichen Browserparametern. Mit dem technischen Token +wird `GET https://resourcemanager.api.stackit.cloud/v2/projects` mit +`containerParentId`, `limit=100` und `offset=0` abgefragt. Das erste aktive Projekt +in sortierter UUID-Reihenfolge dient als Referenz. Ohne direktes Projekt werden +Ordner innerhalb derselben Organisation begrenzt durchsucht. Jede Liste ist auf +ihre erste Seite begrenzt. Ein anderes Projekt mit besseren Produktberechtigungen +wird bei fehlgeschlagenen Produktabrufen nicht automatisch gesucht. + +Ohne lesbares aktives Referenzprojekt bleibt `projectId=null`: projektbezogene +Kataloge werden als nicht verfügbar markiert, regionsbezogene Kataloge unabhängig +davon geladen. Der Editor lädt `eu01` und `eu02` getrennt und behält vorhandene +Werte sowie manuelle Eingaben bei Fehlern bei. Application Owners starten keine +technischen Katalog- oder Credential-Abfragen und benötigen hierfür kein Setup. +Der Abruf startet im aktiven Arbeitsbereich bereits vor dem Editor und wird nach +erfolgreichen Credential-Aktionen erneuert. Laden und teilweise fehlende Kataloge +werden im Editor angezeigt. Organisationsprojekte werden auch in Unterordnern +gesucht: maximal 32 Container, 100 Einträge je Liste und 15 Sekunden Suchbudget; +keine organisationsübergreifende Ausweichsuche. Zyklen werden übersprungen. +Am 2026-10-02 ist der echte Resource-Manager-/Produktabruf mit einem gespeicherten +Organisationstenant-Profil nachgewiesen; Browserabläufe verwenden weiterhin +kontrollierte Antworten. + + + +## Produktumfang + +- [x] Git-Leistungsklassen: projektbezogene, als `available` markierte Flavors. +- [x] VPN-Leistungsklassen: regionsbezogene `planId`-Werte mit Anzeigenamen. +- [x] SKE: unterstützte Kubernetes-Versionen, Node-Pool-Maschinentypen, Betriebssysteme mit mindestens einer unterstützten Image-Version, Verfügbarkeitszonen und Volume-Typen pro Region. +- [x] Firewall-Appliances: IaaS-Maschinentypen sowie primäre und HA-Ersatz-Zonen, für einzelne und mehrere Firewalls einschließlich regionaler Konfigurationen. +- [x] Eingeblendete Dropdowns erhalten bestehende/importierte Werte; fehlende Werte werden als nicht im geladenen Katalog markiert, niemals still ersetzt. +- [x] Getrennte Fehlerbehandlung je Produkt. Fehlende API-Berechtigungen oder nicht verfügbare Kataloge lassen manuelle Eingaben zu; das ist keine erfolgreiche Cloud-Validierung. +- [x] Keine Persistierung des Katalogs, keine Browser-Tokens, kein gemeinsamer Cache über Benutzer/Tenants. Wechsel des Benutzers oder Tenants leert den Kontext. +- [ ] Weitere Kataloge für Datenbanken und zusätzliche Produkte nach produktspezifischer Prüfung. +- [ ] VPN-Verfügbarkeitszonen über eine für VPN dokumentierte Quelle. SKE-Zonen werden ausdrücklich **nicht** als VPN-Zonen angeboten. +- [ ] Automatische erneute Cloud-Validierung vor dem Plan, berücksichtigt Zielprojekt, Region, Berechtigungen und Quoten. +- [x] Im STACKIT-Modus getrennte Regionskataloge für eu01 und eu02; der Legacy-Modus behält die manuelle Regionswahl. +- [x] Live-Abruf mit dem vom Benutzer gespeicherten tenantgebundenen Credential-Profil: eu01 liefert unter anderem 2 Git-Flavors, 3 VPN-Tarife, 2 Kubernetes-Versionen, 133 SKE-Maschinentypen und 12 Observability-Tarife. Der separat geprüfte Standard-Image-Endpunkt liefert 89 öffentliche verfügbare Images; das ist keine vollständige Deployment-Abnahme. + + + +## APIs und Quellen + +Prüfstand 2026-10-01, offizieller STACKIT Go SDK, Commit `7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9`: + +| Produkt | Nur lesender Endpunkt | Verwendete Antwortfelder | +|---|---|---| +| Git | `GET https://git.api.stackit.cloud/v1beta/projects/{projectId}/flavors` | `flavors[].id`, `display_name`, `availability` (`available`, `unavailable`, `internal`, `deprecated`) | +| VPN | `GET https://vpn.api.stackit.cloud/v1/regions/{region}/plans` | `plans[].planId`, optional `name` | +| SKE | `GET https://ske.api.stackit.cloud/v2/regions/{region}/provider-options?versionState=SUPPORTED` | `kubernetesVersions[].version/state`, `machineTypes[].name`, `availabilityZones[].name`, `volumeTypes[].name` | + +Quellen: [Git API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/git/v1betaapi/api_default.go), [Git Availability](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/git/v1betaapi/model_flavor_availability.go), [VPN API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/vpn/v1api/api_default.go), [VPN Plan](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/vpn/v1api/model_plan.go), [SKE API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/ske/v2api/api_default.go), [SKE Provider Options](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/ske/v2api/model_provider_options.go). + +Die globalen/regionsbezogenen APIs liefern keinen Nachweis, dass alle Werte in einem bestimmten künftigen Projekt bestellbar sind. Das Referenzprojekt für Git, Observability und IaaS ist ausdrücklich nicht das künftig anzulegende Zielprojekt. Die API-Version des Katalogs ist unabhängig von der gepinnten Terraform-Provider-Version; ein Eintrag im Katalog bestätigt nicht automatisch dessen Unterstützung durch den Accelerator. + + + +## Sicherheits- und Fehlerverhalten + +`POST /api/v1/cloud-catalogues` verlangt eine aktive Sitzung, gleiche Origin und CSRF-Token. Die Operation führt nur Token-Austausch und lesende Produktabfragen aus. UUIDs und Region (`eu01`/`eu02`) werden strikt validiert. Server-seitige Abfrage des Credential-Profils verwendet explizit Benutzer-ID und Tenant-ID plus PostgreSQL RLS. Der Secrets-Manager-Schlüssel muss mit Profilmetadaten übereinstimmen. Browser erhalten nur normalisierte Katalogdaten. + +Alle Cloud-Ziele sind fest definiert; Redirects sind verboten, Antworten sind auf 2 MB begrenzt und Requests haben 15 Sekunden Timeout. Fehlermeldungen enthalten keine Providerantworten, privaten Schlüssel oder Tokens. Unbekannte/fehlerhafte Antwortschemata markieren nur den betroffenen Katalog als nicht verfügbar. Ein vorhandener, aber leerer Katalog unterscheidet sich von einem fehlgeschlagenen Abruf. + +Die bisherige manuelle Profilauswahl gilt im persönlichen Legacy-Arbeitsbereich. +Im STACKIT-Login-Modus und in Organisationstenants erfolgt der Abruf automatisch. +Platform Engineers dürfen im Organisationstenant eigene Zugänge speichern und +Kataloge abrufen; Application Owner nicht. Migration `013_organisation_credentials.sql` +setzt dieselbe Produktrollenprüfung in PostgreSQL RLS durch. Profile bleiben an +Tenant und Besitzer gebunden, nicht tenantweit geteilt; persönliche Profile werden +nie in einen Organisationstenant übernommen. Cloud-Ausführung bleibt separat gesperrt. +Ohne Organisationskontext werden im persönlichen Tenant die für den Service Account +zugänglichen Projekte abgefragt. Im Organisationstenant begrenzt dessen +Organisations-ID die Suche. Ein fehlender Katalogzugang wird sichtbar gemeldet, +nicht still als erfolgreicher Freitext-Fallback behandelt. + +Im Legacy-Modus werden Katalogzugang, Referenzprojekt-ID und Region in diesem Browser pro Benutzer +und Arbeitsbereich gespeichert und beim erneuten Öffnen wiederhergestellt. +Gespeichert werden ausschließlich diese drei Auswahlwerte, keine Schlüssel, +Tokens oder Katalogantworten. Das Profil wird erneut gegen die zugänglichen, +gespeicherten Credential-Profile geprüft; ein gelöschtes Profil wird nicht mehr +vorausgewählt. Kataloge werden weiterhin nur nach expliziter Aktualisierung +abgerufen. Die Einstellung wird nicht zwischen Geräten synchronisiert; blockierter +Browser-Speicher erzeugt einen sichtbaren Hinweis. + + + +## Erweiterung: Observability und Diagnose-Bastion + +- [x] `observability.plan_name` und die Observability-Blöcke von Plattform-Clustern, Landing Zones und Sandboxes verwenden `plans[].name` als Terraform-Eingabe, nicht die abweichende Plan-UUID. +- [x] IaaS-Maschinentypen, öffentliche verfügbare Images und IaaS-Verfügbarkeitszonen für `platform_kubernetes[*].debug_bastion`. Die Kataloge sind von SKE-Node-Pools getrennt. +- [x] Bestehende Werte und manuelle Eingabe bei Ausfall bleiben erhalten; neue API-Antwortfelder sind optional für kompatible ältere Antworten. +- [ ] Observability-Plankatalog für eu02 verifizieren. Die öffentlich dokumentierte regionale Basis ist `argus.api.eu01.stackit.cloud`; für eu02 wird bewusst kein eu01-Katalog angeboten. Auch die globale Basis ist dokumentiert, jedoch ohne Parameter/Zusicherung einer regionsspezifischen Planliste. + +| Katalog | Quelle | Antwort | +|---|---|---| +| Observability | `GET https://argus.api.eu01.stackit.cloud/v1/projects/{projectId}/plans` | `plans[].name`; Zuordnung über Planname wie im Accelerator | +| Bastion-Maschinentypen | `GET https://iaas.api.stackit.cloud/v2/projects/{projectId}/regions/{region}/machine-types` | `items[].name` | +| Bastion-Images | `GET https://iaas.api.stackit.cloud/v2/projects/{projectId}/regions/{region}/images` | `items[].id` als Wert, `name` als Anzeige, `status`, `scope`; Auswahl nur `AVAILABLE` und `public` | +| Bastion-Zonen | `GET https://iaas.api.stackit.cloud/v2/regions/{region}/availability-zones` | `items[]` | + +Quellen: [Observability OpenAPI](https://docs.api.eu01.stackit.cloud/oas/argus/version/v1), [IaaS v2 API](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/api_default.go), [Image-Modell](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_image.go), [Maschinentypen](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_machine_type_list_response.go), [Zonen](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_availability_zone_list_response.go). + +Die geprüften IaaS-v2-Listenmethoden bieten keine Cursor-/Page-Parameter und die Antwortmodelle keine Fortsetzungsmarker. `all=true` lief beim echten Abruf ins Timeout; der Standardendpunkt antwortete mit 89 öffentlichen `AVAILABLE`-Images. Eine exakt identische Filterung zum Portal ist damit noch nicht nachgewiesen. Antwortgrößen über dem vorhandenen Limit oder mehr als 2.000 Einträge werden nicht still abgeschnitten: der betroffene Katalog wird als nicht verfügbar behandelt. Private, organisations- oder projektgeteilte Images des Referenzprojekts werden nicht als auswählbare Images vorgeschlagen, da ihre Nutzbarkeit im neu angelegten Zielprojekt nicht bewiesen ist. Vorhandene Image-IDs bleiben im Entwurf erhalten. Die OS-Eignung, benötigte Werkzeuge und Image-/Flavor-Kompatibilität sind weiterhin vor dem Deployment zu prüfen. + + + +## Auswahlfeld-Prüfung 2026-10-02 + +Das Inventar basiert auf den generierten Terraform-Eingabedefinitionen und den +tatsächlichen Editoren, nicht auf frei erfundenen Produktfeldern. + +| Feldgruppe | Quelle und Ergebnis | +| --- | --- | +| SKE-Version, Knoten, OS, Zonen, Speicher | Regionales SKE `provider-options`; `machineImages[].versions[].state=SUPPORTED` für OS. SKE liegt im aktuellen Schema unter `platform_kubernetes`, nicht in Public-/Sandbox-Projekt-Templates. | +| Bastion-Image, VM-Typ und Zone | IaaS-v2-Kataloge; Image nur öffentlich und verfügbar. | +| Firewall-Typ, primäre und HA-Zone | Dieselben IaaS-Kataloge; keine Wiederverwendung von SKE-Werten. | +| Git, VPN-Tarif, Observability, Projektrollen/Permissions | Bestehende produktspezifische Kataloge; getrennte regionale Fehlerzustände. | +| DNS-Zonentyp | Feste Auswahl `primary`/`secondary` aus DNS-v1-OpenAPI `zone.ZonePost`; kein eigener Live-Katalog dokumentiert. | +| VPN-Verschlüsselung, Integrität, DH-Gruppen | Feste Enums aus VPN-v1-OpenAPI `Phase`; kein Algorithmus-Katalog dokumentiert. SHA-1 ist dort bis 2026-12-31 abgekündigt; keine automatische Vorauswahl schwacher Algorithmen. | +| VPN-Tunnelzonen | Die geprüfte VPN-v1-OpenAPI enthält keine Zonenlisten-Methode. Freie Eingabe bleibt; SKE/IaaS-Zonen sind kein VPN-Verfügbarkeitsnachweis. | +| Regionen, Routingmodus, Ressourcentyp, Secret-Policy | Bestehende begrenzte Auswahlen; neue API-Werte werden nur bei Unterstützung des Terraform-Moduls ergänzt. | +| Namen, CIDRs, DNS-Namen, Labels, Kubernetes-Images, Principals | Entwurfswerte oder kundeneigene Referenzen, keine STACKIT-Produktkataloge. Keine Bestandsressourcen aus dem Referenzprojekt als Ressourcen des künftig angelegten Zielprojekts anbieten. | +| KMS-Key-Version, Kubernetes-Speicherklasse | Gehören zur separat angelegten Schlüssel-/Clusterkonfiguration. Kein ungeprüfter Katalog aus fremden Bestandsprojekten; spätere Prüfung im tatsächlichen Zielkontext erforderlich. | + +Quellen für neue feste Auswahlen: [DNS-v1-OpenAPI](https://docs.api.eu01.stackit.cloud/oas/dns/version/v1), +[VPN-v1-OpenAPI](https://docs.api.eu01.stackit.cloud/oas/vpn/version/v1), +[SKE-v2-OpenAPI](https://docs.api.eu01.stackit.cloud/oas/ske/version/v2). + + + +## Projektrollen und Permissions + +Der lesende Katalogabruf verwendet zusätzlich die Membership API v2: + +| Katalog | Endpunkt | Normalisierte Felder | +| --- | --- | --- | +| Projektrollen | `GET https://authorization.api.stackit.cloud/v2/project/{projectId}/roles` | `roles[].name`, `description`, `permissions[].name` | +| Projekt-Permissions | `GET https://authorization.api.stackit.cloud/v2/permissions?resourceType=project` | `permissions[].name` | + +Quelle: offizieller SDK-Stand `7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9`, +`services/authorization/v2api`. Die Antwort der Rollenliste muss zur angefragten +Projekt-ID und zum Ressourcentyp `project` gehören. Beide Kataloge bleiben bei +fehlenden Berechtigungen unabhängig von den anderen Produktkatalogen nicht verfügbar. +Die API-Antworten sind wie bisher zeit- und größenbegrenzt und enthalten im Browser +keine Tokens. IAM-Optionen sind projektbezogen, nicht regionsbezogen. + +Der Editor bietet Permissions als Dropdowns und kopiert Rollenvorlagen als lokale +Definitionen. Referenzprojekt-Rollen-IDs werden nicht weitergegeben und fremde +Projektmitglieder werden nicht abgefragt. Die Anwendung prüft noch keine persönliche +STACKIT-Identität über diesen Katalog: spätere Rollenvariablen benötigen den getrennten +verifizierten Instanziierungskontext. Die konkrete Bestellbarkeit und Rollenauflösung +im neuen Zielprojekt bleibt ein Gate vor produktiver Veröffentlichung. + + + +## PIM: zentrale Produktinformationen, keine alleinige Auswahlvalidierung + +Die öffentliche [STACKIT PIM API v2](https://docs.api.eu01.stackit.cloud/documentation/pim/version/v2) ist tatsächlich ein zentraler Katalog für Kategorien, Produkte und SKUs. Die [OpenAPI-Spezifikation](https://docs.api.eu01.stackit.cloud/oas/pim/version/v2) dokumentiert unter anderem: + +- `GET https://pim.api.stackit.cloud/v2/products` +- `GET https://pim.api.stackit.cloud/v2/products/{productId}/skus` +- `GET https://pim.api.stackit.cloud/v2/skus` +- SKU-Attribute wie Region, technische Merkmale, Produktreife und Deprecation sowie Artikelnummern für Abrechnung. +- Öffentlich verfügbare Listen mit Cursor-Paginierung (`pageSize` maximal 100). Der Adapter berücksichtigt Folgeseiten innerhalb expliziter Zeit-/Seitenlimits und verwirft unvollständig abgerufene Listen. + +PIM eignet sich als ergänzende Quelle für einheitliche Produktbezeichnungen, technische Erklärungen und SKU-Zuordnung. Seine öffentlichen SKU-Listen bestätigen keine Bestellbarkeit oder Berechtigung in einem konkreten Projekt, keine Quoten, keine aktuellen Kubernetes-Versionen und keine verfügbaren VM-Images. Daher bleiben die jeweiligen Produkt-APIs die Quelle der technischen Auswahlwerte. Die in der API-Übersicht als auslaufend markierte v1 wird nicht neu angebunden. + + + +### Assistent: aktueller PIM-v2-Abruf (2026-10-10) + +Editor-Chat und vorgelagerte Template-Beratung laden pro Nachricht erneut die +Produktkataloge über dieselbe benutzer-/tenantgebundene Abstraktion wie der Editor +und ergänzend öffentliche PIM-Daten. Der Chat verwendet die Konfigurationsregion; +die Template-Beratung fragt eu01 und eu02 getrennt ab. Kein gemeinsamer +Benutzer-/Tenant-Cache und kein Operator-Credential-Fallback. Ein Ausfall des +berechtigten Produktkatalogs verhindert nicht die Erklärung öffentlicher PIM-Fakten, +ist aber kein Nachweis eines auswählbaren Plans. + +Implementiert: Products und nach Produkt/Region gefilterte SKUs, Cursor-Paginierung +mit 100 Einträgen je Seite, maximal 30 Seiten und 15 Sekunden Budget pro Liste. +Der relevante Produktumfang ist begrenzt (maximal acht Produkte), nicht der gesamte +STACKIT-Katalog. Beim echten eu01-Abruf: Kubernetes Engine, VPN, Observability, +Server und Git, insgesamt 330 SKUs; VPN mit 100, 500 und 1000 Mbit/s. +Der echte eu02-Abruf liefert dieselben fünf Produktbezeichnungen und 129 SKUs, +darunter keine VPN-SKUs. Das ist kein Anlass, eu01-VPN-Pläne für eu02 anzubieten. + +Das Modell erhält normalisierte Labels/Werte und öffentliche technische Attribute, +keine Credential-Profile, IAM-Rollen/Permissions, Referenzprojekt-IDs, Schlüssel, +Preise oder Rohantworten. Kontextlimits: 50 Optionen je Produktkatalog und +100 priorisierte PIM-SKUs je Region, jeweils mit Gesamtzahl/Ausschnitt-Markierung +und Abrufzeit. Daher keine Zusage vollständiger oder ständig verfügbarer Listen. +Die SKU-ID ist eine Abrechnungsartikelnummer, nicht die VPN-Plan-ID; Zuordnung +technischer Auswahlwerte nur über planId/flavor und berechtigte Produktoptionen. + +Für Fragen zu VPN-Leistungsklassen und Flavors ergänzt eine deterministische, +begrenzte Faktenliste den Modelltext, weil Qwen in echten Tests Zahlen trotz +geliefertem Kontext ausgelassen hat. Abgekündigte Einträge werden ausgeschlossen; +Bandbreite/Verbindungszahl/vCPU stammen aus gelieferten Attributen. Die RAM-Einheit +ist noch nicht verifiziert und wird nicht als GB behauptet. Die Faktenliste ist +derzeit deutschsprachig. Technische ID-Felder sind keine zulässigen Rückfragen. +Freie fachliche Beratung, zweisprachige Darstellung und vollständige komplexe +Konfigurationsänderungen bleiben gesondert zu qualifizieren. diff --git a/landing-zone-configurator/docs/cloud-product-catalogues.md b/landing-zone-configurator/docs/cloud-product-catalogues.md index e2fd394..0a4a6be 100644 --- a/landing-zone-configurator/docs/cloud-product-catalogues.md +++ b/landing-zone-configurator/docs/cloud-product-catalogues.md @@ -1,204 +1,217 @@ -# STACKIT-Produktkataloge im Editor - -## Zweck und aktueller Umfang - -Im primären STACKIT-Login-Modus lädt der Editor Produktoptionen automatisch mit dem bereits hinterlegten technischen STACKIT-Service-Account-Zugang des Platform Engineers. Eine weitere Profil-, Projekt- oder Regionswahl für den Katalog entfällt. Im Legacy-GitHub-Modus bleibt die explizite Auswahl eines eigenen Profils und Referenzprojekts erhalten. Zentrale Deployment-Credentials des Configurators werden niemals verwendet. Die Auswahlwerte unterstützen den Entwurf, ersetzen jedoch weder Accelerator-Validierung noch einen tatsächlichen Plan oder eine Quotenprüfung. - -## Automatischer Abruf im STACKIT-Modus - -`POST /api/v1/cloud-catalogues/automatic` nimmt ausschließlich `region` an und -verlangt Origin, CSRF sowie den zur Session passenden `x-lzc-tenant`-Header. -Der Server wählt das neueste eigene Credential-Profil des aktiven Tenants und -prüft die Metadaten gegen den gespeicherten Schlüssel. Es gibt keine Übernahme -persönlicher Credentials in einen anderen Tenant und keine neue Berechtigung -zum Zugriff auf fremde Profile. Bestehende Freigabe-Gates für Organisationstenants -bleiben erhalten; ein tenantweit geteilter Plattformzugang ist hiermit nicht eingeführt. - -Die Organisation stammt aus dem aktiven Tenant oder dem letzten erfolgreichen -Profilcheck, nie aus zusätzlichen Browserparametern. Mit dem technischen Token -wird `GET https://resourcemanager.api.stackit.cloud/v2/projects` mit -`containerParentId`, `limit=100` und `offset=0` abgefragt. Das erste aktive Projekt -in sortierter UUID-Reihenfolge dient als Referenz. Ohne direktes Projekt werden -Ordner innerhalb derselben Organisation begrenzt durchsucht. Jede Liste ist auf -ihre erste Seite begrenzt. Ein anderes Projekt mit besseren Produktberechtigungen -wird bei fehlgeschlagenen Produktabrufen nicht automatisch gesucht. - -Ohne lesbares aktives Referenzprojekt bleibt `projectId=null`: projektbezogene -Kataloge werden als nicht verfügbar markiert, regionsbezogene Kataloge unabhängig -davon geladen. Der Editor lädt `eu01` und `eu02` getrennt und behält vorhandene -Werte sowie manuelle Eingaben bei Fehlern bei. Application Owners starten keine -technischen Katalog- oder Credential-Abfragen und benötigen hierfür kein Setup. -Der Abruf startet im aktiven Arbeitsbereich bereits vor dem Editor und wird nach -erfolgreichen Credential-Aktionen erneuert. Laden und teilweise fehlende Kataloge -werden im Editor angezeigt. Organisationsprojekte werden auch in Unterordnern -gesucht: maximal 32 Container, 100 Einträge je Liste und 15 Sekunden Suchbudget; -keine organisationsübergreifende Ausweichsuche. Zyklen werden übersprungen. -Am 2026-10-02 ist der echte Resource-Manager-/Produktabruf mit einem gespeicherten -Organisationstenant-Profil nachgewiesen; Browserabläufe verwenden weiterhin -kontrollierte Antworten. - -## Produktumfang - -- [x] Git-Leistungsklassen: projektbezogene, als `available` markierte Flavors. -- [x] VPN-Leistungsklassen: regionsbezogene `planId`-Werte mit Anzeigenamen. -- [x] SKE: unterstützte Kubernetes-Versionen, Node-Pool-Maschinentypen, Betriebssysteme mit mindestens einer unterstützten Image-Version, Verfügbarkeitszonen und Volume-Typen pro Region. -- [x] Firewall-Appliances: IaaS-Maschinentypen sowie primäre und HA-Ersatz-Zonen, für einzelne und mehrere Firewalls einschließlich regionaler Konfigurationen. -- [x] Eingeblendete Dropdowns erhalten bestehende/importierte Werte; fehlende Werte werden als nicht im geladenen Katalog markiert, niemals still ersetzt. -- [x] Getrennte Fehlerbehandlung je Produkt. Fehlende API-Berechtigungen oder nicht verfügbare Kataloge lassen manuelle Eingaben zu; das ist keine erfolgreiche Cloud-Validierung. -- [x] Keine Persistierung des Katalogs, keine Browser-Tokens, kein gemeinsamer Cache über Benutzer/Tenants. Wechsel des Benutzers oder Tenants leert den Kontext. -- [ ] Weitere Kataloge für Datenbanken und zusätzliche Produkte nach produktspezifischer Prüfung. -- [ ] VPN-Verfügbarkeitszonen über eine für VPN dokumentierte Quelle. SKE-Zonen werden ausdrücklich **nicht** als VPN-Zonen angeboten. -- [ ] Automatische erneute Cloud-Validierung vor dem Plan, berücksichtigt Zielprojekt, Region, Berechtigungen und Quoten. -- [x] Im STACKIT-Modus getrennte Regionskataloge für eu01 und eu02; der Legacy-Modus behält die manuelle Regionswahl. -- [x] Live-Abruf mit dem vom Benutzer gespeicherten tenantgebundenen Credential-Profil: eu01 liefert unter anderem 2 Git-Flavors, 3 VPN-Tarife, 2 Kubernetes-Versionen, 133 SKE-Maschinentypen und 12 Observability-Tarife. Der separat geprüfte Standard-Image-Endpunkt liefert 89 öffentliche verfügbare Images; das ist keine vollständige Deployment-Abnahme. - -## APIs und Quellen - -Prüfstand 2026-10-01, offizieller STACKIT Go SDK, Commit `7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9`: - -| Produkt | Nur lesender Endpunkt | Verwendete Antwortfelder | + +# STACKIT product catalogues in the editor + +[English](cloud-product-catalogues.md) | [Deutsch](cloud-product-catalogues.de.md) + + +## Purpose and current scope + +In primary STACKIT login mode, the editor automatically loads product options using the Platform Engineer's already stored technical STACKIT service-account credentials. No additional profile, project or region selection is needed for the catalogue. In legacy GitHub mode, explicit selection of an own profile and reference project remains. Central Configurator deployment credentials are never used. Choices support drafting, but replace neither Accelerator validation nor an actual Plan or quota check. + + +## Automatic retrieval in STACKIT mode + +`POST /api/v1/cloud-catalogues/automatic` accepts only `region` and +requires origin, CSRF and the `x-lzc-tenant` header matching the session. +The server selects the latest own credential profile of the active tenant and +checks metadata against the stored key. Personal credentials are not +transferred to another tenant and no new permission to access +others' profiles is granted. Existing approval gates for organization tenants +remain; this does not introduce tenant-wide shared platform credentials. + +The organization comes from the active tenant or last successful +profile check, never additional browser parameters. The technical token is used to +query `GET https://resourcemanager.api.stackit.cloud/v2/projects` with +`containerParentId`, `limit=100` and `offset=0`. The first active project +in sorted UUID order serves as reference. Without a direct project, +folders within the same organization are searched with bounds. Each list is limited to +its first page. Another project with better product permissions +is not automatically sought when product retrieval fails. + +Without a readable active reference project, `projectId=null` remains: project-specific +catalogues are marked unavailable, while region-specific catalogues are loaded +independently. The editor loads `eu01` and `eu02` separately and preserves existing +values and manual inputs on error. Application Owners start no +technical catalogue or credential queries and need no setup for them. +Retrieval starts in the active workspace before the editor opens and is refreshed +after successful credential actions. Loading and partially missing catalogues +are displayed in the editor. Organization projects are also searched in subfolders: +at most 32 containers, 100 entries per list and a 15-second search budget; +no cross-organization fallback search. Cycles are skipped. +On 2026-10-02, real Resource Manager/product retrieval with a stored +organization-tenant profile was demonstrated; browser flows continue to use +controlled responses. + + +## Product scope + +- [x] Git performance tiers: project-specific flavors marked `available`. +- [x] VPN performance tiers: region-specific `planId` values with display names. +- [x] SKE: supported Kubernetes versions, node-pool machine types, operating systems with at least one supported image version, availability zones and volume types per region. +- [x] Firewall appliances: IaaS machine types and primary/HA replacement zones, for single and multiple firewalls including regional configurations. +- [x] Displayed dropdowns preserve existing/imported values; missing values are marked as not in the loaded catalogue, never silently replaced. +- [x] Separate error handling per product. Missing API permissions or unavailable catalogues permit manual input; this is not successful cloud validation. +- [x] No catalogue persistence, no browser tokens, no shared cache across users/tenants. Changing user or tenant clears the context. +- [ ] Further catalogues for databases and additional products after product-specific review. +- [ ] VPN availability zones through a source documented for VPN. SKE zones are explicitly **not** offered as VPN zones. +- [ ] Automatic fresh cloud validation before Plan, considering target project, region, permissions and quotas. +- [x] Separate regional catalogues for eu01 and eu02 in STACKIT mode; legacy mode retains manual region selection. +- [x] Live retrieval with the user-stored tenant-bound credential profile: eu01 supplies, among other things, 2 Git flavors, 3 VPN plans, 2 Kubernetes versions, 133 SKE machine types and 12 Observability plans. The separately checked default image endpoint returns 89 public available images; this is not full deployment acceptance. + + +## APIs and sources + +Verification status 2026-10-01, official STACKIT Go SDK, commit `7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9`: + +| Product | Read-only endpoint | Response fields used | |---|---|---| | Git | `GET https://git.api.stackit.cloud/v1beta/projects/{projectId}/flavors` | `flavors[].id`, `display_name`, `availability` (`available`, `unavailable`, `internal`, `deprecated`) | | VPN | `GET https://vpn.api.stackit.cloud/v1/regions/{region}/plans` | `plans[].planId`, optional `name` | | SKE | `GET https://ske.api.stackit.cloud/v2/regions/{region}/provider-options?versionState=SUPPORTED` | `kubernetesVersions[].version/state`, `machineTypes[].name`, `availabilityZones[].name`, `volumeTypes[].name` | -Quellen: [Git API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/git/v1betaapi/api_default.go), [Git Availability](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/git/v1betaapi/model_flavor_availability.go), [VPN API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/vpn/v1api/api_default.go), [VPN Plan](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/vpn/v1api/model_plan.go), [SKE API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/ske/v2api/api_default.go), [SKE Provider Options](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/ske/v2api/model_provider_options.go). +Sources: [Git API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/git/v1betaapi/api_default.go), [Git Availability](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/git/v1betaapi/model_flavor_availability.go), [VPN API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/vpn/v1api/api_default.go), [VPN Plan](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/vpn/v1api/model_plan.go), [SKE API](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/ske/v2api/api_default.go), [SKE Provider Options](https://github.com/stackitcloud/stackit-sdk-go/blob/7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9/services/ske/v2api/model_provider_options.go). -Die globalen/regionsbezogenen APIs liefern keinen Nachweis, dass alle Werte in einem bestimmten künftigen Projekt bestellbar sind. Das Referenzprojekt für Git, Observability und IaaS ist ausdrücklich nicht das künftig anzulegende Zielprojekt. Die API-Version des Katalogs ist unabhängig von der gepinnten Terraform-Provider-Version; ein Eintrag im Katalog bestätigt nicht automatisch dessen Unterstützung durch den Accelerator. +Global/regional APIs do not prove that all values can be ordered in a specific future project. The reference project for Git, Observability and IaaS is explicitly not the target project to be created. The catalogue API version is independent of the pinned Terraform provider version; a catalogue entry does not automatically confirm its support by the Accelerator. -## Sicherheits- und Fehlerverhalten + +## Security and error behavior -`POST /api/v1/cloud-catalogues` verlangt eine aktive Sitzung, gleiche Origin und CSRF-Token. Die Operation führt nur Token-Austausch und lesende Produktabfragen aus. UUIDs und Region (`eu01`/`eu02`) werden strikt validiert. Server-seitige Abfrage des Credential-Profils verwendet explizit Benutzer-ID und Tenant-ID plus PostgreSQL RLS. Der Secrets-Manager-Schlüssel muss mit Profilmetadaten übereinstimmen. Browser erhalten nur normalisierte Katalogdaten. +`POST /api/v1/cloud-catalogues` requires an active session, same origin and CSRF token. The operation performs only token exchange and read-only product queries. UUIDs and region (`eu01`/`eu02`) are strictly validated. Server-side credential-profile queries explicitly use user ID and tenant ID plus PostgreSQL RLS. The Secrets Manager key must match profile metadata. Browsers receive normalized catalogue data only. -Alle Cloud-Ziele sind fest definiert; Redirects sind verboten, Antworten sind auf 2 MB begrenzt und Requests haben 15 Sekunden Timeout. Fehlermeldungen enthalten keine Providerantworten, privaten Schlüssel oder Tokens. Unbekannte/fehlerhafte Antwortschemata markieren nur den betroffenen Katalog als nicht verfügbar. Ein vorhandener, aber leerer Katalog unterscheidet sich von einem fehlgeschlagenen Abruf. +All cloud targets are fixed; redirects are forbidden, responses limited to 2 MB and requests have a 15-second timeout. Error messages contain no provider responses, private keys or tokens. Unknown/invalid response schemas mark only the affected catalogue unavailable. An existing but empty catalogue differs from failed retrieval. -Die bisherige manuelle Profilauswahl gilt im persönlichen Legacy-Arbeitsbereich. -Im STACKIT-Login-Modus und in Organisationstenants erfolgt der Abruf automatisch. -Platform Engineers dürfen im Organisationstenant eigene Zugänge speichern und -Kataloge abrufen; Application Owner nicht. Migration `013_organisation_credentials.sql` -setzt dieselbe Produktrollenprüfung in PostgreSQL RLS durch. Profile bleiben an -Tenant und Besitzer gebunden, nicht tenantweit geteilt; persönliche Profile werden -nie in einen Organisationstenant übernommen. Cloud-Ausführung bleibt separat gesperrt. -Ohne Organisationskontext werden im persönlichen Tenant die für den Service Account -zugänglichen Projekte abgefragt. Im Organisationstenant begrenzt dessen -Organisations-ID die Suche. Ein fehlender Katalogzugang wird sichtbar gemeldet, -nicht still als erfolgreicher Freitext-Fallback behandelt. +Previous manual profile selection applies in the personal legacy workspace. +In STACKIT login mode and organization tenants, retrieval is automatic. +Platform Engineers may store own credentials and retrieve catalogues in +organization tenants; Application Owners may not. Migration `013_organisation_credentials.sql` +enforces the same product-role check in PostgreSQL RLS. Profiles remain bound to +tenant and owner, not shared tenant-wide; personal profiles are +never transferred into an organization tenant. Cloud execution remains separately blocked. +Without organization context, projects accessible to the service account are queried +in the personal tenant. In organization tenants, the organization ID +limits the search. Missing catalogue access is visibly reported, +not silently treated as a successful free-text fallback. -Im Legacy-Modus werden Katalogzugang, Referenzprojekt-ID und Region in diesem Browser pro Benutzer -und Arbeitsbereich gespeichert und beim erneuten Öffnen wiederhergestellt. -Gespeichert werden ausschließlich diese drei Auswahlwerte, keine Schlüssel, -Tokens oder Katalogantworten. Das Profil wird erneut gegen die zugänglichen, -gespeicherten Credential-Profile geprüft; ein gelöschtes Profil wird nicht mehr -vorausgewählt. Kataloge werden weiterhin nur nach expliziter Aktualisierung -abgerufen. Die Einstellung wird nicht zwischen Geräten synchronisiert; blockierter -Browser-Speicher erzeugt einen sichtbaren Hinweis. +In legacy mode, catalogue credentials, reference project ID and region are stored in this browser per user +and workspace and restored on reopening. +Only these three selection values are stored, no keys, +tokens or catalogue responses. The profile is rechecked against accessible +stored credential profiles; a deleted profile is no longer +preselected. Catalogues are still retrieved only after explicit refresh. +The setting is not synchronized between devices; blocked +browser storage produces a visible notice. -## Erweiterung: Observability und Diagnose-Bastion + +## Extension: Observability and diagnostic bastion -- [x] `observability.plan_name` und die Observability-Blöcke von Plattform-Clustern, Landing Zones und Sandboxes verwenden `plans[].name` als Terraform-Eingabe, nicht die abweichende Plan-UUID. -- [x] IaaS-Maschinentypen, öffentliche verfügbare Images und IaaS-Verfügbarkeitszonen für `platform_kubernetes[*].debug_bastion`. Die Kataloge sind von SKE-Node-Pools getrennt. -- [x] Bestehende Werte und manuelle Eingabe bei Ausfall bleiben erhalten; neue API-Antwortfelder sind optional für kompatible ältere Antworten. -- [ ] Observability-Plankatalog für eu02 verifizieren. Die öffentlich dokumentierte regionale Basis ist `argus.api.eu01.stackit.cloud`; für eu02 wird bewusst kein eu01-Katalog angeboten. Auch die globale Basis ist dokumentiert, jedoch ohne Parameter/Zusicherung einer regionsspezifischen Planliste. +- [x] `observability.plan_name` and Observability blocks of platform clusters, Landing Zones and sandboxes use `plans[].name` as Terraform input, not the different plan UUID. +- [x] IaaS machine types, public available images and IaaS availability zones for `platform_kubernetes[*].debug_bastion`. Catalogues are separate from SKE node pools. +- [x] Existing values and manual input on failure are preserved; new API response fields are optional for compatible older responses. +- [ ] Verify Observability plan catalogue for eu02. The publicly documented regional base is `argus.api.eu01.stackit.cloud`; deliberately no eu01 catalogue is offered for eu02. The global base is also documented, but without parameters/guarantees for a region-specific plan list. -| Katalog | Quelle | Antwort | +| Catalogue | Source | Response | |---|---|---| -| Observability | `GET https://argus.api.eu01.stackit.cloud/v1/projects/{projectId}/plans` | `plans[].name`; Zuordnung über Planname wie im Accelerator | -| Bastion-Maschinentypen | `GET https://iaas.api.stackit.cloud/v2/projects/{projectId}/regions/{region}/machine-types` | `items[].name` | -| Bastion-Images | `GET https://iaas.api.stackit.cloud/v2/projects/{projectId}/regions/{region}/images` | `items[].id` als Wert, `name` als Anzeige, `status`, `scope`; Auswahl nur `AVAILABLE` und `public` | -| Bastion-Zonen | `GET https://iaas.api.stackit.cloud/v2/regions/{region}/availability-zones` | `items[]` | +| Observability | `GET https://argus.api.eu01.stackit.cloud/v1/projects/{projectId}/plans` | `plans[].name`; mapping by plan name as in the Accelerator | +| Bastion machine types | `GET https://iaas.api.stackit.cloud/v2/projects/{projectId}/regions/{region}/machine-types` | `items[].name` | +| Bastion images | `GET https://iaas.api.stackit.cloud/v2/projects/{projectId}/regions/{region}/images` | `items[].id` as value, `name` as display, `status`, `scope`; select only `AVAILABLE` and `public` | +| Bastion zones | `GET https://iaas.api.stackit.cloud/v2/regions/{region}/availability-zones` | `items[]` | -Quellen: [Observability OpenAPI](https://docs.api.eu01.stackit.cloud/oas/argus/version/v1), [IaaS v2 API](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/api_default.go), [Image-Modell](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_image.go), [Maschinentypen](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_machine_type_list_response.go), [Zonen](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_availability_zone_list_response.go). +Sources: [Observability OpenAPI](https://docs.api.eu01.stackit.cloud/oas/argus/version/v1), [IaaS v2 API](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/api_default.go), [Image model](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_image.go), [Machine types](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_machine_type_list_response.go), [Zones](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/iaas/v2api/model_availability_zone_list_response.go). -Die geprüften IaaS-v2-Listenmethoden bieten keine Cursor-/Page-Parameter und die Antwortmodelle keine Fortsetzungsmarker. `all=true` lief beim echten Abruf ins Timeout; der Standardendpunkt antwortete mit 89 öffentlichen `AVAILABLE`-Images. Eine exakt identische Filterung zum Portal ist damit noch nicht nachgewiesen. Antwortgrößen über dem vorhandenen Limit oder mehr als 2.000 Einträge werden nicht still abgeschnitten: der betroffene Katalog wird als nicht verfügbar behandelt. Private, organisations- oder projektgeteilte Images des Referenzprojekts werden nicht als auswählbare Images vorgeschlagen, da ihre Nutzbarkeit im neu angelegten Zielprojekt nicht bewiesen ist. Vorhandene Image-IDs bleiben im Entwurf erhalten. Die OS-Eignung, benötigte Werkzeuge und Image-/Flavor-Kompatibilität sind weiterhin vor dem Deployment zu prüfen. +The reviewed IaaS v2 list methods offer no cursor/page parameters, and response models no continuation markers. `all=true` timed out during real retrieval; the default endpoint returned 89 public `AVAILABLE` images. Exactly identical filtering to the portal is not yet proven. Response sizes above the existing limit or more than 2,000 entries are not silently truncated: the affected catalogue is treated as unavailable. Private, organization-shared or project-shared images of the reference project are not proposed as selectable images because their usability in the newly created target project is unproven. Existing image IDs are preserved in the draft. OS suitability, required tools and image/flavor compatibility still need checking before deployment. -## Auswahlfeld-Prüfung 2026-10-02 + +## Selection-field review 2026-10-02 -Das Inventar basiert auf den generierten Terraform-Eingabedefinitionen und den -tatsächlichen Editoren, nicht auf frei erfundenen Produktfeldern. +The inventory is based on generated Terraform input definitions and +actual editors, not invented product fields. -| Feldgruppe | Quelle und Ergebnis | +| Field group | Source and result | | --- | --- | -| SKE-Version, Knoten, OS, Zonen, Speicher | Regionales SKE `provider-options`; `machineImages[].versions[].state=SUPPORTED` für OS. SKE liegt im aktuellen Schema unter `platform_kubernetes`, nicht in Public-/Sandbox-Projekt-Templates. | -| Bastion-Image, VM-Typ und Zone | IaaS-v2-Kataloge; Image nur öffentlich und verfügbar. | -| Firewall-Typ, primäre und HA-Zone | Dieselben IaaS-Kataloge; keine Wiederverwendung von SKE-Werten. | -| Git, VPN-Tarif, Observability, Projektrollen/Permissions | Bestehende produktspezifische Kataloge; getrennte regionale Fehlerzustände. | -| DNS-Zonentyp | Feste Auswahl `primary`/`secondary` aus DNS-v1-OpenAPI `zone.ZonePost`; kein eigener Live-Katalog dokumentiert. | -| VPN-Verschlüsselung, Integrität, DH-Gruppen | Feste Enums aus VPN-v1-OpenAPI `Phase`; kein Algorithmus-Katalog dokumentiert. SHA-1 ist dort bis 2026-12-31 abgekündigt; keine automatische Vorauswahl schwacher Algorithmen. | -| VPN-Tunnelzonen | Die geprüfte VPN-v1-OpenAPI enthält keine Zonenlisten-Methode. Freie Eingabe bleibt; SKE/IaaS-Zonen sind kein VPN-Verfügbarkeitsnachweis. | -| Regionen, Routingmodus, Ressourcentyp, Secret-Policy | Bestehende begrenzte Auswahlen; neue API-Werte werden nur bei Unterstützung des Terraform-Moduls ergänzt. | -| Namen, CIDRs, DNS-Namen, Labels, Kubernetes-Images, Principals | Entwurfswerte oder kundeneigene Referenzen, keine STACKIT-Produktkataloge. Keine Bestandsressourcen aus dem Referenzprojekt als Ressourcen des künftig angelegten Zielprojekts anbieten. | -| KMS-Key-Version, Kubernetes-Speicherklasse | Gehören zur separat angelegten Schlüssel-/Clusterkonfiguration. Kein ungeprüfter Katalog aus fremden Bestandsprojekten; spätere Prüfung im tatsächlichen Zielkontext erforderlich. | - -Quellen für neue feste Auswahlen: [DNS-v1-OpenAPI](https://docs.api.eu01.stackit.cloud/oas/dns/version/v1), -[VPN-v1-OpenAPI](https://docs.api.eu01.stackit.cloud/oas/vpn/version/v1), -[SKE-v2-OpenAPI](https://docs.api.eu01.stackit.cloud/oas/ske/version/v2). - -## Projektrollen und Permissions - -Der lesende Katalogabruf verwendet zusätzlich die Membership API v2: - -| Katalog | Endpunkt | Normalisierte Felder | +| SKE version, nodes, OS, zones, storage | Regional SKE `provider-options`; `machineImages[].versions[].state=SUPPORTED` for OS. SKE is under `platform_kubernetes` in the current schema, not in Public/sandbox project templates. | +| Bastion image, VM type and zone | IaaS v2 catalogues; image only public and available. | +| Firewall type, primary and HA zone | Same IaaS catalogues; no reuse of SKE values. | +| Git, VPN plan, Observability, project roles/permissions | Existing product-specific catalogues; separate regional error states. | +| DNS zone type | Fixed selection `primary`/`secondary` from DNS v1 OpenAPI `zone.ZonePost`; no dedicated live catalogue documented. | +| VPN encryption, integrity, DH groups | Fixed enums from VPN v1 OpenAPI `Phase`; no algorithm catalogue documented. SHA-1 is deprecated there as of 2026-12-31; no automatic preselection of weak algorithms. | +| VPN tunnel zones | The reviewed VPN v1 OpenAPI contains no zone-list method. Free input remains; SKE/IaaS zones are not proof of VPN availability. | +| Regions, routing mode, resource type, secret policy | Existing bounded choices; new API values are added only when supported by the Terraform module. | +| Names, CIDRs, DNS names, labels, Kubernetes images, principals | Draft values or customer references, not STACKIT product catalogues. Do not offer existing resources from the reference project as resources of the future target project. | +| KMS key version, Kubernetes storage class | Belong to separately created key/cluster configuration. No unchecked catalogue from unrelated existing projects; later verification in the actual target context is required. | + +Sources for new fixed choices: [DNS v1 OpenAPI](https://docs.api.eu01.stackit.cloud/oas/dns/version/v1), +[VPN v1 OpenAPI](https://docs.api.eu01.stackit.cloud/oas/vpn/version/v1), +[SKE v2 OpenAPI](https://docs.api.eu01.stackit.cloud/oas/ske/version/v2). + + +## Project roles and permissions + +Read-only catalogue retrieval additionally uses Membership API v2: + +| Catalogue | Endpoint | Normalized fields | | --- | --- | --- | -| Projektrollen | `GET https://authorization.api.stackit.cloud/v2/project/{projectId}/roles` | `roles[].name`, `description`, `permissions[].name` | -| Projekt-Permissions | `GET https://authorization.api.stackit.cloud/v2/permissions?resourceType=project` | `permissions[].name` | +| Project roles | `GET https://authorization.api.stackit.cloud/v2/project/{projectId}/roles` | `roles[].name`, `description`, `permissions[].name` | +| Project permissions | `GET https://authorization.api.stackit.cloud/v2/permissions?resourceType=project` | `permissions[].name` | -Quelle: offizieller SDK-Stand `7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9`, -`services/authorization/v2api`. Die Antwort der Rollenliste muss zur angefragten -Projekt-ID und zum Ressourcentyp `project` gehören. Beide Kataloge bleiben bei -fehlenden Berechtigungen unabhängig von den anderen Produktkatalogen nicht verfügbar. -Die API-Antworten sind wie bisher zeit- und größenbegrenzt und enthalten im Browser -keine Tokens. IAM-Optionen sind projektbezogen, nicht regionsbezogen. +Source: official SDK revision `7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9`, +`services/authorization/v2api`. The role-list response must belong to the requested +project ID and resource type `project`. Both catalogues remain +unavailable on missing permissions independently of other product catalogues. +API responses remain time- and size-limited and contain +no tokens in the browser. IAM options are project-specific, not region-specific. -Der Editor bietet Permissions als Dropdowns und kopiert Rollenvorlagen als lokale -Definitionen. Referenzprojekt-Rollen-IDs werden nicht weitergegeben und fremde -Projektmitglieder werden nicht abgefragt. Die Anwendung prüft noch keine persönliche -STACKIT-Identität über diesen Katalog: spätere Rollenvariablen benötigen den getrennten -verifizierten Instanziierungskontext. Die konkrete Bestellbarkeit und Rollenauflösung -im neuen Zielprojekt bleibt ein Gate vor produktiver Veröffentlichung. +The editor offers permissions as dropdowns and copies role templates as local +definitions. Reference-project role IDs are not passed on, and other +project members are not queried. The application does not yet verify personal +STACKIT identity through this catalogue: future role variables need the separate +verified instantiation context. Actual orderability and role resolution +in the new target project remain a gate before production publication. -## PIM: zentrale Produktinformationen, keine alleinige Auswahlvalidierung + +## PIM: central product information, not sole selection validation -Die öffentliche [STACKIT PIM API v2](https://docs.api.eu01.stackit.cloud/documentation/pim/version/v2) ist tatsächlich ein zentraler Katalog für Kategorien, Produkte und SKUs. Die [OpenAPI-Spezifikation](https://docs.api.eu01.stackit.cloud/oas/pim/version/v2) dokumentiert unter anderem: +The public [STACKIT PIM API v2](https://docs.api.eu01.stackit.cloud/documentation/pim/version/v2) is indeed a central catalogue for categories, products and SKUs. The [OpenAPI specification](https://docs.api.eu01.stackit.cloud/oas/pim/version/v2) documents, among other things: - `GET https://pim.api.stackit.cloud/v2/products` - `GET https://pim.api.stackit.cloud/v2/products/{productId}/skus` - `GET https://pim.api.stackit.cloud/v2/skus` -- SKU-Attribute wie Region, technische Merkmale, Produktreife und Deprecation sowie Artikelnummern für Abrechnung. -- Öffentlich verfügbare Listen mit Cursor-Paginierung (`pageSize` maximal 100). Der Adapter berücksichtigt Folgeseiten innerhalb expliziter Zeit-/Seitenlimits und verwirft unvollständig abgerufene Listen. - -PIM eignet sich als ergänzende Quelle für einheitliche Produktbezeichnungen, technische Erklärungen und SKU-Zuordnung. Seine öffentlichen SKU-Listen bestätigen keine Bestellbarkeit oder Berechtigung in einem konkreten Projekt, keine Quoten, keine aktuellen Kubernetes-Versionen und keine verfügbaren VM-Images. Daher bleiben die jeweiligen Produkt-APIs die Quelle der technischen Auswahlwerte. Die in der API-Übersicht als auslaufend markierte v1 wird nicht neu angebunden. - -### Assistent: aktueller PIM-v2-Abruf (2026-10-10) - -Editor-Chat und vorgelagerte Template-Beratung laden pro Nachricht erneut die -Produktkataloge über dieselbe benutzer-/tenantgebundene Abstraktion wie der Editor -und ergänzend öffentliche PIM-Daten. Der Chat verwendet die Konfigurationsregion; -die Template-Beratung fragt eu01 und eu02 getrennt ab. Kein gemeinsamer -Benutzer-/Tenant-Cache und kein Operator-Credential-Fallback. Ein Ausfall des -berechtigten Produktkatalogs verhindert nicht die Erklärung öffentlicher PIM-Fakten, -ist aber kein Nachweis eines auswählbaren Plans. - -Implementiert: Products und nach Produkt/Region gefilterte SKUs, Cursor-Paginierung -mit 100 Einträgen je Seite, maximal 30 Seiten und 15 Sekunden Budget pro Liste. -Der relevante Produktumfang ist begrenzt (maximal acht Produkte), nicht der gesamte -STACKIT-Katalog. Beim echten eu01-Abruf: Kubernetes Engine, VPN, Observability, -Server und Git, insgesamt 330 SKUs; VPN mit 100, 500 und 1000 Mbit/s. -Der echte eu02-Abruf liefert dieselben fünf Produktbezeichnungen und 129 SKUs, -darunter keine VPN-SKUs. Das ist kein Anlass, eu01-VPN-Pläne für eu02 anzubieten. - -Das Modell erhält normalisierte Labels/Werte und öffentliche technische Attribute, -keine Credential-Profile, IAM-Rollen/Permissions, Referenzprojekt-IDs, Schlüssel, -Preise oder Rohantworten. Kontextlimits: 50 Optionen je Produktkatalog und -100 priorisierte PIM-SKUs je Region, jeweils mit Gesamtzahl/Ausschnitt-Markierung -und Abrufzeit. Daher keine Zusage vollständiger oder ständig verfügbarer Listen. -Die SKU-ID ist eine Abrechnungsartikelnummer, nicht die VPN-Plan-ID; Zuordnung -technischer Auswahlwerte nur über planId/flavor und berechtigte Produktoptionen. - -Für Fragen zu VPN-Leistungsklassen und Flavors ergänzt eine deterministische, -begrenzte Faktenliste den Modelltext, weil Qwen in echten Tests Zahlen trotz -geliefertem Kontext ausgelassen hat. Abgekündigte Einträge werden ausgeschlossen; -Bandbreite/Verbindungszahl/vCPU stammen aus gelieferten Attributen. Die RAM-Einheit -ist noch nicht verifiziert und wird nicht als GB behauptet. Die Faktenliste ist -derzeit deutschsprachig. Technische ID-Felder sind keine zulässigen Rückfragen. -Freie fachliche Beratung, zweisprachige Darstellung und vollständige komplexe -Konfigurationsänderungen bleiben gesondert zu qualifizieren. +- SKU attributes such as region, technical features, product maturity and deprecation, plus article numbers for billing. +- Publicly available lists with cursor pagination (`pageSize` maximum 100). The adapter follows subsequent pages within explicit time/page limits and discards incompletely retrieved lists. + +PIM is suitable as a supplementary source for consistent product names, technical explanations and SKU mapping. Its public SKU lists confirm neither orderability nor entitlement in a specific project, quotas, current Kubernetes versions or available VM images. Therefore the respective product APIs remain the source of technical selection values. The v1 marked as retiring in the API overview is not newly integrated. + + +### Assistant: current PIM v2 retrieval (2026-10-10) + +Editor chat and preceding template advice reload product catalogues per message +through the same user-/tenant-bound abstraction as the editor, +plus public PIM data. Chat uses the configuration region; +template advice queries eu01 and eu02 separately. No shared +user/tenant cache and no operator-credential fallback. Failure of the +authorized product catalogue does not prevent explaining public PIM facts, +but is not proof of a selectable plan. + +Implemented: products and SKUs filtered by product/region, cursor pagination +with 100 entries per page, at most 30 pages and a 15-second budget per list. +Relevant product scope is bounded (at most eight products), not the whole +STACKIT catalogue. Real eu01 retrieval: Kubernetes Engine, VPN, Observability, +Server and Git, 330 SKUs in total; VPN with 100, 500 and 1000 Mbit/s. +Real eu02 retrieval returns the same five product names and 129 SKUs, +including no VPN SKUs. This is no reason to offer eu01 VPN plans for eu02. + +The model receives normalized labels/values and public technical attributes, +no credential profiles, IAM roles/permissions, reference project IDs, keys, +prices or raw responses. Context limits: 50 options per product catalogue and +100 prioritized PIM SKUs per region, each with total count/subset marker +and retrieval time. Thus no promise of complete or continuously available lists. +The SKU ID is a billing article number, not the VPN plan ID; map +technical selection values only through planId/flavor and authorized product options. + +For questions about VPN performance tiers and flavors, a deterministic, +bounded fact list supplements model text because Qwen omitted numbers in real tests +despite supplied context. Deprecated entries are excluded; +bandwidth/connection count/vCPU come from supplied attributes. The RAM unit +is not yet verified and is not claimed to be GB. The fact list is +currently German. Technical ID fields are not permissible follow-up questions. +Free-form domain advice, bilingual presentation and complete complex +configuration changes remain separately subject to qualification. diff --git a/landing-zone-configurator/docs/common-editor.de.md b/landing-zone-configurator/docs/common-editor.de.md new file mode 100644 index 0000000..9d4fef9 --- /dev/null +++ b/landing-zone-configurator/docs/common-editor.de.md @@ -0,0 +1,495 @@ + + +# Gemeinsamer Editor + +[English](common-editor.md) | [Deutsch](common-editor.de.md) + +Stand: 2026-10-15. Veröffentlichung auf `lzc-dev` ausschließlich vom Feature-Branch. + + + +## Bedienung + +Eine gültige App-Sitzung und ein aktueller STACKIT-Identitätsnachweis sind +getrennt: Die App-Sitzung bleibt acht Stunden bestehen, während der +STACKIT-Nachweis früher ablaufen kann. Name und **Abmelden** bedeuten weiterhin, +dass du im Configurator angemeldet bist. Falls ein aktueller Nachweis fehlt, +bietet die Kopfzeile **STACKIT bestätigen** an, nicht noch einmal **Mit STACKIT +anmelden**. Der Dialog erklärt, dass diese Bestätigung für geschützte +STACKIT-Aktionen nötig ist. Das Auslaufen des Nachweises meldet dich nicht aus +der App ab; es verlängert aber auch keine Cloud-Berechtigung. Ohne App-Sitzung +bleibt **Mit STACKIT anmelden** die eigentliche Anmeldung. + +1. Eine beliebige Vorlage öffnen und **Konfiguration erstellen** wählen. +2. **Grundlagen → Ordner → Netzwerk → Plattform → Projekte → Betrieb → Prüfen**. +3. Einstellungen nur bei Bedarf aufklappen. **Accelerator-Standard verwenden** entfernt die + eigene Einstellung und nutzt den Engine-Standard, nicht den Vorlagenwert. Der Export enthält weiterhin nur explizite Angaben; + angezeigte Standardwerte werden nicht beim bloßen Öffnen materialisiert. +4. In **Projekte** Public, Corporate oder Sandbox hinzufügen. Public/Corporate + können nach Bestätigung gewechselt werden. Der Zielordner wird angezeigt. + Corporate benötigt eine passende Region und einen vorhandenen Bereich. + Sandboxes haben einen eigenen Accelerator-Vertrag; ein Wechsel zu einer + Landing Zone erfolgt durch bewusstes Neuanlegen und Entfernen. +5. **Prüfen** zeigt bekannte Konfigurationsfehler und getrennte Ausführungsgrenzen. + Anschließend tfvars herunterladen oder JSON und tfvars gemeinsam im Fork speichern. + +Einzelbereiche aus alten Hub-&-Spoke-Vorlagen können mit **Mehrere Netzwerkbereiche +verwalten** ohne Änderung der `default`-Referenz in eine Bereichsliste überführt +werden. Bereiche mit Projekt-, DNS-, Firewall-, VPN- oder Clusterreferenzen lassen +sich nicht versehentlich entfernen. Organisationsbaum und Netzwerkzuordnung +verwenden dieselben Daten; ein Hub-Projekt wird je Netzwerkbereich gezeigt. + +Neue Standalone-Entwürfe markieren das Beispielprojekt ausdrücklich als Public +(Korrektur für #84). Der verlustfreie Import und bestehende Dokumente bleiben +unverändert; in einem älteren betroffenen Entwurf die Projektart ausdrücklich auf +**Public** setzen. Eigene Organisations-ID und Verantwortlichen-E-Mail-Adressen +ersetzen weiterhin die Platzhalter der Vorlage. + +Unter **Plattform** stehen Git-Service, Plattform-Kubernetes, zentrales Observability +und Audit-Protokollierung. Kubernetes wird mit einer leeren Clusterliste deaktiviert, +Git-Service mit `null`. Das Entfernen konfigurierter Dienste verlangt eine Bestätigung; +verbleibende Namespace-Abhängigkeiten werden bei der Konfigurationsprüfung gemeldet. +Observability ist ein eigener Dienst. Die Audit-Protokollierung erstellt einen Telemetry +Router mit Zielen STACKIT Logs und S3-Archiv. Der Management-Archiv-Bucket existiert +auch bei deaktivierter Audit-Protokollierung. + +Im Konfigurations-Chat zeigt der Änderungsvorschlag strukturierte Werte mit +Fachbezeichnungen und ihren Werten, beispielsweise **Aufbewahrung (Tage): 90** +für Audit-Protokollierung. Das gilt auch für Ausgangswerte, verschachtelte Objekte, +Listen und den Konfliktdialog. Leere Listen (`[]`) und Objekte (`{}`) bleiben von +**Nicht gesetzt** unterscheidbar. Der Hinweis **Vollständiger Ersatz** bedeutet, +dass die gesamte vorgeschlagene Einstellung übernommen wird, nicht nur einzelne +Unterfelder. Auswahl, ausdrückliche Übernahme und separates Speichern bleiben +unverändert; eine Vorschau ändert weder die Konfiguration noch Cloud-Ressourcen. + + + +### Assistant und Application-Templates (Dev-Release vom 2026-10-15) + +Neue Template-Vorschläge müssen Name, Art, Region und Einstellungen zusammen +enthalten. Bestehende Templates bleiben partiell änderbar. Der Assistant erhält +für Plattform-Entwürfe vorhandene Netzwerkbereichsschlüssel und Regionen, keine +Cloud-Ressourcenkennungen. Template-Entscheidungen referenzieren eine vorhandene +Benutzernachricht; deren Originaltext stellt der Server bereit. +Der daraus abgeleitete Einstellungsumfang begrenzt das geschlossene +Modell-Ausgabeschema: Eine reine Netzwerkanfrage bietet keine Observability-, +Secrets-Manager-, Namespace-Service- oder Parameter-Policy-Einstellungen an. +Explizit angeforderte zusätzliche Einstellungen bleiben unterstützt; der volle +Import-, Speicher- und Runtime-Vertrag wird nicht eingeschränkt. +Der Vorschlagsvergleich im Web-UI liest Templates aus derselben +ID-freien, nach stabilen Schlüsseln indizierten Projektion wie das Backend, +nicht als vermeintliche Terraform-Eingabe. Übernahme aktualisiert den lokalen +Entwurf; erst ausdrückliches Speichern persistiert die Templates. +Ungültige erzeugte Template-Strukturen werden als fehlgeschlagener +Assistant-Vorschlag gemeldet, nicht als Zugangsdaten im Benutzertext. +Gespeicherter Chat und Konfiguration bleiben bei einer Ablehnung unverändert. + +Der Assistant unterscheidet anhand der referenzierten Benutzeranfrage zwischen +Ergänzungen, Korrekturen und einem gewünschten vollständigen Satz von Templates +oder DNS-Zonen. Eine Definition „Corporate und Public, keine Sandbox“ ist eine +Satzdefinition, nicht automatisch eine Ergänzung neben den Startbeispielen. +Ein ausdrücklich zusätzliches Template bzw. eine zusätzliche Zone bleibt additiv. +DNS-Korrekturen verwenden vorhandene stabile Zonenschlüssel; bei mehrdeutigen +Zielen ist eine Rückfrage erforderlich. +Bei einem Satzersatz zeigt die Vorschlagsliste jeden entfernten Eintrag mit +„Eintrag entfernen“ und eigenem Auswahlfeld. Abgewählte Einträge sowie unabhängige, +zwischenzeitliche Ergänzungen bleiben erhalten. Zwischenzeitliche Änderungen +an einem ausgewählten Eintrag benötigen weiterhin Konfliktbestätigung. +Beibehaltene Templates behalten ihre IDs und nicht angeforderten Einstellungen. +Restvorschläge werden nach einer Teilübernahme aus dem aktuellen Kandidaten +zusammengesetzt. Bereits übernommene Einträge bleiben auch bei einer späteren +Übernahme der verbliebenen Löschungen erhalten, sowohl im lokalen Vorschaupfad +als auch beim direkten, revisionsgeprüften Speichern über die API. +Keine dieser Änderungen speichert oder löscht automatisch Kundenkonfigurationen. +Die Nachbesserungen sind als Quelle `045eeafb9813e542f59062139d386b819a3792df` +committed, gepusht und über den erfolgreichen +[Dev-Release 38782981970](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38782981970) +veröffentlicht. Die Freigabe erfolgte nach den normalen geschützten Dev-Gates. +Die lokale Regression besteht aus 718 bestandenen Unit-Tests (57 übersprungen), +51 isolierten PostgreSQL-Plan-/Broker-Tests, 53 PostgreSQL-Integrationstests und +302 Desktop-/Mobil-Browsertests. +Typprüfung, Build und generierte Assistant-Verträge sind geprüft. Dies ersetzt +keine erneute echte Modell- oder Kunden-Cloud-Abnahme; es wurde kein Kunden-Plan +oder Apply gestartet. + +Der endgültige Release bestand auch in CI 718 Unit-, 53 Datenbank- und +302 Browsertests sowie die native Runner-/Image-/Archiv-Qualifikation. +Runner-Staging mit Image-/Engine-Prüfung, Migrationen, API-/Web-Deployment, +Service-Verbindungen, separate Runner-Organisation und Broker-Isolation sowie +öffentliche Routen sind erfolgreich. Nach dem Deployment entsprechen die tatsächlich +ausgelieferten JavaScript-/CSS-Dateien bytegenau dem freigegebenen Stand. +Acht öffentliche Auth-/PKCE-/Callback-/CSRF-Prüfungen sind bestanden. Echte anonyme +Desktop-/Mobil-Browser zeigen jeweils zehn Name-/Typ-Komponenten, funktionierendes +Auf-/Zuklappen per Tastatur und Maus sowie überlappungsfreie Vorschauen bei komplett +geöffneten Projekten, ohne Browserfehler oder Server-Mutationen. +Ein echter Benutzerlogin, Organisationsnachweis und Kunden-Plan wurden nicht +automatisiert durchgeführt. + +Für den damaligen Release blieb die separate +[Validate-Configurator-Ausführung 38782981811](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38782981811) +bei den Standalone-Vertrags- und STACKIT-/GitHub-Operator-Guard-Assertions rot. +Dieser historische Lauf wird nicht als bestanden gewertet. Die unten dokumentierte +Dev-Abnahme vom 2026-10-16 enthält die Korrekturen und einen vollständig grünen +neuen Validierungslauf. + +Die echte Modell-Abnahme der Originalanfrage nach Corporate-/Public-Templates +mit lokalen Netzen ist in drei unabhängigen synthetischen Läufen bestanden: +zwei benannte Templates, gespeicherte Region, lokale Netze, keine Sandbox, +keine zusätzlichen Dienste und keine Rückfragen. Corporate verwendet den +vorhandenen `default`-Netzwerkbereich, auch ohne explizites Key-Override. +Die Quellenprüfung für Produktpläne, Adressen und IDs bleibt unverändert. +Die Modellabnahme ist synthetisch und verändert keine Kundenkonfiguration. +Die Korrekturen sind mit Nutzerfreigabe als `a031273` committed, gepusht und +über den erfolgreichen [Dev-Release 38710301311](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38710301311) +veröffentlicht. Öffentliche Hosted-Prüfungen und der Abgleich des ausgelieferten +UI-Bundles mit diesem Release sind bestanden; die Abnahme führt keine +Kunden-Cloud-Ressourcen aus. + +Auswahlfelder gibt es für Regionen, regionale Netzwerkkennungen, vorhandene +Netzwerkbereiche, Namespace-Projektkennungen sowie die durch den Accelerator +festgelegten Audit-Scope-, VPN-Routing-, Secret-Enforcement- und Firewall-Werte. +Nicht mehr passende importierte Werte bleiben sichtbar und werden nicht automatisch +ersetzt. Freie Bezeichnungen bleiben Textfelder. Regionale Produktangebote wie +Maschinentypen, Pläne und Versionen benötigen künftig API-basierte Kataloge; dafür +werden keine vermeintlich vollständigen statischen Listen vorgetäuscht. + + + +### Template-Übersicht + +Application-Templates erscheinen als auswählbare Übersichtskarten mit Namen, +stabiler Kennung, Art, Region, Zielordner und Netzzuordnung. Nur das ausgewählte +Template zeigt sein vollständiges Bearbeitungsformular. Neue Templates werden +direkt ausgewählt; nach Entfernen eines Templates bleibt ein vorhandenes Template +bearbeitbar. Die Strukturansicht gruppiert dieselben Templates nach Art und +Zielordner und öffnet beim Auswählen denselben Detailbereich. + +Die Netzwerkansicht zeigt Corporate-Templates nur unter dem referenzierten +Netzwerkbereich ihrer Region; ein fehlendes Key-Override bedeutet weiterhin +`default`. Public-Templates werden nicht als zentrale Netzwerk-Spokes dargestellt. +Fehlende SNA- oder Ordnerreferenzen bleiben ausdrücklich sichtbar. Templates +bleiben Entwürfe für spätere Bestellungen, keine bereits angelegten Projekte. +Auswählen und Bearbeiten speichern oder deployen nichts automatisch. + +Die Übersicht ist mit Nutzerfreigabe als Quelle `9c19327` über den erfolgreichen +[Dev-Release 38720037784](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38720037784) +veröffentlicht. Alle 296 Desktop-/Mobil-Browsertests bestanden, einschließlich +Auswahl, gemeinsamer Strukturvorschau, Hinzufügen, Entfernen und leerem Zustand. +Die ausgelieferten JavaScript- und CSS-Bundles wurden mit der exakt gebauten +Quelle abgeglichen. Bestehende Kundenkonfigurationen wurden nicht verändert. + + + +### Komponenten in der Strukturvorschau + +Die Strukturvorschau zeigt unter den Plattformprojekten auch deren konfigurierte +Komponenten, jeweils nur mit Name und Typ: Automatisierungs-Service-Account, +Secrets Manager, Object-Storage-Buckets, +Observability, Audit Logs und Telemetry Router, zugeordnete SNA, Netze, +DNS-Zonen, Firewalls einschließlich eines konfigurierten HA-Partners, VPN-Gateways, +Git-Service sowie Kubernetes-Cluster und ihre optionalen Dienste. +Netzwerkkomponenten werden nach Region und Netzwerkbereich dem richtigen Hub +zugeordnet. SNA erscheinen als logisch zugeordnete Netzwerkbereiche, nicht als +Aussage über deren tatsächlichen Resource-Manager-Container. +Deaktivierte Dienste und lediglich referenzierte bestehende DNS-Zonen erscheinen +nicht als neu bereitzustellende Komponenten. Das Audit-Archiv bleibt entsprechend +dem Accelerator auch ohne aktivierte Audit-Protokollierung sichtbar. +Die Vorschau verwendet native Standardwerte ausschließlich zum Anzeigen; sie +materialisiert diese nicht im Entwurf und liest keine bestehenden Cloud-Ressourcen. +Projekte mit Komponenten sind zunächst eingeklappt und lassen sich über den Pfeil, +die gesamte Überschriftszeile oder per Tastatur öffnen und schließen. +Struktur- und Netzwerkvorschau bleiben im Editor untereinander im normalen +Dokumentfluss, auch wenn alle Projekte geöffnet sind; kein zweiter Sticky-Bereich +überdeckt die darunterliegenden Templates. + + + +### Erstbereitstellungspläne + +Die generelle Sperre für `audit_logs`, `observability`, `connectivity` und `devops` +ist durch geprüfte Unterstützung ersetzt. Für Connectivity umfasst diese +Netzwerkbereiche, DNS, Firewall-/HA-Infrastruktur und VPN-Gateways. +Das Firewall-Image ist die bereits im Accelerator verwendete, versions- und +SHA-256-gebundene OPNsense-Datei; der Runner prüft die tatsächlichen Image-Dateien +und ihre Paketierung. Ein alter Runner ohne passendes Image bleibt ausdrücklich +gesperrt, statt einen vermeintlich ausführbaren Plan mit `/dev/null` zu erstellen. + +Das ist eine Plan-Freigabe, keine automatische Bereitstellung: Firewall-Policies, +Bootstrap, Appliance-Apply und VPN-Verbindungen mit vorab geteilten Schlüsseln +benötigen weiterhin ihre gesonderte Ausführungs- bzw. Secret-Binding-Unterstützung. +Audit-Ziele außerhalb des nachgewiesenen Organisationskontexts bleiben gesperrt. +Identitäts-/Owner-Nachweise, Mandantentrennung, Snapshot-Prüfung und explizite +Freigaben bleiben unverändert erforderlich. Die konkreten Grenzen sind im +[Runner-Vertrag](../runner/README.de.md) beschrieben. + +Vorbereitungen sind unveränderliche Nachweise einschließlich Accelerator-Revision. +Gespeicherte Konfigurationen sind davon getrennt und bleiben nach einem +Configurator-Release weiter bearbeitbar und als Quelle neuer Vorbereitungen +nutzbar. Ein reiner Configurator-Versionswechsel verlangt keine neue Vorbereitung, +solange deren Accelerator-Vertrag weiterhin zum installierten Runner passt. +Der behobene Fehler betraf auch frisch erstellte Vorbereitungen: Die Oberfläche +verwendete noch die Basisrevision, während der Runner bereits den +Plattformvertrags-Root erwartete. Dafür ist keine Neuerstellung der Konfiguration +und kein neuer State erforderlich. +Die Oberfläche zeigt bei einem Runner mit Plattformvertrags-Root eine ausdrücklich +zu bestätigende Vorbereitung für dessen aktuellen Stand an. Ohne Bestätigung +bleibt deren Erstellung gesperrt. Passt die Revision einer älteren Vorbereitung +nicht zum Runner, nennt der Plan-Fehler jetzt diesen Grund und fordert eine neue +Vorbereitung an, statt nur eine ungültige Konfiguration zu melden. Bestehende +Vorbereitungen, State-Bindungen und Plan-Nachweise werden dabei nicht umgeschrieben; +Plan und Apply behalten ihre eigenen Freigaben. + +Die Auswahl des aktuellen Accelerator-Stands ist auch für eine Erstbereitstellung +zulässig; sie setzt keine bereits bereitgestellte Plattform voraus. Ohne +State-Bindung oder mit einem leeren Standard-State (Version 0) kann eine neue +Vorbereitung entstehen. Das gilt auch nach einem fehlgeschlagenen ersten Plan. +Vorhandene Bindungen bleiben erhalten. Ein gesperrter State verhindert den +Wechsel weiterhin ausdrücklich; ein bereits gespeicherter Standard-State muss +vor dem Wechsel an sein S3-Backend übernommen werden. Ein ausgewähltes +S3-Backend ohne lesbaren State erlaubt weiterhin keinen Bootstrap. +Vorbereitungsfehler benennen State-Sperren, Backend-Konflikte, ungültige +Anfragen und abgelaufene Sicherheitsbestätigungen getrennt. Unbekannte +Serverfehler zeigen HTTP-Status und Fehlercode statt einer endlosen +Aufforderung zum Aktualisieren der Liste. + +Der DNS-Zonentyp bezeichnet die Rolle `primary` oder `secondary`, nicht eine +Sichtbarkeit `public` oder `private`. Die gemeinsame Konfigurationsprüfung +beanstandet ungültige Typen am konkreten Zonenfeld, auch in regionalen +Connectivity-Konfigurationen. Der generische Assistant-Vertrag erlaubt dieselben +DNS-Rollen im Modell-Ausgabeschema und in der serverseitigen Übernahmeprüfung. +Das gilt auch für vollständige Netzwerkobjekte sowie direkte Feldvorschläge, +jeweils als Ergänzung oder Ersatz und in beiden Netzwerkmodellen. +Alte Entwürfe bleiben unverändert ladbar und +exportierbar; sie werden nicht stillschweigend umgedeutet. Für eine selbst +verwaltete neue Zone kann der Benutzer den Typ ausdrücklich auf `primary` +korrigieren. Anschließend speichern und eine neue Vorbereitung für diese +Revision erstellen; alte Vorbereitungen behalten ihren ursprünglichen Snapshot. +Diese ergänzende DNS-Validierung ist noch nicht Teil der folgenden Dev-Abnahme. + +Bei Plattform-Plan und -Apply übermittelt der Runner während einer laufenden +OpenTofu-Phase alle zwei Sekunden einen bereinigten Ausgabestand. Die API speichert +ihn verschlüsselt und liefert ihn bereits während der Ausführung an die +Ausgabeansicht. Die Übertragungen erfolgen nacheinander; vor Ergebnisbestätigung +und Aufräumen werden ausstehende Übertragungen abgewartet. Unvollständige letzte +Zeilen werden erst nach ihrem Abschluss übertragen, damit keine nur teilweise +geschriebenen Zugangsdaten die Bereinigung umgehen. Nach dem Endstatus sind +weitere Änderungen des Protokolls gesperrt. „Ausgabe folgen“ steuert weiterhin +das automatische Scrollen, nicht die Übertragung. Der getrennte +Application-Runner behält seinen bisherigen einmaligen Abschlussbericht. +Diese Live-Ausgabekorrektur ist ebenfalls noch nicht veröffentlicht. + +Die zugehörige lokale Regression umfasst frische und zuvor fehlgeschlagene +Erstpläne mit Standard- und S3-Backend bis zum erfolgreichen Plan-Nachweis, +ohne Apply. Sie prüft unveränderte Konfigurationen, alte Vorbereitungen, +State-Bindungen und weiterhin gesperrte Zustände. Desktop- und Mobiltests +decken außerdem die ausdrückliche Auswahl des aktuellen Accelerator-Stands +ohne vorhandenes S3-Backend sowie konkrete und unbekannte Fehlermeldungen ab. +**Dev-Abnahme vom 2026-10-16:** Die Nachbesserung ist als unveränderliche Quelle +`6a5014e7821586a60699bcd52d148f0d56718b8b` über den erfolgreichen +[Dev-Release 38867967256](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38867967256) +veröffentlicht. Auch die zugehörige +[Validate-Configurator-Ausführung 38867967250](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38867967250) +ist vollständig erfolgreich. Die normale geschützte Dev-Freigabe erfolgte erst +nach erfolgreicher separater Validierung und erfolgreichem Release-Build. +Beide Workflows bestanden 718 Unit-Tests (63 im normalen Unit-Lauf übersprungen), +57 ausdrücklich aktivierte PostgreSQL-Plan-/Broker-Tests, 53 API-Datenbanktests, +304 Desktop-/Mobiltests und 13 native Template-Vertragsprüfungen. Die separate +Validierung bestand außerdem alle sechs Infrastruktur-Roots einschließlich +Formatierung, Validierung und Mock-Plänen. Der Release bestand die native +Runner-/Provider-/Image-/Archiv-Qualifikation und die tatsächliche +Cloud-Foundry-Bereitstellung einschließlich Migrationen, Service-Verbindungen, +separater Runner-Organisation, abgewiesenem Job-Ticket und öffentlichen Routen. + +Die ausgelieferten JavaScript-/CSS-Dateien entsprechen bytegenau dem freigegebenen +Build. Acht öffentliche Auth-/PKCE-/Callback-/CSRF-Prüfungen sind bestanden. +Echte anonyme Desktop-/Mobil-Browser zeigen jeweils zehn Name-/Typ-Komponenten, +funktionierendes Auf-/Zuklappen und überlappungsfreie Vorschauen ohne +Browserfehler oder Server-Mutationen. Die Anmeldung wurde nicht mit einem +echten Benutzer durchlaufen; ein Organisationsnachweis oder Kunden-Plan/Apply +wurde nicht ausgeführt. Gespeicherte Kundenkonfigurationen wurden nicht verändert. + +Der separate Validierungsworkflow prüft die reale Release-Konfiguration im +Application-Job nach dem API-Build. Der Infrastruktur-Job benötigt weiterhin +keine Anwendungs-Abhängigkeiten. Der vorherige STACKIT-Fehler entstand durch +den dort fehlenden kompilierten Validator, nicht durch eine GitHub-Pflicht. +Der native Standalone-Test erwartet für das inzwischen ausdrücklich als Public +markierte Beispiel einen erfolgreichen Vertrag. Separate Negativtests prüfen +weiterhin, dass fehlendes oder ausdrücklich wahres `corporate` ohne zentrale +Connectivity abgewiesen wird; der native Standardwert bleibt unverändert. +Validierung und Release führen beide `npm run test:common-contract` und +`npm run test:platform-database` aus. Der zweite Befehl aktiviert die isolierte +PostgreSQL-Broker-Suite ausdrücklich, die im normalen Unit-Lauf übersprungen +wird. Dadurch prüfen auch kommende Releases die Erstbereitstellung und die +nativen Template-Verträge, nicht nur bereits vorhandenen Plattform-State. +Die API-Datenbankintegration verwendet in beiden Workflows dieselben zwei +Worker und 30 Sekunden Test-Timeout. Das bisherige 5-Sekunden-Limit im +Validierungsworkflow brach den mehrstufigen Vertrags-/Identitätsnachweis ab, +bevor dessen Aufräum- und Wiederherstellungsschritte abgeschlossen waren. + +Die gemeinsame Release-Abnahme bestand 710 Unit-Tests (57 im Unit-Lauf +übersprungen), 51 PostgreSQL-Broker-Tests und 300 Desktop-/Mobil-Browsertests +sowie Typprüfung, Build und 19 gezielte Release-/Staging-/Runner-Evidence-Tests. +Native Vertrags-, Offline-Provider- und echte Image-/Archiv-Prüfungen +qualifizierten die Runner-Unterstützung zusätzlich. +Es gab keine Kunden-Cloud-Plans, Applies oder Destroys. + +Komponenten-Vorschau, Plan-Unterstützung und die eindeutige STACKIT-Bestätigung +sind mit Nutzerfreigabe als Quelle `0cee76f` über den erfolgreichen +[Dev-Release 38769119929](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38769119929) +veröffentlicht. Auf CF bestanden Image-SHA-Prüfung, native Runner-Checks, +Migrationen, Dienstverbindungen, Runner-Isolation und die kanonischen Routenprüfungen. +Die ausgelieferten JS-/CSS-Dateien stimmen bytegleich mit der gebauten Quelle +überein. Acht zusätzliche Live-Auth-/PKCE-Prüfungen und zwei echte anonyme +Desktop-/Mobil-Browserläufe bestanden; die Vorschau zeigte jeweils nur Name +und Typ, ohne Browserfehler, horizontalen Überlauf oder Server-Mutationen. + +Das große Image fehlt nur im Hosted-Upload und wird beim Staging SHA-geprüft +ohne zweite Dateikopie ins unveränderliche Droplet verschoben. Dieses ist der +dauerhafte CF-Cache; ein redundantes großes Buildpack-Cache-Archiv entfällt. +Es gibt keinen Download pro Nutzer oder Plan. Web/API verwenden 6 GiB Disk +für die größere Inspektionskopie und Staging-Komprimierung; das qualifizierte +4-GiB-Budget der isolierten Runner-Jobs und Tasks bleibt unverändert. +Paketidentität und bytegleiche Wiederherstellung beider Archive sind geprüft. +Details stehen unter +[CF-Staging und Cache](../deploy/cloud-foundry/README.de.md#image-staging-and-caching). +Ein persönlicher STACKIT-Login, Live-Owner-Nachweis und Kunden-Cloud-Plan wurden +dadurch nicht ausgeführt oder vorgetäuscht. + +Der separate +[Validate-Configurator-Lauf 38769119849](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38769119849) +bleibt an den bereits bekannten Standalone-Template-Vertrags- und +STACKIT/GitHub-Operator-Guard-Assertions rot. Der erfolgreiche Release-Lauf +und die Live-Abnahme sind davon getrennt; nicht sämtliche Repository-CI ist grün. + + + +## Kompatibilität und Grenzen + +- Bestehende v1/v2-Dokumente bleiben im bisherigen Editor nutzbar. **Zum gemeinsamen + Editor wechseln** ist eine ausdrückliche Migration; beim Wechsel werden die + bisherigen Engine-Werte erhalten. Bestehende Deployment-Vorbereitungen bleiben unverändert. +- Der bisherige Standalone-Editor kann auf der Standalone-Vorschauseite weiterhin + ausgewählt werden, einschließlich des bisherigen persönlichen Plan-Ablaufs. +- v3 wird im Fork und Browser-Arbeitsstand unterstützt. Vorlagen-Hashes, + Mandanten-/Kontotrennung, Schreibbasis, Konfliktprüfung und atomarer Export bleiben erhalten. +- v3-Deployment-Vorbereitungen sind **serverseitig gesperrt**. Runner-Anbindung und + geschützte zusätzliche Credential-Bindings werden separat abgenommen. +- Keine Secret-Felder in den Konfigurationsformularen. VPN-Schlüssel, Firewall- + Passwörter/API-Secrets und Kubeconfigs dürfen nicht in Freitextfelder eingefügt werden. +- Die wirkungslose Ordnerbeschreibung wird nicht als bearbeitbares Feature angeboten. +- Formular- und Typabdeckung sind keine Provider-Validierung. Plan/Refresh, + Dienstverfügbarkeit, Berechtigungen und jede Modul-Kombination benötigen weitere + Ausführungsabnahme. Grenzen #37/#65/#80 bleiben sichtbar. +- Kein Kunden-Apply ohne ausdrückliche neue Freigabe, kein Destroy. + + + +## Prüfung + +- [x] Fachbezeichnungen für sämtliche nicht-sensiblen Schemafelder geprüft. +- [x] Projektarten, Referenzen und Bereichsnormalisierung als Domain-Tests. +- [x] v3-JSON/tfvars atomar gespeichert; Deployment-Guard im Backend getestet. +- [x] Neuer Editor, Typwechsel, Navigation und Bereichsreferenzen im Browser getestet. +- [x] v3-Fork speichern, Export, Wiederaufnahme und gesperrte Vorbereitung getestet. +- [x] Legacy-Editor, GitHub-Anmeldung, Fork-Konflikte, Credentials und Plan-Ablauf regressionsgeprüft. +- [x] Release auf lzc-dev und Live-Verbindungstests abgenommen. + +Manuelle Prüfung nach Veröffentlichung: Hub-&-Spoke und Multi-Region öffnen, +Projektart/Bereich wechseln, Entwurf im eigenen Fork speichern, erneut öffnen und +Browser neu laden. Zusätzliche optionale Dienste unter Plattform/Betrieb prüfen. + + + +## Live-Abnahme + +Code `527bd9582f95d3cf845cfaf242f9022e1495fad8` veröffentlicht: + +- [Validate Configurator 36745965890](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36745965890): erfolgreich. +- [Configurator Release 36745965953](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36745965953): erfolgreich. +- 95 Anwendungstests und 20 Desktop-/Mobil-Browserprüfungen, einschließlich v3-Speicherung und Legacy-Kompatibilität. +- Native HCL-/OpenTofu-Vertragstests und Infrastrukturprüfung erfolgreich. +- CF-Netzwerk, PostgreSQL/Secrets-Manager-Verbindungen, isolierter Runner und öffentliche Routen erfolgreich geprüft. +- Direkter Live-Browsercheck: Multi-Region-Vorlage öffnen, neuen Editor starten, Projektliste/Netzwerkansicht auf Desktop und Mobilgerät prüfen; keine Seitenfehler oder horizontales Überlaufen. +- Öffentliche JavaScript-/CSS-Dateien per SHA-256 mit dem getesteten Build abgeglichen; `/healthz` liefert `ok`, Sitzung ohne Anmeldung `401`. + +[Live-Anwendung](https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud). +Keine Kunden-Konfiguration angewendet und keine Änderung nach `main` übernommen. + + + + +### Live-Nachbesserung: Plattformdienste und Voreinstellungen + +Code `10a6ec87f0d0fc9d32d4b9699bd8579fb651683c` veröffentlicht: + +- [Validate Configurator 36752620342](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36752620342): erfolgreich. +- [Configurator Release 36752620332](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36752620332): erfolgreich. +- 96 Anwendungstests, 22 Desktop-/Mobil-Browserfälle und 11 native OpenTofu-Variablentests erfolgreich. +- Live-Build entspricht dem lokal geprüften Bundle; Gesundheitsprüfung `ok`, anonyme Sitzung `401`, keine Browserfehler. +- Live geprüft: neue Standalone-Konfiguration ist Public; Region ist eine Auswahl; Plattformdienste und Kubernetes-Deaktivierung vorhanden. Desktop-/Mobilansicht ohne horizontales Überlaufen, mobile Plattformansicht visuell geprüft. +- Verbindungstests zu PostgreSQL/Secrets Manager und Runner-Trennung erfolgreich. + +Manuell: App neu laden, einen **neuen** Standalone-Entwurf öffnen, Organisations-ID +und eigene Verantwortlichen-E-Mail-Adressen setzen, unter Projekte Public prüfen +und speichern/exportieren. In einem vorhandenen betroffenen Entwurf Public einmal +ausdrücklich wählen. Unter Plattform Kubernetes konfigurieren/deaktivieren; unter +Netzwerk regionale Kennungen und Bereichsverweise auswählen. + + + + +## Nächster Bedienstand: Komponenten statt vollständiger Feldliste + +Die [verbindlichen Designprinzipien](editor-design-principles.de.md) steuern die weitere +Entwicklung. Die erste Umsetzung betrifft Plattform- und Kubernetes-Namespace-Dienste: +Inaktive Komponenten sind über **Komponente hinzufügen** zugänglich, aktive +Komponenten bleiben sichtbar. Das Öffnen und Schließen des Katalogs verändert den +Export nicht. Eine leere Clusterliste ist inaktiv; ein nicht-null gesetzter +Observability-Konfigurationsblock aktiviert dagegen den Dienst auch mit Defaults. + +Public-/Corporate-Projektkarten enthalten direkte Schalter für Secrets Manager und +Observability. Sandboxes besitzen diese Root-Optionen nicht. Netzwerkbezeichnungen +benennen Connectivity und SNA ausdrücklich; ein Hinweis erläutert automatisch +erzeugte Routing-Tabellen. Ein vereinheitlichter Regions-/SNA-Editor und der geführte +VPN-Ablauf sind noch offen und im Designplan separat aufgeführt. + +Dieser Abschnitt beschreibt den Arbeitsstand; die oben protokollierten Live-Abnahmen +beziehen sich auf ihre ausdrücklich genannten Commits. + + + + +## Regions-/SNA-Ansicht und VPN-Assistent (Arbeitsstand 2026-10-01) + +Netzwerk zeigt Connectivity als Regionskarten mit SNAs und optionalen DNS-, +Firewall- und VPN-Komponenten. Bestehendes `connectivity` bleibt im bisherigen +Engine-Format; neue leere Konfigurationen können explizite Regionen hinzufügen. +Für bestehende Standardregion-Konfigurationen gibt es keine automatische Migration +auf regionale Module. Beim Öffnen bleibt der Export unverändert. + +Der [VPN-Assistent](vpn-configuration-scope.de.md) bildet den Accelerator-Vertrag ab +und prüft grundlegende Pflichtangaben. Geschützte Schlüssel, Live-Kataloge und +Deployment-Ausführung fehlen weiterhin. Die neue [Self-Service-Architektur](platform-application-architecture.de.md) +ist geplant; Rollen und Berechtigungen wurden dadurch noch nicht geändert. + + + + +## Live-Abnahme 2026-10-01: Regionen, SNAs und VPN + +Code `78d8f7c6debeba29330fa2699d617da17c3ba3be` auf lzc-dev veröffentlicht. + +- [Release 36830339767](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36830339767): erfolgreich, einschließlich PostgreSQL-/Secrets-Manager-Verbindungstests und Runner-Prüfung. +- [Validate 36830339847](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36830339847): erfolgreich. +- Release umfasst 97 Anwendungstests und 24 Desktop-/Mobil-Browserfälle. +- Live-Bundle `/assets/index-BjLAVHUk.js` entspricht dem geprüften Editor-Release. +- Direkter Gast-Browsercheck: bestehende Vorlagen/Projektansicht, Komponenten hinzufügen, Region eu01 hinzufügen, STACKIT VPN öffnen, Verbindung mit zwei Tunnelfeldern konfigurieren. +- Gesundheit `ok`, anonyme Sitzung `401`, keine Browserfehler und kein horizontales Überlaufen auf Mobilgerät. Keine Kundenressourcen angelegt. + +Manuelle Abnahme: vorhandene Konfiguration öffnen und unverändert speichern; neue +Connectivity-Region/SNA konfigurieren; optionales VPN hinzufügen und dessen Umfang, +Pflichtangaben und Tunnel-Einstellungen prüfen. VPN-Ausführung bleibt gesperrt. + +Der anschließend entstandene separate Application-Root und sein Compiler sind +ein lokaler bzw. im Feature-Branch prüfbarer Prototyp, kein Bestandteil der +aktivierten Self-Service-Oberfläche. diff --git a/landing-zone-configurator/docs/common-editor.md b/landing-zone-configurator/docs/common-editor.md index 767a99d..a1b9fe0 100644 --- a/landing-zone-configurator/docs/common-editor.md +++ b/landing-zone-configurator/docs/common-editor.md @@ -1,467 +1,483 @@ -# Gemeinsamer Editor - -Stand: 2026-10-15. Veröffentlichung auf `lzc-dev` ausschließlich vom Feature-Branch. - -## Bedienung - -Eine gültige App-Sitzung und ein aktueller STACKIT-Identitätsnachweis sind -getrennt: Die App-Sitzung bleibt acht Stunden bestehen, während der -STACKIT-Nachweis früher ablaufen kann. Name und **Abmelden** bedeuten weiterhin, -dass du im Configurator angemeldet bist. Falls ein aktueller Nachweis fehlt, -bietet die Kopfzeile **STACKIT bestätigen** an, nicht noch einmal **Mit STACKIT -anmelden**. Der Dialog erklärt, dass diese Bestätigung für geschützte -STACKIT-Aktionen nötig ist. Das Auslaufen des Nachweises meldet dich nicht aus -der App ab; es verlängert aber auch keine Cloud-Berechtigung. Ohne App-Sitzung -bleibt **Mit STACKIT anmelden** die eigentliche Anmeldung. - -1. Eine beliebige Vorlage öffnen und **Konfiguration erstellen** wählen. -2. **Grundlagen → Ordner → Netzwerk → Plattform → Projekte → Betrieb → Prüfen**. -3. Einstellungen nur bei Bedarf aufklappen. **Accelerator-Standard verwenden** entfernt die - eigene Einstellung und nutzt den Engine-Standard, nicht den Vorlagenwert. Der Export enthält weiterhin nur explizite Angaben; - angezeigte Standardwerte werden nicht beim bloßen Öffnen materialisiert. -4. In **Projekte** Public, Corporate oder Sandbox hinzufügen. Public/Corporate - können nach Bestätigung gewechselt werden. Der Zielordner wird angezeigt. - Corporate benötigt eine passende Region und einen vorhandenen Bereich. - Sandboxes haben einen eigenen Accelerator-Vertrag; ein Wechsel zu einer - Landing Zone erfolgt durch bewusstes Neuanlegen und Entfernen. -5. **Prüfen** zeigt bekannte Konfigurationsfehler und getrennte Ausführungsgrenzen. - Anschließend tfvars herunterladen oder JSON und tfvars gemeinsam im Fork speichern. - -Einzelbereiche aus alten Hub-&-Spoke-Vorlagen können mit **Mehrere Netzwerkbereiche -verwalten** ohne Änderung der `default`-Referenz in eine Bereichsliste überführt -werden. Bereiche mit Projekt-, DNS-, Firewall-, VPN- oder Clusterreferenzen lassen -sich nicht versehentlich entfernen. Organisationsbaum und Netzwerkzuordnung -verwenden dieselben Daten; ein Hub-Projekt wird je Netzwerkbereich gezeigt. - -Neue Standalone-Entwürfe markieren das Beispielprojekt ausdrücklich als Public -(Korrektur für #84). Der verlustfreie Import und bestehende Dokumente bleiben -unverändert; in einem älteren betroffenen Entwurf die Projektart ausdrücklich auf -**Public** setzen. Eigene Organisations-ID und Verantwortlichen-E-Mail-Adressen -ersetzen weiterhin die Platzhalter der Vorlage. - -Unter **Plattform** stehen Git-Service, Plattform-Kubernetes, zentrales Observability -und Audit-Protokollierung. Kubernetes wird mit einer leeren Clusterliste deaktiviert, -Git-Service mit `null`. Das Entfernen konfigurierter Dienste verlangt eine Bestätigung; -verbleibende Namespace-Abhängigkeiten werden bei der Konfigurationsprüfung gemeldet. -Observability ist ein eigener Dienst. Die Audit-Protokollierung erstellt einen Telemetry -Router mit Zielen STACKIT Logs und S3-Archiv. Der Management-Archiv-Bucket existiert -auch bei deaktivierter Audit-Protokollierung. - -Im Konfigurations-Chat zeigt der Änderungsvorschlag strukturierte Werte mit -Fachbezeichnungen und ihren Werten, beispielsweise **Aufbewahrung (Tage): 90** -für Audit-Protokollierung. Das gilt auch für Ausgangswerte, verschachtelte Objekte, -Listen und den Konfliktdialog. Leere Listen (`[]`) und Objekte (`{}`) bleiben von -**Nicht gesetzt** unterscheidbar. Der Hinweis **Vollständiger Ersatz** bedeutet, -dass die gesamte vorgeschlagene Einstellung übernommen wird, nicht nur einzelne -Unterfelder. Auswahl, ausdrückliche Übernahme und separates Speichern bleiben -unverändert; eine Vorschau ändert weder die Konfiguration noch Cloud-Ressourcen. - -### Assistant und Application-Templates (Dev-Release vom 2026-10-15) - -Neue Template-Vorschläge müssen Name, Art, Region und Einstellungen zusammen -enthalten. Bestehende Templates bleiben partiell änderbar. Der Assistant erhält -für Plattform-Entwürfe vorhandene Netzwerkbereichsschlüssel und Regionen, keine -Cloud-Ressourcenkennungen. Template-Entscheidungen referenzieren eine vorhandene -Benutzernachricht; deren Originaltext stellt der Server bereit. -Der daraus abgeleitete Einstellungsumfang begrenzt das geschlossene -Modell-Ausgabeschema: Eine reine Netzwerkanfrage bietet keine Observability-, -Secrets-Manager-, Namespace-Service- oder Parameter-Policy-Einstellungen an. -Explizit angeforderte zusätzliche Einstellungen bleiben unterstützt; der volle -Import-, Speicher- und Runtime-Vertrag wird nicht eingeschränkt. -Der Vorschlagsvergleich im Web-UI liest Templates aus derselben -ID-freien, nach stabilen Schlüsseln indizierten Projektion wie das Backend, -nicht als vermeintliche Terraform-Eingabe. Übernahme aktualisiert den lokalen -Entwurf; erst ausdrückliches Speichern persistiert die Templates. -Ungültige erzeugte Template-Strukturen werden als fehlgeschlagener -Assistant-Vorschlag gemeldet, nicht als Zugangsdaten im Benutzertext. -Gespeicherter Chat und Konfiguration bleiben bei einer Ablehnung unverändert. - -Der Assistant unterscheidet anhand der referenzierten Benutzeranfrage zwischen -Ergänzungen, Korrekturen und einem gewünschten vollständigen Satz von Templates -oder DNS-Zonen. Eine Definition „Corporate und Public, keine Sandbox“ ist eine -Satzdefinition, nicht automatisch eine Ergänzung neben den Startbeispielen. -Ein ausdrücklich zusätzliches Template bzw. eine zusätzliche Zone bleibt additiv. -DNS-Korrekturen verwenden vorhandene stabile Zonenschlüssel; bei mehrdeutigen -Zielen ist eine Rückfrage erforderlich. -Bei einem Satzersatz zeigt die Vorschlagsliste jeden entfernten Eintrag mit -„Eintrag entfernen“ und eigenem Auswahlfeld. Abgewählte Einträge sowie unabhängige, -zwischenzeitliche Ergänzungen bleiben erhalten. Zwischenzeitliche Änderungen -an einem ausgewählten Eintrag benötigen weiterhin Konfliktbestätigung. -Beibehaltene Templates behalten ihre IDs und nicht angeforderten Einstellungen. -Restvorschläge werden nach einer Teilübernahme aus dem aktuellen Kandidaten -zusammengesetzt. Bereits übernommene Einträge bleiben auch bei einer späteren -Übernahme der verbliebenen Löschungen erhalten, sowohl im lokalen Vorschaupfad -als auch beim direkten, revisionsgeprüften Speichern über die API. -Keine dieser Änderungen speichert oder löscht automatisch Kundenkonfigurationen. -Die Nachbesserungen sind als Quelle `045eeafb9813e542f59062139d386b819a3792df` -committed, gepusht und über den erfolgreichen -[Dev-Release 38782981970](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38782981970) -veröffentlicht. Die Freigabe erfolgte nach den normalen geschützten Dev-Gates. -Die lokale Regression besteht aus 718 bestandenen Unit-Tests (57 übersprungen), -51 isolierten PostgreSQL-Plan-/Broker-Tests, 53 PostgreSQL-Integrationstests und -302 Desktop-/Mobil-Browsertests. -Typprüfung, Build und generierte Assistant-Verträge sind geprüft. Dies ersetzt -keine erneute echte Modell- oder Kunden-Cloud-Abnahme; es wurde kein Kunden-Plan -oder Apply gestartet. - -Der endgültige Release bestand auch in CI 718 Unit-, 53 Datenbank- und -302 Browsertests sowie die native Runner-/Image-/Archiv-Qualifikation. -Runner-Staging mit Image-/Engine-Prüfung, Migrationen, API-/Web-Deployment, -Service-Verbindungen, separate Runner-Organisation und Broker-Isolation sowie -öffentliche Routen sind erfolgreich. Nach dem Deployment entsprechen die tatsächlich -ausgelieferten JavaScript-/CSS-Dateien bytegenau dem freigegebenen Stand. -Acht öffentliche Auth-/PKCE-/Callback-/CSRF-Prüfungen sind bestanden. Echte anonyme -Desktop-/Mobil-Browser zeigen jeweils zehn Name-/Typ-Komponenten, funktionierendes -Auf-/Zuklappen per Tastatur und Maus sowie überlappungsfreie Vorschauen bei komplett -geöffneten Projekten, ohne Browserfehler oder Server-Mutationen. -Ein echter Benutzerlogin, Organisationsnachweis und Kunden-Plan wurden nicht -automatisiert durchgeführt. - -Für den damaligen Release blieb die separate -[Validate-Configurator-Ausführung 38782981811](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38782981811) -bei den Standalone-Vertrags- und STACKIT-/GitHub-Operator-Guard-Assertions rot. -Dieser historische Lauf wird nicht als bestanden gewertet. Die unten dokumentierte -Dev-Abnahme vom 2026-10-16 enthält die Korrekturen und einen vollständig grünen -neuen Validierungslauf. - -Die echte Modell-Abnahme der Originalanfrage nach Corporate-/Public-Templates -mit lokalen Netzen ist in drei unabhängigen synthetischen Läufen bestanden: -zwei benannte Templates, gespeicherte Region, lokale Netze, keine Sandbox, -keine zusätzlichen Dienste und keine Rückfragen. Corporate verwendet den -vorhandenen `default`-Netzwerkbereich, auch ohne explizites Key-Override. -Die Quellenprüfung für Produktpläne, Adressen und IDs bleibt unverändert. -Die Modellabnahme ist synthetisch und verändert keine Kundenkonfiguration. -Die Korrekturen sind mit Nutzerfreigabe als `a031273` committed, gepusht und -über den erfolgreichen [Dev-Release 38710301311](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38710301311) -veröffentlicht. Öffentliche Hosted-Prüfungen und der Abgleich des ausgelieferten -UI-Bundles mit diesem Release sind bestanden; die Abnahme führt keine -Kunden-Cloud-Ressourcen aus. - -Auswahlfelder gibt es für Regionen, regionale Netzwerkkennungen, vorhandene -Netzwerkbereiche, Namespace-Projektkennungen sowie die durch den Accelerator -festgelegten Audit-Scope-, VPN-Routing-, Secret-Enforcement- und Firewall-Werte. -Nicht mehr passende importierte Werte bleiben sichtbar und werden nicht automatisch -ersetzt. Freie Bezeichnungen bleiben Textfelder. Regionale Produktangebote wie -Maschinentypen, Pläne und Versionen benötigen künftig API-basierte Kataloge; dafür -werden keine vermeintlich vollständigen statischen Listen vorgetäuscht. - -### Template-Übersicht - -Application-Templates erscheinen als auswählbare Übersichtskarten mit Namen, -stabiler Kennung, Art, Region, Zielordner und Netzzuordnung. Nur das ausgewählte -Template zeigt sein vollständiges Bearbeitungsformular. Neue Templates werden -direkt ausgewählt; nach Entfernen eines Templates bleibt ein vorhandenes Template -bearbeitbar. Die Strukturansicht gruppiert dieselben Templates nach Art und -Zielordner und öffnet beim Auswählen denselben Detailbereich. - -Die Netzwerkansicht zeigt Corporate-Templates nur unter dem referenzierten -Netzwerkbereich ihrer Region; ein fehlendes Key-Override bedeutet weiterhin -`default`. Public-Templates werden nicht als zentrale Netzwerk-Spokes dargestellt. -Fehlende SNA- oder Ordnerreferenzen bleiben ausdrücklich sichtbar. Templates -bleiben Entwürfe für spätere Bestellungen, keine bereits angelegten Projekte. -Auswählen und Bearbeiten speichern oder deployen nichts automatisch. - -Die Übersicht ist mit Nutzerfreigabe als Quelle `9c19327` über den erfolgreichen -[Dev-Release 38720037784](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38720037784) -veröffentlicht. Alle 296 Desktop-/Mobil-Browsertests bestanden, einschließlich -Auswahl, gemeinsamer Strukturvorschau, Hinzufügen, Entfernen und leerem Zustand. -Die ausgelieferten JavaScript- und CSS-Bundles wurden mit der exakt gebauten -Quelle abgeglichen. Bestehende Kundenkonfigurationen wurden nicht verändert. - -### Komponenten in der Strukturvorschau - -Die Strukturvorschau zeigt unter den Plattformprojekten auch deren konfigurierte -Komponenten, jeweils nur mit Name und Typ: Automatisierungs-Service-Account, -Secrets Manager, Object-Storage-Buckets, -Observability, Audit Logs und Telemetry Router, zugeordnete SNA, Netze, -DNS-Zonen, Firewalls einschließlich eines konfigurierten HA-Partners, VPN-Gateways, -Git-Service sowie Kubernetes-Cluster und ihre optionalen Dienste. -Netzwerkkomponenten werden nach Region und Netzwerkbereich dem richtigen Hub -zugeordnet. SNA erscheinen als logisch zugeordnete Netzwerkbereiche, nicht als -Aussage über deren tatsächlichen Resource-Manager-Container. -Deaktivierte Dienste und lediglich referenzierte bestehende DNS-Zonen erscheinen -nicht als neu bereitzustellende Komponenten. Das Audit-Archiv bleibt entsprechend -dem Accelerator auch ohne aktivierte Audit-Protokollierung sichtbar. -Die Vorschau verwendet native Standardwerte ausschließlich zum Anzeigen; sie -materialisiert diese nicht im Entwurf und liest keine bestehenden Cloud-Ressourcen. -Projekte mit Komponenten sind zunächst eingeklappt und lassen sich über den Pfeil, -die gesamte Überschriftszeile oder per Tastatur öffnen und schließen. -Struktur- und Netzwerkvorschau bleiben im Editor untereinander im normalen -Dokumentfluss, auch wenn alle Projekte geöffnet sind; kein zweiter Sticky-Bereich -überdeckt die darunterliegenden Templates. - -### Erstbereitstellungspläne - -Die generelle Sperre für `audit_logs`, `observability`, `connectivity` und `devops` -ist durch geprüfte Unterstützung ersetzt. Für Connectivity umfasst diese -Netzwerkbereiche, DNS, Firewall-/HA-Infrastruktur und VPN-Gateways. -Das Firewall-Image ist die bereits im Accelerator verwendete, versions- und -SHA-256-gebundene OPNsense-Datei; der Runner prüft die tatsächlichen Image-Dateien -und ihre Paketierung. Ein alter Runner ohne passendes Image bleibt ausdrücklich -gesperrt, statt einen vermeintlich ausführbaren Plan mit `/dev/null` zu erstellen. - -Das ist eine Plan-Freigabe, keine automatische Bereitstellung: Firewall-Policies, -Bootstrap, Appliance-Apply und VPN-Verbindungen mit vorab geteilten Schlüsseln -benötigen weiterhin ihre gesonderte Ausführungs- bzw. Secret-Binding-Unterstützung. -Audit-Ziele außerhalb des nachgewiesenen Organisationskontexts bleiben gesperrt. -Identitäts-/Owner-Nachweise, Mandantentrennung, Snapshot-Prüfung und explizite -Freigaben bleiben unverändert erforderlich. Die konkreten Grenzen sind im -[Runner-Vertrag](../runner/README.md) beschrieben. - -Vorbereitungen sind unveränderliche Nachweise einschließlich Accelerator-Revision. -Gespeicherte Konfigurationen sind davon getrennt und bleiben nach einem -Configurator-Release weiter bearbeitbar und als Quelle neuer Vorbereitungen -nutzbar. Ein reiner Configurator-Versionswechsel verlangt keine neue Vorbereitung, -solange deren Accelerator-Vertrag weiterhin zum installierten Runner passt. -Der behobene Fehler betraf auch frisch erstellte Vorbereitungen: Die Oberfläche -verwendete noch die Basisrevision, während der Runner bereits den -Plattformvertrags-Root erwartete. Dafür ist keine Neuerstellung der Konfiguration -und kein neuer State erforderlich. -Die Oberfläche zeigt bei einem Runner mit Plattformvertrags-Root eine ausdrücklich -zu bestätigende Vorbereitung für dessen aktuellen Stand an. Ohne Bestätigung -bleibt deren Erstellung gesperrt. Passt die Revision einer älteren Vorbereitung -nicht zum Runner, nennt der Plan-Fehler jetzt diesen Grund und fordert eine neue -Vorbereitung an, statt nur eine ungültige Konfiguration zu melden. Bestehende -Vorbereitungen, State-Bindungen und Plan-Nachweise werden dabei nicht umgeschrieben; -Plan und Apply behalten ihre eigenen Freigaben. - -Die Auswahl des aktuellen Accelerator-Stands ist auch für eine Erstbereitstellung -zulässig; sie setzt keine bereits bereitgestellte Plattform voraus. Ohne -State-Bindung oder mit einem leeren Standard-State (Version 0) kann eine neue -Vorbereitung entstehen. Das gilt auch nach einem fehlgeschlagenen ersten Plan. -Vorhandene Bindungen bleiben erhalten. Ein gesperrter State verhindert den -Wechsel weiterhin ausdrücklich; ein bereits gespeicherter Standard-State muss -vor dem Wechsel an sein S3-Backend übernommen werden. Ein ausgewähltes -S3-Backend ohne lesbaren State erlaubt weiterhin keinen Bootstrap. -Vorbereitungsfehler benennen State-Sperren, Backend-Konflikte, ungültige -Anfragen und abgelaufene Sicherheitsbestätigungen getrennt. Unbekannte -Serverfehler zeigen HTTP-Status und Fehlercode statt einer endlosen -Aufforderung zum Aktualisieren der Liste. - -Der DNS-Zonentyp bezeichnet die Rolle `primary` oder `secondary`, nicht eine -Sichtbarkeit `public` oder `private`. Die gemeinsame Konfigurationsprüfung -beanstandet ungültige Typen am konkreten Zonenfeld, auch in regionalen -Connectivity-Konfigurationen. Der generische Assistant-Vertrag erlaubt dieselben -DNS-Rollen im Modell-Ausgabeschema und in der serverseitigen Übernahmeprüfung. -Das gilt auch für vollständige Netzwerkobjekte sowie direkte Feldvorschläge, -jeweils als Ergänzung oder Ersatz und in beiden Netzwerkmodellen. -Alte Entwürfe bleiben unverändert ladbar und -exportierbar; sie werden nicht stillschweigend umgedeutet. Für eine selbst -verwaltete neue Zone kann der Benutzer den Typ ausdrücklich auf `primary` -korrigieren. Anschließend speichern und eine neue Vorbereitung für diese -Revision erstellen; alte Vorbereitungen behalten ihren ursprünglichen Snapshot. -Diese ergänzende DNS-Validierung ist noch nicht Teil der folgenden Dev-Abnahme. - -Bei Plattform-Plan und -Apply übermittelt der Runner während einer laufenden -OpenTofu-Phase alle zwei Sekunden einen bereinigten Ausgabestand. Die API speichert -ihn verschlüsselt und liefert ihn bereits während der Ausführung an die -Ausgabeansicht. Die Übertragungen erfolgen nacheinander; vor Ergebnisbestätigung -und Aufräumen werden ausstehende Übertragungen abgewartet. Unvollständige letzte -Zeilen werden erst nach ihrem Abschluss übertragen, damit keine nur teilweise -geschriebenen Zugangsdaten die Bereinigung umgehen. Nach dem Endstatus sind -weitere Änderungen des Protokolls gesperrt. „Ausgabe folgen“ steuert weiterhin -das automatische Scrollen, nicht die Übertragung. Der getrennte -Application-Runner behält seinen bisherigen einmaligen Abschlussbericht. -Diese Live-Ausgabekorrektur ist ebenfalls noch nicht veröffentlicht. - -Die zugehörige lokale Regression umfasst frische und zuvor fehlgeschlagene -Erstpläne mit Standard- und S3-Backend bis zum erfolgreichen Plan-Nachweis, -ohne Apply. Sie prüft unveränderte Konfigurationen, alte Vorbereitungen, -State-Bindungen und weiterhin gesperrte Zustände. Desktop- und Mobiltests -decken außerdem die ausdrückliche Auswahl des aktuellen Accelerator-Stands -ohne vorhandenes S3-Backend sowie konkrete und unbekannte Fehlermeldungen ab. -**Dev-Abnahme vom 2026-10-16:** Die Nachbesserung ist als unveränderliche Quelle -`6a5014e7821586a60699bcd52d148f0d56718b8b` über den erfolgreichen -[Dev-Release 38867967256](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38867967256) -veröffentlicht. Auch die zugehörige -[Validate-Configurator-Ausführung 38867967250](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38867967250) -ist vollständig erfolgreich. Die normale geschützte Dev-Freigabe erfolgte erst -nach erfolgreicher separater Validierung und erfolgreichem Release-Build. -Beide Workflows bestanden 718 Unit-Tests (63 im normalen Unit-Lauf übersprungen), -57 ausdrücklich aktivierte PostgreSQL-Plan-/Broker-Tests, 53 API-Datenbanktests, -304 Desktop-/Mobiltests und 13 native Template-Vertragsprüfungen. Die separate -Validierung bestand außerdem alle sechs Infrastruktur-Roots einschließlich -Formatierung, Validierung und Mock-Plänen. Der Release bestand die native -Runner-/Provider-/Image-/Archiv-Qualifikation und die tatsächliche -Cloud-Foundry-Bereitstellung einschließlich Migrationen, Service-Verbindungen, -separater Runner-Organisation, abgewiesenem Job-Ticket und öffentlichen Routen. - -Die ausgelieferten JavaScript-/CSS-Dateien entsprechen bytegenau dem freigegebenen -Build. Acht öffentliche Auth-/PKCE-/Callback-/CSRF-Prüfungen sind bestanden. -Echte anonyme Desktop-/Mobil-Browser zeigen jeweils zehn Name-/Typ-Komponenten, -funktionierendes Auf-/Zuklappen und überlappungsfreie Vorschauen ohne -Browserfehler oder Server-Mutationen. Die Anmeldung wurde nicht mit einem -echten Benutzer durchlaufen; ein Organisationsnachweis oder Kunden-Plan/Apply -wurde nicht ausgeführt. Gespeicherte Kundenkonfigurationen wurden nicht verändert. - -Der separate Validierungsworkflow prüft die reale Release-Konfiguration im -Application-Job nach dem API-Build. Der Infrastruktur-Job benötigt weiterhin -keine Anwendungs-Abhängigkeiten. Der vorherige STACKIT-Fehler entstand durch -den dort fehlenden kompilierten Validator, nicht durch eine GitHub-Pflicht. -Der native Standalone-Test erwartet für das inzwischen ausdrücklich als Public -markierte Beispiel einen erfolgreichen Vertrag. Separate Negativtests prüfen -weiterhin, dass fehlendes oder ausdrücklich wahres `corporate` ohne zentrale -Connectivity abgewiesen wird; der native Standardwert bleibt unverändert. -Validierung und Release führen beide `npm run test:common-contract` und -`npm run test:platform-database` aus. Der zweite Befehl aktiviert die isolierte -PostgreSQL-Broker-Suite ausdrücklich, die im normalen Unit-Lauf übersprungen -wird. Dadurch prüfen auch kommende Releases die Erstbereitstellung und die -nativen Template-Verträge, nicht nur bereits vorhandenen Plattform-State. -Die API-Datenbankintegration verwendet in beiden Workflows dieselben zwei -Worker und 30 Sekunden Test-Timeout. Das bisherige 5-Sekunden-Limit im -Validierungsworkflow brach den mehrstufigen Vertrags-/Identitätsnachweis ab, -bevor dessen Aufräum- und Wiederherstellungsschritte abgeschlossen waren. - -Die gemeinsame Release-Abnahme bestand 710 Unit-Tests (57 im Unit-Lauf -übersprungen), 51 PostgreSQL-Broker-Tests und 300 Desktop-/Mobil-Browsertests -sowie Typprüfung, Build und 19 gezielte Release-/Staging-/Runner-Evidence-Tests. -Native Vertrags-, Offline-Provider- und echte Image-/Archiv-Prüfungen -qualifizierten die Runner-Unterstützung zusätzlich. -Es gab keine Kunden-Cloud-Plans, Applies oder Destroys. - -Komponenten-Vorschau, Plan-Unterstützung und die eindeutige STACKIT-Bestätigung -sind mit Nutzerfreigabe als Quelle `0cee76f` über den erfolgreichen -[Dev-Release 38769119929](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38769119929) -veröffentlicht. Auf CF bestanden Image-SHA-Prüfung, native Runner-Checks, -Migrationen, Dienstverbindungen, Runner-Isolation und die kanonischen Routenprüfungen. -Die ausgelieferten JS-/CSS-Dateien stimmen bytegleich mit der gebauten Quelle -überein. Acht zusätzliche Live-Auth-/PKCE-Prüfungen und zwei echte anonyme -Desktop-/Mobil-Browserläufe bestanden; die Vorschau zeigte jeweils nur Name -und Typ, ohne Browserfehler, horizontalen Überlauf oder Server-Mutationen. - -Das große Image fehlt nur im Hosted-Upload und wird beim Staging SHA-geprüft -ohne zweite Dateikopie ins unveränderliche Droplet verschoben. Dieses ist der -dauerhafte CF-Cache; ein redundantes großes Buildpack-Cache-Archiv entfällt. -Es gibt keinen Download pro Nutzer oder Plan. Web/API verwenden 6 GiB Disk -für die größere Inspektionskopie und Staging-Komprimierung; das qualifizierte -4-GiB-Budget der isolierten Runner-Jobs und Tasks bleibt unverändert. -Paketidentität und bytegleiche Wiederherstellung beider Archive sind geprüft. -Details stehen unter -[CF-Staging und Cache](../deploy/cloud-foundry/README.md#image-staging-and-caching). -Ein persönlicher STACKIT-Login, Live-Owner-Nachweis und Kunden-Cloud-Plan wurden -dadurch nicht ausgeführt oder vorgetäuscht. - -Der separate -[Validate-Configurator-Lauf 38769119849](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38769119849) -bleibt an den bereits bekannten Standalone-Template-Vertrags- und -STACKIT/GitHub-Operator-Guard-Assertions rot. Der erfolgreiche Release-Lauf -und die Live-Abnahme sind davon getrennt; nicht sämtliche Repository-CI ist grün. - -## Kompatibilität und Grenzen - -- Bestehende v1/v2-Dokumente bleiben im bisherigen Editor nutzbar. **Zum gemeinsamen - Editor wechseln** ist eine ausdrückliche Migration; beim Wechsel werden die - bisherigen Engine-Werte erhalten. Bestehende Deployment-Vorbereitungen bleiben unverändert. -- Der bisherige Standalone-Editor kann auf der Standalone-Vorschauseite weiterhin - ausgewählt werden, einschließlich des bisherigen persönlichen Plan-Ablaufs. -- v3 wird im Fork und Browser-Arbeitsstand unterstützt. Vorlagen-Hashes, - Mandanten-/Kontotrennung, Schreibbasis, Konfliktprüfung und atomarer Export bleiben erhalten. -- v3-Deployment-Vorbereitungen sind **serverseitig gesperrt**. Runner-Anbindung und - geschützte zusätzliche Credential-Bindings werden separat abgenommen. -- Keine Secret-Felder in den Konfigurationsformularen. VPN-Schlüssel, Firewall- - Passwörter/API-Secrets und Kubeconfigs dürfen nicht in Freitextfelder eingefügt werden. -- Die wirkungslose Ordnerbeschreibung wird nicht als bearbeitbares Feature angeboten. -- Formular- und Typabdeckung sind keine Provider-Validierung. Plan/Refresh, - Dienstverfügbarkeit, Berechtigungen und jede Modul-Kombination benötigen weitere - Ausführungsabnahme. Grenzen #37/#65/#80 bleiben sichtbar. -- Kein Kunden-Apply ohne ausdrückliche neue Freigabe, kein Destroy. - -## Prüfung - -- [x] Fachbezeichnungen für sämtliche nicht-sensiblen Schemafelder geprüft. -- [x] Projektarten, Referenzen und Bereichsnormalisierung als Domain-Tests. -- [x] v3-JSON/tfvars atomar gespeichert; Deployment-Guard im Backend getestet. -- [x] Neuer Editor, Typwechsel, Navigation und Bereichsreferenzen im Browser getestet. -- [x] v3-Fork speichern, Export, Wiederaufnahme und gesperrte Vorbereitung getestet. -- [x] Legacy-Editor, GitHub-Anmeldung, Fork-Konflikte, Credentials und Plan-Ablauf regressionsgeprüft. -- [x] Release auf lzc-dev und Live-Verbindungstests abgenommen. - -Manuelle Prüfung nach Veröffentlichung: Hub-&-Spoke und Multi-Region öffnen, -Projektart/Bereich wechseln, Entwurf im eigenen Fork speichern, erneut öffnen und -Browser neu laden. Zusätzliche optionale Dienste unter Plattform/Betrieb prüfen. - -## Live-Abnahme - -Code `527bd9582f95d3cf845cfaf242f9022e1495fad8` veröffentlicht: - -- [Validate Configurator 36745965890](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36745965890): erfolgreich. -- [Configurator Release 36745965953](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36745965953): erfolgreich. -- 95 Anwendungstests und 20 Desktop-/Mobil-Browserprüfungen, einschließlich v3-Speicherung und Legacy-Kompatibilität. -- Native HCL-/OpenTofu-Vertragstests und Infrastrukturprüfung erfolgreich. -- CF-Netzwerk, PostgreSQL/Secrets-Manager-Verbindungen, isolierter Runner und öffentliche Routen erfolgreich geprüft. -- Direkter Live-Browsercheck: Multi-Region-Vorlage öffnen, neuen Editor starten, Projektliste/Netzwerkansicht auf Desktop und Mobilgerät prüfen; keine Seitenfehler oder horizontales Überlaufen. -- Öffentliche JavaScript-/CSS-Dateien per SHA-256 mit dem getesteten Build abgeglichen; `/healthz` liefert `ok`, Sitzung ohne Anmeldung `401`. - -[Live-Anwendung](https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud). -Keine Kunden-Konfiguration angewendet und keine Änderung nach `main` übernommen. - - -### Live-Nachbesserung: Plattformdienste und Voreinstellungen - -Code `10a6ec87f0d0fc9d32d4b9699bd8579fb651683c` veröffentlicht: - -- [Validate Configurator 36752620342](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36752620342): erfolgreich. -- [Configurator Release 36752620332](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36752620332): erfolgreich. -- 96 Anwendungstests, 22 Desktop-/Mobil-Browserfälle und 11 native OpenTofu-Variablentests erfolgreich. -- Live-Build entspricht dem lokal geprüften Bundle; Gesundheitsprüfung `ok`, anonyme Sitzung `401`, keine Browserfehler. -- Live geprüft: neue Standalone-Konfiguration ist Public; Region ist eine Auswahl; Plattformdienste und Kubernetes-Deaktivierung vorhanden. Desktop-/Mobilansicht ohne horizontales Überlaufen, mobile Plattformansicht visuell geprüft. -- Verbindungstests zu PostgreSQL/Secrets Manager und Runner-Trennung erfolgreich. - -Manuell: App neu laden, einen **neuen** Standalone-Entwurf öffnen, Organisations-ID -und eigene Verantwortlichen-E-Mail-Adressen setzen, unter Projekte Public prüfen -und speichern/exportieren. In einem vorhandenen betroffenen Entwurf Public einmal -ausdrücklich wählen. Unter Plattform Kubernetes konfigurieren/deaktivieren; unter -Netzwerk regionale Kennungen und Bereichsverweise auswählen. - - -## Nächster Bedienstand: Komponenten statt vollständiger Feldliste - -Die [verbindlichen Designprinzipien](editor-design-principles.md) steuern die weitere -Entwicklung. Die erste Umsetzung betrifft Plattform- und Kubernetes-Namespace-Dienste: -Inaktive Komponenten sind über **Komponente hinzufügen** zugänglich, aktive -Komponenten bleiben sichtbar. Das Öffnen und Schließen des Katalogs verändert den -Export nicht. Eine leere Clusterliste ist inaktiv; ein nicht-null gesetzter -Observability-Konfigurationsblock aktiviert dagegen den Dienst auch mit Defaults. - -Public-/Corporate-Projektkarten enthalten direkte Schalter für Secrets Manager und -Observability. Sandboxes besitzen diese Root-Optionen nicht. Netzwerkbezeichnungen -benennen Connectivity und SNA ausdrücklich; ein Hinweis erläutert automatisch -erzeugte Routing-Tabellen. Ein vereinheitlichter Regions-/SNA-Editor und der geführte -VPN-Ablauf sind noch offen und im Designplan separat aufgeführt. - -Dieser Abschnitt beschreibt den Arbeitsstand; die oben protokollierten Live-Abnahmen -beziehen sich auf ihre ausdrücklich genannten Commits. - - -## Regions-/SNA-Ansicht und VPN-Assistent (Arbeitsstand 2026-10-01) - -Netzwerk zeigt Connectivity als Regionskarten mit SNAs und optionalen DNS-, -Firewall- und VPN-Komponenten. Bestehendes `connectivity` bleibt im bisherigen -Engine-Format; neue leere Konfigurationen können explizite Regionen hinzufügen. -Für bestehende Standardregion-Konfigurationen gibt es keine automatische Migration -auf regionale Module. Beim Öffnen bleibt der Export unverändert. - -Der [VPN-Assistent](vpn-configuration-scope.md) bildet den Accelerator-Vertrag ab -und prüft grundlegende Pflichtangaben. Geschützte Schlüssel, Live-Kataloge und -Deployment-Ausführung fehlen weiterhin. Die neue [Self-Service-Architektur](platform-application-architecture.md) -ist geplant; Rollen und Berechtigungen wurden dadurch noch nicht geändert. - - -## Live-Abnahme 2026-10-01: Regionen, SNAs und VPN - -Code `78d8f7c6debeba29330fa2699d617da17c3ba3be` auf lzc-dev veröffentlicht. - -- [Release 36830339767](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36830339767): erfolgreich, einschließlich PostgreSQL-/Secrets-Manager-Verbindungstests und Runner-Prüfung. -- [Validate 36830339847](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36830339847): erfolgreich. -- Release umfasst 97 Anwendungstests und 24 Desktop-/Mobil-Browserfälle. -- Live-Bundle `/assets/index-BjLAVHUk.js` entspricht dem geprüften Editor-Release. -- Direkter Gast-Browsercheck: bestehende Vorlagen/Projektansicht, Komponenten hinzufügen, Region eu01 hinzufügen, STACKIT VPN öffnen, Verbindung mit zwei Tunnelfeldern konfigurieren. -- Gesundheit `ok`, anonyme Sitzung `401`, keine Browserfehler und kein horizontales Überlaufen auf Mobilgerät. Keine Kundenressourcen angelegt. - -Manuelle Abnahme: vorhandene Konfiguration öffnen und unverändert speichern; neue -Connectivity-Region/SNA konfigurieren; optionales VPN hinzufügen und dessen Umfang, -Pflichtangaben und Tunnel-Einstellungen prüfen. VPN-Ausführung bleibt gesperrt. - -Der anschließend entstandene separate Application-Root und sein Compiler sind -ein lokaler bzw. im Feature-Branch prüfbarer Prototyp, kein Bestandteil der -aktivierten Self-Service-Oberfläche. + +# Common editor + +[English](common-editor.md) | [Deutsch](common-editor.de.md) + +As of 2026-10-15. Publication on `lzc-dev` exclusively from the feature branch. + + +## Usage + +A valid app session and current STACKIT identity proof are +separate: the app session lasts eight hours, while +STACKIT proof can expire earlier. Name and **Sign out** still mean +you are signed in to the Configurator. If current proof is missing, +the header offers **Confirm STACKIT**, not another **Sign in with STACKIT**. +The dialog explains that confirmation is needed for protected +STACKIT actions. Proof expiry does not sign you out of the app; +it also does not extend any cloud permission. Without an app session, +**Sign in with STACKIT** remains the actual login. + +1. Open any template and choose **Create configuration**. +2. **Foundations → Folders → Network → Platform → Projects → Operations → Review**. +3. Expand settings only when needed. **Use Accelerator default** removes the + custom setting and uses the engine default, not the template value. Export still contains only explicit inputs; + displayed defaults are not materialized merely on opening. +4. Under **Projects**, add Public, Corporate or Sandbox. Public/Corporate + can be switched after confirmation. The target folder is shown. + Corporate needs a matching region and an existing area. + Sandboxes have their own Accelerator contract; switching to a + Landing Zone requires deliberate recreation and removal. +5. **Review** shows known configuration errors and separate execution limitations. + Then download tfvars or save JSON and tfvars together to a fork. + +Single areas from old Hub & Spoke templates can be converted to an area list +with **Manage multiple network areas** without changing the `default` reference. +Areas with project, DNS, firewall, VPN or cluster references cannot +be removed accidentally. Organization tree and network assignment +use the same data; one hub project is shown per network area. + +New Standalone drafts explicitly mark the example project as Public +(correction for #84). Lossless import and existing documents remain +unchanged; explicitly set the project kind to **Public** in an older affected draft. +Replace template placeholders with your own organization ID and owner email addresses +as before. + +**Platform** contains Git service, platform Kubernetes, central Observability +and audit logging. Kubernetes is disabled with an empty cluster list, +Git service with `null`. Removing configured services requires confirmation; +remaining namespace dependencies are reported during configuration validation. +Observability is a separate service. Audit logging creates a Telemetry +Router targeting STACKIT Logs and an S3 archive. The management archive bucket exists +even with audit logging disabled. + +In configuration chat, the change proposal shows structured values with +domain labels and their values, for example **Retention (days): 90** +for audit logging. This also applies to original values, nested objects, +lists and the conflict dialog. Empty lists (`[]`) and objects (`{}`) remain +distinguishable from **Unset**. The **Complete replacement** notice means +the entire proposed setting is adopted, not just individual +subfields. Selection, explicit acceptance and separate saving remain +unchanged; a preview changes neither configuration nor cloud resources. + + +### Assistant and Application templates (dev release of 2026-10-15) + +New template proposals must contain name, kind, region and settings +together. Existing templates remain partially editable. For platform drafts, +the Assistant receives existing network-area keys and regions, not +cloud resource identifiers. Template decisions reference an existing +user message; the server supplies its original text. +The resulting settings scope bounds the closed +model output schema: a network-only request offers no Observability, +Secrets Manager, namespace-service or parameter-policy settings. +Explicitly requested additional settings remain supported; the full +import, storage and runtime contract is not restricted. +The proposal comparison in the web UI reads templates from the same +ID-free projection indexed by stable keys as the backend, +not as supposed Terraform input. Acceptance updates the local +draft; only explicit saving persists templates. +Invalid generated template structures are reported as failed +Assistant proposals, not credentials in user text. +Saved chat and configuration remain unchanged on rejection. + +Using the referenced user request, the Assistant distinguishes +additions, corrections and a desired complete set of templates +or DNS zones. A definition “Corporate and Public, no Sandbox” defines a set, +not automatically an addition alongside initial examples. +An explicitly additional template or zone remains additive. +DNS corrections use existing stable zone keys; ambiguous +targets require clarification. +On set replacement, the proposal list shows every removed entry with +“Remove entry” and its own checkbox. Deselected entries and independent +intervening additions remain. Intervening changes +to a selected entry still require conflict confirmation. +Retained templates keep their IDs and unrequested settings. +Remaining proposals after partial acceptance are assembled from the current candidate. +Already accepted entries survive later +acceptance of remaining deletions, both in the local preview path +and direct revision-checked saving through the API. +None of these changes automatically saves or deletes customer configurations. +The improvements were committed and pushed as source `045eeafb9813e542f59062139d386b819a3792df` +and published through successful +[dev release 38782981970](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38782981970). +Approval followed normal protected dev gates. +Local regression consists of 718 passing unit tests (57 skipped), +51 isolated PostgreSQL Plan/broker tests, 53 PostgreSQL integration tests and +302 desktop/mobile browser tests. +Type checking, build and generated Assistant contracts are checked. This replaces +no fresh real-model or customer-cloud acceptance; no customer Plan +or Apply was started. + +The final release also passed 718 unit, 53 database and +302 browser tests in CI and native Runner/image/archive qualification. +Runner staging with image/engine checks, migrations, API/web deployment, +service connections, separate Runner organization and broker isolation, and +public routes are successful. After deployment, actually served +JavaScript/CSS files match the approved revision byte-for-byte. +Eight public auth/PKCE/callback/CSRF checks passed. Real anonymous +desktop/mobile browsers each show ten name/type components, working +keyboard/mouse expand/collapse and overlap-free previews with all +projects open, without browser errors or server mutations. +A real user login, organization proof and customer Plan were not +performed automatically. + +For that release, the separate +[Validate Configurator run 38782981811](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38782981811) +remained red on Standalone contract and STACKIT/GitHub operator-guard assertions. +This historical run is not counted as passing. The dev acceptance of +2026-10-16 documented below includes corrections and a fully green +new validation run. + +Real-model acceptance of the original request for Corporate/Public templates +with local networks passed in three independent synthetic runs: +two named templates, saved region, local networks, no Sandbox, +no extra services and no follow-up questions. Corporate uses the +existing `default` network area, even without an explicit key override. +Source verification for product plans, addresses and IDs remains unchanged. +Model acceptance is synthetic and changes no customer configuration. +With user approval, corrections were committed and pushed as `a031273` and +published through successful [dev release 38710301311](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38710301311). +Public hosted checks and comparison of the served +UI bundle with this release passed; acceptance executes no +customer cloud resources. + +Selection fields exist for regions, regional network identifiers, existing +network areas, namespace project identifiers and the Accelerator-defined +audit-scope, VPN-routing, secret-enforcement and firewall values. +Imported values that no longer match remain visible and are not automatically +replaced. Free-form labels remain text fields. Regional product offerings such as +machine types, plans and versions need API-based catalogues in future; +no supposedly complete static lists are presented. + + +### Template overview + +Application templates appear as selectable overview cards with name, +stable identifier, kind, region, target folder and network assignment. Only the selected +template shows its complete edit form. New templates are +selected immediately; after removing a template, an existing template remains +editable. The structure view groups the same templates by kind and +target folder and opens the same detail area on selection. + +The network view shows Corporate templates only under the referenced +network area of their region; a missing key override still means +`default`. Public templates are not shown as central network spokes. +Missing SNA or folder references remain explicit. Templates +remain drafts for later orders, not already created projects. +Selection and editing save or deploy nothing automatically. + +With user approval, the overview was published as source `9c19327` through successful +[dev release 38720037784](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38720037784). +All 296 desktop/mobile browser tests passed, including +selection, shared structure preview, adding, removing and empty state. +Served JavaScript and CSS bundles were compared with the exact built +source. Existing customer configurations were not changed. + + +### Components in the structure preview + +The structure preview also shows configured components under platform projects, +each with name and type only: automation service account, +Secrets Manager, Object Storage buckets, +Observability, Audit Logs and Telemetry Router, assigned SNA, networks, +DNS zones, firewalls including a configured HA partner, VPN gateways, +Git service, Kubernetes clusters and their optional services. +Network components are assigned to the correct hub by region and network area. +SNAs appear as logically assigned network areas, not as +a statement about their actual Resource Manager container. +Disabled services and merely referenced existing DNS zones do not appear +as components to be newly provisioned. The audit archive remains visible, +as in the Accelerator, even without enabled audit logging. +The preview uses native defaults only for display; it +does not materialize them in the draft or read existing cloud resources. +Projects with components are initially collapsed and can be opened and closed through the arrow, +the entire heading row or the keyboard. +Structure and network previews remain one below the other in normal +document flow in the editor, even with all projects open; no second sticky area +covers templates below. + + +### Initial deployment Plans + +The blanket block for `audit_logs`, `observability`, `connectivity` and `devops` +has been replaced by tested support. For Connectivity, this covers +network areas, DNS, firewall/HA infrastructure and VPN gateways. +The firewall image is the version- and SHA-256-bound OPNsense file +already used in the Accelerator; the Runner checks actual image files +and their packaging. An old Runner without a matching image remains explicitly +blocked rather than creating a supposedly executable Plan with `/dev/null`. + +This is Plan approval, not automatic provisioning: firewall policies, +bootstrap, appliance Apply and VPN connections with pre-shared keys +still need their separate execution or secret-binding support. +Audit targets outside the verified organization context remain blocked. +Identity/owner proofs, tenant separation, snapshot checks and explicit +approvals remain required unchanged. Specific limitations are described in the +[Runner contract](../runner/README.md). + +Preparations are immutable evidence including Accelerator revision. +Saved configurations are separate and remain editable after a +Configurator release and usable as sources for new preparations. +A Configurator-only version change requires no new preparation +as long as its Accelerator contract still matches the installed Runner. +The fixed defect also affected freshly created preparations: the interface +still used the base revision while the Runner already expected the +platform-contract root. No recreation of the configuration +or new state is needed for this. +For a Runner with the platform-contract root, the interface displays preparation +for its current revision requiring explicit confirmation. Without confirmation, +creation remains blocked. If an older preparation's revision +does not match the Runner, the Plan error now names this reason and requests a new +preparation instead of merely reporting invalid configuration. Existing +preparations, state bindings and Plan evidence are not rewritten; +Plan and Apply retain their own approvals. + +Selecting the current Accelerator revision is also allowed for an initial deployment; +it does not require an already provisioned platform. Without +a state binding or with an empty default state (version 0), a new +preparation can be created. This also applies after a failed first Plan. +Existing bindings remain. Locked state still explicitly prevents +switching; already saved default state must +be adopted into its S3 backend before switching. A selected +S3 backend without readable state still permits no bootstrap. + +Preparation errors distinguish state locks, backend conflicts, invalid +requests and expired security confirmations. Unknown +server errors show HTTP status and error code instead of an endless +request to refresh the list. + +The DNS zone type denotes the role `primary` or `secondary`, not +visibility `public` or `private`. Common configuration validation +reports invalid types at the specific zone field, including regional +Connectivity configurations. The generic Assistant contract allows the same +DNS roles in the model output schema and server-side acceptance check. +This also applies to complete network objects and direct field proposals, +as additions or replacements and in both network models. +Old drafts remain loadable and +exportable unchanged; they are not silently reinterpreted. For a self-managed +new zone, the user can explicitly correct the type to `primary`. +Then save and create a new preparation for this +revision; old preparations keep their original snapshot. +This supplementary DNS validation is not yet part of the following dev acceptance. + +During platform Plan and Apply, the Runner sends a sanitized output snapshot +every two seconds while an OpenTofu phase runs. The API stores +it encrypted and delivers it to the +output view during execution. Transfers occur sequentially; pending transfers +are awaited before result acknowledgment +and cleanup. Incomplete final lines are transferred only after completion +so partially written credentials cannot bypass sanitization. +After final status, further log changes are +blocked. “Follow output” still controls +automatic scrolling, not transmission. The separate +Application Runner retains its previous one-off completion report. +This live-output correction is also not yet published. + +The related local regression includes fresh and previously failed +initial Plans with default and S3 backends through successful Plan evidence, +without Apply. It checks unchanged configurations, old preparations, +state bindings and still-blocked states. Desktop and mobile tests +also cover explicit selection of the current Accelerator revision +without an existing S3 backend, and specific and unknown error messages. +**Dev acceptance of 2026-10-16:** the improvement was published as immutable source +`6a5014e7821586a60699bcd52d148f0d56718b8b` through successful +[dev release 38867967256](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38867967256). +The related +[Validate Configurator run 38867967250](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38867967250) +is also fully successful. Normal protected dev approval followed only +after successful separate validation and release build. +Both workflows passed 718 unit tests (63 skipped in normal unit execution), +57 explicitly enabled PostgreSQL Plan/broker tests, 53 API database tests, +304 desktop/mobile tests and 13 native template-contract checks. Separate +validation also passed all six infrastructure roots including +formatting, validation and mock Plans. The release passed native +Runner/provider/image/archive qualification and actual +Cloud Foundry deployment including migrations, service connections, +separate Runner organization, rejected job ticket and public routes. + +Served JavaScript/CSS files match the approved +build byte-for-byte. Eight public auth/PKCE/callback/CSRF checks passed. +Real anonymous desktop/mobile browsers each show ten name/type components, +working expand/collapse and overlap-free previews without +browser errors or server mutations. Login was not completed with a +real user; organization proof or customer Plan/Apply +was not executed. Saved customer configurations were not changed. + +The separate validation workflow checks the real release configuration in the +application job after the API build. The infrastructure job still needs +no application dependencies. The earlier STACKIT error came from +the missing compiled validator there, not a GitHub requirement. +The native Standalone test expects a successful contract for the example +now explicitly marked Public. Separate negative tests +still check that missing or explicitly true `corporate` without central +Connectivity is rejected; the native default remains unchanged. +Validation and release both run `npm run test:common-contract` and +`npm run test:platform-database`. The second command explicitly enables the isolated +PostgreSQL broker suite skipped in normal unit execution. +Future releases thereby also test initial deployment and +native template contracts, not only already existing platform state. +API database integration uses the same two +workers and 30-second test timeout in both workflows. The former 5-second limit in +the validation workflow interrupted multistage contract/identity proof +before its cleanup and restoration steps completed. + +Joint release acceptance passed 710 unit tests (57 skipped in unit execution), +51 PostgreSQL broker tests and 300 desktop/mobile browser tests, +type checking, build and 19 targeted release/staging/Runner-evidence tests. +Native contract, offline provider and real image/archive checks +additionally qualified Runner support. +There were no customer cloud Plans, Applies or Destroys. + +Component preview, Plan support and unambiguous STACKIT confirmation +were published with user approval as source `0cee76f` through successful +[dev release 38769119929](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38769119929). +On CF, image SHA checking, native Runner checks, +migrations, service connections, Runner isolation and canonical route checks passed. +Served JS/CSS files match the built source byte-for-byte. +Eight additional live auth/PKCE checks and two real anonymous +desktop/mobile browser runs passed; the preview showed only name +and type, without browser errors, horizontal overflow or server mutations. + +The large image is omitted only from the hosted upload and moved after SHA checking +into the immutable droplet during staging without a second file copy. This is the +durable CF cache; a redundant large buildpack cache archive is unnecessary. +There is no download per user or Plan. Web/API use 6 GiB disk +for the larger inspection copy and staging compression; the qualified +4-GiB budget of isolated Runner jobs and tasks remains unchanged. +Package identity and byte-identical restoration of both archives are checked. +Details: +[CF staging and cache](../deploy/cloud-foundry/README.md#image-staging-and-caching). +A personal STACKIT login, live owner proof and customer cloud Plan were +neither executed nor pretended by this. + +The separate +[Validate Configurator run 38769119849](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/38769119849) +remains red on already known Standalone template-contract and +STACKIT/GitHub operator-guard assertions. Successful release run +and live acceptance are separate; not all repository CI is green. + + +## Compatibility and limitations + +- Existing v1/v2 documents remain usable in the previous editor. **Switch to common + editor** is an explicit migration; existing engine values + are preserved when switching. Existing deployment preparations remain unchanged. +- The previous Standalone editor can still be selected on the Standalone preview page, + including the previous personal Plan flow. +- v3 is supported in forks and browser working state. Template hashes, + tenant/account isolation, write base, conflict checks and atomic export are preserved. +- v3 deployment preparations are **blocked server-side**. Runner integration and + protected additional credential bindings undergo separate acceptance. +- No secret fields in configuration forms. VPN keys, firewall + passwords/API secrets and kubeconfigs must not be pasted into free-text fields. +- The ineffective folder description is not offered as an editable feature. +- Form and type coverage are not provider validation. Plan/refresh, + service availability, permissions and every module combination need further + execution acceptance. Limitations #37/#65/#80 remain visible. +- No customer Apply without explicit new approval, no Destroy. + + +## Verification + +- [x] Domain labels for all nonsensitive schema fields checked. +- [x] Project kinds, references and area normalization as domain tests. +- [x] v3 JSON/tfvars saved atomically; deployment guard tested in the backend. +- [x] New editor, kind switching, navigation and area references tested in browser. +- [x] v3 fork saving, export, resumption and blocked preparation tested. +- [x] Legacy editor, GitHub login, fork conflicts, credentials and Plan flow regression-tested. +- [x] Release on lzc-dev and live connection tests accepted. + +Manual check after publication: open Hub & Spoke and Multi-Region, +switch project kind/area, save draft to own fork, reopen and +reload browser. Check additional optional services under Platform/Operations. + + +## Live acceptance + +Code `527bd9582f95d3cf845cfaf242f9022e1495fad8` published: + +- [Validate Configurator 36745965890](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36745965890): successful. +- [Configurator Release 36745965953](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36745965953): successful. +- 95 application tests and 20 desktop/mobile browser checks, including v3 storage and legacy compatibility. +- Native HCL/OpenTofu contract tests and infrastructure checks successful. +- CF network, PostgreSQL/Secrets Manager connections, isolated Runner and public routes checked successfully. +- Direct live browser check: open Multi-Region template, start new editor, check project list/network view on desktop and mobile; no page errors or horizontal overflow. +- Public JavaScript/CSS files compared by SHA-256 with the tested build; `/healthz` returns `ok`, session without login `401`. + +[Live application](https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud). +No customer configuration applied and no change merged to `main`. + + + +### Live improvement: platform services and defaults + +Code `10a6ec87f0d0fc9d32d4b9699bd8579fb651683c` published: + +- [Validate Configurator 36752620342](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36752620342): successful. +- [Configurator Release 36752620332](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36752620332): successful. +- 96 application tests, 22 desktop/mobile browser cases and 11 native OpenTofu variable tests successful. +- Live build matches locally checked bundle; health check `ok`, anonymous session `401`, no browser errors. +- Live checked: new Standalone configuration is Public; region is a selection; platform services and Kubernetes deactivation available. Desktop/mobile view without horizontal overflow, mobile platform view visually checked. +- Connection tests to PostgreSQL/Secrets Manager and Runner separation successful. + +Manual: reload app, open a **new** Standalone draft, set organization ID +and own owner email addresses, check Public under Projects +and save/export. In an existing affected draft, explicitly select Public +once. Configure/disable Kubernetes under Platform; +select regional identifiers and area references under Network. + + +## Next interaction state: components instead of a full field list + +The [binding design principles](editor-design-principles.md) guide further +development. Initial implementation covers platform and Kubernetes namespace services: +inactive components are accessible through **Add component**; active +components remain visible. Opening and closing the catalogue does not change +export. An empty cluster list is inactive; a non-null +Observability configuration block, by contrast, enables the service even with defaults. + +Public/Corporate project cards contain direct toggles for Secrets Manager and +Observability. Sandboxes do not have these root options. Network labels +explicitly name Connectivity and SNA; a notice explains automatically +created routing tables. A unified region/SNA editor and guided +VPN flow remain open and are listed separately in the design plan. + +This section describes working state; live acceptances recorded above +refer to their explicitly named commits. + + + +## Region/SNA view and VPN assistant (working state 2026-10-01) + +Network shows Connectivity as region cards with SNAs and optional DNS, +firewall and VPN components. Existing `connectivity` remains in its previous +engine format; new empty configurations can add explicit regions. +Existing default-region configurations are not automatically migrated +to regional modules. Export remains unchanged on opening. + +The [VPN assistant](vpn-configuration-scope.md) maps the Accelerator contract +and checks basic required inputs. Protected keys, live catalogues and +deployment execution remain missing. The new [self-service architecture](platform-application-architecture.md) +is planned; this has not yet changed roles or permissions. + + + +## Live acceptance 2026-10-01: regions, SNAs and VPN + +Code `78d8f7c6debeba29330fa2699d617da17c3ba3be` published on lzc-dev. + +- [Release 36830339767](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36830339767): successful, including PostgreSQL/Secrets Manager connection tests and Runner check. +- [Validate 36830339847](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36830339847): successful. +- Release includes 97 application tests and 24 desktop/mobile browser cases. +- Live bundle `/assets/index-BjLAVHUk.js` matches the checked editor release. +- Direct guest browser check: existing templates/project view, add components, add region eu01, open STACKIT VPN, configure connection with two tunnel fields. +- Health `ok`, anonymous session `401`, no browser errors or horizontal overflow on mobile. No customer resources created. + +Manual acceptance: open an existing configuration and save unchanged; configure new +Connectivity region/SNA; add optional VPN and check its scope, +required inputs and tunnel settings. VPN execution remains blocked. + +The subsequently created separate Application root and its compiler are +a prototype testable locally or on the feature branch, not part of +the activated self-service interface. diff --git a/landing-zone-configurator/docs/common-feature-model.de.md b/landing-zone-configurator/docs/common-feature-model.de.md new file mode 100644 index 0000000..ca6453b --- /dev/null +++ b/landing-zone-configurator/docs/common-feature-model.de.md @@ -0,0 +1,406 @@ + + +# Gemeinsames Funktionsmodell des Landing Zone Configurators + +[English](common-feature-model.md) | [Deutsch](common-feature-model.de.md) + +Stand: 2026-09-30. Architekturentscheidung nach Benutzerfeedback zur Projekt-/Ordnerauswahl. +**Die Templates sind Voreinstellungen desselben Accelerators. Sie definieren nicht den Funktionsumfang des Editors.** + +Aktueller Konzeptstand 2026-10-10: Die historische Bestandsaufnahme unten nennt +28 Eingaben. Der heutige Domain-Katalog enthaelt 29, einschliesslich +`platform_contract_namespace`. Die aktuelle feldgenaue KI-Abdeckung steht in der +[Assistenten-Matrix](assistant-feature-coverage.de.md). Deren Quellhashes und Tests +pruefen den aktuellen lokalen Katalog; sie bestaetigen keine neue Engine- oder +Cloud-Freigabe unter den historischen Pins dieser Bestandsaufnahme. + +Diese Entscheidung ersetzt den Ausbau des Standalone-Editors um einen isolierten +Corporate-/Einzelbereich-Sonderfall. Der gemeinsame Editor ist inzwischen auf lzc-dev veröffentlicht. Public-/Corporate- +Zuordnung und Netzwerkbereiche werden auf diesem Modell bearbeitet; die v3- +Deployment-Anbindung bleibt ein eigener, noch nicht freigegebener Schritt. + + + +## Verbindliche Quelle und Vollständigkeit + +1. Freigegebener Accelerator-Commit: `a256f6896d11134fdc351786f1be5eba4e56b2e2`. + Der aktuelle lokale `src`-Stand stimmt damit überein. +2. `src/variables.tf`: 28 Root-Eingaben einschließlich verschachtelter Typen, + optionaler Werte, tatsächlicher Defaults, sensibler Eingaben und Validierungen. +3. Alle Root-Dateien: insbesondere `main.tf`, `providers.tf`, + `_landing-zone-kubernetes.tf` und `_firewall-bootstrap.tf`. Diese bestimmen, + welche Funktionen kombiniert werden können und wann sie ausführbar sind. +4. Modulimplementierungen: tatsächliche Ressourcen, Benennung, Elternbeziehungen, + Rollen, Voraussetzungen und Nebenwirkungen. Ein Parameter eines Untermoduls, + den der Root-Aufruf nicht durchreicht, ist noch keine verfügbare UI-Option. +5. Alle acht Configs sind Referenzfälle; kommentierte Beispiele zählen nicht als + aktivierte oder getestete Funktionen. + +Das generierte [Eingabeinventar](accelerator-inputs.json) enthält alle 28 Eingaben +mit Typbaum, optionalen Defaults, Quellzeile und Validierungsblöcken. Sensible +Defaultwerte werden ausgelassen. Es ist eine technische Vollständigkeitsgrundlage, +kein automatisch gerendertes Terraform-Variablenformular. Fachliche Bezeichnungen, +Abhängigkeiten, Verfügbarkeit und UI-Komponenten kommen aus dem gemeinsamen Modell. + +Aktualisieren und prüfen: + +```sh +cd landing-zone-configurator/tools/hcl-adapter +go run . -variables-source ../../../src/variables.tf -output ../../docs/accelerator-inputs.json +go run . -variables-source ../../../src/variables.tf -output ../../docs/accelerator-inputs.json -check +``` + +Die Validierungspipeline prüft die Aktualität. Bei einer Accelerator-Aktualisierung +müssen zusätzlich die Modulverdrahtung, erlaubte Kombinationen und Compilerregeln +fachlich geprüft werden; ein aktuelles JSON-Inventar allein genügt nicht. + + + +## Referenzkonfigurationen + +| Referenz | Abdeckung | +| --- | --- | +| Standalone | Minimaler Einstieg, Public-Projekte und Sandboxes | +| Hub & Spoke | Ein Netzwerkbereich, Corporate und Public, Sandboxes | +| Hub & Spoke Firewall | Appliance im Einzelbereich | +| Multi-Area | Mehrere Bereiche und ausdrückliche Projektzuordnung | +| Multi-Region | eu01/eu02, regionale Bereiche und Plattform-Kubernetes | +| Prod/Nonprod Firewall | Mehrere Bereiche mit zugeordneten Firewalls | +| Finance & Research | Unterschiedliche DNS-/Netzwerkanforderungen je Bereich | +| Tenant Isolation | Drei getrennte Bereiche und zugeordnete Projekte | + +**Multi-Region und Prod/Nonprod Firewall bilden gemeinsam die strukturelle Referenz.** +Zusätzliche Testfälle decken Funktionen ab, die keine Vorlage aktiv nutzt, etwa VPN, +Audit-Logs, föderierte Identitäten, Firewall-HA und Namespace-Dienste. Ein künstliches +„alles eingeschaltet“-Template wäre keine ausreichende Referenz: einige Kombinationen +sind im Accelerator derzeit nicht implementiert. + + + +## Vollständige fachliche Funktionsbereiche + +| Bereich | Unterfunktionen | Root-Eingaben | +| --- | --- | --- | +| Grundlagen | Organisation, Verantwortliche, Anzeigename, Kürzel, Standardregion, Labels | `organization_id`, `owner_email`, `company_name`, `company_code`, `region`, `labels` | +| Organisation und Ordner | Gemeinsamer vorhandener Parent, Ordnerrollen und Anzeigenamen, zusätzliche Ordner, Owner/Auditor-Zuordnungen | `rm_folder_parent_id`, `rm_folders`, `organization_owners`, `organization_auditors` | +| Management | Verpflichtendes Management-Projekt, State-Bucket, optionale zentrale Observability, Audit-Routing/Archivierung, Aufbewahrung/Object Lock, föderierte Identitäten | `observability`, `audit_logs`, `federated_identity_providers`; Grundressourcen automatisch | +| Konnektivität | Regionen, 0..n Netzwerkbereiche je Region, Adresspools, Transfernetze, Präfixgrößen, Resolver, DNS-Zonen und Zuordnung | `connectivity`, `connectivity_regions` | +| Firewall-Infrastruktur | Appliance je unterstütztem Bereich, Größe/Zone/Netze/IPs, optional HA/CARP | Unterfelder von `connectivity`/`connectivity_regions` entsprechend Root-Verdrahtung | +| VPN | Gateway, Plan/Routingart, Verbindungen, zwei Tunnel, Gegenstellen, Routen/Subnetze, IKE/IPsec-Einstellungen | `connectivity.vpn`, `vpn_pre_shared_keys`; regionale Unterstützung separat prüfen | +| Firewall-Policy | Aliase, Routen, Regeln, ausgehendes NAT, Portweiterleitungen, Endpoint/TLS | `firewall_config` | +| Firewall-Zugänge und Ausführungsphase | Benutzer, Passwort/API-Zugang, Erstinitialisierung, Secret-Version | `firewall_admin_username`, `firewall_admin_password`, `firewall_api_credentials`, `firewall_bootstrap`, `firewall_api_secret_version` | +| DevOps | Git-Service, zugelassene Netze und automatisch abgeleitetes Plattformprojekt | `devops` | +| Plattform-Kubernetes | Regionale Cluster, Node-Pools, Netzwerk-/Bereichsbezug, DNS/Gateway, Observability, verschlüsselte Volumes/KMS, Bastion/SSH, Rollen | `platform_kubernetes` | +| Kubernetes-Zugang | Geschützter Clusterzugang für unterstützte Folgeschritte | `platform_kubernetes_kube_config_override` | +| Landing-Zone-Projekte | Public/Corporate, Region und Netzwerkbereich, stabile Kennung, Kürzel, Umgebung, Verantwortliche, Netzgröße, Rollen/Custom Roles, Secrets Manager und Observability | `landing_zones` | +| Sandbox-Projekte | Name, Verantwortliche und zusätzliche Owner | `sandboxes` | +| Namespace-Dienste | Namespace/DNS, Kubernetes-Zugriff, Secrets-Integration und Policy-Modi, Break-glass, Labels/Annotations, optionale Demo/Last/Metriken | `landing_zone_namespace_services` | + +Diese Tabelle ordnet jede Root-Eingabe zu. Unterfelder sind im Inventar enthalten; +die UI-Abdeckung wird zukünftig **pro Unterfunktion/Feld** geführt, nicht nur pro +Top-Level-Schalter. Demo- und Diagnosefunktionen erscheinen getrennt von den +üblichen Produktionsfunktionen. + + + +## Gemeinsames Dokument und Compiler + +Ein versioniertes, templateunabhängiges Dokument beschreibt die fachlichen Objekte: + +- Herkunft: ursprüngliche Vorlage und Quellhash, freigegebene Accelerator-Revision. +- Organisation, Ordnerrollen und Rechte. +- Regionen und Netzwerkbereiche mit stabilen IDs; Referenzen statt Positionsbezug. +- Plattformdienste und deren Bereichs-/Regionszuordnung. +- Eine gemeinsame Liste von Projekten mit expliziter Art, stabiler Identität, + Region, optionalem Netzwerkbereich und projektspezifischen Diensten. +- Sicherheits-/Betriebsfunktionen und Namespace-Angebote mit expliziten Bezügen. + +Passwörter, VPN-Schlüssel, API-Secrets und Kubeconfigs gehören **nicht** in das +Git-Dokument, den Browser-Arbeitsstand oder die Chat-Historie. Der Dokumentinhalt +benennt erforderliche Zugänge; persönliche Zuordnung und Secret-Referenzen liegen +serverseitig in Deployment-Profilen und Secrets Manager. + +Die gemeinsame Verarbeitung lautet: + +```text +Template / gespeicherte Config / Chat-Änderung + ↓ + Import + Versionsmigration + ↓ + gemeinsames fachliches Dokument + ↙ ↘ + Formular-UI Struktur-/Netzansicht + ↓ + gemeinsame fachliche Validierung + ↓ + versionierter deterministischer Compiler + ↓ + natives tfvars + Deployment-Anforderungen +``` + +Formular, Chatbot, Grafik und Export verwenden dasselbe Modell. Es gibt keine +separaten Featurelisten je Template. Template-Wechsel ist eine ausdrücklich +bestätigte neue Voreinstellung; er darf vorhandene Benutzeränderungen nicht +stillschweigend ersetzen. Für bestehende Konfigurationen ist die Herkunft kein +Feature-Limit. + + + +### Verbindlicher Accelerator-Vertrag (2026-10-10) + +Ergaenzende Wissensarchitektur: Kuratierte Markdown-Bausteine pro Thema/Service +mit festem Abschnittsvertrag, explizitem Manifest, Quellen-/Inhaltshashes und +generiertem Backend-Bundle. Die ersten SNA-/Credential-Bausteine sind auf +19 Themen fuer alle Accelerator-Bereiche und den Konfigurationslebenszyklus +erweitert. Jede der aktuell 29 Root-Eingaben braucht eine explizite Themen- +Zuordnung; der Frische-/Vollstaendigkeitsgate prueft diese. Themauswahl folgt +Feature-Gruppen plus Wissensabhaengigkeiten, nicht Aktivierungszwang; Credential- +Grundlagen und Lebenszyklus sind Pflicht. Vorlagenwerte sind keine Nutzerfreigabe +fuer Einrichtung optionaler Komponenten. Kein beliebiges Markdown-/Web-/Kundendaten-Ingest, +keine Vektordatenbank oder automatische Wissenspromotion. Der erforderliche +Frischecheck blockiert veraltete Artefakte. Markdown erklaert, Schema/Compiler +entscheiden. Architektur und Erweiterungsablauf: +[Service-Wissen](assistant-knowledge/README.de.md). + +Der Assistent uebersetzt freie Anforderungen ausschliesslich in dieses gemeinsame +Konfigurationsmodell und dessen bereits unterstuetzte Accelerator-Eingaben. +Er erzeugt weder freies Terraform noch editor-/chat-exklusive Ressourcen oder +Providerkonfiguration. Der native Export bleibt eine eigenstaendig mit der +passenden Accelerator-Version verwendbare Konfiguration. Aktuell ist das +Terraform-tfvars, nicht ein neu erfundenes YAML-Schema. Ein spaeteres YAML-Format +braucht einen expliziten, versionierten Import-/Compilervertrag zum selben +Accelerator; es darf keine zweite Fachlogik oder Configurator-Laufzeit voraussetzen. + +Feature-Einfuehrung erfolgt durchgaengig: Konzept/Architektur, Accelerator-/Modul- +Vertrag, Eingabeschema, gemeinsames Fachmodell, Validierung, Import/Export, +Editor/Assistent, Dokumentation und Tests. Nicht vorhandene Funktionen werden +als fehlend benannt und dort eingefuehrt, wo die Fachentscheidung liegt, nicht +als UI-Sonderoption oder frei erzeugter Terraform-Block. + +Credentials sind keine Modell-/Patchwerte. Konfiguration und sichere Credential- +Bindings sind getrennt: Der Export muss benoetigte externe Zugangsvoraussetzungen +und Referenzen nachvollziehbar machen; ausserhalb des Configurators werden sie +ueber die dokumentierten Accelerator-/Provider-Eingaben bzw. Umgebungsvariablen +bereitgestellt. Keine Configurator-exklusiven versteckten Secrets, keine +Klartext-Secrets in exportierter Konfiguration und keine Credential-Nachfragen +im Chat. Exportierbarkeit allein ist kein Ausfuehrungs- oder Berechtigungsnachweis. + +Der erste strukturierte Chat-Patch erweitert nur vorhandene SNA-Eingaben +(network_area/network_areas). Er fuehrt kein neues Accelerator-Feature ein. +Firewall, VPN, regionale Konnektivitaet und andere komplexe Komponenten brauchen +jeweils einen eigenen geprueften Vorschlags-/Binding-Vertrag. + +Import/Export unterscheiden **nicht gesetzt**, **explizit null/deaktiviert** und +**explizit konfiguriert**. Anzeige wirksamer Defaults darf nicht beim bloßen Öffnen +jede Option in den Export schreiben. Unbearbeitete Werte bleiben erhalten. +Zusätzlich ist eine bewusste Normalisierung der beiden unterstützten Connectivity- +Eingabeformen nötig; beide dürfen nicht parallel als aktive Quellen exportiert werden. + +Version 1/2 der bereits gespeicherten Standalone-Dokumente bekommt einen geprüften +Migrationsadapter. Keine stillen Änderungen an Schlüsseln, Ressourcenadressen, +Ordnerzuordnung oder alten tfvars-Hashes. Alte Deployment-Vorbereitungen bleiben +unveränderlich; Änderungen erzeugen neue Revisionen und Vorbereitungen. Die +unveröffentlichte Einzelbereich-Prototypversion 3 wird nicht als Format festgeschrieben. + + + +## Projektarten und grafische Darstellung + +Eine gemeinsame Projektliste ersetzt die implizite Trennung in obere Landing-Zone- +und untere Sandbox-Formulare. Beim Anlegen und Bearbeiten werden angezeigt: + +| Projektart | Zielordnerrolle | Weitere Auswahl | +| --- | --- | --- | +| Public | `landing_zones_public` | Region, Projektdienste; keine automatische öffentliche Freigabe | +| Corporate | `landing_zones_corporate` | Region **und vorhandener Netzwerkbereich dieser Region** | +| Sandbox | `sandboxes` | Sandbox-spezifische Angaben | +| Plattformprojekt | `platform` | Wird durch Management/Connectivity/DevOps/Kubernetes erzeugt; keine beliebige vierte Projektart | + +Die UI zeigt jeweils den tatsächlich konfigurierten Ordnernamen. Netzwerkbereiche +werden im Netzwerkbereich des Editors verwaltet und ausdrücklich referenziert; +ein Corporate-Projekt erzeugt keinen versteckten zweiten Netzwerk-Konfigurationspfad. +Das Entfernen eines Bereichs mit Referenzen wird blockiert. Projektartwechsel zeigen +Auswirkungen auf Daten, Zuordnung und Ressourcenidentitäten und benötigen eine +bewusste Bestätigung; bestehende Ressourcen werden dadurch noch nicht angewendet. + +Die Grafik verwendet zwei zusammenhängende Ansichten: + +1. **Organisation:** Organisation → optionaler Parent → Ordner → Projekte und + relevante Angebote, einschließlich automatisch erzeugter Plattformprojekte. +2. **Netzwerk:** Region → Netzwerkbereiche → zugeordnete Corporate-Projekte, + Firewall/VPN/DNS. Public und Sandbox bleiben entsprechend ungebunden. + +Ein Netzwerkbereich ist kein Resource-Manager-Ordner. Mehrere Bereiche in einer +Region können mehrere Hub-Projekte erzeugen; die bisherige pauschale Darstellung +„ein Hub je Region“ muss dafür ersetzt werden. + + + +## Editor-Struktur und Abhängigkeiten + +Fachbereiche: **Grundlagen → Organisation/Ordner → Netzwerk → Plattform → Projekte +→ Sicherheit/Betrieb → Prüfen**. Eine Funktionsübersicht zeigt aktivierte Angebote +und Ergänzungsmöglichkeiten. Optionale Details erscheinen bei Bedarf, bleiben aber +für jede Vorlage erreichbar. Es werden keine Terraform-Variablennamen als primäre +Bedienoberfläche verwendet. + +Jede Featuredefinition erhält stabile ID, fachliche Erklärung, Konfigurationsschema, +Default-/Aktivierungsregeln, Referenzen/Abhängigkeiten, zuständigen Editor, +Grafikprojektion, Compilerabbildung und Testfälle. Getrennte Zustände: + +- im Accelerator-Stand vorhanden; +- in der aktuellen Kombination zulässig; +- im Editor umgesetzt; +- für Plan/Apply in der aktuellen Ausführungsphase unterstützt. + +So wird eine vorhandene Engine-Funktion nicht fälschlich als bereits ausführbare +Configurator-Funktion angeboten. Das Ziel bleibt vollständige UI-Abdeckung; die +Migration wird nicht als „alle Features fertig“ ausgegeben. + + + +## Bereits festgestellte Kombinationsgrenzen + +Das [Grenzen- und Issue-Register](accelerator-limitations.de.md) ordnet die Befunde +den Accelerator-Issues zu und trennt Modellierbarkeit von Ausführbarkeit. + +- Private/SNA-Kubernetes-APIs sind vom aktuellen CF-Runner nicht nachweislich + erreichbar ([#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37)). + Kubernetes-/Helm-Phasen dürfen erst mit geeignetem Netzwerkpfad ausgeführt werden. + Serverseitige Capability-Prüfung ist Voraussetzung der Modellerweiterung; + die private Runner-Anbindung wird separat umgesetzt. + +- Corporate referenziert einen existierenden Bereich; mit regionaler Connectivity + muss die Projektregion im regionalen Modell vorhanden sein (`variables.tf`). +- Regionale Root-Instanzen unterstützen derzeit eu01/eu02. Beliebige weitere Regionen + brauchen zuerst Unterstützung im Accelerator. +- Bei `connectivity.firewalls` müssen die Schlüssel zu `network_areas` passen. +- `firewall_config` ist aktuell an die einzelne `connectivity.firewall` gebunden. + Die Policy-UI darf daraus keine beliebige Multi-Area-/Multi-Region-Unterstützung ableiten. +- Namespace-Dienste benötigen genau eine passende Instanz des nichtregionalen + `module.platform_kubernetes`; die Root-Dateien verwenden zudem `module.landing_zone`. + Die Multi-Region-Kubernetes-Vorlage beweist daher keine regionale Namespace-Unterstützung. +- Firewall-Bootstrap und spätere Kubernetes-/VPN-Schritte können mehrere + Ausführungsphasen und geschützte Laufzeitinformationen benötigen. Diese Phasen + werden vom Deployment-Modell gesteuert, nicht durch einen normalen Feature-Schalter. +- Kommentare sind keine verlässlichen Defaults: Bei Audit-Logs beschreibt der Text + Object Lock als aus, während der tatsächliche optionale Default `true` ist. + Die UI muss die wirksame Einstellung ausdrücklich zeigen. Ebenso wird eine + Ordnerbeschreibung zwar im Root-Typ akzeptiert, aber nicht bis zur Ressource durchgereicht. +- Einige Moduloptionen, etwa Governance-Custom-Roles oder bestimmte ACLs, werden vom + Root-Aufruf nicht durchgereicht. Änderungen am Accelerator wären ein eigener Umfang. + + + +## Umsetzung und Abnahme + + + +### A – Vollständige Grundlage + +- [x] Alle acht Templates und 28 Root-Eingaben aufnehmen. +- [x] Verschachtelte Typen, Defaults und Validierungen automatisch extrahieren. +- [x] Sensible Defaults aus dem Inventar ausschließen und testen. +- [x] Inventar-Aktualität in CI prüfen. +- [x] Funktionsbereiche, Projektmodell und wesentliche Kombinationsgrenzen festlegen. +- [x] Feld-/Unterfunktionsabdeckung als maschinenprüfbaren Feature-Katalog abbilden + (`featureFieldCatalogue`; Formularfelder, geschützte Bindings und wirkungslose Felder getrennt). + + + +### B – Gemeinsames Modell und kompatibler Compiler + +- [x] Versioniertes Dokument unabhängig von Standalone implementieren (v3-Domain-Vertrag). +- [x] Alle acht Templates verlustfrei importieren, Herkunft und stabile IDs erhalten. +- [x] Legacy-Adapter für gespeicherte Dokumentversion 1/2, bytegleicher Export. +- [x] Migration lokaler Arbeitsstände und Umschaltung der Speicher-/Produkt-API. +- [ ] Referenz-/Default-/Deaktivierungsregeln zentral validieren. +- [x] Export mit echtem HCL-Parser semantisch rückvergleichen; unveränderte + Legacy-Konfigurationen zusätzlich bytegleich prüfen. +- [ ] Pro Referenzkonfiguration native OpenTofu-Tests mit Mock-Providern, kein Apply. + + + +### C – Erster vollständiger Bedienablauf auf dem gemeinsamen Modell + +- [x] Ordner, Regionen und mehrere Netzwerkbereiche bearbeiten. +- [x] Gemeinsame Projektliste mit Public/Corporate/Sandbox und sichtbaren Zielordnern. +- [x] Region-/Bereichsauswahl für Corporate; Plattformprojekte aus Modulen ableiten. +- [x] Organisations- und Netzwerkansicht aus denselben Daten erzeugen. +- [x] Fork-Speicherung, Wiederaufnahme, Navigation und bestehende Vorbereitungen prüfen. + + + +### D – Vollständige Feature-Abdeckung + +- [ ] Management/Governance, DevOps und Observability/Audit/Federation. +- [ ] DNS, Firewall je unterstütztem Bereich, HA, VPN und unterstützte Policy-Funktionen. +- [ ] Kubernetes/Node-Pools, KMS/Volumes, Bastion, Namespace-Dienste und Zugriff. +- [ ] Secret-Bindings und Ausführungsphasen je Funktion abnehmen. +- [ ] Chat-Werkzeuge auf denselben Katalog und dieselbe Validierung aufsetzen. +- [ ] Abdeckungsmatrix: kein unterstütztes Unterfeld ohne UI, Import/Export und Tests. + + + +### Release-Grenzen + +Nur Feature-Branch. Der bisherige Stand bleibt live, bis das jeweilige Inkrement +vollständig getestet ist. Kein Kunden-Apply ohne neue ausdrückliche Freigabe; kein +Destroy. Ein komplexes Template darf nicht automatisch einen Kunden-Plan oder +Ressourcenaufbau starten. Configurator-Infrastrukturfreigabe bleibt davon getrennt. + + + +## Implementierungsstand gemeinsamer Kern, 2026-09-30 + +[Domain-Vertrag und Prüfungen](../app/packages/domain/README.de.md) sind implementiert. +Typen und explizite Werte aller Root-Eingaben werden abgedeckt; sensible Eingaben +sind ausschließlich als separate Deployment-Bindings vorgesehen. Referenzprüfungen +für Projekte/Bereiche/DNS und die bekannten Ausführungsgrenzen sind als gemeinsame +Funktionen vorhanden. Das ist noch keine vollständige fachliche Provider-Validierung. + +Alle acht Vorlagen werden mit dem nativen HCL-Parser rückverglichen. Zehn direkte +OpenTofu-Tests prüfen den Root-Variablenvertrag inklusive Object-Lock-Defaults. +Vollständige Modulpläne mit Mock-Providern bleiben offen. Standalone enthält den +bestätigten Fehler [#84](https://github.com/stackitcloud/stackit-landing-zone/issues/84); +der unveränderte Import weist die fehlende Public-Markierung aus. Die bestehende +v1/v2-Erzeugung und bereits gespeicherte Entwürfe bleiben bytegleich. + +Der neue Kern ist noch nicht an den produktiven Editor, Fork-Speicher oder Runner +angeschlossen. Damit werden weder neue Konfigurationsarten still für Deployments +freigegeben noch bisherige Vorbereitungen migriert. Nächstes Inkrement ist der +gemeinsame Netzwerk-/Projekteditor mit kontrollierter Speicher- und API-Migration. + + + +### Abnahme des gemeinsamen Kerns + +Code `e6106b9`, [Validate Configurator 36737858294](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36737858294), +Versuch 2 erfolgreich: Anwendung (89 Unit-Tests), Datenbankintegration, Browsertests, +HCL-Roundtrips, zehn native Variablenvertragstests und alle sechs Infrastruktur-Prüfungen. +Der erste Versuch scheiterte ausschließlich beim OpenTofu-Download eines +Infrastrukturjobs mit HTTP 500 von GitHub; Wiederholung erfolgreich. + +Kein Release dieses internen Kerns, keine Kunden-Pläne oder Applies ausgeführt. +Die veröffentlichte Oberfläche bleibt bis zum getesteten Editor-Inkrement unverändert. + + + +## Nachgezogenes Editor-Inkrement + +[Gemeinsamer Editor](common-editor.de.md): sieben Bereiche, fachlich beschriftete +Formulare für alle nicht-sensiblen Root-Eingaben, gemeinsame Projektauswahl, +Bereichszuordnung, v3-Fork-Speicherung und Browser-Wiederaufnahme. Bestehende +v1/v2-Konfigurationen bleiben kompatibel; ein Wechsel zum neuen Editor ist explizit. + +Formularabdeckung bedeutet noch keine vollständige Deployment-Abnahme jedes +Untermoduls. Geschützte Zusatz-Bindings und v3-Runner-Anbindung bleiben offen; +der Backend-Guard verhindert entsprechende Deployment-Vorbereitungen. + + + +### Abnahme des Editor-Releases + +Code `527bd95` ist auf lzc-dev veröffentlicht. Release und vollständige Validierung +erfolgreich; 95 Anwendungstests und 20 Browserprüfungen bestanden. Live-Assets und +CF-Verbindungstests geprüft. [Belege und Prüfliste](common-editor.de.md#live-abnahme). diff --git a/landing-zone-configurator/docs/common-feature-model.md b/landing-zone-configurator/docs/common-feature-model.md index 57374b4..1ff1772 100644 --- a/landing-zone-configurator/docs/common-feature-model.md +++ b/landing-zone-configurator/docs/common-feature-model.md @@ -1,42 +1,46 @@ -# Gemeinsames Funktionsmodell des Landing Zone Configurators - -Stand: 2026-09-30. Architekturentscheidung nach Benutzerfeedback zur Projekt-/Ordnerauswahl. -**Die Templates sind Voreinstellungen desselben Accelerators. Sie definieren nicht den Funktionsumfang des Editors.** - -Aktueller Konzeptstand 2026-10-10: Die historische Bestandsaufnahme unten nennt -28 Eingaben. Der heutige Domain-Katalog enthaelt 29, einschliesslich -`platform_contract_namespace`. Die aktuelle feldgenaue KI-Abdeckung steht in der -[Assistenten-Matrix](assistant-feature-coverage.md). Deren Quellhashes und Tests -pruefen den aktuellen lokalen Katalog; sie bestaetigen keine neue Engine- oder -Cloud-Freigabe unter den historischen Pins dieser Bestandsaufnahme. - -Diese Entscheidung ersetzt den Ausbau des Standalone-Editors um einen isolierten -Corporate-/Einzelbereich-Sonderfall. Der gemeinsame Editor ist inzwischen auf lzc-dev veröffentlicht. Public-/Corporate- -Zuordnung und Netzwerkbereiche werden auf diesem Modell bearbeitet; die v3- -Deployment-Anbindung bleibt ein eigener, noch nicht freigegebener Schritt. - -## Verbindliche Quelle und Vollständigkeit - -1. Freigegebener Accelerator-Commit: `a256f6896d11134fdc351786f1be5eba4e56b2e2`. - Der aktuelle lokale `src`-Stand stimmt damit überein. -2. `src/variables.tf`: 28 Root-Eingaben einschließlich verschachtelter Typen, - optionaler Werte, tatsächlicher Defaults, sensibler Eingaben und Validierungen. -3. Alle Root-Dateien: insbesondere `main.tf`, `providers.tf`, - `_landing-zone-kubernetes.tf` und `_firewall-bootstrap.tf`. Diese bestimmen, - welche Funktionen kombiniert werden können und wann sie ausführbar sind. -4. Modulimplementierungen: tatsächliche Ressourcen, Benennung, Elternbeziehungen, - Rollen, Voraussetzungen und Nebenwirkungen. Ein Parameter eines Untermoduls, - den der Root-Aufruf nicht durchreicht, ist noch keine verfügbare UI-Option. -5. Alle acht Configs sind Referenzfälle; kommentierte Beispiele zählen nicht als - aktivierte oder getestete Funktionen. - -Das generierte [Eingabeinventar](accelerator-inputs.json) enthält alle 28 Eingaben -mit Typbaum, optionalen Defaults, Quellzeile und Validierungsblöcken. Sensible -Defaultwerte werden ausgelassen. Es ist eine technische Vollständigkeitsgrundlage, -kein automatisch gerendertes Terraform-Variablenformular. Fachliche Bezeichnungen, -Abhängigkeiten, Verfügbarkeit und UI-Komponenten kommen aus dem gemeinsamen Modell. - -Aktualisieren und prüfen: + +# Common feature model of the Landing Zone Configurator + +[English](common-feature-model.md) | [Deutsch](common-feature-model.de.md) + +As of 2026-09-30. Architecture decision after user feedback on project/folder selection. +**Templates are presets of the same Accelerator. They do not define the editor's feature scope.** + +Current concept status 2026-10-10: the historical inventory below lists +28 inputs. Today's domain catalogue contains 29, including +`platform_contract_namespace`. Current field-level AI coverage is in the +[Assistant matrix](assistant-feature-coverage.md). Its source hashes and tests +check the current local catalogue; they confirm no new engine or +cloud approval under the historical pins of this inventory. + +This decision replaces extending the Standalone editor with an isolated +Corporate/single-area special case. The common editor has now been published on lzc-dev. Public/Corporate +assignment and network areas are edited on this model; v3 +deployment integration remains a separate, not-yet-approved step. + + +## Authoritative source and completeness + +1. Approved Accelerator commit: `a256f6896d11134fdc351786f1be5eba4e56b2e2`. + The current local `src` revision matches it. +2. `src/variables.tf`: 28 root inputs including nested types, + optional values, actual defaults, sensitive inputs and validations. +3. All root files: especially `main.tf`, `providers.tf`, + `_landing-zone-kubernetes.tf` and `_firewall-bootstrap.tf`. These determine + which features can be combined and when they are executable. +4. Module implementations: actual resources, naming, parent relationships, + roles, prerequisites and side effects. A child-module parameter + not passed through by the root call is not yet an available UI option. +5. All eight configs are reference cases; commented examples do not count as + enabled or tested features. + +The generated [input inventory](accelerator-inputs.json) contains all 28 inputs +with type tree, optional defaults, source line and validation blocks. Sensitive +default values are omitted. It is a technical completeness foundation, +not an automatically rendered Terraform variable form. Domain labels, +dependencies, availability and UI components come from the common model. + +Update and check: ```sh cd landing-zone-configurator/tools/hcl-adapter @@ -44,71 +48,74 @@ go run . -variables-source ../../../src/variables.tf -output ../../docs/accelera go run . -variables-source ../../../src/variables.tf -output ../../docs/accelerator-inputs.json -check ``` -Die Validierungspipeline prüft die Aktualität. Bei einer Accelerator-Aktualisierung -müssen zusätzlich die Modulverdrahtung, erlaubte Kombinationen und Compilerregeln -fachlich geprüft werden; ein aktuelles JSON-Inventar allein genügt nicht. +The validation pipeline checks freshness. An Accelerator update +also requires domain review of module wiring, allowed combinations and compiler rules; +a current JSON inventory alone is insufficient. -## Referenzkonfigurationen + +## Reference configurations -| Referenz | Abdeckung | +| Reference | Coverage | | --- | --- | -| Standalone | Minimaler Einstieg, Public-Projekte und Sandboxes | -| Hub & Spoke | Ein Netzwerkbereich, Corporate und Public, Sandboxes | -| Hub & Spoke Firewall | Appliance im Einzelbereich | -| Multi-Area | Mehrere Bereiche und ausdrückliche Projektzuordnung | -| Multi-Region | eu01/eu02, regionale Bereiche und Plattform-Kubernetes | -| Prod/Nonprod Firewall | Mehrere Bereiche mit zugeordneten Firewalls | -| Finance & Research | Unterschiedliche DNS-/Netzwerkanforderungen je Bereich | -| Tenant Isolation | Drei getrennte Bereiche und zugeordnete Projekte | - -**Multi-Region und Prod/Nonprod Firewall bilden gemeinsam die strukturelle Referenz.** -Zusätzliche Testfälle decken Funktionen ab, die keine Vorlage aktiv nutzt, etwa VPN, -Audit-Logs, föderierte Identitäten, Firewall-HA und Namespace-Dienste. Ein künstliches -„alles eingeschaltet“-Template wäre keine ausreichende Referenz: einige Kombinationen -sind im Accelerator derzeit nicht implementiert. - -## Vollständige fachliche Funktionsbereiche - -| Bereich | Unterfunktionen | Root-Eingaben | +| Standalone | Minimal entry, Public projects and sandboxes | +| Hub & Spoke | One network area, Corporate and Public, sandboxes | +| Hub & Spoke Firewall | Appliance in a single area | +| Multi-Area | Multiple areas and explicit project assignment | +| Multi-Region | eu01/eu02, regional areas and platform Kubernetes | +| Prod/Nonprod Firewall | Multiple areas with assigned firewalls | +| Finance & Research | Different DNS/network requirements per area | +| Tenant Isolation | Three separate areas and assigned projects | + +**Multi-Region and Prod/Nonprod Firewall together form the structural reference.** +Additional tests cover features no template actively uses, such as VPN, +audit logs, federated identities, firewall HA and namespace services. An artificial +“everything enabled” template would not be sufficient: some combinations +are not currently implemented in the Accelerator. + + +## Complete domain feature areas + +| Area | Subfeatures | Root inputs | | --- | --- | --- | -| Grundlagen | Organisation, Verantwortliche, Anzeigename, Kürzel, Standardregion, Labels | `organization_id`, `owner_email`, `company_name`, `company_code`, `region`, `labels` | -| Organisation und Ordner | Gemeinsamer vorhandener Parent, Ordnerrollen und Anzeigenamen, zusätzliche Ordner, Owner/Auditor-Zuordnungen | `rm_folder_parent_id`, `rm_folders`, `organization_owners`, `organization_auditors` | -| Management | Verpflichtendes Management-Projekt, State-Bucket, optionale zentrale Observability, Audit-Routing/Archivierung, Aufbewahrung/Object Lock, föderierte Identitäten | `observability`, `audit_logs`, `federated_identity_providers`; Grundressourcen automatisch | -| Konnektivität | Regionen, 0..n Netzwerkbereiche je Region, Adresspools, Transfernetze, Präfixgrößen, Resolver, DNS-Zonen und Zuordnung | `connectivity`, `connectivity_regions` | -| Firewall-Infrastruktur | Appliance je unterstütztem Bereich, Größe/Zone/Netze/IPs, optional HA/CARP | Unterfelder von `connectivity`/`connectivity_regions` entsprechend Root-Verdrahtung | -| VPN | Gateway, Plan/Routingart, Verbindungen, zwei Tunnel, Gegenstellen, Routen/Subnetze, IKE/IPsec-Einstellungen | `connectivity.vpn`, `vpn_pre_shared_keys`; regionale Unterstützung separat prüfen | -| Firewall-Policy | Aliase, Routen, Regeln, ausgehendes NAT, Portweiterleitungen, Endpoint/TLS | `firewall_config` | -| Firewall-Zugänge und Ausführungsphase | Benutzer, Passwort/API-Zugang, Erstinitialisierung, Secret-Version | `firewall_admin_username`, `firewall_admin_password`, `firewall_api_credentials`, `firewall_bootstrap`, `firewall_api_secret_version` | -| DevOps | Git-Service, zugelassene Netze und automatisch abgeleitetes Plattformprojekt | `devops` | -| Plattform-Kubernetes | Regionale Cluster, Node-Pools, Netzwerk-/Bereichsbezug, DNS/Gateway, Observability, verschlüsselte Volumes/KMS, Bastion/SSH, Rollen | `platform_kubernetes` | -| Kubernetes-Zugang | Geschützter Clusterzugang für unterstützte Folgeschritte | `platform_kubernetes_kube_config_override` | -| Landing-Zone-Projekte | Public/Corporate, Region und Netzwerkbereich, stabile Kennung, Kürzel, Umgebung, Verantwortliche, Netzgröße, Rollen/Custom Roles, Secrets Manager und Observability | `landing_zones` | -| Sandbox-Projekte | Name, Verantwortliche und zusätzliche Owner | `sandboxes` | -| Namespace-Dienste | Namespace/DNS, Kubernetes-Zugriff, Secrets-Integration und Policy-Modi, Break-glass, Labels/Annotations, optionale Demo/Last/Metriken | `landing_zone_namespace_services` | - -Diese Tabelle ordnet jede Root-Eingabe zu. Unterfelder sind im Inventar enthalten; -die UI-Abdeckung wird zukünftig **pro Unterfunktion/Feld** geführt, nicht nur pro -Top-Level-Schalter. Demo- und Diagnosefunktionen erscheinen getrennt von den -üblichen Produktionsfunktionen. - -## Gemeinsames Dokument und Compiler - -Ein versioniertes, templateunabhängiges Dokument beschreibt die fachlichen Objekte: - -- Herkunft: ursprüngliche Vorlage und Quellhash, freigegebene Accelerator-Revision. -- Organisation, Ordnerrollen und Rechte. -- Regionen und Netzwerkbereiche mit stabilen IDs; Referenzen statt Positionsbezug. -- Plattformdienste und deren Bereichs-/Regionszuordnung. -- Eine gemeinsame Liste von Projekten mit expliziter Art, stabiler Identität, - Region, optionalem Netzwerkbereich und projektspezifischen Diensten. -- Sicherheits-/Betriebsfunktionen und Namespace-Angebote mit expliziten Bezügen. - -Passwörter, VPN-Schlüssel, API-Secrets und Kubeconfigs gehören **nicht** in das -Git-Dokument, den Browser-Arbeitsstand oder die Chat-Historie. Der Dokumentinhalt -benennt erforderliche Zugänge; persönliche Zuordnung und Secret-Referenzen liegen -serverseitig in Deployment-Profilen und Secrets Manager. - -Die gemeinsame Verarbeitung lautet: +| Foundations | Organization, owners, display name, code, default region, labels | `organization_id`, `owner_email`, `company_name`, `company_code`, `region`, `labels` | +| Organization and folders | Shared existing parent, folder roles and display names, additional folders, owner/auditor assignments | `rm_folder_parent_id`, `rm_folders`, `organization_owners`, `organization_auditors` | +| Management | Mandatory management project, state bucket, optional central Observability, audit routing/archiving, retention/Object Lock, federated identities | `observability`, `audit_logs`, `federated_identity_providers`; base resources automatic | +| Connectivity | Regions, 0..n network areas per region, address pools, transfer networks, prefix sizes, resolvers, DNS zones and assignment | `connectivity`, `connectivity_regions` | +| Firewall infrastructure | Appliance per supported area, size/zone/networks/IPs, optional HA/CARP | Subfields of `connectivity`/`connectivity_regions` according to root wiring | +| VPN | Gateway, plan/routing type, connections, two tunnels, peers, routes/subnets, IKE/IPsec settings | `connectivity.vpn`, `vpn_pre_shared_keys`; check regional support separately | +| Firewall policy | Aliases, routes, rules, outbound NAT, port forwarding, endpoint/TLS | `firewall_config` | +| Firewall credentials and execution phase | User, password/API access, initialization, secret version | `firewall_admin_username`, `firewall_admin_password`, `firewall_api_credentials`, `firewall_bootstrap`, `firewall_api_secret_version` | +| DevOps | Git service, allowed networks and automatically derived platform project | `devops` | +| Platform Kubernetes | Regional clusters, node pools, network/area reference, DNS/gateway, Observability, encrypted volumes/KMS, bastion/SSH, roles | `platform_kubernetes` | +| Kubernetes access | Protected cluster access for supported follow-up steps | `platform_kubernetes_kube_config_override` | +| Landing Zone projects | Public/Corporate, region and network area, stable identifier, code, environment, owners, network size, roles/custom roles, Secrets Manager and Observability | `landing_zones` | +| Sandbox projects | Name, owners and additional owners | `sandboxes` | +| Namespace services | Namespace/DNS, Kubernetes access, secrets integration and policy modes, break-glass, labels/annotations, optional demo/load/metrics | `landing_zone_namespace_services` | + +This table maps every root input. Subfields are included in the inventory; +UI coverage will be tracked **per subfeature/field**, not only per +top-level toggle. Demo and diagnostic features appear separately from +ordinary production features. + + +## Common document and compiler + +A versioned, template-independent document describes the domain objects: + +- Provenance: original template and source hash, approved Accelerator revision. +- Organization, folder roles and permissions. +- Regions and network areas with stable IDs; references instead of positions. +- Platform services and their area/region assignment. +- One common project list with explicit kind, stable identity, + region, optional network area and project-specific services. +- Security/operations features and namespace offerings with explicit references. + +Passwords, VPN keys, API secrets and kubeconfigs do **not** belong in the +Git document, browser working state or chat history. Document content +names required credentials; personal assignment and secret references reside +server-side in deployment profiles and Secrets Manager. + +The common processing flow is: ```text Template / gespeicherte Config / Chat-Änderung @@ -126,241 +133,254 @@ Template / gespeicherte Config / Chat-Änderung natives tfvars + Deployment-Anforderungen ``` -Formular, Chatbot, Grafik und Export verwenden dasselbe Modell. Es gibt keine -separaten Featurelisten je Template. Template-Wechsel ist eine ausdrücklich -bestätigte neue Voreinstellung; er darf vorhandene Benutzeränderungen nicht -stillschweigend ersetzen. Für bestehende Konfigurationen ist die Herkunft kein -Feature-Limit. - -### Verbindlicher Accelerator-Vertrag (2026-10-10) - -Ergaenzende Wissensarchitektur: Kuratierte Markdown-Bausteine pro Thema/Service -mit festem Abschnittsvertrag, explizitem Manifest, Quellen-/Inhaltshashes und -generiertem Backend-Bundle. Die ersten SNA-/Credential-Bausteine sind auf -19 Themen fuer alle Accelerator-Bereiche und den Konfigurationslebenszyklus -erweitert. Jede der aktuell 29 Root-Eingaben braucht eine explizite Themen- -Zuordnung; der Frische-/Vollstaendigkeitsgate prueft diese. Themauswahl folgt -Feature-Gruppen plus Wissensabhaengigkeiten, nicht Aktivierungszwang; Credential- -Grundlagen und Lebenszyklus sind Pflicht. Vorlagenwerte sind keine Nutzerfreigabe -fuer Einrichtung optionaler Komponenten. Kein beliebiges Markdown-/Web-/Kundendaten-Ingest, -keine Vektordatenbank oder automatische Wissenspromotion. Der erforderliche -Frischecheck blockiert veraltete Artefakte. Markdown erklaert, Schema/Compiler -entscheiden. Architektur und Erweiterungsablauf: -[Service-Wissen](assistant-knowledge/README.md). - -Der Assistent uebersetzt freie Anforderungen ausschliesslich in dieses gemeinsame -Konfigurationsmodell und dessen bereits unterstuetzte Accelerator-Eingaben. -Er erzeugt weder freies Terraform noch editor-/chat-exklusive Ressourcen oder -Providerkonfiguration. Der native Export bleibt eine eigenstaendig mit der -passenden Accelerator-Version verwendbare Konfiguration. Aktuell ist das -Terraform-tfvars, nicht ein neu erfundenes YAML-Schema. Ein spaeteres YAML-Format -braucht einen expliziten, versionierten Import-/Compilervertrag zum selben -Accelerator; es darf keine zweite Fachlogik oder Configurator-Laufzeit voraussetzen. - -Feature-Einfuehrung erfolgt durchgaengig: Konzept/Architektur, Accelerator-/Modul- -Vertrag, Eingabeschema, gemeinsames Fachmodell, Validierung, Import/Export, -Editor/Assistent, Dokumentation und Tests. Nicht vorhandene Funktionen werden -als fehlend benannt und dort eingefuehrt, wo die Fachentscheidung liegt, nicht -als UI-Sonderoption oder frei erzeugter Terraform-Block. - -Credentials sind keine Modell-/Patchwerte. Konfiguration und sichere Credential- -Bindings sind getrennt: Der Export muss benoetigte externe Zugangsvoraussetzungen -und Referenzen nachvollziehbar machen; ausserhalb des Configurators werden sie -ueber die dokumentierten Accelerator-/Provider-Eingaben bzw. Umgebungsvariablen -bereitgestellt. Keine Configurator-exklusiven versteckten Secrets, keine -Klartext-Secrets in exportierter Konfiguration und keine Credential-Nachfragen -im Chat. Exportierbarkeit allein ist kein Ausfuehrungs- oder Berechtigungsnachweis. - -Der erste strukturierte Chat-Patch erweitert nur vorhandene SNA-Eingaben -(network_area/network_areas). Er fuehrt kein neues Accelerator-Feature ein. -Firewall, VPN, regionale Konnektivitaet und andere komplexe Komponenten brauchen -jeweils einen eigenen geprueften Vorschlags-/Binding-Vertrag. - -Import/Export unterscheiden **nicht gesetzt**, **explizit null/deaktiviert** und -**explizit konfiguriert**. Anzeige wirksamer Defaults darf nicht beim bloßen Öffnen -jede Option in den Export schreiben. Unbearbeitete Werte bleiben erhalten. -Zusätzlich ist eine bewusste Normalisierung der beiden unterstützten Connectivity- -Eingabeformen nötig; beide dürfen nicht parallel als aktive Quellen exportiert werden. - -Version 1/2 der bereits gespeicherten Standalone-Dokumente bekommt einen geprüften -Migrationsadapter. Keine stillen Änderungen an Schlüsseln, Ressourcenadressen, -Ordnerzuordnung oder alten tfvars-Hashes. Alte Deployment-Vorbereitungen bleiben -unveränderlich; Änderungen erzeugen neue Revisionen und Vorbereitungen. Die -unveröffentlichte Einzelbereich-Prototypversion 3 wird nicht als Format festgeschrieben. - -## Projektarten und grafische Darstellung - -Eine gemeinsame Projektliste ersetzt die implizite Trennung in obere Landing-Zone- -und untere Sandbox-Formulare. Beim Anlegen und Bearbeiten werden angezeigt: - -| Projektart | Zielordnerrolle | Weitere Auswahl | +Form, chatbot, graphic and export use the same model. There are no +separate feature lists per template. Switching template is an explicitly +confirmed new preset; it must not silently replace existing user changes. +For existing configurations, provenance is not a feature limit. + + +### Binding Accelerator contract (2026-10-10) + +Supplementary knowledge architecture: curated Markdown modules per topic/service +with a fixed section contract, explicit manifest, source/content hashes and +generated backend bundle. The initial SNA/credential modules have been +expanded to 19 topics covering all Accelerator areas and the configuration lifecycle. +Each of the current 29 root inputs needs an explicit topic +assignment; the freshness/completeness gate checks it. Topic selection follows +feature groups plus knowledge dependencies, not compulsory activation; credential +basics and lifecycle are mandatory. Template values are not user approval +to provision optional components. No arbitrary Markdown/web/customer-data ingestion, +no vector database or automatic knowledge promotion. The required +freshness check blocks stale artifacts. Markdown explains; schema/compiler +decide. Architecture and extension flow: +[Service knowledge](assistant-knowledge/README.md). + +The Assistant translates free-form requirements exclusively into this common +configuration model and its already supported Accelerator inputs. +It generates neither unrestricted Terraform nor editor-/chat-exclusive resources or +provider configuration. Native export remains a configuration independently +usable with the matching Accelerator version. Currently this is +Terraform tfvars, not a newly invented YAML schema. A later YAML format +needs an explicit versioned import/compiler contract to the same +Accelerator; it must not require a second domain logic or Configurator runtime. + +Feature introduction is end-to-end: concept/architecture, Accelerator/module +contract, input schema, common domain model, validation, import/export, +editor/Assistant, documentation and tests. Missing features are +identified as missing and introduced where the domain decision belongs, not +as a UI special option or freely generated Terraform block. + +Credentials are not model/patch values. Configuration and secure credential +bindings are separate: export must make required external credentials +and references understandable; outside the Configurator these are +provided through documented Accelerator/provider inputs or environment variables. +No Configurator-exclusive hidden secrets, no +plaintext secrets in exported configuration and no credential questions +in chat. Exportability alone is no proof of execution or permission. + +The first structured chat patch extends only existing SNA inputs +(network_area/network_areas). It introduces no new Accelerator feature. +Firewall, VPN, regional connectivity and other complex components each need +their own reviewed proposal/binding contract. + +Import/export distinguish **unset**, **explicit null/disabled** and +**explicitly configured**. Displaying effective defaults must not write +every option into the export merely on opening. Unedited values are preserved. +Deliberate normalization of the two supported Connectivity +input forms is also necessary; they must not both be exported as active sources. + +Versions 1/2 of already saved Standalone documents receive a reviewed +migration adapter. No silent changes to keys, resource addresses, +folder assignment or old tfvars hashes. Old deployment preparations remain +immutable; changes create new revisions and preparations. The +unpublished single-area prototype version 3 is not established as a format. + + +## Project kinds and graphical representation + +A common project list replaces implicit separation into upper Landing Zone +and lower sandbox forms. Creation and editing display: + +| Project kind | Target folder role | Further selection | | --- | --- | --- | -| Public | `landing_zones_public` | Region, Projektdienste; keine automatische öffentliche Freigabe | -| Corporate | `landing_zones_corporate` | Region **und vorhandener Netzwerkbereich dieser Region** | -| Sandbox | `sandboxes` | Sandbox-spezifische Angaben | -| Plattformprojekt | `platform` | Wird durch Management/Connectivity/DevOps/Kubernetes erzeugt; keine beliebige vierte Projektart | - -Die UI zeigt jeweils den tatsächlich konfigurierten Ordnernamen. Netzwerkbereiche -werden im Netzwerkbereich des Editors verwaltet und ausdrücklich referenziert; -ein Corporate-Projekt erzeugt keinen versteckten zweiten Netzwerk-Konfigurationspfad. -Das Entfernen eines Bereichs mit Referenzen wird blockiert. Projektartwechsel zeigen -Auswirkungen auf Daten, Zuordnung und Ressourcenidentitäten und benötigen eine -bewusste Bestätigung; bestehende Ressourcen werden dadurch noch nicht angewendet. - -Die Grafik verwendet zwei zusammenhängende Ansichten: - -1. **Organisation:** Organisation → optionaler Parent → Ordner → Projekte und - relevante Angebote, einschließlich automatisch erzeugter Plattformprojekte. -2. **Netzwerk:** Region → Netzwerkbereiche → zugeordnete Corporate-Projekte, - Firewall/VPN/DNS. Public und Sandbox bleiben entsprechend ungebunden. - -Ein Netzwerkbereich ist kein Resource-Manager-Ordner. Mehrere Bereiche in einer -Region können mehrere Hub-Projekte erzeugen; die bisherige pauschale Darstellung -„ein Hub je Region“ muss dafür ersetzt werden. - -## Editor-Struktur und Abhängigkeiten - -Fachbereiche: **Grundlagen → Organisation/Ordner → Netzwerk → Plattform → Projekte -→ Sicherheit/Betrieb → Prüfen**. Eine Funktionsübersicht zeigt aktivierte Angebote -und Ergänzungsmöglichkeiten. Optionale Details erscheinen bei Bedarf, bleiben aber -für jede Vorlage erreichbar. Es werden keine Terraform-Variablennamen als primäre -Bedienoberfläche verwendet. - -Jede Featuredefinition erhält stabile ID, fachliche Erklärung, Konfigurationsschema, -Default-/Aktivierungsregeln, Referenzen/Abhängigkeiten, zuständigen Editor, -Grafikprojektion, Compilerabbildung und Testfälle. Getrennte Zustände: - -- im Accelerator-Stand vorhanden; -- in der aktuellen Kombination zulässig; -- im Editor umgesetzt; -- für Plan/Apply in der aktuellen Ausführungsphase unterstützt. - -So wird eine vorhandene Engine-Funktion nicht fälschlich als bereits ausführbare -Configurator-Funktion angeboten. Das Ziel bleibt vollständige UI-Abdeckung; die -Migration wird nicht als „alle Features fertig“ ausgegeben. - -## Bereits festgestellte Kombinationsgrenzen - -Das [Grenzen- und Issue-Register](accelerator-limitations.md) ordnet die Befunde -den Accelerator-Issues zu und trennt Modellierbarkeit von Ausführbarkeit. - -- Private/SNA-Kubernetes-APIs sind vom aktuellen CF-Runner nicht nachweislich - erreichbar ([#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37)). - Kubernetes-/Helm-Phasen dürfen erst mit geeignetem Netzwerkpfad ausgeführt werden. - Serverseitige Capability-Prüfung ist Voraussetzung der Modellerweiterung; - die private Runner-Anbindung wird separat umgesetzt. - -- Corporate referenziert einen existierenden Bereich; mit regionaler Connectivity - muss die Projektregion im regionalen Modell vorhanden sein (`variables.tf`). -- Regionale Root-Instanzen unterstützen derzeit eu01/eu02. Beliebige weitere Regionen - brauchen zuerst Unterstützung im Accelerator. -- Bei `connectivity.firewalls` müssen die Schlüssel zu `network_areas` passen. -- `firewall_config` ist aktuell an die einzelne `connectivity.firewall` gebunden. - Die Policy-UI darf daraus keine beliebige Multi-Area-/Multi-Region-Unterstützung ableiten. -- Namespace-Dienste benötigen genau eine passende Instanz des nichtregionalen - `module.platform_kubernetes`; die Root-Dateien verwenden zudem `module.landing_zone`. - Die Multi-Region-Kubernetes-Vorlage beweist daher keine regionale Namespace-Unterstützung. -- Firewall-Bootstrap und spätere Kubernetes-/VPN-Schritte können mehrere - Ausführungsphasen und geschützte Laufzeitinformationen benötigen. Diese Phasen - werden vom Deployment-Modell gesteuert, nicht durch einen normalen Feature-Schalter. -- Kommentare sind keine verlässlichen Defaults: Bei Audit-Logs beschreibt der Text - Object Lock als aus, während der tatsächliche optionale Default `true` ist. - Die UI muss die wirksame Einstellung ausdrücklich zeigen. Ebenso wird eine - Ordnerbeschreibung zwar im Root-Typ akzeptiert, aber nicht bis zur Ressource durchgereicht. -- Einige Moduloptionen, etwa Governance-Custom-Roles oder bestimmte ACLs, werden vom - Root-Aufruf nicht durchgereicht. Änderungen am Accelerator wären ein eigener Umfang. - -## Umsetzung und Abnahme - -### A – Vollständige Grundlage - -- [x] Alle acht Templates und 28 Root-Eingaben aufnehmen. -- [x] Verschachtelte Typen, Defaults und Validierungen automatisch extrahieren. -- [x] Sensible Defaults aus dem Inventar ausschließen und testen. -- [x] Inventar-Aktualität in CI prüfen. -- [x] Funktionsbereiche, Projektmodell und wesentliche Kombinationsgrenzen festlegen. -- [x] Feld-/Unterfunktionsabdeckung als maschinenprüfbaren Feature-Katalog abbilden - (`featureFieldCatalogue`; Formularfelder, geschützte Bindings und wirkungslose Felder getrennt). - -### B – Gemeinsames Modell und kompatibler Compiler - -- [x] Versioniertes Dokument unabhängig von Standalone implementieren (v3-Domain-Vertrag). -- [x] Alle acht Templates verlustfrei importieren, Herkunft und stabile IDs erhalten. -- [x] Legacy-Adapter für gespeicherte Dokumentversion 1/2, bytegleicher Export. -- [x] Migration lokaler Arbeitsstände und Umschaltung der Speicher-/Produkt-API. -- [ ] Referenz-/Default-/Deaktivierungsregeln zentral validieren. -- [x] Export mit echtem HCL-Parser semantisch rückvergleichen; unveränderte - Legacy-Konfigurationen zusätzlich bytegleich prüfen. -- [ ] Pro Referenzkonfiguration native OpenTofu-Tests mit Mock-Providern, kein Apply. - -### C – Erster vollständiger Bedienablauf auf dem gemeinsamen Modell - -- [x] Ordner, Regionen und mehrere Netzwerkbereiche bearbeiten. -- [x] Gemeinsame Projektliste mit Public/Corporate/Sandbox und sichtbaren Zielordnern. -- [x] Region-/Bereichsauswahl für Corporate; Plattformprojekte aus Modulen ableiten. -- [x] Organisations- und Netzwerkansicht aus denselben Daten erzeugen. -- [x] Fork-Speicherung, Wiederaufnahme, Navigation und bestehende Vorbereitungen prüfen. - -### D – Vollständige Feature-Abdeckung - -- [ ] Management/Governance, DevOps und Observability/Audit/Federation. -- [ ] DNS, Firewall je unterstütztem Bereich, HA, VPN und unterstützte Policy-Funktionen. -- [ ] Kubernetes/Node-Pools, KMS/Volumes, Bastion, Namespace-Dienste und Zugriff. -- [ ] Secret-Bindings und Ausführungsphasen je Funktion abnehmen. -- [ ] Chat-Werkzeuge auf denselben Katalog und dieselbe Validierung aufsetzen. -- [ ] Abdeckungsmatrix: kein unterstütztes Unterfeld ohne UI, Import/Export und Tests. - -### Release-Grenzen - -Nur Feature-Branch. Der bisherige Stand bleibt live, bis das jeweilige Inkrement -vollständig getestet ist. Kein Kunden-Apply ohne neue ausdrückliche Freigabe; kein -Destroy. Ein komplexes Template darf nicht automatisch einen Kunden-Plan oder -Ressourcenaufbau starten. Configurator-Infrastrukturfreigabe bleibt davon getrennt. - -## Implementierungsstand gemeinsamer Kern, 2026-09-30 - -[Domain-Vertrag und Prüfungen](../app/packages/domain/README.md) sind implementiert. -Typen und explizite Werte aller Root-Eingaben werden abgedeckt; sensible Eingaben -sind ausschließlich als separate Deployment-Bindings vorgesehen. Referenzprüfungen -für Projekte/Bereiche/DNS und die bekannten Ausführungsgrenzen sind als gemeinsame -Funktionen vorhanden. Das ist noch keine vollständige fachliche Provider-Validierung. - -Alle acht Vorlagen werden mit dem nativen HCL-Parser rückverglichen. Zehn direkte -OpenTofu-Tests prüfen den Root-Variablenvertrag inklusive Object-Lock-Defaults. -Vollständige Modulpläne mit Mock-Providern bleiben offen. Standalone enthält den -bestätigten Fehler [#84](https://github.com/stackitcloud/stackit-landing-zone/issues/84); -der unveränderte Import weist die fehlende Public-Markierung aus. Die bestehende -v1/v2-Erzeugung und bereits gespeicherte Entwürfe bleiben bytegleich. - -Der neue Kern ist noch nicht an den produktiven Editor, Fork-Speicher oder Runner -angeschlossen. Damit werden weder neue Konfigurationsarten still für Deployments -freigegeben noch bisherige Vorbereitungen migriert. Nächstes Inkrement ist der -gemeinsame Netzwerk-/Projekteditor mit kontrollierter Speicher- und API-Migration. - -### Abnahme des gemeinsamen Kerns +| Public | `landing_zones_public` | Region, project services; no automatic public exposure | +| Corporate | `landing_zones_corporate` | Region **and existing network area of that region** | +| Sandbox | `sandboxes` | Sandbox-specific inputs | +| Platform project | `platform` | Created by Management/Connectivity/DevOps/Kubernetes; not an arbitrary fourth project kind | + +The UI shows the actually configured folder name. Network areas +are managed in the editor's networking section and explicitly referenced; +a Corporate project creates no hidden second network-configuration path. +Removing an area with references is blocked. Project-kind switches show +effects on data, assignment and resource identities and need +deliberate confirmation; this does not yet apply existing resources. + +The graphic uses two connected views: + +1. **Organization:** organization → optional parent → folders → projects and + relevant offerings, including automatically created platform projects. +2. **Network:** region → network areas → assigned Corporate projects, + firewall/VPN/DNS. Public and sandbox remain correspondingly unbound. + +A network area is not a Resource Manager folder. Multiple areas in one +region can create multiple hub projects; the previous blanket display +“one hub per region” must be replaced accordingly. + + +## Editor structure and dependencies + +Domain areas: **Foundations → Organization/folders → Network → Platform → Projects +→ Security/operations → Review**. A feature overview shows enabled offerings +and possible additions. Optional details appear when needed, but remain +accessible for every template. Terraform variable names are not used as the primary +interaction interface. + +Each feature definition receives a stable ID, domain explanation, configuration schema, +default/activation rules, references/dependencies, responsible editor, +graphical projection, compiler mapping and tests. Separate states: + +- present in the Accelerator revision; +- permitted in the current combination; +- implemented in the editor; +- supported for Plan/Apply in the current execution phase. + +This avoids falsely offering an existing engine feature as an already executable +Configurator feature. Full UI coverage remains the goal; migration +is not presented as “all features complete”. + + +## Already identified combination limitations + +The [limitations and issue register](accelerator-limitations.md) maps findings +to Accelerator issues and separates modelability from executability. + +- Private/SNA Kubernetes APIs are not demonstrably reachable from the current CF Runner + ([#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37)). + Kubernetes/Helm phases may run only with a suitable network path. + Server-side capability checking is a prerequisite for model extension; + private Runner connectivity is implemented separately. + +- Corporate references an existing area; with regional connectivity, + the project region must exist in the regional model (`variables.tf`). +- Regional root instances currently support eu01/eu02. Arbitrary additional regions + first need Accelerator support. +- For `connectivity.firewalls`, keys must match `network_areas`. +- `firewall_config` is currently bound to the single `connectivity.firewall`. + The policy UI must not infer arbitrary multi-area/multi-region support. +- Namespace services need exactly one matching instance of nonregional + `module.platform_kubernetes`; root files also use `module.landing_zone`. + The Multi-Region Kubernetes template therefore does not prove regional namespace support. +- Firewall bootstrap and later Kubernetes/VPN steps may need multiple + execution phases and protected runtime information. These phases + are controlled by the deployment model, not a normal feature toggle. +- Comments are not reliable defaults: for audit logs, the text describes + Object Lock as off while the actual optional default is `true`. + The UI must explicitly show the effective setting. Likewise, + folder description is accepted in the root type but not passed through to the resource. +- Some module options, such as governance custom roles or certain ACLs, are not passed + through by the root call. Accelerator changes would be a separate scope. + + +## Implementation and acceptance + + +### A – Complete foundation + +- [x] Inventory all eight templates and 28 root inputs. +- [x] Automatically extract nested types, defaults and validations. +- [x] Exclude sensitive defaults from the inventory and test this. +- [x] Check inventory freshness in CI. +- [x] Define feature areas, project model and key combination limitations. +- [x] Map field/subfeature coverage as a machine-verifiable feature catalogue + (`featureFieldCatalogue`; form fields, protected bindings and ineffective fields separately). + + +### B – Common model and compatible compiler + +- [x] Implement versioned document independent of Standalone (v3 domain contract). +- [x] Losslessly import all eight templates, preserving provenance and stable IDs. +- [x] Legacy adapter for saved document versions 1/2, byte-identical export. +- [x] Migrate local working states and switch storage/product API. +- [ ] Centrally validate reference/default/deactivation rules. +- [x] Semantically compare export with a real HCL parser; additionally check unchanged + legacy configurations byte-for-byte. +- [ ] Native OpenTofu tests with mock providers per reference configuration, no Apply. + + +### C – First complete user flow on the common model + +- [x] Edit folders, regions and multiple network areas. +- [x] Common project list with Public/Corporate/Sandbox and visible target folders. +- [x] Region/area selection for Corporate; derive platform projects from modules. +- [x] Generate organization and network views from the same data. +- [x] Check fork saving, resumption, navigation and existing preparations. + + +### D – Complete feature coverage + +- [ ] Management/governance, DevOps and Observability/audit/federation. +- [ ] DNS, firewall per supported area, HA, VPN and supported policy features. +- [ ] Kubernetes/node pools, KMS/volumes, bastion, namespace services and access. +- [ ] Qualify secret bindings and execution phases per feature. +- [ ] Build chat tools on the same catalogue and validation. +- [ ] Coverage matrix: no supported subfield without UI, import/export and tests. + + +### Release boundaries + +Feature branch only. The previous revision remains live until each increment is +fully tested. No customer Apply without new explicit approval; no +Destroy. A complex template must not automatically start a customer Plan or +resource provisioning. Configurator infrastructure approval remains separate. + + +## Common core implementation status, 2026-09-30 + +[Domain contract and checks](../app/packages/domain/README.md) are implemented. +Types and explicit values of all root inputs are covered; sensitive inputs +are intended exclusively as separate deployment bindings. Reference checks +for projects/areas/DNS and known execution limitations exist as shared +functions. This is not yet complete domain-specific provider validation. + +All eight templates are compared with the native HCL parser. Ten direct +OpenTofu tests check the root variable contract including Object Lock defaults. +Complete module plans with mock providers remain open. Standalone contains the +confirmed defect [#84](https://github.com/stackitcloud/stackit-landing-zone/issues/84); +unchanged import reports the missing Public marking. Existing +v1/v2 creation and already saved drafts remain byte-identical. + +The new core is not yet connected to the production editor, fork storage or Runner. +It therefore neither silently approves new configuration kinds for deployments +nor migrates existing preparations. The next increment is the +common network/project editor with controlled storage and API migration. + + +### Common core acceptance Code `e6106b9`, [Validate Configurator 36737858294](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36737858294), -Versuch 2 erfolgreich: Anwendung (89 Unit-Tests), Datenbankintegration, Browsertests, -HCL-Roundtrips, zehn native Variablenvertragstests und alle sechs Infrastruktur-Prüfungen. -Der erste Versuch scheiterte ausschließlich beim OpenTofu-Download eines -Infrastrukturjobs mit HTTP 500 von GitHub; Wiederholung erfolgreich. +attempt 2 successful: application (89 unit tests), database integration, browser tests, +HCL round trips, ten native variable contract tests and all six infrastructure checks. +The first attempt failed solely during OpenTofu download in an +infrastructure job with HTTP 500 from GitHub; repeat successful. -Kein Release dieses internen Kerns, keine Kunden-Pläne oder Applies ausgeführt. -Die veröffentlichte Oberfläche bleibt bis zum getesteten Editor-Inkrement unverändert. +No release of this internal core, no customer Plans or Applies executed. +The published interface remains unchanged until the tested editor increment. -## Nachgezogenes Editor-Inkrement + +## Subsequent editor increment -[Gemeinsamer Editor](common-editor.md): sieben Bereiche, fachlich beschriftete -Formulare für alle nicht-sensiblen Root-Eingaben, gemeinsame Projektauswahl, -Bereichszuordnung, v3-Fork-Speicherung und Browser-Wiederaufnahme. Bestehende -v1/v2-Konfigurationen bleiben kompatibel; ein Wechsel zum neuen Editor ist explizit. +[Common editor](common-editor.md): seven areas, domain-labeled +forms for all nonsensitive root inputs, common project selection, +area assignment, v3 fork storage and browser resumption. Existing +v1/v2 configurations remain compatible; switching to the new editor is explicit. -Formularabdeckung bedeutet noch keine vollständige Deployment-Abnahme jedes -Untermoduls. Geschützte Zusatz-Bindings und v3-Runner-Anbindung bleiben offen; -der Backend-Guard verhindert entsprechende Deployment-Vorbereitungen. +Form coverage does not yet mean complete deployment acceptance of every +submodule. Protected additional bindings and v3 Runner integration remain open; +the backend guard prevents corresponding deployment preparations. -### Abnahme des Editor-Releases + +### Editor release acceptance -Code `527bd95` ist auf lzc-dev veröffentlicht. Release und vollständige Validierung -erfolgreich; 95 Anwendungstests und 20 Browserprüfungen bestanden. Live-Assets und -CF-Verbindungstests geprüft. [Belege und Prüfliste](common-editor.md#live-abnahme). +Code `527bd95` is published on lzc-dev. Release and full validation +successful; 95 application tests and 20 browser checks passed. Live assets and +CF connection tests checked. [Evidence and checklist](common-editor.md#live-abnahme). diff --git a/landing-zone-configurator/docs/decisions/0001-application-stack.de.md b/landing-zone-configurator/docs/decisions/0001-application-stack.de.md new file mode 100644 index 0000000..aee5fbf --- /dev/null +++ b/landing-zone-configurator/docs/decisions/0001-application-stack.de.md @@ -0,0 +1,62 @@ + + +# ADR 0001 – Sprache und Anwendungsstack + +[English](0001-application-stack.md) | [Deutsch](0001-application-stack.de.md) + +Stand: 2026-09-29. **Status: angenommen im Planungsgespräch.** + + + +## Entscheidung + +TypeScript als Hauptsprache für React-Oberfläche, Node.js-Backend und Worker. Gemeinsames Fachmodell, Laufzeitschemas, API-Verträge, Konfigurationscompiler und Graph-Modell als interne Pakete. Backend: Fastify; Frontend: React mit Vite. npm-Workspaces mit Lockfile. Runtime: Node.js 24.21.0 LTS und npm 11.19.0; konkrete Paketversionen in `app/package.json` und den Workspace-Manifests. + +Go auf einen kleinen HCL-Importadapter begrenzen. OpenTofu wird als gepinnter externer Prozess in isolierten Runnern ausgeführt. Die App muss deshalb nicht in Go geschrieben sein. Für einen Runner-Supervisor erst dann zusätzlich Go wählen, wenn Packaging oder Prozesssteuerung einen konkreten Vorteil belegen. + + + +## Warum das zum Configurator passt + +Die Hauptarbeit besteht aus Formularen, Validierung, GitHub-/Cloud-APIs, Chat-Streaming und asynchroner Jobkoordination. TypeScript ermöglicht gemeinsame Verträge und Fachlogik zwischen Browser und Backend. Ein Sprachwechsel für jede Schemaänderung entfällt. Externe Eingaben dennoch immer zur Laufzeit validieren: TypeScript-Typen sind keine Autorisierungs- oder Validierungsgrenze. + +Die eigentliche Infrastrukturarbeit übernimmt OpenTofu. CPU-intensive Verarbeitung großer Plans und HCL-Import gehören in begrenzte Worker/Adapter-Prozesse, nicht in den HTTP-Event-Loop. Für die erwarteten API-/I/O-Aufgaben ist Backend-Rohleistung nicht das ausschlaggebende Kriterium. + +Cloud Foundry dokumentiert sowohl [Node.js](https://docs.cloudfoundry.org/buildpacks/node/) als auch [Go](https://docs.cloudfoundry.org/buildpacks/go/index.html). STACKIT beschreibt das Deployment mit Buildpacks und anderen Artefaktformen; die im Ziel angebotenen Versionen sind beim Spike zu prüfen. [STACKIT-App-Deployment](https://docs.stackit.cloud/products/runtime/cloud-foundry/getting-started/push-your-app-to-cloud-foundry/) + +Für HCL stellt das Maintainer-Projekt einen Go-Parser und Go-APIs bereit. Daraus leitet sich der gezielte Go-Adapter ab, nicht die Notwendigkeit eines vollständigen Go-Backends. [HashiCorp HCL](https://github.com/hashicorp/hcl) + + + +## Alternativen + +| Variante | Stärke für diese Aufgabe | Aufwand / Nachteil | +| --- | --- | --- | +| TypeScript für Web/API/Worker plus kleiner Go-Adapter | Gemeinsame Fachlogik, kurze Wege zwischen Editor und API | Node-Abhängigkeiten pflegen; kleine zusätzliche Go-Toolchain | +| React/TypeScript plus Go-Backend | Direkte HCL-Integration, kompakte Backend-Binaries, gute Prozesswerkzeuge | Zwei vollwertige Anwendungsstacks; Verträge generieren und Validierungsgrenzen abstimmen | +| React/TypeScript plus Python-Backend | Sinnvoll bei ausgeprägter Python-Erfahrung oder eigener ML-Verarbeitung | Kein klarer Mehrwert für reine Model-Serving-API-Nutzung; ebenfalls zwei Stacks | +| React/TypeScript plus Java/Kotlin-Backend | Sinnvoll bei vorhandenem JVM-Team und etablierten Betriebsstandards | Für dieses neue Projekt ohne solche Vorgaben mehr initiale Struktur | + +React plus Go wäre meine zweite Wahl, besonders bei einem überwiegend Go-erfahrenen Backend-Team. Python ist nicht erforderlich, nur weil ein Chatbot Bestandteil der App ist: Das Modell wird als Dienst angesprochen. + + + +## Bewusste Grenzen + +- Eigene CF-Deployables für API und Worker; keine langen OpenTofu-Läufe in HTTP-Requests. +- Gemeinsame Pakete enthalten keine Server-Secrets; Browser-Bundles werden darauf geprüft. +- Sicherheit und Mandantenisolation ergeben sich aus Architektur, Autorisierung und Tests, nicht aus der Sprache. +- Keine freie Ausführung von HCL oder Shell durch das Modell. +- Team-Erfahrung kann die Empfehlung ändern. Vor Umsetzung vorhandene TypeScript-/Go-Erfahrung und Wartungsverantwortung festhalten. + + + +## Abschlusskriterien + +- [x] Hauptsprache gemeinsam bestätigen. +- [x] Frontend-/Backend-Framework, Paketmanager und unterstützte Runtime-Versionen festlegen. +- [ ] Minimalen CF-Deploy von Web/API/Worker testen. +- [ ] HCL-Import mit allen acht Templates prototypisch validieren. +- [ ] Schema-Verträge, Build-Grenzen und Versionierung festlegen. + +Die lokale Basis ist implementiert und getestet. CF-Deploy und HCL-Adapter sind noch offen. Node.js 24 wurde als LTS-Linie gewählt; Aktualisierungen erfolgen bewusst über Runtime-Pin und Lockfile. [Node.js Release-Status](https://nodejs.org/en/about/previous-releases) diff --git a/landing-zone-configurator/docs/decisions/0001-application-stack.md b/landing-zone-configurator/docs/decisions/0001-application-stack.md index 96a7e19..561af16 100644 --- a/landing-zone-configurator/docs/decisions/0001-application-stack.md +++ b/landing-zone-configurator/docs/decisions/0001-application-stack.md @@ -1,48 +1,56 @@ -# ADR 0001 – Sprache und Anwendungsstack + +# ADR 0001 – Language and application stack -Stand: 2026-09-29. **Status: angenommen im Planungsgespräch.** +[English](0001-application-stack.md) | [Deutsch](0001-application-stack.de.md) -## Entscheidung +As of 2026-09-29. **Status: accepted in the planning discussion.** -TypeScript als Hauptsprache für React-Oberfläche, Node.js-Backend und Worker. Gemeinsames Fachmodell, Laufzeitschemas, API-Verträge, Konfigurationscompiler und Graph-Modell als interne Pakete. Backend: Fastify; Frontend: React mit Vite. npm-Workspaces mit Lockfile. Runtime: Node.js 24.21.0 LTS und npm 11.19.0; konkrete Paketversionen in `app/package.json` und den Workspace-Manifests. + +## Decision -Go auf einen kleinen HCL-Importadapter begrenzen. OpenTofu wird als gepinnter externer Prozess in isolierten Runnern ausgeführt. Die App muss deshalb nicht in Go geschrieben sein. Für einen Runner-Supervisor erst dann zusätzlich Go wählen, wenn Packaging oder Prozesssteuerung einen konkreten Vorteil belegen. +TypeScript as the primary language for the React interface, Node.js backend and worker. Shared domain model, runtime schemas, API contracts, configuration compiler and graph model as internal packages. Backend: Fastify; frontend: React with Vite. npm workspaces with lockfile. Runtime: Node.js 24.21.0 LTS and npm 11.19.0; concrete package versions in `app/package.json` and the workspace manifests. -## Warum das zum Configurator passt +Limit Go to a small HCL import adapter. OpenTofu runs as a pinned external process in isolated Runners. The app therefore does not need to be written in Go. Only choose additional Go for a Runner supervisor when packaging or process control demonstrates a concrete advantage. -Die Hauptarbeit besteht aus Formularen, Validierung, GitHub-/Cloud-APIs, Chat-Streaming und asynchroner Jobkoordination. TypeScript ermöglicht gemeinsame Verträge und Fachlogik zwischen Browser und Backend. Ein Sprachwechsel für jede Schemaänderung entfällt. Externe Eingaben dennoch immer zur Laufzeit validieren: TypeScript-Typen sind keine Autorisierungs- oder Validierungsgrenze. + +## Why this suits the Configurator -Die eigentliche Infrastrukturarbeit übernimmt OpenTofu. CPU-intensive Verarbeitung großer Plans und HCL-Import gehören in begrenzte Worker/Adapter-Prozesse, nicht in den HTTP-Event-Loop. Für die erwarteten API-/I/O-Aufgaben ist Backend-Rohleistung nicht das ausschlaggebende Kriterium. +The main work consists of forms, validation, GitHub/cloud APIs, chat streaming and asynchronous job coordination. TypeScript enables shared contracts and domain logic between browser and backend. No language switch is required for each schema change. Still always validate external inputs at runtime: TypeScript types are not an authorization or validation boundary. -Cloud Foundry dokumentiert sowohl [Node.js](https://docs.cloudfoundry.org/buildpacks/node/) als auch [Go](https://docs.cloudfoundry.org/buildpacks/go/index.html). STACKIT beschreibt das Deployment mit Buildpacks und anderen Artefaktformen; die im Ziel angebotenen Versionen sind beim Spike zu prüfen. [STACKIT-App-Deployment](https://docs.stackit.cloud/products/runtime/cloud-foundry/getting-started/push-your-app-to-cloud-foundry/) +OpenTofu handles the actual infrastructure work. CPU-intensive processing of large Plans and HCL import belong in bounded worker/adapter processes, not in the HTTP event loop. Raw backend performance is not the deciding criterion for the expected API/I/O tasks. -Für HCL stellt das Maintainer-Projekt einen Go-Parser und Go-APIs bereit. Daraus leitet sich der gezielte Go-Adapter ab, nicht die Notwendigkeit eines vollständigen Go-Backends. [HashiCorp HCL](https://github.com/hashicorp/hcl) +Cloud Foundry documents both [Node.js](https://docs.cloudfoundry.org/buildpacks/node/) and [Go](https://docs.cloudfoundry.org/buildpacks/go/index.html). STACKIT describes deployment with buildpacks and other artifact formats; versions offered at the target must be checked during the spike. [STACKIT app deployment](https://docs.stackit.cloud/products/runtime/cloud-foundry/getting-started/push-your-app-to-cloud-foundry/) -## Alternativen +For HCL, the maintainer project provides a Go parser and Go APIs. This motivates the targeted Go adapter, not the need for an entire Go backend. [HashiCorp HCL](https://github.com/hashicorp/hcl) -| Variante | Stärke für diese Aufgabe | Aufwand / Nachteil | + +## Alternatives + +| Option | Strength for this task | Effort / disadvantage | | --- | --- | --- | -| TypeScript für Web/API/Worker plus kleiner Go-Adapter | Gemeinsame Fachlogik, kurze Wege zwischen Editor und API | Node-Abhängigkeiten pflegen; kleine zusätzliche Go-Toolchain | -| React/TypeScript plus Go-Backend | Direkte HCL-Integration, kompakte Backend-Binaries, gute Prozesswerkzeuge | Zwei vollwertige Anwendungsstacks; Verträge generieren und Validierungsgrenzen abstimmen | -| React/TypeScript plus Python-Backend | Sinnvoll bei ausgeprägter Python-Erfahrung oder eigener ML-Verarbeitung | Kein klarer Mehrwert für reine Model-Serving-API-Nutzung; ebenfalls zwei Stacks | -| React/TypeScript plus Java/Kotlin-Backend | Sinnvoll bei vorhandenem JVM-Team und etablierten Betriebsstandards | Für dieses neue Projekt ohne solche Vorgaben mehr initiale Struktur | +| TypeScript for web/API/worker plus small Go adapter | Shared domain logic, short paths between editor and API | Maintain Node dependencies; small additional Go toolchain | +| React/TypeScript plus Go backend | Direct HCL integration, compact backend binaries, good process tools | Two full application stacks; generate contracts and align validation boundaries | +| React/TypeScript plus Python backend | Useful with substantial Python experience or custom ML processing | No clear added value for pure Model Serving API usage; also two stacks | +| React/TypeScript plus Java/Kotlin backend | Useful with an existing JVM team and established operational standards | More initial structure for this new project without such requirements | -React plus Go wäre meine zweite Wahl, besonders bei einem überwiegend Go-erfahrenen Backend-Team. Python ist nicht erforderlich, nur weil ein Chatbot Bestandteil der App ist: Das Modell wird als Dienst angesprochen. +React plus Go would be my second choice, especially with a backend team predominantly experienced in Go. Python is not required just because a chatbot is part of the app: the model is called as a service. -## Bewusste Grenzen + +## Deliberate boundaries -- Eigene CF-Deployables für API und Worker; keine langen OpenTofu-Läufe in HTTP-Requests. -- Gemeinsame Pakete enthalten keine Server-Secrets; Browser-Bundles werden darauf geprüft. -- Sicherheit und Mandantenisolation ergeben sich aus Architektur, Autorisierung und Tests, nicht aus der Sprache. -- Keine freie Ausführung von HCL oder Shell durch das Modell. -- Team-Erfahrung kann die Empfehlung ändern. Vor Umsetzung vorhandene TypeScript-/Go-Erfahrung und Wartungsverantwortung festhalten. +- Separate CF deployables for API and worker; no long OpenTofu runs in HTTP requests. +- Shared packages contain no server secrets; browser bundles are checked for them. +- Security and tenant isolation come from architecture, authorization and tests, not the language. +- No unrestricted HCL or shell execution by the model. +- Team experience can change the recommendation. Record existing TypeScript/Go experience and maintenance responsibilities before implementation. -## Abschlusskriterien + +## Completion criteria -- [x] Hauptsprache gemeinsam bestätigen. -- [x] Frontend-/Backend-Framework, Paketmanager und unterstützte Runtime-Versionen festlegen. -- [ ] Minimalen CF-Deploy von Web/API/Worker testen. -- [ ] HCL-Import mit allen acht Templates prototypisch validieren. -- [ ] Schema-Verträge, Build-Grenzen und Versionierung festlegen. +- [x] Jointly confirm the primary language. +- [x] Define frontend/backend framework, package manager and supported runtime versions. +- [ ] Test a minimal CF deployment of web/API/worker. +- [ ] Validate HCL import with all eight templates in a prototype. +- [ ] Define schema contracts, build boundaries and versioning. -Die lokale Basis ist implementiert und getestet. CF-Deploy und HCL-Adapter sind noch offen. Node.js 24 wurde als LTS-Linie gewählt; Aktualisierungen erfolgen bewusst über Runtime-Pin und Lockfile. [Node.js Release-Status](https://nodejs.org/en/about/previous-releases) +The local foundation is implemented and tested. CF deployment and HCL adapter remain open. Node.js 24 was chosen as the LTS line; updates are made deliberately through the runtime pin and lockfile. [Node.js release status](https://nodejs.org/en/about/previous-releases) diff --git a/landing-zone-configurator/docs/deployment-credentials.de.md b/landing-zone-configurator/docs/deployment-credentials.de.md new file mode 100644 index 0000000..2934676 --- /dev/null +++ b/landing-zone-configurator/docs/deployment-credentials.de.md @@ -0,0 +1,142 @@ + + +# Persönliche Deployment-Zugänge + +[English](deployment-credentials.md) | [Deutsch](deployment-credentials.de.md) + +Stand: 2026-09-30. Nächster Baustein nach Fork-Speicherung und tfvars-Export. + + + +## Umfang und Benutzerablauf + +1. Mit GitHub anmelden und **Deployment-Zugänge** öffnen (`/credentials`). +2. Einen Profilnamen vergeben und eine STACKIT-Service-Account-Schlüsseldatei als + JSON mit enthaltenem privatem RSA-Schlüssel auswählen. +3. **Zugang sicher speichern**. Die Liste zeigt Name, Service-Account und Status; + der Schlüssel wird nicht wieder angezeigt oder zum Download angeboten. +4. **Zugang löschen** entfernt alle Secret-Versionen aus dem Configurator. Das + widerruft den Schlüssel bei STACKIT nicht. Ein Widerruf erfolgt separat in der + STACKIT-Service-Account-Verwaltung. + +Unterstützt wird zunächst der Key Flow mit eingebettetem RSA-Schlüssel ab 2048 Bit. +Dateien mit deaktiviertem oder bereits abgelaufenem Schlüssel, widersprüchlichen IDs, +fehlendem privaten Schlüssel oder unbekannter Audience werden abgewiesen. Diese +Prüfung bestätigt nur das Dateiformat und lokale Schlüssellesbarkeit. Ein gültiges +Format beweist weder aktuelle STACKIT-Rechte noch Übereinstimmung mit dem bei STACKIT +registrierten öffentlichen Schlüssel. Status daher ausdrücklich **Berechtigungen +noch nicht geprüft**. Separate PEM-Dateien, WIF, Rotation im vorhandenen Profil, +Delegation und automatische Cloud-Rechteprüfung folgen später. + +[Offizielles STACKIT-Schlüsseldateiformat](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-keys/). + + + +## Daten und Zugriff + +- `lzc.credential_profiles` enthält ausschließlich Metadaten: UUID, Mandant, + Eigentümer, Profilname, Service-Account-Mail, Key-ID, Speicherstatus und Zeitstempel. +- Migration `002_credential_profiles.sql` läuft über den vorhandenen separaten + CF-Migrations-Task als `configurator_migration`. Die Laufzeitrolle bleibt ohne + Tabellenbesitz und ohne BYPASSRLS. Keine neue Cloud-Ressource oder manuelle + Rechteerweiterung erforderlich; bestehende IaC-provisionierte Dienste werden genutzt. +- Forced RLS verlangt aktuellen Mandanten, Mitgliedschaft und Eigentümer. Auch + andere Administratoren desselben Mandanten sehen oder löschen persönliche Profile + nicht. Anlegen verlangt `admin` oder `deployer`. Rollen/Identität stammen aus der + Backend-Session, niemals aus dem Request-Body. +- Secret-Pfad in der dedizierten Configurator-Instanz: + `configurator/tenants//users//credentials/`. + UUIDs werden serverseitig erzeugt/validiert. Secret-Daten binden Mandant, Benutzer, + Profil und Typ; keine GitHub-Sessionbindung, damit Profile nach erneutem Login bleiben. +- Die UI sendet die Datei nur mit explizitem Speichern über HTTPS. Kein Git-Commit, + kein Browser-Storage, kein Query-Parameter, kein Secret-Download-Endpunkt. Der + Datei-Input wird nach dem Versuch geleert; Navigation/Abmeldung entfernt die + Komponente. JavaScript garantiert keine physische Speicherlöschung. +- GET listet Metadaten. POST und DELETE benötigen Session, exakte Origin und CSRF. + `Cache-Control: no-store`; keine Body-/Secret-/Parserfehler in Anwendungslogs. +- Maximal 20 Profile pro Benutzer und Mandant; konkurrierendes Anlegen wird durch + einen PostgreSQL-Advisory-Lock beim Reservieren serialisiert. UI-Dateilimit 24 KiB, + API-Bodylimit 32 KiB. Keine automatische Wiederholung von POST. + +Der App-Benutzer hat die bereits genehmigten instanzweiten Secrets-Manager-Rechte. +Die Trennung persönlicher Secrets wird durch Backend-Pfade, Session und Datenbank-RLS +implementiert; es bestehen noch keine separaten Vault-Policies pro Mandant. Ein +kompromittiertes Backend liegt damit weiterhin innerhalb der Vertrauensgrenze. + + + +## Fehler und Löschung + +Vor dem Secret-Schreiben wird ein `pending`-Metadatensatz dauerhaft reserviert. +Danach sperrt eine Transaktion genau diese Zeile, schreibt mit Vault-CAS `0` und +setzt bei Erfolg `stored`. Create/Delete können dasselbe Profil dadurch nicht +während des Schreibens gegenseitig entfernen. Nach Crash oder unklarer Antwort +bleibt mindestens der Metadatensatz zur Bereinigung erhalten. `pending` bedeutet +nicht verwendbar; UI bietet Löschen und Neuanlegen, keine blinde Wiederholung. + +Löschen sperrt die autorisierte Zeile, entfernt zuerst Vault-Metadaten einschließlich +aller Secret-Versionen und danach den DB-Datensatz. 404 beim Secret-Löschen gilt als +bereits entfernt. Bei Abbruch kann ein Metadatensatz verbleiben, dessen Secret schon +fehlt; Löschen ist wiederholbar. Ein späterer Runner darf sich deshalb niemals allein +auf `stored` verlassen, sondern muss Existenz, Secret-Identität und Berechtigung vor +jeder Verwendung erneut prüfen. Es gibt noch keinen Runner-Zugriff auf diese Profile. +Vault-Login-Tokens werden nach jeder Operation widerrufen, auch bei Fehlern. + + + +## Abnahme und weitere Arbeit + +- [x] Schlüsseldatei formal und kryptografisch lokal prüfen. +- [x] Persönliche Profile anlegen, auflisten und löschen; kein Schlüssel-Leseendpunkt. +- [x] Session-/CSRF-/Identitätsinjektions- und Secret-Pfad-Negativtests. +- [x] Echtes PostgreSQL: fremde Mandanten, fremde Eigentümer im selben Mandanten, + fehlende Rolle, kein Secret in Metadaten und wiederholbare Fehlerbereinigung. +- [x] Feature-Branch-Release inklusive Migration auf lzc-dev abnehmen. +- [x] Persönliches Profil über die live bereitgestellte UI abnehmen (Benutzerbestätigung). +- [x] STACKIT-Authentifizierung und lesende Organisationsprüfung ergänzen; [Ablauf und Abnahme](deployment-preparation.de.md). +- [x] Feste Accelerator-Referenz und unveränderliche Konfiguration in einer Vorbereitung binden; Cloud-/Plan-Qualifizierung bleibt offen. +- [ ] Kundenbezogenen Remote State, Runner, Queue, Plan und expliziten Apply ergänzen. +- [ ] Rotation, automatische Bereinigung, Audit-Ereignisse und Delegationen ausbauen. + +Die Betreiber-Schlüsseldatei aus dem Repository-Root wird nicht als Benutzerprofil +importiert. Lokale Tests nutzen nur generierte oder künstliche Testschlüssel. + + + +## Technische Release-Abnahme + +Code-Commit `629fab6` auf `feature/landing-zone-configurator`. +[Validierung 36706267168](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36706267168) +und [Release 36706267163](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36706267163) +erfolgreich. 38 Anwendungstests, neun echte PostgreSQL-Tests und 14 Browserfälle +bestanden. Migration und CF-Verbindungstests zu PostgreSQL und Secrets Manager grün. +Mobile Profilverwaltung visuell anhand des Test-Screenshots geprüft. +Live bestätigt: `/credentials`, Reload, mobile Breite, keine Browserfehler und +401 für anonymes GET/POST/DELETE. Kein echter Schlüssel für die Live-Abnahme hochgeladen; +der persönliche Upload durch den Benutzer bleibt ein separater Abnahmepunkt. + + + +## Korrektur: aktuelles STACKIT-Accounts-Schlüsselformat + +Die ursprüngliche Audience-Allowlist berücksichtigte nur die älteren Service-Account- +Hosts und wies gültige Dateien mit `credentials.aud = https://accounts.stackit.cloud` +zurück. Die Validierung akzeptiert nun auch diese Audience und bewahrt das optionale +`credentials.tokenEndpoint`, insbesondere `https://accounts.stackit.cloud/oauth/v2/token`. +Nur ausdrücklich bekannte HTTPS-Endpunkte sind zulässig; keine beliebigen Upload-URLs. +Regressionstest: aktuelles Format wird akzeptiert und vollständig an den Secret-Store +übergeben; manipulierte Token-Endpunkte werden abgewiesen. Bestehende ältere Dateien +ohne `tokenEndpoint` bleiben unterstützt. Ein abgewiesener Upload hat keinen Profil- +oder Secret-Schreibvorgang ausgelöst. + +Quellen: [STACKIT Token-Abruf](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/get-access-token/), +[SDK-Unterstützung für tokenEndpoint](https://github.com/stackitcloud/stackit-sdk-go/releases/). + +Fix-Abnahme: Commit `6c95098`, [Validierung 36711832436](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36711832436) +und [Release 36711832452](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36711832452) +erfolgreich. 39 Anwendungstests grün. Die vorhandene lokale STACKIT-Schlüsseldatei +besteht die Formatprüfung einschließlich Erhalt des Token-Endpunkts; dabei kein +Upload und keine Ausgabe von Schlüsselinhalten. Live-Seite und anonymer Zugriffsschutz +nach Release geprüft; persönliche erneute Upload-Abnahme bleibt beim Benutzer. + +Aktueller Folgestand: [Zugangstest und Deployment-Vorbereitung](deployment-preparation.de.md). Die oben beschriebene ursprüngliche Ablage wird jetzt um interne Secret-Lesezugriffe ausschließlich für autorisierte Prüfungen erweitert; Rohschlüssel bleiben für den Browser unzugänglich. diff --git a/landing-zone-configurator/docs/deployment-credentials.md b/landing-zone-configurator/docs/deployment-credentials.md index a2df803..cb2815c 100644 --- a/landing-zone-configurator/docs/deployment-credentials.md +++ b/landing-zone-configurator/docs/deployment-credentials.md @@ -1,126 +1,135 @@ -# Persönliche Deployment-Zugänge - -Stand: 2026-09-30. Nächster Baustein nach Fork-Speicherung und tfvars-Export. - -## Umfang und Benutzerablauf - -1. Mit GitHub anmelden und **Deployment-Zugänge** öffnen (`/credentials`). -2. Einen Profilnamen vergeben und eine STACKIT-Service-Account-Schlüsseldatei als - JSON mit enthaltenem privatem RSA-Schlüssel auswählen. -3. **Zugang sicher speichern**. Die Liste zeigt Name, Service-Account und Status; - der Schlüssel wird nicht wieder angezeigt oder zum Download angeboten. -4. **Zugang löschen** entfernt alle Secret-Versionen aus dem Configurator. Das - widerruft den Schlüssel bei STACKIT nicht. Ein Widerruf erfolgt separat in der - STACKIT-Service-Account-Verwaltung. - -Unterstützt wird zunächst der Key Flow mit eingebettetem RSA-Schlüssel ab 2048 Bit. -Dateien mit deaktiviertem oder bereits abgelaufenem Schlüssel, widersprüchlichen IDs, -fehlendem privaten Schlüssel oder unbekannter Audience werden abgewiesen. Diese -Prüfung bestätigt nur das Dateiformat und lokale Schlüssellesbarkeit. Ein gültiges -Format beweist weder aktuelle STACKIT-Rechte noch Übereinstimmung mit dem bei STACKIT -registrierten öffentlichen Schlüssel. Status daher ausdrücklich **Berechtigungen -noch nicht geprüft**. Separate PEM-Dateien, WIF, Rotation im vorhandenen Profil, -Delegation und automatische Cloud-Rechteprüfung folgen später. - -[Offizielles STACKIT-Schlüsseldateiformat](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-keys/). - -## Daten und Zugriff - -- `lzc.credential_profiles` enthält ausschließlich Metadaten: UUID, Mandant, - Eigentümer, Profilname, Service-Account-Mail, Key-ID, Speicherstatus und Zeitstempel. -- Migration `002_credential_profiles.sql` läuft über den vorhandenen separaten - CF-Migrations-Task als `configurator_migration`. Die Laufzeitrolle bleibt ohne - Tabellenbesitz und ohne BYPASSRLS. Keine neue Cloud-Ressource oder manuelle - Rechteerweiterung erforderlich; bestehende IaC-provisionierte Dienste werden genutzt. -- Forced RLS verlangt aktuellen Mandanten, Mitgliedschaft und Eigentümer. Auch - andere Administratoren desselben Mandanten sehen oder löschen persönliche Profile - nicht. Anlegen verlangt `admin` oder `deployer`. Rollen/Identität stammen aus der - Backend-Session, niemals aus dem Request-Body. -- Secret-Pfad in der dedizierten Configurator-Instanz: + +# Personal deployment credentials + +[English](deployment-credentials.md) | [Deutsch](deployment-credentials.de.md) + +As of 2026-09-30. Next building block after fork storage and tfvars export. + + +## Scope and user flow + +1. Sign in with GitHub and open **Deployment credentials** (`/credentials`). +2. Enter a profile name and select a STACKIT service-account key file as + JSON containing a private RSA key. +3. **Save credentials securely**. The list shows name, service account and status; + the key is not shown again or offered for download. +4. **Delete credentials** removes all secret versions from the Configurator. This + does not revoke the key at STACKIT. Revoke it separately in + STACKIT service-account management. + +Initially supported: Key Flow with an embedded RSA key of at least 2048 bits. +Files with a disabled or already expired key, conflicting IDs, +missing private key or unknown audience are rejected. This +check confirms only the file format and local key readability. A valid +format proves neither current STACKIT permissions nor correspondence with the public key +registered at STACKIT. The status therefore explicitly reads **Permissions +not yet checked**. Separate PEM files, WIF, rotation within an existing profile, +delegation and automatic cloud permission checks follow later. + +[Official STACKIT key file format](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/manage-service-account-keys/). + + +## Data and access + +- `lzc.credential_profiles` contains metadata only: UUID, tenant, + owner, profile name, service-account email, key ID, storage status and timestamps. +- Migration `002_credential_profiles.sql` runs through the existing separate + CF migration task as `configurator_migration`. The runtime role retains neither + table ownership nor BYPASSRLS. No new cloud resource or manual + permission expansion is required; existing IaC-provisioned services are used. +- Forced RLS requires the current tenant, membership and owner. Even + other administrators in the same tenant cannot see or delete personal profiles. + Creation requires `admin` or `deployer`. Roles/identity come from the + backend session, never the request body. +- Secret path in the dedicated Configurator instance: `configurator/tenants//users//credentials/`. - UUIDs werden serverseitig erzeugt/validiert. Secret-Daten binden Mandant, Benutzer, - Profil und Typ; keine GitHub-Sessionbindung, damit Profile nach erneutem Login bleiben. -- Die UI sendet die Datei nur mit explizitem Speichern über HTTPS. Kein Git-Commit, - kein Browser-Storage, kein Query-Parameter, kein Secret-Download-Endpunkt. Der - Datei-Input wird nach dem Versuch geleert; Navigation/Abmeldung entfernt die - Komponente. JavaScript garantiert keine physische Speicherlöschung. -- GET listet Metadaten. POST und DELETE benötigen Session, exakte Origin und CSRF. - `Cache-Control: no-store`; keine Body-/Secret-/Parserfehler in Anwendungslogs. -- Maximal 20 Profile pro Benutzer und Mandant; konkurrierendes Anlegen wird durch - einen PostgreSQL-Advisory-Lock beim Reservieren serialisiert. UI-Dateilimit 24 KiB, - API-Bodylimit 32 KiB. Keine automatische Wiederholung von POST. - -Der App-Benutzer hat die bereits genehmigten instanzweiten Secrets-Manager-Rechte. -Die Trennung persönlicher Secrets wird durch Backend-Pfade, Session und Datenbank-RLS -implementiert; es bestehen noch keine separaten Vault-Policies pro Mandant. Ein -kompromittiertes Backend liegt damit weiterhin innerhalb der Vertrauensgrenze. - -## Fehler und Löschung - -Vor dem Secret-Schreiben wird ein `pending`-Metadatensatz dauerhaft reserviert. -Danach sperrt eine Transaktion genau diese Zeile, schreibt mit Vault-CAS `0` und -setzt bei Erfolg `stored`. Create/Delete können dasselbe Profil dadurch nicht -während des Schreibens gegenseitig entfernen. Nach Crash oder unklarer Antwort -bleibt mindestens der Metadatensatz zur Bereinigung erhalten. `pending` bedeutet -nicht verwendbar; UI bietet Löschen und Neuanlegen, keine blinde Wiederholung. - -Löschen sperrt die autorisierte Zeile, entfernt zuerst Vault-Metadaten einschließlich -aller Secret-Versionen und danach den DB-Datensatz. 404 beim Secret-Löschen gilt als -bereits entfernt. Bei Abbruch kann ein Metadatensatz verbleiben, dessen Secret schon -fehlt; Löschen ist wiederholbar. Ein späterer Runner darf sich deshalb niemals allein -auf `stored` verlassen, sondern muss Existenz, Secret-Identität und Berechtigung vor -jeder Verwendung erneut prüfen. Es gibt noch keinen Runner-Zugriff auf diese Profile. -Vault-Login-Tokens werden nach jeder Operation widerrufen, auch bei Fehlern. - -## Abnahme und weitere Arbeit - -- [x] Schlüsseldatei formal und kryptografisch lokal prüfen. -- [x] Persönliche Profile anlegen, auflisten und löschen; kein Schlüssel-Leseendpunkt. -- [x] Session-/CSRF-/Identitätsinjektions- und Secret-Pfad-Negativtests. -- [x] Echtes PostgreSQL: fremde Mandanten, fremde Eigentümer im selben Mandanten, - fehlende Rolle, kein Secret in Metadaten und wiederholbare Fehlerbereinigung. -- [x] Feature-Branch-Release inklusive Migration auf lzc-dev abnehmen. -- [x] Persönliches Profil über die live bereitgestellte UI abnehmen (Benutzerbestätigung). -- [x] STACKIT-Authentifizierung und lesende Organisationsprüfung ergänzen; [Ablauf und Abnahme](deployment-preparation.md). -- [x] Feste Accelerator-Referenz und unveränderliche Konfiguration in einer Vorbereitung binden; Cloud-/Plan-Qualifizierung bleibt offen. -- [ ] Kundenbezogenen Remote State, Runner, Queue, Plan und expliziten Apply ergänzen. -- [ ] Rotation, automatische Bereinigung, Audit-Ereignisse und Delegationen ausbauen. - -Die Betreiber-Schlüsseldatei aus dem Repository-Root wird nicht als Benutzerprofil -importiert. Lokale Tests nutzen nur generierte oder künstliche Testschlüssel. - -## Technische Release-Abnahme - -Code-Commit `629fab6` auf `feature/landing-zone-configurator`. -[Validierung 36706267168](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36706267168) -und [Release 36706267163](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36706267163) -erfolgreich. 38 Anwendungstests, neun echte PostgreSQL-Tests und 14 Browserfälle -bestanden. Migration und CF-Verbindungstests zu PostgreSQL und Secrets Manager grün. -Mobile Profilverwaltung visuell anhand des Test-Screenshots geprüft. -Live bestätigt: `/credentials`, Reload, mobile Breite, keine Browserfehler und -401 für anonymes GET/POST/DELETE. Kein echter Schlüssel für die Live-Abnahme hochgeladen; -der persönliche Upload durch den Benutzer bleibt ein separater Abnahmepunkt. - -## Korrektur: aktuelles STACKIT-Accounts-Schlüsselformat - -Die ursprüngliche Audience-Allowlist berücksichtigte nur die älteren Service-Account- -Hosts und wies gültige Dateien mit `credentials.aud = https://accounts.stackit.cloud` -zurück. Die Validierung akzeptiert nun auch diese Audience und bewahrt das optionale -`credentials.tokenEndpoint`, insbesondere `https://accounts.stackit.cloud/oauth/v2/token`. -Nur ausdrücklich bekannte HTTPS-Endpunkte sind zulässig; keine beliebigen Upload-URLs. -Regressionstest: aktuelles Format wird akzeptiert und vollständig an den Secret-Store -übergeben; manipulierte Token-Endpunkte werden abgewiesen. Bestehende ältere Dateien -ohne `tokenEndpoint` bleiben unterstützt. Ein abgewiesener Upload hat keinen Profil- -oder Secret-Schreibvorgang ausgelöst. - -Quellen: [STACKIT Token-Abruf](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/get-access-token/), -[SDK-Unterstützung für tokenEndpoint](https://github.com/stackitcloud/stackit-sdk-go/releases/). - -Fix-Abnahme: Commit `6c95098`, [Validierung 36711832436](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36711832436) -und [Release 36711832452](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36711832452) -erfolgreich. 39 Anwendungstests grün. Die vorhandene lokale STACKIT-Schlüsseldatei -besteht die Formatprüfung einschließlich Erhalt des Token-Endpunkts; dabei kein -Upload und keine Ausgabe von Schlüsselinhalten. Live-Seite und anonymer Zugriffsschutz -nach Release geprüft; persönliche erneute Upload-Abnahme bleibt beim Benutzer. - -Aktueller Folgestand: [Zugangstest und Deployment-Vorbereitung](deployment-preparation.md). Die oben beschriebene ursprüngliche Ablage wird jetzt um interne Secret-Lesezugriffe ausschließlich für autorisierte Prüfungen erweitert; Rohschlüssel bleiben für den Browser unzugänglich. + UUIDs are generated/validated server-side. Secret data binds tenant, user, + profile and type; no GitHub session binding, so profiles survive a new login. +- The UI sends the file only on explicit save over HTTPS. No Git commit, + browser storage, query parameter or secret download endpoint. The + file input is cleared after the attempt; navigation/sign-out removes the + component. JavaScript does not guarantee physical memory erasure. +- GET lists metadata. POST and DELETE require session, exact origin and CSRF. + `Cache-Control: no-store`; no body/secret/parser errors in application logs. +- Maximum 20 profiles per user and tenant; concurrent creation is + serialized by a PostgreSQL advisory lock during reservation. UI file limit 24 KiB, + API body limit 32 KiB. No automatic POST retry. + +The app user has the already approved instance-wide Secrets Manager permissions. +Personal secret separation is implemented through backend paths, session and database RLS; +there are not yet separate Vault policies per tenant. A +compromised backend therefore remains inside the trust boundary. + + +## Errors and deletion + +Before writing the secret, a `pending` metadata record is durably reserved. +A transaction then locks exactly this row, writes with Vault CAS `0` and +sets `stored` on success. Create/Delete cannot thereby remove the same profile +from each other while writing. After a crash or ambiguous response, +at least the metadata record remains for cleanup. `pending` means +unusable; the UI offers deletion and recreation, not blind retry. + +Deletion locks the authorized row, first removes Vault metadata including +all secret versions, then the DB record. A 404 during secret deletion counts as +already removed. An interruption may leave a metadata record whose secret is already +missing; deletion is repeatable. A future Runner must therefore never rely solely +on `stored`, but must recheck existence, secret identity and authorization before +every use. There is not yet Runner access to these profiles. +Vault login tokens are revoked after every operation, including failures. + + +## Acceptance and further work + +- [x] Check key file formally and cryptographically locally. +- [x] Create, list and delete personal profiles; no key read endpoint. +- [x] Session/CSRF/identity injection and secret-path negative tests. +- [x] Real PostgreSQL: other tenants, other owners within the same tenant, + missing role, no secret in metadata and repeatable error cleanup. +- [x] Qualify feature-branch release including migration on lzc-dev. +- [x] Qualify personal profile through the live UI (user confirmation). +- [x] Add STACKIT authentication and read-only organization check; [flow and acceptance](deployment-preparation.md). +- [x] Bind fixed Accelerator reference and immutable configuration in a preparation; cloud/Plan qualification remains open. +- [ ] Add customer-specific remote state, Runner, queue, Plan and explicit Apply. +- [ ] Expand rotation, automatic cleanup, audit events and delegations. + +The operator key file from the repository root is not imported as a user profile. +Local tests use only generated or artificial test keys. + + +## Technical release acceptance + +Code commit `629fab6` on `feature/landing-zone-configurator`. +[Validation 36706267168](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36706267168) +and [release 36706267163](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36706267163) +successful. 38 application tests, nine real PostgreSQL tests and 14 browser cases +passed. Migration and CF connection tests to PostgreSQL and Secrets Manager green. +Mobile profile management visually checked using the test screenshot. +Live confirmed: `/credentials`, reload, mobile width, no browser errors and +401 for anonymous GET/POST/DELETE. No real key uploaded for live acceptance; +the user's personal upload remains a separate acceptance item. + + +## Correction: current STACKIT Accounts key format + +The original audience allowlist considered only the older service-account +hosts and rejected valid files with `credentials.aud = https://accounts.stackit.cloud`. +Validation now also accepts this audience and preserves the optional +`credentials.tokenEndpoint`, especially `https://accounts.stackit.cloud/oauth/v2/token`. +Only explicitly known HTTPS endpoints are allowed; no arbitrary upload URLs. +Regression test: current format accepted and passed completely to the secret store; +manipulated token endpoints rejected. Existing older files +without `tokenEndpoint` remain supported. A rejected upload triggered no profile +or secret write operation. + +Sources: [STACKIT token retrieval](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/get-access-token/), +[SDK support for tokenEndpoint](https://github.com/stackitcloud/stackit-sdk-go/releases/). + +Fix acceptance: commit `6c95098`, [validation 36711832436](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36711832436) +and [release 36711832452](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36711832452) +successful. 39 application tests green. The existing local STACKIT key file +passes format validation including token endpoint preservation; no +upload or key content output. Live page and anonymous access protection +checked after release; personal repeat upload acceptance remains with the user. + +Current follow-up: [Credential check and deployment preparation](deployment-preparation.md). The original storage described above is now extended with internal secret reads exclusively for authorized checks; raw keys remain inaccessible to the browser. diff --git a/landing-zone-configurator/docs/deployment-preparation.de.md b/landing-zone-configurator/docs/deployment-preparation.de.md new file mode 100644 index 0000000..59a7e6c --- /dev/null +++ b/landing-zone-configurator/docs/deployment-preparation.de.md @@ -0,0 +1,197 @@ + + +# Zugang prüfen und Deployment vorbereiten + +[English](deployment-preparation.md) | [Deutsch](deployment-preparation.de.md) + +Stand: 2026-09-30. Drei zusammenhängende Schritte: persönliche Anmeldung prüfen, +Zielorganisation lesend prüfen und eine unveränderliche Vorbereitung speichern. + + + +## Prüfliste für die Benutzerabnahme + +- [ ] **Deployment-Zugänge:** Beim gespeicherten Profil die UUID der Zielorganisation + eintragen und **Zugang prüfen** wählen. Ergebnis und Prüfzeit bleiben nach Reload + sichtbar. Die Datei muss dafür nicht erneut hochgeladen werden. +- [ ] Bei fehlender Berechtigung erscheint ein klarer Organisationszugriffsfehler; + ein abgelehnter/abgelaufener Schlüssel erhält einen anderen Fehler. Ein Fehler + ersetzt einen früheren erfolgreichen Profil-Prüfstatus. +- [ ] In **GitHub-Forks** den Fork auswählen und bei einer gespeicherten Konfiguration + **Deployment vorbereiten** wählen. Name, Git-Version und Zielorganisation prüfen. + Ein ungespeicherter lokaler Entwurf wird nicht verwendet. +- [ ] Persönlichen Zugang auswählen und **Zugang prüfen und Vorbereitung speichern** + wählen. Nach erfolgreichem frischem Organisationstest erscheint die Vorbereitung + unter **Deployments**, auch nach Reload. +- [ ] Unter **Versionsnachweise** Konfigurations-Commit, Accelerator-Referenz und + tfvars-Prüfsumme ansehen. Ein späterer Fork-Commit ändert diesen Stand nicht. +- [ ] Eine Test-Vorbereitung entfernen. Das löscht weder Konfiguration noch Ressourcen. + Optional einen ausschließlich zum Testen angelegten Zugang löschen: vorhandene + Vorbereitungen müssen danach „Zugang gelöscht“ anzeigen. + + + +## Was der Zugangstest nachweist + +Das Backend liest nur das eigene, vollständig gespeicherte Credential-Profil unter +RLS und Zeilensperre. Es verlangt die Rolle `admin` oder `deployer`, liest das Secret +und vergleicht Mandant, Eigentümer, Profil, Typ, Key-ID und Service-Account. Die +Secret-Version wird mitgeführt. Es gibt weiterhin keinen Schlüssel-Leseendpunkt für +Browser oder Benutzer-API. + +Ein RS512-signierter JWT mit `kid`, `iss`, `sub`, `aud`, zufälligem `jti` und maximal +zehn Minuten Gültigkeit wird an einen explizit zugelassenen STACKIT-Token-Endpunkt +gesendet. Feste HTTPS-Ziele, keine Redirects, jeweils 15 Sekunden Timeout. Access Token +und Assertion bleiben im Backend-Speicher; sie werden nicht in DB, Logs, Browser, +Git oder Manifest geschrieben. Es erfolgt kein Refresh-/Token-Cache. + +Danach liest das Backend ausschließlich +`GET https://resource-manager.api.stackit.cloud/v2/organizations/`. +Die Antwort muss die angefragte Organisations-ID und den Status `ACTIVE` enthalten. +Ein erfolgreicher Test bestätigt Anmeldung und `resource-manager.organization.get`; +**keine** Schreibrechte, Projekt-Erstellung, Dienstaktivierung, Plan- oder Apply-Rechte. +Auch `stored` oder ein älteres positives Prüfergebnis sind keine Deployment-Freigabe. + +Quellen: [STACKIT Token-Abruf](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/get-access-token/), +[offizieller Resource-Manager-Client](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/resourcemanager/api_default.go), +[Organisationsantwort](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/resourcemanager/model_organization_response.go). + +Lesender Protokolltest mit dem vorhandenen **Betreiber-/Projekt-Service-Account**: +Token-Abruf HTTP 200, Lesen der konfigurierten Organisation HTTP 403. Dafür werden +Rechte auf der Zielorganisation benötigt; Projektzugriff allein reicht für diese +Prüfung nicht. Keine automatische Rechteausweitung und kein Import dieses Schlüssels +als Kundenprofil. Dieser Test ist kein Nachweis für die Rechte eines anderen, vom +Benutzer hochgeladenen Profils. + + + +## Unveränderliche Vorbereitung + +1. Berechtigung und Eigentum am Credential-Profil serverseitig prüfen. +2. GitHub-Benutzertoken aus der Session verwenden; Repository-ID, Herkunft und + aktuellen Fork-Zugriff erneut prüfen. Kein Betreiber- oder Installation-Token. +3. Den gewählten Head von `lzc/configurations` bestätigen und Git-Tree sowie + `landing-zone.json` über unveränderliche Objekt-IDs lesen. Andere Revisionen + werden nicht still übernommen. +4. Fachmodell und Template-Hash validieren. Vorhandene `landing-zone.tfvars` muss + ein regulärer Blob sein und exakt dem deterministischen Export entsprechen. + Fehlende oder manuell veränderte Exporte blockieren die Vorbereitung. +5. Zielorganisation ausschließlich aus dem validierten Git-Dokument übernehmen; + die API akzeptiert kein separates Ziel und keinen frei gewählten Accelerator-Code. +6. Den persönlichen STACKIT-Zugang erneut prüfen. Nur bei Erfolg Manifest speichern. + Nach den externen Anfragen Profilbestand und Rechte nochmals überprüfen. + +`lzc.deployment_preparations` enthält Eigentümer/Mandant und einen unveränderlichen +Snapshot aus Fachkonfiguration, Repository/Branch/Commit, SHA-256 der tfvars, +Export-/Schema-Version, festem Accelerator-Referenzcommit, Credential-ID/Secret-Version, +Key-ID, Organisation und Prüfergebnis. Maximal 100 Vorbereitungen pro Eigentümer und +Mandant. Keine Update-Berechtigung für die Runtime; Entfernen ist möglich. Forced RLS +verhindert Zugriff fremder Benutzer auch im selben Mandanten und die Verknüpfung +fremder Credential-Profile. + +Accelerator-Referenz ist explizit `a256f6896d11134fdc351786f1be5eba4e56b2e2` aus +`stackitcloud/stackit-landing-zone`. Dies friert den Codebezug ein; es ist noch keine +Cloud-/Plan-Qualifizierung dieses Stands. Der Benutzer-Fork liefert nur Konfigurationsdaten. +Ein späterer Runner benötigt einen weitergehenden freigegebenen Laufvertrag. + +Wird ein Credential gelöscht, setzt der Fremdschlüssel die aktive Profilbindung +auf `NULL`; der historische Manifestnachweis bleibt erhalten. Die UI zeigt die +Vorbereitung als nicht verwendbar. Rechte können sich ebenfalls ändern: Vor jedem +künftigen Plan/Apply müssen Zugriff, Secret-Version und Ziel erneut geprüft werden. + + + +## Lokaler Platform-Upgrade-Plan + +Ergänzung vom 2026-10-06: Die gewöhnliche Vorbereitung bleibt auf `a256f68` +gebunden. Für den Contract-Output kann eine zusätzliche Vorbereitung ausdrücklich +den fest qualifizierten Commit `c4b43c36af198985980b17626c48d357795e3fbd` wählen. +Das ist derzeit ein lokaler, opt-in Laufpfad, keine allgemeine Source-Auswahl und +keine Produktionsfreigabe. + +Das neue Paket wird mit `LZC_LOCAL_RUNNER_PACKAGE=true`, +`LZC_PACKAGE_PLATFORM_UPGRADE_ROOT=true` und einem neuen +`LZC_RUNNER_PACKAGE_DIR` erstellt. Bestehende Verzeichnisse werden nicht überschrieben. +Die Source-Metadatei `platform-source.json` wird strikt validiert und gehört zum +Paket-Fingerprint. Der Runner akzeptiert nur den dazu passenden Quellcommit; +gespeicherte Plans eines anderen Pakets bleiben ungültig für diesen Runner. + +`POST /api/v1/preparations` verwendet die vorhandene gespeicherte Konfiguration, +Revision und das eigene Credential-Profil. Die zusätzliche Auswahl lautet: + +```json +{ + "platformUpgrade": { + "confirm": true, + "acceleratorCommit": "c4b43c36af198985980b17626c48d357795e3fbd" + } +} +``` + +Der Server verlangt ein passendes qualifiziertes Paket sowie einen bestehenden, +entsperrten S3-State. Fremde Revisionen, zusätzliche Namespace-/Tenant-Felder und +abweichende Backend-Bindungen werden abgelehnt. Die neue Vorbereitung verwendet +denselben State und dieselbe Konfiguration. Alte Manifeste, Artefakte, Revisionen +und Freigaben werden nicht umgeschrieben. + +Der Contract-Namensraum stammt aus der authentifizierten Serversitzung und ist Teil +des exakten neuen tfvars-Hashes. Die API lockert ihre Tenant-/Organisationsprüfung +nicht. Im unabhängigen Accelerator bleibt der optionale CLI-Namensraum erhalten; +es entsteht keine Configurator-Laufzeitabhängigkeit. + +Erst ein neuer vollständiger, gespeicherter echter Plan zeigt die tatsächlichen +Ressourcen-/Output-Änderungen. Auch ein reiner Output-Plan benötigt eine ausdrückliche +Freigabe seines konkreten SHA-256. Abgelaufene Plans werden weder verlängert noch +angewendet; ein neuer Plan braucht eine eigene Freigabe. Ein Apply wird nicht +automatisch wiederholt. + + + +## Bewusste Grenze und nächste Schritte + +Diese Vorbereitung ist **kein OpenTofu-Plan**, kein genehmigtes Deployment und kein +fertiger Runner-Auftrag. Es werden keine Kundenressourcen angelegt. Offene Aufgaben: + +- [ ] Kundenbezogenen Remote State und Backend-Zugänge konfigurieren. +- [ ] Isolierte Runner, Queue, Abbruch und Wiederanlauf ohne doppelten Apply. +- [ ] Vollständiger Laufvertrag mit Engine/Provider-Lockfile und Artefakt-Digests. +- [ ] `init`, `validate`, `plan`, redigierte Plan-Darstellung und exakte Apply-Freigabe. +- [ ] Mehrmandanten-/Quoten-, Audit-, Ablauf- und Rotationserweiterungen. + + + +## Technische Abnahme + +- [x] JWT-Signatur, Claims, neue `jti`, feste Endpunkte und negative Cloud-Antworten getestet. +- [x] Secret-Identität und Version geprüft, keine Roh-Secrets in Ergebnis oder Manifest. +- [x] Veralteter Git-Head sowie fehlende/manuell geänderte tfvars werden abgewiesen. +- [x] Echtes PostgreSQL: RLS, Rollen, unveränderliche Vorbereitung und Löschinvalidierung. +- [x] Browserablauf auf Desktop und Mobil abgenommen; mobile Darstellung visuell geprüft. +- [x] Feature-Branch-Release inklusive Migration und CF-Verbindungstests. +- [x] Persönlicher Erfolgsfall mit einem auf der Zielorganisation berechtigten Profil (Benutzer bestätigt, 2026-09-30). + + + +### Release-Abnahme + +Code-Commit `366cc3c`, [Validierung 36716027326](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36716027326) +und [Release 36716027274](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36716027274) +erfolgreich. 47 Anwendungstests, zehn PostgreSQL-Tests und 16 Browserfälle grün. +Migration und CF-Verbindungstests zu PostgreSQL und Secrets Manager erfolgreich. +Live geprüft: `/deployments`, Reload, mobile Breite, keine Browserfehler sowie 401 +für anonyme Vorbereitungsliste, Anlegen, Entfernen und Credential-Prüfung. Dabei keine +persönlichen Credentials verwendet und keine Vorbereitung angelegt. Bekannte lokale +Credential-Werte wurden in den Release-Logs nicht gefunden. Der Benutzer hat anschließend die vollständige Vorbereitung und den Zugangstest mit +einer passenden Kombination aus Organisation und persönlichem Service Account bestätigt. +Die zuvor beobachtete Ablehnung war auf eine nicht passende Kombination zurückzuführen. +Die übrigen einzelnen Prüfpunkte gelten dadurch nicht automatisch als abgenommen. + + + +## Freigabegrenze für die nächste Phase + +Benutzerentscheidung vom 2026-09-30: Kunden-Plan darf getestet werden. Jeder +Kunden-Apply benötigt eine neue ausdrückliche Freigabe des Benutzers. Die bestehende +Freigabe für Configurator-Infrastruktur gilt nicht für Kundenressourcen. Kein Destroy; +der Benutzer weist auf die derzeit fehlende Möglichkeit zum Folder-Destroy hin. +Weiterarbeit und offene Voraussetzungen: [Plan-Ausführung](plan-execution.de.md). diff --git a/landing-zone-configurator/docs/deployment-preparation.md b/landing-zone-configurator/docs/deployment-preparation.md index 6651bb9..9799a93 100644 --- a/landing-zone-configurator/docs/deployment-preparation.md +++ b/landing-zone-configurator/docs/deployment-preparation.md @@ -1,111 +1,118 @@ -# Zugang prüfen und Deployment vorbereiten - -Stand: 2026-09-30. Drei zusammenhängende Schritte: persönliche Anmeldung prüfen, -Zielorganisation lesend prüfen und eine unveränderliche Vorbereitung speichern. - -## Prüfliste für die Benutzerabnahme - -- [ ] **Deployment-Zugänge:** Beim gespeicherten Profil die UUID der Zielorganisation - eintragen und **Zugang prüfen** wählen. Ergebnis und Prüfzeit bleiben nach Reload - sichtbar. Die Datei muss dafür nicht erneut hochgeladen werden. -- [ ] Bei fehlender Berechtigung erscheint ein klarer Organisationszugriffsfehler; - ein abgelehnter/abgelaufener Schlüssel erhält einen anderen Fehler. Ein Fehler - ersetzt einen früheren erfolgreichen Profil-Prüfstatus. -- [ ] In **GitHub-Forks** den Fork auswählen und bei einer gespeicherten Konfiguration - **Deployment vorbereiten** wählen. Name, Git-Version und Zielorganisation prüfen. - Ein ungespeicherter lokaler Entwurf wird nicht verwendet. -- [ ] Persönlichen Zugang auswählen und **Zugang prüfen und Vorbereitung speichern** - wählen. Nach erfolgreichem frischem Organisationstest erscheint die Vorbereitung - unter **Deployments**, auch nach Reload. -- [ ] Unter **Versionsnachweise** Konfigurations-Commit, Accelerator-Referenz und - tfvars-Prüfsumme ansehen. Ein späterer Fork-Commit ändert diesen Stand nicht. -- [ ] Eine Test-Vorbereitung entfernen. Das löscht weder Konfiguration noch Ressourcen. - Optional einen ausschließlich zum Testen angelegten Zugang löschen: vorhandene - Vorbereitungen müssen danach „Zugang gelöscht“ anzeigen. - -## Was der Zugangstest nachweist - -Das Backend liest nur das eigene, vollständig gespeicherte Credential-Profil unter -RLS und Zeilensperre. Es verlangt die Rolle `admin` oder `deployer`, liest das Secret -und vergleicht Mandant, Eigentümer, Profil, Typ, Key-ID und Service-Account. Die -Secret-Version wird mitgeführt. Es gibt weiterhin keinen Schlüssel-Leseendpunkt für -Browser oder Benutzer-API. - -Ein RS512-signierter JWT mit `kid`, `iss`, `sub`, `aud`, zufälligem `jti` und maximal -zehn Minuten Gültigkeit wird an einen explizit zugelassenen STACKIT-Token-Endpunkt -gesendet. Feste HTTPS-Ziele, keine Redirects, jeweils 15 Sekunden Timeout. Access Token -und Assertion bleiben im Backend-Speicher; sie werden nicht in DB, Logs, Browser, -Git oder Manifest geschrieben. Es erfolgt kein Refresh-/Token-Cache. - -Danach liest das Backend ausschließlich + +# Check credentials and prepare deployment + +[English](deployment-preparation.md) | [Deutsch](deployment-preparation.de.md) + +As of 2026-09-30. Three connected steps: check personal authentication, +check the target organization read-only and save an immutable preparation. + + +## User acceptance checklist + +- [ ] **Deployment credentials:** enter the target organization UUID for the saved + profile and select **Check credentials**. Result and check time remain visible after + reload. The file does not need to be uploaded again. +- [ ] Missing permission produces a clear organization-access error; + a rejected/expired key receives a different error. An error + replaces an earlier successful profile check status. +- [ ] In **GitHub forks**, select the fork and choose **Prepare deployment** + for a saved configuration. Check name, Git version and target organization. + An unsaved local draft is not used. +- [ ] Select personal credentials and choose **Check credentials and save preparation**. + After a successful fresh organization check, the preparation appears + under **Deployments**, including after reload. +- [ ] Under **Version evidence**, inspect configuration commit, Accelerator reference and + tfvars checksum. A later fork commit does not change this snapshot. +- [ ] Remove a test preparation. This deletes neither configuration nor resources. + Optionally delete credentials created solely for testing: existing + preparations must then display “Credentials deleted”. + + +## What the credential check proves + +The backend reads only the user's own fully stored credential profile under +RLS and row lock. It requires the `admin` or `deployer` role, reads the secret +and compares tenant, owner, profile, type, key ID and service account. The +secret version is carried along. There is still no key read endpoint for +the browser or user API. + +An RS512-signed JWT with `kid`, `iss`, `sub`, `aud`, random `jti` and at most +ten minutes validity is sent to an explicitly allowlisted STACKIT token endpoint. +Fixed HTTPS targets, no redirects, 15-second timeout each. Access token +and assertion remain in backend memory; they are not written to DB, logs, browser, +Git or manifest. No refresh/token cache. + +Then the backend reads only `GET https://resource-manager.api.stackit.cloud/v2/organizations/`. -Die Antwort muss die angefragte Organisations-ID und den Status `ACTIVE` enthalten. -Ein erfolgreicher Test bestätigt Anmeldung und `resource-manager.organization.get`; -**keine** Schreibrechte, Projekt-Erstellung, Dienstaktivierung, Plan- oder Apply-Rechte. -Auch `stored` oder ein älteres positives Prüfergebnis sind keine Deployment-Freigabe. - -Quellen: [STACKIT Token-Abruf](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/get-access-token/), -[offizieller Resource-Manager-Client](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/resourcemanager/api_default.go), -[Organisationsantwort](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/resourcemanager/model_organization_response.go). - -Lesender Protokolltest mit dem vorhandenen **Betreiber-/Projekt-Service-Account**: -Token-Abruf HTTP 200, Lesen der konfigurierten Organisation HTTP 403. Dafür werden -Rechte auf der Zielorganisation benötigt; Projektzugriff allein reicht für diese -Prüfung nicht. Keine automatische Rechteausweitung und kein Import dieses Schlüssels -als Kundenprofil. Dieser Test ist kein Nachweis für die Rechte eines anderen, vom -Benutzer hochgeladenen Profils. - -## Unveränderliche Vorbereitung - -1. Berechtigung und Eigentum am Credential-Profil serverseitig prüfen. -2. GitHub-Benutzertoken aus der Session verwenden; Repository-ID, Herkunft und - aktuellen Fork-Zugriff erneut prüfen. Kein Betreiber- oder Installation-Token. -3. Den gewählten Head von `lzc/configurations` bestätigen und Git-Tree sowie - `landing-zone.json` über unveränderliche Objekt-IDs lesen. Andere Revisionen - werden nicht still übernommen. -4. Fachmodell und Template-Hash validieren. Vorhandene `landing-zone.tfvars` muss - ein regulärer Blob sein und exakt dem deterministischen Export entsprechen. - Fehlende oder manuell veränderte Exporte blockieren die Vorbereitung. -5. Zielorganisation ausschließlich aus dem validierten Git-Dokument übernehmen; - die API akzeptiert kein separates Ziel und keinen frei gewählten Accelerator-Code. -6. Den persönlichen STACKIT-Zugang erneut prüfen. Nur bei Erfolg Manifest speichern. - Nach den externen Anfragen Profilbestand und Rechte nochmals überprüfen. - -`lzc.deployment_preparations` enthält Eigentümer/Mandant und einen unveränderlichen -Snapshot aus Fachkonfiguration, Repository/Branch/Commit, SHA-256 der tfvars, -Export-/Schema-Version, festem Accelerator-Referenzcommit, Credential-ID/Secret-Version, -Key-ID, Organisation und Prüfergebnis. Maximal 100 Vorbereitungen pro Eigentümer und -Mandant. Keine Update-Berechtigung für die Runtime; Entfernen ist möglich. Forced RLS -verhindert Zugriff fremder Benutzer auch im selben Mandanten und die Verknüpfung -fremder Credential-Profile. - -Accelerator-Referenz ist explizit `a256f6896d11134fdc351786f1be5eba4e56b2e2` aus -`stackitcloud/stackit-landing-zone`. Dies friert den Codebezug ein; es ist noch keine -Cloud-/Plan-Qualifizierung dieses Stands. Der Benutzer-Fork liefert nur Konfigurationsdaten. -Ein späterer Runner benötigt einen weitergehenden freigegebenen Laufvertrag. - -Wird ein Credential gelöscht, setzt der Fremdschlüssel die aktive Profilbindung -auf `NULL`; der historische Manifestnachweis bleibt erhalten. Die UI zeigt die -Vorbereitung als nicht verwendbar. Rechte können sich ebenfalls ändern: Vor jedem -künftigen Plan/Apply müssen Zugriff, Secret-Version und Ziel erneut geprüft werden. - -## Lokaler Platform-Upgrade-Plan - -Ergänzung vom 2026-10-06: Die gewöhnliche Vorbereitung bleibt auf `a256f68` -gebunden. Für den Contract-Output kann eine zusätzliche Vorbereitung ausdrücklich -den fest qualifizierten Commit `c4b43c36af198985980b17626c48d357795e3fbd` wählen. -Das ist derzeit ein lokaler, opt-in Laufpfad, keine allgemeine Source-Auswahl und -keine Produktionsfreigabe. - -Das neue Paket wird mit `LZC_LOCAL_RUNNER_PACKAGE=true`, -`LZC_PACKAGE_PLATFORM_UPGRADE_ROOT=true` und einem neuen -`LZC_RUNNER_PACKAGE_DIR` erstellt. Bestehende Verzeichnisse werden nicht überschrieben. -Die Source-Metadatei `platform-source.json` wird strikt validiert und gehört zum -Paket-Fingerprint. Der Runner akzeptiert nur den dazu passenden Quellcommit; -gespeicherte Plans eines anderen Pakets bleiben ungültig für diesen Runner. - -`POST /api/v1/preparations` verwendet die vorhandene gespeicherte Konfiguration, -Revision und das eigene Credential-Profil. Die zusätzliche Auswahl lautet: +The response must contain the requested organization ID and `ACTIVE` status. +A successful check confirms authentication and `resource-manager.organization.get`; +**not** write permissions, project creation, service activation, Plan or Apply rights. +Neither `stored` nor an older positive check result is deployment approval. + +Sources: [STACKIT token retrieval](https://docs.stackit.cloud/platform/access-and-identity/service-accounts/how-tos/get-access-token/), +[official Resource Manager client](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/resourcemanager/api_default.go), +[organization response](https://github.com/stackitcloud/stackit-sdk-go/blob/main/services/resourcemanager/model_organization_response.go). + +Read-only protocol test with the existing **operator/project service account**: +token retrieval HTTP 200, reading the configured organization HTTP 403. This requires +permissions on the target organization; project access alone is insufficient +for this check. No automatic permission expansion and no import of this key +as a customer profile. This test does not prove permissions for another profile +uploaded by the user. + + +## Immutable preparation + +1. Check permission and ownership of the credential profile server-side. +2. Use the GitHub user token from the session; recheck repository ID, origin and + current fork access. No operator or installation token. +3. Confirm the selected head of `lzc/configurations` and read Git tree and + `landing-zone.json` through immutable object IDs. Other revisions + are not silently adopted. +4. Validate domain model and template hash. Existing `landing-zone.tfvars` must + be a regular blob and exactly match deterministic export. + Missing or manually changed exports block preparation. +5. Take the target organization exclusively from the validated Git document; + the API accepts neither a separate target nor freely selected Accelerator code. +6. Check personal STACKIT credentials again. Save the manifest only on success. + After external requests, recheck profile existence and permissions. + +`lzc.deployment_preparations` contains owner/tenant and an immutable +snapshot of domain configuration, repository/branch/commit, SHA-256 of tfvars, +export/schema version, fixed Accelerator reference commit, credential ID/secret version, +key ID, organization and check result. Maximum 100 preparations per owner and +tenant. No update permission for runtime; removal is possible. Forced RLS +prevents access by other users even within the same tenant and linking +others' credential profiles. + +The Accelerator reference is explicitly `a256f6896d11134fdc351786f1be5eba4e56b2e2` from +`stackitcloud/stackit-landing-zone`. This freezes the code reference; it is not yet +cloud/Plan qualification of this revision. The user's fork supplies configuration data only. +A later Runner requires a more comprehensive approved execution contract. + +When a credential is deleted, the foreign key sets the active profile binding +to `NULL`; historical manifest evidence remains. The UI shows the +preparation as unusable. Permissions can also change: before every +future Plan/Apply, access, secret version and target must be checked again. + + +## Local platform upgrade Plan + +Addition from 2026-10-06: ordinary preparation remains bound to `a256f68`. +For contract output, an additional preparation can explicitly +select the fixed qualified commit `c4b43c36af198985980b17626c48d357795e3fbd`. +This is currently a local opt-in execution path, not general source selection or +production approval. + +The new package is built with `LZC_LOCAL_RUNNER_PACKAGE=true`, +`LZC_PACKAGE_PLATFORM_UPGRADE_ROOT=true` and a new +`LZC_RUNNER_PACKAGE_DIR`. Existing directories are not overwritten. +The source metadata file `platform-source.json` is strictly validated and part of +the package fingerprint. The Runner accepts only the matching source commit; +saved Plans from another package remain invalid for this Runner. + +`POST /api/v1/preparations` uses the existing saved configuration, +revision and own credential profile. The additional selection is: ```json { @@ -116,62 +123,66 @@ Revision und das eigene Credential-Profil. Die zusätzliche Auswahl lautet: } ``` -Der Server verlangt ein passendes qualifiziertes Paket sowie einen bestehenden, -entsperrten S3-State. Fremde Revisionen, zusätzliche Namespace-/Tenant-Felder und -abweichende Backend-Bindungen werden abgelehnt. Die neue Vorbereitung verwendet -denselben State und dieselbe Konfiguration. Alte Manifeste, Artefakte, Revisionen -und Freigaben werden nicht umgeschrieben. - -Der Contract-Namensraum stammt aus der authentifizierten Serversitzung und ist Teil -des exakten neuen tfvars-Hashes. Die API lockert ihre Tenant-/Organisationsprüfung -nicht. Im unabhängigen Accelerator bleibt der optionale CLI-Namensraum erhalten; -es entsteht keine Configurator-Laufzeitabhängigkeit. - -Erst ein neuer vollständiger, gespeicherter echter Plan zeigt die tatsächlichen -Ressourcen-/Output-Änderungen. Auch ein reiner Output-Plan benötigt eine ausdrückliche -Freigabe seines konkreten SHA-256. Abgelaufene Plans werden weder verlängert noch -angewendet; ein neuer Plan braucht eine eigene Freigabe. Ein Apply wird nicht -automatisch wiederholt. - -## Bewusste Grenze und nächste Schritte - -Diese Vorbereitung ist **kein OpenTofu-Plan**, kein genehmigtes Deployment und kein -fertiger Runner-Auftrag. Es werden keine Kundenressourcen angelegt. Offene Aufgaben: - -- [ ] Kundenbezogenen Remote State und Backend-Zugänge konfigurieren. -- [ ] Isolierte Runner, Queue, Abbruch und Wiederanlauf ohne doppelten Apply. -- [ ] Vollständiger Laufvertrag mit Engine/Provider-Lockfile und Artefakt-Digests. -- [ ] `init`, `validate`, `plan`, redigierte Plan-Darstellung und exakte Apply-Freigabe. -- [ ] Mehrmandanten-/Quoten-, Audit-, Ablauf- und Rotationserweiterungen. - -## Technische Abnahme - -- [x] JWT-Signatur, Claims, neue `jti`, feste Endpunkte und negative Cloud-Antworten getestet. -- [x] Secret-Identität und Version geprüft, keine Roh-Secrets in Ergebnis oder Manifest. -- [x] Veralteter Git-Head sowie fehlende/manuell geänderte tfvars werden abgewiesen. -- [x] Echtes PostgreSQL: RLS, Rollen, unveränderliche Vorbereitung und Löschinvalidierung. -- [x] Browserablauf auf Desktop und Mobil abgenommen; mobile Darstellung visuell geprüft. -- [x] Feature-Branch-Release inklusive Migration und CF-Verbindungstests. -- [x] Persönlicher Erfolgsfall mit einem auf der Zielorganisation berechtigten Profil (Benutzer bestätigt, 2026-09-30). - -### Release-Abnahme - -Code-Commit `366cc3c`, [Validierung 36716027326](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36716027326) -und [Release 36716027274](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36716027274) -erfolgreich. 47 Anwendungstests, zehn PostgreSQL-Tests und 16 Browserfälle grün. -Migration und CF-Verbindungstests zu PostgreSQL und Secrets Manager erfolgreich. -Live geprüft: `/deployments`, Reload, mobile Breite, keine Browserfehler sowie 401 -für anonyme Vorbereitungsliste, Anlegen, Entfernen und Credential-Prüfung. Dabei keine -persönlichen Credentials verwendet und keine Vorbereitung angelegt. Bekannte lokale -Credential-Werte wurden in den Release-Logs nicht gefunden. Der Benutzer hat anschließend die vollständige Vorbereitung und den Zugangstest mit -einer passenden Kombination aus Organisation und persönlichem Service Account bestätigt. -Die zuvor beobachtete Ablehnung war auf eine nicht passende Kombination zurückzuführen. -Die übrigen einzelnen Prüfpunkte gelten dadurch nicht automatisch als abgenommen. - -## Freigabegrenze für die nächste Phase - -Benutzerentscheidung vom 2026-09-30: Kunden-Plan darf getestet werden. Jeder -Kunden-Apply benötigt eine neue ausdrückliche Freigabe des Benutzers. Die bestehende -Freigabe für Configurator-Infrastruktur gilt nicht für Kundenressourcen. Kein Destroy; -der Benutzer weist auf die derzeit fehlende Möglichkeit zum Folder-Destroy hin. -Weiterarbeit und offene Voraussetzungen: [Plan-Ausführung](plan-execution.md). +The server requires a matching qualified package and an existing, +unlocked S3 state. Other revisions, extra namespace/tenant fields and +different backend bindings are rejected. The new preparation uses +the same state and configuration. Old manifests, artifacts, revisions +and approvals are not rewritten. + +The contract namespace comes from the authenticated server session and is part of +the exact new tfvars hash. The API does not relax its tenant/organization check. +The optional CLI namespace remains in the independent Accelerator; +no Configurator runtime dependency is introduced. + +Only a new complete saved real Plan shows actual +resource/output changes. Even an output-only Plan requires explicit +approval of its specific SHA-256. Expired Plans are neither extended nor +applied; a new Plan needs its own approval. An Apply is not +automatically retried. + + +## Deliberate boundary and next steps + +This preparation is **not an OpenTofu Plan**, an approved deployment or a +complete Runner job. No customer resources are created. Open tasks: + +- [ ] Configure customer-specific remote state and backend credentials. +- [ ] Isolated Runners, queue, cancellation and restart without duplicate Apply. +- [ ] Complete execution contract with engine/provider lockfile and artifact digests. +- [ ] `init`, `validate`, `plan`, redacted Plan presentation and exact Apply approval. +- [ ] Multi-tenant/quota, audit, expiry and rotation extensions. + + +## Technical acceptance + +- [x] Test JWT signature, claims, new `jti`, fixed endpoints and negative cloud responses. +- [x] Check secret identity and version, no raw secrets in result or manifest. +- [x] Reject stale Git head and missing/manually changed tfvars. +- [x] Real PostgreSQL: RLS, roles, immutable preparation and deletion invalidation. +- [x] Browser flow qualified on desktop and mobile; mobile presentation visually checked. +- [x] Feature-branch release including migration and CF connection tests. +- [x] Personal success case with a profile authorized on the target organization (user confirmed, 2026-09-30). + + +### Release acceptance + +Code commit `366cc3c`, [validation 36716027326](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36716027326) +and [release 36716027274](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36716027274) +successful. 47 application tests, ten PostgreSQL tests and 16 browser cases green. +Migration and CF connection tests to PostgreSQL and Secrets Manager successful. +Live checked: `/deployments`, reload, mobile width, no browser errors and 401 +for anonymous preparation listing, creation, removal and credential checking. No +personal credentials used and no preparation created. Known local +credential values were not found in release logs. The user subsequently confirmed full preparation and credential checking with +a suitable combination of organization and personal service account. +The earlier rejection resulted from a mismatched combination. +The remaining individual checklist items are not automatically accepted thereby. + + +## Approval boundary for the next phase + +User decision from 2026-09-30: customer Plan may be tested. Every +customer Apply needs new explicit user approval. Existing +Configurator infrastructure approval does not apply to customer resources. No Destroy; +the user points out the currently missing folder Destroy option. +Further work and open prerequisites: [Plan execution](plan-execution.md). diff --git a/landing-zone-configurator/docs/design-reference.de.md b/landing-zone-configurator/docs/design-reference.de.md new file mode 100644 index 0000000..052684b --- /dev/null +++ b/landing-zone-configurator/docs/design-reference.de.md @@ -0,0 +1,125 @@ + + +# Designreferenz: offizielles STACKIT Portal + +[English](design-reference.md) | [Deutsch](design-reference.de.md) + +Benutzeranforderung vom 2026-09-30: Look & Feel des Landing Zone Configurators +soll dem offiziellen STACKIT Portal entsprechen. Referenz ist die bereits vom +Benutzer geöffnete Projektstartseite. Kein frei interpretiertes STACKIT-ähnliches +Theme als Ersatz für diesen Abgleich. + + + +## Design-Abnahme + +- [ ] Geöffnete Projektstartseite im Benutzerbrowser ansehen und Referenz erfassen. +- [ ] Portal-Shell: Header, Projekt-/Organisationsauswahl, Navigation, Breadcrumbs und Inhaltsbreite bestimmen. +- [ ] Tatsächliche Farben, Typografie, Schriftgewichte, Abstände, Radien, Rahmen und Schatten dokumentieren. +- [ ] Formulare, Buttons, Karten, Tabellen, Dialoge sowie Fokus-/Fehler-/Disabled-Zustände vergleichen. +- [x] Offizielle Design-Tokens, Fonts und Komponentenquellen über Nebula prüfen. +- [ ] Offizielle Icons und vollständige Komponentenparität integrieren. +- [x] Gemeinsame Formular-/Strukturkomponenten und ausgewählte semantische Tokens im Configurator implementieren. +- [ ] Login, Template-Auswahl, fachlichen Editor und Fork-Auswahl gegen die Referenz visuell abnehmen. +- [ ] Tastaturbedienung, Fokus, Kontrast und schmale Ansichten prüfen. + + + +## Öffentliche Designquellen erfasst (2026-09-30) + +- [x] Portal-HTML, referenzierte Stylesheets und Haupt-JavaScript ohne Login per `curl` abgerufen. +- [x] Originale `--nds-*`-Deklarationen mit Marken-/Theme-Selektoren und Font-Face-Definitionen extrahiert. +- [x] Wiederholbaren Abruf mit Quellen-URLs, UTC-Zeitpunkt und SHA-256 dokumentiert. +- [ ] Aktive Marke, Theme und berechnete Styles der Projektansicht visuell bestätigen. + +Abruf: [Anleitung und Werkzeug](../tools/portal-reference/README.de.md). +Die lokalen Quelldateien liegen unter `.local/portal-reference/` und werden nicht +versioniert. Persönliche Tokens, Cookies oder Projektzugriffe sind dafür unnötig. + +Der erfasste öffentliche [Portal-Stylesheet](https://portal.stackit.cloud/styles-HOVMV7T5.css) +enthält folgende Referenzwerte (Dateiname gilt für diesen Snapshot): + +| Geltungsbereich | Beobachtete Deklaration | +| --- | --- | +| `html.brand--digits` | Fließtext: DIN 2014; Überschriften: Univia Pro | +| `html.brand--digits` | Heller Branding-Header: `#0a1e2dff` | +| `html.brand--digits` | CTA: `#00c2ccff`, Hover `#00b2bcff`, aktiv `#00a2acff` | +| `html.brand--neutral` | Fließtext und Überschriften: Inter | +| `html.brand--schwarz` | Fließtext und Überschriften: Helvetica Now Var | +| Theme-Selektoren | `theme--light`, `theme--dark`, `theme--a11y` | +| Body-Regel | 16 px, Gewicht 400, Zeilenhöhe 1.56; Farben über Theme-Tokens | + +Die HTML-Antwort enthält zunächst nur `html lang="en"`, keine ausgewählte Marke +oder Theme-Klasse. Die Tokens dürfen daher nicht über alle Selektoren hinweg +zusammengeführt werden. Die Extraktion ist kein vollständiger CSS-Parser und +berechnet weder Kaskade noch gerenderte Styles. Für die Anwendung wird ausdrücklich +`digits/light` gewählt. Ein begrenzter semantischer Token-Snapshot erhält die +Viewport-Regeln; Schriftdateien und Logo werden lokal ausgeliefert. +[Asset-Herkunft und Prüfsummen](brand-assets.de.md). Portal-JavaScript wird nicht +in die Anwendung übernommen. + +`curl` liefert die SPA-Quelldateien, aber keine gerenderte, angemeldete +Projektstartseite. Shell-Geometrie, konkrete Komponenten und Interaktionszustände +bleiben deshalb offene Abnahmepunkte. Der frühere Browser-Verbindungsfehler +(fehlende Plugin-Version `26.917.71314`) verhindert den öffentlichen Abruf nicht. + + + +## Unabhängig vorbereitete Arbeit + +- [x] GitHub-App-Registrierungsentwurf mit fester Callback-URL unter `deploy/github/`. +- [x] Reine Auth-Bausteine für S256-PKCE, State-/Browserbindung und sichere Cookie-Ausgabe mit Negativtests. +- [ ] GitHub App registrieren/zuordnen und Benutzerautorisierung konfigurieren. +- [ ] Persistente, atomar konsumierte Login-Vorgänge und serverseitige Sessions implementieren. +- [ ] Mandanten-/Mitgliedschaftsmodell, Migrationen und echte PostgreSQL-RLS-Negativtests. +- [ ] Benutzergebundene GitHub-Tokens geschützt ablegen; ausschließlich damit Repository-Aktionen ausführen. +- [ ] Erster vertikaler Template-bis-Fork-Ablauf mit tatsächlichem Benutzerlogin. + +Die Auth-Helfer sind noch nicht an HTTP-Routen angebunden. Insbesondere ersetzt +ein erfolgreicher State-Vergleich keine atomare Einmalverwendung in PostgreSQL. +Die geschützte API bleibt bis zur vollständigen Integration geschlossen. +Der öffentliche Template-Editor arbeitet ausschließlich mit Repository-Vorlagen +und flüchtigen Entwürfen im aktuellen Browser-Tab. + + + +## Nebula als bestätigte Referenz + +Der Benutzer hat am 2026-09-30 [styleguide.stackit.schwarz](https://styleguide.stackit.schwarz/) +als Referenz angegeben. Die Seiten sind ohne Login abrufbar (Unterseiten mit +abschließendem `/`). Relevante Vorgaben: + +- [Tokens](https://styleguide.stackit.schwarz/foundations/design-tokens/about-tokens/): + semantische Namen verwenden, Marken/Modi getrennt halten. +- [Typografie](https://styleguide.stackit.schwarz/foundations/typography/): + 16-px-Basiseinheit, abgestufte Textstile; lokale Originalschriften. +- [Formulare](https://styleguide.stackit.schwarz/patterns/forms/design/): + ein-/zweispaltiger Wizard, Inline-Fehler und anklickbare Fehlerzusammenfassung. + Download bleibt klickbar und führt bei ungültigen Angaben zum betroffenen Feld. +- [Buttons](https://styleguide.stackit.schwarz/components/buttons/design/): + eine hervorgehobene Hauptaktion pro Aktionsgruppe. +- [Header](https://styleguide.stackit.schwarz/components/header/design/) und + [Navigation](https://styleguide.stackit.schwarz/patterns/side-navigation/design/): + Logo, Kontext und klar markierter aktiver Navigationspunkt. + +Nebula verweist auf eine Angular-Komponentenbibliothek. Diese ist keine direkt +nutzbare React-Abhängigkeit. Der bestätigte React-Stack bleibt für diesen Schritt +bestehen; native semantische Komponenten verwenden den ausgewählten Token-Snapshot. +Vollständige Komponenten- und Verhaltensparität ist damit nicht automatisch erreicht. +Der Configurator zeigt nur seine tatsächlich verfügbaren Funktionen; eine +Projekt-/Regionsauswahl für authentifizierte Benutzer folgt mit dem Login. + +Lokale Abnahme: Browserprüfungen auf 1440 und 390 px, inklusive Suche, +Fehlerfokus, Entwurfsdownload und erfolgreichem Laden beider Originalschriften und +des Logos. Screenshots liegen unter `.local/browser-tests`. Die integrierte +Browser-Verbindung ist weiterhin defekt; deshalb wurden isolierte lokale +Browser-Kontexte verwendet. Ein direkter visueller Vergleich mit der angemeldeten +Portal-Projektstartseite und die vollständige Tastatur-/Kontrastprüfung stehen aus. + + + +## Fachliches Bedienkonzept + +Die [verbindlichen Editor-Designprinzipien](editor-design-principles.de.md) ergänzen +die visuellen Portalreferenzen: offizielle Produktnamen, Komponentenübersicht, +schrittweise Detailanzeige und dokumentationsnahe Abläufe, zunächst für STACKIT VPN. diff --git a/landing-zone-configurator/docs/design-reference.md b/landing-zone-configurator/docs/design-reference.md index 10bcb09..81d5560 100644 --- a/landing-zone-configurator/docs/design-reference.md +++ b/landing-zone-configurator/docs/design-reference.md @@ -1,111 +1,119 @@ -# Designreferenz: offizielles STACKIT Portal + +# Design reference: official STACKIT Portal -Benutzeranforderung vom 2026-09-30: Look & Feel des Landing Zone Configurators -soll dem offiziellen STACKIT Portal entsprechen. Referenz ist die bereits vom -Benutzer geöffnete Projektstartseite. Kein frei interpretiertes STACKIT-ähnliches -Theme als Ersatz für diesen Abgleich. +[English](design-reference.md) | [Deutsch](design-reference.de.md) -## Design-Abnahme +User requirement from 2026-09-30: the look and feel of the Landing Zone Configurator +should match the official STACKIT Portal. The reference is the project home page +already open in the user's browser. No freely interpreted STACKIT-like +theme as a substitute for this comparison. -- [ ] Geöffnete Projektstartseite im Benutzerbrowser ansehen und Referenz erfassen. -- [ ] Portal-Shell: Header, Projekt-/Organisationsauswahl, Navigation, Breadcrumbs und Inhaltsbreite bestimmen. -- [ ] Tatsächliche Farben, Typografie, Schriftgewichte, Abstände, Radien, Rahmen und Schatten dokumentieren. -- [ ] Formulare, Buttons, Karten, Tabellen, Dialoge sowie Fokus-/Fehler-/Disabled-Zustände vergleichen. -- [x] Offizielle Design-Tokens, Fonts und Komponentenquellen über Nebula prüfen. -- [ ] Offizielle Icons und vollständige Komponentenparität integrieren. -- [x] Gemeinsame Formular-/Strukturkomponenten und ausgewählte semantische Tokens im Configurator implementieren. -- [ ] Login, Template-Auswahl, fachlichen Editor und Fork-Auswahl gegen die Referenz visuell abnehmen. -- [ ] Tastaturbedienung, Fokus, Kontrast und schmale Ansichten prüfen. + +## Design acceptance -## Öffentliche Designquellen erfasst (2026-09-30) +- [ ] View the open project home page in the user's browser and capture the reference. +- [ ] Determine portal shell: header, project/organization selection, navigation, breadcrumbs and content width. +- [ ] Document actual colors, typography, font weights, spacing, radii, borders and shadows. +- [ ] Compare forms, buttons, cards, tables, dialogs and focus/error/disabled states. +- [x] Check official design tokens, fonts and component sources through Nebula. +- [ ] Integrate official icons and full component parity. +- [x] Implement shared form/structure components and selected semantic tokens in the Configurator. +- [ ] Visually qualify login, template selection, domain editor and fork selection against the reference. +- [ ] Check keyboard operation, focus, contrast and narrow views. -- [x] Portal-HTML, referenzierte Stylesheets und Haupt-JavaScript ohne Login per `curl` abgerufen. -- [x] Originale `--nds-*`-Deklarationen mit Marken-/Theme-Selektoren und Font-Face-Definitionen extrahiert. -- [x] Wiederholbaren Abruf mit Quellen-URLs, UTC-Zeitpunkt und SHA-256 dokumentiert. -- [ ] Aktive Marke, Theme und berechnete Styles der Projektansicht visuell bestätigen. + +## Public design sources captured (2026-09-30) -Abruf: [Anleitung und Werkzeug](../tools/portal-reference/README.md). -Die lokalen Quelldateien liegen unter `.local/portal-reference/` und werden nicht -versioniert. Persönliche Tokens, Cookies oder Projektzugriffe sind dafür unnötig. +- [x] Retrieve portal HTML, referenced stylesheets and main JavaScript without login using `curl`. +- [x] Extract original `--nds-*` declarations with brand/theme selectors and font-face definitions. +- [x] Document repeatable retrieval with source URLs, UTC timestamp and SHA-256. +- [ ] Visually confirm active brand, theme and computed styles of the project view. -Der erfasste öffentliche [Portal-Stylesheet](https://portal.stackit.cloud/styles-HOVMV7T5.css) -enthält folgende Referenzwerte (Dateiname gilt für diesen Snapshot): +Retrieval: [instructions and tool](../tools/portal-reference/README.md). +Local source files are under `.local/portal-reference/` and are not +versioned. Personal tokens, cookies or project access are unnecessary. -| Geltungsbereich | Beobachtete Deklaration | +The captured public [portal stylesheet](https://portal.stackit.cloud/styles-HOVMV7T5.css) +contains these reference values (filename applies to this snapshot): + +| Scope | Observed declaration | | --- | --- | -| `html.brand--digits` | Fließtext: DIN 2014; Überschriften: Univia Pro | -| `html.brand--digits` | Heller Branding-Header: `#0a1e2dff` | -| `html.brand--digits` | CTA: `#00c2ccff`, Hover `#00b2bcff`, aktiv `#00a2acff` | -| `html.brand--neutral` | Fließtext und Überschriften: Inter | -| `html.brand--schwarz` | Fließtext und Überschriften: Helvetica Now Var | -| Theme-Selektoren | `theme--light`, `theme--dark`, `theme--a11y` | -| Body-Regel | 16 px, Gewicht 400, Zeilenhöhe 1.56; Farben über Theme-Tokens | - -Die HTML-Antwort enthält zunächst nur `html lang="en"`, keine ausgewählte Marke -oder Theme-Klasse. Die Tokens dürfen daher nicht über alle Selektoren hinweg -zusammengeführt werden. Die Extraktion ist kein vollständiger CSS-Parser und -berechnet weder Kaskade noch gerenderte Styles. Für die Anwendung wird ausdrücklich -`digits/light` gewählt. Ein begrenzter semantischer Token-Snapshot erhält die -Viewport-Regeln; Schriftdateien und Logo werden lokal ausgeliefert. -[Asset-Herkunft und Prüfsummen](brand-assets.md). Portal-JavaScript wird nicht -in die Anwendung übernommen. - -`curl` liefert die SPA-Quelldateien, aber keine gerenderte, angemeldete -Projektstartseite. Shell-Geometrie, konkrete Komponenten und Interaktionszustände -bleiben deshalb offene Abnahmepunkte. Der frühere Browser-Verbindungsfehler -(fehlende Plugin-Version `26.917.71314`) verhindert den öffentlichen Abruf nicht. - -## Unabhängig vorbereitete Arbeit - -- [x] GitHub-App-Registrierungsentwurf mit fester Callback-URL unter `deploy/github/`. -- [x] Reine Auth-Bausteine für S256-PKCE, State-/Browserbindung und sichere Cookie-Ausgabe mit Negativtests. -- [ ] GitHub App registrieren/zuordnen und Benutzerautorisierung konfigurieren. -- [ ] Persistente, atomar konsumierte Login-Vorgänge und serverseitige Sessions implementieren. -- [ ] Mandanten-/Mitgliedschaftsmodell, Migrationen und echte PostgreSQL-RLS-Negativtests. -- [ ] Benutzergebundene GitHub-Tokens geschützt ablegen; ausschließlich damit Repository-Aktionen ausführen. -- [ ] Erster vertikaler Template-bis-Fork-Ablauf mit tatsächlichem Benutzerlogin. - -Die Auth-Helfer sind noch nicht an HTTP-Routen angebunden. Insbesondere ersetzt -ein erfolgreicher State-Vergleich keine atomare Einmalverwendung in PostgreSQL. -Die geschützte API bleibt bis zur vollständigen Integration geschlossen. -Der öffentliche Template-Editor arbeitet ausschließlich mit Repository-Vorlagen -und flüchtigen Entwürfen im aktuellen Browser-Tab. - -## Nebula als bestätigte Referenz - -Der Benutzer hat am 2026-09-30 [styleguide.stackit.schwarz](https://styleguide.stackit.schwarz/) -als Referenz angegeben. Die Seiten sind ohne Login abrufbar (Unterseiten mit -abschließendem `/`). Relevante Vorgaben: +| `html.brand--digits` | Body text: DIN 2014; headings: Univia Pro | +| `html.brand--digits` | Light branding header: `#0a1e2dff` | +| `html.brand--digits` | CTA: `#00c2ccff`, hover `#00b2bcff`, active `#00a2acff` | +| `html.brand--neutral` | Body text and headings: Inter | +| `html.brand--schwarz` | Body text and headings: Helvetica Now Var | +| Theme selectors | `theme--light`, `theme--dark`, `theme--a11y` | +| Body rule | 16 px, weight 400, line height 1.56; colors through theme tokens | + +The HTML response initially contains only `html lang="en"`, no selected brand +or theme class. Tokens must therefore not be merged across all selectors. +Extraction is not a complete CSS parser and computes neither cascade nor rendered +styles. The application explicitly selects +`digits/light`. A limited semantic token snapshot preserves +viewport rules; font files and logo are served locally. +[Asset origin and checksums](brand-assets.md). Portal JavaScript is not +incorporated into the application. + +`curl` delivers SPA source files, not a rendered, authenticated +project home page. Shell geometry, concrete components and interaction states +therefore remain open acceptance items. The earlier browser connection error +(missing plugin version `26.917.71314`) does not prevent public retrieval. + + +## Independently prepared work + +- [x] GitHub App registration draft with fixed callback URL under `deploy/github/`. +- [x] Pure auth building blocks for S256 PKCE, state/browser binding and secure cookie output with negative tests. +- [ ] Register/assign GitHub App and configure user authorization. +- [ ] Implement persistent, atomically consumed login transactions and server-side sessions. +- [ ] Tenant/membership model, migrations and real PostgreSQL RLS negative tests. +- [ ] Protect user-bound GitHub tokens; perform repository actions exclusively with them. +- [ ] First vertical template-to-fork flow with actual user login. + +The auth helpers are not yet connected to HTTP routes. In particular, +a successful state comparison does not replace atomic single use in PostgreSQL. +The protected API remains closed until full integration. +The public template editor works exclusively with repository templates +and transient drafts in the current browser tab. + + +## Nebula as the confirmed reference + +On 2026-09-30 the user specified [styleguide.stackit.schwarz](https://styleguide.stackit.schwarz/) +as the reference. Pages are accessible without login (subpages with +a trailing `/`). Relevant requirements: - [Tokens](https://styleguide.stackit.schwarz/foundations/design-tokens/about-tokens/): - semantische Namen verwenden, Marken/Modi getrennt halten. -- [Typografie](https://styleguide.stackit.schwarz/foundations/typography/): - 16-px-Basiseinheit, abgestufte Textstile; lokale Originalschriften. -- [Formulare](https://styleguide.stackit.schwarz/patterns/forms/design/): - ein-/zweispaltiger Wizard, Inline-Fehler und anklickbare Fehlerzusammenfassung. - Download bleibt klickbar und führt bei ungültigen Angaben zum betroffenen Feld. + use semantic names, keep brands/modes separate. +- [Typography](https://styleguide.stackit.schwarz/foundations/typography/): + 16-px base unit, graduated text styles; local original fonts. +- [Forms](https://styleguide.stackit.schwarz/patterns/forms/design/): + one-/two-column wizard, inline errors and clickable error summary. + Download remains clickable and leads to the affected field when inputs are invalid. - [Buttons](https://styleguide.stackit.schwarz/components/buttons/design/): - eine hervorgehobene Hauptaktion pro Aktionsgruppe. -- [Header](https://styleguide.stackit.schwarz/components/header/design/) und - [Navigation](https://styleguide.stackit.schwarz/patterns/side-navigation/design/): - Logo, Kontext und klar markierter aktiver Navigationspunkt. - -Nebula verweist auf eine Angular-Komponentenbibliothek. Diese ist keine direkt -nutzbare React-Abhängigkeit. Der bestätigte React-Stack bleibt für diesen Schritt -bestehen; native semantische Komponenten verwenden den ausgewählten Token-Snapshot. -Vollständige Komponenten- und Verhaltensparität ist damit nicht automatisch erreicht. -Der Configurator zeigt nur seine tatsächlich verfügbaren Funktionen; eine -Projekt-/Regionsauswahl für authentifizierte Benutzer folgt mit dem Login. - -Lokale Abnahme: Browserprüfungen auf 1440 und 390 px, inklusive Suche, -Fehlerfokus, Entwurfsdownload und erfolgreichem Laden beider Originalschriften und -des Logos. Screenshots liegen unter `.local/browser-tests`. Die integrierte -Browser-Verbindung ist weiterhin defekt; deshalb wurden isolierte lokale -Browser-Kontexte verwendet. Ein direkter visueller Vergleich mit der angemeldeten -Portal-Projektstartseite und die vollständige Tastatur-/Kontrastprüfung stehen aus. - -## Fachliches Bedienkonzept - -Die [verbindlichen Editor-Designprinzipien](editor-design-principles.md) ergänzen -die visuellen Portalreferenzen: offizielle Produktnamen, Komponentenübersicht, -schrittweise Detailanzeige und dokumentationsnahe Abläufe, zunächst für STACKIT VPN. + one prominent primary action per action group. +- [Header](https://styleguide.stackit.schwarz/components/header/design/) and + [navigation](https://styleguide.stackit.schwarz/patterns/side-navigation/design/): + logo, context and clearly marked active navigation item. + +Nebula refers to an Angular component library. This is not a directly +usable React dependency. The confirmed React stack remains in place for this step; +native semantic components use the selected token snapshot. +Full component and behavior parity is not automatically achieved. +The Configurator shows only its actually available features; project/region +selection for authenticated users follows with login. + +Local acceptance: browser checks at 1440 and 390 px, including search, +error focus, draft download and successful loading of both original fonts and +the logo. Screenshots are under `.local/browser-tests`. The integrated +browser connection remains broken; isolated local +browser contexts were therefore used. Direct visual comparison with the authenticated +portal project home page and complete keyboard/contrast checks remain outstanding. + + +## Domain interaction concept + +The [binding editor design principles](editor-design-principles.md) supplement +the visual portal references: official product names, component overview, +progressive detail disclosure and documentation-aligned flows, initially for STACKIT VPN. diff --git a/landing-zone-configurator/docs/development.de.md b/landing-zone-configurator/docs/development.de.md new file mode 100644 index 0000000..8304c5e --- /dev/null +++ b/landing-zone-configurator/docs/development.de.md @@ -0,0 +1,72 @@ + +# Configurator-Entwicklungsübersicht + +[English](development.md) | [Deutsch](development.de.md) + +Beginne mit [CONTRIBUTING](../../CONTRIBUTING.de.md) und der +[lokalen Anwendungseinrichtung](../app/README.de.md). Diese Seite verzeichnet technische +Referenzen; das [Benutzerhandbuch](user-guide.de.md) beschreibt die Produktnutzung. + + +## Komponentenverträge + +| Bereich | Referenz | +| --- | --- | +| Komponenten, Vertrauensgrenzen und Diagramme | [Architektur](architecture.de.md) | +| Native Schemas und Compiler | [Gemeinsames Funktionsmodell](common-feature-model.de.md), [gemeinsamer Editor](common-editor.de.md) | +| Vorlagenentwürfe und Parameter | [Projektvorlagenentwürfe](project-template-drafts.de.md), [Parameter und Bindungen](template-parameters-and-bindings.de.md) | +| Authentifizierung und Organisationsbindung | [Anmeldung](github-login.de.md) | +| Runner, Jobs und State | [Plan-Ausführung](plan-execution.de.md), [Runner-Paketierung](../deploy/runner/README.de.md) | +| Assistant-Fakten, Generierung und Qualifikation | [Wissensvertrag](assistant-knowledge/README.de.md) | +| Betreiber-IaC und verschlüsselter State | [Infrastruktur](../infra/README.de.md) | +| CI-Berechtigungen und manuelle Operationen | [CI-Betriebshandbuch](../infra/ci/README.de.md) | +| Paketierung, Migrationen und Promotion | [CF-Release](../deploy/cloud-foundry/README.de.md) | + +Die älteren [Planungsnotizen](planning.de.md) und +die [Platform-/Application-Designbegründung](platform-application-architecture.de.md) +bewahren Designentscheidungen, nicht den aktuellen Abnahmestand oder Betreiberbefehle. +Nutze Code, aktuelle Verträge, Tests und Issue-Diskussionen für den Implementierungsstand. +Historische Arbeitsplatzübergaben und laufbezogene Abnahmeprotokolle gehören nicht +zur gepflegten Dokumentation. + +Lesen der Konfigurationsliste darf eine neuere Aktualisierung nach dem Speichern +nicht mit einer älteren initialen Antwort oder einem Fehler überschreiben. +Erhalte die Reihenfolge der Anfragen und das erfasste Abort-Signal für die +Sitzungslebensdauer. Der Datenbank-Konfigurations-Browserablauf verzögert initiale +Lesezugriffe bis nach erfolgreichem Speichern, um diese Reihenfolge auf Desktop +und Mobilgeräten neben erneutem Öffnen, Revisionskonflikt und Löschen zu prüfen. +Die initiale Sitzungsabfrage beim Übergang von Gast zu authentifiziert erhält den +Editor-DOM, damit ein fokussiertes Eingabefeld nicht entfernt wird. Tatsächliche +Identitäts-/Arbeitsumgebungswechsel setzen weiterhin den Entwurf und den +bereichsgebundenen Katalogprovider zurück; private Kataloge dürfen nie über +diese Grenzen hinweg erhalten bleiben. + +Halte Frontend-Navigation und die explizite SPA-Routen-Allowlist der API synchron, +einschließlich Arbeitsumgebungs- und Deployment-Phasen-URLs. Direkte Aufrufe und +Neuladen müssen die kompilierte UI über die API ausliefern, nicht nur über den +History-Fallback des Entwicklungsservers. Die Static-Serving-API-Regression deckt +diese Pfade ab und erhält 404-Antworten für unbekannte Routen, API-/Auth-Pfade und +fehlende Assets; ersetze die Allowlist nicht durch einen Catch-all. + + +## Validierung gegenüber Cloud-Operationen + +Runner-Ausgabe verwendet einen authentifizierten NDJSON-Stream mit unveränderter +JSON-Snapshot-Kompatibilität. Halte den gemeinsamen Ausgabeereignisvertrag, +Worker-Redaktion und UTF-8-Bytegrenzen, die native UI-Ereignisprojektion und den +abschließenden menschenlesbaren gespeicherten Plan synchron. Teste Ausgabe vor +Prozessabschluss und vor HTTP-EOF, Zugriffsentzug, Verbindungsabbau und +Desktop-/Mobil-Einklappen/Wiederverbinden. Ersetze nativen Fortschritt nicht durch +erfundene Prozentangaben und lege weder rohe Maschinen-UI noch gespeichertes +Plan-JSON oder State offen. Assistant-Übernahme und Ausgabeansicht erteilen keine +Ausführungsberechtigung. + +Der repositoryweite [Workflow-Katalog](../../docs/workflows.de.md) ist die zentrale +Tabelle für alle Pipelines, automatische/manuelle Auslöser, wiederverwendbare +Aufrufe, Eingaben und Startanweisungen für die GitHub-UI. Aktualisiere ihn bei +Workflow-Änderungen, statt hier ein zweites unvollständiges Inventar zu pflegen. + +Ein Quellmerge löst kein Deployment aus. Kunden-Zugangsdaten, State, private +Inventare oder rohe Plan-Ausgabe gehören niemals in Issues, Chat oder Testartefakte. +Lokale Modellbelege qualifizieren nur ihre exakte Quelle und konfigurierten Modelle; +sie ersetzen nicht die Qualifikation des geschützten Release-Workflows. diff --git a/landing-zone-configurator/docs/development.md b/landing-zone-configurator/docs/development.md index 46e3d80..826f46c 100644 --- a/landing-zone-configurator/docs/development.md +++ b/landing-zone-configurator/docs/development.md @@ -1,5 +1,7 @@ # Configurator development map +[English](development.md) | [Deutsch](development.de.md) + Start with [CONTRIBUTING](../../CONTRIBUTING.md) and the [local application setup](../app/README.md). This page indexes technical references; the [user guide](user-guide.md) describes product usage. diff --git a/landing-zone-configurator/docs/editor-design-principles.de.md b/landing-zone-configurator/docs/editor-design-principles.de.md new file mode 100644 index 0000000..4e68ce2 --- /dev/null +++ b/landing-zone-configurator/docs/editor-design-principles.de.md @@ -0,0 +1,164 @@ + + +# Verbindliche Designprinzipien des Landing Zone Configurators + +[English](editor-design-principles.md) | [Deutsch](editor-design-principles.de.md) + +Status: vom Benutzer bestätigte Richtung; schrittweise Umsetzung auf dem Feature-Branch. +Diese Prinzipien ergänzen [Designreferenz](design-reference.de.md) und +[gemeinsames Funktionsmodell](common-feature-model.de.md). + + + +## Begriffe und Orientierung + +- Offizielle STACKIT-Produktnamen verwenden: STACKIT Network Area (SNA), STACKIT VPN, + STACKIT Observability, STACKIT Secrets Manager. Wo kein Produkt gemeint ist, + den Accelerator-Modulnamen verwenden, beispielsweise Connectivity. +- Kubernetes-Namespace-Dienste ausdrücklich als Kubernetes-Funktion benennen. +- Produkt, Modul, Ressource und Instanz unterscheiden. Observability und der + Telemetry Router der Audit-Protokollierung sind unterschiedliche Dienste. +- Technische Feldnamen dienen intern der Zuordnung; sichtbare Begriffe, Hilfen und + Abläufe orientieren sich am Produkt und an seiner offiziellen Dokumentation. +- Portalparität erst nach tatsächlichem Vergleich behaupten. Die öffentliche VPN- + Anleitung bezeichnet Portal-Integration noch als nicht verfügbar; das ist kein + Nachweis über den vom Benutzer beobachteten aktuellen Portalablauf. + + + +## Arbeitsbereich und Konfigurationskontext + +Bestätigter Hauptablauf: **Login > Arbeitsbereich öffnen > Konfiguration öffnen +oder erstellen > Bearbeiten > Plan > Apply**. + +- Beim ersten Einstieg verfügbare Arbeitsbereiche einschließlich des persönlichen + anbieten; Erstellen und Öffnen sind eigene Aktionen. +- Beim erneuten Einstieg den letzten noch zugänglichen Arbeitsbereich wieder + öffnen. Explizite Deep Links und gesicherte Login-Entwürfe nicht überschreiben. +- Arbeitsbereichswechsel im Header auch auf Mobilgeräten erreichbar halten. +- **Konfigurationen** ist die Plattformübersicht; **Neue Konfiguration** öffnet + die Vorlagen. Templates und „Mein Entwurf“ sind keine primären Sidebarziele. +- Geöffnete Konfigurationen haben **Konfiguration · Bereitstellung · Verlauf** + als gemeinsamen Kontext mit Namen und gespeicherter Revision. +- **Speichern und zur Bereitstellung** verwendet exakt die neue Serverrevision. + Ungespeicherte Änderungen sperren den direkten Bereitstellungstab; Wechsel + in andere Arbeitsbereiche dürfen sie nicht still verwerfen. +- Verlauf bleibt ausschließlich lesbar und konfigurationsbezogen. Sichtbare + Ausführungen und Statusangaben unterliegen weiterhin den bestehenden Rollen, + Benutzer- und Tenant-Grenzen. +- Navigation und Wiederaufnahme starten keine Vorbereitung, keinen Plan und + keinen Apply. Bestehende Planbindungen und Ablaufzeiten bleiben unverändert. +- Application Owner behalten den getrennten Application-Landing-Zone-Ablauf. + +Lokal am 2026-10-04 umgesetzt: Gesamtcheck mit 305 Unit-Tests und vollständige +Browser-Suite mit 134 Desktop-/Mobilfällen bestanden. Arbeitsbereichsauswahl und +Konfigurations-/Bereitstellungskontext visuell geprüft. Browser-APIs simuliert; +kein Kunden-Apply und keine Live-S3-Abnahme durch diese Umsetzung. + + + +## Weniger sichtbare Komplexität + +- Die Übersicht zeigt aktive Komponenten kompakt; Einstellungen erst beim Bearbeiten. +- Optionale, inaktive Komponenten über **Komponente hinzufügen** erreichbar machen. +- Aktivität anhand wirksamer Werte inklusive Engine-Defaults bestimmen, nicht allein + anhand vorhandener JSON-Felder. Standardmäßig aktive Projektdienste sichtbar halten. +- Katalog öffnen, Karte schließen und Abschnitt einklappen verändern keine Konfiguration. +- Deaktivieren, Entfernen und Zurücksetzen sind unterschiedliche Aktionen. Vorhandene + Einstellungen und Referenzen nicht durch bloßes Verbergen verlieren; geplante + Ressourcenlöschung bei späterem Apply ausdrücklich kenntlich machen. +- Details in **Erweiterte Einstellungen**; notwendige Angaben und Fehler sichtbar halten. +- Unvollständige Entwürfe dürfen bearbeitet werden. Konfiguriert, ausführbar, + bereitgestellt und technisch verbunden als verschiedene Zustände anzeigen. +- Bekannte Auswahlwerte als Dropdowns; dynamische Produktangebote aus regionalen + Katalogen laden. Keine erfundenen oder vermeintlich vollständigen SKU-Listen. +- Accelerator-Standard und Vorlagenwert klar unterscheiden. Bestehende Dokumente + nicht still normalisieren oder auf andere Terraform-Moduladressen umstellen. + + + +## Netzwerkmodell + +Zielansicht: **Region → SNAs → zugeordnete Projekte** mit DNS, Firewall und VPN im +Connectivity-Kontext. Eine SNA ist eine Organisationsressource mit regionaler +Konfiguration. Der aktuelle Accelerator erstellt getrennte SNAs je regionalem +Moduleintrag; gleiche Kennungen erzeugen keine regionsübergreifende Verbindung. + +`connectivity` in der Standardregion und `connectivity_regions` sind alternative +Engine-Eingaben, keine zwei unabhängigen Produkte. Eine einheitliche Oberfläche +muss den bestehenden Export und die Ressourcenzuordnung erhalten. Vor einem +Wechsel Namenspräfixe, Moduladressen und Einschränkungen (#65/#80) prüfen. + +Routing-Tabellen nicht als fehlend darstellen: WAN-Tabelle je SNA und +Firewall-Standardrouten der Corporate-Projekte werden vom Accelerator erzeugt. +Frei definierbare zusätzliche Tabellen sind im geprüften Root-Vertrag nicht +vorgesehen. Statische VPN-Routen sind eine gesonderte Einstellung; automatische +Inter-Region-Verbindungen bleiben Thema #64. + + + +## VPN als erste geführte Produktkomponente + +1. **Gateway:** Region, SNA, Name, Leistungsplan und Verfügbarkeitszonen. +2. **Routing:** unterstütztes Routingverfahren erklären und auswählen; Folgen einer + nachträglichen Änderung vor Ausführung sichtbar machen. +3. **Verbindungen:** Gegenstelle und passende Netze bzw. statische Routen je Verbindung. +4. **Tunnel und Zugang:** beide Tunnel, Gegenstellenadressen, geschützte PSK-Referenzen. +5. **Prüfen:** STACKIT-Ressourcen, noch fehlende Daten und Aufgaben an der Gegenstelle. + +Dokumentationslinks direkt am betreffenden Schritt: +- [Gateway erstellen](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/gateway-create/) +- [Verbindung erstellen](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/connection-create/) +- [Gateway- und Verbindungsoptionen](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/basics/gateway-and-connection-options/) + +Der Accelerator kann Gateway und konfigurierte STACKIT-seitige Verbindungen +anlegen, nicht das entfernte VPN-Gerät konfigurieren. BGP ist im geprüften Modul +nicht unterstützt. Gemeinsamer Editor, geschützte VPN-Schlüsselanbindung und +vollständige Deployment-Ausführung sind getrennte Ausbauschritte. Ein vollständiger +Dialog allein darf deshalb nicht als betriebsbereites VPN dargestellt werden. + + + +## Umsetzung und Abnahme + +- [x] Designprinzipien mit Benutzerentscheidung dokumentiert. +- [x] Kubernetes-/Connectivity-/SNA-Bezeichnungen im begonnenen Editor angepasst. +- [x] Projektschalter für Secrets Manager und Observability direkt zugänglich. +- [x] Erste Komponentenübersicht für Plattform und Kubernetes-Namespace-Dienste implementiert. +- [x] Komponentenübersicht auf optionale Connectivity-Dienste (DNS, Firewall, VPN) ausgeweitet. +- [ ] Weitere verschachtelte optionale Dienste vereinfachen. +- [x] Einheitliche Regions-/SNA-Ansicht mit beibehaltenen Engine-Eingabeformen und Referenzschutz implementiert. +- [ ] VPN-Eingaben gegen Engine-Version, Produktdokumentation und aktuellen Portalablauf abgleichen. +- [x] VPN-Konfigurationsassistent mit Gateway, Routing, Verbindungen/Tunneln, Zusammenfassung und Dokumentationslinks implementiert. +- [ ] Vollständige produktseitige Validierung (u. a. regionale Kataloge/IPsec-Kompatibilität) ergänzen. +- [ ] Regionale Produktkataloge und geschützte VPN-Schlüsselreferenzen anbinden. +- [ ] Getrennte Gateway-/Verbindungsphasen und Ausführungsgrenzen im Backend abnehmen. +- [ ] Fachliche Beschriftungen, Tastaturbedienung und Desktop-/Mobilansichten prüfen. +- [ ] Speicherung/Wiederaufnahme, inaktive Konfigurationen und unveränderte Exporte regressionsprüfen. +- [ ] Veröffentlichung und Live-Abnahme des überarbeiteten Bedienkonzepts. + +Kunden-Apply weiterhin nur nach ausdrücklicher Freigabe. Keine Main-Merge-Freigabe. + + + +## Lokaler Prüfstand der ersten Umsetzung + +- Lint, TypeScript und Produktionsbuild erfolgreich; 96 Anwendungstests bestanden. +- 22 Desktop-/Mobil-Browserfälle bestanden. Nach Ergänzung der Prüfung auf + unveränderte Werte beim Katalog-Öffnen/-Schließen die sechs betroffenen + Editor-Browserfälle erneut erfolgreich ausgeführt. +- Geprüft: Projektschalter, Komponentenauswahl, unveränderte Speicherung, + Wiederaufnahme, Legacy-Abläufe und bestehende Deployment-Sperren. +- Noch kein Deployment dieser Änderungen; letzte Live-Abnahme siehe + [gemeinsamer Editor](common-editor.de.md). + + + +### Weiterer Prüfstand 2026-10-01 + +Regions-/SNA-Ansicht und VPN-Konfigurationsassistent implementiert; 97 +Anwendungstests und 24 Desktop-/Mobil-Browserfälle erfolgreich, mobile VPN-Ansicht +visuell geprüft. Noch keine Veröffentlichung dieses Arbeitsstands. Die +[Platform-/Application-Architektur](platform-application-architecture.de.md) trennt +künftig die Rollenansichten, Vorlagen und Instanzen. Die aktuelle Oberfläche +stellt diese noch nicht als vorhandene Berechtigungsfunktionen dar. diff --git a/landing-zone-configurator/docs/editor-design-principles.md b/landing-zone-configurator/docs/editor-design-principles.md index 9328041..e53df60 100644 --- a/landing-zone-configurator/docs/editor-design-principles.md +++ b/landing-zone-configurator/docs/editor-design-principles.md @@ -1,144 +1,155 @@ -# Verbindliche Designprinzipien des Landing Zone Configurators - -Status: vom Benutzer bestätigte Richtung; schrittweise Umsetzung auf dem Feature-Branch. -Diese Prinzipien ergänzen [Designreferenz](design-reference.md) und -[gemeinsames Funktionsmodell](common-feature-model.md). - -## Begriffe und Orientierung - -- Offizielle STACKIT-Produktnamen verwenden: STACKIT Network Area (SNA), STACKIT VPN, - STACKIT Observability, STACKIT Secrets Manager. Wo kein Produkt gemeint ist, - den Accelerator-Modulnamen verwenden, beispielsweise Connectivity. -- Kubernetes-Namespace-Dienste ausdrücklich als Kubernetes-Funktion benennen. -- Produkt, Modul, Ressource und Instanz unterscheiden. Observability und der - Telemetry Router der Audit-Protokollierung sind unterschiedliche Dienste. -- Technische Feldnamen dienen intern der Zuordnung; sichtbare Begriffe, Hilfen und - Abläufe orientieren sich am Produkt und an seiner offiziellen Dokumentation. -- Portalparität erst nach tatsächlichem Vergleich behaupten. Die öffentliche VPN- - Anleitung bezeichnet Portal-Integration noch als nicht verfügbar; das ist kein - Nachweis über den vom Benutzer beobachteten aktuellen Portalablauf. - -## Arbeitsbereich und Konfigurationskontext - -Bestätigter Hauptablauf: **Login > Arbeitsbereich öffnen > Konfiguration öffnen -oder erstellen > Bearbeiten > Plan > Apply**. - -- Beim ersten Einstieg verfügbare Arbeitsbereiche einschließlich des persönlichen - anbieten; Erstellen und Öffnen sind eigene Aktionen. -- Beim erneuten Einstieg den letzten noch zugänglichen Arbeitsbereich wieder - öffnen. Explizite Deep Links und gesicherte Login-Entwürfe nicht überschreiben. -- Arbeitsbereichswechsel im Header auch auf Mobilgeräten erreichbar halten. -- **Konfigurationen** ist die Plattformübersicht; **Neue Konfiguration** öffnet - die Vorlagen. Templates und „Mein Entwurf“ sind keine primären Sidebarziele. -- Geöffnete Konfigurationen haben **Konfiguration · Bereitstellung · Verlauf** - als gemeinsamen Kontext mit Namen und gespeicherter Revision. -- **Speichern und zur Bereitstellung** verwendet exakt die neue Serverrevision. - Ungespeicherte Änderungen sperren den direkten Bereitstellungstab; Wechsel - in andere Arbeitsbereiche dürfen sie nicht still verwerfen. -- Verlauf bleibt ausschließlich lesbar und konfigurationsbezogen. Sichtbare - Ausführungen und Statusangaben unterliegen weiterhin den bestehenden Rollen, - Benutzer- und Tenant-Grenzen. -- Navigation und Wiederaufnahme starten keine Vorbereitung, keinen Plan und - keinen Apply. Bestehende Planbindungen und Ablaufzeiten bleiben unverändert. -- Application Owner behalten den getrennten Application-Landing-Zone-Ablauf. - -Lokal am 2026-10-04 umgesetzt: Gesamtcheck mit 305 Unit-Tests und vollständige -Browser-Suite mit 134 Desktop-/Mobilfällen bestanden. Arbeitsbereichsauswahl und -Konfigurations-/Bereitstellungskontext visuell geprüft. Browser-APIs simuliert; -kein Kunden-Apply und keine Live-S3-Abnahme durch diese Umsetzung. - -## Weniger sichtbare Komplexität - -- Die Übersicht zeigt aktive Komponenten kompakt; Einstellungen erst beim Bearbeiten. -- Optionale, inaktive Komponenten über **Komponente hinzufügen** erreichbar machen. -- Aktivität anhand wirksamer Werte inklusive Engine-Defaults bestimmen, nicht allein - anhand vorhandener JSON-Felder. Standardmäßig aktive Projektdienste sichtbar halten. -- Katalog öffnen, Karte schließen und Abschnitt einklappen verändern keine Konfiguration. -- Deaktivieren, Entfernen und Zurücksetzen sind unterschiedliche Aktionen. Vorhandene - Einstellungen und Referenzen nicht durch bloßes Verbergen verlieren; geplante - Ressourcenlöschung bei späterem Apply ausdrücklich kenntlich machen. -- Details in **Erweiterte Einstellungen**; notwendige Angaben und Fehler sichtbar halten. -- Unvollständige Entwürfe dürfen bearbeitet werden. Konfiguriert, ausführbar, - bereitgestellt und technisch verbunden als verschiedene Zustände anzeigen. -- Bekannte Auswahlwerte als Dropdowns; dynamische Produktangebote aus regionalen - Katalogen laden. Keine erfundenen oder vermeintlich vollständigen SKU-Listen. -- Accelerator-Standard und Vorlagenwert klar unterscheiden. Bestehende Dokumente - nicht still normalisieren oder auf andere Terraform-Moduladressen umstellen. - -## Netzwerkmodell - -Zielansicht: **Region → SNAs → zugeordnete Projekte** mit DNS, Firewall und VPN im -Connectivity-Kontext. Eine SNA ist eine Organisationsressource mit regionaler -Konfiguration. Der aktuelle Accelerator erstellt getrennte SNAs je regionalem -Moduleintrag; gleiche Kennungen erzeugen keine regionsübergreifende Verbindung. - -`connectivity` in der Standardregion und `connectivity_regions` sind alternative -Engine-Eingaben, keine zwei unabhängigen Produkte. Eine einheitliche Oberfläche -muss den bestehenden Export und die Ressourcenzuordnung erhalten. Vor einem -Wechsel Namenspräfixe, Moduladressen und Einschränkungen (#65/#80) prüfen. - -Routing-Tabellen nicht als fehlend darstellen: WAN-Tabelle je SNA und -Firewall-Standardrouten der Corporate-Projekte werden vom Accelerator erzeugt. -Frei definierbare zusätzliche Tabellen sind im geprüften Root-Vertrag nicht -vorgesehen. Statische VPN-Routen sind eine gesonderte Einstellung; automatische -Inter-Region-Verbindungen bleiben Thema #64. - -## VPN als erste geführte Produktkomponente - -1. **Gateway:** Region, SNA, Name, Leistungsplan und Verfügbarkeitszonen. -2. **Routing:** unterstütztes Routingverfahren erklären und auswählen; Folgen einer - nachträglichen Änderung vor Ausführung sichtbar machen. -3. **Verbindungen:** Gegenstelle und passende Netze bzw. statische Routen je Verbindung. -4. **Tunnel und Zugang:** beide Tunnel, Gegenstellenadressen, geschützte PSK-Referenzen. -5. **Prüfen:** STACKIT-Ressourcen, noch fehlende Daten und Aufgaben an der Gegenstelle. - -Dokumentationslinks direkt am betreffenden Schritt: -- [Gateway erstellen](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/gateway-create/) -- [Verbindung erstellen](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/connection-create/) -- [Gateway- und Verbindungsoptionen](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/basics/gateway-and-connection-options/) - -Der Accelerator kann Gateway und konfigurierte STACKIT-seitige Verbindungen -anlegen, nicht das entfernte VPN-Gerät konfigurieren. BGP ist im geprüften Modul -nicht unterstützt. Gemeinsamer Editor, geschützte VPN-Schlüsselanbindung und -vollständige Deployment-Ausführung sind getrennte Ausbauschritte. Ein vollständiger -Dialog allein darf deshalb nicht als betriebsbereites VPN dargestellt werden. - -## Umsetzung und Abnahme - -- [x] Designprinzipien mit Benutzerentscheidung dokumentiert. -- [x] Kubernetes-/Connectivity-/SNA-Bezeichnungen im begonnenen Editor angepasst. -- [x] Projektschalter für Secrets Manager und Observability direkt zugänglich. -- [x] Erste Komponentenübersicht für Plattform und Kubernetes-Namespace-Dienste implementiert. -- [x] Komponentenübersicht auf optionale Connectivity-Dienste (DNS, Firewall, VPN) ausgeweitet. -- [ ] Weitere verschachtelte optionale Dienste vereinfachen. -- [x] Einheitliche Regions-/SNA-Ansicht mit beibehaltenen Engine-Eingabeformen und Referenzschutz implementiert. -- [ ] VPN-Eingaben gegen Engine-Version, Produktdokumentation und aktuellen Portalablauf abgleichen. -- [x] VPN-Konfigurationsassistent mit Gateway, Routing, Verbindungen/Tunneln, Zusammenfassung und Dokumentationslinks implementiert. -- [ ] Vollständige produktseitige Validierung (u. a. regionale Kataloge/IPsec-Kompatibilität) ergänzen. -- [ ] Regionale Produktkataloge und geschützte VPN-Schlüsselreferenzen anbinden. -- [ ] Getrennte Gateway-/Verbindungsphasen und Ausführungsgrenzen im Backend abnehmen. -- [ ] Fachliche Beschriftungen, Tastaturbedienung und Desktop-/Mobilansichten prüfen. -- [ ] Speicherung/Wiederaufnahme, inaktive Konfigurationen und unveränderte Exporte regressionsprüfen. -- [ ] Veröffentlichung und Live-Abnahme des überarbeiteten Bedienkonzepts. - -Kunden-Apply weiterhin nur nach ausdrücklicher Freigabe. Keine Main-Merge-Freigabe. - -## Lokaler Prüfstand der ersten Umsetzung - -- Lint, TypeScript und Produktionsbuild erfolgreich; 96 Anwendungstests bestanden. -- 22 Desktop-/Mobil-Browserfälle bestanden. Nach Ergänzung der Prüfung auf - unveränderte Werte beim Katalog-Öffnen/-Schließen die sechs betroffenen - Editor-Browserfälle erneut erfolgreich ausgeführt. -- Geprüft: Projektschalter, Komponentenauswahl, unveränderte Speicherung, - Wiederaufnahme, Legacy-Abläufe und bestehende Deployment-Sperren. -- Noch kein Deployment dieser Änderungen; letzte Live-Abnahme siehe - [gemeinsamer Editor](common-editor.md). - -### Weiterer Prüfstand 2026-10-01 - -Regions-/SNA-Ansicht und VPN-Konfigurationsassistent implementiert; 97 -Anwendungstests und 24 Desktop-/Mobil-Browserfälle erfolgreich, mobile VPN-Ansicht -visuell geprüft. Noch keine Veröffentlichung dieses Arbeitsstands. Die -[Platform-/Application-Architektur](platform-application-architecture.md) trennt -künftig die Rollenansichten, Vorlagen und Instanzen. Die aktuelle Oberfläche -stellt diese noch nicht als vorhandene Berechtigungsfunktionen dar. + +# Binding design principles for the Landing Zone Configurator + +[English](editor-design-principles.md) | [Deutsch](editor-design-principles.de.md) + +Status: direction confirmed by the user; incremental implementation on the feature branch. +These principles supplement the [design reference](design-reference.md) and +[common feature model](common-feature-model.md). + + +## Terminology and orientation + +- Use official STACKIT product names: STACKIT Network Area (SNA), STACKIT VPN, + STACKIT Observability, STACKIT Secrets Manager. Where no product is meant, + use the Accelerator module name, for example Connectivity. +- Explicitly identify Kubernetes namespace services as a Kubernetes feature. +- Distinguish product, module, resource and instance. Observability and the + Telemetry Router for audit logging are different services. +- Technical field names serve internal mapping; visible terms, help and + flows follow the product and its official documentation. +- Claim portal parity only after actual comparison. The public VPN + guide still calls portal integration unavailable; this is not + evidence about the current portal flow observed by the user. + + +## Workspace and configuration context + +Confirmed main flow: **Login > Open workspace > Open +or create configuration > Edit > Plan > Apply**. + +- On first entry, offer available workspaces including the personal + workspace; create and open are separate actions. +- On return, reopen the last still-accessible workspace. + Do not override explicit deep links or secured login drafts. +- Keep workspace switching in the header accessible on mobile too. +- **Configurations** is the platform overview; **New configuration** opens + templates. Templates and “My draft” are not primary sidebar destinations. +- Open configurations share **Configuration · Deployment · History** + as a common context with name and saved revision. +- **Save and continue to deployment** uses exactly the new server revision. + Unsaved changes block the direct deployment tab; switching + to other workspaces must not silently discard them. +- History remains read-only and configuration-specific. Visible + executions and status remain subject to existing role, + user and tenant boundaries. +- Navigation and resumption start no preparation, Plan or + Apply. Existing Plan bindings and expiry times remain unchanged. +- Application Owners retain the separate Application Landing Zone flow. + +Implemented locally on 2026-10-04: full check with 305 unit tests and complete +browser suite with 134 desktop/mobile cases passed. Workspace selection and +configuration/deployment context visually checked. Browser APIs simulated; +no customer Apply or live S3 acceptance through this implementation. + + +## Less visible complexity + +- The overview compactly shows active components; settings appear only while editing. +- Make optional inactive components accessible through **Add component**. +- Determine activity from effective values including engine defaults, not only + from existing JSON fields. Keep project services that are active by default visible. +- Opening the catalogue, closing a card and collapsing a section change no configuration. +- Disabling, removing and resetting are different actions. Do not lose existing + settings and references merely by hiding them; explicitly identify planned + resource deletion during a later Apply. +- Details in **Advanced settings**; keep required inputs and errors visible. +- Incomplete drafts may be edited. Show configured, executable, + deployed and technically connected as different states. +- Known choices as dropdowns; load dynamic product offerings from regional + catalogues. No invented or supposedly complete SKU lists. +- Clearly distinguish Accelerator defaults from template values. Do not silently + normalize existing documents or switch them to different Terraform module addresses. + + +## Network model + +Target view: **Region → SNAs → assigned projects**, with DNS, firewall and VPN in +the Connectivity context. An SNA is an organization resource with regional +configuration. The current Accelerator creates separate SNAs per regional +module entry; identical identifiers do not create cross-region connectivity. + +`connectivity` in the default region and `connectivity_regions` are alternative +engine inputs, not two independent products. A unified interface +must preserve existing export and resource assignment. Before +switching, check name prefixes, module addresses and limitations (#65/#80). + +Do not portray routing tables as missing: the Accelerator creates a WAN table per SNA +and firewall default routes for Corporate projects. +Freely definable additional tables are not provided in the reviewed root contract. +Static VPN routes are a separate setting; automatic +inter-region connections remain issue #64. + + +## VPN as the first guided product component + +1. **Gateway:** region, SNA, name, performance plan and availability zones. +2. **Routing:** explain and select the supported routing method; make the effects of + a later change visible before execution. +3. **Connections:** peer and matching networks or static routes per connection. +4. **Tunnel and access:** both tunnels, peer addresses, protected PSK references. +5. **Review:** STACKIT resources, still-missing data and tasks on the peer. + +Documentation links directly at the relevant step: +- [Create gateway](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/gateway-create/) +- [Create connection](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/connection-create/) +- [Gateway and connection options](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/basics/gateway-and-connection-options/) + +The Accelerator can create a gateway and configured STACKIT-side connections, +not configure the remote VPN device. BGP is not supported in the reviewed module. +Common editor, protected VPN key binding and +complete deployment execution are separate extensions. A complete +dialog alone must therefore not be portrayed as an operational VPN. + + +## Implementation and acceptance + +- [x] Document design principles with user decision. +- [x] Adjust Kubernetes/Connectivity/SNA terminology in the editor under development. +- [x] Make project toggles for Secrets Manager and Observability directly accessible. +- [x] Implement initial component overview for platform and Kubernetes namespace services. +- [x] Extend component overview to optional Connectivity services (DNS, firewall, VPN). +- [ ] Simplify further nested optional services. +- [x] Implement unified region/SNA view preserving engine input forms and reference protection. +- [ ] Compare VPN inputs against engine version, product documentation and current portal flow. +- [x] Implement VPN configuration assistant with gateway, routing, connections/tunnels, summary and documentation links. +- [ ] Add complete product-side validation (including regional catalogues/IPsec compatibility). +- [ ] Connect regional product catalogues and protected VPN key references. +- [ ] Qualify separate gateway/connection phases and execution boundaries in the backend. +- [ ] Check domain labels, keyboard operation and desktop/mobile views. +- [ ] Regression-test saving/resumption, inactive configurations and unchanged exports. +- [ ] Publish and perform live acceptance of the revised interaction concept. + +Customer Apply still requires explicit approval. No main-merge approval. + + +## Local verification status of the first implementation + +- Lint, TypeScript and production build successful; 96 application tests passed. +- 22 desktop/mobile browser cases passed. After adding the check for + unchanged values on catalogue opening/closing, the six affected + editor browser cases ran successfully again. +- Checked: project toggles, component selection, unchanged saving, + resumption, legacy flows and existing deployment blocks. +- No deployment of these changes yet; last live acceptance in the + [common editor](common-editor.md). + + +### Further verification status 2026-10-01 + +Region/SNA view and VPN configuration assistant implemented; 97 +application tests and 24 desktop/mobile browser cases successful, mobile VPN view +visually checked. No publication of this working state yet. The +[Platform/Application architecture](platform-application-architecture.md) will separate +role views, templates and instances. The current interface does not +yet present these as existing authorization capabilities. diff --git a/landing-zone-configurator/docs/forks-and-navigation.de.md b/landing-zone-configurator/docs/forks-and-navigation.de.md new file mode 100644 index 0000000..72bac7b --- /dev/null +++ b/landing-zone-configurator/docs/forks-and-navigation.de.md @@ -0,0 +1,210 @@ + + +# Fork-Speicherung und Browser-Navigation + +[English](forks-and-navigation.md) | [Deutsch](forks-and-navigation.de.md) + +Stand: 2026-09-30. Auf lzc-dev bereitgestellt; Browser-Navigation live geprüft. Fork-Erstellung, App-Zugriff und persönliches Speichern durch den Benutzer bestätigt. + + + +## Benutzerablauf + +1. Mit GitHub anmelden und links **GitHub-Forks** öffnen. +2. Bei Bedarf **Fork bei GitHub erstellen** verwenden. Die Erstellung bestätigt + der Benutzer direkt bei GitHub. +3. **App-Zugriff auf Fork einrichten** öffnen und die App auf ausgewählten eigenen + Repositories installieren (`Only select repositories`). +4. **Forks aktualisieren**, gegebenenfalls **Weitere Repositories prüfen**, dann + den gewünschten Fork auswählen. +5. Einen Standalone-Entwurf vollständig ausfüllen und **Im Fork speichern** wählen. + Beim ersten Speichern entsteht der Arbeitsbranch `lzc/configurations` aus dem + aktuellen Default-Branch des Forks. Der Default-Branch wird nicht verändert. +6. Gespeicherte Konfigurationen lassen sich über denselben Bereich wieder öffnen, + bearbeiten und als neue Revision speichern. **Neue Kopie vorbereiten** gibt dem + aktuellen Entwurf eine neue Identität, sobald er gespeichert wird. + +Aktuelles kanonisches Dateiformat: + +```text +src/config/custom//landing-zone.json +src/config/custom//landing-zone.tfvars +``` + +Enthalten sind Schema-Version, Konfigurations-ID, freigegebene Template-Identität +mit Quellhash und der fachliche Editor-Entwurf. `kind` ist +`landing-zone-configurator-configuration`; dies unterscheidet die bearbeitbare +Ablage vom bisherigen Downloadformat. Unbekannte Eingabefelder werden nicht +übernommen. Keine Zugangsdaten, GitHub-Tokens, Terraform-Module oder HCL-Ausdrücke +werden als zusätzliche Nutzdaten angenommen. Der deterministische Export erzeugt zusätzlich +`landing-zone.tfvars` in nativem HCL. Download und Backend verwenden denselben Serializer. +Zeichenketten bleiben Daten, auch bei `${…}` und `%{…}`. Der Export übernimmt die +validierte Standalone-Konfiguration einschließlich unveränderter Vorlagenattribute. +Bisherige JSON-only-Konfigurationen erhalten beim nächsten Speichern die zweite Datei. +Die JSON-Datei bleibt die Quelle für den Editor; manuelle tfvars-Änderungen werden nicht importiert. +Die Ausgabe ist eine Variablendatei, keine abgeschlossene Cloud-/Plan-Abnahme. +Der Configurator startet beim Speichern keinen Plan/Apply. Repository-eigene +GitHub-Workflows unterliegen weiterhin den dort konfigurierten Commit-Triggern. + + + +## Zugriff und Konflikte + +- Jede Anfrage benötigt eine gültige Backend-Session; Schreiben zusätzlich exakte + Origin und sitzungsgebundenen CSRF-Wert. +- Das Backend liest ausschließlich das zu Session, Benutzer und Mandant gehörende + GitHub-App-Benutzertoken aus dem Secrets Manager. Keine GitHub-CLI-, Betreiber- + oder Installation-Tokens für Benutzer-Repositories. +- GitHub bestätigt vor jedem Zugriff Repository-ID, Fork-Status, Schreibrecht und + `source.id == 1168467997` (Accelerator). Archivierte oder deaktivierte Repositories + sowie das Upstream selbst werden abgelehnt. Geänderte Rechte gelten sofort beim + nächsten API-Zugriff; die UI-Auswahl ist kein Berechtigungsnachweis. +- Commit-Ziel ist fest `lzc/configurations`; der Dateipfad wird aus einer UUID + abgeleitet. Symlinks, Submodule, unvollständige Git-Trees und inkompatible Dateien + dürfen nicht überschrieben werden. +- Erwarteter Branch-Commit wird vor dem Schreiben geprüft. Neuer Tree basiert auf + diesem Snapshot und enthält genau die beiden Konfigurationspfade. Neuer Commit hat genau + diesen Parent. Branch-Updates verwenden `force: false`; parallele Änderungen + führen zum Konflikt. Keine automatische Wiederholung mit neuer Basis und kein + stilles Überschreiben. Bei konkurrierender Erstanlage schlägt die Ref-Erstellung + fehl; es bleiben allenfalls nicht referenzierte Git-Objekte zurück. +- Vorhandene tfvars müssen als regulärer Git-Blob exakt dem Export des bisherigen + JSON-Dokuments entsprechen (Git-Blob-Hash inklusive UTF-8-Länge). Abweichungen, + Symlinks und verwaiste Exportdateien führen vor Schreibzugriffen zum Konflikt. + Fehlende Exporte werden ergänzt. Bei zukünftigen Änderungen am Serializer ist + eine explizite Exportmigration erforderlich; niemals den Vergleich umgehen. +- Bei Netzwerkabbruch bleibt das Ergebnis zunächst unklar. Die UI behält die + Konfigurations-ID und den Entwurf; Benutzer sollen den GitHub-Stand prüfen und + gegebenenfalls neu öffnen. Ein Wiederholungsversuch überschreibt keinen neuen Head. +- Fremde Template-Versionen werden zurückgewiesen, nicht still konvertiert. + Backend und Frontend verwenden denselben aus HCL generierten Katalog. + +GitHub verlangt für automatische Fork-Erstellung bei GitHub Apps am Zielaccount +Zugriff auf alle Repositories und Zugriff auf das Quellrepo am Quellaccount. Wir +weiten dafür keine Installationsrechte aus. Der GitHub-Fork-Dialog ist der aktuelle +Erstellungsweg; eine automatische API-Erstellung bleibt offen. + + + +## URLs und History + +| Ansicht | URL | +| --- | --- | +| Template-Katalog | `/templates` (auch `/`) | +| Template-Vorschau | `/templates/` | +| Editor | `/configurations/edit/basics`, `/projects`, `/review` unter demselben Präfix | +| Fork-Auswahl | `/repositories` | + +Ansichtswechsel und Editor-Schritte verwenden `history.pushState`. `popstate` +stellt die Ansicht bei Zurück/Vorwärts wieder her; Eingaben bleiben im laufenden +Tab erhalten. Nur die kurzen OAuth-Weiterleitungen sichern Entwürfe zeitlich +begrenzt im Session-Speicher. Ein normaler Reload ersetzt keine Git-Speicherung; +ohne lokalen Entwurf bietet der Editor die Wiederherstellung aus einem Fork an. + +Der API-Server liefert das UI nur für ausdrücklich bekannte Seitenpfade. Fehlende +API-/Auth-Endpunkte und Assets behalten ihre Fehlerantwort. Direkte Vorschau-Links +und Reload sind dadurch auch auf CF möglich. + + + +## Abnahme und nächste Schritte + +- [x] 35 Anwendungstests: Herkunft/ID/Rechte, Session/CSRF, Pfadschutz, Commit-Inhalt, + veralteter Head, konkurrierendes Schreiben und Erstanlage. +- [x] Zwölf Browserfälle auf Desktop/Mobilgeräten: Editor, Login, History, Deep Links, + Fork-Auswahl, Konflikt, neue Kopie und Wiederöffnen nach Reload. +- [x] HCL-Importer geprüft; gemeinsamer Katalog bytegleich zum bisherigen Stand. +- [x] [Validierung 36700860848](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36700860848) und [Release 36700861231](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36700861231) erfolgreich (`c77345a`). +- [x] Live-Browser: Vorschau-URL, Editor-Schritte, Zurück/Vorwärts, Entwurfserhalt, + Fork-URL und Reload geprüft; anonyme Lese-/Schreibzugriffe 401, fehlende Assets 404. + Test ohne Benutzer-Session und ohne echte Repository-Schreibzugriffe. +- [x] Persönlichen Fork verbinden und echten GitHub-Commit über UI abnehmen (Benutzerbestätigung). +- [x] Feldhilfen einschließlich stabiler Kennung und Ressourcenpräfix ergänzen. +- [x] HCL-Export: alle acht Vorlagen und Sonderzeichen mit echtem HCL-Parser semantisch rückvergleichen; atomare JSON-/tfvars-Ablage und Konfliktschutz testen. +- [ ] PR-Workflow für geschützte Arbeitsbranches ergänzen; derzeit klare Fehlermeldung. +- [ ] Automatische Fork-Erstellung bei passenden Installationsvoraussetzungen. +- [ ] Versionierte Compiler-Ausgabe und Deployment-Unterstützung. +- [ ] Ausbau der Pagination: derzeit 25 Repository-Einträge je Seite (max. 100 Seiten), + höchstens 30 Konfigurationsdateien im ausgewählten Branch. Nicht unterstützte + Dateien und abgeschnittene Konfigurationslisten werden angezeigt. + +Quellen: +- https://docs.github.com/en/rest/repos/forks#create-a-fork +- https://docs.github.com/en/rest/repos/repos#list-repositories-for-the-authenticated-user +- https://docs.github.com/en/rest/git/refs +- https://docs.github.com/en/rest/git/trees + + + +## Bedeutung der Projektfelder und Verwendung des Exports + +- **Eindeutige Kennung:** Schlüssel in `landing_zones`, damit stabile Zuordnung für + OpenTofu-`for_each` und Referenzen. Beispiel `kundenportal-prod`. Änderungen nach + Deployment benötigen eine geplante State-/Adressmigration, sonst droht Neuerstellung. +- **Projektkürzel:** Bestandteil des Ressourcenpräfixes, beispielsweise + `acme-lz-portal-prod` aus Unternehmenskürzel `acme`, Projektkürzel `portal` und + Umgebung `prod`. Es fließt gegebenenfalls auch in DNS-Namen ein. Änderungen können + Ressourcen umbenennen oder ersetzen. +- **Projektname:** lesbarer Name im Konfigurator. Der aktuelle Root-Accelerator gibt + `project_name` nicht an das Landing-Zone-Modul weiter; der STACKIT-Projektname + entsteht daher aus dem Präfix. Sandbox-Namen gehen dagegen in Projektname und + Ressourcenidentität ein. + +Bei manueller Verwendung im passenden, initialisierten Accelerator-Checkout: + +```sh +tofu -chdir=src plan -var-file=config/custom//landing-zone.tfvars +``` + +Zugangsdaten und Backend müssen dafür separat eingerichtet sein. Der Configurator +wählt den freigegebenen Accelerator-Code für zukünftige verwaltete Deployments; +der Export allein führt keinen Plan oder Apply aus. Vor einem ersten Cloud-Deployment +bleiben Provider-/Variablenvalidierung und Plan-Abnahme erforderlich. + + + +### Abnahme Feldhilfen und tfvars-Export + +Commit `c2f15e2`, nur Feature-Branch. [Validierung 36703394675](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36703394675) +und [Release 36703394711](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36703394711) +erfolgreich. 35 Anwendungstests, zwölf Browserfälle, PostgreSQL-Integration und +HCL-Roundtrip-Prüfung grün. CF-Verbindungstests zu PostgreSQL und Secrets Manager +erfolgreich. Mobile Live-Prüfung bestätigt zugängliche Feldhilfen, nativen +`landing-zone.tfvars`-Download, keine Browserfehler und keinen horizontalen Überlauf; +Screenshot visuell geprüft. Kein Benutzer-Login oder echter Fork-Schreibzugriff +für diesen Live-Test. Die neue Ausgabe beider Dateien ist zusätzlich mit der +GitHub-API-Testdouble geprüft; persönliche Abnahme des vorherigen JSON-Speicherns +ist bestätigt. Bestehende Konfiguration erneut speichern, um tfvars hinzuzufügen. + + + +## Arbeitsstand beim Wiederkommen + +Nach Anmeldung werden Forks automatisch geladen. Im selben Browser merkt sich die +App pro Benutzer-ID und Mandant den ausgewählten Fork, die Konfigurationsbindung, +den Editor-Entwurf und die letzte Seite einschließlich Editor-Schritt. Ein Aufruf +von `/` setzt dort fort; explizite Links behalten ihre Zielseite. Der Zugriff auf +einen gespeicherten Fork wird vor dem Wiederherstellen erneut serverseitig geprüft. + +Die lokale Kopie erhält auch noch unvollständige oder ungespeicherte Eingaben. Sie +behält den ursprünglichen Git-Commit als Schreibbasis: ein inzwischen geänderter +Branch führt weiterhin zum Konflikt, niemals zum automatischen Überschreiben. +Bei einem Zugriffs-/Netzwerkfehler bleibt die lokale Wiederherstellungskopie +unangetastet. Ein Wechsel auf einen anderen Fork ist eine bewusste neue Auswahl. +Logout/Identitätswechsel entfernt den sichtbaren Entwurf; andere angemeldete +Konten bekommen diese lokale Auswahl nicht zugeordnet. + +Ablage: `localStorage`, Schema 1, mit Template-Hash und Größen-/Formprüfung. Keine +GitHub-/STACKIT-Schlüssel, CSRF-Werte oder Sessions. Konfigurationsinhalte wie +Organisations-ID und Verantwortlichenadressen liegen dabei lokal im Browserprofil; +das ist keine verschlüsselte Ablage oder Trennung gegenüber Personen mit Zugriff +auf dieses Browserprofil. Browserverlauf/-daten löschen entfernt auch diesen +Arbeitsstand. Auf einem anderen Gerät bleibt der explizit gespeicherte Fork die +Quelle; geräteübergreifende Arbeitsstände sind noch nicht implementiert. +Bei deaktiviertem/vollen Browserspeicher wird im Fork-Bereich ein Fehler angezeigt. +**Im Fork speichern** bleibt ausdrücklich erforderlich für die Git-Ablage. + + +Ordneranpassungen verwenden Dokumentversion 2 mit vier stabilen Schlüsseln in +`draft.folders`. Version 1 bleibt ohne Ordnerüberschreibung kompatibel und exportiert +unverändert. Siehe [gemeinsamer Editor](common-editor.de.md). diff --git a/landing-zone-configurator/docs/forks-and-navigation.md b/landing-zone-configurator/docs/forks-and-navigation.md index f316705..6182fbd 100644 --- a/landing-zone-configurator/docs/forks-and-navigation.md +++ b/landing-zone-configurator/docs/forks-and-navigation.md @@ -1,192 +1,202 @@ -# Fork-Speicherung und Browser-Navigation + +# Fork storage and browser navigation -Stand: 2026-09-30. Auf lzc-dev bereitgestellt; Browser-Navigation live geprüft. Fork-Erstellung, App-Zugriff und persönliches Speichern durch den Benutzer bestätigt. +[English](forks-and-navigation.md) | [Deutsch](forks-and-navigation.de.md) -## Benutzerablauf +As of 2026-09-30. Deployed on lzc-dev; browser navigation checked live. Fork creation, app access and personal saving confirmed by the user. -1. Mit GitHub anmelden und links **GitHub-Forks** öffnen. -2. Bei Bedarf **Fork bei GitHub erstellen** verwenden. Die Erstellung bestätigt - der Benutzer direkt bei GitHub. -3. **App-Zugriff auf Fork einrichten** öffnen und die App auf ausgewählten eigenen - Repositories installieren (`Only select repositories`). -4. **Forks aktualisieren**, gegebenenfalls **Weitere Repositories prüfen**, dann - den gewünschten Fork auswählen. -5. Einen Standalone-Entwurf vollständig ausfüllen und **Im Fork speichern** wählen. - Beim ersten Speichern entsteht der Arbeitsbranch `lzc/configurations` aus dem - aktuellen Default-Branch des Forks. Der Default-Branch wird nicht verändert. -6. Gespeicherte Konfigurationen lassen sich über denselben Bereich wieder öffnen, - bearbeiten und als neue Revision speichern. **Neue Kopie vorbereiten** gibt dem - aktuellen Entwurf eine neue Identität, sobald er gespeichert wird. + +## User flow -Aktuelles kanonisches Dateiformat: +1. Sign in with GitHub and open **GitHub forks** on the left. +2. Use **Create fork on GitHub** if needed. The user confirms creation + directly on GitHub. +3. Open **Set up app access to fork** and install the app on selected own + repositories (`Only select repositories`). +4. **Refresh forks**, optionally **Check more repositories**, then + select the desired fork. +5. Complete a Standalone draft and select **Save to fork**. + First save creates the working branch `lzc/configurations` from the + fork's current default branch. The default branch is not changed. +6. Saved configurations can be reopened in the same area, + edited and saved as a new revision. **Prepare new copy** gives the + current draft a new identity when it is saved. + +Current canonical file format: ```text src/config/custom//landing-zone.json src/config/custom//landing-zone.tfvars ``` -Enthalten sind Schema-Version, Konfigurations-ID, freigegebene Template-Identität -mit Quellhash und der fachliche Editor-Entwurf. `kind` ist -`landing-zone-configurator-configuration`; dies unterscheidet die bearbeitbare -Ablage vom bisherigen Downloadformat. Unbekannte Eingabefelder werden nicht -übernommen. Keine Zugangsdaten, GitHub-Tokens, Terraform-Module oder HCL-Ausdrücke -werden als zusätzliche Nutzdaten angenommen. Der deterministische Export erzeugt zusätzlich -`landing-zone.tfvars` in nativem HCL. Download und Backend verwenden denselben Serializer. -Zeichenketten bleiben Daten, auch bei `${…}` und `%{…}`. Der Export übernimmt die -validierte Standalone-Konfiguration einschließlich unveränderter Vorlagenattribute. -Bisherige JSON-only-Konfigurationen erhalten beim nächsten Speichern die zweite Datei. -Die JSON-Datei bleibt die Quelle für den Editor; manuelle tfvars-Änderungen werden nicht importiert. -Die Ausgabe ist eine Variablendatei, keine abgeschlossene Cloud-/Plan-Abnahme. -Der Configurator startet beim Speichern keinen Plan/Apply. Repository-eigene -GitHub-Workflows unterliegen weiterhin den dort konfigurierten Commit-Triggern. - -## Zugriff und Konflikte - -- Jede Anfrage benötigt eine gültige Backend-Session; Schreiben zusätzlich exakte - Origin und sitzungsgebundenen CSRF-Wert. -- Das Backend liest ausschließlich das zu Session, Benutzer und Mandant gehörende - GitHub-App-Benutzertoken aus dem Secrets Manager. Keine GitHub-CLI-, Betreiber- - oder Installation-Tokens für Benutzer-Repositories. -- GitHub bestätigt vor jedem Zugriff Repository-ID, Fork-Status, Schreibrecht und - `source.id == 1168467997` (Accelerator). Archivierte oder deaktivierte Repositories - sowie das Upstream selbst werden abgelehnt. Geänderte Rechte gelten sofort beim - nächsten API-Zugriff; die UI-Auswahl ist kein Berechtigungsnachweis. -- Commit-Ziel ist fest `lzc/configurations`; der Dateipfad wird aus einer UUID - abgeleitet. Symlinks, Submodule, unvollständige Git-Trees und inkompatible Dateien - dürfen nicht überschrieben werden. -- Erwarteter Branch-Commit wird vor dem Schreiben geprüft. Neuer Tree basiert auf - diesem Snapshot und enthält genau die beiden Konfigurationspfade. Neuer Commit hat genau - diesen Parent. Branch-Updates verwenden `force: false`; parallele Änderungen - führen zum Konflikt. Keine automatische Wiederholung mit neuer Basis und kein - stilles Überschreiben. Bei konkurrierender Erstanlage schlägt die Ref-Erstellung - fehl; es bleiben allenfalls nicht referenzierte Git-Objekte zurück. -- Vorhandene tfvars müssen als regulärer Git-Blob exakt dem Export des bisherigen - JSON-Dokuments entsprechen (Git-Blob-Hash inklusive UTF-8-Länge). Abweichungen, - Symlinks und verwaiste Exportdateien führen vor Schreibzugriffen zum Konflikt. - Fehlende Exporte werden ergänzt. Bei zukünftigen Änderungen am Serializer ist - eine explizite Exportmigration erforderlich; niemals den Vergleich umgehen. -- Bei Netzwerkabbruch bleibt das Ergebnis zunächst unklar. Die UI behält die - Konfigurations-ID und den Entwurf; Benutzer sollen den GitHub-Stand prüfen und - gegebenenfalls neu öffnen. Ein Wiederholungsversuch überschreibt keinen neuen Head. -- Fremde Template-Versionen werden zurückgewiesen, nicht still konvertiert. - Backend und Frontend verwenden denselben aus HCL generierten Katalog. - -GitHub verlangt für automatische Fork-Erstellung bei GitHub Apps am Zielaccount -Zugriff auf alle Repositories und Zugriff auf das Quellrepo am Quellaccount. Wir -weiten dafür keine Installationsrechte aus. Der GitHub-Fork-Dialog ist der aktuelle -Erstellungsweg; eine automatische API-Erstellung bleibt offen. - -## URLs und History - -| Ansicht | URL | +It contains schema version, configuration ID, approved template identity +with source hash and the domain editor draft. `kind` is +`landing-zone-configurator-configuration`; this distinguishes editable +storage from the previous download format. Unknown input fields are not +adopted. No credentials, GitHub tokens, Terraform modules or HCL expressions +are accepted as additional payload. Deterministic export additionally produces +`landing-zone.tfvars` in native HCL. Download and backend use the same serializer. +Strings remain data, even with `${…}` and `%{…}`. Export uses the +validated Standalone configuration including unchanged template attributes. +Previous JSON-only configurations receive the second file on next save. +The JSON file remains the editor's source; manual tfvars changes are not imported. +Output is a variable file, not complete cloud/Plan acceptance. +The Configurator starts no Plan/Apply when saving. Repository-specific +GitHub workflows remain subject to their configured commit triggers. + + +## Access and conflicts + +- Every request requires a valid backend session; writes additionally require exact + origin and session-bound CSRF value. +- The backend reads only the GitHub App user token belonging to the session, user + and tenant from Secrets Manager. No GitHub CLI, operator + or installation tokens for user repositories. +- Before each access, GitHub confirms repository ID, fork status, write permission and + `source.id == 1168467997` (Accelerator). Archived or disabled repositories + and upstream itself are rejected. Changed permissions apply immediately on + the next API access; UI selection is not proof of permission. +- Commit target is fixed to `lzc/configurations`; the file path is derived from + a UUID. Symlinks, submodules, incomplete Git trees and incompatible files + must not be overwritten. +- Expected branch commit is checked before writing. The new tree is based on + this snapshot and contains exactly the two configuration paths. The new commit has exactly + this parent. Branch updates use `force: false`; parallel changes + cause a conflict. No automatic retry on a new base and no + silent overwrite. On concurrent initial creation, ref creation + fails; at most unreferenced Git objects remain. +- Existing tfvars must, as a regular Git blob, exactly match the export of the previous + JSON document (Git blob hash including UTF-8 length). Deviations, + symlinks and orphan export files cause a conflict before writes. + Missing exports are added. Future serializer changes require + an explicit export migration; never bypass the comparison. +- A network interruption initially leaves the result uncertain. The UI preserves + configuration ID and draft; users should check GitHub's state and + reopen if necessary. A retry does not overwrite a new head. +- Other template versions are rejected, not silently converted. + Backend and frontend use the same HCL-generated catalogue. + +GitHub requires GitHub Apps to have access to all repositories on the target account +and access to the source repo on the source account for automatic fork creation. +We do not expand installation permissions for this. The GitHub fork dialog is the current +creation path; automatic API creation remains open. + + +## URLs and history + +| View | URL | | --- | --- | -| Template-Katalog | `/templates` (auch `/`) | -| Template-Vorschau | `/templates/` | -| Editor | `/configurations/edit/basics`, `/projects`, `/review` unter demselben Präfix | -| Fork-Auswahl | `/repositories` | - -Ansichtswechsel und Editor-Schritte verwenden `history.pushState`. `popstate` -stellt die Ansicht bei Zurück/Vorwärts wieder her; Eingaben bleiben im laufenden -Tab erhalten. Nur die kurzen OAuth-Weiterleitungen sichern Entwürfe zeitlich -begrenzt im Session-Speicher. Ein normaler Reload ersetzt keine Git-Speicherung; -ohne lokalen Entwurf bietet der Editor die Wiederherstellung aus einem Fork an. - -Der API-Server liefert das UI nur für ausdrücklich bekannte Seitenpfade. Fehlende -API-/Auth-Endpunkte und Assets behalten ihre Fehlerantwort. Direkte Vorschau-Links -und Reload sind dadurch auch auf CF möglich. - -## Abnahme und nächste Schritte - -- [x] 35 Anwendungstests: Herkunft/ID/Rechte, Session/CSRF, Pfadschutz, Commit-Inhalt, - veralteter Head, konkurrierendes Schreiben und Erstanlage. -- [x] Zwölf Browserfälle auf Desktop/Mobilgeräten: Editor, Login, History, Deep Links, - Fork-Auswahl, Konflikt, neue Kopie und Wiederöffnen nach Reload. -- [x] HCL-Importer geprüft; gemeinsamer Katalog bytegleich zum bisherigen Stand. -- [x] [Validierung 36700860848](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36700860848) und [Release 36700861231](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36700861231) erfolgreich (`c77345a`). -- [x] Live-Browser: Vorschau-URL, Editor-Schritte, Zurück/Vorwärts, Entwurfserhalt, - Fork-URL und Reload geprüft; anonyme Lese-/Schreibzugriffe 401, fehlende Assets 404. - Test ohne Benutzer-Session und ohne echte Repository-Schreibzugriffe. -- [x] Persönlichen Fork verbinden und echten GitHub-Commit über UI abnehmen (Benutzerbestätigung). -- [x] Feldhilfen einschließlich stabiler Kennung und Ressourcenpräfix ergänzen. -- [x] HCL-Export: alle acht Vorlagen und Sonderzeichen mit echtem HCL-Parser semantisch rückvergleichen; atomare JSON-/tfvars-Ablage und Konfliktschutz testen. -- [ ] PR-Workflow für geschützte Arbeitsbranches ergänzen; derzeit klare Fehlermeldung. -- [ ] Automatische Fork-Erstellung bei passenden Installationsvoraussetzungen. -- [ ] Versionierte Compiler-Ausgabe und Deployment-Unterstützung. -- [ ] Ausbau der Pagination: derzeit 25 Repository-Einträge je Seite (max. 100 Seiten), - höchstens 30 Konfigurationsdateien im ausgewählten Branch. Nicht unterstützte - Dateien und abgeschnittene Konfigurationslisten werden angezeigt. - -Quellen: +| Template catalogue | `/templates` (also `/`) | +| Template preview | `/templates/` | +| Editor | `/configurations/edit/basics`, `/projects`, `/review` under the same prefix | +| Fork selection | `/repositories` | + +View changes and editor steps use `history.pushState`. `popstate` +restores the view on back/forward; inputs remain in the running +tab. Only short OAuth redirects secure drafts for a limited time +in session storage. A normal reload does not replace Git saving; +without a local draft the editor offers restoration from a fork. + +The API server serves the UI only for explicitly known page paths. Missing +API/auth endpoints and assets retain their error response. Direct preview links +and reload are therefore also possible on CF. + + +## Acceptance and next steps + +- [x] 35 application tests: origin/ID/permissions, session/CSRF, path protection, commit content, + stale head, concurrent writing and initial creation. +- [x] Twelve desktop/mobile browser cases: editor, login, history, deep links, + fork selection, conflict, new copy and reopening after reload. +- [x] HCL importer checked; common catalogue byte-identical to the previous state. +- [x] [Validation 36700860848](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36700860848) and [release 36700861231](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36700861231) successful (`c77345a`). +- [x] Live browser: preview URL, editor steps, back/forward, draft preservation, + fork URL and reload checked; anonymous reads/writes 401, missing assets 404. + Test without user session or real repository writes. +- [x] Connect personal fork and qualify actual GitHub commit through UI (user confirmation). +- [x] Add field help including stable identifier and resource prefix. +- [x] HCL export: semantically compare all eight templates and special characters with a real HCL parser; test atomic JSON/tfvars storage and conflict protection. +- [ ] Add PR workflow for protected working branches; currently clear error message. +- [ ] Automatic fork creation with suitable installation prerequisites. +- [ ] Versioned compiler output and deployment support. +- [ ] Expand pagination: currently 25 repository entries per page (max. 100 pages), + at most 30 configuration files in the selected branch. Unsupported + files and truncated configuration lists are shown. + +Sources: - https://docs.github.com/en/rest/repos/forks#create-a-fork - https://docs.github.com/en/rest/repos/repos#list-repositories-for-the-authenticated-user - https://docs.github.com/en/rest/git/refs - https://docs.github.com/en/rest/git/trees -## Bedeutung der Projektfelder und Verwendung des Exports + +## Meaning of project fields and using the export -- **Eindeutige Kennung:** Schlüssel in `landing_zones`, damit stabile Zuordnung für - OpenTofu-`for_each` und Referenzen. Beispiel `kundenportal-prod`. Änderungen nach - Deployment benötigen eine geplante State-/Adressmigration, sonst droht Neuerstellung. -- **Projektkürzel:** Bestandteil des Ressourcenpräfixes, beispielsweise - `acme-lz-portal-prod` aus Unternehmenskürzel `acme`, Projektkürzel `portal` und - Umgebung `prod`. Es fließt gegebenenfalls auch in DNS-Namen ein. Änderungen können - Ressourcen umbenennen oder ersetzen. -- **Projektname:** lesbarer Name im Konfigurator. Der aktuelle Root-Accelerator gibt - `project_name` nicht an das Landing-Zone-Modul weiter; der STACKIT-Projektname - entsteht daher aus dem Präfix. Sandbox-Namen gehen dagegen in Projektname und - Ressourcenidentität ein. +- **Unique identifier:** key in `landing_zones`, giving stable assignment for + OpenTofu `for_each` and references. Example `kundenportal-prod`. Changes after + deployment require planned state/address migration, otherwise recreation may occur. +- **Project code:** part of the resource prefix, for example + `acme-lz-portal-prod` from company code `acme`, project code `portal` and + environment `prod`. It may also contribute to DNS names. Changes can + rename or replace resources. +- **Project name:** readable name in the Configurator. The current root Accelerator does + not pass `project_name` to the Landing Zone module; the STACKIT project name + therefore comes from the prefix. Sandbox names, by contrast, contribute to project name and + resource identity. -Bei manueller Verwendung im passenden, initialisierten Accelerator-Checkout: +For manual use in a matching initialized Accelerator checkout: ```sh tofu -chdir=src plan -var-file=config/custom//landing-zone.tfvars ``` -Zugangsdaten und Backend müssen dafür separat eingerichtet sein. Der Configurator -wählt den freigegebenen Accelerator-Code für zukünftige verwaltete Deployments; -der Export allein führt keinen Plan oder Apply aus. Vor einem ersten Cloud-Deployment -bleiben Provider-/Variablenvalidierung und Plan-Abnahme erforderlich. - -### Abnahme Feldhilfen und tfvars-Export - -Commit `c2f15e2`, nur Feature-Branch. [Validierung 36703394675](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36703394675) -und [Release 36703394711](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36703394711) -erfolgreich. 35 Anwendungstests, zwölf Browserfälle, PostgreSQL-Integration und -HCL-Roundtrip-Prüfung grün. CF-Verbindungstests zu PostgreSQL und Secrets Manager -erfolgreich. Mobile Live-Prüfung bestätigt zugängliche Feldhilfen, nativen -`landing-zone.tfvars`-Download, keine Browserfehler und keinen horizontalen Überlauf; -Screenshot visuell geprüft. Kein Benutzer-Login oder echter Fork-Schreibzugriff -für diesen Live-Test. Die neue Ausgabe beider Dateien ist zusätzlich mit der -GitHub-API-Testdouble geprüft; persönliche Abnahme des vorherigen JSON-Speicherns -ist bestätigt. Bestehende Konfiguration erneut speichern, um tfvars hinzuzufügen. - -## Arbeitsstand beim Wiederkommen - -Nach Anmeldung werden Forks automatisch geladen. Im selben Browser merkt sich die -App pro Benutzer-ID und Mandant den ausgewählten Fork, die Konfigurationsbindung, -den Editor-Entwurf und die letzte Seite einschließlich Editor-Schritt. Ein Aufruf -von `/` setzt dort fort; explizite Links behalten ihre Zielseite. Der Zugriff auf -einen gespeicherten Fork wird vor dem Wiederherstellen erneut serverseitig geprüft. - -Die lokale Kopie erhält auch noch unvollständige oder ungespeicherte Eingaben. Sie -behält den ursprünglichen Git-Commit als Schreibbasis: ein inzwischen geänderter -Branch führt weiterhin zum Konflikt, niemals zum automatischen Überschreiben. -Bei einem Zugriffs-/Netzwerkfehler bleibt die lokale Wiederherstellungskopie -unangetastet. Ein Wechsel auf einen anderen Fork ist eine bewusste neue Auswahl. -Logout/Identitätswechsel entfernt den sichtbaren Entwurf; andere angemeldete -Konten bekommen diese lokale Auswahl nicht zugeordnet. - -Ablage: `localStorage`, Schema 1, mit Template-Hash und Größen-/Formprüfung. Keine -GitHub-/STACKIT-Schlüssel, CSRF-Werte oder Sessions. Konfigurationsinhalte wie -Organisations-ID und Verantwortlichenadressen liegen dabei lokal im Browserprofil; -das ist keine verschlüsselte Ablage oder Trennung gegenüber Personen mit Zugriff -auf dieses Browserprofil. Browserverlauf/-daten löschen entfernt auch diesen -Arbeitsstand. Auf einem anderen Gerät bleibt der explizit gespeicherte Fork die -Quelle; geräteübergreifende Arbeitsstände sind noch nicht implementiert. -Bei deaktiviertem/vollen Browserspeicher wird im Fork-Bereich ein Fehler angezeigt. -**Im Fork speichern** bleibt ausdrücklich erforderlich für die Git-Ablage. - - -Ordneranpassungen verwenden Dokumentversion 2 mit vier stabilen Schlüsseln in -`draft.folders`. Version 1 bleibt ohne Ordnerüberschreibung kompatibel und exportiert -unverändert. Siehe [gemeinsamer Editor](common-editor.md). +Credentials and backend must be configured separately. The Configurator +selects approved Accelerator code for future managed deployments; +export alone executes no Plan or Apply. Provider/variable validation and Plan +acceptance remain required before a first cloud deployment. + + +### Acceptance of field help and tfvars export + +Commit `c2f15e2`, feature branch only. [Validation 36703394675](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36703394675) +and [release 36703394711](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36703394711) +successful. 35 application tests, twelve browser cases, PostgreSQL integration and +HCL round-trip check green. CF connection tests to PostgreSQL and Secrets Manager +successful. Mobile live check confirms accessible field help, native +`landing-zone.tfvars` download, no browser errors and no horizontal overflow; +screenshot visually checked. No user login or real fork write access +for this live test. The new two-file output is additionally checked with the +GitHub API test double; personal acceptance of the previous JSON saving +is confirmed. Save an existing configuration again to add tfvars. + + +## Working state on return + +Forks load automatically after login. In the same browser, the +app remembers the selected fork, configuration binding, +editor draft and last page including editor step per user ID and tenant. Opening +`/` resumes there; explicit links keep their destination. Access to +a saved fork is rechecked server-side before restoration. + +The local copy also preserves incomplete or unsaved inputs. It +keeps the original Git commit as its write base: a meanwhile-changed +branch still causes a conflict, never automatic overwrite. +On access/network failure, the local restoration copy remains +untouched. Switching to another fork is a deliberate new selection. +Logout/identity change removes the visible draft; other signed-in +accounts are not assigned this local selection. + +Storage: `localStorage`, schema 1, with template hash and size/shape checks. No +GitHub/STACKIT keys, CSRF values or sessions. Configuration contents such as +organization ID and owner addresses reside locally in the browser profile; +this is neither encrypted storage nor separation from people with access +to this browser profile. Clearing browser history/data also removes +this working state. On another device, the explicitly saved fork remains the +source; cross-device working states are not yet implemented. +Disabled/full browser storage produces an error in the fork area. +**Save to fork** remains explicitly required for Git storage. + + +Folder adjustments use document version 2 with four stable keys in +`draft.folders`. Version 1 remains compatible without folder overrides and exports +unchanged. See [common editor](common-editor.md). diff --git a/landing-zone-configurator/docs/github-login.de.md b/landing-zone-configurator/docs/github-login.de.md new file mode 100644 index 0000000..f926a95 --- /dev/null +++ b/landing-zone-configurator/docs/github-login.de.md @@ -0,0 +1,358 @@ + + +# STACKIT-Login, optionale GitHub-Verbindung und Mandantentrennung + +[English](github-login.md) | [Deutsch](github-login.de.md) + +Stand: 2026-10-06. STACKIT als primärer Login lokal implementiert und getestet. +Die ausdrueckliche Dev-Client-Freigabe ersetzt keine Produktionsregistrierung. +Migrationen bis 039 sind nach privaten Sicherungen und vollstaendigen isolierten +Restore-Pruefungen lokal aktiviert. Echter menschlicher Login, vollstaendiger +Owner-Nachweis und ausdrueckliche Organisationsbindung sind in der bestehenden +Kundenorganisation erfolgreich abgenommen. GitHub bleibt als Legacy-Modus erhalten. + +Seit Migration 058 ist die achtstuendige Configurator-Sitzung unabhaengig von +der kuerzeren STACKIT-Tokenlaufzeit. Beim Login muss der verifizierte Nachweis +weiterhin aktuell sein. Identitaets- und Organisations-Owner-Nachweise behalten +ihre eigenen Ablaufzeiten; abgelaufene Nachweise erlauben weder eine neue +Organisationsbindung noch geschuetzte Cloud-Aktionen. Sie muessen bei Bedarf +erneut bestaetigt werden. Refresh-Tokens werden weiterhin nicht gespeichert. +Logout widerruft die App-Sitzung, und Rollen-/Mandantenpruefungen bleiben aktiv. +Bestehende Sitzungen werden nicht nachtraeglich verlaengert; die neue Laufzeit +gilt nach erneuter Anmeldung. + +Der Web-Login mit Authorization Code und PKCE verwendet denselben Browser-Tab. +Der vorhandene Callback setzt die Anmeldung im Configurator fort; unvollständige +Entwürfe bleiben dabei über den bestehenden tabgebundenen Zwischenspeicher erhalten. +Dies gilt auch für die erneute STACKIT-Bestätigung im Kontobereich. Nur der +kompatible Device-Flow mit Anmeldecode öffnet weiterhin einen separaten Tab, +weil der ursprüngliche Tab für das Polling geöffnet bleiben muss. + +Der Resource Manager liefert fuer die exakt angefragte Organisations-UUID einen +IAM-Containerbezug. Die Pruefung verwendet ausschliesslich diesen Bezug fuer +IAM-Rechte und Rollen; fremde Container bleiben gesperrt. Die reale Antwort mit +965 Owner-Rechten wird vollstaendig geprueft. Parser und Migration 037 erlauben +hoechstens 4096 Rechte, bei unveraenderter Antwortgroessen- und Autoritaetspruefung. +Migration 023 wurde nicht veraendert. Der PKCE-Nachweis kehrt zu +`/organisation#stackit-proof` zurueck; geschuetztes Polling setzt ihn fort. +Die Benutzerverwaltung erlaubt auch nach erfolgter Bindung eine erneute +zeitlich begrenzte Owner-Pruefung, ohne eine weitere Bindung anzubieten. + + + +## CLI-PKCE und Nachweisdiagnose + +Die folgenden Diagnose- und Aktivierungsabschnitte dokumentieren historische +Zwischenstaende. Fuer die aktuelle Abnahme gilt der Stand oberhalb dieses Abschnitts. + +Ein anonymer Browser ohne bestehende STACKIT-Sitzung erreicht mit dem freigegebenen +CLI-Device-Client die Provider-Seite `/ui/login/user`, aber nur mit einem +Weiter-Button und versteckten Formularfeldern, ohne Login-Eingabe. Weiter fuehrt +wieder auf dieselbe Seite. Dies wurde auch mit `openid email profile` und mit +manueller Code-Eingabe am Basis-Bestaetigungslink reproduziert. Scope- oder +Linkwechsel sind daher kein belegter Fix. Der Vergleich mit dem lokal geklonten +STACKIT-CLI korrigiert die urspruengliche Einordnung als allgemeiner Providerfehler: +`stackit auth login` verwendet Authorization Code mit PKCE, nicht Device Flow. +Ein frischer anonymer CLI-artiger Authorization-Code-Aufruf liefert tatsaechlich +ein Benutzernamenfeld. Der vollstaendige menschliche Login ist noch nicht abgenommen. + +Der lokale Startscript verwendet jetzt denselben CLI-Client, S256-PKCE und +`openid offline_access email`. Zusaetzlich schuetzen zufaelliger State und Nonce +den Browserflow. Ein Loopback-Listener waehlt einen freien Port zwischen 8000 und +8020 und verwendet exakt `http://localhost:` als registrierten Callback. +Die Weiterleitung ist auf den festen lokalen Configurator-Origin begrenzt; +Code und Callback-URLs werden nicht geloggt. Der Configurator-Callback verlangt +das urspruengliche Browsercookie bzw. die echte Nachweissitzung und denselben +Tenant. Fremde, abgelaufene, wiederholte oder unpassende Callbacks werden abgelehnt. +Erst das bestehende browsergebundene Polling tauscht den Code mit dem Verifier +aus und prueft signiertes ID-Token, Nonce, Issuer, Audience und Userinfo. Der +Callback erzeugt keine Sitzung und bindet keine Organisation automatisch. +Refresh-Tokens werden trotz CLI-kompatiblem Scope nicht gespeichert. + +PKCE ist nur lokal vorbereitet, nicht in der laufenden API aktiviert. Der +Standard-Device-Flow bleibt kompatibel. Der CLI-Loopback-Callback ist kein +Deployment-Verfahren fuer gehostete Apps; ein eigener registrierter Web-OIDC-Client +mit passendem Callback bleibt fuer Produktion erforderlich. Bestehende Sitzungen +und die pausierten Application-Migrationen werden nicht automatisch veraendert. + +Die Nachweisoberflaeche zeigt den angemeldeten Configurator-Benutzer und die +zuletzt bestaetigte STACKIT-E-Mail. Abgelaufene Nachweise bleiben als solche +gekennzeichnet; Benutzer-/Tenantwechsel entfernen die bisherige Anzeige. +Bekannte Zugriffs-, Berechtigungs-, Identitaets- und Provider-Antwortfehler haben +kontrollierte DE/EN-Meldungen. Unbekannte Codes und Providerdetails werden nicht +angezeigt. Fehler erlauben weder Organisationsbindung noch Wiederverwendung +alter Owner-Rechte. Der echte gemeldete Organisationsfehler ist noch nicht +identifiziert: im eigenen authentifizierten Browser neu laden, Nachweis pruefen +und die konkrete Meldung samt angezeigter Identitaet pruefen. Keine Tokens teilen. + +Nachweise: 61 Device-/Uebersetzungstests, TypeScript und 14 vorhandene erweiterte +Desktop-/Mobil-Browserfaelle bestanden. Die Browserfaelle verwenden synthetische +Identitaeten und gemockte APIs; sie sind keine reale Organisationsabnahme. +Keine API-Neustarts, Kundenmigrationen, Cloud-Plans oder Applies fuer diese +Diagnoseaenderung. #91 bleibt offen. + +PKCE-Folgepruefung: 62 Auth-Tests, insgesamt 395 Tests mit 45 erwarteten Skips, +TypeScript sowie 4 Login- und 16 Nachweis-Browserfaelle bestanden. Vor der +Wiederaufnahme stoppt der globale `npm run check` an fuenf Format-/Importdiagnosen +in den pausierten Applied-Platform-Aenderungen; der begrenzte Login-Biome-Check +hat keine Fehler. Diese historische Blockade wurde bei der Wiederaufnahme behoben. + + + +### Lokale Aktivierung (2026-10-06) + +Der freigegebene Login-only-Stand ist lokal aktiviert. Ein isolierter Runtime-Stand +enthält Basis `056d4df`, Nachweisoberflaeche `929f7fd` und CLI-PKCE `ce6db69`, aber +nicht die nachfolgenden Gruppen-/Application-Migrationen. Vor dem API-Neustart +wurde die private Sicherung vollstaendig in einem eigenen PostgreSQL-Container +wiederhergestellt und der unveraenderte Migrationsstand 034 geprueft. Nach dem +Neustart sind alle 33 Kundentabellen unveraendert. Der bisherige Plattform-Runner +bleibt derselbe; Application-Ausfuehrung bleibt deaktiviert. + +Der reale anonyme Start ueber die laufende UI erreicht die Provider-Seite mit +sichtbarem Benutzernamenfeld und ohne Device-Code. Der eigene Pruefflow wurde +beendet. Vollstaendiger menschlicher Login und echter Organisationsnachweis +bleiben noch abzunehmen; #91 bleibt offen. Die isolierte Aktivierung erlaubt +keinen ungeprueften Start des aktuellen Repository-Scripts mit Migrationen 035/036. + + + +### Rueckkehr-Tab und Session-Uebernahme + +Der Nutzer bestaetigt den erfolgreichen Login bei STACKIT, aber die App im +Rueckkehr-Tab blieb unangemeldet. Die bisherige Initialisierung fragte die Session +nur einmal ab; zum Zeitpunkt der Rueckkehr konnte das urspruengliche Tab den +Code noch nicht per geschuetztem Polling in eine Session umgewandelt haben. +Zwei neue Sessions waren bereits gespeichert, ohne dass dies den geoeffneten +Rueckkehr-Tab aktualisierte. + +Der Callback leitet jetzt zum festen `/#stackit-login` am Configurator-Origin. +Der Marker enthaelt weder Code noch Tokens und wird aus der Browseradresse +entfernt. Das Rueckkehr-Tab setzt das browsergebundene Polling selbst fort, +auch wenn das Ursprungstab geschlossen wurde. Hat ein anderes Tab den Flow +bereits abgeschlossen, wird ausschliesslich die vom Server anhand des echten +Session-Cookies bestaetigte Session eingelesen. Ein Marker ohne gueltigen Flow +oder Session erzeugt keine Anmeldung. State-, Nonce-, Replay- und Cookie-Gates +bleiben unveraendert; der Callback selbst erzeugt weiterhin keine Session. + +Der Login-only-Fix ist nach erneuter privater Sicherung lokal aktiviert; +Schema bleibt 034, alle 33 Kundentabellen sind nach Neustart unveraendert. +62 Auth- und 10 Desktop-/Mobil-Loginfaelle bestehen, einschliesslich Rueckkehr +ohne Ursprungstab und Parallelabschluss. Die Browserfaelle verwenden API-Mocks. +Die tatsaechliche Anzeige im Browser des Nutzers muss nochmals geprueft werden. + + + +## Primärer STACKIT-Login + +Platform Engineer und Application Owner melden sich mit ihrer persönlichen +STACKIT-Identität an und wählen bei mehreren Mitgliedschaften ihren aktiven Tenant. +Der Application Owner benötigt weder GitHub noch einen Service Account. +Der Platform Engineer hinterlegt den technischen STACKIT-Service-Account-Zugang; +Produktkataloge verwenden danach denselben Zugang automatisch, ohne weitere +Profil- oder Projektwahl im Editor. Persönliche Login-Tokens werden nicht für +technische STACKIT-Automatisierungen gespeichert oder wiederverwendet. + +`POST /auth/stackit/start` beginnt den konfigurierten browsergebundenen Flow. +Lokal ist dies CLI-PKCE; ohne explizite Flow-Factory bleibt es Device Flow. +Beim Device Flow erhält der Browser den öffentlichen Bestätigungscode und den +STACKIT-Bestätigungslink, bei PKCE nur den Authorization-Link ohne Device-Code. +`/auth/stackit/poll` verifiziert die Identität serverseitig +und erzeugt die normale opaque Session. Ein vorhandenes ID-Token wird vollständig +geprüft; fehlt es, wird ausschließlich Userinfo mit dem im selben Device Grant +erhaltenen Access Token verwendet. Ein bestätigtes persönliches Konto ist Pflicht. +Issuer und Subject bestimmen den stabilen Benutzer, niemals allein die E-Mail-Adresse. + +Device-Cookies sind `Secure`, `HttpOnly`, `SameSite=Strict`; fuer die PKCE- +Callback-Rueckkehr verwendet die Browserbindung `SameSite=Lax`. Sessions verwenden +`SameSite=Lax`. Pre-Auth-POSTs verlangen die exakte Origin, authentifizierte +Änderungen zusätzlich CSRF. Sessions gelten höchstens acht Stunden und enden +spätestens 30 Sekunden vor dem Provider-Token. Kein Refresh-Token wird behalten. +Offene Device-Flows liegen nur im Speicher einer Instanz: Neustart verwirft sie; +mehrere Instanzen benötigen vor Aktivierung eine gemeinsame Ablage oder Sticky Routing. + + + +## Autoritativer Organisationsnachweis + +Login oder Resource-Manager-Lesezugriff sind kein Adminnachweis. Im aktiven +Organisationsarbeitsbereich startet ein Platform Engineer mit Mitgliederverwaltung +die Pruefung ausdruecklich. Dabei wird sein bisheriger aktueller +Organisationsnachweis entfernt; menschliche Identitaet und historische Audits +bleiben erhalten. Ein fehlgeschlagener neuer Nachweis darf keine alte +Owner-Freigabe wiederverwenden. + +Der neue Device Grant verifiziert dieselbe menschliche Identitaet und die exakte +Organisation. Derselbe kurzlebige menschliche Bearer Token fragt am festen +IAM-Origin `https://authorization.api.stackit.cloud` folgende APIs ab: + +- `GET /v2/users/{verifiedEmail}/permissions?resourceType=organization&resource={verifiedOrganizationResourceId}` +- `GET /v2/organization/{verifiedOrganizationResourceId}/roles` + +`verifiedOrganizationResourceId` ist der Containerbezug aus der erfolgreich +geprueften Resource-Manager-Antwort, ersatzweise deren Organisations-UUID, falls +kein Containerbezug geliefert wurde. Zurueckgegebene IAM-Ressourcen muessen exakt +diesem Bezug entsprechen; die gebundene Organisation behaelt ihre echte UUID. + +Antworten werden auf Organisation, Ressourcentyp, Umfang und Struktur geprueft. +Das konservative Minimum umfasst alle Rechte genau einer nicht leeren +offiziellen `owner`-Rolle. Die effektiven Benutzerrechte muessen diesen Satz +vollstaendig enthalten. Leserechte, fehlende/mehrdeutige Owner-Rollen und +gesperrte Rollenabfragen erteilen keine Bindungsautoritaet. Grundlage ist der +offizielle STACKIT-Go-SDK-Vertrag, Revision +`7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9`, `services/authorization/v2api`. + +Erst eine separate Bestaetigung sendet +`POST /api/v1/stackit/identity/bind-organization` mit ausschliesslich +`{"confirmOrganizationBinding":true}`. Origin, CSRF, Tenant, echte aktuelle +DB-Session, PE-Rolle, Mitgliederverwaltung und nicht abgelaufene/widerrufene +Identitaets-/Owner-Nachweise werden erneut geprueft. SQL-seitig erzeugte +unveraenderliche Autorisierungsbelege binden Organisation, Benutzer, +Issuer/Subject, Rechte und Gueltigkeit. Die atomare Bindung referenziert diesen +Beleg im Audit; Wiederholungen liefern denselben Bindungsbeleg. + +Migrationen `023_organization_authorizations.sql` und +`024_organization_binding.sql` sind erforderlich. Alte APIs ohne Capability +zeigen die Steuerung nicht an. `organization_verified` bezeichnet die +historisch bestaetigte Zuordnung, nicht unbegrenzte aktuelle Owner-Rechte. +Die Bindung startet weder Cloud-Plan noch Apply und ersetzt keinen technischen +Job-Grant. Echte Zwei-Organisations-Abnahme, Produktions-Client-Registrierung +und Least-Privilege-Providerqualifizierung bleiben fuer #91 erforderlich. + + + +## GitHub nur für Repository-Funktionen + +Im STACKIT-Modus ist GitHub erst unter GitHub-Forks über **GitHub verbinden** nötig. +Der Start erfolgt authentifiziert per `POST /auth/github/connect` mit Origin/CSRF. +Der OAuth-Callback ist an dieselbe bestehende Session gebunden und verbindet die +geprüfte GitHub-ID mit diesem Benutzer, ohne Benutzer oder Tenant zu wechseln. +Bereits anderweitig zugeordnete Identitäten werden abgelehnt; Konten werden nicht +anhand gleicher E-Mail-Adressen zusammengeführt. Die Verbindung ist für Login und +Application-Owner-Bestellungen nicht erforderlich. + +Der bestehende forkbasierte Plattform-Plan bleibt eine Repository-Funktion und +benötigt deshalb weiterhin diese optionale Verbindung. Ein echter isolierter +Application-Plan ist durch diese Login-Änderung noch nicht angeschlossen. + + + +## Aktivierung und Bestandskonten + +Vor Aktivierung müssen Migrationen `011_stackit_identity.sql` und +`012_stackit_login.sql` angewendet sein. Mit `LZC_AUTH_ENABLED=true` und +`LZC_STACKIT_DEVICE_ENABLED=true` wird STACKIT primär; GitHub-Client-ID und +Client-Secret sind dann optional, müssen aber gemeinsam gesetzt werden. +`LZC_STACKIT_CLI_CLIENT_APPROVED=true` ist eine ausdrückliche Freigabe für die +Wiederverwendung des CLI-Clients, kein technischer Schalter zum Umgehen der +Registrierungsfrage. Der Benutzer hat die Nutzung für Configurator-Dev am +2026-10-02 ausdrücklich freigegeben; das Ticket für einen eigenen OIDC-Client +bleibt offen. Diese Dev-Freigabe ist keine Produktionsfreigabe. + +Bestandsnutzer können ihre STACKIT-Identität mit einer noch gültigen alten Session +explizit binden; Benutzer-ID, Tenant und gespeicherte GitHub-Zuordnung bleiben +erhalten. Eine ungebundene, bereits abgemeldete GitHub-Identität wird bei einem +STACKIT-Login nicht automatisch zusammengeführt. Der Rollout benötigt deshalb +eine kontrollierte Bindung der Bestandskonten vor dem Wechsel. + +Aktuelle Betriebsgrenzen stehen in der [Architektur](architecture.de.md) und im +[MVP-Umfang](mvp-scope.de.md). Laufbezogene Pruefergebnisse gehoeren zu den +jeweiligen CI-Artefakten, nicht in einen fortgeschriebenen historischen Bericht. + + + +## Legacy-Ablauf: GitHub als Login + +1. `/auth/github/start` speichert einen fünf Minuten gültigen Login-Vorgang in + PostgreSQL: State-Hash, Browserbindungs-Hash und PKCE-Verifier. Das Browsercookie + ist `Secure`, `HttpOnly`, `SameSite=Lax` und besitzt den `__Host-`-Präfix. +2. Der Callback verbraucht den Vorgang atomar und tauscht den Code mit PKCE gegen + ein zeitlich begrenztes GitHub-App-**Benutzertoken**. `/user` bestätigt die Identität. + Installation-Tokens und nicht ablaufende Tokens werden abgelehnt. +3. Die Datenbank erzeugt einen persönlichen Arbeitsbereich mit Mitgliedschaft. + Die Anwendung legt das GitHub-Token im Secrets Manager ab. Erst danach erhält + der Browser ein zufälliges Sessioncookie; die Datenbank enthält nur dessen Hash. +4. Die Session gilt höchstens acht Stunden, mit Abstand zum Tokenablauf. Refresh- + Tokens werden vorerst verworfen; danach ist eine erneute Anmeldung erforderlich. +5. Abmelden verlangt exakte Origin und einen sitzungsgebundenen CSRF-Wert. Zuerst + wird die DB-Session ungültig, anschließend ihr Secret gelöscht. + +Entwürfe werden für die OAuth-Weiterleitung maximal zehn Minuten in `sessionStorage` +des Tabs gesichert, gegen Struktur und Template-Hash geprüft und nach Rückkehr +entfernt. Dies ersetzt weder Datenbankpersistenz noch Speichern im Fork. Keine +GitHub-Tokens, Client-Secrets oder Sessiontokens in JavaScript-Speicher. + + + +## Vertrauensgrenzen + +- `configurator_app` ist weder Datenbankbesitzer noch Superuser oder BYPASSRLS. +- Konfigurationen, Mandanten und Mitgliedschaften besitzen erzwungene RLS. + Der Server setzt Benutzer- und Mandanten-ID ausschließlich transaktionslokal + aus einer validierten Session. Fehlender Kontext gewährt keinen Zugriff. +- Kleine SECURITY-DEFINER-Funktionen verwalten Login/Sessions mit festem + `search_path`; die App darf Sessions oder Mitgliedschaften nicht direkt auslesen + beziehungsweise Mitgliedschaften ändern. SQL-Injection bleibt eine kritische + Backend-Grenze: parametrisierte Queries sind zwingend. +- Secrets-Manager-Berechtigungen gelten für die dedizierte Instanz insgesamt. + Pfade und gespeicherte Metadaten binden Tokens an Session, Benutzer und Mandant. + Das ist Anwendungsautorisierung, keine pro Mandant durch Vault erzwungene Policy. + Die instanzweiten Schreibrechte wurden am 2026-09-30 ausdrücklich freigegeben. +- Keine Kunden-Repository-Operation verwendet Operator-PATs, App-Private-Keys oder + Installation-Tokens. Der Client-Secret dient allein dem OAuth-Codeaustausch. + + + +## Migration und Release + +SQL-Migrationen unter `app/apps/api/db/` laufen mit `configurator_migration` in einer +separaten CF-Task-App ohne Route und ohne GitHub-/Secrets-/Model-Serving-Bindings. +Die Release-Pipeline führt `cf push --task`, `cf run-task ... --wait` und danach +`cf delete` sichtbar aus. Die Web-App erhält nie das Passwort des Datenbankbesitzers. +Migrationen sind transaktional, über Advisory Lock serialisiert und mit SHA-256 +gegen Änderungen bereits angewendeter Dateien abgesichert. Keine automatischen +Down-Migrationen; alte Releases müssen mit dem neuen Schema kompatibel bleiben. + +Im Legacy-Modus aktiviert `LZC_AUTH_ENABLED=true` Login erst zusammen mit `LZC_GITHUB_CLIENT_ID` +und `LZC_GITHUB_CLIENT_SECRET` aus dem geschützten Release-Environment. Die API +prüft beim Start die Sessionfunktion. Der Release-Verbindungstest prüft zusätzlich +Secrets schreiben, lesen und dauerhaft löschen an einem zufälligen Probe-Pfad. +Rohe CF-Routerlogs werden nicht in CI ausgegeben, da OAuth-Codes in URLs stehen +können. Applikationslogs enthalten keine Request-URLs oder Cookie-/Tokenwerte. + + + +## Abnahme und offene Arbeiten + +- [x] GitHub-App unter `lweberru` registriert; Client-Zugangsdaten lokal 0600. +- [x] Build, 25 Anwendungstests und sechs echte PostgreSQL-Integrationstests bestanden. +- [x] Sechs Browserfälle auf Desktop/Mobilgeräten inklusive Login-Weiterleitung, + Entwurfserhalt und Logout erfolgreich (GitHub dabei simuliert). +- [x] CI erhält die PostgreSQL-Tests vor Validierung und Release. +- [x] Plattform-Output via [CI-Apply 36693151989](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693151989) aktiviert (keine Ressourcenänderung). +- [x] Secrets-Schreibrechte via [CI-Apply 36693644577](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693644577) aktiviert (ein Update, keine Ersetzung). +- [x] [Validierung 36693906434](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693906434) für `cd9d79f` erfolgreich, einschließlich PostgreSQL und Browsern. +- [x] OAuth-Zugangsdaten nach ausdrücklicher Freigabe im Release-Environment und CF-Backend bereitgestellt. +- [x] [Release 36693906545](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693906545): Migration erfolgreich; privilegierte Task-App entfernt; Web-App, PostgreSQL- und Secrets-Verbindungstests erfolgreich. +- [x] [Login-Release 36695423593](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36695423593): GitHub-Login aktiviert, Secrets-Schreiben/Lesen/Löschen erfolgreich; Health 200 und anonyme Session 401. OAuth-Weiterleitung, Client-ID, Callback, PKCE S256, State und sicheres Cookie live geprüft. +- [x] Echten GitHub-Login und Logout vom Benutzer bestätigt. +- [ ] Installation auf den benötigten Repositories und Fork-Voraussetzungen prüfen. +- [x] Fork-Auswahl, Speichern und Wiederöffnen implementiert und simuliert getestet; Live-Abnahme siehe [Forks und Navigation](forks-and-navigation.de.md). +- [ ] Organisationen, Einladungen und Mandantenwechsel implementieren. Aktuell erhält + jeder Benutzer einen eigenen isolierten Arbeitsbereich. +- [ ] Abgelaufene Sessiondatensätze und verwaiste Secrets regelmäßig bereinigen. + Abgelaufene Tokens sind unbrauchbar; fehlgeschlagene Löschungen sind noch kein + dauerhaft abgearbeiteter Cleanup-Job. Vor breiter Freigabe nachholen. +- [ ] Verteiltes Rate-Limit, Audit-Aufbewahrung und GitHub-Widerruf prüfen; das aktuelle + Startlimit gilt nur je Instanz, Widerrufe werden spätestens bei API-Nutzung erkannt. + + + +## Credential-Freigabe + +Der Benutzer hat am 2026-09-30 den Transfer von `LZC_GITHUB_CLIENT_ID` und +`LZC_GITHUB_CLIENT_SECRET` für `lweberru/lz-configurator-dev-7dbff805` in +`stackitcloud/stackit-landing-zone`, Environment `lzc-dev-release`, sowie die +anschließende CF-Backend-Bindung ausdrücklich freigegeben. Beide Environment-Secrets +sind hinterlegt; `LZC_AUTH_ENABLED=true` ist für den nächsten Release gesetzt. +Live-Aktivierung und Secrets-Rundtrip wurden mit Release `36695423593` erfolgreich abgeschlossen. diff --git a/landing-zone-configurator/docs/github-login.md b/landing-zone-configurator/docs/github-login.md index 8cdefae..4612ac0 100644 --- a/landing-zone-configurator/docs/github-login.md +++ b/landing-zone-configurator/docs/github-login.md @@ -1,330 +1,345 @@ -# STACKIT-Login, optionale GitHub-Verbindung und Mandantentrennung - -Stand: 2026-10-06. STACKIT als primärer Login lokal implementiert und getestet. -Die ausdrueckliche Dev-Client-Freigabe ersetzt keine Produktionsregistrierung. -Migrationen bis 039 sind nach privaten Sicherungen und vollstaendigen isolierten -Restore-Pruefungen lokal aktiviert. Echter menschlicher Login, vollstaendiger -Owner-Nachweis und ausdrueckliche Organisationsbindung sind in der bestehenden -Kundenorganisation erfolgreich abgenommen. GitHub bleibt als Legacy-Modus erhalten. - -Seit Migration 058 ist die achtstuendige Configurator-Sitzung unabhaengig von -der kuerzeren STACKIT-Tokenlaufzeit. Beim Login muss der verifizierte Nachweis -weiterhin aktuell sein. Identitaets- und Organisations-Owner-Nachweise behalten -ihre eigenen Ablaufzeiten; abgelaufene Nachweise erlauben weder eine neue -Organisationsbindung noch geschuetzte Cloud-Aktionen. Sie muessen bei Bedarf -erneut bestaetigt werden. Refresh-Tokens werden weiterhin nicht gespeichert. -Logout widerruft die App-Sitzung, und Rollen-/Mandantenpruefungen bleiben aktiv. -Bestehende Sitzungen werden nicht nachtraeglich verlaengert; die neue Laufzeit -gilt nach erneuter Anmeldung. - -Der Web-Login mit Authorization Code und PKCE verwendet denselben Browser-Tab. -Der vorhandene Callback setzt die Anmeldung im Configurator fort; unvollständige -Entwürfe bleiben dabei über den bestehenden tabgebundenen Zwischenspeicher erhalten. -Dies gilt auch für die erneute STACKIT-Bestätigung im Kontobereich. Nur der -kompatible Device-Flow mit Anmeldecode öffnet weiterhin einen separaten Tab, -weil der ursprüngliche Tab für das Polling geöffnet bleiben muss. - -Der Resource Manager liefert fuer die exakt angefragte Organisations-UUID einen -IAM-Containerbezug. Die Pruefung verwendet ausschliesslich diesen Bezug fuer -IAM-Rechte und Rollen; fremde Container bleiben gesperrt. Die reale Antwort mit -965 Owner-Rechten wird vollstaendig geprueft. Parser und Migration 037 erlauben -hoechstens 4096 Rechte, bei unveraenderter Antwortgroessen- und Autoritaetspruefung. -Migration 023 wurde nicht veraendert. Der PKCE-Nachweis kehrt zu -`/organisation#stackit-proof` zurueck; geschuetztes Polling setzt ihn fort. -Die Benutzerverwaltung erlaubt auch nach erfolgter Bindung eine erneute -zeitlich begrenzte Owner-Pruefung, ohne eine weitere Bindung anzubieten. - -## CLI-PKCE und Nachweisdiagnose - -Die folgenden Diagnose- und Aktivierungsabschnitte dokumentieren historische -Zwischenstaende. Fuer die aktuelle Abnahme gilt der Stand oberhalb dieses Abschnitts. - -Ein anonymer Browser ohne bestehende STACKIT-Sitzung erreicht mit dem freigegebenen -CLI-Device-Client die Provider-Seite `/ui/login/user`, aber nur mit einem -Weiter-Button und versteckten Formularfeldern, ohne Login-Eingabe. Weiter fuehrt -wieder auf dieselbe Seite. Dies wurde auch mit `openid email profile` und mit -manueller Code-Eingabe am Basis-Bestaetigungslink reproduziert. Scope- oder -Linkwechsel sind daher kein belegter Fix. Der Vergleich mit dem lokal geklonten -STACKIT-CLI korrigiert die urspruengliche Einordnung als allgemeiner Providerfehler: -`stackit auth login` verwendet Authorization Code mit PKCE, nicht Device Flow. -Ein frischer anonymer CLI-artiger Authorization-Code-Aufruf liefert tatsaechlich -ein Benutzernamenfeld. Der vollstaendige menschliche Login ist noch nicht abgenommen. - -Der lokale Startscript verwendet jetzt denselben CLI-Client, S256-PKCE und -`openid offline_access email`. Zusaetzlich schuetzen zufaelliger State und Nonce -den Browserflow. Ein Loopback-Listener waehlt einen freien Port zwischen 8000 und -8020 und verwendet exakt `http://localhost:` als registrierten Callback. -Die Weiterleitung ist auf den festen lokalen Configurator-Origin begrenzt; -Code und Callback-URLs werden nicht geloggt. Der Configurator-Callback verlangt -das urspruengliche Browsercookie bzw. die echte Nachweissitzung und denselben -Tenant. Fremde, abgelaufene, wiederholte oder unpassende Callbacks werden abgelehnt. -Erst das bestehende browsergebundene Polling tauscht den Code mit dem Verifier -aus und prueft signiertes ID-Token, Nonce, Issuer, Audience und Userinfo. Der -Callback erzeugt keine Sitzung und bindet keine Organisation automatisch. -Refresh-Tokens werden trotz CLI-kompatiblem Scope nicht gespeichert. - -PKCE ist nur lokal vorbereitet, nicht in der laufenden API aktiviert. Der -Standard-Device-Flow bleibt kompatibel. Der CLI-Loopback-Callback ist kein -Deployment-Verfahren fuer gehostete Apps; ein eigener registrierter Web-OIDC-Client -mit passendem Callback bleibt fuer Produktion erforderlich. Bestehende Sitzungen -und die pausierten Application-Migrationen werden nicht automatisch veraendert. - -Die Nachweisoberflaeche zeigt den angemeldeten Configurator-Benutzer und die -zuletzt bestaetigte STACKIT-E-Mail. Abgelaufene Nachweise bleiben als solche -gekennzeichnet; Benutzer-/Tenantwechsel entfernen die bisherige Anzeige. -Bekannte Zugriffs-, Berechtigungs-, Identitaets- und Provider-Antwortfehler haben -kontrollierte DE/EN-Meldungen. Unbekannte Codes und Providerdetails werden nicht -angezeigt. Fehler erlauben weder Organisationsbindung noch Wiederverwendung -alter Owner-Rechte. Der echte gemeldete Organisationsfehler ist noch nicht -identifiziert: im eigenen authentifizierten Browser neu laden, Nachweis pruefen -und die konkrete Meldung samt angezeigter Identitaet pruefen. Keine Tokens teilen. - -Nachweise: 61 Device-/Uebersetzungstests, TypeScript und 14 vorhandene erweiterte -Desktop-/Mobil-Browserfaelle bestanden. Die Browserfaelle verwenden synthetische -Identitaeten und gemockte APIs; sie sind keine reale Organisationsabnahme. -Keine API-Neustarts, Kundenmigrationen, Cloud-Plans oder Applies fuer diese -Diagnoseaenderung. #91 bleibt offen. - -PKCE-Folgepruefung: 62 Auth-Tests, insgesamt 395 Tests mit 45 erwarteten Skips, -TypeScript sowie 4 Login- und 16 Nachweis-Browserfaelle bestanden. Vor der -Wiederaufnahme stoppt der globale `npm run check` an fuenf Format-/Importdiagnosen -in den pausierten Applied-Platform-Aenderungen; der begrenzte Login-Biome-Check -hat keine Fehler. Diese historische Blockade wurde bei der Wiederaufnahme behoben. - -### Lokale Aktivierung (2026-10-06) - -Der freigegebene Login-only-Stand ist lokal aktiviert. Ein isolierter Runtime-Stand -enthält Basis `056d4df`, Nachweisoberflaeche `929f7fd` und CLI-PKCE `ce6db69`, aber -nicht die nachfolgenden Gruppen-/Application-Migrationen. Vor dem API-Neustart -wurde die private Sicherung vollstaendig in einem eigenen PostgreSQL-Container -wiederhergestellt und der unveraenderte Migrationsstand 034 geprueft. Nach dem -Neustart sind alle 33 Kundentabellen unveraendert. Der bisherige Plattform-Runner -bleibt derselbe; Application-Ausfuehrung bleibt deaktiviert. - -Der reale anonyme Start ueber die laufende UI erreicht die Provider-Seite mit -sichtbarem Benutzernamenfeld und ohne Device-Code. Der eigene Pruefflow wurde -beendet. Vollstaendiger menschlicher Login und echter Organisationsnachweis -bleiben noch abzunehmen; #91 bleibt offen. Die isolierte Aktivierung erlaubt -keinen ungeprueften Start des aktuellen Repository-Scripts mit Migrationen 035/036. - -### Rueckkehr-Tab und Session-Uebernahme - -Der Nutzer bestaetigt den erfolgreichen Login bei STACKIT, aber die App im -Rueckkehr-Tab blieb unangemeldet. Die bisherige Initialisierung fragte die Session -nur einmal ab; zum Zeitpunkt der Rueckkehr konnte das urspruengliche Tab den -Code noch nicht per geschuetztem Polling in eine Session umgewandelt haben. -Zwei neue Sessions waren bereits gespeichert, ohne dass dies den geoeffneten -Rueckkehr-Tab aktualisierte. - -Der Callback leitet jetzt zum festen `/#stackit-login` am Configurator-Origin. -Der Marker enthaelt weder Code noch Tokens und wird aus der Browseradresse -entfernt. Das Rueckkehr-Tab setzt das browsergebundene Polling selbst fort, -auch wenn das Ursprungstab geschlossen wurde. Hat ein anderes Tab den Flow -bereits abgeschlossen, wird ausschliesslich die vom Server anhand des echten -Session-Cookies bestaetigte Session eingelesen. Ein Marker ohne gueltigen Flow -oder Session erzeugt keine Anmeldung. State-, Nonce-, Replay- und Cookie-Gates -bleiben unveraendert; der Callback selbst erzeugt weiterhin keine Session. - -Der Login-only-Fix ist nach erneuter privater Sicherung lokal aktiviert; -Schema bleibt 034, alle 33 Kundentabellen sind nach Neustart unveraendert. -62 Auth- und 10 Desktop-/Mobil-Loginfaelle bestehen, einschliesslich Rueckkehr -ohne Ursprungstab und Parallelabschluss. Die Browserfaelle verwenden API-Mocks. -Die tatsaechliche Anzeige im Browser des Nutzers muss nochmals geprueft werden. - -## Primärer STACKIT-Login - -Platform Engineer und Application Owner melden sich mit ihrer persönlichen -STACKIT-Identität an und wählen bei mehreren Mitgliedschaften ihren aktiven Tenant. -Der Application Owner benötigt weder GitHub noch einen Service Account. -Der Platform Engineer hinterlegt den technischen STACKIT-Service-Account-Zugang; -Produktkataloge verwenden danach denselben Zugang automatisch, ohne weitere -Profil- oder Projektwahl im Editor. Persönliche Login-Tokens werden nicht für -technische STACKIT-Automatisierungen gespeichert oder wiederverwendet. - -`POST /auth/stackit/start` beginnt den konfigurierten browsergebundenen Flow. -Lokal ist dies CLI-PKCE; ohne explizite Flow-Factory bleibt es Device Flow. -Beim Device Flow erhält der Browser den öffentlichen Bestätigungscode und den -STACKIT-Bestätigungslink, bei PKCE nur den Authorization-Link ohne Device-Code. -`/auth/stackit/poll` verifiziert die Identität serverseitig -und erzeugt die normale opaque Session. Ein vorhandenes ID-Token wird vollständig -geprüft; fehlt es, wird ausschließlich Userinfo mit dem im selben Device Grant -erhaltenen Access Token verwendet. Ein bestätigtes persönliches Konto ist Pflicht. -Issuer und Subject bestimmen den stabilen Benutzer, niemals allein die E-Mail-Adresse. - -Device-Cookies sind `Secure`, `HttpOnly`, `SameSite=Strict`; fuer die PKCE- -Callback-Rueckkehr verwendet die Browserbindung `SameSite=Lax`. Sessions verwenden -`SameSite=Lax`. Pre-Auth-POSTs verlangen die exakte Origin, authentifizierte -Änderungen zusätzlich CSRF. Sessions gelten höchstens acht Stunden und enden -spätestens 30 Sekunden vor dem Provider-Token. Kein Refresh-Token wird behalten. -Offene Device-Flows liegen nur im Speicher einer Instanz: Neustart verwirft sie; -mehrere Instanzen benötigen vor Aktivierung eine gemeinsame Ablage oder Sticky Routing. - -## Autoritativer Organisationsnachweis - -Login oder Resource-Manager-Lesezugriff sind kein Adminnachweis. Im aktiven -Organisationsarbeitsbereich startet ein Platform Engineer mit Mitgliederverwaltung -die Pruefung ausdruecklich. Dabei wird sein bisheriger aktueller -Organisationsnachweis entfernt; menschliche Identitaet und historische Audits -bleiben erhalten. Ein fehlgeschlagener neuer Nachweis darf keine alte -Owner-Freigabe wiederverwenden. - -Der neue Device Grant verifiziert dieselbe menschliche Identitaet und die exakte -Organisation. Derselbe kurzlebige menschliche Bearer Token fragt am festen -IAM-Origin `https://authorization.api.stackit.cloud` folgende APIs ab: + +# STACKIT login, optional GitHub connection and tenant isolation + +[English](github-login.md) | [Deutsch](github-login.de.md) + +As of 2026-10-06. STACKIT as primary login implemented and tested locally. +Explicit dev-client approval does not replace production registration. +Migrations through 039 are activated locally after private backups and complete isolated +restore checks. Real human login, complete +owner proof and explicit organization binding have passed acceptance in the existing +customer organization. GitHub remains as legacy mode. + +Since migration 058, the eight-hour Configurator session is independent of +the shorter STACKIT token lifetime. At login, verified proof +must still be current. Identity and organization-owner proofs retain +their own expiry times; expired proofs permit neither a new +organization binding nor protected cloud actions. They must be +reconfirmed when needed. Refresh tokens are still not stored. +Logout revokes the app session, and role/tenant checks remain active. +Existing sessions are not extended retroactively; the new lifetime +applies after signing in again. + +Web login with Authorization Code and PKCE uses the same browser tab. +The existing callback resumes login in the Configurator; incomplete +drafts survive through the existing tab-bound intermediate storage. +This also applies to renewed STACKIT confirmation in the account area. Only the +compatible Device Flow with login code still opens a separate tab, +because the original tab must remain open for polling. + +Resource Manager returns an IAM container reference for the exact requested organization UUID. +Verification uses only this reference for +IAM permissions and roles; other containers remain blocked. The real response with +965 owner permissions is checked in full. Parser and migration 037 allow +at most 4096 permissions, with unchanged response-size and authority checks. +Migration 023 was not changed. PKCE proof returns to +`/organisation#stackit-proof`; protected polling resumes it. +User management permits another time-limited owner check even after binding, +without offering another binding. + + +## CLI PKCE and proof diagnostics + +The following diagnostic and activation sections document historical +intermediate states. For current acceptance, the status above this section applies. + +An anonymous browser without an existing STACKIT session reaches the provider page +`/ui/login/user` with the approved CLI Device client, but only with a +continue button and hidden form fields, without login input. Continue +returns to the same page. This was also reproduced with `openid email profile` and +manual code entry at the base confirmation link. Scope or +link changes are therefore not a proven fix. Comparison with the locally cloned +STACKIT CLI corrects the original classification as a general provider error: +`stackit auth login` uses Authorization Code with PKCE, not Device Flow. +A fresh anonymous CLI-style Authorization Code request actually provides +a username field. Full human login has not yet passed acceptance. + +The local start script now uses the same CLI client, S256 PKCE and +`openid offline_access email`. Random state and nonce additionally protect +the browser flow. A loopback listener selects a free port between 8000 and +8020 and uses exactly `http://localhost:` as registered callback. +Redirect is limited to the fixed local Configurator origin; +code and callback URLs are not logged. The Configurator callback requires +the original browser cookie or real proof session and the same +tenant. Foreign, expired, repeated or mismatched callbacks are rejected. +Only existing browser-bound polling exchanges the code with the verifier +and checks signed ID token, nonce, issuer, audience and userinfo. The +callback creates no session and binds no organization automatically. +Refresh tokens are not stored despite the CLI-compatible scope. + +PKCE is prepared locally only, not activated in the running API. The +standard Device Flow remains compatible. The CLI loopback callback is not +a deployment method for hosted apps; a separately registered web OIDC client +with matching callback remains required for production. Existing sessions +and paused Application migrations are not automatically changed. + +The proof interface shows the signed-in Configurator user and +last confirmed STACKIT email. Expired proofs remain marked as such; +user/tenant changes remove the previous display. +Known access, permission, identity and provider-response errors have +controlled DE/EN messages. Unknown codes and provider details are not +displayed. Errors permit neither organization binding nor reuse of +old owner permissions. The actual reported organization error is not yet +identified: reload in the user's own authenticated browser, check proof +and inspect the specific message and displayed identity. Do not share tokens. + +Evidence: 61 Device/translation tests, TypeScript and 14 existing extended +desktop/mobile browser cases passed. Browser cases use synthetic +identities and mocked APIs; they are not real organization acceptance. +No API restarts, customer migrations, cloud Plans or Applies for this +diagnostic change. #91 remains open. + +PKCE follow-up check: 62 auth tests, 395 tests in total with 45 expected skips, +TypeScript and 4 login plus 16 proof browser cases passed. Before +resumption, global `npm run check` stops at five formatting/import diagnostics +in the paused Applied Platform changes; the bounded login Biome check +has no errors. This historical blocker was fixed on resumption. + + +### Local activation (2026-10-06) + +The approved login-only revision is activated locally. An isolated runtime revision +contains base `056d4df`, proof interface `929f7fd` and CLI PKCE `ce6db69`, but +not subsequent group/Application migrations. Before the API restart, +the private backup was fully restored in its own PostgreSQL container +and unchanged migration revision 034 checked. After +restart, all 33 customer tables are unchanged. The existing platform Runner +remains the same; Application execution remains disabled. + +The real anonymous start through the running UI reaches the provider page with +a visible username field and no Device code. The agent's own verification flow was +ended. Full human login and real organization proof +remain to be accepted; #91 remains open. Isolated activation does not permit +unchecked launch of the current repository script with migrations 035/036. + + +### Return tab and session adoption + +The user confirms successful login at STACKIT, but the app in the +return tab remained signed out. Previous initialization queried the session +only once; at return time, the original tab might not yet have +converted the code into a session through protected polling. +Two new sessions were already stored without updating the open +return tab. + +The callback now redirects to fixed `/#stackit-login` at the Configurator origin. +The marker contains neither code nor tokens and is removed from the browser address. +The return tab resumes browser-bound polling itself, +even if the original tab was closed. If another tab has +already completed the flow, only the session confirmed by the server through the real +session cookie is read. A marker without valid flow +or session creates no login. State, nonce, replay and cookie gates +remain unchanged; the callback itself still creates no session. + +The login-only fix is activated locally after another private backup; +schema remains 034, all 33 customer tables are unchanged after restart. +62 auth and 10 desktop/mobile login cases pass, including return +without original tab and parallel completion. Browser cases use API mocks. +The actual display in the user's browser must be checked again. + + +## Primary STACKIT login + +Platform Engineer and Application Owner sign in with their personal +STACKIT identity and select their active tenant when they have multiple memberships. +The Application Owner needs neither GitHub nor a service account. +The Platform Engineer stores technical STACKIT service-account credentials; +product catalogues then automatically use the same credentials without additional +profile or project selection in the editor. Personal login tokens are not stored +or reused for technical STACKIT automation. + +`POST /auth/stackit/start` begins the configured browser-bound flow. +Locally this is CLI PKCE; without an explicit flow factory it remains Device Flow. +With Device Flow the browser receives the public confirmation code and +STACKIT confirmation link; with PKCE only the authorization link without Device code. +`/auth/stackit/poll` verifies identity server-side +and creates the normal opaque session. An existing ID token is fully +checked; if absent, only userinfo with the access token received in the same +Device Grant is used. A confirmed personal account is mandatory. +Issuer and subject determine the stable user, never email alone. + +Device cookies are `Secure`, `HttpOnly`, `SameSite=Strict`; for the PKCE +callback return, browser binding uses `SameSite=Lax`. Sessions use +`SameSite=Lax`. Pre-auth POSTs require exact origin; authenticated +changes additionally CSRF. Sessions last at most eight hours and end +at least 30 seconds before the provider token. No refresh token is retained. +Open Device Flows reside only in one instance's memory: restart discards them; +multiple instances need shared storage or sticky routing before activation. + + +## Authoritative organization proof + +Login or Resource Manager read access is not administrator proof. In the active +organization workspace, a Platform Engineer with membership management +explicitly starts verification. Their previous current +organization proof is removed; human identity and historical audits +remain. A failed new proof must not reuse old +owner approval. + +The new Device Grant verifies the same human identity and exact +organization. The same short-lived human ****** queries the following APIs at the fixed +IAM origin `https://authorization.api.stackit.cloud`: - `GET /v2/users/{verifiedEmail}/permissions?resourceType=organization&resource={verifiedOrganizationResourceId}` - `GET /v2/organization/{verifiedOrganizationResourceId}/roles` -`verifiedOrganizationResourceId` ist der Containerbezug aus der erfolgreich -geprueften Resource-Manager-Antwort, ersatzweise deren Organisations-UUID, falls -kein Containerbezug geliefert wurde. Zurueckgegebene IAM-Ressourcen muessen exakt -diesem Bezug entsprechen; die gebundene Organisation behaelt ihre echte UUID. - -Antworten werden auf Organisation, Ressourcentyp, Umfang und Struktur geprueft. -Das konservative Minimum umfasst alle Rechte genau einer nicht leeren -offiziellen `owner`-Rolle. Die effektiven Benutzerrechte muessen diesen Satz -vollstaendig enthalten. Leserechte, fehlende/mehrdeutige Owner-Rollen und -gesperrte Rollenabfragen erteilen keine Bindungsautoritaet. Grundlage ist der -offizielle STACKIT-Go-SDK-Vertrag, Revision +`verifiedOrganizationResourceId` is the container reference from the successfully +checked Resource Manager response, falling back to its organization UUID if +no container reference was supplied. Returned IAM resources must exactly match +this reference; the bound organization retains its real UUID. + +Responses are checked for organization, resource type, scope and structure. +The conservative minimum includes all permissions of exactly one nonempty +official `owner` role. Effective user permissions must contain this set +in full. Read access, missing/ambiguous owner roles and +blocked role queries grant no binding authority. The basis is the +official STACKIT Go SDK contract, revision `7746310c7fe0a5e3f5c5e6e9b1be69d48c6184d9`, `services/authorization/v2api`. -Erst eine separate Bestaetigung sendet -`POST /api/v1/stackit/identity/bind-organization` mit ausschliesslich -`{"confirmOrganizationBinding":true}`. Origin, CSRF, Tenant, echte aktuelle -DB-Session, PE-Rolle, Mitgliederverwaltung und nicht abgelaufene/widerrufene -Identitaets-/Owner-Nachweise werden erneut geprueft. SQL-seitig erzeugte -unveraenderliche Autorisierungsbelege binden Organisation, Benutzer, -Issuer/Subject, Rechte und Gueltigkeit. Die atomare Bindung referenziert diesen -Beleg im Audit; Wiederholungen liefern denselben Bindungsbeleg. - -Migrationen `023_organization_authorizations.sql` und -`024_organization_binding.sql` sind erforderlich. Alte APIs ohne Capability -zeigen die Steuerung nicht an. `organization_verified` bezeichnet die -historisch bestaetigte Zuordnung, nicht unbegrenzte aktuelle Owner-Rechte. -Die Bindung startet weder Cloud-Plan noch Apply und ersetzt keinen technischen -Job-Grant. Echte Zwei-Organisations-Abnahme, Produktions-Client-Registrierung -und Least-Privilege-Providerqualifizierung bleiben fuer #91 erforderlich. - -## GitHub nur für Repository-Funktionen - -Im STACKIT-Modus ist GitHub erst unter GitHub-Forks über **GitHub verbinden** nötig. -Der Start erfolgt authentifiziert per `POST /auth/github/connect` mit Origin/CSRF. -Der OAuth-Callback ist an dieselbe bestehende Session gebunden und verbindet die -geprüfte GitHub-ID mit diesem Benutzer, ohne Benutzer oder Tenant zu wechseln. -Bereits anderweitig zugeordnete Identitäten werden abgelehnt; Konten werden nicht -anhand gleicher E-Mail-Adressen zusammengeführt. Die Verbindung ist für Login und -Application-Owner-Bestellungen nicht erforderlich. - -Der bestehende forkbasierte Plattform-Plan bleibt eine Repository-Funktion und -benötigt deshalb weiterhin diese optionale Verbindung. Ein echter isolierter -Application-Plan ist durch diese Login-Änderung noch nicht angeschlossen. - -## Aktivierung und Bestandskonten - -Vor Aktivierung müssen Migrationen `011_stackit_identity.sql` und -`012_stackit_login.sql` angewendet sein. Mit `LZC_AUTH_ENABLED=true` und -`LZC_STACKIT_DEVICE_ENABLED=true` wird STACKIT primär; GitHub-Client-ID und -Client-Secret sind dann optional, müssen aber gemeinsam gesetzt werden. -`LZC_STACKIT_CLI_CLIENT_APPROVED=true` ist eine ausdrückliche Freigabe für die -Wiederverwendung des CLI-Clients, kein technischer Schalter zum Umgehen der -Registrierungsfrage. Der Benutzer hat die Nutzung für Configurator-Dev am -2026-10-02 ausdrücklich freigegeben; das Ticket für einen eigenen OIDC-Client -bleibt offen. Diese Dev-Freigabe ist keine Produktionsfreigabe. - -Bestandsnutzer können ihre STACKIT-Identität mit einer noch gültigen alten Session -explizit binden; Benutzer-ID, Tenant und gespeicherte GitHub-Zuordnung bleiben -erhalten. Eine ungebundene, bereits abgemeldete GitHub-Identität wird bei einem -STACKIT-Login nicht automatisch zusammengeführt. Der Rollout benötigt deshalb -eine kontrollierte Bindung der Bestandskonten vor dem Wechsel. - -Aktuelle Betriebsgrenzen stehen in der [Architektur](architecture.md) und im -[MVP-Umfang](mvp-scope.md). Laufbezogene Pruefergebnisse gehoeren zu den -jeweiligen CI-Artefakten, nicht in einen fortgeschriebenen historischen Bericht. - -## Legacy-Ablauf: GitHub als Login - -1. `/auth/github/start` speichert einen fünf Minuten gültigen Login-Vorgang in - PostgreSQL: State-Hash, Browserbindungs-Hash und PKCE-Verifier. Das Browsercookie - ist `Secure`, `HttpOnly`, `SameSite=Lax` und besitzt den `__Host-`-Präfix. -2. Der Callback verbraucht den Vorgang atomar und tauscht den Code mit PKCE gegen - ein zeitlich begrenztes GitHub-App-**Benutzertoken**. `/user` bestätigt die Identität. - Installation-Tokens und nicht ablaufende Tokens werden abgelehnt. -3. Die Datenbank erzeugt einen persönlichen Arbeitsbereich mit Mitgliedschaft. - Die Anwendung legt das GitHub-Token im Secrets Manager ab. Erst danach erhält - der Browser ein zufälliges Sessioncookie; die Datenbank enthält nur dessen Hash. -4. Die Session gilt höchstens acht Stunden, mit Abstand zum Tokenablauf. Refresh- - Tokens werden vorerst verworfen; danach ist eine erneute Anmeldung erforderlich. -5. Abmelden verlangt exakte Origin und einen sitzungsgebundenen CSRF-Wert. Zuerst - wird die DB-Session ungültig, anschließend ihr Secret gelöscht. - -Entwürfe werden für die OAuth-Weiterleitung maximal zehn Minuten in `sessionStorage` -des Tabs gesichert, gegen Struktur und Template-Hash geprüft und nach Rückkehr -entfernt. Dies ersetzt weder Datenbankpersistenz noch Speichern im Fork. Keine -GitHub-Tokens, Client-Secrets oder Sessiontokens in JavaScript-Speicher. - -## Vertrauensgrenzen - -- `configurator_app` ist weder Datenbankbesitzer noch Superuser oder BYPASSRLS. -- Konfigurationen, Mandanten und Mitgliedschaften besitzen erzwungene RLS. - Der Server setzt Benutzer- und Mandanten-ID ausschließlich transaktionslokal - aus einer validierten Session. Fehlender Kontext gewährt keinen Zugriff. -- Kleine SECURITY-DEFINER-Funktionen verwalten Login/Sessions mit festem - `search_path`; die App darf Sessions oder Mitgliedschaften nicht direkt auslesen - beziehungsweise Mitgliedschaften ändern. SQL-Injection bleibt eine kritische - Backend-Grenze: parametrisierte Queries sind zwingend. -- Secrets-Manager-Berechtigungen gelten für die dedizierte Instanz insgesamt. - Pfade und gespeicherte Metadaten binden Tokens an Session, Benutzer und Mandant. - Das ist Anwendungsautorisierung, keine pro Mandant durch Vault erzwungene Policy. - Die instanzweiten Schreibrechte wurden am 2026-09-30 ausdrücklich freigegeben. -- Keine Kunden-Repository-Operation verwendet Operator-PATs, App-Private-Keys oder - Installation-Tokens. Der Client-Secret dient allein dem OAuth-Codeaustausch. - -## Migration und Release - -SQL-Migrationen unter `app/apps/api/db/` laufen mit `configurator_migration` in einer -separaten CF-Task-App ohne Route und ohne GitHub-/Secrets-/Model-Serving-Bindings. -Die Release-Pipeline führt `cf push --task`, `cf run-task ... --wait` und danach -`cf delete` sichtbar aus. Die Web-App erhält nie das Passwort des Datenbankbesitzers. -Migrationen sind transaktional, über Advisory Lock serialisiert und mit SHA-256 -gegen Änderungen bereits angewendeter Dateien abgesichert. Keine automatischen -Down-Migrationen; alte Releases müssen mit dem neuen Schema kompatibel bleiben. - -Im Legacy-Modus aktiviert `LZC_AUTH_ENABLED=true` Login erst zusammen mit `LZC_GITHUB_CLIENT_ID` -und `LZC_GITHUB_CLIENT_SECRET` aus dem geschützten Release-Environment. Die API -prüft beim Start die Sessionfunktion. Der Release-Verbindungstest prüft zusätzlich -Secrets schreiben, lesen und dauerhaft löschen an einem zufälligen Probe-Pfad. -Rohe CF-Routerlogs werden nicht in CI ausgegeben, da OAuth-Codes in URLs stehen -können. Applikationslogs enthalten keine Request-URLs oder Cookie-/Tokenwerte. - -## Abnahme und offene Arbeiten - -- [x] GitHub-App unter `lweberru` registriert; Client-Zugangsdaten lokal 0600. -- [x] Build, 25 Anwendungstests und sechs echte PostgreSQL-Integrationstests bestanden. -- [x] Sechs Browserfälle auf Desktop/Mobilgeräten inklusive Login-Weiterleitung, - Entwurfserhalt und Logout erfolgreich (GitHub dabei simuliert). -- [x] CI erhält die PostgreSQL-Tests vor Validierung und Release. -- [x] Plattform-Output via [CI-Apply 36693151989](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693151989) aktiviert (keine Ressourcenänderung). -- [x] Secrets-Schreibrechte via [CI-Apply 36693644577](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693644577) aktiviert (ein Update, keine Ersetzung). -- [x] [Validierung 36693906434](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693906434) für `cd9d79f` erfolgreich, einschließlich PostgreSQL und Browsern. -- [x] OAuth-Zugangsdaten nach ausdrücklicher Freigabe im Release-Environment und CF-Backend bereitgestellt. -- [x] [Release 36693906545](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693906545): Migration erfolgreich; privilegierte Task-App entfernt; Web-App, PostgreSQL- und Secrets-Verbindungstests erfolgreich. -- [x] [Login-Release 36695423593](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36695423593): GitHub-Login aktiviert, Secrets-Schreiben/Lesen/Löschen erfolgreich; Health 200 und anonyme Session 401. OAuth-Weiterleitung, Client-ID, Callback, PKCE S256, State und sicheres Cookie live geprüft. -- [x] Echten GitHub-Login und Logout vom Benutzer bestätigt. -- [ ] Installation auf den benötigten Repositories und Fork-Voraussetzungen prüfen. -- [x] Fork-Auswahl, Speichern und Wiederöffnen implementiert und simuliert getestet; Live-Abnahme siehe [Forks und Navigation](forks-and-navigation.md). -- [ ] Organisationen, Einladungen und Mandantenwechsel implementieren. Aktuell erhält - jeder Benutzer einen eigenen isolierten Arbeitsbereich. -- [ ] Abgelaufene Sessiondatensätze und verwaiste Secrets regelmäßig bereinigen. - Abgelaufene Tokens sind unbrauchbar; fehlgeschlagene Löschungen sind noch kein - dauerhaft abgearbeiteter Cleanup-Job. Vor breiter Freigabe nachholen. -- [ ] Verteiltes Rate-Limit, Audit-Aufbewahrung und GitHub-Widerruf prüfen; das aktuelle - Startlimit gilt nur je Instanz, Widerrufe werden spätestens bei API-Nutzung erkannt. - -## Credential-Freigabe - -Der Benutzer hat am 2026-09-30 den Transfer von `LZC_GITHUB_CLIENT_ID` und -`LZC_GITHUB_CLIENT_SECRET` für `lweberru/lz-configurator-dev-7dbff805` in -`stackitcloud/stackit-landing-zone`, Environment `lzc-dev-release`, sowie die -anschließende CF-Backend-Bindung ausdrücklich freigegeben. Beide Environment-Secrets -sind hinterlegt; `LZC_AUTH_ENABLED=true` ist für den nächsten Release gesetzt. -Live-Aktivierung und Secrets-Rundtrip wurden mit Release `36695423593` erfolgreich abgeschlossen. +Only separate confirmation sends +`POST /api/v1/stackit/identity/bind-organization` with only +`{"confirmOrganizationBinding":true}`. Origin, CSRF, tenant, real current +DB session, PE role, membership management and unexpired/unrevoked +identity/owner proofs are checked again. SQL-generated +immutable authorization records bind organization, user, +issuer/subject, permissions and validity. Atomic binding references this +record in the audit; repetitions return the same binding record. + +Migrations `023_organization_authorizations.sql` and +`024_organization_binding.sql` are required. Old APIs without capability +do not display the control. `organization_verified` denotes the +historically confirmed assignment, not unlimited current owner rights. +Binding starts neither cloud Plan nor Apply and replaces no technical +job grant. Real two-organization acceptance, production client registration +and least-privilege provider qualification remain required for #91. + + +## GitHub only for repository features + +In STACKIT mode, GitHub is needed only under GitHub forks through **Connect GitHub**. +Start is authenticated through `POST /auth/github/connect` with origin/CSRF. +The OAuth callback is bound to the same existing session and connects the +verified GitHub ID to this user without switching user or tenant. +Identities already assigned elsewhere are rejected; accounts are not merged +based on matching email addresses. Connection is not required for login or +Application Owner orders. + +The existing fork-based platform Plan remains a repository feature and +therefore still needs this optional connection. A real isolated +Application Plan is not yet connected through this login change. + + +## Activation and existing accounts + +Before activation, migrations `011_stackit_identity.sql` and +`012_stackit_login.sql` must be applied. With `LZC_AUTH_ENABLED=true` and +`LZC_STACKIT_DEVICE_ENABLED=true`, STACKIT becomes primary; GitHub client ID and +client secret are then optional but must be set together. +`LZC_STACKIT_CLI_CLIENT_APPROVED=true` is explicit approval to +reuse the CLI client, not a technical switch to bypass the +registration question. The user explicitly approved usage for Configurator dev on +2026-10-02; the ticket for a dedicated OIDC client +remains open. This dev approval is not production approval. + +Existing users can explicitly bind their STACKIT identity with a still-valid old session; +user ID, tenant and saved GitHub assignment are preserved. +An unbound GitHub identity already signed out is not automatically merged on +STACKIT login. Rollout therefore requires +controlled binding of existing accounts before switching. + +Current operational limitations are in the [architecture](architecture.md) and +[MVP scope](mvp-scope.md). Run-specific results belong in +their respective CI artifacts, not an ongoing historical report. + + +## Legacy flow: GitHub as login + +1. `/auth/github/start` stores a login transaction valid for five minutes in + PostgreSQL: state hash, browser-binding hash and PKCE verifier. The browser cookie + is `Secure`, `HttpOnly`, `SameSite=Lax` and has the `__Host-` prefix. +2. The callback atomically consumes the transaction and exchanges the code with PKCE for + a time-limited GitHub App **user token**. `/user` confirms identity. + Installation tokens and nonexpiring tokens are rejected. +3. The database creates a personal workspace with membership. + The application stores the GitHub token in Secrets Manager. Only then does + the browser receive a random session cookie; the database contains only its hash. +4. The session lasts at most eight hours, with a margin before token expiry. Refresh + tokens are initially discarded; afterwards signing in again is required. +5. Logout requires exact origin and a session-bound CSRF value. First + the DB session is invalidated, then its secret deleted. + +Drafts are secured for OAuth redirect for at most ten minutes in the tab's +`sessionStorage`, checked for structure and template hash and removed +after return. This replaces neither database persistence nor saving to a fork. No +GitHub tokens, client secrets or session tokens in JavaScript storage. + + +## Trust boundaries + +- `configurator_app` is neither database owner nor superuser nor BYPASSRLS. +- Configurations, tenants and memberships have forced RLS. + The server sets user and tenant IDs only transaction-locally + from a validated session. Missing context grants no access. +- Small SECURITY DEFINER functions manage login/sessions with fixed + `search_path`; the app may not directly read sessions or memberships + or change memberships. SQL injection remains a critical + backend boundary: parameterized queries are mandatory. +- Secrets Manager permissions apply to the entire dedicated instance. + Paths and stored metadata bind tokens to session, user and tenant. + This is application authorization, not a per-tenant policy enforced by Vault. + Instance-wide write permissions were explicitly approved on 2026-09-30. +- No customer repository operation uses operator PATs, app private keys or + installation tokens. The client secret serves only OAuth code exchange. + + +## Migration and release + +SQL migrations under `app/apps/api/db/` run with `configurator_migration` in a +separate CF task app without route or GitHub/Secrets/Model Serving bindings. +The release pipeline visibly executes `cf push --task`, `cf run-task ... --wait` and then +`cf delete`. The web app never receives the database owner's password. +Migrations are transactional, serialized through advisory lock and protected with SHA-256 +against changes to already-applied files. No automatic +down migrations; old releases must remain compatible with the new schema. + +In legacy mode, `LZC_AUTH_ENABLED=true` activates login only together with `LZC_GITHUB_CLIENT_ID` +and `LZC_GITHUB_CLIENT_SECRET` from the protected release environment. The API +checks the session function at startup. The release connection test additionally checks +writing, reading and permanently deleting secrets at a random probe path. +Raw CF router logs are not printed in CI, since OAuth codes can appear in URLs. +Application logs contain no request URLs or cookie/token values. + + +## Acceptance and open work + +- [x] GitHub App registered under `lweberru`; client credentials local 0600. +- [x] Build, 25 application tests and six real PostgreSQL integration tests passed. +- [x] Six desktop/mobile browser cases including login redirect, + draft preservation and logout successful (GitHub simulated). +- [x] CI receives PostgreSQL tests before validation and release. +- [x] Platform output enabled through [CI Apply 36693151989](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693151989) (no resource change). +- [x] Secrets write permissions enabled through [CI Apply 36693644577](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693644577) (one update, no replacement). +- [x] [Validation 36693906434](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693906434) for `cd9d79f` successful, including PostgreSQL and browsers. +- [x] OAuth credentials supplied in release environment and CF backend after explicit approval. +- [x] [Release 36693906545](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36693906545): migration successful; privileged task app removed; web app, PostgreSQL and Secrets connection tests successful. +- [x] [Login release 36695423593](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36695423593): GitHub login enabled, secrets write/read/delete successful; health 200 and anonymous session 401. OAuth redirect, client ID, callback, PKCE S256, state and secure cookie checked live. +- [x] Real GitHub login and logout confirmed by user. +- [ ] Check installation on required repositories and fork prerequisites. +- [x] Fork selection, saving and reopening implemented and tested with simulation; live acceptance in [forks and navigation](forks-and-navigation.md). +- [ ] Implement organizations, invitations and tenant switching. Currently + each user receives their own isolated workspace. +- [ ] Regularly clean up expired session records and orphaned secrets. + Expired tokens are unusable; failed deletions are not yet + a durably processed cleanup job. Complete before wider release. +- [ ] Check distributed rate limit, audit retention and GitHub revocation; current + start limit applies only per instance, revocations are detected at latest on API use. + + +## Credential approval + +On 2026-09-30, the user explicitly approved transfer of `LZC_GITHUB_CLIENT_ID` and +`LZC_GITHUB_CLIENT_SECRET` for `lweberru/lz-configurator-dev-7dbff805` to +`stackitcloud/stackit-landing-zone`, environment `lzc-dev-release`, and the +subsequent CF backend binding. Both environment secrets +are stored; `LZC_AUTH_ENABLED=true` is set for the next release. +Live activation and secrets round trip completed successfully with release `36695423593`. diff --git a/landing-zone-configurator/docs/mvp-scope.de.md b/landing-zone-configurator/docs/mvp-scope.de.md new file mode 100644 index 0000000..292cdcd --- /dev/null +++ b/landing-zone-configurator/docs/mvp-scope.de.md @@ -0,0 +1,56 @@ + +# MVP-Umfang und Grenzen + +[English](mvp-scope.md) | [Deutsch](mvp-scope.de.md) + +Das MVP verbindet den unabhängig nutzbaren Accelerator mit einem mandantenfähigen +Editor, geprüften Assistant-Vorschlägen und ausdrücklich autorisierter Ausführung. +Es macht aus einem Konfigurationsentwurf keinen autonomen Deployment-Agenten. + + +## Enthaltene Implementierung + +- STACKIT-OIDC-Anmeldung, Mandantenmitgliedschaft und getrennte technische Ausführungsberechtigungen. +- Gemeinsame native Editor-/Compiler-Verträge, Import/Export und Erhaltung + bestehender Ressourcenidentitäten. +- Plattformentwürfe, Projektvorlagenentwürfe, unveränderliche Veröffentlichung und getrennte + Application-Instanzen. +- Geprüfte, revisionsgebundene Assistant-Vorschläge; kuratiertes Dienstwissen, + deterministische Validierung und Regressionsqualifikation mit echten Modellen. +- Getrennte Vorbereitung, Plan und Apply; isolierte gepinnte Runner, Fortschrittsausgabe, + verschlüsselte Artefakte und State-/Recovery-Verarbeitung. +- Automatische Quellvalidierung und manuell gestartete Workflows für Betreiberbereitstellung + und Anwendungsreleases. + +Implementierung, automatisierte Tests, eine erfolgreiche Cloud-Operation und +Produktionsabnahme sind unterschiedliche Nachweise. Keine Liste hier zertifiziert +jede mögliche Kundenkonfiguration oder Netzwerktopologie. + + +## Bewusste Grenzen + +- **Produktion ist zurückgestellt.** Im Rahmen des MVP-Quellmerges wird keine + Produktionsumgebung erstellt. Produktion benötigt eigene Identität, Netzwerk, + Backup, Recovery, Observability, Kapazität und betriebliche Abnahme. +- **Firewall-Policy folgt nach dem MVP** ([#101](https://github.com/stackitcloud/stackit-landing-zone/issues/101)). + Appliance-/HA-Vorschläge werden unterstützt, geführte Policy-/NAT-/Routenverwaltung + jedoch nicht. Der Firewall-Administrator pflegt die Policy in OPNsense. +- **Private Ausführungspfade benötigen separate Qualifikation** + ([#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37)). + Ein gehosteter Runner erreicht nicht automatisch private Firewall-, Kubernetes- + oder Helm-Endpunkte in Kundennetzwerken. +- **DNS-Rollen sind keine Sichtbarkeitssteuerung.** Primary und Secondary sind native + autoritative Rollen; die Konfiguration des Secondary-Servers ist unvollständig. +- **Die Integration des Managed Private DNS Resolver ist zurückgestellt** + ([#100](https://github.com/stackitcloud/stackit-landing-zone/issues/100)). + Bestehende DNS-Einstellungen für Zonen/Bereiche implementieren dieses separate Produkt nicht. +- **Cloud-Fakten bleiben extern.** Verfügbarkeit, Berechtigung, Durchsatz, nutzbare + Netze und effektive Rechte erfordern eine aktuelle verbindliche Prüfung. +- **Assistant-Qualifikation ist begrenzt.** Bestandene synthetische Szenarien beweisen + keine universelle sachliche Korrektheit. Jede fehlgeschlagene Wiederholung bleibt blockierend; + Änderungen an der qualifizierten Quelle benötigen neue Nachweise. + +Offene Arbeit wird in [GitHub-Issues](https://github.com/stackitcloud/stackit-landing-zone/issues) +verfolgt, nicht in datierten öffentlichen Übergabe- oder Abnahmeprotokollen. Siehe +[Benutzerhandbuch](user-guide.de.md), [Architektur](architecture.de.md) und +[Entwicklungsübersicht](development.de.md). diff --git a/landing-zone-configurator/docs/mvp-scope.md b/landing-zone-configurator/docs/mvp-scope.md index 02ca587..5018dd7 100644 --- a/landing-zone-configurator/docs/mvp-scope.md +++ b/landing-zone-configurator/docs/mvp-scope.md @@ -1,5 +1,7 @@ # MVP scope and limits +[English](mvp-scope.md) | [Deutsch](mvp-scope.de.md) + The MVP connects the independently usable Accelerator to a tenant-aware editor, reviewed Assistant proposals and explicitly authorized execution. It does not turn a configuration draft into an autonomous deployment agent. diff --git a/landing-zone-configurator/docs/plan-execution.de.md b/landing-zone-configurator/docs/plan-execution.de.md new file mode 100644 index 0000000..9bdb8b0 --- /dev/null +++ b/landing-zone-configurator/docs/plan-execution.de.md @@ -0,0 +1,729 @@ + + +# Erstbereitstellungspläne + +[English](plan-execution.md) | [Deutsch](plan-execution.de.md) + +Stand: 2026-10-02. Umsetzung auf `feature/landing-zone-configurator`. + + + +## Was der Benutzer testen kann (nach erfolgreichem Release) + +1. **Deployments** öffnen und im Abschnitt **Erstbereitstellung planen** eine + gespeicherte Vorbereitung auswählen. +2. Nur für eine neue Landing Zone bestätigen, dass noch keine Ressourcen und kein + bestehender State zu dieser Konfiguration existieren. Bestehende/teilweise + erzeugte Landing Zones sind in diesem Ablauf nicht unterstützt. +3. **Erstbereitstellung planen** starten. Erwartete Stationen: Runner vorbereiten, + initialisieren, validieren, planen und abgeschlossen/fehlgeschlagen. +4. Seite neu laden: Auftrag und Ergebnis bleiben erhalten. Anlegen, Ändern, + Ersetzen, Löschen, Datenlesen und geänderte Ausgaben werden getrennt gezählt. +5. Optional einen weiteren Plan abbrechen. Abbruch entzieht sofort den Broker- + Zugriff; das Stoppen des CF-Tasks durch Cleanup erfolgt zeitversetzt. + +**Keine Kunden-Ausführung in dieser Abnahme.** Der Benutzer verlangt ausdrücklich +eine neue Freigabe vor jedem Kunden-Apply; Infrastrukturfreigaben gelten nicht dafür. +Der ältere Erstbereitstellungsplan bleibt plan-only. Der neue Plattformpfad besitzt +einen gated Apply-Endpunkt: nur bei aktivierter Execution, passendem unveränderlichem +Planartefakt/Hash, bestätigter Zielorganisation und erneut geprüften Zugriffs-, +Quell- und State-Bindungen. Ein Export ist keine Apply-Freigabe. Kein Destroy-Pfad. + +Ein erfolgreicher Plan ist nicht automatisch fuer Apply freigegeben. Der Server +liefert zu einer gesperrten Freigabe einen Fehlercode und bei nicht unterstuetzten +Komponenten die betroffenen Felder mit Begruendung. Plan- und Apply-Seite zeigen +diese Sperre an; der Apply-Button bleibt sichtbar, aber deaktiviert. Ein +freigabefaehiger Plan zeigt weiterhin die explizite Pruefbestaetigung und verlangt +die exakte UUID der Zielorganisation. Alle Bedingungen werden vor Apply erneut +serverseitig geprueft. + +Firewall-/HA-Infrastruktur bleibt derzeit nur fuer Plan qualifiziert. Ein neuer +Plan allein hebt diese Komponentensperre nicht auf. Der Administrations- und +Bootstrap-Vertrag muss separat fuer Apply qualifiziert werden; Firewall-Policy +und VPN-PSKs werden dabei nicht stillschweigend ausgelassen. Konfiguration und +Plan-Nachweise bleiben unveraendert erhalten. Die komponentenweise +Ausfuehrungsqualifikation wird in +[#89](https://github.com/stackitcloud/stackit-landing-zone/issues/89) weitergefuehrt. + + + +## Plattformentwürfe mit Projekt-Templates + +Neue Editor-Konfigurationen enthalten Projekt-Template-Entwürfe statt konkreter +Anwendungsprojekte. Ihr tfvars-Export und damit ihr Erstbereitstellungsplan enthalten +**nur die Plattform**, keine Instanzen dieser Vorlagen. Alte Gesamtkonfigurationen +behalten ihre bisherigen Projekte. [Details und Bestandsschutz](project-template-drafts.de.md). + + + +## Application-Plan-Input und Plattformvertrag + +Der lokal aktivierte Application-Katalog hat einen eigenen Freigabe- und Bestellpfad. +Er startet **noch keinen CF-Task** und legt keinen State an. `Plan-Input prüfen` +ist eine erneute serverseitige Qualifikation und zeigt Terraform-Variablen, +Entrypoint und Ausführungssperre, kein berechnetes Ressourcenergebnis. + +Ein Platform Engineer kann im Application-Katalog einen JSON-Vertrag aus bereits +angewendeten, geprüften Plattform-Outputs laden. Das Dokument ist kein Terraform-State +und enthält keine Credentials. Minimaler Importvertrag: + +```json +{ + "schema_version": 1, + "organization_id": "00000000-0000-4000-8000-000000000001", + "targets": { + "public": { + "folder_id": "00000000-0000-4000-8000-000000000002", + "region": "eu01", + "corporate": false, + "network_area_id": null, + "firewall_next_hop_ip": null, + "ipv4_nameservers": null + } + } +} +``` + +Die UUIDs sind Platzhalter und müssen aus der tatsächlich angewendeten Plattform +kommen. Die Freigabe ist eine bewusste PE-Prüfung der Outputs, **keine automatische +Bestätigung, dass ein angegebener Ordner existiert oder zur Organisation gehört**. +Diese Ressourcenprüfung bleibt vor einer zukünftigen Job-/Credential-Freigabe nötig. + +- GET/POST `/api/v1/applications/platform-contracts`: aktuelle Tenant-Mitgliedschaft; + POST zusätzlich PE-Rolle, gültige menschliche STACKIT-Identität, Origin/CSRF, + `confirmApproval: true` und gespeicherten SA-Zugang. Optional `credentialProfileId`; + bei genau einem gespeicherten Profil automatische Auswahl. Organisationszugriff + wird technisch geprüft, ohne eine zweite menschliche OAuth-Anmeldung zu verlangen. +- Tenant und Revision werden serverseitig bestimmt. Migration 014 persistiert + unveränderliche Vertragsversionen mit Forced RLS und technischem Prüf-/Versionsnachweis. + Ein Zugangstest oder Vertrag ist keine Apply-Freigabe. +- POST `/api/v1/applications/templates` kann `platformRevision` und `targetKey` + gemeinsam binden. Region und Projektart müssen zum Vertragsziel passen; + tenantfremde Vertrags-IDs werden nicht sichtbar. Änderung erzeugt eine neue Version. +- POST `/api/v1/applications/instances/:id/plan-input` akzeptiert nur `{}`. + Der Besitzer wird aus Session und Bestellung ermittelt; fremde Bestellungen und + Client-Identitäts-/Backend-Overrides werden abgewiesen. Identitätsablauf, Widerruf, + Rollenentzug und geänderte Besteller-E-Mail werden erneut geprüft. +- Der Compiler verwendet exakt die Vertrags- und Template-Version der Bestellung, + feste Parameterregeln und den eigenen Instanz-State-Key. Die MVP-Teilmenge ist + Public mit lokalem Netz, ohne Observability-Ausführung oder Namespace-Dienste. + Die Antwort meldet ausdrücklich `cloudPlanExecuted: false` und + `executionEnabled: false`; keine Schlüssel werden an den Browser geliefert. + Die unveraenderliche Versions-/Bestellpolicy wird als `applyPolicy` uebernommen + (`approval-required` oder `direct`); `requiresExplicitApplyApproval: true` + bleibt fuer beide gesetzt. Eine direkte Policy ist keine Ausfuehrungsfreigabe. + +Für den tatsächlichen eigenen Cloud-Plan fehlen noch ein unveränderlich freigegebenes +Application-Runner-Artefakt, getrenntes State-Backend mit Locking und eng begrenzte +serverseitige Nutzung des PE-Zugangs durch genau den autorisierten Job. Der bisherige +Runner-Pin enthält kein Application-Root. Er wird nicht auf ungeprüften Arbeitsbaumcode +umgestellt. Application-Apply bleibt deaktiviert; der freigabegebundene +Plattform-Apply-Pfad ist davon getrennt. + + + +## Gemeinsamer Editor und Ausführungsumfang + +Schema v3 wird für eine konservative Standalone-Teilmenge unterstützt: eu01, +Organisations-Owner/Auditor, Ordner samt Namen und Owner-/Leseberechtigungen, +optional ein übergeordneter Ordner (UUID), explizit Public-Projekte in bestehenden +Gesamtkonfigurationen, Sandbox-Projekte, Grundeinstellungen und die bisherige +Secrets-Manager-Option. Leere oder nicht gesetzte Ordnerbeschreibungen sind zulässig; +gefüllte Beschreibungen werden bis zur Behebung von #82 gezielt abgewiesen, weil der +Accelerator sie nicht übernimmt. Netzwerk, Kubernetes, Firewall und zusätzliche Plattform- +oder Projektdienste bleiben für diesen Runner gesperrt. Die Prüfung erfolgt anhand +der effektiven Konfiguration, nicht anhand des Template-Namens. UI, Vorbereitung +und Broker verwenden `initialPlanIssues`; vor Übergabe der Zugangsdaten an den +Runner wird erneut geprüft. JSON und tfvars bleiben an dieselbe Git-Revision und +den unveränderten Export-Hash gebunden. Legacy-Dokumente bleiben unterstützt. + +Die Organisationstenant-Sperren gelten weiter. Der ältere Erstbereitstellungsplan +verwendet leeren State. Im neuen Plattformpfad wird bestehender State ausschließlich +über die geprüfte Backend-Bindung verwendet; fehlende oder widersprüchliche Bindungen +dürfen keinen stillen Neustart mit leerem State auslösen. +Erweiterte Ausführung: [#89](https://github.com/stackitcloud/stackit-landing-zone/issues/89). + + + +## Ablauf und Grenzen + +**Private Kubernetes-APIs:** Der aktuelle CF-Runner hat keinen nachgewiesenen +Zugriff auf Kunden-SNAs. Ein erfolgreicher STACKIT-Zugangstest belegt diesen +Netzwerkpfad nicht. Auch Plan/Refresh mit Kubernetes-/Helm-Providern kann ihn +benötigen. Die zweistufige Ausführung aus +[#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37) ist noch offen +und wird separat umgesetzt. Anforderungen an Ausführungssperren bei Erweiterung +des bisherigen Standalone-Vertrags stehen im +[Grenzenregister](accelerator-limitations.de.md#private-kubernetes-api-ausführungsgrenze). + + +- POST `/api/v1/plans` verlangt Session, exakten Origin, CSRF-Token und + `confirmNewDeployment: true`. Nur eine eigene Vorbereitung mit eigenem + gespeichertem Credential und Rolle admin/deployer wird akzeptiert. +- GitHub-Fork-Zugriff, festgehaltener Head und generierter tfvars-Export werden + mit dem GitHub-Benutzertoken erneut geprüft. Geänderter Fork-Head erfordert eine + neue Vorbereitung; es wird keine andere Version still übernommen. +- SQL 004/005 persistiert Aufträge mit Forced RLS, Vorbereitung, Status, Engine- + und Provider-Lock-Version sowie CF-Droplet-Referenz. Ein aktiver Auftrag pro + Benutzer/Mandant, höchstens 20 Starts in 24 Stunden; Liste zeigt letzte 100. +- Der Dispatcher verwaltet ausschließlich die separate Organisation + `lzc-dev-runners`, Space `plans`, SSH deaktiviert. Für jeden Auftrag erstellt er + eine App ohne Route/Service-Bindings und kopiert das geprüfte Runner-Droplet. + CF-Manager-Credentials verbleiben im vertrauenswürdigen API-Backend/Release. +- Der Runner erhält drei App-Variablen: Auftrags-ID, feste Broker-URL, zufälliges + 256-Bit-Ticket. In PostgreSQL liegt nur dessen Hash. Gültigkeit maximal 25 Minuten. + Eine eng begrenzte SECURITY-DEFINER-Funktion löst das Ticket auf genau einen + aktiven Auftrag auf; danach gelten Eigentümer-/Tenant-RLS und Rollenprüfung. +- Eingaben werden einmal ausgegeben, nach erneuter Rollen-, Profil-, Versions- + und Organisationsprüfung. Andere Profile oder Mandanten sind nicht auswählbar. + Die Terraform-Unterprozesse erhalten eine explizite Umgebung ohne Broker-Ticket. +- Fester Accelerator-Commit `a256f6896d11134fdc351786f1be5eba4e56b2e2`, OpenTofu + 1.12.6, Provider-Lock SHA-256 + `a52433c424472d6e618caa3a94579bbcd19b60b759d053cf0d5caf9ac6872888`. + CI baut nur Upstream-Code dieses Commits und einen Linux-Provider-Mirror. +- OpenTofu 1.12.6 exportiert im Saved-Plan-JSON 1.2 kein Terraform-Feld `complete`. + Der Worker darf Vollständigkeit für dieses genaue Format nur nach Prüfung der + gepinnten Engine und seinem festen vollständigen Plan-Befehl ohne Targeting + bestätigen. Der Summary-Parser verlangt diesen expliziten Engine-Kontext; + fehlender Kontext, unbekannte Versionen/Formate oder Deferred-Metadaten bleiben + `not-reported`, ein gemeldeter Teilplan bleibt `incomplete`. Fehlerstatus, + offene/fehlgeschlagene Checks und alle Artefakt-/State-/Freigabebindungen + sperren Apply weiterhin. Vorher gespeicherte Summaries werden nicht umgeschrieben. +- Direkte Befehle in `deploy/runner/run-plan.sh`: init mit readonly Lock, validate, + plan mit detailed exit code und show. Kein frei wählbarer Befehl. Der neue + Plattformpfad darf Apply nur mit dem freigegebenen gespeicherten Plan ausführen. +- Ergebnisprojektion enthält nur Zahlen, Status und feste Fehlercodes; keine + Adressen, Attributwerte, Output-Namen, Rohdiagnosen oder Geheimnisse. Auch nicht + als sensitive markierte Werte werden nicht in diese Summary exportiert. + Separat zeigt der Runner dem berechtigten Plan-Eigentümer unter + **OpenTofu-Ausgabe** die normale CLI-Textdarstellung: Live-Logs aus dem privaten + aktiven Job oder `tofu show -no-color` des exakt hash-/paketgebundenen, + verschlüsselt gespeicherten Planartefakts. Sitzung, Deployment-Rolle und + Eigentümer-/Tenant-RLS werden vor jedem Zugriff geprüft; Antworten sind + `no-store`. Ressourcenadressen und normale Attributwerte sind dort sichtbar, + sensitive Werte bleiben durch OpenTofu maskiert. Bekannte Credential-Felder + werden aus Live-Logs zusätzlich entfernt. Plan-Binary und `show -json` bleiben + serverseitig. Es laufen kein neuer Cloud-Plan, kein Apply und kein Backend-Init; + die Inspektion verwendet nur backendfreies Init und Show ohne geerbte Secrets. + Die Apply-Ablauffrist bleibt unabhängig von der read-only Anzeige, solange das + verschlüsselte Artefakt vorhanden ist. +- Aktive Plattformaufträge öffnen einen NDJSON-Live-Kanal auf + `GET /api/v1/plans/:id/output` mit `Accept: application/x-ndjson`. + JSON-Snapshots bleiben für Historie und bestehende Clients erhalten. Der Worker + liest vollständige Log-Zeilen alle 500 ms und überträgt nur geänderte, + redigierte Mitschnitte. Nach dem verschlüsselten Commit benachrichtigt die API + ihre lokalen Abonnenten; andere API-Instanzen prüfen spätestens nach einer + Sekunde erneut. Unveränderte Ausgabe erzeugt nur ein Heartbeat, keinen neuen + Mitschnitt. Sitzung, Workspace, Deployment-Rolle und Eigentümerschaft werden + während der Verbindung erneut geprüft, nicht nur beim Öffnen. + Verbindungen enden nach spätestens 35 Sekunden und werden bei weiterhin + aktivem Auftrag erneut geöffnet. Collapse, Navigation und Abmeldung brechen + sie ab. Pro Eigentümer/Tenant sind je API-Instanz höchstens acht Verbindungen + erlaubt; langsame Leser erzeugen Backpressure statt unbegrenzter Warteschlangen. +- Der Plan verwendet OpenTofus native `-json`-UI-Ereignisse für tatsächliche + Fortschrittsmeldungen, auch bevor der fertige Diff existiert. Nur menschliche + Meldungen des unterstützten UI-Protokolls werden projiziert; rohe Ereignisse, + Metadaten und Output-Werte werden nicht an den Browser gesendet. + Unvollständige Zeilen bleiben zurückgehalten, ungültige Ereignisse erhalten + einen sichtbaren festen Fehlerhinweis. Anschließend ergänzt + `tofu show -no-color plan.bin` den vollständigen normalen Plantext. + Init, Validate, Apply und Migration behalten ihre native CLI-Ausgabe. + Es gibt keine geschätzten Prozentwerte: wenn OpenTofu während einer Operation + keine Meldung erzeugt, bleiben Phase und Laufzeit sichtbar. +- Während des Laufs und vor dem terminalen Ergebnis sichert der Worker den redigierten CLI-Mitschnitt + von Init/Validate/Plan/Apply/Migration über `POST /api/runner/output`. Das + auftragsspezifische Ticket muss gültig und die Eingabe bereits beansprucht sein; + der Text darf bis zum Abschluss aktualisiert werden, danach ist er eingefroren. Migration 020 legt + dafür private Output-Spalten unter der bestehenden Eigentümer-/Tenant-RLS an. + Der Broker verschlüsselt maximal 2 MiB mit AEAD und auftragsspezifischer AAD. + Erfolgs- und Fehlerausgaben bleiben nach Cleanup und Reload lesbar, ohne laufenden + Runner. Kürzungen sind gekennzeichnet. Ein harter Prozessabbruch oder gescheiterter + Upload kann weiterhin historische Ausgabe verlieren; die best-effort Sicherung + löst weder einen Apply-Retry aus noch ersetzt sie den dauerhaften State-Recovery- + Empfangsnachweis. Apply-Nachweise zeigen den exakten Plan, SHA-256, + Zielorganisation, das State-Backend des Auftrags und die Abschlusszeit. + Ein inkompatibles natives Runner-Paket sperrt Apply bereits vor Dispatch; + ein neuer Plan mit erneuter Prüfung und Freigabe ist erforderlich. +- Task: 1 GiB RAM, 4 GiB Disk, 18 Minuten Engine-Frist, private Dateien begrenzt. + SQL-Frist: 25 Minuten. Maintenance alle 30 Sekunden, Cleanup nach mindestens + 30 Sekunden terminalem Status. Auch nach API-Neustart werden Aufträge abgeräumt. + Bei CF-/Netzfehlern kann Cleanup länger dauern; Ticket-Ablauf bleibt unabhängig. +- Kein automatischer Dispatch-Wiederholungsversuch. Ein Prozessverlust vor Start + führt zu Abbruch/Ablauf statt stiller Neuausführung. Es gibt noch keinen allgemeinen + Queue-Scheduler und keine dauerhafte Runner-Heartbeat-Überwachung. Der neue + Plattformpfad speichert Planartefakte verschlüsselt und bindet sie an Quelle, + Engine und State-Version. CF-Quoten begrenzen die Gesamtkapazität zusätzlich. +- Vorbereitungen mit Plan-Nachweisen werden nicht gelöscht. Archivierung und + Aufbewahrungsfristen der Metadaten sind ein nachfolgender Schritt. + + + +## State-Lebenszyklus gemäß LZA + +Entscheidung des Benutzers: bestehenden +[LZA-Bootstrap](https://github.com/stackitcloud/stackit-landing-zone/blob/main/docs/getting-started.md) +übernehmen. Der gespeicherte Zugang ist der Bootstrap-Service-Account; Projekt und +Account werden nicht erneut angelegt. Ein Plan legt weder Management-Projekt noch +Bucket an. Im neuen Plattformpfad dient das dauerhafte, verschlüsselte HTTP-Backend +nur dem Bootstrap, nicht als permanenter Ersatz für den Kunden-S3-State. + +Beim separat freigegebenen ersten Apply erzeugt das Management-Modul den +Kunden-State-Bucket samt Credentials. Danach migriert der Runner mit +`tofu init -migrate-state`; die API bestätigt die Migration erst nach Abgleich von +State-Hash und Remote-Version/ETag sowie gebundener State-Version. Erst danach +wird der HTTP-Primärstate entfernt. Anschließend wird der verifizierte +Management-Service-Account verwendet. Das S3-Backend nutzt `use_lockfile = true`. +Application-Instanzen erhalten jeweils eigene Keys +`applications///terraform.tfstate`; Plattform-, +Application- und Configurator-Infrastruktur-States bleiben getrennt. + +Legacy-State-Zuordnungen sind mit `legacy_state_migration_required` gesperrt und +benötigen eine explizite Zuordnung/Migration, keinen neuen leeren State. Bei +`state_failed` oder unbestätigter Migration ist vor Wiederaufnahme ein expliziter +State-Abgleich erforderlich; eine abgeschlossene S3-Kopie kann wie unten +beschrieben ohne erneuten Apply bestätigt werden. Andere Recovery-Fälle +benötigen weiterhin einen geschützten Export. Der Runner übermittelt einen geprüften, +verschlüsselten Recovery-Nachweis und entfernt lokale Fehlerstates erst nach +passender dauerhafter Empfangsbestätigung. Das garantiert keine automatische +vollständige Wiederherstellung nach jedem harten Runner-Verlust; Abgleich und +operative Recovery bleiben erforderlich. Ein echter Cloud-S3-Lock-Test wurde +nicht durchgeführt. Kein Kunden-Apply wurde in dieser Umsetzung ausgeführt. + + + +## Konfiguration nach fehlgeschlagenem Bootstrap-Apply korrigieren + +Migration `034_platform_reconciliation.sql` ergaenzt einen ausdruecklichen, +auditierten UI-Abgleich. In der Apply-Ansicht liest erst **Checkpoint pruefen** +den verschluesselten Bootstrap-Checkpoint des eigenen fehlgeschlagenen Applys. +Die Antwort enthaelt nur State-Version, SHA256, Serial, Lock-/Migrationsstatus +und Ressourcenanzahlen nach Typ; keine Attribute, Outputs oder Rohstates. + +**Erneute Planung freigeben** erfordert eine gesonderte Bestaetigung zum +unveraenderten Erhalten des States. Die API prueft die angezeigte Version und +Pruefsumme erneut in einer Transaktion. Nur ein regulaer mit `apply_failed` +beendeter, bereits gestarteter Apply mit lesbarem Bootstrap-Checkpoint, +positiver State-Version, ohne gehaltenen Lock, offene Migration oder separaten +Recovery-State ist freigebbar. Ein unveraenderlicher, tenant-/ownergebundener +Auditbeleg bindet Apply, echte Sitzung, State-Key, Version und Pruefsumme. +Gleichzeitige identische Bestaetigungen erzeugen nur einen Beleg. Der Run wird +als fehlgeschlagen abgeschlossen; State, Version, Lock und Backend bleiben +unveraendert. Es erfolgen weder Cloud-Zugriffe noch ein automatischer Plan/Apply. + +Danach kann der Benutzer die korrigierte Konfiguration speichern, eine neue +Vorbereitung waehlen und einen neuen Plan gegen denselben bestehenden State +starten. Fuer Apply ist erneut die separate Pruefung und Freigabe des neuen +gespeicherten Plans erforderlich. Der alte Plan bleibt verbraucht. Bei einem +zwischenzeitlich veraenderten Checkpoint ist eine neue Pruefung erforderlich. +Unklare Runner-Abbrueche, nicht verifizierbare Migrationen und separate Recovery- +States bleiben gesperrt und benoetigen einen gesonderten operativen Abgleich. +Es gibt keine automatische Entsperrung, State-Loeschung, Import- oder +Destroy-Aktion. Die Migration muss vor Nutzung der neuen API aktiviert sein. + + + +### Erfolgreichen Apply mit offener S3-Bestaetigung abschliessen + +OpenTofu 1.12.6 verwendet bei der HTTP-zu-S3-Migration eine neue Lineage und +Serial 1. Das ist mit dem echten, gepinnten Runner-Binary und ausschliesslich +synthetischen lokalen HTTP-/S3-Endpunkten reproduziert, auch nach mehreren +Ausgangs-State-Schreibvorgaengen. Die fruehere Forderung nach identischem +Gesamt-Hash, Lineage und Serial lehnte diese erfolgreiche Kopie ab. +`migrationStateMatches` akzeptiert neben einer exakten Vollkopie nur diese +nachgewiesene Transformation: Quellversion 1.12.6, neue Lineage, Ziel-Serial 1 +und ansonsten exakt gleicher kanonischer State-Inhalt. Ressourcen, Attribute, +Outputs, Format, Version und alle weiteren Felder bleiben vollstaendig geprueft. +Nur die Reihenfolge der obersten `check_results`-Liste wird beim gepinnten +nativen Migrationsvergleich normalisiert. Alle vollstaendigen Pruefeintraege +einschliesslich ihrer verschachtelten Inhalte und mehrfacher Eintraege bleiben +erhalten; es wird nichts entfernt oder auf erfolgreiche Statuswerte reduziert. +Diese Reihenfolgeaenderung ist mit echten OpenTofu-Validierungen reproduziert. +Globale State-Hashes, Quell-Sicherungsbelege und andere Array-Reihenfolgen +bleiben unveraendert. Geaenderte Pruefergebnisse oder Ressourcen bleiben gesperrt. +Unbekannte Versionen oder beliebige Serial-/Inhaltsaenderungen werden nicht +freigegeben. Das Host-Binary darf nicht als Runner-Version angenommen werden; +der Native-Test verwendet `LZC_NATIVE_TOFU_BINARY` und prueft die echte Version. + +Bei einem regulaer beendeten `state_failed` mit gebundener offener Migration +liest **Checkpoint pruefen** auf ausdruecklichen Klick den verschluesselten +Bootstrap-State und den bereits registrierten S3-State. Es werden nur aggregierte +Metadaten angezeigt, einschliesslich S3-Pruefstand, Serial und dem Bool-Wert, +ob die Lineage erhalten blieb. Ohne Lock, separate Recovery oder abweichenden +Inhalt kann der Benutzer die eigene **Backend-Migration bestaetigen**. + +Diese Bestaetigung bindet Quellversion, Quell-SHA und den exakten Remote- +Objektstand. Vor Abschluss werden alle Belege erneut geprueft. In derselben +Transaktion erfolgen der bereits vorhandene CAS-Backend-Wechsel, der +unveraenderliche Auditbeleg und der Abschluss des Applys als `succeeded`. +Erst nach erfolgreichem S3-Abgleich wird der temporaere Bootstrap-Primaerstate +entfernt. Identische parallele Bestaetigungen sind idempotent. Kein Runner, +Apply, S3-Schreibzugriff, Import, Unlock oder Destroy wird dabei gestartet. +Bei einem geaenderten Pruefstand bleiben Bootstrap-Sicherung und Recovery- +Sperre erhalten. Eine neue Schema-Migration ist hierfuer nicht erforderlich. + + + +### Lokale Aktivierung am 2026-10-06 + +Nach ausdruecklicher Freigabe wurden die laufende Kunden-DB privat gesichert, +der vollstaendige Dump in einer getrennten loopbackgebundenen PostgreSQL-17- +Instanz restauriert und dort mit dem echten Migrator auf Migration 034 gebracht. +Zeilenzahlen und Hashes aller 32 bestehenden Tabellen in `lzc` und `lzc_auth` +blieben unveraendert. Erst danach wurde die API ohne laufende Kundenjobs neu +gestartet. Derselbe Vergleich bestand auch nach der Live-Migration. + +Die Live-DB enthaelt nun Migrationen 001 bis 034; die neue Audit-Tabelle ist leer +und hat erzwungene RLS. Der fehlgeschlagene Apply bleibt `recovery_required`. +Das bisherige unveraenderliche Platform-Runner-Paket bleibt aktiv; +Application-Ausfuehrung bleibt ausdruecklich deaktiviert. API und UI-Proxy +antworten auf Health-Pruefungen mit 200, die neuen Checkpoint-/Freigaberouten +ohne Anmeldung mit 401 und der deaktivierte Application-Runner mit 404. +Die UI liefert den qualifizierten aktuellen Build. Die temporaere Restore- +Instanz samt eigenem Volume wurde entfernt; privater Dump und Hash-Nachweise +bleiben fuer Wiederherstellung erhalten. + +Diese Aktivierung pruefte ausschliesslich Sicherung, Schema, Datenbewahrung +und Zugriffssperren. Der Kunden-Checkpoint wurde weder entschluesselt noch +freigegeben. Die echte Checkpoint-Pruefung und Bestaetigung erfolgen durch den +Benutzer in seiner angemeldeten UI. Es wurde kein Cloud-Plan/Apply gestartet. + + + +### Aktivierung des S3-Abschluss-Fixes am 2026-10-06 + +Nach dem vom Benutzer gemeldeten erfolgreichen Apply und `init -migrate-state` +wurde der aktuelle DB-Stand erneut privat gesichert. Vor dem reinen Code- +Neustart liefen keine Platform- oder Application-Jobs. Zeilenzahlen und Hashes +aller 33 bestehenden Tabellen, nun einschliesslich Recovery-Belegen, blieben +nach dem Neustart unveraendert. Migrationen 001 bis 034, das gebundene native +Platform-Paket und die deaktivierte Application-Ausfuehrung bleiben bestehen. +API und UI-Proxy `/healthz` antworten mit 200; Checkpoint-/Freigaberouten ohne +Anmeldung mit 401 und der deaktivierte Application-Runner mit 404. + +Der aktuelle Build besteht das kanonische Gate mit 376 Unit-Tests sowie alle +42 isolierten PostgreSQL-Brokerfaelle, 16 Backend-Tests einschliesslich echter +lokaler OpenTofu-1.12.6-Migration und 12 betroffene Desktop-/Mobil-Browserfaelle. +Die Browser- und Brokerfaelle verwenden kontrollierte Testdaten; sie belegen +nicht den erfolgreichen S3-Abgleich des Kundenlaufs. Dieser wurde bei der +Aktivierung weder gelesen noch bestaetigt und bleibt ein ausdruecklicher +UI-Schritt des Benutzers. Es wurde kein Kunden-Apply wiederholt. + + + +### Nachgewiesene Check-Reihenfolge und Korrektur am 2026-10-06 + +Nach ausdruecklicher Freigabe wurde genau der offene Migrationsfall lokal +entschluesselt und dessen gebundener S3-State ausschliesslich lesend verglichen. +Es wurden nur maskierte Strukturpfade und Gleichheits-/Anzahlmetadaten +ausgegeben, keine Werte, Schluessel oder Rohstates. Alle 36 vollstaendigen +Pruefeintraege waren gleich, aber anders angeordnet; Ressourcen, Attribute und +Outputs waren identisch. Der korrigierte Vergleich besteht auch fuer diesen +State. Der vorherige Vergleich wurde mit 24 echten lokalen OpenTofu- +Validierungen als fehlschlagender Native-Regressionsfall reproduziert. + +Nach frischem privaten Backup und null aktiven Jobs wurde nur die API mit +unveraendertem Platform-Paket neu gestartet. Alle 30 Nicht-Authentifizierungs- +Tabellen, insbesondere States, Backends, Plans, Artefakte und Recovery-Belege, +blieben unveraendert. Parallel wurden eine weitere Sitzung und Aenderungen an +Identitaets-/Zugangsmetadaten beobachtet; diese drei Tabellen sind deshalb +nicht als unveraendert ausgewiesen und wurden nicht zurueckgesetzt. +Keine Schema-Migration oder S3-Schreibaktion wurde durchgefuehrt; die eigentliche +Backend-Bestaetigung bleibt ein gesonderter Benutzer-UI-Schritt. +Das Gate besteht mit 387 Unit-Tests, 27 Backend-Tests einschliesslich nativer +Migration und allen 42 isolierten PostgreSQL-Brokerfaellen. + + + +## Portabler GitHub-Export + +Der Export schreibt atomar `landing-zone.json`, `landing-zone.tfvars` und eine +kurze CLI-Anleitung unter `src/config/custom//`. Bei einer +serverseitig verifizierten S3-Bindung kommt `backend.tf.json` hinzu: vollständige +Standard-Terraform-Backend-Konfiguration ohne AWS-/SA-Schlüssel oder State-Datei. +Nur `backend_not_found` erlaubt einen neuen Bootstrap-Export ohne Backend; +Service- und Berechtigungsfehler brechen das Speichern ab. Eine vorhandene +Backend-Datei muss exakt dem deterministischen Git-Blob-Hash des geprüften +Deskriptors entsprechen. Andernfalls gilt `backend_configuration_changed`; +fehlt die Bindung, gilt `backend_configuration_missing` statt Metadatenverlust. + +Beim ersten DB-zu-GitHub-Export bleibt die Konfigurations-ID erhalten. Eine +bereits geöffnete Git-Konfiguration behält ihre eigene ID. Bei abweichender +Quell-ID exportiert der Server den gebundenen Deskriptor ohne Alias- oder +State-Mutation; eine neue Vorbereitung muss den registrierten Backend-ID +ausdrücklich auswählen. Für unabhängigen CLI-Betrieb: geprüften Accelerator-Code +verwenden, ursprünglichen Backend-Block in `src/backend.tf` deaktivieren, +exportierte Backend-Datei nach `src/backend.tf.json` kopieren und genau einen +aktiven Backend-Block behalten. AWS-Zugang aus dem Management Secrets Manager +gemäß LZA in die Umgebung laden, dann `tofu init` und +`tofu plan -var-file=config/custom//landing-zone.tfvars`. +Ohne S3-Bindung zuerst LZA-Bootstrap und verifizierte State-Migration abschließen. + + + +## Abnahme + +- [x] API: Session/CSRF, striktes Eingabeschema, Erstbereitstellungsbestätigung, + persönliches GitHub-Token und kein Apply-Endpunkt getestet. +- [x] PostgreSQL: fremde Aufträge, konkurrierender Start, Ticket-Replay, Status- + Reihenfolge, Ablauf und gezieltes Cleanup getestet. +- [x] CF-Client: eigene App, feste Befehle, nur drei Job-Variablen und keine Route. +- [x] Desktop/Mobil: Plan-Start, laufender Status, Ergebnis nach Reload, kein Apply. +- [x] Lokaler echter OpenTofu-Vertragstest ohne Cloud-Zugang und ohne Apply. +- [x] Separate CF-Organisation samt Manager per Plattform-IaC erstellt. +- [x] Runner-Space/Rollen per Runtime-IaC erfolgreich angewendet. +- [x] Linux-Paket, Provider-Mirror und CF-Engine-Test erfolgreich. +- [x] Live-App: separaten Runner ohne Service-Bindings prüfen, ungültiges Ticket + darf keinen Kundenauftrag ausführen; Probe-App entfernen. +- [ ] Erster persönlicher Kunden-Plan durch den Benutzer. + + + +## Live-Abnahme vom 2026-09-30 + +[Release 36727211809](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36727211809) +für `b5686ef` erfolgreich: CF-Engine init/validate, Datenbankmigrationen, +PostgreSQL-/Secrets-Manager-Verbindungen, separate Probe-App und öffentliche +Route. Runner-Verwaltungsidentität hat keinen Zugriff auf die Configurator-App; +Probe-App ohne Routen oder Service-Bindings. Zufälliges, nicht registriertes Ticket +führte zu einem fehlgeschlagenen Task. Dies ist eine Infrastruktur-/Isolationsprobe, +noch kein erfolgreicher persönlicher Kunden-Plan. + +Gemessen vom Dispatch bis zur Task-Erstellung: **3.907 ms**; bis zum beobachteten +Task-Ende: **12.244 ms**. Ein Einzelwert, keine Latenzgarantie. Die Probe nutzt die +vorab gestagte Vorlage, keinen `cf push` pro Auftrag. Reguläre Jobausführung hat +zusätzlich Eingabe-/Zugriffsprüfung und OpenTofu-Laufzeit. Kein Kunden-Apply. + + + +## Quellen + +[OpenTofu JSON-Format](https://opentofu.org/docs/internals/json-format/), +[Plan-Exitcodes](https://opentofu.org/docs/cli/commands/plan/), +[CF V3 Droplet-Kopie](https://v3-apidocs.cloudfoundry.org/version/3.199.0/index.html#copy-a-droplet), +[CF V3 Tasks](https://v3-apidocs.cloudfoundry.org/version/3.199.0/index.html#create-a-task). + + + +## Release des v3-Standalone-Planpfads (2026-10-01) + +Commit `9aa3322`, [Release 36849188406](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36849188406) +und [Validierung 36849188417](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36849188417) +erfolgreich. Lokal 123 Unit-, 22 PostgreSQL- und 38 Browserprüfungen; echter +OpenTofu-Plan-Summary-Test und vier native Application-Root-Verträge mit 1.12.6. +Die Datenbankprüfung umfasst Legacy/v3 und die erneute Sperrprüfung im Broker. +Die Live-App liefert das neue Bundle, Health 200 und anonym geschützte APIs 401. +Dies ist keine persönliche Kunden-Plan-Abnahme und kein Kunden-Apply. + + + +## Governance-Qualifikation und Service-Account-Föderation (2026-10-01) + +Die Freigabe der Governance-Eingaben wird zusätzlich mit dem tatsächlich +verwendeten Governance-Modul geprüft: `npm run test:plan` ruft den separaten +`test-governance-contract.sh` auf. Quellhashes binden die Prüfung an den +Accelerator-Pin. OpenTofu 1.12.6 plant mit Mock-Providern in bereinigter Umgebung, +ohne Cloud-Credentials und ohne Apply. Geprüft werden Organisationsrollen +`owner`/`organization.auditor`, Ordnerrollen `owner`/`auditor`, das Auslassen +doppelter Ordnerzuweisungen für Organisations-Owner sowie beide Elternvarianten. +Diese lokale Qualifikation ersetzt keinen Plan gegen die konkrete Kundenorganisation. + +**Service-Account-Föderation für CI/CD** ist eine optionale Editor-Komponente. +Sie regelt, welche OIDC-Tokens externer Pipelines den Management-Service-Account +nutzen dürfen; sie ist keine Benutzeranmeldung am Configurator. +`issuer` ist der vertrauenswürdige Aussteller, `aud` die Token-Zielgruppe und +`sub` beispielsweise das konkrete GitHub-Repository mit Branch. Bedingungen +verwenden den vom gepinnten Provider unterstützten Vergleich `equals`; `aud` +ist erforderlich. Die GitHub-Vorlage begrenzt `sub` auf einen angegebenen Branch +und gilt nicht unverändert für Jobs mit GitHub Environments. + +Die Komponente richtet keinen Workflow oder Token-Austausch ein und entfernt +keine bestehenden Schlüssel. Für den aktuellen Configurator-Runner und einen +kleinen Erstbereitstellungsplan ist sie nicht erforderlich. Ihre Ausführung +bleibt bis zur gesonderten Runner-Qualifikation gesperrt; Speichern und Bearbeiten +der Konfiguration bleiben möglich. + +Quelle: [STACKIT Provider 0.114.0 – Service Account Federated Identity Provider](https://registry.terraform.io/providers/stackitcloud/stackit/0.114.0/docs/resources/service_account_federated_identity_provider). + + + +### Release-Nachweis + +- Quellstand `64e33cb`, [Release 36856248765](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36856248765) und [Validierung 36856248770](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36856248770) erfolgreich. +- Lokal: 140 Unit-Tests, Desktop-/Mobil-Browserprüfung einschließlich Überlaufprüfung, drei Governance-Mockpläne sowie die vorhandenen OpenTofu-Plan-/Application-Vertragstests erfolgreich. +- Live: SPA und Assets HTTP 200 (`index-CnPzJNzo.js`, `index-DoULK2fp.css`), `/healthz` HTTP 200, anonyme Session HTTP 401. Release-Verbindungstests erfolgreich. +- Kein Kunden-Apply, keine Abnahme eines echten Kunden-Plans und kein Merge nach main. + + + +## Begrenzte Plattform-Credential-Grants + +Lokal implementiert am 2026-10-05, noch nicht in der laufenden Kunden-API +aktiviert: Migration `025_plan_credential_grants.sql` legt bei ausdruecklichem +Plan-Start beziehungsweise bestehender ausdruecklicher Apply-Freigabe einen +Grant in derselben Transaktion an. Es gibt keine allgemeine Credential- +Delegation und keine automatische Nachruestung fuer alte wartende Jobs. + +Der unveraenderliche Beleg bindet Job, Tenant, Benutzer, Vorbereitung, +Organisation, Credential-Profil, Secret-Version, Key-ID, Manifest-Hash und +Operation (`plan` oder `apply`). Seine Gueltigkeit endet spaetestens mit +Job-Ticket oder ausstellender Sitzung. Er enthaelt keine Schluessel oder Tokens. +SQL prueft die Bindung an den echten Job und dessen Vorbereitungsdaten; +RLS begrenzt Zugriff auf den eigenen aktuell autorisierten Deployment-Benutzer. + +Der Runner beansprucht den Grant einmalig, bevor die technische Credential- +Pruefung oder der Secret-Abruf stattfinden. Fehlende, abgelaufene, widerrufene +oder abweichende Grants sperren diese Nutzung. Vor Rueckgabe von Schluessel, +Backend und gegebenenfalls gespeichertem Plan werden Grant, Ablauf und +initialisierender Job erneut geprueft. Ein fehlgeschlagener Claim wird nicht +zurueckgesetzt; ein neuer Auftrag verlangt eine neue ausdrueckliche Freigabe. +Parallele Input-Anfragen koennen nur einmal Credentials erhalten. + +`POST /api/v1/plans/{id}/credential-grant/revoke` verlangt Origin, CSRF, den +aktuellen `x-lzc-tenant` und ausschliesslich +`{"confirmCredentialGrantRevocation":true}`. Wiederholter Widerruf liefert +denselben Beleg. Normales Plan-Abbrechen widerruft einen noch ungenutzten +Grant ebenfalls. Bereits beanspruchte Grants liefern +`credential_grant_already_consumed`; bereits uebertragene Credentials koennen +nicht aus einem Runner zurueckgeholt werden. Laufender Worker, Cloud-IAM- +Schluesselrotation und Recovery muessen bei einem solchen Vorfall gesondert +behandelt werden. Ticketgebundene Ergebnis-/Recovery-Endpunkte bleiben +unveraendert und sind nicht erneut Credential-Ausgabe. + +Diese Grenze beschraenkt den Credential-Abruf, nicht die Cloud-IAM-Rechte des +Schluessels oder eine bereits laufende Operation. Least-Privilege-Qualifikation, +Application-Root-/Instanz-Dispatch mit eigenem State und Grant sowie echte +Zwei-Organisations-/Widerrufsabnahme bleiben #91/#93. AO erhalten durch diesen +Schritt keinen Zugriff auf Plattform-Credentials. 31 echte isolierte PostgreSQL- +Broker-/Grantfaelle und der kanonische Gesamtcheck bestehen. + + + +## Lokaler Application-Runner-Root (2026-10-05) + +Der Feature-Zwischenstand ist lokal als `4ad9367` gesichert. Der separate +Application-Quell-Pin ist `4d15d7870afa323badd93559d8b37c5a8d138dcf`; +Backend, Provider und Versionsanforderungen liegen in getrennten Dateien. +Der bisherige Plattform-Pin `a256f6896d11134fdc351786f1be5eba4e56b2e2` +und bereits gebundene Runner-Pakete bleiben unveraendert. + +Mit `LZC_LOCAL_RUNNER_PACKAGE=true` und `LZC_PACKAGE_APPLICATION_ROOT=true` +packt das Build-Skript zusaetzlich ausschliesslich `src/application` und +`src/modules/landing-zone` aus dem festen Git-Pin als `application-src`. +Ein neuer, noch nicht existierender `LZC_RUNNER_PACKAGE_DIR` ist zu verwenden. +Der eigene Provider-Lock pinnt STACKIT 0.114.0 und time 0.14.1, mit geprueften +Checksummen fuer Darwin ARM64 und Linux AMD64. Seine SHA-256 ist +`d40debbff204aee590c2a76d09f6ad3234643329b438fd5c6497de60687f6fa5`. +Die Application-Paketierung ist fuer den produktiven Build bewusst gesperrt. + +Die neuen Worker-Modi `application-plan` und `application-apply` verlangen +den festen Application-Pin/Lock und eine strikte Bindung aus `tenantId` und +`instanceId`. Der S3-Key muss exakt +`applications///terraform.tfstate` sein; Lockfile ist +verpflichtend. Bootstrap-/Plattform-State und freie Root-Pfade werden abgewiesen. +Das Arbeitsverzeichnis behaelt den relativen Modulpfad, liegt aber getrennt +vom Plattform-Root. Apply verwendet nur den gespeicherten Plan, ohne Replan +oder Bootstrap-Migration. Bei fehlgeschlagener Recovery-Uebertragung bleiben +nur der private Application-Recovery-State und seine Verzeichnisse erhalten. + +Dies ist noch kein Application-Broker-Dispatch oder Cloud-IAM-Scope: +`executionEnabled: false` bleibt bestehen. Instanz-Jobs, eigene echte Locks, +PE-autorisierte Credential-Grants, Ablauf/Widerruf, Quoten und explizite Upgrades +muessen noch angebunden werden. Der neue Quell-Pin braucht eine ausdrueckliche +neue Template-Veroeffentlichung; gespeicherte Versionen/Plans werden nicht +umgebunden. Kein aktives Paket wurde ausgetauscht und keine Kundenoperation +gestartet. Die Worker-Tests verwenden eine kontrollierte Engine, waehrend +Paket-Init/Validate und die nativen Mock-Vertragstests echtes OpenTofu verwenden. + + + +## Vorbereitete Application-Jobs und Grant-Belege (2026-10-05) + +Der Begriff Quell-Pin bezeichnet eine feste Git-Commit-ID des Accelerator- +Terraform-Codes, keine Zugangsdaten oder persoenliche PIN. Neue Publikationen +koennen `acceleratorRevision` ausdruecklich auf den qualifizierten Application- +Commit `4d15d7870afa323badd93559d8b37c5a8d138dcf` setzen. Dies erzeugt eine neue +immutable Template-Version; der bisherige Default und alle Altversionen bleiben +unveraendert. Andere Commits werden abgewiesen. Die API-Pin-Auswahl ist noch +nicht als zusaetzlicher UI-Publikationsschritt angebunden. + +Migration 026 speichert Jobs mit Status `prepared` und SQL-abgeleitete Grant- +Belege. `POST /api/v1/applications/instances/{id}/jobs` verlangt genau +`{"idempotencyKey":"","confirmPlan":true}`. Session, aktueller Tenant, +Origin und CSRF werden geprueft; Rolle, verifizierte Bestelleridentitaet, +Eigentum, Version/Policy und Compiler-Eingaben werden erneut aus den gespeicherten +Datensaetzen gelesen. Nur der qualifizierte Application-Quellstand wird angenommen. +Ein transaktionaler Lock serialisiert den Idempotenzschluessel. Wiederholung +liefert denselben gueltigen Auftrag; abgelaufener oder widerrufener Grant wird +nicht durch Retry erneuert. Ein frischer Auftrag braucht einen neuen Schluessel +und eine erneute ausdrueckliche Bestaetigung. + +Der SQL-Trigger prueft die echte Session, die verifizierte Organisation, +aktuelle PE-Mitgliedschaft des Vertragsfreigebers und aktuelle Bestelleridentitaet. +Er leitet Organisation, Profil-/Secret-Version/Key-ID, Besteller, Instanz, +Template-/Vertragsversion, Quellstand, Compiler-Hash, Operation und State-Key +ab. Der Ablauf ist durch echte Session, Human-Token und maximal 25 Minuten +begrenzt. Die App-Rolle darf keine Grants direkt einfuegen oder Bindungen +veraendern; Tenant-/Owner-RLS und unveraenderliche Belege bleiben erzwungen. + +`POST /api/v1/applications/jobs/{id}/credential-grant/revoke` verlangt genau +`{"confirmCredentialGrantRevocation":true}` mit denselben HTTP-Grenzen. +Besteller oder vertragsfreigebender aktueller PE duerfen innerhalb des Tenants +widerrufen. Wiederholung liefert denselben Zeitbeleg; Widerruf kann nicht +zurueckgesetzt werden. + +Die Job-Antwort enthaelt nur ID, Instanz, Status und Ablauf sowie +`executionEnabled:false` und `cloudPlanExecuted:false`. Keine Credentials, +kein Ticket und kein Runner-Start. Ein Grant-Beleg ist noch keine einmalige +Credential-Uebergabe, State-Datei oder Cloud-Operation. Die einmalige Ausgabe +unter erneuter Autoritaets-/Profilpruefung und der echte instanzgebundene +S3-State-/Lock-Zugang muessen vor Dispatch weiter integriert werden. + + + +## Explizite Application-Backend-Freigabe (2026-10-05) + +Migration 027 ergaenzt einen unveraenderlichen Backend-Beleg fuer einen gueltigen +vorbereiteten Application-Job. `POST /api/v1/applications/jobs/{id}/backend-approval` +verlangt genau `{"stateBackendId":"","confirmBackendApproval":true}` mit +Session-/Origin-/CSRF-/Tenant-Pruefung. Nur der aktuelle PE, der den Plattform- +Vertrag freigegeben hat, darf bestaetigen. SQL prueft erneut Job- und Grant-Ablauf, +Widerruf, Besteller-Session, Mitgliedschaften, Organisation und beide aktuellen +menschlichen Identitaeten. Der Backend-Datensatz muss zum selben Tenant gehoeren. + +Der S3-Descriptor wird aus dem registrierten Backend abgeleitet, sein Key ist +zwingend `applications///terraform.tfstate`, Lockfile bleibt +verpflichtend. Freigabe-Session und Backend-Bindung sind immutable. Die Laufzeit +ist das Minimum aus Grant, echter PE-Session und PE-Identitaet. Parallele gleiche +Freigaben sind idempotent; Backend-Wechsel liefert 409. Abgelaufene oder nicht +mehr aktive Freigabesessions werden auch mit einer neuen Session nicht erneuert. + +Die Antwort enthaelt nur Job-/Backend-ID, State-Key, Ablauf und +`executionEnabled:false`. AO kann den nicht geheimen Beleg lesen, aber weiterhin +keine Backend-Credentials. Die SQL-Funktion liest weder Credentials noch echten +S3-State. Die API validiert den gespeicherten Descriptor mit dem vorhandenen +S3-Vertrag. Ein Freigabebeleg ersetzt keine einmalige Credential-Ausgabe, echte +S3-Zugriffs-/Lock-Pruefung, Runner-Ticket oder Cloud-Plan/Apply. + + + +## Interner einmaliger Application-Claim (2026-10-05) + +Migration 028 stellt die atomare Verbrauchsstufe bereit. Die interne +`claimJobGrant`-Methode benoetigt die tatsaechliche weiterhin gueltige +PE-Backend-Freigabesession, nicht eine rekonstruierte PE-Identitaet aus dem +AO-Aufruf. SQL prueft alle Backend-/Grant-Autoritaetsgrenzen erneut und sperrt +die Grant-Zeile, bevor der immutable Claim-Beleg erzeugt wird. Zwei konkurrierende +Claims ergeben einen Erfolg und einen Konflikt. Eine andere echte Session +desselben PE darf den Claim nicht uebernehmen. + +Claim und Widerruf serialisieren dieselbe Zeile; nur eines kann erfolgreich sein. +Nach Verbrauch wird kein Widerruf mit behaupteter Credential-Rueckholung bestaetigt, +sondern 409 zurueckgegeben. Retry der urspruenglichen Job-Vorbereitung liefert +keinen falschen `prepared`-Beleg. Die App-Rolle darf Claims weder direkt schreiben +noch zuruecksetzen oder loeschen. + +Kein Browser-/Runner-Endpunkt fuer diese Methode ist registriert. Sie gibt nur +Job-ID, Claimzeit und Ablauf zurueck; keine Credentials, Ticket oder Runner-Start. +Die anschliessende technische Profil-/Version-/Key-Pruefung, sichere Secret- +Ausgabe, abschliessende Autoritaetspruefung und ticketgebundene Dispatch-Integration +sind weiterhin erforderlich. Der interne Claim allein aktiviert keine Ausfuehrung. diff --git a/landing-zone-configurator/docs/plan-execution.md b/landing-zone-configurator/docs/plan-execution.md index 68988e0..a69d22c 100644 --- a/landing-zone-configurator/docs/plan-execution.md +++ b/landing-zone-configurator/docs/plan-execution.md @@ -1,61 +1,37 @@ -# Erstbereitstellungspläne - -Stand: 2026-10-02. Umsetzung auf `feature/landing-zone-configurator`. - -## Was der Benutzer testen kann (nach erfolgreichem Release) - -1. **Deployments** öffnen und im Abschnitt **Erstbereitstellung planen** eine - gespeicherte Vorbereitung auswählen. -2. Nur für eine neue Landing Zone bestätigen, dass noch keine Ressourcen und kein - bestehender State zu dieser Konfiguration existieren. Bestehende/teilweise - erzeugte Landing Zones sind in diesem Ablauf nicht unterstützt. -3. **Erstbereitstellung planen** starten. Erwartete Stationen: Runner vorbereiten, - initialisieren, validieren, planen und abgeschlossen/fehlgeschlagen. -4. Seite neu laden: Auftrag und Ergebnis bleiben erhalten. Anlegen, Ändern, - Ersetzen, Löschen, Datenlesen und geänderte Ausgaben werden getrennt gezählt. -5. Optional einen weiteren Plan abbrechen. Abbruch entzieht sofort den Broker- - Zugriff; das Stoppen des CF-Tasks durch Cleanup erfolgt zeitversetzt. - -**Keine Kunden-Ausführung in dieser Abnahme.** Der Benutzer verlangt ausdrücklich -eine neue Freigabe vor jedem Kunden-Apply; Infrastrukturfreigaben gelten nicht dafür. -Der ältere Erstbereitstellungsplan bleibt plan-only. Der neue Plattformpfad besitzt -einen gated Apply-Endpunkt: nur bei aktivierter Execution, passendem unveränderlichem -Planartefakt/Hash, bestätigter Zielorganisation und erneut geprüften Zugriffs-, -Quell- und State-Bindungen. Ein Export ist keine Apply-Freigabe. Kein Destroy-Pfad. - -Ein erfolgreicher Plan ist nicht automatisch fuer Apply freigegeben. Der Server -liefert zu einer gesperrten Freigabe einen Fehlercode und bei nicht unterstuetzten -Komponenten die betroffenen Felder mit Begruendung. Plan- und Apply-Seite zeigen -diese Sperre an; der Apply-Button bleibt sichtbar, aber deaktiviert. Ein -freigabefaehiger Plan zeigt weiterhin die explizite Pruefbestaetigung und verlangt -die exakte UUID der Zielorganisation. Alle Bedingungen werden vor Apply erneut -serverseitig geprueft. - -Firewall-/HA-Infrastruktur bleibt derzeit nur fuer Plan qualifiziert. Ein neuer -Plan allein hebt diese Komponentensperre nicht auf. Der Administrations- und -Bootstrap-Vertrag muss separat fuer Apply qualifiziert werden; Firewall-Policy -und VPN-PSKs werden dabei nicht stillschweigend ausgelassen. Konfiguration und -Plan-Nachweise bleiben unveraendert erhalten. Die komponentenweise -Ausfuehrungsqualifikation wird in -[#89](https://github.com/stackitcloud/stackit-landing-zone/issues/89) weitergefuehrt. - -## Plattformentwürfe mit Projekt-Templates - -Neue Editor-Konfigurationen enthalten Projekt-Template-Entwürfe statt konkreter -Anwendungsprojekte. Ihr tfvars-Export und damit ihr Erstbereitstellungsplan enthalten -**nur die Plattform**, keine Instanzen dieser Vorlagen. Alte Gesamtkonfigurationen -behalten ihre bisherigen Projekte. [Details und Bestandsschutz](project-template-drafts.md). - -## Application-Plan-Input und Plattformvertrag - -Der lokal aktivierte Application-Katalog hat einen eigenen Freigabe- und Bestellpfad. -Er startet **noch keinen CF-Task** und legt keinen State an. `Plan-Input prüfen` -ist eine erneute serverseitige Qualifikation und zeigt Terraform-Variablen, -Entrypoint und Ausführungssperre, kein berechnetes Ressourcenergebnis. - -Ein Platform Engineer kann im Application-Katalog einen JSON-Vertrag aus bereits -angewendeten, geprüften Plattform-Outputs laden. Das Dokument ist kein Terraform-State -und enthält keine Credentials. Minimaler Importvertrag: +# Initial provisioning plans + +[English](plan-execution.md) | [Deutsch](plan-execution.de.md) + + + +As of: 2026-10-02. Implementation on `feature/landing-zone-configurator`. + + +## What the user can test (after a successful release) + +1. Open **Deployments** and select a saved preparation in **Plan initial provisioning**. +2. Only for a new Landing Zone, confirm that no resources or existing state for this configuration exist yet. Existing/partially created Landing Zones are not supported in this workflow. +3. Start **Plan initial provisioning**. Expected stages: prepare Runner, initialize, validate, plan and completed/failed. +4. Reload the page: job and result are retained. Creation, modification, replacement, deletion, data reads and changed outputs are counted separately. +5. Optionally cancel another Plan. Cancellation immediately revokes broker access; cleanup stops the CF task after a delay. + +**No customer execution in this acceptance.** The user explicitly requires fresh approval before every customer Apply; infrastructure approvals do not cover this. The older initial-provisioning plan remains Plan-only. The new platform path has a gated Apply endpoint: only with execution enabled, matching immutable plan artifact/hash, confirmed target organization and rechecked access, source and state bindings. Export is not Apply approval. No Destroy path. + +A successful Plan is not automatically eligible for Apply. For blocked approval, the server returns an error code and, for unsupported components, the affected fields with reasons. Plan and Apply pages show this block; the Apply button remains visible but disabled. An eligible Plan still shows explicit review confirmation and requires the exact UUID of the target organization. All conditions are checked again server-side before Apply. + +Firewall/HA infrastructure is currently qualified only for Plan. A new Plan alone does not lift this component block. The administration and bootstrap contract must be qualified separately for Apply; firewall policy and VPN PSKs are not silently omitted. Configuration and Plan evidence remain unchanged. Component-specific execution qualification continues in [#89](https://github.com/stackitcloud/stackit-landing-zone/issues/89). + + +## Platform drafts with project templates + +New editor configurations contain project template drafts instead of concrete application projects. Their tfvars export, and thus their initial-provisioning plan, contain **only the platform**, no instances of these templates. Old combined configurations retain their previous projects. [Details and legacy protection](project-template-drafts.md). + + +## Application Plan input and platform contract + +The locally enabled Application catalogue has its own approval and ordering path. It **does not yet start a CF task** or create state. `Check Plan input` is renewed server-side qualification and shows Terraform variables, entry point and execution block, not a calculated resource result. + +A Platform Engineer can load a JSON contract from already applied, checked platform outputs in the Application catalogue. The document is not Terraform state and contains no credentials. Minimal import contract: ```json { @@ -74,606 +50,206 @@ und enthält keine Credentials. Minimaler Importvertrag: } ``` -Die UUIDs sind Platzhalter und müssen aus der tatsächlich angewendeten Plattform -kommen. Die Freigabe ist eine bewusste PE-Prüfung der Outputs, **keine automatische -Bestätigung, dass ein angegebener Ordner existiert oder zur Organisation gehört**. -Diese Ressourcenprüfung bleibt vor einer zukünftigen Job-/Credential-Freigabe nötig. - -- GET/POST `/api/v1/applications/platform-contracts`: aktuelle Tenant-Mitgliedschaft; - POST zusätzlich PE-Rolle, gültige menschliche STACKIT-Identität, Origin/CSRF, - `confirmApproval: true` und gespeicherten SA-Zugang. Optional `credentialProfileId`; - bei genau einem gespeicherten Profil automatische Auswahl. Organisationszugriff - wird technisch geprüft, ohne eine zweite menschliche OAuth-Anmeldung zu verlangen. -- Tenant und Revision werden serverseitig bestimmt. Migration 014 persistiert - unveränderliche Vertragsversionen mit Forced RLS und technischem Prüf-/Versionsnachweis. - Ein Zugangstest oder Vertrag ist keine Apply-Freigabe. -- POST `/api/v1/applications/templates` kann `platformRevision` und `targetKey` - gemeinsam binden. Region und Projektart müssen zum Vertragsziel passen; - tenantfremde Vertrags-IDs werden nicht sichtbar. Änderung erzeugt eine neue Version. -- POST `/api/v1/applications/instances/:id/plan-input` akzeptiert nur `{}`. - Der Besitzer wird aus Session und Bestellung ermittelt; fremde Bestellungen und - Client-Identitäts-/Backend-Overrides werden abgewiesen. Identitätsablauf, Widerruf, - Rollenentzug und geänderte Besteller-E-Mail werden erneut geprüft. -- Der Compiler verwendet exakt die Vertrags- und Template-Version der Bestellung, - feste Parameterregeln und den eigenen Instanz-State-Key. Die MVP-Teilmenge ist - Public mit lokalem Netz, ohne Observability-Ausführung oder Namespace-Dienste. - Die Antwort meldet ausdrücklich `cloudPlanExecuted: false` und - `executionEnabled: false`; keine Schlüssel werden an den Browser geliefert. - Die unveraenderliche Versions-/Bestellpolicy wird als `applyPolicy` uebernommen - (`approval-required` oder `direct`); `requiresExplicitApplyApproval: true` - bleibt fuer beide gesetzt. Eine direkte Policy ist keine Ausfuehrungsfreigabe. - -Für den tatsächlichen eigenen Cloud-Plan fehlen noch ein unveränderlich freigegebenes -Application-Runner-Artefakt, getrenntes State-Backend mit Locking und eng begrenzte -serverseitige Nutzung des PE-Zugangs durch genau den autorisierten Job. Der bisherige -Runner-Pin enthält kein Application-Root. Er wird nicht auf ungeprüften Arbeitsbaumcode -umgestellt. Application-Apply bleibt deaktiviert; der freigabegebundene -Plattform-Apply-Pfad ist davon getrennt. - -## Gemeinsamer Editor und Ausführungsumfang - -Schema v3 wird für eine konservative Standalone-Teilmenge unterstützt: eu01, -Organisations-Owner/Auditor, Ordner samt Namen und Owner-/Leseberechtigungen, -optional ein übergeordneter Ordner (UUID), explizit Public-Projekte in bestehenden -Gesamtkonfigurationen, Sandbox-Projekte, Grundeinstellungen und die bisherige -Secrets-Manager-Option. Leere oder nicht gesetzte Ordnerbeschreibungen sind zulässig; -gefüllte Beschreibungen werden bis zur Behebung von #82 gezielt abgewiesen, weil der -Accelerator sie nicht übernimmt. Netzwerk, Kubernetes, Firewall und zusätzliche Plattform- -oder Projektdienste bleiben für diesen Runner gesperrt. Die Prüfung erfolgt anhand -der effektiven Konfiguration, nicht anhand des Template-Namens. UI, Vorbereitung -und Broker verwenden `initialPlanIssues`; vor Übergabe der Zugangsdaten an den -Runner wird erneut geprüft. JSON und tfvars bleiben an dieselbe Git-Revision und -den unveränderten Export-Hash gebunden. Legacy-Dokumente bleiben unterstützt. - -Die Organisationstenant-Sperren gelten weiter. Der ältere Erstbereitstellungsplan -verwendet leeren State. Im neuen Plattformpfad wird bestehender State ausschließlich -über die geprüfte Backend-Bindung verwendet; fehlende oder widersprüchliche Bindungen -dürfen keinen stillen Neustart mit leerem State auslösen. -Erweiterte Ausführung: [#89](https://github.com/stackitcloud/stackit-landing-zone/issues/89). - -## Ablauf und Grenzen - -**Private Kubernetes-APIs:** Der aktuelle CF-Runner hat keinen nachgewiesenen -Zugriff auf Kunden-SNAs. Ein erfolgreicher STACKIT-Zugangstest belegt diesen -Netzwerkpfad nicht. Auch Plan/Refresh mit Kubernetes-/Helm-Providern kann ihn -benötigen. Die zweistufige Ausführung aus -[#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37) ist noch offen -und wird separat umgesetzt. Anforderungen an Ausführungssperren bei Erweiterung -des bisherigen Standalone-Vertrags stehen im -[Grenzenregister](accelerator-limitations.md#private-kubernetes-api-ausführungsgrenze). - - -- POST `/api/v1/plans` verlangt Session, exakten Origin, CSRF-Token und - `confirmNewDeployment: true`. Nur eine eigene Vorbereitung mit eigenem - gespeichertem Credential und Rolle admin/deployer wird akzeptiert. -- GitHub-Fork-Zugriff, festgehaltener Head und generierter tfvars-Export werden - mit dem GitHub-Benutzertoken erneut geprüft. Geänderter Fork-Head erfordert eine - neue Vorbereitung; es wird keine andere Version still übernommen. -- SQL 004/005 persistiert Aufträge mit Forced RLS, Vorbereitung, Status, Engine- - und Provider-Lock-Version sowie CF-Droplet-Referenz. Ein aktiver Auftrag pro - Benutzer/Mandant, höchstens 20 Starts in 24 Stunden; Liste zeigt letzte 100. -- Der Dispatcher verwaltet ausschließlich die separate Organisation - `lzc-dev-runners`, Space `plans`, SSH deaktiviert. Für jeden Auftrag erstellt er - eine App ohne Route/Service-Bindings und kopiert das geprüfte Runner-Droplet. - CF-Manager-Credentials verbleiben im vertrauenswürdigen API-Backend/Release. -- Der Runner erhält drei App-Variablen: Auftrags-ID, feste Broker-URL, zufälliges - 256-Bit-Ticket. In PostgreSQL liegt nur dessen Hash. Gültigkeit maximal 25 Minuten. - Eine eng begrenzte SECURITY-DEFINER-Funktion löst das Ticket auf genau einen - aktiven Auftrag auf; danach gelten Eigentümer-/Tenant-RLS und Rollenprüfung. -- Eingaben werden einmal ausgegeben, nach erneuter Rollen-, Profil-, Versions- - und Organisationsprüfung. Andere Profile oder Mandanten sind nicht auswählbar. - Die Terraform-Unterprozesse erhalten eine explizite Umgebung ohne Broker-Ticket. -- Fester Accelerator-Commit `a256f6896d11134fdc351786f1be5eba4e56b2e2`, OpenTofu - 1.12.6, Provider-Lock SHA-256 - `a52433c424472d6e618caa3a94579bbcd19b60b759d053cf0d5caf9ac6872888`. - CI baut nur Upstream-Code dieses Commits und einen Linux-Provider-Mirror. -- OpenTofu 1.12.6 exportiert im Saved-Plan-JSON 1.2 kein Terraform-Feld `complete`. - Der Worker darf Vollständigkeit für dieses genaue Format nur nach Prüfung der - gepinnten Engine und seinem festen vollständigen Plan-Befehl ohne Targeting - bestätigen. Der Summary-Parser verlangt diesen expliziten Engine-Kontext; - fehlender Kontext, unbekannte Versionen/Formate oder Deferred-Metadaten bleiben - `not-reported`, ein gemeldeter Teilplan bleibt `incomplete`. Fehlerstatus, - offene/fehlgeschlagene Checks und alle Artefakt-/State-/Freigabebindungen - sperren Apply weiterhin. Vorher gespeicherte Summaries werden nicht umgeschrieben. -- Direkte Befehle in `deploy/runner/run-plan.sh`: init mit readonly Lock, validate, - plan mit detailed exit code und show. Kein frei wählbarer Befehl. Der neue - Plattformpfad darf Apply nur mit dem freigegebenen gespeicherten Plan ausführen. -- Ergebnisprojektion enthält nur Zahlen, Status und feste Fehlercodes; keine - Adressen, Attributwerte, Output-Namen, Rohdiagnosen oder Geheimnisse. Auch nicht - als sensitive markierte Werte werden nicht in diese Summary exportiert. - Separat zeigt der Runner dem berechtigten Plan-Eigentümer unter - **OpenTofu-Ausgabe** die normale CLI-Textdarstellung: Live-Logs aus dem privaten - aktiven Job oder `tofu show -no-color` des exakt hash-/paketgebundenen, - verschlüsselt gespeicherten Planartefakts. Sitzung, Deployment-Rolle und - Eigentümer-/Tenant-RLS werden vor jedem Zugriff geprüft; Antworten sind - `no-store`. Ressourcenadressen und normale Attributwerte sind dort sichtbar, - sensitive Werte bleiben durch OpenTofu maskiert. Bekannte Credential-Felder - werden aus Live-Logs zusätzlich entfernt. Plan-Binary und `show -json` bleiben - serverseitig. Es laufen kein neuer Cloud-Plan, kein Apply und kein Backend-Init; - die Inspektion verwendet nur backendfreies Init und Show ohne geerbte Secrets. - Die Apply-Ablauffrist bleibt unabhängig von der read-only Anzeige, solange das - verschlüsselte Artefakt vorhanden ist. -- Aktive Plattformaufträge öffnen einen NDJSON-Live-Kanal auf - `GET /api/v1/plans/:id/output` mit `Accept: application/x-ndjson`. - JSON-Snapshots bleiben für Historie und bestehende Clients erhalten. Der Worker - liest vollständige Log-Zeilen alle 500 ms und überträgt nur geänderte, - redigierte Mitschnitte. Nach dem verschlüsselten Commit benachrichtigt die API - ihre lokalen Abonnenten; andere API-Instanzen prüfen spätestens nach einer - Sekunde erneut. Unveränderte Ausgabe erzeugt nur ein Heartbeat, keinen neuen - Mitschnitt. Sitzung, Workspace, Deployment-Rolle und Eigentümerschaft werden - während der Verbindung erneut geprüft, nicht nur beim Öffnen. - Verbindungen enden nach spätestens 35 Sekunden und werden bei weiterhin - aktivem Auftrag erneut geöffnet. Collapse, Navigation und Abmeldung brechen - sie ab. Pro Eigentümer/Tenant sind je API-Instanz höchstens acht Verbindungen - erlaubt; langsame Leser erzeugen Backpressure statt unbegrenzter Warteschlangen. -- Der Plan verwendet OpenTofus native `-json`-UI-Ereignisse für tatsächliche - Fortschrittsmeldungen, auch bevor der fertige Diff existiert. Nur menschliche - Meldungen des unterstützten UI-Protokolls werden projiziert; rohe Ereignisse, - Metadaten und Output-Werte werden nicht an den Browser gesendet. - Unvollständige Zeilen bleiben zurückgehalten, ungültige Ereignisse erhalten - einen sichtbaren festen Fehlerhinweis. Anschließend ergänzt - `tofu show -no-color plan.bin` den vollständigen normalen Plantext. - Init, Validate, Apply und Migration behalten ihre native CLI-Ausgabe. - Es gibt keine geschätzten Prozentwerte: wenn OpenTofu während einer Operation - keine Meldung erzeugt, bleiben Phase und Laufzeit sichtbar. -- Während des Laufs und vor dem terminalen Ergebnis sichert der Worker den redigierten CLI-Mitschnitt - von Init/Validate/Plan/Apply/Migration über `POST /api/runner/output`. Das - auftragsspezifische Ticket muss gültig und die Eingabe bereits beansprucht sein; - der Text darf bis zum Abschluss aktualisiert werden, danach ist er eingefroren. Migration 020 legt - dafür private Output-Spalten unter der bestehenden Eigentümer-/Tenant-RLS an. - Der Broker verschlüsselt maximal 2 MiB mit AEAD und auftragsspezifischer AAD. - Erfolgs- und Fehlerausgaben bleiben nach Cleanup und Reload lesbar, ohne laufenden - Runner. Kürzungen sind gekennzeichnet. Ein harter Prozessabbruch oder gescheiterter - Upload kann weiterhin historische Ausgabe verlieren; die best-effort Sicherung - löst weder einen Apply-Retry aus noch ersetzt sie den dauerhaften State-Recovery- - Empfangsnachweis. Apply-Nachweise zeigen den exakten Plan, SHA-256, - Zielorganisation, das State-Backend des Auftrags und die Abschlusszeit. - Ein inkompatibles natives Runner-Paket sperrt Apply bereits vor Dispatch; - ein neuer Plan mit erneuter Prüfung und Freigabe ist erforderlich. -- Task: 1 GiB RAM, 4 GiB Disk, 18 Minuten Engine-Frist, private Dateien begrenzt. - SQL-Frist: 25 Minuten. Maintenance alle 30 Sekunden, Cleanup nach mindestens - 30 Sekunden terminalem Status. Auch nach API-Neustart werden Aufträge abgeräumt. - Bei CF-/Netzfehlern kann Cleanup länger dauern; Ticket-Ablauf bleibt unabhängig. -- Kein automatischer Dispatch-Wiederholungsversuch. Ein Prozessverlust vor Start - führt zu Abbruch/Ablauf statt stiller Neuausführung. Es gibt noch keinen allgemeinen - Queue-Scheduler und keine dauerhafte Runner-Heartbeat-Überwachung. Der neue - Plattformpfad speichert Planartefakte verschlüsselt und bindet sie an Quelle, - Engine und State-Version. CF-Quoten begrenzen die Gesamtkapazität zusätzlich. -- Vorbereitungen mit Plan-Nachweisen werden nicht gelöscht. Archivierung und - Aufbewahrungsfristen der Metadaten sind ein nachfolgender Schritt. - -## State-Lebenszyklus gemäß LZA - -Entscheidung des Benutzers: bestehenden -[LZA-Bootstrap](https://github.com/stackitcloud/stackit-landing-zone/blob/main/docs/getting-started.md) -übernehmen. Der gespeicherte Zugang ist der Bootstrap-Service-Account; Projekt und -Account werden nicht erneut angelegt. Ein Plan legt weder Management-Projekt noch -Bucket an. Im neuen Plattformpfad dient das dauerhafte, verschlüsselte HTTP-Backend -nur dem Bootstrap, nicht als permanenter Ersatz für den Kunden-S3-State. - -Beim separat freigegebenen ersten Apply erzeugt das Management-Modul den -Kunden-State-Bucket samt Credentials. Danach migriert der Runner mit -`tofu init -migrate-state`; die API bestätigt die Migration erst nach Abgleich von -State-Hash und Remote-Version/ETag sowie gebundener State-Version. Erst danach -wird der HTTP-Primärstate entfernt. Anschließend wird der verifizierte -Management-Service-Account verwendet. Das S3-Backend nutzt `use_lockfile = true`. -Application-Instanzen erhalten jeweils eigene Keys -`applications///terraform.tfstate`; Plattform-, -Application- und Configurator-Infrastruktur-States bleiben getrennt. - -Legacy-State-Zuordnungen sind mit `legacy_state_migration_required` gesperrt und -benötigen eine explizite Zuordnung/Migration, keinen neuen leeren State. Bei -`state_failed` oder unbestätigter Migration ist vor Wiederaufnahme ein expliziter -State-Abgleich erforderlich; eine abgeschlossene S3-Kopie kann wie unten -beschrieben ohne erneuten Apply bestätigt werden. Andere Recovery-Fälle -benötigen weiterhin einen geschützten Export. Der Runner übermittelt einen geprüften, -verschlüsselten Recovery-Nachweis und entfernt lokale Fehlerstates erst nach -passender dauerhafter Empfangsbestätigung. Das garantiert keine automatische -vollständige Wiederherstellung nach jedem harten Runner-Verlust; Abgleich und -operative Recovery bleiben erforderlich. Ein echter Cloud-S3-Lock-Test wurde -nicht durchgeführt. Kein Kunden-Apply wurde in dieser Umsetzung ausgeführt. - -## Konfiguration nach fehlgeschlagenem Bootstrap-Apply korrigieren - -Migration `034_platform_reconciliation.sql` ergaenzt einen ausdruecklichen, -auditierten UI-Abgleich. In der Apply-Ansicht liest erst **Checkpoint pruefen** -den verschluesselten Bootstrap-Checkpoint des eigenen fehlgeschlagenen Applys. -Die Antwort enthaelt nur State-Version, SHA256, Serial, Lock-/Migrationsstatus -und Ressourcenanzahlen nach Typ; keine Attribute, Outputs oder Rohstates. - -**Erneute Planung freigeben** erfordert eine gesonderte Bestaetigung zum -unveraenderten Erhalten des States. Die API prueft die angezeigte Version und -Pruefsumme erneut in einer Transaktion. Nur ein regulaer mit `apply_failed` -beendeter, bereits gestarteter Apply mit lesbarem Bootstrap-Checkpoint, -positiver State-Version, ohne gehaltenen Lock, offene Migration oder separaten -Recovery-State ist freigebbar. Ein unveraenderlicher, tenant-/ownergebundener -Auditbeleg bindet Apply, echte Sitzung, State-Key, Version und Pruefsumme. -Gleichzeitige identische Bestaetigungen erzeugen nur einen Beleg. Der Run wird -als fehlgeschlagen abgeschlossen; State, Version, Lock und Backend bleiben -unveraendert. Es erfolgen weder Cloud-Zugriffe noch ein automatischer Plan/Apply. - -Danach kann der Benutzer die korrigierte Konfiguration speichern, eine neue -Vorbereitung waehlen und einen neuen Plan gegen denselben bestehenden State -starten. Fuer Apply ist erneut die separate Pruefung und Freigabe des neuen -gespeicherten Plans erforderlich. Der alte Plan bleibt verbraucht. Bei einem -zwischenzeitlich veraenderten Checkpoint ist eine neue Pruefung erforderlich. -Unklare Runner-Abbrueche, nicht verifizierbare Migrationen und separate Recovery- -States bleiben gesperrt und benoetigen einen gesonderten operativen Abgleich. -Es gibt keine automatische Entsperrung, State-Loeschung, Import- oder -Destroy-Aktion. Die Migration muss vor Nutzung der neuen API aktiviert sein. - -### Erfolgreichen Apply mit offener S3-Bestaetigung abschliessen - -OpenTofu 1.12.6 verwendet bei der HTTP-zu-S3-Migration eine neue Lineage und -Serial 1. Das ist mit dem echten, gepinnten Runner-Binary und ausschliesslich -synthetischen lokalen HTTP-/S3-Endpunkten reproduziert, auch nach mehreren -Ausgangs-State-Schreibvorgaengen. Die fruehere Forderung nach identischem -Gesamt-Hash, Lineage und Serial lehnte diese erfolgreiche Kopie ab. -`migrationStateMatches` akzeptiert neben einer exakten Vollkopie nur diese -nachgewiesene Transformation: Quellversion 1.12.6, neue Lineage, Ziel-Serial 1 -und ansonsten exakt gleicher kanonischer State-Inhalt. Ressourcen, Attribute, -Outputs, Format, Version und alle weiteren Felder bleiben vollstaendig geprueft. -Nur die Reihenfolge der obersten `check_results`-Liste wird beim gepinnten -nativen Migrationsvergleich normalisiert. Alle vollstaendigen Pruefeintraege -einschliesslich ihrer verschachtelten Inhalte und mehrfacher Eintraege bleiben -erhalten; es wird nichts entfernt oder auf erfolgreiche Statuswerte reduziert. -Diese Reihenfolgeaenderung ist mit echten OpenTofu-Validierungen reproduziert. -Globale State-Hashes, Quell-Sicherungsbelege und andere Array-Reihenfolgen -bleiben unveraendert. Geaenderte Pruefergebnisse oder Ressourcen bleiben gesperrt. -Unbekannte Versionen oder beliebige Serial-/Inhaltsaenderungen werden nicht -freigegeben. Das Host-Binary darf nicht als Runner-Version angenommen werden; -der Native-Test verwendet `LZC_NATIVE_TOFU_BINARY` und prueft die echte Version. - -Bei einem regulaer beendeten `state_failed` mit gebundener offener Migration -liest **Checkpoint pruefen** auf ausdruecklichen Klick den verschluesselten -Bootstrap-State und den bereits registrierten S3-State. Es werden nur aggregierte -Metadaten angezeigt, einschliesslich S3-Pruefstand, Serial und dem Bool-Wert, -ob die Lineage erhalten blieb. Ohne Lock, separate Recovery oder abweichenden -Inhalt kann der Benutzer die eigene **Backend-Migration bestaetigen**. - -Diese Bestaetigung bindet Quellversion, Quell-SHA und den exakten Remote- -Objektstand. Vor Abschluss werden alle Belege erneut geprueft. In derselben -Transaktion erfolgen der bereits vorhandene CAS-Backend-Wechsel, der -unveraenderliche Auditbeleg und der Abschluss des Applys als `succeeded`. -Erst nach erfolgreichem S3-Abgleich wird der temporaere Bootstrap-Primaerstate -entfernt. Identische parallele Bestaetigungen sind idempotent. Kein Runner, -Apply, S3-Schreibzugriff, Import, Unlock oder Destroy wird dabei gestartet. -Bei einem geaenderten Pruefstand bleiben Bootstrap-Sicherung und Recovery- -Sperre erhalten. Eine neue Schema-Migration ist hierfuer nicht erforderlich. - -### Lokale Aktivierung am 2026-10-06 - -Nach ausdruecklicher Freigabe wurden die laufende Kunden-DB privat gesichert, -der vollstaendige Dump in einer getrennten loopbackgebundenen PostgreSQL-17- -Instanz restauriert und dort mit dem echten Migrator auf Migration 034 gebracht. -Zeilenzahlen und Hashes aller 32 bestehenden Tabellen in `lzc` und `lzc_auth` -blieben unveraendert. Erst danach wurde die API ohne laufende Kundenjobs neu -gestartet. Derselbe Vergleich bestand auch nach der Live-Migration. - -Die Live-DB enthaelt nun Migrationen 001 bis 034; die neue Audit-Tabelle ist leer -und hat erzwungene RLS. Der fehlgeschlagene Apply bleibt `recovery_required`. -Das bisherige unveraenderliche Platform-Runner-Paket bleibt aktiv; -Application-Ausfuehrung bleibt ausdruecklich deaktiviert. API und UI-Proxy -antworten auf Health-Pruefungen mit 200, die neuen Checkpoint-/Freigaberouten -ohne Anmeldung mit 401 und der deaktivierte Application-Runner mit 404. -Die UI liefert den qualifizierten aktuellen Build. Die temporaere Restore- -Instanz samt eigenem Volume wurde entfernt; privater Dump und Hash-Nachweise -bleiben fuer Wiederherstellung erhalten. - -Diese Aktivierung pruefte ausschliesslich Sicherung, Schema, Datenbewahrung -und Zugriffssperren. Der Kunden-Checkpoint wurde weder entschluesselt noch -freigegeben. Die echte Checkpoint-Pruefung und Bestaetigung erfolgen durch den -Benutzer in seiner angemeldeten UI. Es wurde kein Cloud-Plan/Apply gestartet. - -### Aktivierung des S3-Abschluss-Fixes am 2026-10-06 - -Nach dem vom Benutzer gemeldeten erfolgreichen Apply und `init -migrate-state` -wurde der aktuelle DB-Stand erneut privat gesichert. Vor dem reinen Code- -Neustart liefen keine Platform- oder Application-Jobs. Zeilenzahlen und Hashes -aller 33 bestehenden Tabellen, nun einschliesslich Recovery-Belegen, blieben -nach dem Neustart unveraendert. Migrationen 001 bis 034, das gebundene native -Platform-Paket und die deaktivierte Application-Ausfuehrung bleiben bestehen. -API und UI-Proxy `/healthz` antworten mit 200; Checkpoint-/Freigaberouten ohne -Anmeldung mit 401 und der deaktivierte Application-Runner mit 404. - -Der aktuelle Build besteht das kanonische Gate mit 376 Unit-Tests sowie alle -42 isolierten PostgreSQL-Brokerfaelle, 16 Backend-Tests einschliesslich echter -lokaler OpenTofu-1.12.6-Migration und 12 betroffene Desktop-/Mobil-Browserfaelle. -Die Browser- und Brokerfaelle verwenden kontrollierte Testdaten; sie belegen -nicht den erfolgreichen S3-Abgleich des Kundenlaufs. Dieser wurde bei der -Aktivierung weder gelesen noch bestaetigt und bleibt ein ausdruecklicher -UI-Schritt des Benutzers. Es wurde kein Kunden-Apply wiederholt. - -### Nachgewiesene Check-Reihenfolge und Korrektur am 2026-10-06 - -Nach ausdruecklicher Freigabe wurde genau der offene Migrationsfall lokal -entschluesselt und dessen gebundener S3-State ausschliesslich lesend verglichen. -Es wurden nur maskierte Strukturpfade und Gleichheits-/Anzahlmetadaten -ausgegeben, keine Werte, Schluessel oder Rohstates. Alle 36 vollstaendigen -Pruefeintraege waren gleich, aber anders angeordnet; Ressourcen, Attribute und -Outputs waren identisch. Der korrigierte Vergleich besteht auch fuer diesen -State. Der vorherige Vergleich wurde mit 24 echten lokalen OpenTofu- -Validierungen als fehlschlagender Native-Regressionsfall reproduziert. - -Nach frischem privaten Backup und null aktiven Jobs wurde nur die API mit -unveraendertem Platform-Paket neu gestartet. Alle 30 Nicht-Authentifizierungs- -Tabellen, insbesondere States, Backends, Plans, Artefakte und Recovery-Belege, -blieben unveraendert. Parallel wurden eine weitere Sitzung und Aenderungen an -Identitaets-/Zugangsmetadaten beobachtet; diese drei Tabellen sind deshalb -nicht als unveraendert ausgewiesen und wurden nicht zurueckgesetzt. -Keine Schema-Migration oder S3-Schreibaktion wurde durchgefuehrt; die eigentliche -Backend-Bestaetigung bleibt ein gesonderter Benutzer-UI-Schritt. -Das Gate besteht mit 387 Unit-Tests, 27 Backend-Tests einschliesslich nativer -Migration und allen 42 isolierten PostgreSQL-Brokerfaellen. - -## Portabler GitHub-Export - -Der Export schreibt atomar `landing-zone.json`, `landing-zone.tfvars` und eine -kurze CLI-Anleitung unter `src/config/custom//`. Bei einer -serverseitig verifizierten S3-Bindung kommt `backend.tf.json` hinzu: vollständige -Standard-Terraform-Backend-Konfiguration ohne AWS-/SA-Schlüssel oder State-Datei. -Nur `backend_not_found` erlaubt einen neuen Bootstrap-Export ohne Backend; -Service- und Berechtigungsfehler brechen das Speichern ab. Eine vorhandene -Backend-Datei muss exakt dem deterministischen Git-Blob-Hash des geprüften -Deskriptors entsprechen. Andernfalls gilt `backend_configuration_changed`; -fehlt die Bindung, gilt `backend_configuration_missing` statt Metadatenverlust. - -Beim ersten DB-zu-GitHub-Export bleibt die Konfigurations-ID erhalten. Eine -bereits geöffnete Git-Konfiguration behält ihre eigene ID. Bei abweichender -Quell-ID exportiert der Server den gebundenen Deskriptor ohne Alias- oder -State-Mutation; eine neue Vorbereitung muss den registrierten Backend-ID -ausdrücklich auswählen. Für unabhängigen CLI-Betrieb: geprüften Accelerator-Code -verwenden, ursprünglichen Backend-Block in `src/backend.tf` deaktivieren, -exportierte Backend-Datei nach `src/backend.tf.json` kopieren und genau einen -aktiven Backend-Block behalten. AWS-Zugang aus dem Management Secrets Manager -gemäß LZA in die Umgebung laden, dann `tofu init` und -`tofu plan -var-file=config/custom//landing-zone.tfvars`. -Ohne S3-Bindung zuerst LZA-Bootstrap und verifizierte State-Migration abschließen. - -## Abnahme - -- [x] API: Session/CSRF, striktes Eingabeschema, Erstbereitstellungsbestätigung, - persönliches GitHub-Token und kein Apply-Endpunkt getestet. -- [x] PostgreSQL: fremde Aufträge, konkurrierender Start, Ticket-Replay, Status- - Reihenfolge, Ablauf und gezieltes Cleanup getestet. -- [x] CF-Client: eigene App, feste Befehle, nur drei Job-Variablen und keine Route. -- [x] Desktop/Mobil: Plan-Start, laufender Status, Ergebnis nach Reload, kein Apply. -- [x] Lokaler echter OpenTofu-Vertragstest ohne Cloud-Zugang und ohne Apply. -- [x] Separate CF-Organisation samt Manager per Plattform-IaC erstellt. -- [x] Runner-Space/Rollen per Runtime-IaC erfolgreich angewendet. -- [x] Linux-Paket, Provider-Mirror und CF-Engine-Test erfolgreich. -- [x] Live-App: separaten Runner ohne Service-Bindings prüfen, ungültiges Ticket - darf keinen Kundenauftrag ausführen; Probe-App entfernen. -- [ ] Erster persönlicher Kunden-Plan durch den Benutzer. - -## Live-Abnahme vom 2026-09-30 - -[Release 36727211809](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36727211809) -für `b5686ef` erfolgreich: CF-Engine init/validate, Datenbankmigrationen, -PostgreSQL-/Secrets-Manager-Verbindungen, separate Probe-App und öffentliche -Route. Runner-Verwaltungsidentität hat keinen Zugriff auf die Configurator-App; -Probe-App ohne Routen oder Service-Bindings. Zufälliges, nicht registriertes Ticket -führte zu einem fehlgeschlagenen Task. Dies ist eine Infrastruktur-/Isolationsprobe, -noch kein erfolgreicher persönlicher Kunden-Plan. - -Gemessen vom Dispatch bis zur Task-Erstellung: **3.907 ms**; bis zum beobachteten -Task-Ende: **12.244 ms**. Ein Einzelwert, keine Latenzgarantie. Die Probe nutzt die -vorab gestagte Vorlage, keinen `cf push` pro Auftrag. Reguläre Jobausführung hat -zusätzlich Eingabe-/Zugriffsprüfung und OpenTofu-Laufzeit. Kein Kunden-Apply. - -## Quellen - -[OpenTofu JSON-Format](https://opentofu.org/docs/internals/json-format/), -[Plan-Exitcodes](https://opentofu.org/docs/cli/commands/plan/), -[CF V3 Droplet-Kopie](https://v3-apidocs.cloudfoundry.org/version/3.199.0/index.html#copy-a-droplet), -[CF V3 Tasks](https://v3-apidocs.cloudfoundry.org/version/3.199.0/index.html#create-a-task). - -## Release des v3-Standalone-Planpfads (2026-10-01) - -Commit `9aa3322`, [Release 36849188406](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36849188406) -und [Validierung 36849188417](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36849188417) -erfolgreich. Lokal 123 Unit-, 22 PostgreSQL- und 38 Browserprüfungen; echter -OpenTofu-Plan-Summary-Test und vier native Application-Root-Verträge mit 1.12.6. -Die Datenbankprüfung umfasst Legacy/v3 und die erneute Sperrprüfung im Broker. -Die Live-App liefert das neue Bundle, Health 200 und anonym geschützte APIs 401. -Dies ist keine persönliche Kunden-Plan-Abnahme und kein Kunden-Apply. - -## Governance-Qualifikation und Service-Account-Föderation (2026-10-01) - -Die Freigabe der Governance-Eingaben wird zusätzlich mit dem tatsächlich -verwendeten Governance-Modul geprüft: `npm run test:plan` ruft den separaten -`test-governance-contract.sh` auf. Quellhashes binden die Prüfung an den -Accelerator-Pin. OpenTofu 1.12.6 plant mit Mock-Providern in bereinigter Umgebung, -ohne Cloud-Credentials und ohne Apply. Geprüft werden Organisationsrollen -`owner`/`organization.auditor`, Ordnerrollen `owner`/`auditor`, das Auslassen -doppelter Ordnerzuweisungen für Organisations-Owner sowie beide Elternvarianten. -Diese lokale Qualifikation ersetzt keinen Plan gegen die konkrete Kundenorganisation. - -**Service-Account-Föderation für CI/CD** ist eine optionale Editor-Komponente. -Sie regelt, welche OIDC-Tokens externer Pipelines den Management-Service-Account -nutzen dürfen; sie ist keine Benutzeranmeldung am Configurator. -`issuer` ist der vertrauenswürdige Aussteller, `aud` die Token-Zielgruppe und -`sub` beispielsweise das konkrete GitHub-Repository mit Branch. Bedingungen -verwenden den vom gepinnten Provider unterstützten Vergleich `equals`; `aud` -ist erforderlich. Die GitHub-Vorlage begrenzt `sub` auf einen angegebenen Branch -und gilt nicht unverändert für Jobs mit GitHub Environments. - -Die Komponente richtet keinen Workflow oder Token-Austausch ein und entfernt -keine bestehenden Schlüssel. Für den aktuellen Configurator-Runner und einen -kleinen Erstbereitstellungsplan ist sie nicht erforderlich. Ihre Ausführung -bleibt bis zur gesonderten Runner-Qualifikation gesperrt; Speichern und Bearbeiten -der Konfiguration bleiben möglich. - -Quelle: [STACKIT Provider 0.114.0 – Service Account Federated Identity Provider](https://registry.terraform.io/providers/stackitcloud/stackit/0.114.0/docs/resources/service_account_federated_identity_provider). - -### Release-Nachweis - -- Quellstand `64e33cb`, [Release 36856248765](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36856248765) und [Validierung 36856248770](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36856248770) erfolgreich. -- Lokal: 140 Unit-Tests, Desktop-/Mobil-Browserprüfung einschließlich Überlaufprüfung, drei Governance-Mockpläne sowie die vorhandenen OpenTofu-Plan-/Application-Vertragstests erfolgreich. -- Live: SPA und Assets HTTP 200 (`index-CnPzJNzo.js`, `index-DoULK2fp.css`), `/healthz` HTTP 200, anonyme Session HTTP 401. Release-Verbindungstests erfolgreich. -- Kein Kunden-Apply, keine Abnahme eines echten Kunden-Plans und kein Merge nach main. - -## Begrenzte Plattform-Credential-Grants - -Lokal implementiert am 2026-10-05, noch nicht in der laufenden Kunden-API -aktiviert: Migration `025_plan_credential_grants.sql` legt bei ausdruecklichem -Plan-Start beziehungsweise bestehender ausdruecklicher Apply-Freigabe einen -Grant in derselben Transaktion an. Es gibt keine allgemeine Credential- -Delegation und keine automatische Nachruestung fuer alte wartende Jobs. - -Der unveraenderliche Beleg bindet Job, Tenant, Benutzer, Vorbereitung, -Organisation, Credential-Profil, Secret-Version, Key-ID, Manifest-Hash und -Operation (`plan` oder `apply`). Seine Gueltigkeit endet spaetestens mit -Job-Ticket oder ausstellender Sitzung. Er enthaelt keine Schluessel oder Tokens. -SQL prueft die Bindung an den echten Job und dessen Vorbereitungsdaten; -RLS begrenzt Zugriff auf den eigenen aktuell autorisierten Deployment-Benutzer. - -Der Runner beansprucht den Grant einmalig, bevor die technische Credential- -Pruefung oder der Secret-Abruf stattfinden. Fehlende, abgelaufene, widerrufene -oder abweichende Grants sperren diese Nutzung. Vor Rueckgabe von Schluessel, -Backend und gegebenenfalls gespeichertem Plan werden Grant, Ablauf und -initialisierender Job erneut geprueft. Ein fehlgeschlagener Claim wird nicht -zurueckgesetzt; ein neuer Auftrag verlangt eine neue ausdrueckliche Freigabe. -Parallele Input-Anfragen koennen nur einmal Credentials erhalten. - -`POST /api/v1/plans/{id}/credential-grant/revoke` verlangt Origin, CSRF, den -aktuellen `x-lzc-tenant` und ausschliesslich -`{"confirmCredentialGrantRevocation":true}`. Wiederholter Widerruf liefert -denselben Beleg. Normales Plan-Abbrechen widerruft einen noch ungenutzten -Grant ebenfalls. Bereits beanspruchte Grants liefern -`credential_grant_already_consumed`; bereits uebertragene Credentials koennen -nicht aus einem Runner zurueckgeholt werden. Laufender Worker, Cloud-IAM- -Schluesselrotation und Recovery muessen bei einem solchen Vorfall gesondert -behandelt werden. Ticketgebundene Ergebnis-/Recovery-Endpunkte bleiben -unveraendert und sind nicht erneut Credential-Ausgabe. - -Diese Grenze beschraenkt den Credential-Abruf, nicht die Cloud-IAM-Rechte des -Schluessels oder eine bereits laufende Operation. Least-Privilege-Qualifikation, -Application-Root-/Instanz-Dispatch mit eigenem State und Grant sowie echte -Zwei-Organisations-/Widerrufsabnahme bleiben #91/#93. AO erhalten durch diesen -Schritt keinen Zugriff auf Plattform-Credentials. 31 echte isolierte PostgreSQL- -Broker-/Grantfaelle und der kanonische Gesamtcheck bestehen. - -## Lokaler Application-Runner-Root (2026-10-05) - -Der Feature-Zwischenstand ist lokal als `4ad9367` gesichert. Der separate -Application-Quell-Pin ist `4d15d7870afa323badd93559d8b37c5a8d138dcf`; -Backend, Provider und Versionsanforderungen liegen in getrennten Dateien. -Der bisherige Plattform-Pin `a256f6896d11134fdc351786f1be5eba4e56b2e2` -und bereits gebundene Runner-Pakete bleiben unveraendert. - -Mit `LZC_LOCAL_RUNNER_PACKAGE=true` und `LZC_PACKAGE_APPLICATION_ROOT=true` -packt das Build-Skript zusaetzlich ausschliesslich `src/application` und -`src/modules/landing-zone` aus dem festen Git-Pin als `application-src`. -Ein neuer, noch nicht existierender `LZC_RUNNER_PACKAGE_DIR` ist zu verwenden. -Der eigene Provider-Lock pinnt STACKIT 0.114.0 und time 0.14.1, mit geprueften -Checksummen fuer Darwin ARM64 und Linux AMD64. Seine SHA-256 ist -`d40debbff204aee590c2a76d09f6ad3234643329b438fd5c6497de60687f6fa5`. -Die Application-Paketierung ist fuer den produktiven Build bewusst gesperrt. - -Die neuen Worker-Modi `application-plan` und `application-apply` verlangen -den festen Application-Pin/Lock und eine strikte Bindung aus `tenantId` und -`instanceId`. Der S3-Key muss exakt -`applications///terraform.tfstate` sein; Lockfile ist -verpflichtend. Bootstrap-/Plattform-State und freie Root-Pfade werden abgewiesen. -Das Arbeitsverzeichnis behaelt den relativen Modulpfad, liegt aber getrennt -vom Plattform-Root. Apply verwendet nur den gespeicherten Plan, ohne Replan -oder Bootstrap-Migration. Bei fehlgeschlagener Recovery-Uebertragung bleiben -nur der private Application-Recovery-State und seine Verzeichnisse erhalten. - -Dies ist noch kein Application-Broker-Dispatch oder Cloud-IAM-Scope: -`executionEnabled: false` bleibt bestehen. Instanz-Jobs, eigene echte Locks, -PE-autorisierte Credential-Grants, Ablauf/Widerruf, Quoten und explizite Upgrades -muessen noch angebunden werden. Der neue Quell-Pin braucht eine ausdrueckliche -neue Template-Veroeffentlichung; gespeicherte Versionen/Plans werden nicht -umgebunden. Kein aktives Paket wurde ausgetauscht und keine Kundenoperation -gestartet. Die Worker-Tests verwenden eine kontrollierte Engine, waehrend -Paket-Init/Validate und die nativen Mock-Vertragstests echtes OpenTofu verwenden. - -## Vorbereitete Application-Jobs und Grant-Belege (2026-10-05) - -Der Begriff Quell-Pin bezeichnet eine feste Git-Commit-ID des Accelerator- -Terraform-Codes, keine Zugangsdaten oder persoenliche PIN. Neue Publikationen -koennen `acceleratorRevision` ausdruecklich auf den qualifizierten Application- -Commit `4d15d7870afa323badd93559d8b37c5a8d138dcf` setzen. Dies erzeugt eine neue -immutable Template-Version; der bisherige Default und alle Altversionen bleiben -unveraendert. Andere Commits werden abgewiesen. Die API-Pin-Auswahl ist noch -nicht als zusaetzlicher UI-Publikationsschritt angebunden. - -Migration 026 speichert Jobs mit Status `prepared` und SQL-abgeleitete Grant- -Belege. `POST /api/v1/applications/instances/{id}/jobs` verlangt genau -`{"idempotencyKey":"","confirmPlan":true}`. Session, aktueller Tenant, -Origin und CSRF werden geprueft; Rolle, verifizierte Bestelleridentitaet, -Eigentum, Version/Policy und Compiler-Eingaben werden erneut aus den gespeicherten -Datensaetzen gelesen. Nur der qualifizierte Application-Quellstand wird angenommen. -Ein transaktionaler Lock serialisiert den Idempotenzschluessel. Wiederholung -liefert denselben gueltigen Auftrag; abgelaufener oder widerrufener Grant wird -nicht durch Retry erneuert. Ein frischer Auftrag braucht einen neuen Schluessel -und eine erneute ausdrueckliche Bestaetigung. - -Der SQL-Trigger prueft die echte Session, die verifizierte Organisation, -aktuelle PE-Mitgliedschaft des Vertragsfreigebers und aktuelle Bestelleridentitaet. -Er leitet Organisation, Profil-/Secret-Version/Key-ID, Besteller, Instanz, -Template-/Vertragsversion, Quellstand, Compiler-Hash, Operation und State-Key -ab. Der Ablauf ist durch echte Session, Human-Token und maximal 25 Minuten -begrenzt. Die App-Rolle darf keine Grants direkt einfuegen oder Bindungen -veraendern; Tenant-/Owner-RLS und unveraenderliche Belege bleiben erzwungen. - -`POST /api/v1/applications/jobs/{id}/credential-grant/revoke` verlangt genau -`{"confirmCredentialGrantRevocation":true}` mit denselben HTTP-Grenzen. -Besteller oder vertragsfreigebender aktueller PE duerfen innerhalb des Tenants -widerrufen. Wiederholung liefert denselben Zeitbeleg; Widerruf kann nicht -zurueckgesetzt werden. - -Die Job-Antwort enthaelt nur ID, Instanz, Status und Ablauf sowie -`executionEnabled:false` und `cloudPlanExecuted:false`. Keine Credentials, -kein Ticket und kein Runner-Start. Ein Grant-Beleg ist noch keine einmalige -Credential-Uebergabe, State-Datei oder Cloud-Operation. Die einmalige Ausgabe -unter erneuter Autoritaets-/Profilpruefung und der echte instanzgebundene -S3-State-/Lock-Zugang muessen vor Dispatch weiter integriert werden. - -## Explizite Application-Backend-Freigabe (2026-10-05) - -Migration 027 ergaenzt einen unveraenderlichen Backend-Beleg fuer einen gueltigen -vorbereiteten Application-Job. `POST /api/v1/applications/jobs/{id}/backend-approval` -verlangt genau `{"stateBackendId":"","confirmBackendApproval":true}` mit -Session-/Origin-/CSRF-/Tenant-Pruefung. Nur der aktuelle PE, der den Plattform- -Vertrag freigegeben hat, darf bestaetigen. SQL prueft erneut Job- und Grant-Ablauf, -Widerruf, Besteller-Session, Mitgliedschaften, Organisation und beide aktuellen -menschlichen Identitaeten. Der Backend-Datensatz muss zum selben Tenant gehoeren. - -Der S3-Descriptor wird aus dem registrierten Backend abgeleitet, sein Key ist -zwingend `applications///terraform.tfstate`, Lockfile bleibt -verpflichtend. Freigabe-Session und Backend-Bindung sind immutable. Die Laufzeit -ist das Minimum aus Grant, echter PE-Session und PE-Identitaet. Parallele gleiche -Freigaben sind idempotent; Backend-Wechsel liefert 409. Abgelaufene oder nicht -mehr aktive Freigabesessions werden auch mit einer neuen Session nicht erneuert. - -Die Antwort enthaelt nur Job-/Backend-ID, State-Key, Ablauf und -`executionEnabled:false`. AO kann den nicht geheimen Beleg lesen, aber weiterhin -keine Backend-Credentials. Die SQL-Funktion liest weder Credentials noch echten -S3-State. Die API validiert den gespeicherten Descriptor mit dem vorhandenen -S3-Vertrag. Ein Freigabebeleg ersetzt keine einmalige Credential-Ausgabe, echte -S3-Zugriffs-/Lock-Pruefung, Runner-Ticket oder Cloud-Plan/Apply. - -## Interner einmaliger Application-Claim (2026-10-05) - -Migration 028 stellt die atomare Verbrauchsstufe bereit. Die interne -`claimJobGrant`-Methode benoetigt die tatsaechliche weiterhin gueltige -PE-Backend-Freigabesession, nicht eine rekonstruierte PE-Identitaet aus dem -AO-Aufruf. SQL prueft alle Backend-/Grant-Autoritaetsgrenzen erneut und sperrt -die Grant-Zeile, bevor der immutable Claim-Beleg erzeugt wird. Zwei konkurrierende -Claims ergeben einen Erfolg und einen Konflikt. Eine andere echte Session -desselben PE darf den Claim nicht uebernehmen. - -Claim und Widerruf serialisieren dieselbe Zeile; nur eines kann erfolgreich sein. -Nach Verbrauch wird kein Widerruf mit behaupteter Credential-Rueckholung bestaetigt, -sondern 409 zurueckgegeben. Retry der urspruenglichen Job-Vorbereitung liefert -keinen falschen `prepared`-Beleg. Die App-Rolle darf Claims weder direkt schreiben -noch zuruecksetzen oder loeschen. - -Kein Browser-/Runner-Endpunkt fuer diese Methode ist registriert. Sie gibt nur -Job-ID, Claimzeit und Ablauf zurueck; keine Credentials, Ticket oder Runner-Start. -Die anschliessende technische Profil-/Version-/Key-Pruefung, sichere Secret- -Ausgabe, abschliessende Autoritaetspruefung und ticketgebundene Dispatch-Integration -sind weiterhin erforderlich. Der interne Claim allein aktiviert keine Ausfuehrung. +The UUIDs are placeholders and must come from the actually applied platform. Approval is a deliberate PE review of outputs, **not automatic confirmation that a specified folder exists or belongs to the organization**. This resource check remains necessary before future job/credential release. + +- GET/POST `/api/v1/applications/platform-contracts`: current tenant membership; POST additionally requires PE role, valid human STACKIT identity, Origin/CSRF, `confirmApproval: true` and stored SA access. Optional `credentialProfileId`; automatic selection if exactly one profile is stored. Organization access is checked technically without requiring a second human OAuth login. +- Tenant and revision are determined server-side. Migration 014 persists immutable contract versions with Forced RLS and technical verification/version evidence. An access test or contract is not Apply approval. +- POST `/api/v1/applications/templates` can jointly bind `platformRevision` and `targetKey`. Region and project type must match the contract target; cross-tenant contract IDs are not visible. A change creates a new version. +- POST `/api/v1/applications/instances/:id/plan-input` accepts only `{}`. Owner is determined from session and order; other people's orders and client identity/backend overrides are rejected. Identity expiry, revocation, role removal and changed requester email are checked again. +- The compiler uses exactly the order's contract and template versions, fixed parameter rules and own instance state key. The MVP subset is Public with local network, without Observability execution or namespace services. The response explicitly reports `cloudPlanExecuted: false` and `executionEnabled: false`; no keys are delivered to the browser. Immutable version/order policy is adopted as `applyPolicy` (`approval-required` or `direct`); `requiresExplicitApplyApproval: true` remains set for both. Direct policy is not execution approval. + +An actual independent cloud Plan still needs an immutably approved Application Runner artifact, separate state backend with locking and tightly limited server-side use of PE access by exactly the authorized job. The previous Runner pin contains no Application root. It is not switched to unchecked worktree code. Application Apply remains disabled; the approval-bound platform Apply path is separate. + + +## Common editor and execution scope + +Schema v3 is supported for a conservative standalone subset: eu01, organization owner/auditor, folders with names and owner/read permissions, optional parent folder (UUID), explicit Public projects in existing combined configurations, sandbox projects, basic settings and the previous Secrets Manager option. Empty or unset folder descriptions are permitted; populated descriptions are specifically rejected until #82 is fixed because the Accelerator does not adopt them. Network, Kubernetes, firewall and additional platform or project services remain blocked for this Runner. Checking uses the effective configuration, not the template name. UI, preparation and broker use `initialPlanIssues`; checking is repeated before handing credentials to the Runner. JSON and tfvars remain bound to the same Git revision and unchanged export hash. Legacy documents remain supported. + +Organization-tenant blocks still apply. The older initial-provisioning plan uses empty state. In the new platform path, existing state is used exclusively through the checked backend binding; missing or contradictory bindings must not trigger a silent restart with empty state. Extended execution: [#89](https://github.com/stackitcloud/stackit-landing-zone/issues/89). + + +## Workflow and limitations + +**Private Kubernetes APIs:** The current CF Runner has no demonstrated access to customer SNAs. A successful STACKIT access test does not demonstrate this network path. Even Plan/Refresh with Kubernetes/Helm providers can need it. Two-stage execution from [#37](https://github.com/stackitcloud/stackit-landing-zone/issues/37) remains open and is implemented separately. Requirements for execution guards when extending the existing standalone contract are in the [limitations register](accelerator-limitations.md#private-kubernetes-api-ausführungsgrenze). + +- POST `/api/v1/plans` requires session, exact Origin, CSRF token and `confirmNewDeployment: true`. Only one's own preparation with one's own stored credential and admin/deployer role is accepted. +- GitHub fork access, recorded head and generated tfvars export are checked again with the GitHub user token. A changed fork head requires new preparation; another version is not silently adopted. +- SQL 004/005 persists jobs with Forced RLS, preparation, status, engine/provider lock version and CF droplet reference. One active job per user/tenant, at most 20 starts in 24 hours; list shows the latest 100. +- Dispatcher manages exclusively the separate organization `lzc-dev-runners`, space `plans`, SSH disabled. For every job, it creates an app without route/service bindings and copies the checked Runner droplet. CF manager credentials remain in the trusted API backend/release. +- Runner receives three app variables: job ID, fixed broker URL, random 256-bit ticket. Only its hash is stored in PostgreSQL. Validity at most 25 minutes. A narrowly scoped SECURITY-DEFINER function resolves the ticket to exactly one active job; owner/tenant RLS and role checking apply afterwards. +- Inputs are issued once, after renewed role, profile, version and organization checking. Other profiles or tenants cannot be selected. Terraform subprocesses receive an explicit environment without the broker ticket. +- Fixed Accelerator commit `a256f6896d11134fdc351786f1be5eba4e56b2e2`, OpenTofu 1.12.6, provider-lock SHA-256 `a52433c424472d6e618caa3a94579bbcd19b60b759d053cf0d5caf9ac6872888`. CI builds only upstream code of this commit and a Linux provider mirror. +- OpenTofu 1.12.6 does not export Terraform's `complete` field in saved-plan JSON 1.2. For this exact format, the worker may confirm completeness only after checking the pinned engine and its fixed complete Plan command without targeting. The summary parser requires this explicit engine context; missing context, unknown versions/formats or deferred metadata remain `not-reported`, a reported partial plan remains `incomplete`. Error status, open/failed checks and all artifact/state/approval bindings continue to block Apply. Previously saved summaries are not rewritten. +- Direct commands in `deploy/runner/run-plan.sh`: init with readonly lock, validate, plan with detailed exit code and show. No freely selectable command. The new platform path may execute Apply only with the approved saved plan. +- Result projection contains only counts, status and fixed error codes; no addresses, attribute values, output names, raw diagnostics or secrets. Even values not marked sensitive are not exported into this summary. Separately, under **OpenTofu output**, Runner shows the authorized Plan owner normal CLI text: live logs from the private active job or `tofu show -no-color` of the exactly hash/package-bound, encrypted saved plan artifact. Session, deployment role and owner/tenant RLS are checked before every access; responses are `no-store`. Resource addresses and normal attribute values are visible there; sensitive values remain masked by OpenTofu. Known credential fields are additionally removed from live logs. Plan binary and `show -json` remain server-side. No new cloud Plan, Apply or backend init runs; inspection uses only backend-free init and show without inherited secrets. Apply expiry remains independent of the read-only display as long as the encrypted artifact exists. +- Active platform jobs open an NDJSON live channel at `GET /api/v1/plans/:id/output` with `Accept: application/x-ndjson`. JSON snapshots remain for history and existing clients. Worker reads complete log lines every 500 ms and transmits only changed, redacted transcripts. After encrypted commit, the API notifies its local subscribers; other API instances recheck within one second at the latest. Unchanged output creates only a heartbeat, not a new transcript. Session, workspace, deployment role and ownership are rechecked during the connection, not only at opening. Connections end after at most 35 seconds and reopen if the job is still active. Collapse, navigation and logout abort them. Per owner/tenant, each API instance permits at most eight connections; slow readers cause backpressure rather than unbounded queues. +- Plan uses OpenTofu's native `-json` UI events for actual progress messages, even before the completed diff exists. Only human-readable messages of the supported UI protocol are projected; raw events, metadata and output values are not sent to the browser. Incomplete lines are withheld; invalid events receive a visible fixed error notice. Afterwards `tofu show -no-color plan.bin` adds the complete normal plan text. Init, Validate, Apply and migration retain native CLI output. No estimated percentages: if OpenTofu produces no message during an operation, phase and elapsed time remain visible. +- During the run and before the terminal result, worker saves the redacted CLI transcript of Init/Validate/Plan/Apply/migration through `POST /api/runner/output`. The job-specific ticket must be valid and input already claimed; text may be updated until completion, then is frozen. Migration 020 creates private output columns under existing owner/tenant RLS. Broker encrypts at most 2 MiB with AEAD and job-specific AAD. Success and failure output remains readable after cleanup and reload without a running Runner. Truncation is marked. A hard process abort or failed upload can still lose historical output; best-effort saving neither triggers an Apply retry nor replaces the durable state-recovery receipt. Apply evidence shows the exact plan, SHA-256, target organization, job's state backend and completion time. An incompatible native Runner package blocks Apply before dispatch; a new Plan with renewed review and approval is required. +- Task: 1 GiB RAM, 4 GiB disk, 18-minute engine deadline, bounded private files. SQL deadline: 25 minutes. Maintenance every 30 seconds, cleanup after at least 30 seconds in terminal status. Jobs are cleaned up even after API restart. CF/network errors can delay cleanup; ticket expiry remains independent. +- No automatic dispatch retry. Process loss before start leads to cancellation/expiry rather than silent re-execution. No general queue scheduler or durable Runner heartbeat monitoring yet. The new platform path stores plan artifacts encrypted and binds them to source, engine and state version. CF quotas additionally limit overall capacity. +- Preparations with Plan evidence are not deleted. Archiving and metadata retention periods are a subsequent step. + + +## State lifecycle according to LZA + +User decision: adopt existing [LZA bootstrap](https://github.com/stackitcloud/stackit-landing-zone/blob/main/docs/getting-started.md). Stored access is the bootstrap service account; project and account are not recreated. A Plan creates neither management project nor bucket. In the new platform path, the durable encrypted HTTP backend serves only bootstrap, not as a permanent replacement for customer S3 state. + +At the separately approved first Apply, the management module creates the customer state bucket with credentials. Afterwards Runner migrates with `tofu init -migrate-state`; the API confirms migration only after comparing state hash and remote version/ETag and bound state version. Only then is the HTTP primary state removed. The verified management service account is used subsequently. The S3 backend uses `use_lockfile = true`. Application instances each receive their own keys `applications///terraform.tfstate`; platform, Application and Configurator infrastructure states remain separate. + +Legacy state mappings are blocked with `legacy_state_migration_required` and require explicit mapping/migration, not new empty state. For `state_failed` or unconfirmed migration, explicit state reconciliation is required before resumption; a completed S3 copy can be confirmed without another Apply as described below. Other recovery cases still need a protected export. Runner transmits checked, encrypted recovery evidence and removes local error states only after matching durable receipt confirmation. This does not guarantee automatic complete restoration after every hard Runner loss; reconciliation and operational recovery remain necessary. No real cloud S3 lock test was performed. No customer Apply was executed in this implementation. + + +## Correcting configuration after a failed bootstrap Apply + +Migration `034_platform_reconciliation.sql` adds explicit, audited UI reconciliation. In the Apply view, only **Check checkpoint** reads the encrypted bootstrap checkpoint of one's own failed Apply. The response contains only state version, SHA256, serial, lock/migration status and resource counts by type; no attributes, outputs or raw states. + +**Allow replanning** requires separate confirmation to preserve state unchanged. The API rechecks the displayed version and checksum in a transaction. Only an already started Apply regularly terminated with `apply_failed`, with readable bootstrap checkpoint, positive state version, no held lock, open migration or separate recovery state, is eligible. Immutable tenant/owner-bound audit evidence binds Apply, real session, state key, version and checksum. Concurrent identical confirmations create only one record. The run is completed as failed; state, version, lock and backend remain unchanged. No cloud access or automatic Plan/Apply occurs. + +The user can then save the corrected configuration, choose a new preparation and start a new Plan against the same existing state. Apply again requires separate review and approval of the new saved plan. The old plan remains consumed. If the checkpoint has changed meanwhile, a new check is required. Ambiguous Runner aborts, unverifiable migrations and separate recovery states remain blocked and need separate operational reconciliation. No automatic unblocking, state deletion, import or Destroy action. The migration must be enabled before using the new API. + + +### Completing a successful Apply with pending S3 confirmation + +OpenTofu 1.12.6 uses a new lineage and serial 1 for HTTP-to-S3 migration. This is reproduced with the real pinned Runner binary and exclusively synthetic local HTTP/S3 endpoints, even after multiple writes to source state. The former requirement for identical overall hash, lineage and serial rejected this successful copy. Besides an exact full copy, `migrationStateMatches` accepts only this demonstrated transformation: source version 1.12.6, new lineage, target serial 1 and otherwise exactly identical canonical state content. Resources, attributes, outputs, format, version and all other fields remain fully checked. Only ordering of the top-level `check_results` list is normalized in the pinned native migration comparison. All complete check entries, including nested content and duplicate entries, are retained; nothing is removed or reduced to successful status values. This ordering change is reproduced with real OpenTofu validations. Global state hashes, source backup evidence and other array orders remain unchanged. Changed check results or resources remain blocked. Unknown versions or arbitrary serial/content changes are not approved. The host binary must not be assumed to be the Runner version; the native test uses `LZC_NATIVE_TOFU_BINARY` and checks the real version. + +For a regularly terminated `state_failed` with a bound open migration, **Check checkpoint** reads encrypted bootstrap state and already registered S3 state on explicit click. Only aggregated metadata is shown, including S3 check status, serial and the boolean indicating whether lineage was retained. Without lock, separate recovery or differing content, users can **Confirm backend migration** themselves. + +This confirmation binds source version, source SHA and exact remote object version. All evidence is rechecked before completion. In the same transaction, the existing CAS backend switch, immutable audit evidence and completion of Apply as `succeeded` take place. Only after successful S3 reconciliation is temporary bootstrap primary state removed. Identical concurrent confirmations are idempotent. This starts no Runner, Apply, S3 write, import, unlock or Destroy. If check status changes, bootstrap backup and recovery block are retained. No new schema migration is required. + + +### Local activation on 2026-10-06 + +After explicit approval, the running customer DB was privately backed up, the full dump restored in a separate loopback-bound PostgreSQL 17 instance and upgraded there to migration 034 with the real migrator. Row counts and hashes of all 32 existing tables in `lzc` and `lzc_auth` remained unchanged. Only then was the API restarted with no running customer jobs. The same comparison also passed after live migration. + +The live DB now contains migrations 001 through 034; the new audit table is empty and has enforced RLS. The failed Apply remains `recovery_required`. The previous immutable platform Runner package remains active; Application execution remains explicitly disabled. API and UI proxy answer health checks with 200, new checkpoint/approval routes without login with 401 and disabled Application Runner with 404. The UI serves the qualified current build. The temporary restore instance and its own volume were removed; private dump and hash evidence remain for recovery. + +This activation checked only backup, schema, data preservation and access guards. The customer checkpoint was neither decrypted nor approved. The real checkpoint check and confirmation are performed by the user in their authenticated UI. No cloud Plan/Apply was started. + + +### Activation of the S3 completion fix on 2026-10-06 + +After the user reported successful Apply and `init -migrate-state`, current DB state was privately backed up again. No platform or Application jobs were running before the code-only restart. Row counts and hashes of all 33 existing tables, now including recovery evidence, remained unchanged after restart. Migrations 001 through 034, bound native platform package and disabled Application execution remain. API and UI proxy `/healthz` return 200; checkpoint/approval routes without login 401 and disabled Application Runner 404. + +The current build passes the canonical gate with 376 unit tests and all 42 isolated PostgreSQL broker cases, 16 backend tests including real local OpenTofu 1.12.6 migration and 12 affected desktop/mobile browser cases. Browser and broker cases use controlled test data; they do not demonstrate successful S3 reconciliation of the customer run. This was neither read nor confirmed during activation and remains an explicit UI step for the user. No customer Apply was repeated. + + +### Demonstrated check ordering and correction on 2026-10-06 + +After explicit approval, exactly the open migration case was decrypted locally and its bound S3 state compared read-only. Only masked structural paths and equality/count metadata were output, no values, keys or raw states. All 36 complete check entries were equal but differently ordered; resources, attributes and outputs were identical. The corrected comparison also passes for this state. The previous comparison was reproduced as a failing native regression case with 24 real local OpenTofu validations. + +After a fresh private backup and zero active jobs, only the API was restarted with unchanged platform package. All 30 non-authentication tables, particularly states, backends, plans, artifacts and recovery evidence, remained unchanged. In parallel, an additional session and changes to identity/access metadata were observed; these three tables are therefore not reported as unchanged and were not reset. No schema migration or S3 write was performed; actual backend confirmation remains a separate user UI step. The gate passes with 387 unit tests, 27 backend tests including native migration and all 42 isolated PostgreSQL broker cases. + + +## Portable GitHub export + +Export atomically writes `landing-zone.json`, `landing-zone.tfvars` and a short CLI guide under `src/config/custom//`. For server-verified S3 binding, it adds `backend.tf.json`: complete standard Terraform backend configuration without AWS/SA keys or state file. Only `backend_not_found` allows a new bootstrap export without backend; service and permission errors abort saving. An existing backend file must exactly match the deterministic Git blob hash of the checked descriptor. Otherwise `backend_configuration_changed` applies; if binding is absent, `backend_configuration_missing` applies instead of metadata loss. + +At first DB-to-GitHub export, configuration ID is retained. An already opened Git configuration keeps its own ID. For a differing source ID, the server exports the bound descriptor without alias or state mutation; new preparation must explicitly select the registered backend ID. For independent CLI operation: use checked Accelerator code, disable the original backend block in `src/backend.tf`, copy the exported backend file to `src/backend.tf.json` and retain exactly one active backend block. Load AWS access from management Secrets Manager into the environment according to LZA, then `tofu init` and `tofu plan -var-file=config/custom//landing-zone.tfvars`. Without S3 binding, first complete LZA bootstrap and verified state migration. + + +## Acceptance + +- [x] API: session/CSRF, strict input schema, initial-provisioning confirmation, personal GitHub token and no Apply endpoint tested. +- [x] PostgreSQL: foreign jobs, concurrent start, ticket replay, status ordering, expiry and targeted cleanup tested. +- [x] CF client: own app, fixed commands, only three job variables and no route. +- [x] Desktop/mobile: Plan start, running status, result after reload, no Apply. +- [x] Local real OpenTofu contract test without cloud access and without Apply. +- [x] Separate CF organization with manager created through platform IaC. +- [x] Runner space/roles successfully applied through runtime IaC. +- [x] Linux package, provider mirror and CF engine test successful. +- [x] Live app: check separate Runner without service bindings, invalid ticket must not execute a customer job; remove probe app. +- [ ] First personal customer Plan by the user. + + +## Live acceptance on 2026-09-30 + +[Release 36727211809](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36727211809) for `b5686ef` successful: CF engine init/validate, database migrations, PostgreSQL/Secrets Manager connections, separate probe app and public route. Runner management identity has no access to the Configurator app; probe app without routes or service bindings. A random unregistered ticket caused a failed task. This is an infrastructure/isolation probe, not yet a successful personal customer Plan. + +Measured from dispatch to task creation: **3.907 ms**; to observed task completion: **12.244 ms**. A single value, not a latency guarantee. The probe uses the prestaged template, not `cf push` per job. Regular job execution additionally includes input/access checking and OpenTofu runtime. No customer Apply. + + +## Sources + +[OpenTofu JSON format](https://opentofu.org/docs/internals/json-format/), +[Plan exit codes](https://opentofu.org/docs/cli/commands/plan/), +[CF V3 droplet copy](https://v3-apidocs.cloudfoundry.org/version/3.199.0/index.html#copy-a-droplet), +[CF V3 tasks](https://v3-apidocs.cloudfoundry.org/version/3.199.0/index.html#create-a-task). + + +## Release of the v3 standalone Plan path (2026-10-01) + +Commit `9aa3322`, [release 36849188406](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36849188406) and [validation 36849188417](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36849188417) successful. Locally 123 unit, 22 PostgreSQL and 38 browser checks; real OpenTofu Plan summary test and four native Application root contracts with 1.12.6. Database checking covers legacy/v3 and renewed broker blocking checks. Live app serves the new bundle, health 200 and anonymously protected APIs 401. This is neither personal customer Plan acceptance nor customer Apply. + + +## Governance qualification and service-account federation (2026-10-01) + +Governance input approval is additionally checked with the actually used governance module: `npm run test:plan` calls separate `test-governance-contract.sh`. Source hashes bind checking to the Accelerator pin. OpenTofu 1.12.6 plans with mock providers in a cleaned environment, without cloud credentials or Apply. Checks cover organization roles `owner`/`organization.auditor`, folder roles `owner`/`auditor`, omission of duplicate folder assignments for organization owners and both parent variants. This local qualification does not replace a Plan against the specific customer organization. + +**Service-account federation for CI/CD** is an optional editor component. It controls which external pipeline OIDC tokens may use the management service account; it is not user login to the Configurator. `issuer` is the trusted issuer, `aud` the token audience and `sub`, for example, the specific GitHub repository with branch. Conditions use comparison `equals` supported by the pinned provider; `aud` is required. The GitHub template limits `sub` to a specified branch and does not apply unchanged to jobs with GitHub environments. + +The component sets up neither workflow nor token exchange and removes no existing keys. It is not required for the current Configurator Runner or a small initial-provisioning plan. Its execution remains blocked until separate Runner qualification; saving and editing configuration remain possible. + +Source: [STACKIT Provider 0.114.0 – Service Account Federated Identity Provider](https://registry.terraform.io/providers/stackitcloud/stackit/0.114.0/docs/resources/service_account_federated_identity_provider). + + +### Release evidence + +- Source `64e33cb`, [release 36856248765](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36856248765) and [validation 36856248770](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36856248770) successful. +- Local: 140 unit tests, desktop/mobile browser checks including overflow checking, three governance mock plans and existing OpenTofu Plan/Application contract tests successful. +- Live: SPA and assets HTTP 200 (`index-CnPzJNzo.js`, `index-DoULK2fp.css`), `/healthz` HTTP 200, anonymous session HTTP 401. Release connection tests successful. +- No customer Apply, no acceptance of a real customer Plan and no merge to main. + + +## Limited platform credential grants + +Implemented locally on 2026-10-05, not yet enabled in the running customer API: migration `025_plan_credential_grants.sql` creates a grant in the same transaction at explicit Plan start or existing explicit Apply approval. No general credential delegation and no automatic retrofitting of old waiting jobs. + +Immutable evidence binds job, tenant, user, preparation, organization, credential profile, secret version, key ID, manifest hash and operation (`plan` or `apply`). Its validity ends no later than the job ticket or issuing session. It contains no keys or tokens. SQL checks binding to the real job and its preparation data; RLS limits access to the currently authorized deployment user who owns it. + +Runner claims the grant once before technical credential checking or secret retrieval. Missing, expired, revoked or mismatching grants block this use. Before returning key, backend and, if applicable, saved plan, grant, expiry and initiating job are checked again. A failed claim is not reset; a new job requires new explicit approval. Concurrent input requests can receive credentials only once. + +`POST /api/v1/plans/{id}/credential-grant/revoke` requires Origin, CSRF, current `x-lzc-tenant` and exclusively `{"confirmCredentialGrantRevocation":true}`. Repeated revocation returns the same evidence. Normal Plan cancellation also revokes an unused grant. Already claimed grants return `credential_grant_already_consumed`; credentials already transferred cannot be retrieved from a Runner. Running worker, cloud IAM key rotation and recovery must be handled separately in such an incident. Ticket-bound result/recovery endpoints remain unchanged and are not another credential issuance. + +This boundary limits credential retrieval, not cloud IAM permissions of the key or an already running operation. Least-privilege qualification, Application root/instance dispatch with own state and grant, and real two-organization/revocation acceptance remain #91/#93. This step gives AOs no access to platform credentials. 31 real isolated PostgreSQL broker/grant cases and the canonical overall check pass. + + +## Local Application Runner root (2026-10-05) + +The intermediate feature status is saved locally as `4ad9367`. The separate Application source pin is `4d15d7870afa323badd93559d8b37c5a8d138dcf`; backend, provider and version requirements are in separate files. The previous platform pin `a256f6896d11134fdc351786f1be5eba4e56b2e2` and already bound Runner packages remain unchanged. + +With `LZC_LOCAL_RUNNER_PACKAGE=true` and `LZC_PACKAGE_APPLICATION_ROOT=true`, the build script additionally packages exclusively `src/application` and `src/modules/landing-zone` from the fixed Git pin as `application-src`. Use a new, not-yet-existing `LZC_RUNNER_PACKAGE_DIR`. Its own provider lock pins STACKIT 0.114.0 and time 0.14.1, with checked checksums for Darwin ARM64 and Linux AMD64. Its SHA-256 is `d40debbff204aee590c2a76d09f6ad3234643329b438fd5c6497de60687f6fa5`. Application packaging is deliberately blocked for production builds. + +New worker modes `application-plan` and `application-apply` require the fixed Application pin/lock and strict binding of `tenantId` and `instanceId`. S3 key must be exactly `applications///terraform.tfstate`; lockfile is mandatory. Bootstrap/platform state and arbitrary root paths are rejected. Working directory retains the relative module path but is separate from the platform root. Apply uses only the saved plan, without replan or bootstrap migration. If recovery transfer fails, only the private Application recovery state and its directories are retained. + +This is not yet Application broker dispatch or cloud IAM scope: `executionEnabled: false` remains. Instance jobs, own real locks, PE-authorized credential grants, expiry/revocation, quotas and explicit upgrades still need connecting. The new source pin needs explicit new template publication; stored versions/plans are not rebound. No active package was replaced and no customer operation started. Worker tests use a controlled engine, while package init/validate and native mock contract tests use real OpenTofu. + + +## Prepared Application jobs and grant evidence (2026-10-05) + +The term source pin means a fixed Git commit ID of Accelerator Terraform code, not credentials or a personal PIN. New publications can explicitly set `acceleratorRevision` to qualified Application commit `4d15d7870afa323badd93559d8b37c5a8d138dcf`. This creates a new immutable template version; the previous default and all old versions remain unchanged. Other commits are rejected. API pin selection is not yet connected as an additional UI publication step. + +Migration 026 stores jobs with status `prepared` and SQL-derived grant evidence. `POST /api/v1/applications/instances/{id}/jobs` requires exactly `{"idempotencyKey":"","confirmPlan":true}`. Session, current tenant, Origin and CSRF are checked; role, verified requester identity, ownership, version/policy and compiler inputs are reread from stored records. Only the qualified Application source revision is accepted. A transactional lock serializes the idempotency key. Repetition returns the same valid job; an expired or revoked grant is not renewed by retry. A fresh job needs a new key and renewed explicit confirmation. + +The SQL trigger checks real session, verified organization, current PE membership of the contract approver and current requester identity. It derives organization, profile/secret version/key ID, requester, instance, template/contract version, source revision, compiler hash, operation and state key. Expiry is bounded by real session, human token and at most 25 minutes. The app role may not insert grants directly or change bindings; tenant/owner RLS and immutable evidence remain enforced. + +`POST /api/v1/applications/jobs/{id}/credential-grant/revoke` requires exactly `{"confirmCredentialGrantRevocation":true}` with the same HTTP boundaries. Requester or contract-approving current PE may revoke within the tenant. Repetition returns the same timestamped evidence; revocation cannot be reset. + +The job response contains only ID, instance, status and expiry plus `executionEnabled:false` and `cloudPlanExecuted:false`. No credentials, ticket or Runner start. Grant evidence is not yet one-time credential handover, state file or cloud operation. One-time issuance under renewed authority/profile checking and real instance-bound S3 state/lock access must be further integrated before dispatch. + + +## Explicit Application backend approval (2026-10-05) + +Migration 027 adds immutable backend evidence for a valid prepared Application job. `POST /api/v1/applications/jobs/{id}/backend-approval` requires exactly `{"stateBackendId":"","confirmBackendApproval":true}` with session/Origin/CSRF/tenant checking. Only the current PE who approved the platform contract may confirm. SQL rechecks job and grant expiry, revocation, requester session, memberships, organization and both current human identities. The backend record must belong to the same tenant. + +The S3 descriptor is derived from the registered backend; its key must be `applications///terraform.tfstate`, lockfile remains mandatory. Approval session and backend binding are immutable. Lifetime is the minimum of grant, real PE session and PE identity. Concurrent identical approvals are idempotent; backend switch returns 409. Expired or no-longer-active approval sessions are not renewed even with a new session. + +The response contains only job/backend ID, state key, expiry and `executionEnabled:false`. AO can read non-secret evidence, but still no backend credentials. The SQL function reads neither credentials nor real S3 state. The API validates the saved descriptor using the existing S3 contract. Approval evidence replaces neither one-time credential issuance, real S3 access/locking checks, Runner ticket nor cloud Plan/Apply. + + +## Internal one-time Application claim (2026-10-05) + +Migration 028 provides the atomic consumption stage. Internal `claimJobGrant` requires the actual still-valid PE backend approval session, not a reconstructed PE identity from the AO call. SQL rechecks all backend/grant authority boundaries and locks the grant row before creating immutable claim evidence. Two concurrent claims produce one success and one conflict. Another real session of the same PE may not take over the claim. + +Claim and revocation serialize the same row; only one can succeed. After consumption, no revocation claiming credential retrieval is confirmed; 409 is returned instead. Retrying original job preparation returns no false `prepared` evidence. The app role may neither write claims directly nor reset or delete them. + +No browser/Runner endpoint for this method is registered. It returns only job ID, claim time and expiry; no credentials, ticket or Runner start. Subsequent technical profile/version/key checking, secure secret issuance, final authority check and ticket-bound dispatch integration remain necessary. Internal claim alone activates no execution. diff --git a/landing-zone-configurator/docs/planning.de.md b/landing-zone-configurator/docs/planning.de.md new file mode 100644 index 0000000..78fc0a5 --- /dev/null +++ b/landing-zone-configurator/docs/planning.de.md @@ -0,0 +1,1153 @@ + + +# Landing Zone Configurator – Architektur und Planung + +[English](planning.md) | [Deutsch](planning.de.md) + +> Stand: 2026-10-01 · Architektur-Ausgangsstand: `2161871` +> Historisches Entscheidungsprotokoll, kein aktueller Betriebs- oder Abnahmestand. +> Aktuelle Referenzen: [Architektur](architecture.de.md), [MVP-Grenzen](mvp-scope.de.md), [Entwicklung](development.de.md) und [GitHub-Issues](https://github.com/stackitcloud/stackit-landing-zone/issues). +> Die folgenden Architekturabschnitte und datierten Fortschrittsnotizen sind das Entscheidungsprotokoll; ältere Statusangaben beschreiben den damaligen Stand. +> `[x]` = je nach Abschnitt entschieden oder mit angegebenem Nachweis umgesetzt; eine Entscheidung allein ist keine Live-Abnahme. + + + +## Aktueller Umsetzungsschritt + +**Aktueller Template-Schritt:** [Typisierte Bestelleingaben und Ressourcenverknüpfungen](template-parameters-and-bindings.de.md), einschließlich Stage-Auswahl und Observability-Zugriff aus dem eigenen Projektnetz. Der Parametervertrag mit fünf freigegebenen Feldern, Editor und lokaler Bestellvorschau ist implementiert. Die produktive Projektnetz-/Egress-Bindung bleibt in #96 offen; Veröffentlichung und Application-Owner-Bestellungen folgen gesondert. + + +**Korrektur des Rollenablaufs:** Neue Plattformkonfigurationen enthalten +[Projekt-Template-Entwürfe](project-template-drafts.de.md) statt konkreter +Anwendungsprojekte. Der Platform Engineer definiert sie; Instanzen entstehen +später durch den Application Owner aus veröffentlichten Versionen. Alte +Gesamtkonfigurationen bleiben unverändert, Übernahme nur als ausdrückliche Kopie. + + +Governance-Pläne umfassen auch Organisationsrollen und Ordnerberechtigungen; +leere Ordnerbeschreibungen blockieren nicht mehr. Die optionale +Service-Account-Föderation erhält einen eigenen erklärten CI/CD-Editor. +[Umfang und Qualifikation](plan-execution.de.md). + +Die MVP-Bestandsaufnahme trennt Editorabdeckung von Ausführungsfreigabe. Zunächst +wird die geprüfte Standalone-Teilmenge des gemeinsamen Editors an den vorhandenen +Erstbereitstellungsplan angebunden. Anschließend folgen dauerhafter Bootstrap-State +und freigegebener Apply. Parallel werden verifizierte Organisationstenants, +veröffentlichte Application Templates und der Model-Serving-Assistent aufgebaut. +Die Arbeitspakete #89–#95 enthalten konkrete Abnahmekriterien. + +Kunden-Apply benötigt weiterhin eine ausdrückliche Freigabe; Organisationen sind +bis zum Berechtigungsnachweis unverifizierte Entwürfe. Der Featurebranch wird in +diesem Schritt nicht nach main gemergt. + + + +## 1. Zielbild und bestätigte Entscheidungen + +Eine zentral auf STACKIT Cloud Foundry gehostete Anwendung begleitet Benutzer vom Landing-Zone-Template bis zum überprüfbaren Deployment. Die Oberfläche arbeitet mit Organisationen, Netzwerkbereichen, Plattformdiensten und Workloads. Ein deterministischer Compiler übersetzt diese fachlichen Angaben in die Konfiguration des Accelerators. Terraform bleibt im Hintergrund; technische Details sind bei Bedarf einsehbar. + +**Bestätigt im Planungsgespräch:** + +- [x] Produktname: Landing Zone Configurator. +- [x] Sämtliche Configurator-Dienste inklusive Aktivierung werden via IaC erstellt; keine manuelle Portal-Provisionierung. +- [x] Erste Entwicklungsumgebung: lzc-dev in eu01. +- [x] App, IaC und Dokumentation unter `landing-zone-configurator/` getrennt vom Accelerator organisieren. +- [x] Betreiberprojekt und Service-Account-Datei sind lokal bereitgestellt; `NAME=WERT`-Format geprüft; Projektzugriff sowie Bereitstellung von Plattform und Runtime durch CI-Applies nachgewiesen. + +- [x] Von Beginn an mehrere unabhängige Kundenorganisationen unterstützen. Mandantentrennung ist Voraussetzung der ersten Freigabe, kein späterer Ausbau. +- [x] Zunächst ausschließlich Konfigurationen verändern und mit freigegebenem Accelerator-Code ausführen. Eigene Terraform-Modifikationen aus Forks folgen später. +- [x] GitHub-Zugriffe erfolgen im Namen und mit Berechtigungen des Benutzers, ohne zentrale Repository-Credentials. +- [x] App-Hosting auf STACKIT Cloud Foundry; Plattformumgebung über IaC aufbauen. +- [x] STACKIT Model Serving als Chat-Backend; dessen Betreiber-Credentials serverseitig über CF-Variablen bereitstellen. + +Die Betreiber benötigen technische Identitäten für CF, Datenbank, Secret-Verwaltung und Runner. Diese dürfen keine pauschale Berechtigung für Kunden-Repositories oder Kunden-Deployments haben. Die gewünschten zentralen Model-Serving-Credentials sind eine ausdrücklich abgegrenzte Betreiberfunktion. + + + +### Anforderungskatalog + +| ID | Fähigkeit | Einordnung | +| --- | --- | --- | +| F01 | GitHub-Login und benutzergebundene Repository-Zugriffe | Erste Version | +| F02 | Fork erstellen und mehrere vorhandene Repository-Verbindungen auswählen | Erste Version; GitHub-Grenzen berücksichtigen | +| F03 | Vorhandene `src/config/`-Beispiele als Templates anbieten und kopieren | Erste Version | +| F04 | Fachlicher Editor passend zu Modulen und Features | Schrittweise Umsetzung; Abdeckung sichtbar machen | +| F05 | Konfigurationen im ausgewählten eigenen Fork speichern | Erste Version | +| F06 | Persönliche Credentials und Deployment-Profile sicher verwalten | Vor erstem Deployment | +| F07 | Terraform/OpenTofu Plan und Apply visuell begleiten und ausführen | Kernumfang | +| F08 | Optionale Drift Detection und optionale Drift Correction | Nach stabilem Apply | +| F09 | Chat mit Rückfragen, vollständigem versionsbezogenem Feature-Wissen und Themenbegrenzung | Kernumfang | +| F10 | Grafische Konfigurationsdarstellung, später Plan-Delta und bekanntes Ist | Kernumfang | +| F11 | STACKIT-PaaS-Datenbank für Persistenz | Empfehlung: PostgreSQL Flex | +| F12 | Optionaler STACKIT-IdP-Login | Machbarkeit prüfen; keine MVP-Abhängigkeit | +| F13 | Model-Serving-Service als Voraussetzung und Plattformaufbau per IaC | Kernumfang | + + + +## 2. Ausgangslage dieses Repositories + +Grundlage sind [Root-Variablen](../../src/variables.tf), [Provider](../../src/providers.tf), [Engine-/Provider-Vorgaben](../../src/terraform.tf), [Backend-Beispiel](../../src/backend.tf), [Getting Started](../../docs/getting-started.de.md), [Architektur](../../docs/architecture.de.md), [mise.toml](../../mise.toml) und [Beitragsregeln](../../CONTRIBUTING.de.md). + + + +### Template-Katalog + +| Datei unter `src/config/` | Fachliche Darstellung | +| --- | --- | +| `standalone.tfvars` | Unabhängige Landing Zones ohne zentralen Netzwerk-Hub | +| `hub-and-spoke.tfvars` | Zentraler Netzwerk-Hub mit angebundenen Landing Zones | +| `hub-and-spoke-firewall.tfvars` | Hub-Spoke mit OPNsense-Firewall | +| `hub-and-spoke-multi-area.tfvars` | Getrennte Bereiche für regulierte und gemeinsame Workloads | +| `hub-and-spoke-finance-research.tfvars` | Getrennte Bereiche für Fachorganisationen | +| `hub-and-spoke-prod-nonprod-firewall.tfvars` | Getrennte Prod-/Nonprod-Bereiche mit Appliances | +| `hub-and-spoke-tenant-isolation.tfvars` | Netzwerkisolation innerhalb einer STACKIT-Organisation | +| `hub-and-spoke-multi-region.tfvars` | Regionale Hubs, Landing Zones und Plattformcluster in `eu01`/`eu02` | + +**Wichtige Grenzen und Konsequenzen:** + +- Templates enthalten Platzhalter und auskommentierte optionale Features. Ein HCL-Parser allein entdeckt daher nicht den gesamten Funktionsumfang. Ein expliziter Feature-Katalog ist nötig. +- `src/providers.tf` unterstützt statische regionale Aliasse für `eu01` und `eu02`. Die UI darf weitere Regionen nicht als automatisch unterstützt ausgeben. +- `connectivity_regions` ist als `map(any)` modelliert. Fachliche UI-Validierung muss über die Terraform-Typprüfung hinausgehen. +- Ein Projekt gehört gemäß Repo-Dokumentation zu genau einer SNA; mehrere SNAs oder Regionen sind nicht automatisch privat verbunden. +- `firewall_config` konfiguriert derzeit eine Appliance. Mehrere Appliances bedeuten keine automatische Policy-Verteilung. Dies bleibt eine sichtbare Einschränkung. +- Firewall-Bootstrap benötigt mehrere Schritte, ein Image und Shell-Werkzeuge. Die Anleitung beschreibt ein anfänglich öffentliches Admin-Interface mit gemeinsamem Initialpasswort. Automatisierte Freigabe erst nach sicherem Bootstrap und Passwortrotation. +- Private Firewall-/Kubernetes-Endpunkte benötigen passende Runner-Konnektivität. Zentraler CF-Betrieb allein stellt diese nicht her. +- Das Backend ist auskommentiert; die Anleitung migriert lokalen State erst nach der Erstbereitstellung in den erzeugten Management-Bucket. Kurzlebige Runner benötigen dagegen Remote State vor dem ersten Lauf. +- `mise.toml` pinnt OpenTofu `1.12.6`; `src/terraform.tf` verlangt mindestens `1.11`. README/Getting Started nennen teils abweichende Mindestversionen. Empfehlung: zunächst die gepinnte OpenTofu-Version qualifizieren; Terraform als weitere Engine separat testen. +- Das Repo verspricht keine pauschale Migrationskompatibilität. Upgrades brauchen explizite Migration, Versionsprüfung und neuen Plan. +- Die Netzwerkisolation des Templates „Tenant Isolation“ ersetzt nicht die Mandantentrennung der zentralen Anwendung. + + + +## 3. Zielarchitektur + +Empfehlung: modularer Backend-Dienst mit klaren internen Grenzen; Terraform-Ausführung als getrennte Laufzeit. Keine unnötige Aufteilung in viele Microservices zum Start. + +```mermaid +flowchart TB + U[Browser] --> W[Web UI und Backend-for-Frontend auf CF] + W --> GH[GitHub API mit Benutzer-Token] + W --> DB[PostgreSQL Flex: Metadaten und Jobqueue] + W --> SM[Secret Store: Benutzer- und Deployment-Secrets] + W --> AI[STACKIT Model Serving] + W --> OBJ[Object Storage: geschützte Run-Artefakte] + S[Scheduler und Dispatcher auf CF] --> DB + S --> R[Isolierter kurzlebiger Runner je Lauf] + R --> ST[Remote State je Deployment] + R --> TARGET[STACKIT-Zielumgebung des Kunden] + R --> OBJ + R --> B[Run-begrenzte Credential-Ausgabe] + B --> SM +``` + +| Baustein | Empfehlung | Verantwortung | +| --- | --- | --- | +| Frontend | React/TypeScript mit Vite; Graph-Bibliothek noch auswählen | Wizard, Fachformulare, Topologie, Chat und Run-Ansicht | +| Backend/BFF | TypeScript mit Fastify auf Node.js 24 LTS | Sessions, Autorisierung, GitHub, Konfiguration, Chat-Orchestrierung | +| HCL-Adapter | Kleiner Go-Adapter mit HCL-Parser | Bestehende `.tfvars` strukturiert lesen, keine Regex-Konvertierung | +| Konfigurationskern | Versioniertes JSON Schema, Fachregeln und Compiler | Gemeinsamer Vertrag für Editor, Import, Chat und Ausgabe | +| Datenbank | STACKIT PostgreSQL Flex | Mandanten, Entwürfe, Revisionen, Runs, Audit und Queue | +| Scheduler/Queue | Durable PostgreSQL-Queue und separater CF-Prozess | Leases, Heartbeats, Wiederaufnahme, faire Mandantenquoten | +| Secrets | STACKIT Secrets Manager, nach Prüfung der erforderlichen Policies | DB enthält Referenzen; keine Klartext-Credentials | +| Artefakte | STACKIT Object Storage | Geschützte Plans, bereinigte Logs und Laufmanifest | +| Runner | Unveränderliches Artefakt mit gepinnter Engine und Providern | Nur Credentials des konkreten Deployments | +| Chat | STACKIT Model Serving über Backend | Beratung und validierte Vorschläge; keine Ausführungsrechte | + +PostgreSQL Flex ist als verwalteter Dienst dokumentiert und unterstützt Verwaltung über Terraform und Cloud Foundry. Konkrete Region, Plan, HA, Backup, ACLs und CF-Anbindung sind vor Provisionierung festzulegen. [PostgreSQL Flex](https://docs.stackit.cloud/products/databases/postgresql-flex/) + + + +### CF-Hosting und Runner + +Web/API sowie Scheduler/Dispatcher laufen auf CF. Sessions und Jobs werden extern gespeichert. Mehrere Web-Instanzen, Health Checks, DB-Pooling und rückwärtskompatible DB-Migrationen vorsehen. SSE für Fortschritt/Chat, Polling als Rückfalloption; Proxy-Timeouts und Wiederverbindung testen. + +STACKIT dokumentiert für Prozesse/Tasks bis zu 32 GB RAM und 6 GB flüchtigen lokalen Speicher. Das lokale Dateisystem ist nicht persistent. Diese Grenzen sind besonders für Provider-Binaries, Firewall-Image und Plan-Artefakte zu prüfen. [Anwendungsanforderungen](https://docs.stackit.cloud/products/runtime/cloud-foundry/basics/requirements-for-applications/) + +CF Tasks laufen in eigenen Containern, erben aber Umgebungsvariablen, Bindings und Security Groups ihrer App. Deshalb **keine Terraform-Task der Backend-App** starten. Empfohlen ist eine eigene Runner-App ohne Backend-Bindings, bei Bedarf mit separaten Apps/Spaces pro Kunde. Ob dies die geforderte Isolation und private Erreichbarkeit bietet, ist durch Tests zu belegen. Logs von Tasks fließen in die App-Logs; Redaktion muss deshalb vor stdout/stderr erfolgen. [CF Tasks](https://docs.cloudfoundry.org/devguide/using-tasks.html) + +Falls CF-Ressourcenlimits, Netzwerk oder Isolation nicht genügen: isolierte Jobs auf SKE oder kurzlebige Compute-Runner. Für private Ziele gegebenenfalls Runner im Kundennetz mit ausgehender Verbindung zur Steuerung. Die Webanwendung bleibt auf CF. Diese Erweiterung benötigt eine explizite Architekturentscheidung. + +**Freigabekriterium:** Ein Runner erreicht weder andere Kunden-Secrets/States noch Model-Serving-Credentials oder die App-Datenbank. Eigener Ordner allein genügt nicht. Auch freigegebener Terraform-Code führt Provider und teilweise Skripte aus. + + + +## 4. Mandantenmodell und Berechtigungen + +Ein Tenant repräsentiert eine Kundenorganisation. Darunter liegen Workspaces, Repository-Verbindungen, Konfigurationen und Deployments. Benutzer können Mitglied mehrerer Tenants sein; der aktuelle Kontext muss im UI jederzeit sichtbar sein. GitHub-Organisation, App-Tenant und STACKIT-Organisation sind unterschiedliche Objekte mit expliziter Zuordnung. + +Empfehlung für den Start: gemeinsame PostgreSQL-Instanz mit `tenant_id` auf allen Kundenobjekten und Row-Level Security als zusätzliche Schutzschicht. Rollen und DB-Zugänge so gestalten, dass der Anwendungspfad RLS nicht umgeht. Separate Datenbanken/Instanzen für erhöhte Isolationsanforderungen als spätere Betriebsoption. Secrets, State, Artefakte, Queue, Caches und Chat-Verlauf brauchen dieselbe Trennung; ein DB-Filter alleine reicht nicht. + +- Tenant-Mitgliedschaft nur durch bestätigte Einladung/Administration oder verifizierte Organisationszuordnung; keine automatische Zuordnung anhand einer E-Mail-Domain. +- Rollen: Viewer, Editor, Deployer, Tenant-Admin. Credential-Nutzung wird zusätzlich autorisiert. +- GitHub-Rechte bei Repository-Aktionen weiterhin prüfen; eine App-Rolle erweitert keine GitHub-Berechtigung. +- Persönliche Credentials sind standardmäßig privat. Freigabe an Workspace oder Hintergrundjob braucht eine explizite, widerrufbare Delegation. +- Jeder Request und jeder Job wird serverseitig auf Tenant, Workspace und Objekt autorisiert. IDs im Request sind kein Berechtigungsnachweis. +- Rate Limits, aktive Runner, Queue-Anteil, Artefaktspeicher und KI-Budget pro Tenant begrenzen; kein Kunde darf alle Kapazitäten belegen. +- Betreiberzugriffe als nachvollziehbaren Notfallprozess gestalten. Keine normale Support-Oberfläche zur Anzeige von Kundensecrets. +- Bereits vor erster externer Freigabe Negativtests für horizontale Zugriffe, fremde Job-IDs, Artefakt-URLs, Cache-Schlüssel, Secret-Referenzen und Chat-Sessions. + + + +## 5. Benutzerablauf + +1. **Anmelden und Tenant wählen:** GitHub verbinden, eigenen Kundenkontext erstellen oder Einladung annehmen. +2. **Repository auswählen:** vorhandenen zugänglichen Fork auswählen oder einen neuen erstellen; Schreibrechte prüfen. +3. **Template kopieren:** Zielbild, Features, Grenzen und Voraussetzungen sehen; eigene Konfigurations-ID und Name vergeben. +4. **Gestalten:** Wizard oder Chat; beide arbeiten auf demselben fachlichen Modell. Topologie reagiert auf validierte Änderungen. +5. **Überprüfen und speichern:** Diff zeigen; Repository, Branch und Pfad sichtbar machen; Git-Commit oder optional PR erstellen. +6. **Deployment vorbereiten:** Zielorganisation, Region, Credential-Profil, Remote State und Runner-Netz prüfen. +7. **Plan:** feste Revision verwenden; Create/Update/Delete/Replace fachlich erklären. +8. **Apply:** konkreten Plan ausdrücklich freigeben; Fortschritt und Fehler verfolgen. +9. **Betrieb:** zuletzt erfolgreich ausgerollte Revision, letzten bekannten Ist-Stand und optionale Drift-Prüfungen sehen. + +Navigation: Dashboard, Templates, Konfigurationen, grafischer Editor mit Chat, Repository-Verbindungen, Deployment-Profile, persönliche Credentials, Runs/Drift und Tenant-Verwaltung. Begriffe wie „Netzwerkbereich“ ersetzen Terraform-Variablennamen im normalen Ablauf. Technische Details bleiben für Diagnose und Export verfügbar. + + + +## 6. GitHub und Login + + + +### Benutzergebundener Zugriff + +Empfehlung: GitHub App mit User Authorization und User Access Tokens. Jeder Benutzer autorisiert die App selbst. Repository-Aktionen nutzen ausschließlich seinen Token, keine Installation Tokens und keinen zentralen PAT. Die Rechte sind durch Benutzerrechte, App-Berechtigungen und Installation begrenzt. [Benutzerbezogene GitHub-App-Authentisierung](https://docs.github.com/en/enterprise-cloud%40latest/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-with-a-github-app-on-behalf-of-a-user) + +OAuth-State, sichere Callback-Allowlist, unterstütztes PKCE, CSRF-Schutz und sichere HttpOnly-/Secure-/SameSite-Sessions vorsehen. Tokens nur serverseitig im Secret Store halten. Ablauf, Refresh, Widerruf, SSO und Organisationsrichtlinien testen. Repo-Zugriffe nach Rechteentzug blockieren. Repositories über stabile GitHub-IDs referenzieren. + +**Wichtige Fork-Voraussetzung:** Laut GitHub benötigt das Fork-API bei GitHub Apps eine Installation am Zielaccount mit Zugriff auf alle Repositories sowie eine Installation am Quellaccount mit Zugriff auf das Quellrepo. Für diesen Endpunkt sind `Administration: write` und `Contents: read` angegeben. Die Erstellung läuft asynchron. Das ist ein zentraler Onboarding-Prüfpunkt, insbesondere für den Upstream `stackitcloud/stackit-landing-zone`. [Fork-API](https://docs.github.com/en/rest/repos/forks) + +Im Spike die vollständige Berechtigungsmatrix für Fork, Lesen, Branch/Commit und optional PR prüfen. Falls die nötige Quellinstallation oder Zielberechtigung nicht verfügbar ist: geführtes manuelles Forken in GitHub und anschließendes Verbinden; alternativ separat bewertete OAuth-App. Kein stiller Wechsel auf zentrale Credentials. Eine OAuth-App kann breitere Scopes benötigen; daher keine voreilige Festlegung nur aufgrund des einfacheren Fork-Ablaufs. [GitHub Apps und OAuth Apps](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps) + + + +### Mehrere Forks und Speichern + +Mehrere Repository-Verbindungen pro Benutzer/Tenant unterstützen, beispielsweise persönlicher Fork und Forks in berechtigten Organisationen. Nicht zusagen, dass beliebig viele echte Forks desselben Upstreams im selben Owner-Namespace möglich sind: die aktuelle Fork-Netzwerkgrenze im Spike prüfen. Mehrere Konfigurationen/Branches in einem Fork sind die bevorzugte Alternative; eine eigenständige Repository-Kopie wäre separat anzubieten und kein echter Fork. + +Fork-Erstellung idempotent behandeln, Bereitschaft pollen und Fehler verständlich anzeigen. Beim Speichern mehrere Dateien atomar committen und die erwartete Basisrevision prüfen. Konflikte nicht überschreiben. Geschützte Branches über Arbeitsbranch/PR bedienen. Webhooks signiert und idempotent verarbeiten; sie erlauben keinen automatischen Apply. + + + +### Optionaler STACKIT-IdP + +Die gefundene STACKIT-Anleitung beschreibt Federation, bei der STACKIT als Relying Party einem externen IdP vertraut. Sie belegt **nicht**, dass Kunden eine eigene Web-App unkompliziert als OIDC-Client des STACKIT-IdP registrieren können. Daher Client-Registrierung, Discovery, Claims und Nutzungsfreigabe separat klären. GitHub bleibt der initiale Login. [STACKIT-IdP-Einstieg](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/getting-started/) + +Zusätzlicher IdP-Login erteilt weder GitHub- noch Cloud-API-Rechte. GitHub-Verbindung bleibt nötig. Identitäten nur nach Nachweis beider Konten verknüpfen, niemals allein über gleiche E-Mail-Adressen. + + + +## 7. Fachmodell, Templates und Compiler + + + +### Versionierte Ablage + +Vorschlag für UI-Konfigurationen im ausgewählten Fork: + +```text +src/config/custom// + landing-zone.json # kanonisches Fachmodell, ohne Secrets + landing-zone.tfvars # deterministisch erzeugte Terraform-Eingaben + manifest.json # Schema-, Compiler-, Template-/Accelerator-Versionen +``` + +Das Fachmodell ist die Quelle für UI-verwaltete Konfigurationen. Die generierte Datei ermöglicht weiterhin CLI-Nutzung. Vor Runs neu kompilieren und Hash vergleichen; manuelle Änderungen an generierten Dateien als Konflikt behandeln. Originale `.tfvars` bleiben erhalten. Importbericht für unbekannte Felder und Kommentarverlust; keine stillschweigende Löschung nicht unterstützter Einstellungen. + +Manifest: Template-Pfad/-Commit, Accelerator-Commit/Release, Schema-/Compiler-Version und Content-Hashes. Deployment-Bindings und Secret-Referenzen liegen außerhalb von Git. DB-Entwürfe sind nicht „gespeichert“, bevor der Git-Commit erfolgreich war. Runs verwenden ausschließlich unveränderliche Git-Revisionen. + +Der Template-Katalog startet mit den acht Upstream-Dateien einer freigegebenen Version. Fork-spezifische Konfigurationen sind eigene Konfigurationen und nicht automatisch vertrauenswürdige globale Templates. Upstream-Updates zunächst als explizites Upgrade mit Diff und Migration anbieten. Rollback einer Konfiguration bedeutet neue Revision und neuen Plan, nicht automatischen Infrastruktur-Rollback. + + + +### Feature-Katalog + +| Fachbereich | Repo-Bezug | UI-Verhalten und Regeln | +| --- | --- | --- | +| Organisation | Owner, Firma/-code, Organisations-ID, Labels, Parent-Folder | Pflichtwerte, Platzhalter ersetzen, gültige Referenzen | +| Governance | `rm_folders`, Organisationseigentümer/-auditoren, Rollen | Hierarchie und Rollenmodell | +| Management | State-Bucket, Secrets Manager, Service Accounts, Federation | Bootstrap- und Betriebsidentität unterscheiden | +| Observability/Audit | `observability`, `audit_logs` | Retention, Zugriff, Folgen von Object Lock erklären | +| Konnektivität | `connectivity`, `connectivity_regions` | SNA, CIDRs, DNS, regionale Zuordnungen | +| Firewall/VPN | Firewall/HA, `firewall_config`, VPN | Erreichbarkeit, Bootstrap und Grenzen der Traffic-Inspektion | +| Landing Zones | `landing_zones`, Modul `landing-zone` | Projekte, Owner, Umgebung, RBAC, Netz, DNS, Buckets, Secrets | +| Kubernetes-Plattform | `platform_kubernetes` | Cluster, Node Pools, Netz, verschlüsselte Volumes, Bastion | +| Kubernetes-Services | `landing_zone_namespace_services`, Namespace-Demo, Root-Kubernetes-Ressourcen | Plattformabhängigkeiten und erreichbarer API-Endpunkt | +| DevOps | `devops` | Git-Service und zulässige Netzwerkbereiche | +| Sandboxes | `sandboxes` | Projekt und Owner | + +Jedes Feature erhält eine stabile ID, Fachtext, Mapping, Defaultwerte, Abhängigkeiten, Regionsgrenzen, Secret-Bedarf, Compiler-Regeln, Grafik-Semantik und Tests. Struktur teilweise aus HCL ableiten; Fachtexte/Abhängigkeiten explizit pflegen. CI meldet Änderungen an Variablen/Modulen ohne aktualisierten Katalog. + +Validierung: Referenzen zwischen Bereichen/Landing Zones/Clustern, Namensregeln, unterstützte Regionen und Kombinationen, CIDR-Konflikte in verbundenen Netzen. Wiederverwendete Adressbereiche in tatsächlich isolierten Netzen gesondert bewerten. Stabile Terraform-Ressourcenschlüssel erhalten; eine Umbenennung darf kein unsichtbares Destroy/Create erzeugen. + +Pro Feature getrennt kennzeichnen: **darstellbar, editierbar, planbar, ausführbar**. Ein importierbares Firewall-Template ist noch nicht vollständig automatisiert deploybar. + + + +### Grenze zum Terraform-Code + +Der Compiler erzeugt nur Daten, keine frei eingegebenen HCL-Ausdrücke oder Shell-Kommandos. Im MVP wird Accelerator-Code anhand eines freigegebenen Commits materialisiert; aus dem Benutzer-Fork werden nur erlaubte Konfigurationsdateien gelesen. Abweichende Module klar melden. Keine beliebigen `.auto.tfvars`, Provider, Backend-Dateien oder Skripte aus Forks implizit mitladen. + +Eigener Terraform-Code ist ein späterer Vertrauensmodus mit stärkerer Isolation und expliziten Provider-/Modul-/Netzrichtlinien. Die aktuelle Einschränkung sichtbar machen, weil das Repo grundsätzlich Modul-Anpassungen vorsieht. + + + +## 8. Credentials und Persistenz + +| Kategorie | Ablage / Eigentümer | Verwendung | +| --- | --- | --- | +| GitHub User-/Refresh-Token | Secret Store, persönlicher Benutzer | Repository-Zugriff im Benutzerauftrag | +| STACKIT Service Account Key bzw. unterstützte Federation | Persönliches oder explizit geteiltes Deployment-Profil | Zugeordnetes Kunden-Deployment | +| S3-Backend-Zugang | Deployment-Profil | Genau zugehöriger State-Bereich | +| VPN-PSKs, Firewall-Login/API-Key, ggf. Kubeconfig | Secret Store je Deployment | Nur benötigte Laufphase | +| Model-Serving-Token | Betreiber, CF-Variablen des Backends | Chat-Service | +| CF-/DB-/Secret-Betriebsidentität | Betreiber | Plattformbetrieb, keine Kunden-Cloud-Vollmacht | + +„Credentials anlegen“ bedeutet zuerst Profil erstellen und vorhandene Credentials sicher hinterlegen. Neue STACKIT-Service-Accounts/Schlüssel kann die App nur mit explizit delegierten Cloud-Rechten erzeugen; GitHub-Login genügt nicht. Später kurzlebige Federation bevorzugen, sofern die benötigten Flows unterstützt sind. + +STACKIT Secrets Manager auf Mandanten-Policies, Credential-Lifecycle und runbezogene Ausgabe prüfen. Keine Annahme, dass beliebige Vault-Features im Managed Service verfügbar sind. Bei fehlenden Fähigkeiten eine explizite Alternative entscheiden, z. B. tenantgetrennte Secret-Instanzen oder geprüfte Envelope-Verschlüsselung mit separat verwalteten Schlüsseln; kein unverschlüsselter DB-Fallback. + +Runner erhalten nur ein kurzlebiges, auf Run und Secret-Version begrenztes Ausgabeticket. Kein allgemeines Secret-Store-Token. Persönliche Profile zeigen Status, Zweck, Ablauf und „Ersetzen/Widerrufen“, keine Rohwerte. Rotation, Backup, Wiederherstellung und Notfallzugriff planen. + +`Sensitive`-Markierungen verhindern nicht, dass Terraform-State oder gespeicherte Plans Secrets enthalten. Diese Artefakte wie Secrets schützen. Browser, Git, Chat, Audit und normale Logs erhalten keine Roh-Secrets. Frei angegebene Endpoints gegen SSRF absichern; Zielnetze per Profil freigeben statt beliebige interne Adressen vom Backend anzusprechen. + + + +### Datenmodell + +Alle Kundenobjekte tragen `tenant_id`, gegebenenfalls `workspace_id`, serverseitig geprüft. + +| Entität | Inhalt | +| --- | --- | +| User / Identity / Session | Interne UUID, Provider-ID, verknüpfte Identitäten, Session-Lifecycle | +| Tenant / Workspace / Membership | Kundenkontext, Mitgliedschaft, Rollen und Einladungen | +| RepositoryConnection | GitHub-ID, Benutzerautorisierung, Branch, Zugriffsstatus | +| TemplateVersion | Pfad/Commit, Metadaten, unterstützte Features | +| Configuration / Revision | Fachmodell, Schema, Git-Ziel, Basis-SHA und Speicherstatus | +| CredentialProfile / Delegation | Secret-Referenz/-Version, Besitzer, erlaubte Nutzung, Ablauf | +| Deployment | Revision, Zielorganisation, Backend-/State-ID und Runner-Profil | +| Run / Approval / Artifact | Status, Manifest, Plan-Hash, Freigabe, Ergebnis und Artefaktreferenzen | +| DriftSchedule / DriftFinding | Opt-in, Referenzrevision, Prüfung und Korrekturpolicy | +| ChatSession / Proposal | Versionskontext, Rückfragen, Patch und Übernahmezustand | +| AuditEvent | Akteur, Aktion, Ressource, Zeit, Ergebnis; keine Secret-Werte | + +Retention getrennt für Chat, Logs, Plans, Audit und State festlegen. State niemals mit normaler Artefaktbereinigung löschen. Konto-/Konfigurationslöschung zerstört keine Infrastruktur; Offboarding umfasst Export von Konfiguration/State, Entzug von Zugängen und dokumentierte Löschung verbleibender Daten. + + + +## 9. Plan, Apply und State + + + +### Unveränderlicher Laufvertrag + +Jeder Run bindet Tenant, Deployment, Git-Commit, Config-Hash, Accelerator-Commit, Schema-/Compiler-Version, Engine-Version, Provider-Lockfile, Runner-Artefakt-Digest, Backend-/State-ID und relevante Credential-Versionen. + +```mermaid +stateDiagram-v2 + [*] --> Queued + Queued --> Preflight + Preflight --> Planning + Planning --> NoChanges + Planning --> AwaitingApproval + AwaitingApproval --> Applying: Konkreten Plan freigeben + AwaitingApproval --> Expired: Veraltet oder abgelaufen + Applying --> Succeeded + Applying --> Failed + Preflight --> Failed + Planning --> Failed + Queued --> Cancelled + AwaitingApproval --> Cancelled + Applying --> ReconciliationRequired: Prozessstatus unklar +``` + +1. Berechtigung, Profil, Kompatibilität, Quota, Backend und Erreichbarkeit prüfen. +2. Geprüften Code und genau eine ausgewählte Konfiguration materialisieren; Backend-Einstellungen ohne Secrets im Git erzeugen. +3. `init` mit festgelegtem Backend und gepinnten Providern; `validate` und Fach-/Policy-Prüfungen. +4. `plan -out= -detailed-exitcode`: 0 = keine Änderungen, 2 = Änderungen, 1 = Fehler. CLI-Vertrag mit gepinnter Engine testen. +5. `show -json` auswerten, sensible Werte anhand der Sensitivitätsmarkierungen und zusätzlicher Regeln redigieren. Roh-JSON nie direkt an Browser oder Chat geben. +6. Create/Update/Delete/Replace und unbekannte Werte zeigen; Auswirkungen auf Fachobjekte erklären. Kosten nur bei belastbarer Datenquelle als Schätzung kennzeichnen. +7. Freigabe an Plan-Hash und Manifest binden; Genehmiger und Zeitpunkt protokollieren. Tenant-Policy kann Vier-Augen-Freigabe verlangen. +8. Exakt den gespeicherten Binär-Plan mit gleicher Engine/Plattform anwenden. Geänderte Revision, State oder relevante Ausführungsbedingungen erfordern neuen Plan und neue Freigabe. +9. Ergebnis, State-Version und bereinigte Outputs persistieren; temporäre Secrets/Dateien entfernen. + +Plan-Gültigkeit begrenzen. Cloud-Änderungen außerhalb des Systems können während der Freigabezeit stattfinden; State-Vergleich allein erkennt nicht alles. Bei erkanntem Risiko neu planen. Kein unbemerkter Re-Plan zwischen Freigabe und Apply. + + + +### Remote State und Sperren + +Entscheidung 2026-09-30: dem vorhandenen LZA-Bootstrap folgen. Der erste Plan einer +expliziten Neuanlage verwendet lokalen leeren State und die bereits hinterlegten +Bootstrap-Credentials. Beim separat freigegebenen ersten Apply erstellt das Management- +Modul das spätere Kunden-Backend. Danach State exklusiv mit `tofu init -migrate-state` +migrieren, überprüfen und auf den Management-Service-Account wechseln. + +Der Configurator muss den anfänglichen State dauerhaft und verschlüsselt sichern, +auch bei Runner-Verlust und partiellem Apply. Diese Recovery ist Voraussetzung für +Apply. Vorhandene Deployments dürfen nie als neue leere States geplant werden. +Kein zusätzlicher dauerhafter zentraler Kunden-State-Bucket. Plattform-IaC und +Kunden-Deployments teilen niemals einen State. [Details](plan-execution.de.md). + +- Backend-Locking mit gewählter Engine und STACKIT Object Storage praktisch testen, einschließlich konkurrierendem CLI-Zugriff. S3-Kompatibilität ist kein Locking-Nachweis. +- Zusätzlich DB-Lease pro kanonischer State-ID; doppelte Deployment-Registrierung desselben States verhindern. Lease ersetzt Backend-Lock nicht. +- Versionierung, Verschlüsselung, Restore-Test und protokollierte manuelle Entsperrung vor Produktivfreigabe. +- Bei Runner-Absturz nicht blind erneut Apply ausführen. Prozessstatus, Lock und State abgleichen; gegebenenfalls neuen Plan erstellen. +- Apply kann teilweise erfolgreich sein. Kein automatischer Rollback; Wiederherstellung über neuen Plan. Abbruch ist best effort und kann Teiländerungen hinterlassen. +- Ein Deployment entspricht zunächst einem Accelerator-Root. Größere State-Aufteilung benötigt gesonderte Migrations- und Abhängigkeitsplanung. + + + +### Spezielle Runbooks + +Firewall-Bootstrap, Policy-Konfiguration, Secret-Übergabe, HA und gegebenenfalls Kubernetes-Provider-Bootstrap als versionierte Abläufe implementieren. Jede schreibende Phase mit verändertem Plan benötigt eine passende Freigabe. Kein UI für beliebige `-target`-Argumente. + +Für Firewall: Image-Herkunft/Prüfsumme, Speicherbedarf, Werkzeuge, private API-Erreichbarkeit, Passwortrotation und TLS-Verifikation testen. Abbruch während offenem Admin-Interface muss sichtbar sein und eine konkrete Absicherungs-/Wiederaufnahmeanleitung bieten. Ohne erfolgreichen Nachweis diese Variante nicht als automatisiert ausführbar freigeben. + + + +## 10. Drift Detection und Correction + +Pro Deployment: Aus, nur erkennen, nach Freigabe korrigieren, später eng begrenzte automatische Korrektur. Standard: Aus. Hintergrundnutzung von Credentials benötigt eine explizite widerrufbare Delegation, getrennt von einer interaktiven Session. + +- Referenz ist die zuletzt erfolgreich ausgerollte Git-/Accelerator-Revision, nicht der aktuelle Branch-Head. +- Refresh-only-Plan kann Unterschiede zwischen Cloud und State zeigen. Normaler Plan gegen dieselbe Revision zeigt die zur Soll-Wiederherstellung nötigen Änderungen. Beide Aussagen unterscheiden. +- Kein automatisches `apply -refresh-only`, um Befunde lediglich verschwinden zu lassen. +- Zeitpläne mit Jitter, Backoff, Mandantenquoten und Lauf-Sperren; keine Prüfung parallel zu schreibendem Run desselben States. +- API-Fehler oder abgelaufene Credentials bedeuten „Prüfung fehlgeschlagen“, nicht „keine Drift“. +- Correction stellt den genehmigten Sollzustand her. „Ist als Soll übernehmen“ ist separate Konfigurationsänderung mit Git-Commit und Review. +- Automatische Correction nur nach ausdrücklichem Opt-in mit testbarer Allowlist, Wartungsfenster, Ressourcenlimit, Audit und Not-Aus. +- Delete/Replace, IAM, Firewall-/Routing-Änderungen, Secret-Rotation und unbekannte Aktionen zunächst immer freigabepflichtig. +- Nach Fehlern pausieren statt Endlosschleife; neue Konfigurationsänderungen nie als Drift-Korrektur einschleusen. + + + +## 11. Chatbot mit STACKIT Model Serving + + + +### Bestätigte Produktentscheidungen (2026-10-10) + +- Umfang: alle tatsächlich implementierten Configurator-Features werden dauerhaft 1:1 von der KI-Komponente abgedeckt, einschließlich komplexer Komponenten und ihrer Abhängigkeiten; nicht sämtliche STACKIT-Services. Eine versionsgebundene Abdeckungsmatrix macht Unterstützung und Ausführungsgrenzen sichtbar. Neue oder geänderte Features benötigen entsprechende Wissens-, Dialog-, Validierungs- und Testabdeckung im selben qualifizierten Release; bestehende Ausführungssperren werden dadurch nicht aufgehoben. +- Dialog: passende Konfigurationsvorlage auswählen, Wünsche schrittweise ergänzen und fehlende Details oder Widersprüche gezielt nachfragen. Vollständigkeit wird durch Schema und Fachregeln geprüft, nicht allein durch das Modell behauptet. +- Templates: vorhandene autorisierte Application Landing Zone Templates auswählen und neue Template-Entwürfe erstellen. Veröffentlichung bleibt eine separate Aktion berechtigter Platform Engineers. +- Bestandsänderungen: bestehende Konfiguration analysieren und revisionsgebundene Vorschläge im Chat-Arbeitsentwurf sammeln. Erst ein ausdrücklich bestätigter Gesamt-Diff ändert den Konfigurationsentwurf; keine automatische Änderung veröffentlichter Templates oder bestehender Instanzen. +- Wissen: aktuelle offizielle STACKIT-Informationen kontrolliert einlesen, Änderungen automatisch erkennen und vor Nutzung geprüft freigeben. Modul-, Provider- und Configurator-Wissen bleibt an die jeweilige Konfigurationsversion gebunden. Keine automatischen Upgrades und kein beliebiger Webzugriff durch das Modell. +- Modell: `Qwen/Qwen3-VL-235B-A22B-Instruct-FP8` als bevorzugter Startwert; Modell, Endpoint und technische Limits bleiben betreiberseitig konfigurierbar. Der vorhandene Terraform-provisionierte Dev-Token wird ausschließlich backendseitig verwendet. +- Eingaben: Text und Konfigurationen; keine Bilder im MVP. +- Scope-Entscheidung 2026-10-13: Geführte Firewall-Policy-Bearbeitung und + Assistant-Vorschläge für Regeln/NAT/Aliase/Routen sind Post-MVP + ([#101](https://github.com/stackitcloud/stackit-landing-zone/issues/101)). + Der Assistant benennt diese Grenze sofort; im MVP pflegt der Firewall-Admin + die Policy nach Bereitstellung manuell in OPNsense. Generische native + Editorfelder bleiben erhalten, sind aber kein Ausführungsnachweis. + Firewall-Infrastruktur/HA bleibt im Scope und garantiert allein keine + Isolation, Erreichbarkeit oder NAT. +- Zugang und Zweck: ausschließlich angemeldete Benutzer mit aktuell gültiger Session und passenden Tenant-/Konfigurationsrechten. Beratung und Vorschläge sind auf die oben genannten Configurator-Aufgaben beschränkt; serverseitige Werkzeug-, Schema- und Rechteprüfungen erzwingen diese Grenze. Keine allgemeine Chat-, Shell-, Secret- oder Cloud-Ausführungsfunktion. +- Budget: keine monetäre Budgetgrenze im MVP. Begrenzte Requestgrößen, Kontext-/Ausgabelängen, Parallelität, Anfrageraten, Timeouts und Reparaturversuche bleiben zum Missbrauchs- und Betriebsschutz erforderlich. Verbrauch wird secretfrei beobachtet. +- Gespräche: serverseitig persistent und nach erneuter Anmeldung fortsetzbar, mit verpflichtendem Bezug zu Tenant, Workspace und Konfiguration. Zugriff wird bei jedem Lesen, Fortsetzen und Übernehmen erneut geprüft. Die gebundene Ausgangsrevision wird mit der aktuellen Konfiguration abgeglichen; veraltete Vorschläge werden nicht ungeprüft übernommen. +- Löschung und Alter: Löschen einer Konfiguration oder ihres Workspaces löscht die zugehörigen Gespräche samt Nachrichten, Zusammenfassungen und Vorschlägen mit; keine verwaisten Gesprächsdaten. Maximales Gesprächsalter sind drei Kalendermonate ab Erstellung, nicht ab letzter Aktivität. Fortsetzen verlängert die Frist nicht. Nach Ablauf kann die weiterhin vorhandene Konfiguration in einem neuen Gespräch erneut analysiert werden. +- Lastziel: höchstens fünf gleichzeitige Chat-Sitzungen für die MVP-Abnahme. Dies ist kein Limit für die Anzahl gespeicherter Gespräche. Inferenzparallelität, begrenzte Warteschlange und Timeouts berücksichtigen zusätzlich die tatsächlichen Model-Serving-Limits. + +Die fachliche Abnahme umfasst jedes implementierte Feature 1:1, nicht nur ausgewählte Beispielvorlagen. Konkrete Referenzkonfigurationen und messbare Antwortzeitziele werden beim Modell-Spike und Aufbau der Feature-Matrix präzisiert. Eine vorläufige Schätzung für den Gesamtumfang beträgt 30–50 Engineering-Personentage einschließlich Tests und Dokumentation, ohne externe Wartezeiten oder zusätzliche fehlende Modul-/Compiler-Funktionen. Die Modell- und Komponentenqualifikation muss diese Spanne einschließlich vollständiger Feature-Abdeckung verfeinern. Der Konzeptbeschluss ist kein Implementierungs- oder Inferenznachweis. + + + +### Gesprächslebenszyklus und Abnahme + +Die konkrete [Feature-Matrix und Dialogabnahme](assistant-feature-coverage.de.md) umfasst alle 29 aktuellen Root-Eingaben, 501 Feld-/Containerpfade, acht Funktionsgruppen, fünf übergreifende Workflow-Bereiche und 24 Szenarien. Die [generierte Matrix](assistant-feature-coverage.json) enthält neun geschützte Feld-/Containerpfade ohne Secret-Werte; jeder Eintrag bleibt bis zum tatsächlichen Modellnachweis `not-qualified`. Ihr Frischetest ist in die bestehende Unit-Suite integriert. Dies ist der erste qualifizierte Konzeptschritt, nicht die Implementierung des Assistenten. + +Persistierter Gesprächszustand ist von der kurzlebigen Login-Session und vom begrenzten Modellkontext getrennt. Nach Wiederanmeldung werden nur aktuell autorisierte, nicht gelöschte und nicht abgelaufene Gespräche geladen. Vor der Vorlagenauswahl wird bei Bedarf ein regulärer autorisierter Konfigurationsentwurf angelegt; auch ein neues Gespräch bleibt damit an einen Workspace und eine Konfiguration gebunden. Ohne gültiges Elternobjekt ist kein Chat-Zugriff möglich. + +Der Löschpfad muss Nachrichten, Gesprächs-Arbeitsentwürfe, Zusammenfassungen und abgeleitete Cache-/Indexdaten berücksichtigen. Autorisierte Elternlöschung und die Löschung persistierter Gesprächsdaten sind atomar; verspätete Modellantworten dürfen gelöschte oder abgelaufene Gespräche nicht wiederherstellen. Ablauf wird vor jedem Zugriff geprüft und durch einen überwachten Bereinigungsprozess physisch umgesetzt. Logs enthalten keine Gesprächsinhalte. Backup-Aufbewahrung und Restore müssen die Lösch- und Altersgrenzen erhalten; vor erneutem Zugriff nach Restore werden gelöschte und abgelaufene Daten entfernt. Ein Datenbank-Cascade allein ist kein Nachweis der Löschung aller Kopien. + +Erforderliche Tests: Fortsetzung nach Wiederanmeldung oder Backend-Neustart, Workspace-/Konfigurations- und Tenant-Isolation, aktueller Rechteentzug, Konfigurationsrevision-Konflikte, beide Elternlöschpfade einschließlich laufender Inferenz, feste Drei-Monats-Grenze ohne Aktivitätsverlängerung und bereinigter Restore. Fünf parallele Sitzungen dürfen weder Kontexte vermischen noch stille Requestverluste oder unbegrenzte Warteschlangen verursachen. + +Die Abdeckungsmatrix ordnet jedem implementierten Feature mindestens Analyse, Neuerstellung/Änderung soweit vom Editor unterstützt, fehlende Angaben, Abhängigkeiten, validierten Diff und passende Negativfälle zu. Gemeinsame Schema-/Compilerprüfungen bleiben maßgeblich. CI/Release prüfen fehlende Zuordnungen und Tests; reale Modell-Evaluationen qualifizieren zusätzlich die Dialogqualität, denn eine vollständige Matrix allein beweist keine zuverlässigen Antworten. + + + +### Fachlicher Vertrag + +Der Chat behandelt ausschließlich Planung und Konfiguration des versionsgebundenen Accelerators. Er erklärt Features und Grenzen, fragt aktiv fehlende Informationen ab und erzeugt überprüfbare Änderungen. Außerhalb dieses Bereichs führt er zum unterstützten Thema zurück. + +Wissen: Feature-Katalog, Schema, freigegebene Repo-/Moduldokumentation und Templates der gewählten Version. Kein beliebiger Web-/Repository-Zugriff. Dokumentverweise in Antworten; unbekannte Features nicht erfinden. Systemprompt alleine garantiert die Einschränkung nicht: Tool- und Datenzugriffe im Backend erzwingen. + +Ablauf: + +1. Benutzer beschreibt sein Ziel. +2. Backend liefert minimale secretfreie Konfiguration und relevante versionierte Wissensabschnitte. +3. Chat fragt notwendige Angaben ab: Owner, Organisation, Regionen, Isolation, Netzplanung. Widersprüche erklären, etwa getrennte SNAs bei gleichzeitig gewünschtem gemeinsamen privaten Git-Service. +4. Modell erzeugt `questions`, `assumptions`, `patch`, `explanation`, `references`. +5. Backend prüft Schema/Fachregeln und Basisrevision des Patches. +6. UI zeigt Diff und Topologie-Vorschau. Erst „Übernehmen“ ändert den Entwurf; Git-Speichern, Plan und Apply sind separate Aktionen. + +Erlaubte interne Werkzeuge: Features nachschlagen, bereinigte Konfiguration lesen, Patch vorschlagen/validieren. Kein Secret-Lesen, Shell, Git-Schreiben oder Apply durch das Modell. Repo-Kommentare und Freitext gelten als untrusted input. Keine fremden Tenant-Daten, Credentials, States oder Roh-Plans im Modellkontext. + + + +### Anbindung und Betrieb + +STACKIT dokumentiert eine OpenAI-kompatible Inferenz-API mit Auth-Token. Die API hält keinen Gesprächszustand; das Backend verwaltet den nötigen Kontext selbst. [Modelle verwenden](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/how-tos/use-the-models/) + +Voraussetzung: STACKIT-Projekt mit aktiviertem AI Model Serving, ausgewähltem Modell, Kapazität und Inferenz-Token. Token-Erzeugung benötigt eine separate STACKIT-Autorisierung; Inferenz-Token nicht mit allgemeinen STACKIT-Credentials verwechseln. [Auth-Tokens](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/how-tos/manage-auth-tokens/) + +Vorgeschlagene app-eigene CF-Variablen: + +```text +MODEL_SERVING_BASE_URL +MODEL_SERVING_MODEL +MODEL_SERVING_API_KEY +MODEL_SERVING_TIMEOUT_SECONDS +``` + +Der dokumentierte Shared-Model-Einstieg verwendet `https://api.openai-compat.model-serving.eu01.onstackit.cloud/v1/chat/completions`. Endpoint/Modell aus der gewählten Service-Konfiguration übernehmen; nicht den Management-API-Endpoint für Inferenz nutzen. Modellfähigkeiten wie Tool Calling/strukturierte Ausgabe separat evaluieren. [Shared Models starten](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/getting-started/getting-started-with-shared-models/) + +Credentials ausschließlich auf Backend/Chat-App setzen, nie ins Frontend-Build oder Runner. CF-Umgebungsvariablen sind für entsprechend berechtigte Space-Developer lesbar; diese gehören damit zur Betreiber-Vertrauensgrenze. Über geschützte Deployment-Injektion setzen, nicht in Git-Manifeste schreiben; Rotation und Redaktion testen. [CF-Variablen und Secrets](https://docs.stackit.cloud/products/runtime/cloud-foundry/how-tos/manage-environment-variables-and-secrets/) + +Technische Token-/Anfragelimits pro Tenant, Timeouts, begrenzte Reparaturversuche für ungültiges JSON und Circuit Breaker; keine monetäre Budgetgrenze im MVP. Bei KI-Ausfall bleibt der manuelle Editor nutzbar. Gesprächsaufbewahrung, Löschung und übermittelte Organisationsdaten transparent machen. Tenant-Chatdaten nicht in einen gemeinsamen Wissensindex übernehmen. + +Evaluationsfälle: fehlende Pflichtfelder, widersprüchliche Netze, unbekannte Features, Themenwechsel, Prompt Injection, Secret-Offenlegung, fremde Tenants, veraltete Revisionen und ungültige Ausgabe. Der Chat gilt erst mit gemessenen Akzeptanzkriterien als freigegeben. + + + +## 12. Grafische Darstellung + +Ein deterministischer Graph-Builder verwendet dasselbe validierte Fachmodell wie der Compiler. Kein frei vom Sprachmodell gezeichnetes Infrastrukturdiagramm. + +- Gruppierung: Organisation → Region → Netzwerkbereich → Projekte/Landing Zones → Dienste. +- Knoten für Management, DevOps, Plattformcluster, Firewall, VPN, DNS und Sandboxes. +- Kanten für echte Beziehungen: SNA-Anbindung, Default Route, Cluster-Zuordnung, explizite VPN-Verbindung. Keine impliziten Verbindungen zwischen SNAs/Regionen. +- Getrennte Ansichten: Konfigurations-Soll, Plan-Delta und zuletzt bekannter Ist-/State-Stand mit Zeitstempel. State ist kein Echtzeit-Monitoring. +- Create/Update/Delete/Replace sowie unbekannte Werte durch Symbol und Farbe markieren. +- Plan-Ressourcen über versioniertes Mapping Features zuordnen; nicht zuordenbare Ressourcen bleiben technisch sichtbar. +- Knoten öffnen Fachformulare. Freies Zeichnen von Beziehungen erst später mit denselben Validierungsregeln. +- Tastaturbedienbare Listen-/Tabellenalternative; secretfreier Grafikexport als Ausbau. + + + +## 13. IaC, Lieferung und Betrieb + +Das getrennte Verzeichnisgerüst und die lokale App-Entwicklungsbasis sind angelegt; Bootstrap-, Backend- und Plattform-IaC sind implementiert; noch kein Cloud-Apply. Details stehen in der [Configurator-README](../README.de.md). Die [Sprachentscheidung](decisions/0001-application-stack.de.md) ist als angenommen dokumentiert. + +```text +landing-zone-configurator/ + app/apps/{web,api,worker}/ + app/packages/{domain,contracts}/ + tools/hcl-adapter/ + runner/ + infra/{bootstrap,backend,platform,modules,environments}/ + deploy/cloud-foundry/ + docs/decisions/ +``` + +Die lokal bereitgestellten Dateien `landing-zone-configurator.env` und `landing-zone-configurator-credentials.json` bleiben im Repository-Root und sind von Git ausgeschlossen. Sie betreffen die Betreiberplattform, nicht Kunden-Deployments. Werte nicht in Dokumentation, Manifeste oder Git übernehmen. Die `.env` verwendet nach Benutzerkorrektur das geprüfte `NAME=WERT`-Format. Erkannte Variablennamen: `PROJECT_ID`, `ORGANISATION_ID`. Vor IaC-Nutzung das Mapping zu den Plattformvariablen festlegen. Zielprojekt-Lesezugriff und ausgewählte Dienst-Metadaten wurden geprüft; Schreibrechte sind noch nicht nachgewiesen. Siehe [Plattformprüfung](platform-check.de.md). + +App-Infrastruktur und Kunden-Landing-Zones haben getrennte States, Credentials und Release-Zyklen. Die App darf nicht von einer Landing Zone abhängen, die erst durch dieselbe App erzeugt werden müsste. STACKIT dokumentiert CF-Provisionierung via Terraform; die konkrete Ressourcenabdeckung ist dennoch im Spike nachzuweisen. [CF mit Terraform](https://docs.stackit.cloud/products/runtime/cloud-foundry/how-tos/provision-cloud-foundry-via-terraform/) + + + +### Plattformaufbau + +- [ ] Betreiberprojekt, Region, CF-Org/-Spaces, Quoten und Betriebsrollen festlegen. +- [ ] Plattform-Remote-State und Bootstrap-Identität vorab provisionieren; anschließend eingeschränkte Betriebsidentität. +- [ ] CF-Apps/Prozesse, Routes, Domain/TLS, Bindings, Health Checks und Skalierung deklarieren. +- [ ] PostgreSQL Flex, Secret Store, Artefakt-Buckets, IAM, ACLs/Netzregeln und Monitoring provisionieren. +- [ ] Model Serving aktivieren/provisionieren oder vorhandenen Service explizit anbinden; Provider-/API-Abdeckung prüfen. +- [ ] Runner und gegebenenfalls kundenspezifische Netzverbindung über eigene Module bereitstellen. +- [ ] GitHub App, Callback-/Webhook-URLs und Schlüssel verwalten; nicht automatisierbare Registrierungsschritte dokumentieren. +- [ ] Provider-Versionen pinnen; fehlende Ressourcen nur über dokumentierte idempotente API-/CLI-Schritte ergänzen. +- [ ] Secrets geschützt in CF injizieren. `sensitive = true` verhindert keine Aufnahme in Terraform-State; Secret-Werte möglichst nicht durch IaC-Ressourcenparameter schleusen. +- [ ] Entwicklungs-, Staging- und Produktionsumgebung trennen; keine Kundensecrets in Entwicklung. + + + +### CI/CD und Betrieb + +- [ ] Parser-/Compiler-Fixtures für alle acht Templates; semantischer Import-/Export-Vergleich. +- [ ] Fachregeln, Versionsmigrationen und Feature-Abdeckung prüfen. +- [ ] Autorisierungs-, RLS-, Runner-Isolations- und Secret-Redaktionstests. +- [ ] Dependency-/Image-Scans, reproduzierbare Builds, IaC-Validate und Staging-Smoke-Test. +- [ ] Gepinnte Engine/Provider mit realer Testorganisation qualifizieren; bestehende Repo-Tests benötigen teilweise STACKIT-API-Zugriff. +- [ ] Blue/green oder getesteter CF-Rollout; rückwärtskompatible DB-Migrationen und App-Rollback. +- [ ] Backup/Restore von DB, Secrets und State einschließlich benötigter Schlüssel praktisch üben. +- [ ] CF-Restart, verlorenen Runner, DB-Ausfall, Token-Widerruf und teilweise fehlgeschlagenen Apply testen. +- [ ] Metriken: Queue-Alter, Runner-Heartbeat, Fehlerquoten, Plan-/Apply-Dauer, Drift-Fehler, KI-Verbrauch und Mandantenquoten. +- [ ] RPO/RTO, Verfügbarkeit, Retention, Budget, Supportwege und Notfallzugriffe vor erster Kundenfreigabe festlegen. + + + +## 14. Roadmap und Abnahme + +Mehrmandantenfähigkeit ist Teil jeder Phase. Funktionsumfang kann schrittweise wachsen; Kundenisolation darf nicht auf eine spätere Phase verschoben werden. Aufwand und Termine erst nach Spikes und Teamzuschnitt schätzen. + + + +### P0 – Machbarkeit und verbindliche Entscheidungen + + + +#### Entwicklungsbasis – erster abgeschlossener Schritt + +- [x] Stack bestätigen und Runtime-/Paketversionen pinnen. +- [x] Eigenen npm-Workspace mit Lockfile, React/Vite und Fastify anlegen. +- [x] Gemeinsame Verträge und initiale Tenant-/Rollen-Policy anlegen. +- [x] Lokales Linting, Typecheck, Build und fünf Tests erfolgreich ausführen. +- [x] Separate Configurator-CI als Workflow anlegen (noch nicht auf GitHub ausgeführt). +- [x] Plattform lesend prüfen und Grenzen/Ergebnisse dokumentieren. +- [ ] Vollständige Sessions, DB/RLS und tenantgetrennte Persistenz implementieren. + +Diese Basis ersetzt keinen der folgenden Architektur-Spikes. Details zum Start: [Entwicklungsanleitung](../app/README.de.md). + +- [x] Anforderungen, Repo-Ausgangslage und Architekturentwurf dokumentieren. +- [x] Mehrere unabhängige Kunden ab Beginn und zunächst nur Konfigurationsänderungen bestätigen. +- [ ] GitHub-Spike: User Token, Upstream-/Zielinstallation, Fork, mehrere Owner, Commit/PR, Widerruf und Refresh. +- [ ] CF-Runner-Spike: Isolation, Limits, Abbruch, Secret-Übergabe und private Ziele. +- [ ] State-Spike: erster Run, echtes Locking, konkurrierender CLI-Zugriff, Restore. +- [ ] Secret-Store-Spike: Policies, Mandantentrennung, Rotation und Delegation. +- [ ] Service-Pläne, Regionen, IaC-Ressourcenabdeckung und optionalen IdP klären. +- [ ] Model-Serving-Spike: Auth, Modell, strukturierte Vorschläge, Limits und Evaluation. + +**Abnahme:** Kritische Annahmen sind belegt oder durch beschlossene Alternativen ersetzt. Architekturentscheidungen mit Nachweisen erfassen. + + + +### P1 – Mandanten, GitHub, Templates und Editor + +- [ ] Tenant-Onboarding, Rollen, Einladungen, Sessions und serverseitige Objekt-Autorisierung. +- [ ] Repository-Auswahl, Fork-Flow und konkurrierendes Speichern. +- [ ] Alle acht Templates katalogisieren, importieren und Unterstützung kennzeichnen. +- [ ] Fachmodell/Compiler und Editor zunächst für Standalone und einfaches Hub-Spoke vollständig umsetzen. +- [ ] Soll-Topologie, Entwürfe, Git-Versionierung und Upgrade-Metadaten. +- [ ] Negativtests gegen fremde Mandanten und Verlust von Feldern beim Import. + +**Abnahme:** Template kopieren → fachlich ändern → Grafik prüfen → im ausgewählten Fork speichern → semantisch unverändert laden. Keine Secrets im Commit und kein Überschreiben fremder Änderungen. + + + +### P2 – Sichere Deployments und Betriebsgrundlage + +- [ ] Staging-/Produktionsgrundlage per IaC, Backups und Observability. +- [x] Persönliche Credential-Profile: Upload, Secrets-Manager-Ablage, eigene Metadaten und Löschung implementieren. +- [x] STACKIT-Anmeldung und Organisations-Lesezugriff prüfen; Ergebnis pro Profil speichern. +- [x] Gespeicherte Git-Konfiguration, Organisation, Code-Referenz und Secret-Version in einer Vorbereitung binden. +- [ ] Weitergehende Deployment-Rechte, Delegationen und kundenbezogener Remote State. +- [ ] Runner, Queue, Manifest, Plan-Redaktion, Freigabe und exakter Apply. +- [ ] Standalone und einfaches Hub-Spoke in getrennten Testorganisationen ausführen. +- [ ] Isolation, Quoten, Crash, Abbruch, Rechteentzug, Restore und partielle Fehler prüfen. + +**Abnahme:** Mindestens zwei unabhängige Testkunden können getrennt arbeiten. Fremde Daten/Secrets sind unerreichbar; veraltete Plans werden abgewiesen; Runner-Ausfall erzeugt keinen blinden zweiten Apply. Betriebsziele und Runbooks sind festgelegt. + + + +### P3 – Chat und vollständige Feature-Abdeckung + +- [ ] Model Serving mit Rückfragen, Schema-Patches, Diff und Übernahme integrieren. +- [ ] Versioniertes Wissen und Evaluationssuite. +- [ ] Multi-Area, Multi-Region, Kubernetes, Firewall/HA/VPN und weitere Services abdecken. +- [ ] Spezielle Bootstrap-Abläufe und Netzkonnektivität nachweisen. +- [ ] Plan-Delta und bekannten Ist-Stand grafisch zeigen. + +**Abnahme:** Chat und Formular erzeugen äquivalente validierte Konfigurationen. Alle Templates haben nachvollziehbaren Unterstützungsstatus. Repo-Grenzen bleiben sichtbar; keine frei erfundenen Features und kein Apply durch Chat. + + + +### P4 – Optionaler Betriebsausbau + +- [ ] Drift Detection mit expliziter Hintergrunddelegation und Statusmeldungen. +- [ ] Correction nach Freigabe, später enge automatische Allowlist mit Not-Aus. +- [ ] Optional STACKIT-IdP nach Machbarkeitsnachweis. +- [ ] Eigener Terraform-Code erst nach gesonderter Sicherheits-/Runner-Entscheidung. +- [ ] Erweiterte Teamprozesse, Audit-Export und kundenspezifische Isolationsoptionen. + +**Abnahme:** Automatische Korrektur hält ihre Policy auch bei unbekannten oder destruktiven Plans ein. Ausfall/Widerruf führt zu kontrollierter Pause statt unkontrollierten Wiederholungen. + + + +## 15. Entscheidungsregister + +| ID | Entscheidung | Empfehlung / Ergebnis | Status | Owner | +| --- | --- | --- | --- | --- | +| D01 | Zielgruppe | Mehrere unabhängige Kundenorganisationen ab Beginn | Bestätigt | Produkt | +| D02 | Terraform-Modifikationen | V1 nur Konfigurationen, eigener Code später | Bestätigt | Produkt | +| D03 | GitHub-Integration | GitHub App mit User Token; Fork-Voraussetzungen nachweisen | Offen | Backend | +| D04 | Mehrere Forks | Mehrere Owner/Repos; Branches/Configs als zusätzliche Varianten | Spike | Produkt/Backend | +| D05 | Persistenz | PostgreSQL Flex, Tenant-Isolation plus RLS | Vorschlag | Plattform | +| D06 | Runner-Hosting | Separate CF-Runner, sonst explizit SKE/Compute | Kritischer Spike | Plattform/Security | +| D07 | State-Eigentum | LZA-Bootstrap, anschließend Migration zum erzeugten Kunden-Backend | Entschieden; Recovery/Migration umzusetzen | Architektur | +| D08 | Secret-Verwaltung | Secret Store mit Run-Delegation und Tenant-Policies | Kritischer Spike | Security | +| D09 | Config-Format | Fach-JSON plus native landing-zone.tfvars | Standalone implementiert; versioniertes Deployment-Manifest offen | Architektur | +| D10 | Engine | Gepinntes OpenTofu 1.12.6 zuerst; Terraform separat qualifizieren | Vorschlag | Maintainer | +| D11 | STACKIT-IdP | Optional, Client-Registrierung nicht nachgewiesen | Offen | IAM | +| D12 | Drift Correction | Freigabe zuerst, automatische Allowlist später | Vorschlag | Produkt/Betrieb | +| D13 | KI-Modell | STACKIT-Service mit evaluiertem Modell und Tenant-Limits | Spike | KI/Produkt | +| D14 | Betriebsziele | RPO/RTO, Retention, Verfügbarkeit und Budget vor Kundenfreigabe | Offen | Betrieb | +| D15 | Produktname und Struktur | Landing Zone Configurator unter eigenem Top-Level-Verzeichnis | Bestätigt / Gerüst angelegt | Produkt | +| D16 | Anwendungssprache | TypeScript für Web/API/Worker; Go für begrenzten HCL-Adapter | Bestätigt, siehe ADR 0001 | Entwicklung | +| D17 | Dienstbereitstellung | Sämtliche Configurator-Dienste und Aktivierungen via IaC | Bestätigt | Plattform | +| D18 | Erste Umgebung | lzc-dev in eu01; Backend-Zugang zunächst ca. 90 Tage | Umgebung bestätigt; Laufzeit als Betriebsdefault | Plattform | + + + +## 16. Risiken und Definition of Done + +| Risiko | Gegenmaßnahme / Nachweis | +| --- | --- | +| Tenant-übergreifender Zugriff | RLS plus Objekt-Autorisierung, getrennte Secrets/States, Negativtests | +| Runner liest Betreiber-Secrets | Keine Backend-Bindings; gezielter Isolationstest | +| Fork-API passt nicht zum Onboarding | Früher GitHub-Spike; manueller Fork-/Connect-Flow als klare Alternative | +| UI und Terraform divergieren | Versionierter Katalog, Compiler-Fixtures und Migrationsprüfungen | +| Secret in Plan/State/Log/Chat | Geschützte Artefakte, Redaktion vor Logging, negative Tests | +| Private API aus CF unerreichbar | Netz-Spike, dediziertes Runner-Profil im Zielnetz | +| Zwei Prozesse schreiben denselben State | Backend-Lock plus kanonische State-ID und Plattform-Lease | +| Initial offene Firewall | Sicherer Bootstrap, Passwortrotation und Fehler-Runbook vor Freigabe | +| Unerwartetes Destroy/Create | Stabile Schlüssel, sichtbare Ersetzungen und konkrete Plan-Freigabe | +| Kunden blockieren gegenseitig Kapazitäten | Tenant-Quoten, faire Queue, Rate Limits und Backoff | +| KI missachtet Thema/Schema | Backend erzwingt Tools und Datenzugriffe; Evaluation und Fallback | +| Backup nicht wiederherstellbar | Restore-Übungen einschließlich Schlüsselmaterial | + +Für jedes Feature: + +- [ ] Fachliches Verhalten, Mapping und Grenzen dokumentiert. +- [ ] Editor, Chat, Compiler und Grafik nutzen dieselbe Semantik. +- [ ] Autorisierung, Mandantentrennung und relevante Fehlerfälle geprüft. +- [ ] Keine Secrets in Git, Frontend oder ungeschützten Artefakten. +- [ ] Migration und Betrieb dokumentiert, sofern erforderlich. +- [ ] Akzeptanznachweis und Issue-/PR-Link hinterlegt. + + + +## 17. Quellenstatus und laufende Planung + +Lokale Analyse: Repo-Stand `2161871`. Externe Primärquellen wurden am 2026-09-29 nach Wiederherstellung des Netzwerkzugriffs geprüft und direkt an den relevanten Aussagen verlinkt. Dokumentation ersetzt keine Integrationstests. Offen bleiben insbesondere konkrete Service-Pläne/-Quoten, die GitHub-Fork-UX, Secret-Policies, S3-Locking, private Runner-Konnektivität und STACKIT-IdP-Client-Registrierung. Object Storage und Model Serving werden durch ihre Provider-Ressourcen automatisch aktiviert; der frühere 404 ist damit geklärt. + +**Nächster Planungsschritt:** P0-Spikes für GitHub, Runner/Netz, State und Secrets priorisieren und Verantwortliche zuweisen. Danach D03/D06/D07/D08 entscheiden und den ersten vertikalen Ablauf von Login bis freigegebenem Apply schätzen. + +| Datum | Ergebnis / Entscheidung | Verantwortlich | Nachweis | +| --- | --- | --- | --- | +| 2026-09-29 | Architekturentwurf und Repo-Feature-Mapping erstellt | Noch zuzuweisen | Dieses Dokument | +| 2026-09-29 | Mehrere unabhängige Kunden ab Beginn; V1 nur Konfigurationen | Benutzerentscheidung | Planungsgespräch, D01/D02 | +| 2026-09-29 | TypeScript/React/Fastify bestätigt; lokale Entwicklungsbasis und getrennte CI angelegt | Entwicklung | ADR 0001, App-Workspace | +| 2026-09-29 | Object Storage 404 als nicht aktiviert geklärt; Provider aktiviert bei erstem Bucket | Entwicklung | platform-check.md | +| 2026-09-29 | lzc-dev/eu01 bestätigt; erster echter Bootstrap-Plan mit 3 Create erfolgreich | Benutzer / Entwicklung | infra/README.md | + +Vorlage für laufende Arbeitspakete: + +```markdown +### : +- Status: offen / in Arbeit / blockiert / erledigt +- Owner: +- Ziel und Abnahmekriterium: +- Abhängigkeiten / Entscheidungen: +- Aufwand / Zieltermin: +- Issue / PR: +- [ ] Umsetzung +- [ ] Relevante Prüfungen und Abnahmenachweis +- [ ] Dokumentation und Betrieb +``` + + + +## 18. CI/CD nach Lebenszyklus + +Das [CI/CD-Konzept](cicd.de.md) definiert getrennte Workflows für seltenen Bootstrap, Plattformänderungen, häufige App-Releases und optionale Drift-Erkennung. Es enthält State-/Secret-Abhängigkeiten, Lifecycle-Ownership und eine abhakbare Umsetzungsreihenfolge. Deployment-Workflows sind geplant; die Validierungs-CI besteht bereits. Nächster technischer Schritt: unabhängiges Verwaltungs-Backend und sichere CI-Schlüsselhaltung vor dem ersten Cloud-Apply. + +Verwaltungs-Backend: separater Bucket im bestehenden Projekt durch `seed`/`seed-protection` angelegt. Bootstrap an S3 angebunden; CI-Schlüsselübergabe und Deployment-Workflows bleiben nächste Schritte. + +CI-Stand: Bootstrap-Workflow und Environment-Einrichtung lokal implementiert; Secret-Upload wartet auf explizite Freigabe. S3-Locking-Abnahme fehlgeschlagen (zweiter Prozess trotz Lock nicht blockiert); Remote-Applies sind technisch gesperrt. Backend-/Sperrstrategie muss vor Deployment entschieden werden. Siehe [CI-Betrieb](../infra/ci/README.de.md). + +Bestätigte Folgeentscheidung: S3 beibehalten, Deployments vorerst ausschließlich über serialisierte GitHub Actions. Lokale Remote-Applies bleiben gesperrt; alle mutierenden Workflows nutzen eine gemeinsame Concurrency-Gruppe. Benutzer hat den konkreten Secret-Transfer in die drei benannten GitHub Environments ausdrücklich genehmigt. + + + +## Feature-Branch und Code Ownership + +Die Entwicklung erfolgt auf `feature/landing-zone-configurator`; eine Übernahme nach `main` ist derzeit ausdrücklich nicht vorgesehen. Für `/landing-zone-configurator/` und Configurator-Workflows unter `/.github/workflows/` ist ausschließlich `@lweberru` als CODEOWNER eingetragen. Gemeinsame Repository-Dateien behalten ihre bestehenden Owner. + +Die GitHub-Environment-Regeln und der Deployment-Workflow erlauben weiterhin ausschließlich `main`. Feature-Branch-Entwicklung aktiviert daher keine Cloud-Deployments. Ein späterer Testbetrieb vom Feature-Branch braucht eine gezielte Anpassung dieser Regeln; der Branch wird dafür nicht automatisch nach main übernommen. + +GitHub wertet CODEOWNERS für Pull Requests aus dem jeweiligen Zielbranch aus: Für einen späteren PR nach main gilt zunächst die dortige bisherige Regel. CODEOWNERS setzt außerdem keine Branch-Protection-Regeln außer Kraft; eigene PRs können nicht selbst freigegeben werden. + +Feature-Branch-Test freigegeben: Push-Trigger für Bootstrap-Plan auf `feature/landing-zone-configurator`, entsprechende zusätzliche Branch-Regel ausschließlich im Plan-Environment. Apply/Recovery bleiben main-only. Kein Merge nach main für den Test erforderlich. + +Bootstrap-Apply abgeschlossen: GitHub Run 36601941540 auf dem Feature-Branch, drei Ressourcen erstellt. Verschlüsselter Remote-State unabhängig geprüft; einmalige Commit-Freigabe entfernt. Nächster Schritt: separater Backend-Root zur Versionierung des Workload-State-Buckets. main bleibt unverändert. + +Backend-Apply abgeschlossen: Run 36602706599, Versionierung für den Workload-State-Bucket aktiviert und direkt über S3 verifiziert. Verschlüsselter Backend-State geprüft; einmalige Freigaben entfernt. Die [Plattform-Vorbereitung](platform-readiness.de.md) dokumentiert die ausgewählten Katalogwerte und offenen Netzwerkparameter. + +Netzwerk-Korrektur: CF-Egress-Adressen sind nicht dokumentiert/stabil (Benutzerhinweis). Die bisherige Anforderung fester CF-CIDRs entfällt. Stattdessen dienstspezifische, unterstützte Zugangsmodelle prüfen: dokumentierte STACKIT-Netze für PostgreSQL mit Konnektivitätstest; Secrets Manager separat. Migrationen als CF-Task vorsehen. Service-Bindings nicht als Netzwerkfreigabe behandeln. Siehe [Plattform-Vorbereitung](platform-readiness.de.md). + + +Plattform-Versuch 2026-09-30: Plan mit neun Creates und Validierung erfolgreich; Apply-Run 36632950493 nach 45 Minuten abgebrochen. Teilbestand existiert (CF aktiv, Secrets Manager Running, PostgreSQL zuletzt PROGRESSING), Plattform-State fehlt. Einmalige Freigabe entfernt und Plattform-CI vorübergehend deaktiviert. Nächster Schritt ist die kontrollierte State-Recovery und verbesserte Abbruchbehandlung, nicht ein erneuter ursprünglicher Apply. Details und Checkliste: [Plattform-Betriebsstand](platform-readiness.de.md#vorfall-2026-09-30-erster-plattform-apply-unvollständig). + + +Plattform-Recovery abgeschlossen (2026-09-30): Run 36675347654 importierte den Teilbestand und vervollständigte die Plattform. Neun Ressourcen im verschlüsselten Remote-State unabhängig geprüft; PostgreSQL READY, CF aktiv, Secrets Manager Running. Verlorene technische Credentials kontrolliert ersetzt. Job-Timeout auf 100 Minuten erhöht, geordneten OpenTofu-Abbruch und verschlüsselte Diagnose-/State-Artefakte ergänzt. Einmalfreigaben entfernt. Nächster Ausbauschritt nach No-op-Abnahme: CF-Runtime/Bindings und Zugriffstests aus CF. [Aktuelle Abnahme](platform-readiness.de.md#erfolgreiche-recovery-und-plattform-abnahme). + + +No-op-Abnahme abgeschlossen: Plattform-Run 36675895279 zeigt für alle neun Ressourcen `no-op`; Recovery/Apply korrekt übersprungen. Validierung 36675895374 erfolgreich. Die Plattform ist damit konsistent unter IaC-Verwaltung. + + +CI-Entscheidung 2026-09-30: Auf Benutzerwunsch den eigenen JavaScript-Deployment-Runner durch direkte, sichtbare OpenTofu-Schritte in GitHub Actions ersetzen. Kleine Hilfsprogramme bereiten ausschließlich Credentials vor, prüfen Planintegrität und schützen State-Snapshots. Normale CLI-Logs werden wieder live ausgegeben; JSON-Credential-/State-Ausgaben bleiben privat. Abgeschlossene Recovery vom regulären Ablauf trennen. Auch lokale Validierung und Seed-Bedienung verwenden direkte `tofu`-Befehle. [Aktuelle Betriebsanleitung](../infra/ci/README.de.md). + + +CI-Vereinfachung abgenommen: echte direkte OpenTofu-Pläne für Bootstrap (36677111141), Plattform (36677111032) und Backend (36677367229) jeweils ohne Änderungen; Apply jeweils übersprungen. Native Logs sichtbar und gegen bekannte Credentials geprüft. Validierung einschließlich Linux-Timeout-Test erfolgreich. Temporäre Backend-Auswahl entfernt; Feature-Branch bleibt getrennt von main. + + + + +## Aktueller Meilenstein: CF-Hosting und Service-Verbindungen + +Owner: `@lweberru`. Alle Änderungen bleiben auf `feature/landing-zone-configurator`. +Die Benutzerfreigabe vom 2026-09-30 umfasst notwendige Configurator-Deployment- +Applies bis zum MVP. Konkrete Pläne werden weiterhin geprüft; die Freigabe ist +keine Erlaubnis, Kundenressourcen oder fremde Projekte zu ändern. + +- [x] Separate Runtime-IaC für CF-Space und Rollen. +- [x] Separate PostgreSQL-/Secrets-Laufzeitidentitäten; kein Migrations- oder Provisionierungszugang in der App. +- [x] Deklaratives CF-Manifest unter `deploy/cloud-foundry/`; OpenTofu und Release haben getrennte Zuständigkeiten. +- [x] Unabhängige Release-Pipeline mit direktem `cf push`, versioniertem Node-Runtime-Paket und Verbindungstest als CF-Task. +- [x] Öffentliche HTTPS-Route, UI-/JS-Auslieferung und gesperrte API (401) geprüft. +- [x] PostgreSQL: Login, SELECT und geprüfte TLS-Verbindung aus CF erfolgreich. +- [x] Secrets Manager: Login, TLS, authentifizierter KV-Lese-Endpunkt und Ablehnung ohne Token aus CF geprüft. +- [x] Abschließender [Release-Run 36683898762](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898762) vollständig erfolgreich; [Validierung 36683898795](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898795) ebenfalls grün. + +Nachweise und Netzkorrektur: [Plattform-Betriebsstand](platform-readiness.de.md). +Das Grundgerüst ist noch kein nutzbarer Configurator und verarbeitet keine +Kundenkonfigurationen oder persönlichen Cloud-Zugangsdaten. + +Nächster fachlicher Meilenstein: + +- [ ] GitHub-App/OAuth-Integration festlegen, Callback-URL registrieren und Benutzerlogin umsetzen. +- [ ] Mandanten, Mitgliedschaften und Sessions mit Datenbankschema/Migrationen/RLS absichern. +- [ ] Ein vorhandenes Accelerator-Template als ersten vertikalen Ablauf importieren, fachlich bearbeiten und im persönlichen Fork speichern. +- [ ] Persönliche Deployment-Credentials: mandantenbezogene Zugriffsregeln, Secrets-Schreibidentität und Write/Read/Rotation-Test ergänzen. +- [ ] Danach Plan/Apply-Runner, Freigaben, grafische Konfiguration und begrenzten Chat integrieren. + +Vor Produktion zusätzlich: eigener CF-Deployer mit nur Space-Rechten, schmalere +Credential-Veröffentlichung für Releases, Rotation, Restore-Abnahme, Rolling +Deployment und definierter Rollback. Diese Punkte werden nicht durch den ersten +Konnektivitätstest als erledigt markiert. + + + + +## Portal-Design und Beginn des Login-Meilensteins (2026-09-30) + +Neue bestätigte Anforderung: Das Look & Feel soll identisch zum offiziellen +STACKIT Portal werden. Referenz ist die vom Benutzer geöffnete Projektstartseite. +[Design-Abgleich und Fortschritt](design-reference.de.md) dokumentieren die Abnahme. +Die öffentlichen Portal-Assets wurden anschließend erfolgreich ohne Anmeldung per +`curl` erfasst. Originale NDS-Tokens und Schriftdefinitionen sind mit ihren +Marken-/Theme-Selektoren dokumentiert; [Abrufwerkzeug](../tools/portal-reference/README.de.md). +Die gerenderte Projektansicht und ihre aktive Marken-/Theme-Auswahl sind noch +nicht visuell bestätigt. + +Der [GitHub-App-Entwurf](../deploy/github/README.de.md) und die getesteten +PKCE-/State-/Session-Token-Helfer sind vorbereitet. Dies aktiviert noch keinen +Login und bedeutet keine abgeschlossene Session-, RLS- oder Token-Store-Integration. + + + + +## Template-Auswahl und erster Editor (2026-09-30) + +- [x] Acht echte Repository-Templates über einen gepinnten Go/HCL-Adapter importieren. +- [x] Template-Katalog mit SHA-256, Suche und grafischer Organisationsstruktur. +- [x] Standalone-Kopie: Grundlagen, Landing Zones, Sandboxes, Umgebungen und Secrets-Manager-Auswahl bearbeiten. +- [x] Platzhalter, fehlende Angaben und doppelte Projektkennungen prüfen; unberührte Attribute erhalten. +- [x] Versionierten lokalen Entwurf herunterladen; GitHub-Speicherung klar als Folgeschritt kennzeichnen. +- [x] Originale Nebula-Tokens, STACKIT-Logo, DIN 2014 und Univia Pro mit Herkunft dokumentieren. +- [x] App-Tests, HCL-Tests und Browserablauf für Desktop/Mobil lokal erfolgreich. +- [x] Katalog-Aktualität und Browserablauf in Validierungs-/Release-Pipeline aufnehmen. +- [x] Feature-Branch-Release auf CF und Verbindungstests abnehmen. +- [ ] Portal-Parität visuell bestätigen und verbleibende Komponenten-/Icon-Abweichungen schließen. +- [ ] GitHub-Login, RLS/Mandantenmodell und Speicherung im ausgewählten Fork umsetzen. + +Wichtige Grenzen: Der Editor bearbeitet bisher nur Standalone; komplexe Templates +sind lesbare Vorschauen. Im damaligen Stand lagen Entwürfe nur im Tab-Arbeitsspeicher; +die unten dokumentierte Wiederaufnahme ergänzt nun Browserspeicherung. Der Download +war zunächst ein `.lzc.json`-Entwurf. Der aktuelle Stand ergänzt native `.tfvars` +und bearbeitbare JSON-Ablage im Fork (siehe [Forks und Navigation](forks-and-navigation.de.md)). Es findet kein Kunden-Deployment statt. + +Die bestehende Standalone-Vorlage enthält keine explizite Corporate-Zuordnung, +obwohl `variables.tf` standardmäßig `true` verwendet. Die bearbeitete Kopie setzt +`corporate: false`, passend zu ihrem fehlenden Netzwerk-Hub; der Accelerator selbst +bleibt unverändert. Ein späterer Export benötigt zusätzlich Schema-/Plan-Abnahme. + + +Abnahme dieses Stands: Commit `76db252` auf `feature/landing-zone-configurator`. +[Validierung 36689446249](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36689446249) +und [Release 36689446170](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36689446170) +sind erfolgreich. Die Pipeline prüft 16 App-Tests, den HCL-Adapter und vier +Browserfälle (Desktop/Mobil). CF-Push, Service-Verbindungstests und öffentliche +Smoke-Checks waren erfolgreich. Zusätzlich auf der Live-URL geprüft: acht +Templates, Standalone-Editor, Health 200, Session ohne Login 401 und keine +JavaScript-Laufzeitfehler. Keine Infrastrukturänderung und kein Merge nach main. + + + +### Kunden-Plan, 2026-09-30 + +Benutzer bestätigt persönlichen Zugangstest und vollständige Deployment-Vorbereitung. +Kunden-Plan darf getestet werden; **Kunden-Apply ausschließlich nach neuer ausdrücklicher +Freigabe**, kein Destroy. Die Configurator-Infrastrukturfreigabe gilt dafür nicht. +D07: bestehenden LZA-Bootstrap mit anschließendem Kunden-Backend übernehmen. Wertfreie Plan-Auswertung und lokaler echter +OpenTofu-Vertragstest umgesetzt; produktiver Kunden-Runner noch offen. +[Umsetzung und Abnahme](plan-execution.de.md). + + + +### Plan-only-Ausführung + +Persistierte persönliche Plan-Aufträge und isolierte CF-Tasks in eigener Organisation +umgesetzt; Erstbereitstellung nur nach Bestätigung eines leeren States. Direkte +init/validate/plan/show-Befehle, feste Engine/Provider, bereinigte Aktionszahlen und +Abbruch. Kein Apply-/Destroy-Endpunkt. Dauerhafte Bootstrap-State-Sicherung und +exakte Apply-Artefakte bleiben offene Voraussetzungen. [Abnahme](plan-execution.de.md). + + + +### Wiederaufnahme und Ordnerprüfung, 2026-09-30 + +- [x] Automatische Fork-Liste und kontogebundene Wiederaufnahme im selben Browser + einschließlich lokalem Entwurf, letzter Seite und ursprünglicher Git-Schreibbasis. +- [ ] Geräteübergreifende persönliche Arbeitsbereiche in PostgreSQL. +- [x] Ordnerhierarchie des Accelerators prüfen und Empfehlung dokumentieren. +- [x] Ordner-Editor und Strukturvorschau nach ausdrücklicher fachlicher Bestätigung umsetzen. + +Details: [Arbeitsstand](forks-and-navigation.de.md#arbeitsstand-beim-wiederkommen), +[gemeinsamer Editor](common-editor.de.md). + + +Abnahme Wiederaufnahme/Ordner: Code `21b5529`, +[Release 36729582680](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36729582680) +erfolgreich. Aktuelle Grenzen siehe [MVP-Umfang](mvp-scope.de.md). +Der Benutzer öffnet seine bestehende Konfiguration einmal, um den ersten lokalen +Arbeitsstand zu speichern. Weitere Besuche im selben Browser stellen ihn wieder her. +Nach Konfigurationsänderungen ist eine neue unveränderliche Deployment-Vorbereitung +nötig. Persönlicher Initial-Plan kann jetzt getestet werden; Apply bleibt gesperrt. + + + +### Architekturkorrektur: gemeinsames Feature-Modell, 2026-09-30 + +Benutzer fordert alle Accelerator-Funktionen unabhängig vom gewählten Beispiel. +Templates sind Presets; der Standalone-Editor ist keine tragfähige Grenze des +Datenmodells. [Gemeinsames Funktionsmodell und Umsetzungsplan](common-feature-model.de.md) +und [generiertes Eingabeinventar](accelerator-inputs.json) sind die Grundlage. + +Die feste Public-/Sandbox-Zuordnung im veröffentlichten Projekte-Schritt ist noch +offen. Der unveröffentlichte Corporate-Einzelbereich-Prototyp wurde gesichert und +nicht ausgeliefert. Die Korrektur erfolgt als gemeinsame Projekt-/Netzwerkstruktur +mit mehreren Bereichen und Regionen, anschließend vollständiger Feature-Abdeckung. + + + +### Accelerator-Grenzen und Issue-Verfolgung, 2026-09-30 + +[Grenzen- und Issue-Register](accelerator-limitations.de.md) ist Bestandteil des +gemeinsamen Feature-Modells. #37 bleibt der separate Arbeitsstrang für private +SNA-Kubernetes-APIs; #65 deckt Multi-Appliance-Firewall-Policies ab. +Zusätzlich wurden #80 (regionale Namespace-Zuordnung), #81 (Object-Lock-Default), +#82 (Ordnerbeschreibung) und #83 (fehlender Root-Vertrag für Moduloptionen) angelegt. + +Die Registrierung dieser Grenzen implementiert noch keine Laufzeitprüfung. +Capability-Prüfungen im Backend und Hinweise im Editor sind vor Freigabe der +betroffenen erweiterten Konfigurationen umzusetzen. Kein Kunden-Apply ausgeführt. + + + +### Gemeinsamer Konfigurationskern, 2026-09-30 + +- [x] Templateunabhängiges v3-Dokument und Feldkatalog für alle 28 Root-Eingaben. +- [x] Verlustfreier Import/Export aller acht Vorlagen; geprüfte Legacy-Migration. +- [x] Gemeinsame Projekt-/Bereichsprojektionen und erste Referenz-/Capability-Regeln. +- [x] Native HCL-Roundtrips und direkte OpenTofu-Variablenvertragstests in CI ergänzen. +- [x] Neu entdeckten Standalone-Defaultfehler als Accelerator-Issue #84 erfassen. +- [x] Gemeinsamen Editor, Arbeitsstand/Fork-Speicher und API auf den neuen Kern umstellen. +- [ ] Übrige Feature-Editoren, Credential-Bindings und serverseitige Ausführungsprüfung. + +Die Produkt-API bleibt vorerst auf v1/v2 beschränkt. Keine Kunden-Ausführung und +keine Änderungen an Accelerator-Modulen. Details im +[Domain-README](../app/packages/domain/README.de.md). + + + +### Gemeinsamer Editor und Release + +- [x] Sieben Editor-Bereiche, deutsche Fachbezeichnungen, optionale Einstellungen. +- [x] Projektarten und Corporate-Region-/Bereichsauswahl vereinheitlichen. +- [x] v3-Speicherung, Wiederaufnahme, Legacy-Migration und serverseitige Ausführungssperre. +- [x] Desktop-/Mobil-Browsertests für neue und bestehende Abläufe. +- [x] Veröffentlichung mit CF-/Datenbank-/Secrets-Manager-Verbindungstests. + +Details und Benutzer-Prüfliste: [gemeinsamer Editor](common-editor.de.md). + +Live-Abnahme: Code `527bd95`, Release `36745965953`, Validate `36745965890` erfolgreich. +Neue v3-Konfigurationen sind bearbeitbar und speicherbar; ihre Deployment-Ausführung +bleibt serverseitig gesperrt. [Abnahme](common-editor.de.md#live-abnahme). + + + + +### Editor-Nachbesserungen: Plattformdienste, Auswahlfelder und Standalone (#84) + +- [x] Plattform-Kubernetes ausdrücklich über leere Clusterliste deaktivierbar; bestehende Abhängigkeiten bleiben prüfbar. +- [x] Zentrales Observability und Audit-Protokollierung im Plattform-Reiter; Telemetry Router von Observability unterschieden. +- [x] Bekannte Enum-Werte und regionale/Projekt-/Netzwerkreferenzen als Auswahlfelder. +- [x] Accelerator-Standard ausdrücklich von Vorlagenwerten unterschieden. +- [x] Neue Standalone-Entwürfe mit explizitem Public-Projekt; unveränderte Imports und bestehende Exporte beibehalten. +- [x] 96 Anwendungstests, 22 Desktop-/Mobilprüfungen und 11 native OpenTofu-Variablentests erfolgreich. +- [ ] Regionale Live-Kataloge für Produktpläne, Maschinentypen und Versionen anbinden. +- [x] Veröffentlichung `10a6ec8` und Live-Abnahme dieses Nachbesserungsstands; Release 36752620332 erfolgreich. + + + +### Verbindliche Bedienprinzipien und Komponentenansicht + +Entscheidung: [Designprinzipien und VPN-Umsetzungsplan](editor-design-principles.de.md). +Produkt-/Modulnamen, aktive Komponenten mit Hinzufügen-Katalog, progressive +Detailanzeige und dokumentationsnahe Produktabläufe sind verbindliche Leitlinien. +Die vollständige Feature-Abdeckung darf nicht zu einem dauerhaft aufgeklappten +Variablenformular führen. Umsetzung und Abnahme werden im verlinkten Plan verfolgt. + + + +### Platform Landing Zone und Application Self-Service (Architekturdiskussion) + +Zielbild und offene Entscheidungen: [Platform-/Application-Architektur](platform-application-architecture.de.md). + +- [x] Plattformressourcen, veröffentlichte Application Templates und Instanzen fachlich getrennt. +- [x] Zwei mandantenbezogene Personas vorgesehen; Configurator-Rechte, STACKIT-IAM und Git-Zugriff getrennt behandelt. +- [x] Separate Accelerator-Roots, getrennte States und versionierter Plattformvertrag als Ziel eingeplant. +- [x] Benutzer bestätigt unveränderliche veröffentlichte Versionen, ausdrückliche Upgrades und je Template vom Platform Engineer wählbare direkte oder genehmigungspflichtige Bereitstellung. +- [ ] STACKIT-Login/OIDC-Client und delegierten Bootstrap-Zugriff technisch verifizieren. +- [ ] Application-Owner-Git-Ablage, Team-Zuordnung und Templateumfang entscheiden. +- [ ] Accelerator-Verträge und Bestandsmigration entwerfen; keine automatische State-Aufteilung. +- [ ] Serverseitige Autorisierung und Templateinstanziierung vor Einführung der Rollenansichten implementieren. + +Die laufende Regions-/SNA- und VPN-Oberfläche wird unabhängig davon weitergebaut. +Sie gehört perspektivisch zur Platform-Engineer-Sicht. Bis zur Umsetzung bleiben +heutige Berechtigungen und die ausdrückliche Freigabepflicht für Kunden-Apply bestehen. + + + +### Regions-/SNA-Ansicht und VPN-Konfiguration: lokaler Prüfstand 2026-10-01 + +- [x] Connectivity nach Regionen mit SNAs und optionalen Diensten dargestellt; bisherige Engine-Eingabeformen bleiben erhalten. +- [x] Neue Regionen für regionale Konfigurationen hinzufügbar; Bestandsumstellung auf regionale Module nicht automatisiert. +- [x] VPN-Assistent für Gateway, Routing, Verbindungen/Tunnel und Zusammenfassung. +- [x] Grundlegende VPN-Pflichtangaben auch im gemeinsamen Validierungsmodell geprüft; keine Aussage über vollständige Provider-/Produktvalidierung. +- [x] Grenze der VPN-Replikation auf alle SNAs gegen main geprüft und als Issue #85 erfasst. +- [x] Lint/TypeScript/Build, 97 Anwendungstests und 24 Desktop-/Mobil-Browserfälle erfolgreich; mobile VPN-Ansicht visuell geprüft. +- [ ] Veröffentlichung und Live-Abnahme; dieser Stand ist noch nicht deployed. + +VPN-PSKs, dynamische Produktkataloge, tatsächliche VPN-Ausführung und die neue +Self-Service-Rollenarchitektur bleiben gesonderte Arbeitspakete. Kein Kunden-Apply. + + + + +### Veröffentlichung und Einstieg in Self-Service (2026-10-01) + +- [x] Editor-Release `78d8f7c` auf lzc-dev veröffentlicht; Release 36830339767 und Validate 36830339847 erfolgreich. +- [x] Regionsansicht, Komponenten und VPN mit zwei Tunneln direkt live geprüft; Gesundheits-/Sitzungsprüfungen erfolgreich. +- [x] Prototyp `src/application` für eine neue Anwendungsinstanz, getrennt vom kombinierten Root. +- [x] Reiner Template-/Plattformvertrag-Compiler mit Owner aus Serverkontext und isoliertem State-Key. +- [x] Vier Compiler-Tests (101 Anwendungstests insgesamt) und vier native Mock-Plan-Tests erfolgreich; `tofu validate` erfolgreich mit bestehenden Observability-Deprecation-Warnungen. +- [ ] Separate Plattform-Veröffentlichung, unveränderliche Template-Persistenz und Identitäts-/Rollenverwaltung. +- [ ] Server-API, Instanz-Idempotenz, eingeschränkte Credentials, Queue/Runner und tatsächlicher autorisierter Kunden-Plan. + +Der Prototyp aktiviert keine neue Berechtigung und keinen Apply. Der Application- +Root erzeugt neben optionalen Diensten die bereits im Modul enthaltenen +Automations- und Object-Storage-Ressourcen; dies ist Teil des zu veröffentlichenden +Templateumfangs. Bestehende States werden nicht umgestellt. + + + + +### VPN-BGP-Erweiterung erfasst + +- [x] Offene und geschlossene VPN-/BGP-Issues abgeglichen; kein dediziertes offenes BGP-Issue vorhanden. +- [x] [#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) für BGP-Unterstützung angelegt, einschließlich Prüfung des historischen Provider-Blockers mit der aktuellen gepinnten Version. +- [ ] Accelerator-Unterstützung und Tests umsetzen; anschließend Configurator-Schema, Assistent und Engine-Freigabe aktualisieren. + +BGP bleibt bis dahin im Configurator gesperrt. Keine Änderung am Live-Deployment. + + + +### Benutzerverwaltung und API-gestützte Produktoptionen + +- [x] Interne Benutzeridentität von externer GitHub-Identität getrennt (Migration 006). +- [x] Entwurfs-Organisationstenants, Rollenmitgliedschaften und Verwaltung implementiert (Migration 007). +- [x] Persönliche GitHub-Token beim Tenant-Wechsel getrennt halten; bestehende Benutzer nicht automatisch hochstufen. +- [x] Aktuelle Produktoptionen über persönlichen STACKIT-Zugang abfragen: Git-Leistungsklassen, VPN-Pläne, SKE-Versionen, Node-Flavors, Zonen und Volume-Typen. +- [x] Bestandswerte bei fehlenden Katalogeinträgen erhalten; Ausfall einzelner Produkt-APIs sichtbar machen. +- [ ] Live-Abnahme der neuen Verwaltung und Produktkataloge mit Benutzerkonten und ausgewähltem persönlichem STACKIT-Zugang. +- [ ] STACKIT-IDP-Ticket klären und Organisationsbindung verifizieren. +- [ ] Serverseitige Produktverfügbarkeit unmittelbar vor Plan/Deployment erneut prüfen; Kataloge allein garantieren weder Quote noch Kapazität. +- [ ] Weitere dynamische Felder nach Produkt-API-Verfügbarkeit ergänzen. + +Organisationstenants bleiben bis zur verifizierten STACKIT-Anbindung Verwaltungsentwürfe; +Kunden-Apply bleibt unverändert freigabepflichtig. Details in der +[Platform-/Application-Architektur](platform-application-architecture.de.md). + +Prüfstand für Commit `59b0a04`: Lint/TypeScript/Build, 114 Anwendungstests, +17 PostgreSQL-Integrationstests und alle 30 Desktop-/Mobil-Browserfälle erfolgreich. +Die Organisationsansicht wurde zusätzlich auf mobilen Überlauf geprüft und visuell +kontrolliert. Validate-Workflow +[36836376140](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36836376140) +ist erfolgreich. Die Katalogtests verwenden kontrollierte API-Antworten; eine +Live-Abfrage mit einem persönlichen Benutzerzugang steht noch aus. + +- [x] Commit `59b0a04` auf lzc-dev veröffentlicht: [Release 36836376110](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36836376110) erfolgreich, einschließlich Migrationen, CF-Deployment und Runner-Prüfungen. +- [x] Live-Gesundheit, neue Organisationsseite und Netzwerk-Deep-Link geprüft; ausgeliefertes Bundle `index-DxHvyiWG.js`. Anonymer Zugriff auf die Organisations-API wird mit 401 abgewiesen. +- [ ] Benutzerabnahme: persönliche Produktkatalog-Abfrage und Organisations-Mitgliederverwaltung mit zwei Benutzerkonten. + + + +### Rückmeldungen zu Komponenten, Katalogen und Arbeitsbereichen + +- [x] Diagnose-Bastion gegen Accelerator geprüft: VM im Cluster-Projekt/SNA-Netz; unabhängige Komponente als [#87](https://github.com/stackitcloud/stackit-landing-zone/issues/87) erfasst. +- [x] Zentrale und clusterbezogene Observability getrennt erklärt; Referenz statt Neuanlage als [#88](https://github.com/stackitcloud/stackit-landing-zone/issues/88) erfasst. Zulässige Projekt-/Regionsbeziehungen vor Umsetzung prüfen. +- [x] Löschen leerer unverifizierter Organisationsentwürfe als auditierbare Archivierung ergänzt; keine Cloud-Ressourcen werden gelöscht. +- [x] Benutzerkennung mit UUID-Beispiel, Kopierfunktion und verständlicher Validierung erklärt; Leerzeichen beim Einfügen entfernt. +- [x] Versehentliche doppelte Anlage gleichnamiger zugänglicher Arbeitsbereiche für dieselbe Organisations-ID serverseitig abgefangen. +- [ ] Unabhängigen Bastion-Root-Vertrag und sichere Observability-Referenzen im Accelerator implementieren; keine Änderung bestehender Ressourcenadressen ohne Migrationskonzept. + +- [x] Observability-Plan-Auswahl für eu01 sowie Bastion-Maschinentypen, öffentliche Images und IaaS-Zonen ergänzt; eu02-Observability bleibt mangels verifizierter API-Quelle manuell. +- [x] PIM-v2-Angebotskatalog geprüft und gegenüber technischen Produktkatalogen abgegrenzt; kein automatischer SKU-zu-Provider-ID-Adapter eingeführt. +- [x] Lokale Prüfung dieser Erweiterung: 117 Anwendungstests, 18 PostgreSQL-Tests, 30 Desktop-/Mobil-Browserfälle sowie Lint/TypeScript/Build erfolgreich. + +Veröffentlicht auf lzc-dev mit Commit `3532645`: +[Release 36840987284](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36840987284) +und [Validierung 36840987238](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36840987238) +erfolgreich. Migration 008, Cloud-Foundry-Deployment und Abschlussprüfungen erfolgreich; +Live-Health und Organisationsseite liefern HTTP 200, Bundle `index-DqgRf507.js`. +Keine realen Arbeitsbereiche während der Entwicklung/Veröffentlichung gelöscht; +keine Kunden-Apply-Ausführung. Produkt-APIs mit kontrollierten Antworten getestet, +persönliche Live-Abnahme der neu ergänzten Kataloge bleibt offen. + + + +### Einladungsbasierte Mitgliederverwaltung + +- [x] UUID-Eingabe durch Rollenwahl und einmaligen Einladungslink ersetzt. +- [x] Sieben Tage Gültigkeit, offene Einladungen auflisten und widerrufen; keine E-Mail-Zustellung. +- [x] Token nur gehasht speichern; Beitritt nach Anmeldung und ausdrücklicher Bestätigung. +- [x] GitHub-Erstanmeldung legt den internen Benutzer an; Einladungsabsicht bleibt im selben Browser-Tab erhalten. +- [x] Keine Rolleneskalation vorhandener Mitglieder über Einladungen; alte API fügt keine unbekannten Mitglieder mehr hinzu. +- [x] Audit sowie Schutz vor paralleler Mehrfachannahme, Widerruf, Ablauf und archivierten Tenants. +- [ ] Spätere optionale Zustellung per E-Mail / Auswahl verifizierter STACKIT-Organisationsmitglieder. + +Lokale Abnahme: Lint/TypeScript/Build, 118 Anwendungstests, 21 echte PostgreSQL- +Tests und 32 Desktop-/Mobil-Browserfälle erfolgreich. Browserprüfung deckt das +Erstellen/Widerrufen und die Einladungsfortsetzung nach dem Login ab; DB-Prüfung +deckt insbesondere konkurrierende Annahme, Hashspeicherung, Ablauf, Widerruf, +archivierte Tenants und entzogene Verwaltungsrechte ab. + +Einladungsablauf auf lzc-dev veröffentlicht mit Commit `dde3379`: +[Release 36846494967](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36846494967) +und [Validierung 36846494917](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36846494917) +erfolgreich. Migration 009 und Abschlussprüfungen erfolgreich. Live-Health und +Organisationsseite HTTP 200, Bundle `index-DFtM2hCS.js`; anonyme Einladungsabfrage +HTTP 401. Keine realen Einladungen durch Entwicklung/Deployment erzeugt oder +versendet. Benutzerabnahme mit zweitem Konto bleibt offen. diff --git a/landing-zone-configurator/docs/planning.md b/landing-zone-configurator/docs/planning.md index 5def1bf..17b9bde 100644 --- a/landing-zone-configurator/docs/planning.md +++ b/landing-zone-configurator/docs/planning.md @@ -1,111 +1,104 @@ -# Landing Zone Configurator – Architektur und Planung +# Landing Zone Configurator – architecture and planning -> Stand: 2026-10-01 · Architektur-Ausgangsstand: `2161871` -> Historisches Entscheidungsprotokoll, kein aktueller Betriebs- oder Abnahmestand. -> Aktuelle Referenzen: [Architektur](architecture.md), [MVP-Grenzen](mvp-scope.md), [Entwicklung](development.md) und [GitHub-Issues](https://github.com/stackitcloud/stackit-landing-zone/issues). -> Die folgenden Architekturabschnitte und datierten Fortschrittsnotizen sind das Entscheidungsprotokoll; ältere Statusangaben beschreiben den damaligen Stand. -> `[x]` = je nach Abschnitt entschieden oder mit angegebenem Nachweis umgesetzt; eine Entscheidung allein ist keine Live-Abnahme. +[English](planning.md) | [Deutsch](planning.de.md) -## Aktueller Umsetzungsschritt + -**Aktueller Template-Schritt:** [Typisierte Bestelleingaben und Ressourcenverknüpfungen](template-parameters-and-bindings.md), einschließlich Stage-Auswahl und Observability-Zugriff aus dem eigenen Projektnetz. Der Parametervertrag mit fünf freigegebenen Feldern, Editor und lokaler Bestellvorschau ist implementiert. Die produktive Projektnetz-/Egress-Bindung bleibt in #96 offen; Veröffentlichung und Application-Owner-Bestellungen folgen gesondert. +> As of: 2026-10-01 · Architecture baseline: `2161871` +> Historical decision log, not current operational or acceptance status. +> Current references: [architecture](architecture.md), [MVP boundaries](mvp-scope.md), [development](development.md) and [GitHub issues](https://github.com/stackitcloud/stackit-landing-zone/issues). +> The following architecture sections and dated progress notes form the decision log; older status statements describe the state at that time. +> `[x]` = decided or implemented with the stated evidence, depending on the section; a decision alone is not live acceptance. + +## Current implementation step -**Korrektur des Rollenablaufs:** Neue Plattformkonfigurationen enthalten -[Projekt-Template-Entwürfe](project-template-drafts.md) statt konkreter -Anwendungsprojekte. Der Platform Engineer definiert sie; Instanzen entstehen -später durch den Application Owner aus veröffentlichten Versionen. Alte -Gesamtkonfigurationen bleiben unverändert, Übernahme nur als ausdrückliche Kopie. +**Current template step:** [Typed order inputs and resource bindings](template-parameters-and-bindings.md), including stage selection and Observability access from the project's own network. The parameter contract with five approved fields, editor and local order preview is implemented. Production project-network/egress binding remains open in #96; publication and Application Owner orders follow separately. +**Role-workflow correction:** New platform configurations contain [project template drafts](project-template-drafts.md) rather than concrete application projects. The Platform Engineer defines them; instances are later created by the Application Owner from published versions. Old combined configurations remain unchanged; adoption only as an explicit copy. -Governance-Pläne umfassen auch Organisationsrollen und Ordnerberechtigungen; -leere Ordnerbeschreibungen blockieren nicht mehr. Die optionale -Service-Account-Föderation erhält einen eigenen erklärten CI/CD-Editor. -[Umfang und Qualifikation](plan-execution.md). +Governance Plans also cover organization roles and folder permissions; empty folder descriptions no longer block. Optional service-account federation receives its own explained CI/CD editor. [Scope and qualification](plan-execution.md). -Die MVP-Bestandsaufnahme trennt Editorabdeckung von Ausführungsfreigabe. Zunächst -wird die geprüfte Standalone-Teilmenge des gemeinsamen Editors an den vorhandenen -Erstbereitstellungsplan angebunden. Anschließend folgen dauerhafter Bootstrap-State -und freigegebener Apply. Parallel werden verifizierte Organisationstenants, -veröffentlichte Application Templates und der Model-Serving-Assistent aufgebaut. -Die Arbeitspakete #89–#95 enthalten konkrete Abnahmekriterien. +The MVP inventory separates editor coverage from execution approval. First, the checked standalone subset of the common editor is connected to the existing initial-provisioning Plan. Durable bootstrap state and approved Apply follow. Verified organization tenants, published Application templates and the Model Serving Assistant are developed in parallel. Work packages #89–#95 contain specific acceptance criteria. -Kunden-Apply benötigt weiterhin eine ausdrückliche Freigabe; Organisationen sind -bis zum Berechtigungsnachweis unverifizierte Entwürfe. Der Featurebranch wird in -diesem Schritt nicht nach main gemergt. +Customer Apply still needs explicit approval; organizations remain unverified drafts until permission evidence exists. The feature branch is not merged to main in this step. -## 1. Zielbild und bestätigte Entscheidungen + +## 1. Target design and confirmed decisions -Eine zentral auf STACKIT Cloud Foundry gehostete Anwendung begleitet Benutzer vom Landing-Zone-Template bis zum überprüfbaren Deployment. Die Oberfläche arbeitet mit Organisationen, Netzwerkbereichen, Plattformdiensten und Workloads. Ein deterministischer Compiler übersetzt diese fachlichen Angaben in die Konfiguration des Accelerators. Terraform bleibt im Hintergrund; technische Details sind bei Bedarf einsehbar. +An application hosted centrally on STACKIT Cloud Foundry guides users from Landing Zone template to verifiable deployment. The UI works with organizations, network areas, platform services and workloads. A deterministic compiler translates this business information into Accelerator configuration. Terraform stays in the background; technical details can be inspected when needed. -**Bestätigt im Planungsgespräch:** +**Confirmed in the planning discussion:** -- [x] Produktname: Landing Zone Configurator. -- [x] Sämtliche Configurator-Dienste inklusive Aktivierung werden via IaC erstellt; keine manuelle Portal-Provisionierung. -- [x] Erste Entwicklungsumgebung: lzc-dev in eu01. -- [x] App, IaC und Dokumentation unter `landing-zone-configurator/` getrennt vom Accelerator organisieren. -- [x] Betreiberprojekt und Service-Account-Datei sind lokal bereitgestellt; `NAME=WERT`-Format geprüft; Projektzugriff sowie Bereitstellung von Plattform und Runtime durch CI-Applies nachgewiesen. +- [x] Product name: Landing Zone Configurator. +- [x] All Configurator services, including activation, are created through IaC; no manual portal provisioning. +- [x] First development environment: lzc-dev in eu01. +- [x] Organize app, IaC and documentation under `landing-zone-configurator/`, separate from the Accelerator. +- [x] Operator project and service-account file provided locally; `NAME=WERT` format checked; project access and platform/runtime provisioning demonstrated through CI Applies. +- [x] Support multiple independent customer organizations from the start. Tenant separation is a prerequisite for first release, not a later extension. +- [x] Initially change configurations only and execute them with approved Accelerator code. Custom Terraform modifications from forks follow later. +- [x] GitHub access uses the user's identity and permissions, without central repository credentials. +- [x] App hosting on STACKIT Cloud Foundry; build platform environment through IaC. +- [x] STACKIT Model Serving as chat backend; provide its operator credentials server-side through CF variables. -- [x] Von Beginn an mehrere unabhängige Kundenorganisationen unterstützen. Mandantentrennung ist Voraussetzung der ersten Freigabe, kein späterer Ausbau. -- [x] Zunächst ausschließlich Konfigurationen verändern und mit freigegebenem Accelerator-Code ausführen. Eigene Terraform-Modifikationen aus Forks folgen später. -- [x] GitHub-Zugriffe erfolgen im Namen und mit Berechtigungen des Benutzers, ohne zentrale Repository-Credentials. -- [x] App-Hosting auf STACKIT Cloud Foundry; Plattformumgebung über IaC aufbauen. -- [x] STACKIT Model Serving als Chat-Backend; dessen Betreiber-Credentials serverseitig über CF-Variablen bereitstellen. +Operators need technical identities for CF, database, secret management and Runner. These must not have blanket permission for customer repositories or deployments. The requested central Model Serving credentials are an explicitly bounded operator function. -Die Betreiber benötigen technische Identitäten für CF, Datenbank, Secret-Verwaltung und Runner. Diese dürfen keine pauschale Berechtigung für Kunden-Repositories oder Kunden-Deployments haben. Die gewünschten zentralen Model-Serving-Credentials sind eine ausdrücklich abgegrenzte Betreiberfunktion. + +### Requirements catalogue -### Anforderungskatalog - -| ID | Fähigkeit | Einordnung | +| ID | Capability | Classification | | --- | --- | --- | -| F01 | GitHub-Login und benutzergebundene Repository-Zugriffe | Erste Version | -| F02 | Fork erstellen und mehrere vorhandene Repository-Verbindungen auswählen | Erste Version; GitHub-Grenzen berücksichtigen | -| F03 | Vorhandene `src/config/`-Beispiele als Templates anbieten und kopieren | Erste Version | -| F04 | Fachlicher Editor passend zu Modulen und Features | Schrittweise Umsetzung; Abdeckung sichtbar machen | -| F05 | Konfigurationen im ausgewählten eigenen Fork speichern | Erste Version | -| F06 | Persönliche Credentials und Deployment-Profile sicher verwalten | Vor erstem Deployment | -| F07 | Terraform/OpenTofu Plan und Apply visuell begleiten und ausführen | Kernumfang | -| F08 | Optionale Drift Detection und optionale Drift Correction | Nach stabilem Apply | -| F09 | Chat mit Rückfragen, vollständigem versionsbezogenem Feature-Wissen und Themenbegrenzung | Kernumfang | -| F10 | Grafische Konfigurationsdarstellung, später Plan-Delta und bekanntes Ist | Kernumfang | -| F11 | STACKIT-PaaS-Datenbank für Persistenz | Empfehlung: PostgreSQL Flex | -| F12 | Optionaler STACKIT-IdP-Login | Machbarkeit prüfen; keine MVP-Abhängigkeit | -| F13 | Model-Serving-Service als Voraussetzung und Plattformaufbau per IaC | Kernumfang | - -## 2. Ausgangslage dieses Repositories - -Grundlage sind [Root-Variablen](../../src/variables.tf), [Provider](../../src/providers.tf), [Engine-/Provider-Vorgaben](../../src/terraform.tf), [Backend-Beispiel](../../src/backend.tf), [Getting Started](../../docs/getting-started.md), [Architektur](../../docs/architecture.md), [mise.toml](../../mise.toml) und [Beitragsregeln](../../CONTRIBUTING.md). - -### Template-Katalog - -| Datei unter `src/config/` | Fachliche Darstellung | +| F01 | GitHub login and user-bound repository access | First version | +| F02 | Create fork and select multiple existing repository connections | First version; consider GitHub limits | +| F03 | Offer and copy existing `src/config/` examples as templates | First version | +| F04 | Business editor matching modules and features | Incremental implementation; make coverage visible | +| F05 | Save configurations in the selected personal fork | First version | +| F06 | Securely manage personal credentials and deployment profiles | Before first deployment | +| F07 | Visually accompany and execute Terraform/OpenTofu Plan and Apply | Core scope | +| F08 | Optional drift detection and optional drift correction | After stable Apply | +| F09 | Chat with follow-ups, complete version-specific feature knowledge and topic restrictions | Core scope | +| F10 | Graphical configuration display, later Plan delta and known actual state | Core scope | +| F11 | STACKIT PaaS database for persistence | Recommendation: PostgreSQL Flex | +| F12 | Optional STACKIT IdP login | Check feasibility; no MVP dependency | +| F13 | Model Serving service as prerequisite and platform setup through IaC | Core scope | + + +## 2. Repository baseline + +Based on [root variables](../../src/variables.tf), [providers](../../src/providers.tf), [engine/provider requirements](../../src/terraform.tf), [backend example](../../src/backend.tf), [Getting Started](../../docs/getting-started.md), [architecture](../../docs/architecture.md), [mise.toml](../../mise.toml) and [contribution rules](../../CONTRIBUTING.md). + + +### Template catalogue + +| File under `src/config/` | Business representation | | --- | --- | -| `standalone.tfvars` | Unabhängige Landing Zones ohne zentralen Netzwerk-Hub | -| `hub-and-spoke.tfvars` | Zentraler Netzwerk-Hub mit angebundenen Landing Zones | -| `hub-and-spoke-firewall.tfvars` | Hub-Spoke mit OPNsense-Firewall | -| `hub-and-spoke-multi-area.tfvars` | Getrennte Bereiche für regulierte und gemeinsame Workloads | -| `hub-and-spoke-finance-research.tfvars` | Getrennte Bereiche für Fachorganisationen | -| `hub-and-spoke-prod-nonprod-firewall.tfvars` | Getrennte Prod-/Nonprod-Bereiche mit Appliances | -| `hub-and-spoke-tenant-isolation.tfvars` | Netzwerkisolation innerhalb einer STACKIT-Organisation | -| `hub-and-spoke-multi-region.tfvars` | Regionale Hubs, Landing Zones und Plattformcluster in `eu01`/`eu02` | - -**Wichtige Grenzen und Konsequenzen:** - -- Templates enthalten Platzhalter und auskommentierte optionale Features. Ein HCL-Parser allein entdeckt daher nicht den gesamten Funktionsumfang. Ein expliziter Feature-Katalog ist nötig. -- `src/providers.tf` unterstützt statische regionale Aliasse für `eu01` und `eu02`. Die UI darf weitere Regionen nicht als automatisch unterstützt ausgeben. -- `connectivity_regions` ist als `map(any)` modelliert. Fachliche UI-Validierung muss über die Terraform-Typprüfung hinausgehen. -- Ein Projekt gehört gemäß Repo-Dokumentation zu genau einer SNA; mehrere SNAs oder Regionen sind nicht automatisch privat verbunden. -- `firewall_config` konfiguriert derzeit eine Appliance. Mehrere Appliances bedeuten keine automatische Policy-Verteilung. Dies bleibt eine sichtbare Einschränkung. -- Firewall-Bootstrap benötigt mehrere Schritte, ein Image und Shell-Werkzeuge. Die Anleitung beschreibt ein anfänglich öffentliches Admin-Interface mit gemeinsamem Initialpasswort. Automatisierte Freigabe erst nach sicherem Bootstrap und Passwortrotation. -- Private Firewall-/Kubernetes-Endpunkte benötigen passende Runner-Konnektivität. Zentraler CF-Betrieb allein stellt diese nicht her. -- Das Backend ist auskommentiert; die Anleitung migriert lokalen State erst nach der Erstbereitstellung in den erzeugten Management-Bucket. Kurzlebige Runner benötigen dagegen Remote State vor dem ersten Lauf. -- `mise.toml` pinnt OpenTofu `1.12.6`; `src/terraform.tf` verlangt mindestens `1.11`. README/Getting Started nennen teils abweichende Mindestversionen. Empfehlung: zunächst die gepinnte OpenTofu-Version qualifizieren; Terraform als weitere Engine separat testen. -- Das Repo verspricht keine pauschale Migrationskompatibilität. Upgrades brauchen explizite Migration, Versionsprüfung und neuen Plan. -- Die Netzwerkisolation des Templates „Tenant Isolation“ ersetzt nicht die Mandantentrennung der zentralen Anwendung. - -## 3. Zielarchitektur - -Empfehlung: modularer Backend-Dienst mit klaren internen Grenzen; Terraform-Ausführung als getrennte Laufzeit. Keine unnötige Aufteilung in viele Microservices zum Start. +| `standalone.tfvars` | Independent Landing Zones without central network hub | +| `hub-and-spoke.tfvars` | Central network hub with connected Landing Zones | +| `hub-and-spoke-firewall.tfvars` | Hub-and-spoke with OPNsense firewall | +| `hub-and-spoke-multi-area.tfvars` | Separate areas for regulated and shared workloads | +| `hub-and-spoke-finance-research.tfvars` | Separate areas for business organizations | +| `hub-and-spoke-prod-nonprod-firewall.tfvars` | Separate Prod/Nonprod areas with appliances | +| `hub-and-spoke-tenant-isolation.tfvars` | Network isolation within a STACKIT organization | +| `hub-and-spoke-multi-region.tfvars` | Regional hubs, Landing Zones and platform clusters in `eu01`/`eu02` | + +**Important limitations and implications:** + +- Templates contain placeholders and commented-out optional features. An HCL parser alone therefore does not discover all functionality. An explicit feature catalogue is needed. +- `src/providers.tf` supports static regional aliases for `eu01` and `eu02`. The UI must not present further regions as automatically supported. +- `connectivity_regions` is modeled as `map(any)`. Business-level UI validation must go beyond Terraform type checking. +- According to repository documentation, a project belongs to exactly one SNA; multiple SNAs or regions are not automatically privately connected. +- `firewall_config` currently configures one appliance. Multiple appliances do not imply automatic policy distribution. This remains a visible limitation. +- Firewall bootstrap needs multiple steps, an image and shell tools. The guide describes an initially public admin interface with a shared initial password. Approve automation only after secure bootstrap and password rotation. +- Private firewall/Kubernetes endpoints need suitable Runner connectivity. Central CF operation alone does not provide it. +- Backend is commented out; the guide migrates local state into the created management bucket only after initial provisioning. Short-lived Runners, however, need remote state before the first run. +- `mise.toml` pins OpenTofu `1.12.6`; `src/terraform.tf` requires at least `1.11`. README/Getting Started sometimes state different minimum versions. Recommendation: first qualify pinned OpenTofu; test Terraform separately as another engine. +- Repository promises no blanket migration compatibility. Upgrades need explicit migration, version checking and a new Plan. +- Network isolation of the “Tenant Isolation” template does not replace tenant separation in the central application. + + +## 3. Target architecture + +Recommendation: modular backend service with clear internal boundaries; Terraform execution as a separate runtime. No unnecessary division into many microservices at the start. ```mermaid flowchart TB @@ -124,91 +117,100 @@ flowchart TB B --> SM ``` -| Baustein | Empfehlung | Verantwortung | +| Component | Recommendation | Responsibility | | --- | --- | --- | -| Frontend | React/TypeScript mit Vite; Graph-Bibliothek noch auswählen | Wizard, Fachformulare, Topologie, Chat und Run-Ansicht | -| Backend/BFF | TypeScript mit Fastify auf Node.js 24 LTS | Sessions, Autorisierung, GitHub, Konfiguration, Chat-Orchestrierung | -| HCL-Adapter | Kleiner Go-Adapter mit HCL-Parser | Bestehende `.tfvars` strukturiert lesen, keine Regex-Konvertierung | -| Konfigurationskern | Versioniertes JSON Schema, Fachregeln und Compiler | Gemeinsamer Vertrag für Editor, Import, Chat und Ausgabe | -| Datenbank | STACKIT PostgreSQL Flex | Mandanten, Entwürfe, Revisionen, Runs, Audit und Queue | -| Scheduler/Queue | Durable PostgreSQL-Queue und separater CF-Prozess | Leases, Heartbeats, Wiederaufnahme, faire Mandantenquoten | -| Secrets | STACKIT Secrets Manager, nach Prüfung der erforderlichen Policies | DB enthält Referenzen; keine Klartext-Credentials | -| Artefakte | STACKIT Object Storage | Geschützte Plans, bereinigte Logs und Laufmanifest | -| Runner | Unveränderliches Artefakt mit gepinnter Engine und Providern | Nur Credentials des konkreten Deployments | -| Chat | STACKIT Model Serving über Backend | Beratung und validierte Vorschläge; keine Ausführungsrechte | +| Frontend | React/TypeScript with Vite; graph library still to select | Wizard, business forms, topology, chat and run view | +| Backend/BFF | TypeScript with Fastify on Node.js 24 LTS | Sessions, authorization, GitHub, configuration, chat orchestration | +| HCL adapter | Small Go adapter with HCL parser | Read existing `.tfvars` structurally, no regex conversion | +| Configuration core | Versioned JSON Schema, domain rules and compiler | Common contract for editor, import, chat and output | +| Database | STACKIT PostgreSQL Flex | Tenants, drafts, revisions, runs, audit and queue | +| Scheduler/queue | Durable PostgreSQL queue and separate CF process | Leases, heartbeats, recovery, fair tenant quotas | +| Secrets | STACKIT Secrets Manager, after checking required policies | DB contains references; no plaintext credentials | +| Artifacts | STACKIT Object Storage | Protected plans, sanitized logs and run manifest | +| Runner | Immutable artifact with pinned engine and providers | Only credentials of the specific deployment | +| Chat | STACKIT Model Serving through backend | Advice and validated proposals; no execution permissions | -PostgreSQL Flex ist als verwalteter Dienst dokumentiert und unterstützt Verwaltung über Terraform und Cloud Foundry. Konkrete Region, Plan, HA, Backup, ACLs und CF-Anbindung sind vor Provisionierung festzulegen. [PostgreSQL Flex](https://docs.stackit.cloud/products/databases/postgresql-flex/) +PostgreSQL Flex is documented as a managed service and supports management through Terraform and Cloud Foundry. Specific region, plan, HA, backup, ACLs and CF binding must be defined before provisioning. [PostgreSQL Flex](https://docs.stackit.cloud/products/databases/postgresql-flex/) -### CF-Hosting und Runner + +### CF hosting and Runner -Web/API sowie Scheduler/Dispatcher laufen auf CF. Sessions und Jobs werden extern gespeichert. Mehrere Web-Instanzen, Health Checks, DB-Pooling und rückwärtskompatible DB-Migrationen vorsehen. SSE für Fortschritt/Chat, Polling als Rückfalloption; Proxy-Timeouts und Wiederverbindung testen. +Web/API and scheduler/dispatcher run on CF. Sessions and jobs are stored externally. Plan for multiple web instances, health checks, DB pooling and backward-compatible DB migrations. SSE for progress/chat, polling as fallback; test proxy timeouts and reconnection. -STACKIT dokumentiert für Prozesse/Tasks bis zu 32 GB RAM und 6 GB flüchtigen lokalen Speicher. Das lokale Dateisystem ist nicht persistent. Diese Grenzen sind besonders für Provider-Binaries, Firewall-Image und Plan-Artefakte zu prüfen. [Anwendungsanforderungen](https://docs.stackit.cloud/products/runtime/cloud-foundry/basics/requirements-for-applications/) +STACKIT documents up to 32 GB RAM and 6 GB ephemeral local storage for processes/tasks. The local filesystem is not persistent. Check these limits especially for provider binaries, firewall image and plan artifacts. [Application requirements](https://docs.stackit.cloud/products/runtime/cloud-foundry/basics/requirements-for-applications/) -CF Tasks laufen in eigenen Containern, erben aber Umgebungsvariablen, Bindings und Security Groups ihrer App. Deshalb **keine Terraform-Task der Backend-App** starten. Empfohlen ist eine eigene Runner-App ohne Backend-Bindings, bei Bedarf mit separaten Apps/Spaces pro Kunde. Ob dies die geforderte Isolation und private Erreichbarkeit bietet, ist durch Tests zu belegen. Logs von Tasks fließen in die App-Logs; Redaktion muss deshalb vor stdout/stderr erfolgen. [CF Tasks](https://docs.cloudfoundry.org/devguide/using-tasks.html) +CF tasks run in their own containers but inherit their app's environment variables, bindings and security groups. Therefore **do not start a Terraform task of the backend app**. A dedicated Runner app without backend bindings is recommended, if necessary with separate apps/spaces per customer. Tests must demonstrate whether this provides required isolation and private connectivity. Task logs flow into app logs; redaction must therefore happen before stdout/stderr. [CF tasks](https://docs.cloudfoundry.org/devguide/using-tasks.html) -Falls CF-Ressourcenlimits, Netzwerk oder Isolation nicht genügen: isolierte Jobs auf SKE oder kurzlebige Compute-Runner. Für private Ziele gegebenenfalls Runner im Kundennetz mit ausgehender Verbindung zur Steuerung. Die Webanwendung bleibt auf CF. Diese Erweiterung benötigt eine explizite Architekturentscheidung. +If CF resource limits, network or isolation are insufficient: isolated jobs on SKE or short-lived compute Runners. For private targets, possibly Runners in customer networks with outbound control connection. Web application remains on CF. This extension needs an explicit architecture decision. -**Freigabekriterium:** Ein Runner erreicht weder andere Kunden-Secrets/States noch Model-Serving-Credentials oder die App-Datenbank. Eigener Ordner allein genügt nicht. Auch freigegebener Terraform-Code führt Provider und teilweise Skripte aus. +**Approval criterion:** A Runner can access neither other customers' secrets/states, Model Serving credentials nor app database. A separate directory alone is insufficient. Even approved Terraform code executes providers and sometimes scripts. -## 4. Mandantenmodell und Berechtigungen + +## 4. Tenant model and permissions -Ein Tenant repräsentiert eine Kundenorganisation. Darunter liegen Workspaces, Repository-Verbindungen, Konfigurationen und Deployments. Benutzer können Mitglied mehrerer Tenants sein; der aktuelle Kontext muss im UI jederzeit sichtbar sein. GitHub-Organisation, App-Tenant und STACKIT-Organisation sind unterschiedliche Objekte mit expliziter Zuordnung. +A tenant represents a customer organization. Under it are workspaces, repository connections, configurations and deployments. Users can belong to multiple tenants; current context must always be visible in the UI. GitHub organization, app tenant and STACKIT organization are distinct objects with explicit mapping. -Empfehlung für den Start: gemeinsame PostgreSQL-Instanz mit `tenant_id` auf allen Kundenobjekten und Row-Level Security als zusätzliche Schutzschicht. Rollen und DB-Zugänge so gestalten, dass der Anwendungspfad RLS nicht umgeht. Separate Datenbanken/Instanzen für erhöhte Isolationsanforderungen als spätere Betriebsoption. Secrets, State, Artefakte, Queue, Caches und Chat-Verlauf brauchen dieselbe Trennung; ein DB-Filter alleine reicht nicht. +Initial recommendation: shared PostgreSQL instance with `tenant_id` on all customer objects and row-level security as an additional protection layer. Design roles and DB access so the application path does not bypass RLS. Separate databases/instances for heightened isolation requirements as a later operational option. Secrets, state, artifacts, queue, caches and chat history need the same separation; a DB filter alone is insufficient. -- Tenant-Mitgliedschaft nur durch bestätigte Einladung/Administration oder verifizierte Organisationszuordnung; keine automatische Zuordnung anhand einer E-Mail-Domain. -- Rollen: Viewer, Editor, Deployer, Tenant-Admin. Credential-Nutzung wird zusätzlich autorisiert. -- GitHub-Rechte bei Repository-Aktionen weiterhin prüfen; eine App-Rolle erweitert keine GitHub-Berechtigung. -- Persönliche Credentials sind standardmäßig privat. Freigabe an Workspace oder Hintergrundjob braucht eine explizite, widerrufbare Delegation. -- Jeder Request und jeder Job wird serverseitig auf Tenant, Workspace und Objekt autorisiert. IDs im Request sind kein Berechtigungsnachweis. -- Rate Limits, aktive Runner, Queue-Anteil, Artefaktspeicher und KI-Budget pro Tenant begrenzen; kein Kunde darf alle Kapazitäten belegen. -- Betreiberzugriffe als nachvollziehbaren Notfallprozess gestalten. Keine normale Support-Oberfläche zur Anzeige von Kundensecrets. -- Bereits vor erster externer Freigabe Negativtests für horizontale Zugriffe, fremde Job-IDs, Artefakt-URLs, Cache-Schlüssel, Secret-Referenzen und Chat-Sessions. +- Tenant membership only through confirmed invitation/administration or verified organization assignment; no automatic mapping by email domain. +- Roles: Viewer, Editor, Deployer, Tenant Admin. Credential use is additionally authorized. +- Continue checking GitHub permissions for repository actions; an app role extends no GitHub permission. +- Personal credentials are private by default. Sharing with workspace or background job needs explicit revocable delegation. +- Every request and job is authorized server-side for tenant, workspace and object. Request IDs are not permission evidence. +- Limit rate, active Runners, queue share, artifact storage and AI budget per tenant; no customer may consume all capacity. +- Design operator access as a traceable emergency process. No normal support UI displaying customer secrets. +- Before the first external release, negative tests for horizontal access, foreign job IDs, artifact URLs, cache keys, secret references and chat sessions. -## 5. Benutzerablauf + +## 5. User workflow -1. **Anmelden und Tenant wählen:** GitHub verbinden, eigenen Kundenkontext erstellen oder Einladung annehmen. -2. **Repository auswählen:** vorhandenen zugänglichen Fork auswählen oder einen neuen erstellen; Schreibrechte prüfen. -3. **Template kopieren:** Zielbild, Features, Grenzen und Voraussetzungen sehen; eigene Konfigurations-ID und Name vergeben. -4. **Gestalten:** Wizard oder Chat; beide arbeiten auf demselben fachlichen Modell. Topologie reagiert auf validierte Änderungen. -5. **Überprüfen und speichern:** Diff zeigen; Repository, Branch und Pfad sichtbar machen; Git-Commit oder optional PR erstellen. -6. **Deployment vorbereiten:** Zielorganisation, Region, Credential-Profil, Remote State und Runner-Netz prüfen. -7. **Plan:** feste Revision verwenden; Create/Update/Delete/Replace fachlich erklären. -8. **Apply:** konkreten Plan ausdrücklich freigeben; Fortschritt und Fehler verfolgen. -9. **Betrieb:** zuletzt erfolgreich ausgerollte Revision, letzten bekannten Ist-Stand und optionale Drift-Prüfungen sehen. +1. **Sign in and choose tenant:** Connect GitHub, create own customer context or accept invitation. +2. **Select repository:** Choose an existing accessible fork or create a new one; check write permission. +3. **Copy template:** See target design, features, limitations and prerequisites; assign own configuration ID and name. +4. **Design:** Wizard or chat; both work on the same business model. Topology responds to validated changes. +5. **Review and save:** Show diff; make repository, branch and path visible; create Git commit or optional PR. +6. **Prepare deployment:** Check target organization, region, credential profile, remote state and Runner network. +7. **Plan:** Use fixed revision; explain Create/Update/Delete/Replace in business terms. +8. **Apply:** Explicitly approve the specific plan; follow progress and errors. +9. **Operate:** See last successfully deployed revision, last known actual state and optional drift checks. -Navigation: Dashboard, Templates, Konfigurationen, grafischer Editor mit Chat, Repository-Verbindungen, Deployment-Profile, persönliche Credentials, Runs/Drift und Tenant-Verwaltung. Begriffe wie „Netzwerkbereich“ ersetzen Terraform-Variablennamen im normalen Ablauf. Technische Details bleiben für Diagnose und Export verfügbar. +Navigation: dashboard, templates, configurations, graphical editor with chat, repository connections, deployment profiles, personal credentials, runs/drift and tenant management. Terms such as “network area” replace Terraform variable names in normal use. Technical details remain available for diagnostics and export. -## 6. GitHub und Login + +## 6. GitHub and login -### Benutzergebundener Zugriff + +### User-bound access -Empfehlung: GitHub App mit User Authorization und User Access Tokens. Jeder Benutzer autorisiert die App selbst. Repository-Aktionen nutzen ausschließlich seinen Token, keine Installation Tokens und keinen zentralen PAT. Die Rechte sind durch Benutzerrechte, App-Berechtigungen und Installation begrenzt. [Benutzerbezogene GitHub-App-Authentisierung](https://docs.github.com/en/enterprise-cloud%40latest/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-with-a-github-app-on-behalf-of-a-user) +Recommendation: GitHub App with user authorization and user access tokens. Every user authorizes the app themselves. Repository actions use exclusively their token, no installation tokens or central PAT. Rights are limited by user permissions, app permissions and installation. [User-based GitHub App authentication](https://docs.github.com/en/enterprise-cloud%40latest/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-with-a-github-app-on-behalf-of-a-user) -OAuth-State, sichere Callback-Allowlist, unterstütztes PKCE, CSRF-Schutz und sichere HttpOnly-/Secure-/SameSite-Sessions vorsehen. Tokens nur serverseitig im Secret Store halten. Ablauf, Refresh, Widerruf, SSO und Organisationsrichtlinien testen. Repo-Zugriffe nach Rechteentzug blockieren. Repositories über stabile GitHub-IDs referenzieren. +Provide OAuth state, secure callback allowlist, supported PKCE, CSRF protection and secure HttpOnly/Secure/SameSite sessions. Keep tokens only server-side in the secret store. Test expiry, refresh, revocation, SSO and organization policies. Block repository access after revocation. Reference repositories through stable GitHub IDs. -**Wichtige Fork-Voraussetzung:** Laut GitHub benötigt das Fork-API bei GitHub Apps eine Installation am Zielaccount mit Zugriff auf alle Repositories sowie eine Installation am Quellaccount mit Zugriff auf das Quellrepo. Für diesen Endpunkt sind `Administration: write` und `Contents: read` angegeben. Die Erstellung läuft asynchron. Das ist ein zentraler Onboarding-Prüfpunkt, insbesondere für den Upstream `stackitcloud/stackit-landing-zone`. [Fork-API](https://docs.github.com/en/rest/repos/forks) +**Important fork prerequisite:** According to GitHub, the fork API for GitHub Apps needs an installation on the target account with all-repository access and an installation on the source account with access to the source repository. `Administration: write` and `Contents: read` are stated for this endpoint. Creation is asynchronous. This is a central onboarding check, especially for upstream `stackitcloud/stackit-landing-zone`. [Fork API](https://docs.github.com/en/rest/repos/forks) -Im Spike die vollständige Berechtigungsmatrix für Fork, Lesen, Branch/Commit und optional PR prüfen. Falls die nötige Quellinstallation oder Zielberechtigung nicht verfügbar ist: geführtes manuelles Forken in GitHub und anschließendes Verbinden; alternativ separat bewertete OAuth-App. Kein stiller Wechsel auf zentrale Credentials. Eine OAuth-App kann breitere Scopes benötigen; daher keine voreilige Festlegung nur aufgrund des einfacheren Fork-Ablaufs. [GitHub Apps und OAuth Apps](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps) +In the spike, check the full permission matrix for fork, read, branch/commit and optional PR. If required source installation or target permission is unavailable: guided manual forking in GitHub followed by connecting; alternatively a separately assessed OAuth App. No silent switch to central credentials. An OAuth App may need broader scopes; do not decide prematurely solely because forking is easier. [GitHub Apps and OAuth Apps](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps) -### Mehrere Forks und Speichern + +### Multiple forks and saving -Mehrere Repository-Verbindungen pro Benutzer/Tenant unterstützen, beispielsweise persönlicher Fork und Forks in berechtigten Organisationen. Nicht zusagen, dass beliebig viele echte Forks desselben Upstreams im selben Owner-Namespace möglich sind: die aktuelle Fork-Netzwerkgrenze im Spike prüfen. Mehrere Konfigurationen/Branches in einem Fork sind die bevorzugte Alternative; eine eigenständige Repository-Kopie wäre separat anzubieten und kein echter Fork. +Support multiple repository connections per user/tenant, e.g. personal fork and forks in authorized organizations. Do not promise arbitrary numbers of real forks of the same upstream in one owner namespace: check current fork-network limit in the spike. Multiple configurations/branches in one fork are the preferred alternative; a standalone repository copy would be offered separately and is not a real fork. -Fork-Erstellung idempotent behandeln, Bereitschaft pollen und Fehler verständlich anzeigen. Beim Speichern mehrere Dateien atomar committen und die erwartete Basisrevision prüfen. Konflikte nicht überschreiben. Geschützte Branches über Arbeitsbranch/PR bedienen. Webhooks signiert und idempotent verarbeiten; sie erlauben keinen automatischen Apply. +Handle fork creation idempotently, poll readiness and display understandable errors. At saving, commit multiple files atomically and check expected base revision. Do not overwrite conflicts. Use working branch/PR for protected branches. Process webhooks with signature checks and idempotency; they permit no automatic Apply. -### Optionaler STACKIT-IdP + +### Optional STACKIT IdP -Die gefundene STACKIT-Anleitung beschreibt Federation, bei der STACKIT als Relying Party einem externen IdP vertraut. Sie belegt **nicht**, dass Kunden eine eigene Web-App unkompliziert als OIDC-Client des STACKIT-IdP registrieren können. Daher Client-Registrierung, Discovery, Claims und Nutzungsfreigabe separat klären. GitHub bleibt der initiale Login. [STACKIT-IdP-Einstieg](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/getting-started/) +The STACKIT guide found describes federation where STACKIT as relying party trusts an external IdP. It **does not** demonstrate that customers can easily register their own web app as an OIDC client of the STACKIT IdP. Clarify client registration, discovery, claims and usage approval separately. GitHub remains initial login. [STACKIT IdP introduction](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/getting-started/) -Zusätzlicher IdP-Login erteilt weder GitHub- noch Cloud-API-Rechte. GitHub-Verbindung bleibt nötig. Identitäten nur nach Nachweis beider Konten verknüpfen, niemals allein über gleiche E-Mail-Adressen. +Additional IdP login grants neither GitHub nor cloud API permissions. GitHub connection remains necessary. Link identities only after proof of both accounts, never solely through equal email addresses. -## 7. Fachmodell, Templates und Compiler + +## 7. Business model, templates and compiler -### Versionierte Ablage + +### Versioned storage -Vorschlag für UI-Konfigurationen im ausgewählten Fork: +Proposed UI configuration storage in the selected fork: ```text src/config/custom// @@ -217,84 +219,90 @@ src/config/custom// manifest.json # Schema-, Compiler-, Template-/Accelerator-Versionen ``` -Das Fachmodell ist die Quelle für UI-verwaltete Konfigurationen. Die generierte Datei ermöglicht weiterhin CLI-Nutzung. Vor Runs neu kompilieren und Hash vergleichen; manuelle Änderungen an generierten Dateien als Konflikt behandeln. Originale `.tfvars` bleiben erhalten. Importbericht für unbekannte Felder und Kommentarverlust; keine stillschweigende Löschung nicht unterstützter Einstellungen. +The business model is the source for UI-managed configurations. Generated file continues to enable CLI use. Recompile and compare hashes before runs; treat manual changes to generated files as a conflict. Original `.tfvars` are retained. Import report for unknown fields and comment loss; no silent deletion of unsupported settings. -Manifest: Template-Pfad/-Commit, Accelerator-Commit/Release, Schema-/Compiler-Version und Content-Hashes. Deployment-Bindings und Secret-Referenzen liegen außerhalb von Git. DB-Entwürfe sind nicht „gespeichert“, bevor der Git-Commit erfolgreich war. Runs verwenden ausschließlich unveränderliche Git-Revisionen. +Manifest: template path/commit, Accelerator commit/release, schema/compiler version and content hashes. Deployment bindings and secret references live outside Git. DB drafts are not “saved” until the Git commit succeeds. Runs use exclusively immutable Git revisions. -Der Template-Katalog startet mit den acht Upstream-Dateien einer freigegebenen Version. Fork-spezifische Konfigurationen sind eigene Konfigurationen und nicht automatisch vertrauenswürdige globale Templates. Upstream-Updates zunächst als explizites Upgrade mit Diff und Migration anbieten. Rollback einer Konfiguration bedeutet neue Revision und neuen Plan, nicht automatischen Infrastruktur-Rollback. +Template catalogue starts with the eight upstream files of an approved version. Fork-specific configurations are own configurations, not automatically trusted global templates. Initially offer upstream updates as explicit upgrades with diff and migration. Configuration rollback means new revision and Plan, not automatic infrastructure rollback. -### Feature-Katalog + +### Feature catalogue -| Fachbereich | Repo-Bezug | UI-Verhalten und Regeln | +| Business area | Repository reference | UI behavior and rules | | --- | --- | --- | -| Organisation | Owner, Firma/-code, Organisations-ID, Labels, Parent-Folder | Pflichtwerte, Platzhalter ersetzen, gültige Referenzen | -| Governance | `rm_folders`, Organisationseigentümer/-auditoren, Rollen | Hierarchie und Rollenmodell | -| Management | State-Bucket, Secrets Manager, Service Accounts, Federation | Bootstrap- und Betriebsidentität unterscheiden | -| Observability/Audit | `observability`, `audit_logs` | Retention, Zugriff, Folgen von Object Lock erklären | -| Konnektivität | `connectivity`, `connectivity_regions` | SNA, CIDRs, DNS, regionale Zuordnungen | -| Firewall/VPN | Firewall/HA, `firewall_config`, VPN | Erreichbarkeit, Bootstrap und Grenzen der Traffic-Inspektion | -| Landing Zones | `landing_zones`, Modul `landing-zone` | Projekte, Owner, Umgebung, RBAC, Netz, DNS, Buckets, Secrets | -| Kubernetes-Plattform | `platform_kubernetes` | Cluster, Node Pools, Netz, verschlüsselte Volumes, Bastion | -| Kubernetes-Services | `landing_zone_namespace_services`, Namespace-Demo, Root-Kubernetes-Ressourcen | Plattformabhängigkeiten und erreichbarer API-Endpunkt | -| DevOps | `devops` | Git-Service und zulässige Netzwerkbereiche | -| Sandboxes | `sandboxes` | Projekt und Owner | +| Organization | Owner, company/code, organization ID, labels, parent folder | Required values, replace placeholders, valid references | +| Governance | `rm_folders`, organization owners/auditors, roles | Hierarchy and role model | +| Management | State bucket, Secrets Manager, service accounts, federation | Distinguish bootstrap and operating identity | +| Observability/audit | `observability`, `audit_logs` | Explain retention, access, Object Lock consequences | +| Connectivity | `connectivity`, `connectivity_regions` | SNA, CIDRs, DNS, regional assignments | +| Firewall/VPN | Firewall/HA, `firewall_config`, VPN | Connectivity, bootstrap and traffic-inspection limits | +| Landing Zones | `landing_zones`, module `landing-zone` | Projects, owners, environment, RBAC, network, DNS, buckets, secrets | +| Kubernetes platform | `platform_kubernetes` | Cluster, node pools, network, encrypted volumes, bastion | +| Kubernetes services | `landing_zone_namespace_services`, namespace demo, root Kubernetes resources | Platform dependencies and reachable API endpoint | +| DevOps | `devops` | Git service and permitted network areas | +| Sandboxes | `sandboxes` | Project and owner | -Jedes Feature erhält eine stabile ID, Fachtext, Mapping, Defaultwerte, Abhängigkeiten, Regionsgrenzen, Secret-Bedarf, Compiler-Regeln, Grafik-Semantik und Tests. Struktur teilweise aus HCL ableiten; Fachtexte/Abhängigkeiten explizit pflegen. CI meldet Änderungen an Variablen/Modulen ohne aktualisierten Katalog. +Every feature receives a stable ID, business description, mapping, defaults, dependencies, regional limits, secret needs, compiler rules, graph semantics and tests. Derive structure partly from HCL; maintain business descriptions/dependencies explicitly. CI reports variable/module changes without updated catalogue. -Validierung: Referenzen zwischen Bereichen/Landing Zones/Clustern, Namensregeln, unterstützte Regionen und Kombinationen, CIDR-Konflikte in verbundenen Netzen. Wiederverwendete Adressbereiche in tatsächlich isolierten Netzen gesondert bewerten. Stabile Terraform-Ressourcenschlüssel erhalten; eine Umbenennung darf kein unsichtbares Destroy/Create erzeugen. +Validation: references between areas/Landing Zones/clusters, naming rules, supported regions and combinations, CIDR conflicts in connected networks. Assess reused address ranges in genuinely isolated networks separately. Preserve stable Terraform resource keys; renaming must not cause invisible Destroy/Create. -Pro Feature getrennt kennzeichnen: **darstellbar, editierbar, planbar, ausführbar**. Ein importierbares Firewall-Template ist noch nicht vollständig automatisiert deploybar. +Label each feature separately: **displayable, editable, plannable, executable**. An importable firewall template is not yet fully automatically deployable. -### Grenze zum Terraform-Code + +### Boundary with Terraform code -Der Compiler erzeugt nur Daten, keine frei eingegebenen HCL-Ausdrücke oder Shell-Kommandos. Im MVP wird Accelerator-Code anhand eines freigegebenen Commits materialisiert; aus dem Benutzer-Fork werden nur erlaubte Konfigurationsdateien gelesen. Abweichende Module klar melden. Keine beliebigen `.auto.tfvars`, Provider, Backend-Dateien oder Skripte aus Forks implizit mitladen. +Compiler generates only data, no freely entered HCL expressions or shell commands. In MVP, Accelerator code is materialized at an approved commit; only permitted configuration files are read from the user fork. Clearly report divergent modules. Do not implicitly load arbitrary `.auto.tfvars`, providers, backend files or scripts from forks. -Eigener Terraform-Code ist ein späterer Vertrauensmodus mit stärkerer Isolation und expliziten Provider-/Modul-/Netzrichtlinien. Die aktuelle Einschränkung sichtbar machen, weil das Repo grundsätzlich Modul-Anpassungen vorsieht. +Custom Terraform code is a later trust mode with stronger isolation and explicit provider/module/network policies. Make current restriction visible because the repository generally permits module customization. -## 8. Credentials und Persistenz + +## 8. Credentials and persistence -| Kategorie | Ablage / Eigentümer | Verwendung | +| Category | Storage / owner | Use | | --- | --- | --- | -| GitHub User-/Refresh-Token | Secret Store, persönlicher Benutzer | Repository-Zugriff im Benutzerauftrag | -| STACKIT Service Account Key bzw. unterstützte Federation | Persönliches oder explizit geteiltes Deployment-Profil | Zugeordnetes Kunden-Deployment | -| S3-Backend-Zugang | Deployment-Profil | Genau zugehöriger State-Bereich | -| VPN-PSKs, Firewall-Login/API-Key, ggf. Kubeconfig | Secret Store je Deployment | Nur benötigte Laufphase | -| Model-Serving-Token | Betreiber, CF-Variablen des Backends | Chat-Service | -| CF-/DB-/Secret-Betriebsidentität | Betreiber | Plattformbetrieb, keine Kunden-Cloud-Vollmacht | +| GitHub user/refresh token | Secret store, personal user | Repository access on user's behalf | +| STACKIT service-account key or supported federation | Personal or explicitly shared deployment profile | Assigned customer deployment | +| S3 backend access | Deployment profile | Exactly associated state area | +| VPN PSKs, firewall login/API key, possibly kubeconfig | Secret store per deployment | Only required run phase | +| Model Serving token | Operator, backend CF variables | Chat service | +| CF/DB/secret operating identity | Operator | Platform operation, no customer-cloud authority | -„Credentials anlegen“ bedeutet zuerst Profil erstellen und vorhandene Credentials sicher hinterlegen. Neue STACKIT-Service-Accounts/Schlüssel kann die App nur mit explizit delegierten Cloud-Rechten erzeugen; GitHub-Login genügt nicht. Später kurzlebige Federation bevorzugen, sofern die benötigten Flows unterstützt sind. +“Create credentials” initially means creating a profile and securely storing existing credentials. The app can create new STACKIT service accounts/keys only with explicitly delegated cloud permissions; GitHub login is insufficient. Later prefer short-lived federation if required flows are supported. -STACKIT Secrets Manager auf Mandanten-Policies, Credential-Lifecycle und runbezogene Ausgabe prüfen. Keine Annahme, dass beliebige Vault-Features im Managed Service verfügbar sind. Bei fehlenden Fähigkeiten eine explizite Alternative entscheiden, z. B. tenantgetrennte Secret-Instanzen oder geprüfte Envelope-Verschlüsselung mit separat verwalteten Schlüsseln; kein unverschlüsselter DB-Fallback. +Check STACKIT Secrets Manager for tenant policies, credential lifecycle and run-specific issuance. Do not assume arbitrary Vault features are available in the managed service. If capabilities are missing, decide an explicit alternative, e.g. tenant-separated secret instances or reviewed envelope encryption with separately managed keys; no unencrypted DB fallback. -Runner erhalten nur ein kurzlebiges, auf Run und Secret-Version begrenztes Ausgabeticket. Kein allgemeines Secret-Store-Token. Persönliche Profile zeigen Status, Zweck, Ablauf und „Ersetzen/Widerrufen“, keine Rohwerte. Rotation, Backup, Wiederherstellung und Notfallzugriff planen. +Runners receive only a short-lived issuance ticket limited to run and secret version. No general secret-store token. Personal profiles show status, purpose, expiry and “Replace/Revoke”, no raw values. Plan rotation, backup, restoration and emergency access. -`Sensitive`-Markierungen verhindern nicht, dass Terraform-State oder gespeicherte Plans Secrets enthalten. Diese Artefakte wie Secrets schützen. Browser, Git, Chat, Audit und normale Logs erhalten keine Roh-Secrets. Frei angegebene Endpoints gegen SSRF absichern; Zielnetze per Profil freigeben statt beliebige interne Adressen vom Backend anzusprechen. +`Sensitive` markings do not prevent Terraform state or saved plans from containing secrets. Protect these artifacts like secrets. Browser, Git, chat, audit and ordinary logs receive no raw secrets. Protect freely specified endpoints against SSRF; approve target networks per profile rather than addressing arbitrary internal addresses from the backend. -### Datenmodell + +### Data model -Alle Kundenobjekte tragen `tenant_id`, gegebenenfalls `workspace_id`, serverseitig geprüft. +All customer objects carry `tenant_id`, optionally `workspace_id`, checked server-side. -| Entität | Inhalt | +| Entity | Content | | --- | --- | -| User / Identity / Session | Interne UUID, Provider-ID, verknüpfte Identitäten, Session-Lifecycle | -| Tenant / Workspace / Membership | Kundenkontext, Mitgliedschaft, Rollen und Einladungen | -| RepositoryConnection | GitHub-ID, Benutzerautorisierung, Branch, Zugriffsstatus | -| TemplateVersion | Pfad/Commit, Metadaten, unterstützte Features | -| Configuration / Revision | Fachmodell, Schema, Git-Ziel, Basis-SHA und Speicherstatus | -| CredentialProfile / Delegation | Secret-Referenz/-Version, Besitzer, erlaubte Nutzung, Ablauf | -| Deployment | Revision, Zielorganisation, Backend-/State-ID und Runner-Profil | -| Run / Approval / Artifact | Status, Manifest, Plan-Hash, Freigabe, Ergebnis und Artefaktreferenzen | -| DriftSchedule / DriftFinding | Opt-in, Referenzrevision, Prüfung und Korrekturpolicy | -| ChatSession / Proposal | Versionskontext, Rückfragen, Patch und Übernahmezustand | -| AuditEvent | Akteur, Aktion, Ressource, Zeit, Ergebnis; keine Secret-Werte | +| User / Identity / Session | Internal UUID, provider ID, linked identities, session lifecycle | +| Tenant / Workspace / Membership | Customer context, membership, roles and invitations | +| RepositoryConnection | GitHub ID, user authorization, branch, access status | +| TemplateVersion | Path/commit, metadata, supported features | +| Configuration / Revision | Business model, schema, Git target, base SHA and save status | +| CredentialProfile / Delegation | Secret reference/version, owner, permitted use, expiry | +| Deployment | Revision, target organization, backend/state ID and Runner profile | +| Run / Approval / Artifact | Status, manifest, plan hash, approval, result and artifact references | +| DriftSchedule / DriftFinding | Opt-in, reference revision, check and correction policy | +| ChatSession / Proposal | Version context, follow-ups, patch and adoption state | +| AuditEvent | Actor, action, resource, time, result; no secret values | -Retention getrennt für Chat, Logs, Plans, Audit und State festlegen. State niemals mit normaler Artefaktbereinigung löschen. Konto-/Konfigurationslöschung zerstört keine Infrastruktur; Offboarding umfasst Export von Konfiguration/State, Entzug von Zugängen und dokumentierte Löschung verbleibender Daten. +Define retention separately for chat, logs, plans, audit and state. Never delete state through normal artifact cleanup. Account/configuration deletion destroys no infrastructure; offboarding includes configuration/state export, access revocation and documented deletion of remaining data. -## 9. Plan, Apply und State + +## 9. Plan, Apply and state -### Unveränderlicher Laufvertrag + +### Immutable run contract -Jeder Run bindet Tenant, Deployment, Git-Commit, Config-Hash, Accelerator-Commit, Schema-/Compiler-Version, Engine-Version, Provider-Lockfile, Runner-Artefakt-Digest, Backend-/State-ID und relevante Credential-Versionen. +Every run binds tenant, deployment, Git commit, configuration hash, Accelerator commit, schema/compiler version, engine version, provider lockfile, Runner artifact digest, backend/state ID and relevant credential versions. ```mermaid stateDiagram-v2 @@ -314,122 +322,115 @@ stateDiagram-v2 Applying --> ReconciliationRequired: Prozessstatus unklar ``` -1. Berechtigung, Profil, Kompatibilität, Quota, Backend und Erreichbarkeit prüfen. -2. Geprüften Code und genau eine ausgewählte Konfiguration materialisieren; Backend-Einstellungen ohne Secrets im Git erzeugen. -3. `init` mit festgelegtem Backend und gepinnten Providern; `validate` und Fach-/Policy-Prüfungen. -4. `plan -out= -detailed-exitcode`: 0 = keine Änderungen, 2 = Änderungen, 1 = Fehler. CLI-Vertrag mit gepinnter Engine testen. -5. `show -json` auswerten, sensible Werte anhand der Sensitivitätsmarkierungen und zusätzlicher Regeln redigieren. Roh-JSON nie direkt an Browser oder Chat geben. -6. Create/Update/Delete/Replace und unbekannte Werte zeigen; Auswirkungen auf Fachobjekte erklären. Kosten nur bei belastbarer Datenquelle als Schätzung kennzeichnen. -7. Freigabe an Plan-Hash und Manifest binden; Genehmiger und Zeitpunkt protokollieren. Tenant-Policy kann Vier-Augen-Freigabe verlangen. -8. Exakt den gespeicherten Binär-Plan mit gleicher Engine/Plattform anwenden. Geänderte Revision, State oder relevante Ausführungsbedingungen erfordern neuen Plan und neue Freigabe. -9. Ergebnis, State-Version und bereinigte Outputs persistieren; temporäre Secrets/Dateien entfernen. +1. Check permission, profile, compatibility, quota, backend and connectivity. +2. Materialize checked code and exactly one selected configuration; generate backend settings without secrets in Git. +3. `init` with defined backend and pinned providers; `validate` and domain/policy checks. +4. `plan -out= -detailed-exitcode`: 0 = no changes, 2 = changes, 1 = error. Test CLI contract with pinned engine. +5. Evaluate `show -json`, redact sensitive values using sensitivity markings and additional rules. Never give raw JSON directly to browser or chat. +6. Show Create/Update/Delete/Replace and unknown values; explain effects on business objects. Label costs as estimates only with a sound data source. +7. Bind approval to plan hash and manifest; record approver and time. Tenant policy can require two-person approval. +8. Apply exactly the saved binary plan with same engine/platform. Changed revision, state or relevant execution conditions require new Plan and approval. +9. Persist result, state version and sanitized outputs; remove temporary secrets/files. -Plan-Gültigkeit begrenzen. Cloud-Änderungen außerhalb des Systems können während der Freigabezeit stattfinden; State-Vergleich allein erkennt nicht alles. Bei erkanntem Risiko neu planen. Kein unbemerkter Re-Plan zwischen Freigabe und Apply. +Limit plan validity. Cloud changes outside the system can occur during approval time; state comparison alone does not detect everything. Replan on detected risk. No unnoticed replan between approval and Apply. -### Remote State und Sperren + +### Remote state and locks -Entscheidung 2026-09-30: dem vorhandenen LZA-Bootstrap folgen. Der erste Plan einer -expliziten Neuanlage verwendet lokalen leeren State und die bereits hinterlegten -Bootstrap-Credentials. Beim separat freigegebenen ersten Apply erstellt das Management- -Modul das spätere Kunden-Backend. Danach State exklusiv mit `tofu init -migrate-state` -migrieren, überprüfen und auf den Management-Service-Account wechseln. +Decision 2026-09-30: follow existing LZA bootstrap. The first Plan for explicitly new creation uses local empty state and already stored bootstrap credentials. At the separately approved first Apply, the management module creates the future customer backend. Then migrate state exclusively with `tofu init -migrate-state`, verify and switch to the management service account. -Der Configurator muss den anfänglichen State dauerhaft und verschlüsselt sichern, -auch bei Runner-Verlust und partiellem Apply. Diese Recovery ist Voraussetzung für -Apply. Vorhandene Deployments dürfen nie als neue leere States geplant werden. -Kein zusätzlicher dauerhafter zentraler Kunden-State-Bucket. Plattform-IaC und -Kunden-Deployments teilen niemals einen State. [Details](plan-execution.md). +Configurator must durably and encryptedly save initial state, including Runner loss and partial Apply. This recovery is a prerequisite for Apply. Existing deployments must never be planned as new empty states. No additional permanent central customer-state bucket. Platform IaC and customer deployments never share state. [Details](plan-execution.md). -- Backend-Locking mit gewählter Engine und STACKIT Object Storage praktisch testen, einschließlich konkurrierendem CLI-Zugriff. S3-Kompatibilität ist kein Locking-Nachweis. -- Zusätzlich DB-Lease pro kanonischer State-ID; doppelte Deployment-Registrierung desselben States verhindern. Lease ersetzt Backend-Lock nicht. -- Versionierung, Verschlüsselung, Restore-Test und protokollierte manuelle Entsperrung vor Produktivfreigabe. -- Bei Runner-Absturz nicht blind erneut Apply ausführen. Prozessstatus, Lock und State abgleichen; gegebenenfalls neuen Plan erstellen. -- Apply kann teilweise erfolgreich sein. Kein automatischer Rollback; Wiederherstellung über neuen Plan. Abbruch ist best effort und kann Teiländerungen hinterlassen. -- Ein Deployment entspricht zunächst einem Accelerator-Root. Größere State-Aufteilung benötigt gesonderte Migrations- und Abhängigkeitsplanung. +- Practically test backend locking with selected engine and STACKIT Object Storage, including concurrent CLI access. S3 compatibility is not locking evidence. +- Additionally, DB lease per canonical state ID; prevent duplicate deployment registration of the same state. Lease does not replace backend lock. +- Versioning, encryption, restore test and logged manual unlock before production release. +- Do not blindly repeat Apply after Runner crash. Reconcile process status, lock and state; create new Plan if needed. +- Apply can succeed partially. No automatic rollback; recovery through new Plan. Cancellation is best effort and can leave partial changes. +- Initially one deployment corresponds to one Accelerator root. Larger state splitting needs separate migration and dependency planning. -### Spezielle Runbooks + +### Special runbooks -Firewall-Bootstrap, Policy-Konfiguration, Secret-Übergabe, HA und gegebenenfalls Kubernetes-Provider-Bootstrap als versionierte Abläufe implementieren. Jede schreibende Phase mit verändertem Plan benötigt eine passende Freigabe. Kein UI für beliebige `-target`-Argumente. +Implement firewall bootstrap, policy configuration, secret handover, HA and possibly Kubernetes provider bootstrap as versioned workflows. Every writing phase with changed plan needs matching approval. No UI for arbitrary `-target` arguments. -Für Firewall: Image-Herkunft/Prüfsumme, Speicherbedarf, Werkzeuge, private API-Erreichbarkeit, Passwortrotation und TLS-Verifikation testen. Abbruch während offenem Admin-Interface muss sichtbar sein und eine konkrete Absicherungs-/Wiederaufnahmeanleitung bieten. Ohne erfolgreichen Nachweis diese Variante nicht als automatisiert ausführbar freigeben. +For firewall: test image provenance/checksum, storage needs, tools, private API connectivity, password rotation and TLS verification. An abort while the admin interface is open must be visible and provide concrete securing/resumption instructions. Without successful evidence, do not approve this variant as automatically executable. -## 10. Drift Detection und Correction + +## 10. Drift detection and correction -Pro Deployment: Aus, nur erkennen, nach Freigabe korrigieren, später eng begrenzte automatische Korrektur. Standard: Aus. Hintergrundnutzung von Credentials benötigt eine explizite widerrufbare Delegation, getrennt von einer interaktiven Session. +Per deployment: off, detect only, correct after approval, later narrowly bounded automatic correction. Default: off. Background credential use needs explicit revocable delegation separate from an interactive session. -- Referenz ist die zuletzt erfolgreich ausgerollte Git-/Accelerator-Revision, nicht der aktuelle Branch-Head. -- Refresh-only-Plan kann Unterschiede zwischen Cloud und State zeigen. Normaler Plan gegen dieselbe Revision zeigt die zur Soll-Wiederherstellung nötigen Änderungen. Beide Aussagen unterscheiden. -- Kein automatisches `apply -refresh-only`, um Befunde lediglich verschwinden zu lassen. -- Zeitpläne mit Jitter, Backoff, Mandantenquoten und Lauf-Sperren; keine Prüfung parallel zu schreibendem Run desselben States. -- API-Fehler oder abgelaufene Credentials bedeuten „Prüfung fehlgeschlagen“, nicht „keine Drift“. -- Correction stellt den genehmigten Sollzustand her. „Ist als Soll übernehmen“ ist separate Konfigurationsänderung mit Git-Commit und Review. -- Automatische Correction nur nach ausdrücklichem Opt-in mit testbarer Allowlist, Wartungsfenster, Ressourcenlimit, Audit und Not-Aus. -- Delete/Replace, IAM, Firewall-/Routing-Änderungen, Secret-Rotation und unbekannte Aktionen zunächst immer freigabepflichtig. -- Nach Fehlern pausieren statt Endlosschleife; neue Konfigurationsänderungen nie als Drift-Korrektur einschleusen. +- Reference is last successfully deployed Git/Accelerator revision, not current branch head. +- Refresh-only Plan can show cloud/state differences. Normal Plan against the same revision shows changes needed to restore desired state. Distinguish these statements. +- No automatic `apply -refresh-only` merely to make findings disappear. +- Schedules with jitter, backoff, tenant quotas and run locks; no checking parallel to a writing run on the same state. +- API errors or expired credentials mean “check failed”, not “no drift”. +- Correction restores approved desired state. “Adopt actual as desired” is a separate configuration change with Git commit and review. +- Automatic correction only after explicit opt-in with testable allowlist, maintenance window, resource limit, audit and emergency stop. +- Delete/Replace, IAM, firewall/routing changes, secret rotation and unknown actions initially always need approval. +- Pause after errors instead of looping; never smuggle new configuration changes in as drift correction. -## 11. Chatbot mit STACKIT Model Serving + +## 11. Chatbot with STACKIT Model Serving -### Bestätigte Produktentscheidungen (2026-10-10) + +### Confirmed product decisions (2026-10-10) -- Umfang: alle tatsächlich implementierten Configurator-Features werden dauerhaft 1:1 von der KI-Komponente abgedeckt, einschließlich komplexer Komponenten und ihrer Abhängigkeiten; nicht sämtliche STACKIT-Services. Eine versionsgebundene Abdeckungsmatrix macht Unterstützung und Ausführungsgrenzen sichtbar. Neue oder geänderte Features benötigen entsprechende Wissens-, Dialog-, Validierungs- und Testabdeckung im selben qualifizierten Release; bestehende Ausführungssperren werden dadurch nicht aufgehoben. -- Dialog: passende Konfigurationsvorlage auswählen, Wünsche schrittweise ergänzen und fehlende Details oder Widersprüche gezielt nachfragen. Vollständigkeit wird durch Schema und Fachregeln geprüft, nicht allein durch das Modell behauptet. -- Templates: vorhandene autorisierte Application Landing Zone Templates auswählen und neue Template-Entwürfe erstellen. Veröffentlichung bleibt eine separate Aktion berechtigter Platform Engineers. -- Bestandsänderungen: bestehende Konfiguration analysieren und revisionsgebundene Vorschläge im Chat-Arbeitsentwurf sammeln. Erst ein ausdrücklich bestätigter Gesamt-Diff ändert den Konfigurationsentwurf; keine automatische Änderung veröffentlichter Templates oder bestehender Instanzen. -- Wissen: aktuelle offizielle STACKIT-Informationen kontrolliert einlesen, Änderungen automatisch erkennen und vor Nutzung geprüft freigeben. Modul-, Provider- und Configurator-Wissen bleibt an die jeweilige Konfigurationsversion gebunden. Keine automatischen Upgrades und kein beliebiger Webzugriff durch das Modell. -- Modell: `Qwen/Qwen3-VL-235B-A22B-Instruct-FP8` als bevorzugter Startwert; Modell, Endpoint und technische Limits bleiben betreiberseitig konfigurierbar. Der vorhandene Terraform-provisionierte Dev-Token wird ausschließlich backendseitig verwendet. -- Eingaben: Text und Konfigurationen; keine Bilder im MVP. -- Scope-Entscheidung 2026-10-13: Geführte Firewall-Policy-Bearbeitung und - Assistant-Vorschläge für Regeln/NAT/Aliase/Routen sind Post-MVP - ([#101](https://github.com/stackitcloud/stackit-landing-zone/issues/101)). - Der Assistant benennt diese Grenze sofort; im MVP pflegt der Firewall-Admin - die Policy nach Bereitstellung manuell in OPNsense. Generische native - Editorfelder bleiben erhalten, sind aber kein Ausführungsnachweis. - Firewall-Infrastruktur/HA bleibt im Scope und garantiert allein keine - Isolation, Erreichbarkeit oder NAT. -- Zugang und Zweck: ausschließlich angemeldete Benutzer mit aktuell gültiger Session und passenden Tenant-/Konfigurationsrechten. Beratung und Vorschläge sind auf die oben genannten Configurator-Aufgaben beschränkt; serverseitige Werkzeug-, Schema- und Rechteprüfungen erzwingen diese Grenze. Keine allgemeine Chat-, Shell-, Secret- oder Cloud-Ausführungsfunktion. -- Budget: keine monetäre Budgetgrenze im MVP. Begrenzte Requestgrößen, Kontext-/Ausgabelängen, Parallelität, Anfrageraten, Timeouts und Reparaturversuche bleiben zum Missbrauchs- und Betriebsschutz erforderlich. Verbrauch wird secretfrei beobachtet. -- Gespräche: serverseitig persistent und nach erneuter Anmeldung fortsetzbar, mit verpflichtendem Bezug zu Tenant, Workspace und Konfiguration. Zugriff wird bei jedem Lesen, Fortsetzen und Übernehmen erneut geprüft. Die gebundene Ausgangsrevision wird mit der aktuellen Konfiguration abgeglichen; veraltete Vorschläge werden nicht ungeprüft übernommen. -- Löschung und Alter: Löschen einer Konfiguration oder ihres Workspaces löscht die zugehörigen Gespräche samt Nachrichten, Zusammenfassungen und Vorschlägen mit; keine verwaisten Gesprächsdaten. Maximales Gesprächsalter sind drei Kalendermonate ab Erstellung, nicht ab letzter Aktivität. Fortsetzen verlängert die Frist nicht. Nach Ablauf kann die weiterhin vorhandene Konfiguration in einem neuen Gespräch erneut analysiert werden. -- Lastziel: höchstens fünf gleichzeitige Chat-Sitzungen für die MVP-Abnahme. Dies ist kein Limit für die Anzahl gespeicherter Gespräche. Inferenzparallelität, begrenzte Warteschlange und Timeouts berücksichtigen zusätzlich die tatsächlichen Model-Serving-Limits. +- Scope: all actually implemented Configurator features are permanently covered 1:1 by the AI component, including complex components and dependencies; not all STACKIT services. A version-bound coverage matrix makes support and execution limitations visible. New or changed features need matching knowledge, dialogue, validation and test coverage in the same qualified release; this does not lift existing execution guards. +- Dialogue: select a suitable configuration template, incrementally add wishes and ask specifically about missing details or contradictions. Completeness is checked by schema and domain rules, not claimed solely by the model. +- Templates: select existing authorized Application Landing Zone templates and create new template drafts. Publication remains a separate action for authorized Platform Engineers. +- Existing changes: analyze existing configuration and collect revision-bound proposals in the chat working draft. Only an explicitly confirmed overall diff changes the configuration draft; no automatic change to published templates or existing instances. +- Knowledge: ingest current official STACKIT information in a controlled way, detect changes automatically and release after review before use. Module, provider and Configurator knowledge remains bound to the respective configuration version. No automatic upgrades or arbitrary model web access. +- Model: `Qwen/Qwen3-VL-235B-A22B-Instruct-FP8` as preferred initial value; model, endpoint and technical limits remain operator-configurable. Existing Terraform-provisioned dev token is used exclusively backend-side. +- Inputs: text and configurations; no images in MVP. +- Scope decision 2026-10-13: guided firewall-policy editing and Assistant proposals for rules/NAT/aliases/routes are post-MVP ([#101](https://github.com/stackitcloud/stackit-landing-zone/issues/101)). Assistant states this boundary immediately; in MVP the firewall administrator maintains policy manually in OPNsense after provisioning. Generic native editor fields remain but are not execution evidence. Firewall infrastructure/HA remains in scope and alone guarantees neither isolation, connectivity nor NAT. +- Access and purpose: only authenticated users with currently valid session and appropriate tenant/configuration permissions. Advice and proposals are limited to Configurator tasks above; server-side tool, schema and permission checks enforce this boundary. No general chat, shell, secret or cloud execution function. +- Budget: no monetary budget limit in MVP. Bounded request sizes, context/output lengths, concurrency, request rates, timeouts and repair attempts remain necessary for abuse and operational protection. Usage is observed without secrets. +- Conversations: persistent server-side and continuable after re-login, with mandatory tenant, workspace and configuration reference. Access is rechecked on every read, continuation and adoption. Bound initial revision is reconciled with current configuration; stale proposals are not adopted unchecked. +- Deletion and age: deleting a configuration or its workspace also deletes associated conversations with messages, summaries and proposals; no orphaned conversation data. Maximum conversation age is three calendar months from creation, not last activity. Continuation does not extend the deadline. After expiry, an existing configuration can be analyzed again in a new conversation. +- Load target: at most five concurrent chat sessions for MVP acceptance. This is not a limit on saved conversation count. Inference concurrency, bounded queue and timeouts additionally consider actual Model Serving limits. -Die fachliche Abnahme umfasst jedes implementierte Feature 1:1, nicht nur ausgewählte Beispielvorlagen. Konkrete Referenzkonfigurationen und messbare Antwortzeitziele werden beim Modell-Spike und Aufbau der Feature-Matrix präzisiert. Eine vorläufige Schätzung für den Gesamtumfang beträgt 30–50 Engineering-Personentage einschließlich Tests und Dokumentation, ohne externe Wartezeiten oder zusätzliche fehlende Modul-/Compiler-Funktionen. Die Modell- und Komponentenqualifikation muss diese Spanne einschließlich vollständiger Feature-Abdeckung verfeinern. Der Konzeptbeschluss ist kein Implementierungs- oder Inferenznachweis. +Business acceptance covers every implemented feature 1:1, not just selected example templates. Specific reference configurations and measurable response-time goals are refined during the model spike and feature matrix setup. A preliminary overall estimate is 30–50 engineering person-days including tests and documentation, excluding external waiting times or additional missing module/compiler capabilities. Model and component qualification must refine this range including complete feature coverage. Concept approval is neither implementation nor inference evidence. -### Gesprächslebenszyklus und Abnahme + +### Conversation lifecycle and acceptance -Die konkrete [Feature-Matrix und Dialogabnahme](assistant-feature-coverage.md) umfasst alle 29 aktuellen Root-Eingaben, 501 Feld-/Containerpfade, acht Funktionsgruppen, fünf übergreifende Workflow-Bereiche und 24 Szenarien. Die [generierte Matrix](assistant-feature-coverage.json) enthält neun geschützte Feld-/Containerpfade ohne Secret-Werte; jeder Eintrag bleibt bis zum tatsächlichen Modellnachweis `not-qualified`. Ihr Frischetest ist in die bestehende Unit-Suite integriert. Dies ist der erste qualifizierte Konzeptschritt, nicht die Implementierung des Assistenten. +The specific [feature matrix and dialogue acceptance](assistant-feature-coverage.md) covers all 29 current root inputs, 501 field/container paths, eight feature groups, five cross-cutting workflow areas and 24 scenarios. The [generated matrix](assistant-feature-coverage.json) contains nine protected field/container paths without secret values; every entry remains `not-qualified` until actual model evidence. Its freshness test is integrated into existing unit suite. This is the first qualified concept step, not Assistant implementation. -Persistierter Gesprächszustand ist von der kurzlebigen Login-Session und vom begrenzten Modellkontext getrennt. Nach Wiederanmeldung werden nur aktuell autorisierte, nicht gelöschte und nicht abgelaufene Gespräche geladen. Vor der Vorlagenauswahl wird bei Bedarf ein regulärer autorisierter Konfigurationsentwurf angelegt; auch ein neues Gespräch bleibt damit an einen Workspace und eine Konfiguration gebunden. Ohne gültiges Elternobjekt ist kein Chat-Zugriff möglich. +Persisted conversation state is separate from short-lived login session and bounded model context. After re-login, only currently authorized, undeleted and unexpired conversations are loaded. Before template selection, create a regular authorized configuration draft if needed; even a new conversation is thereby bound to a workspace and configuration. No chat access without valid parent object. -Der Löschpfad muss Nachrichten, Gesprächs-Arbeitsentwürfe, Zusammenfassungen und abgeleitete Cache-/Indexdaten berücksichtigen. Autorisierte Elternlöschung und die Löschung persistierter Gesprächsdaten sind atomar; verspätete Modellantworten dürfen gelöschte oder abgelaufene Gespräche nicht wiederherstellen. Ablauf wird vor jedem Zugriff geprüft und durch einen überwachten Bereinigungsprozess physisch umgesetzt. Logs enthalten keine Gesprächsinhalte. Backup-Aufbewahrung und Restore müssen die Lösch- und Altersgrenzen erhalten; vor erneutem Zugriff nach Restore werden gelöschte und abgelaufene Daten entfernt. Ein Datenbank-Cascade allein ist kein Nachweis der Löschung aller Kopien. +Deletion path must consider messages, conversation working drafts, summaries and derived cache/index data. Authorized parent deletion and deletion of persisted conversation data are atomic; late model responses must not restore deleted or expired conversations. Expiry is checked before every access and physically implemented through monitored cleanup. Logs contain no conversation content. Backup retention and restore must preserve deletion and age limits; deleted and expired data are removed before renewed access after restore. A DB cascade alone is not evidence of deletion of all copies. -Erforderliche Tests: Fortsetzung nach Wiederanmeldung oder Backend-Neustart, Workspace-/Konfigurations- und Tenant-Isolation, aktueller Rechteentzug, Konfigurationsrevision-Konflikte, beide Elternlöschpfade einschließlich laufender Inferenz, feste Drei-Monats-Grenze ohne Aktivitätsverlängerung und bereinigter Restore. Fünf parallele Sitzungen dürfen weder Kontexte vermischen noch stille Requestverluste oder unbegrenzte Warteschlangen verursachen. +Required tests: continuation after re-login or backend restart, workspace/configuration and tenant isolation, current permission revocation, configuration revision conflicts, both parent deletion paths including running inference, fixed three-month limit without activity extension and sanitized restore. Five parallel sessions must neither mix contexts nor cause silent request loss or unbounded queues. -Die Abdeckungsmatrix ordnet jedem implementierten Feature mindestens Analyse, Neuerstellung/Änderung soweit vom Editor unterstützt, fehlende Angaben, Abhängigkeiten, validierten Diff und passende Negativfälle zu. Gemeinsame Schema-/Compilerprüfungen bleiben maßgeblich. CI/Release prüfen fehlende Zuordnungen und Tests; reale Modell-Evaluationen qualifizieren zusätzlich die Dialogqualität, denn eine vollständige Matrix allein beweist keine zuverlässigen Antworten. +Coverage matrix assigns every implemented feature at least analysis, creation/modification where editor-supported, missing information, dependencies, validated diff and matching negative cases. Common schema/compiler checks remain authoritative. CI/release check missing assignments and tests; real model evaluations additionally qualify dialogue quality because a complete matrix alone does not prove reliable answers. -### Fachlicher Vertrag + +### Business contract -Der Chat behandelt ausschließlich Planung und Konfiguration des versionsgebundenen Accelerators. Er erklärt Features und Grenzen, fragt aktiv fehlende Informationen ab und erzeugt überprüfbare Änderungen. Außerhalb dieses Bereichs führt er zum unterstützten Thema zurück. +Chat handles exclusively planning and configuration of the version-bound Accelerator. It explains features and limits, actively asks for missing information and produces reviewable changes. Outside this scope, it redirects to supported topics. -Wissen: Feature-Katalog, Schema, freigegebene Repo-/Moduldokumentation und Templates der gewählten Version. Kein beliebiger Web-/Repository-Zugriff. Dokumentverweise in Antworten; unbekannte Features nicht erfinden. Systemprompt alleine garantiert die Einschränkung nicht: Tool- und Datenzugriffe im Backend erzwingen. +Knowledge: feature catalogue, schema, approved repository/module documentation and templates of the selected version. No arbitrary web/repository access. Document references in responses; do not invent unknown features. System prompt alone does not guarantee restriction: backend tool/data access enforces it. -Ablauf: +Workflow: -1. Benutzer beschreibt sein Ziel. -2. Backend liefert minimale secretfreie Konfiguration und relevante versionierte Wissensabschnitte. -3. Chat fragt notwendige Angaben ab: Owner, Organisation, Regionen, Isolation, Netzplanung. Widersprüche erklären, etwa getrennte SNAs bei gleichzeitig gewünschtem gemeinsamen privaten Git-Service. -4. Modell erzeugt `questions`, `assumptions`, `patch`, `explanation`, `references`. -5. Backend prüft Schema/Fachregeln und Basisrevision des Patches. -6. UI zeigt Diff und Topologie-Vorschau. Erst „Übernehmen“ ändert den Entwurf; Git-Speichern, Plan und Apply sind separate Aktionen. +1. User describes their goal. +2. Backend supplies minimal secret-free configuration and relevant versioned knowledge sections. +3. Chat asks for required information: owner, organization, regions, isolation, network planning. Explain contradictions, e.g. separate SNAs alongside a desired shared private Git service. +4. Model produces `questions`, `assumptions`, `patch`, `explanation`, `references`. +5. Backend checks schema/domain rules and patch base revision. +6. UI shows diff and topology preview. Only “Accept” changes the draft; Git saving, Plan and Apply are separate actions. -Erlaubte interne Werkzeuge: Features nachschlagen, bereinigte Konfiguration lesen, Patch vorschlagen/validieren. Kein Secret-Lesen, Shell, Git-Schreiben oder Apply durch das Modell. Repo-Kommentare und Freitext gelten als untrusted input. Keine fremden Tenant-Daten, Credentials, States oder Roh-Plans im Modellkontext. +Permitted internal tools: look up features, read sanitized configuration, propose/validate patch. No secret reads, shell, Git writes or Apply by the model. Repository comments and free text are untrusted input. No other tenants' data, credentials, states or raw plans in model context. -### Anbindung und Betrieb + +### Integration and operation -STACKIT dokumentiert eine OpenAI-kompatible Inferenz-API mit Auth-Token. Die API hält keinen Gesprächszustand; das Backend verwaltet den nötigen Kontext selbst. [Modelle verwenden](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/how-tos/use-the-models/) +STACKIT documents an OpenAI-compatible inference API with auth token. API keeps no conversation state; backend manages necessary context itself. [Use models](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/how-tos/use-the-models/) -Voraussetzung: STACKIT-Projekt mit aktiviertem AI Model Serving, ausgewähltem Modell, Kapazität und Inferenz-Token. Token-Erzeugung benötigt eine separate STACKIT-Autorisierung; Inferenz-Token nicht mit allgemeinen STACKIT-Credentials verwechseln. [Auth-Tokens](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/how-tos/manage-auth-tokens/) +Prerequisite: STACKIT project with enabled AI Model Serving, selected model, capacity and inference token. Token creation requires separate STACKIT authorization; do not confuse inference token with general STACKIT credentials. [Auth tokens](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/how-tos/manage-auth-tokens/) -Vorgeschlagene app-eigene CF-Variablen: +Proposed app-specific CF variables: ```text MODEL_SERVING_BASE_URL @@ -438,30 +439,32 @@ MODEL_SERVING_API_KEY MODEL_SERVING_TIMEOUT_SECONDS ``` -Der dokumentierte Shared-Model-Einstieg verwendet `https://api.openai-compat.model-serving.eu01.onstackit.cloud/v1/chat/completions`. Endpoint/Modell aus der gewählten Service-Konfiguration übernehmen; nicht den Management-API-Endpoint für Inferenz nutzen. Modellfähigkeiten wie Tool Calling/strukturierte Ausgabe separat evaluieren. [Shared Models starten](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/getting-started/getting-started-with-shared-models/) +Documented shared-model entry uses `https://api.openai-compat.model-serving.eu01.onstackit.cloud/v1/chat/completions`. Take endpoint/model from selected service configuration; do not use management API endpoint for inference. Evaluate model capabilities such as tool calling/structured output separately. [Getting started with shared models](https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/getting-started/getting-started-with-shared-models/) -Credentials ausschließlich auf Backend/Chat-App setzen, nie ins Frontend-Build oder Runner. CF-Umgebungsvariablen sind für entsprechend berechtigte Space-Developer lesbar; diese gehören damit zur Betreiber-Vertrauensgrenze. Über geschützte Deployment-Injektion setzen, nicht in Git-Manifeste schreiben; Rotation und Redaktion testen. [CF-Variablen und Secrets](https://docs.stackit.cloud/products/runtime/cloud-foundry/how-tos/manage-environment-variables-and-secrets/) +Set credentials exclusively on backend/chat app, never frontend build or Runner. CF environment variables are readable by appropriately authorized space developers; these therefore belong to the operator trust boundary. Set through protected deployment injection, not Git manifests; test rotation and redaction. [CF variables and secrets](https://docs.stackit.cloud/products/runtime/cloud-foundry/how-tos/manage-environment-variables-and-secrets/) -Technische Token-/Anfragelimits pro Tenant, Timeouts, begrenzte Reparaturversuche für ungültiges JSON und Circuit Breaker; keine monetäre Budgetgrenze im MVP. Bei KI-Ausfall bleibt der manuelle Editor nutzbar. Gesprächsaufbewahrung, Löschung und übermittelte Organisationsdaten transparent machen. Tenant-Chatdaten nicht in einen gemeinsamen Wissensindex übernehmen. +Technical token/request limits per tenant, timeouts, bounded repair attempts for invalid JSON and circuit breaker; no monetary budget limit in MVP. Manual editor remains usable during AI outage. Make conversation retention, deletion and transmitted organization data transparent. Do not place tenant chat data in a shared knowledge index. -Evaluationsfälle: fehlende Pflichtfelder, widersprüchliche Netze, unbekannte Features, Themenwechsel, Prompt Injection, Secret-Offenlegung, fremde Tenants, veraltete Revisionen und ungültige Ausgabe. Der Chat gilt erst mit gemessenen Akzeptanzkriterien als freigegeben. +Evaluation cases: missing required fields, contradictory networks, unknown features, topic switch, prompt injection, secret disclosure, foreign tenants, stale revisions and invalid output. Chat is approved only with measured acceptance criteria. -## 12. Grafische Darstellung + +## 12. Graphical representation -Ein deterministischer Graph-Builder verwendet dasselbe validierte Fachmodell wie der Compiler. Kein frei vom Sprachmodell gezeichnetes Infrastrukturdiagramm. +A deterministic graph builder uses the same validated business model as the compiler. No infrastructure diagram drawn freely by the language model. -- Gruppierung: Organisation → Region → Netzwerkbereich → Projekte/Landing Zones → Dienste. -- Knoten für Management, DevOps, Plattformcluster, Firewall, VPN, DNS und Sandboxes. -- Kanten für echte Beziehungen: SNA-Anbindung, Default Route, Cluster-Zuordnung, explizite VPN-Verbindung. Keine impliziten Verbindungen zwischen SNAs/Regionen. -- Getrennte Ansichten: Konfigurations-Soll, Plan-Delta und zuletzt bekannter Ist-/State-Stand mit Zeitstempel. State ist kein Echtzeit-Monitoring. -- Create/Update/Delete/Replace sowie unbekannte Werte durch Symbol und Farbe markieren. -- Plan-Ressourcen über versioniertes Mapping Features zuordnen; nicht zuordenbare Ressourcen bleiben technisch sichtbar. -- Knoten öffnen Fachformulare. Freies Zeichnen von Beziehungen erst später mit denselben Validierungsregeln. -- Tastaturbedienbare Listen-/Tabellenalternative; secretfreier Grafikexport als Ausbau. +- Grouping: organization → region → network area → projects/Landing Zones → services. +- Nodes for management, DevOps, platform cluster, firewall, VPN, DNS and sandboxes. +- Edges for real relationships: SNA connection, default route, cluster assignment, explicit VPN connection. No implicit connections between SNAs/regions. +- Separate views: desired configuration, Plan delta and last known actual/state status with timestamp. State is not real-time monitoring. +- Mark Create/Update/Delete/Replace and unknown values with symbol and color. +- Map Plan resources to features through versioned mapping; unmappable resources remain technically visible. +- Nodes open business forms. Free drawing of relationships only later with the same validation rules. +- Keyboard-operable list/table alternative; secret-free graph export as extension. -## 13. IaC, Lieferung und Betrieb + +## 13. IaC, delivery and operation -Das getrennte Verzeichnisgerüst und die lokale App-Entwicklungsbasis sind angelegt; Bootstrap-, Backend- und Plattform-IaC sind implementiert; noch kein Cloud-Apply. Details stehen in der [Configurator-README](../README.md). Die [Sprachentscheidung](decisions/0001-application-stack.md) ist als angenommen dokumentiert. +The separate directory skeleton and local app development foundation are created; bootstrap, backend and platform IaC are implemented; no cloud Apply yet. Details are in the [Configurator README](../README.md). The [language decision](decisions/0001-application-stack.md) is documented as accepted. ```text landing-zone-configurator/ @@ -474,548 +477,474 @@ landing-zone-configurator/ docs/decisions/ ``` -Die lokal bereitgestellten Dateien `landing-zone-configurator.env` und `landing-zone-configurator-credentials.json` bleiben im Repository-Root und sind von Git ausgeschlossen. Sie betreffen die Betreiberplattform, nicht Kunden-Deployments. Werte nicht in Dokumentation, Manifeste oder Git übernehmen. Die `.env` verwendet nach Benutzerkorrektur das geprüfte `NAME=WERT`-Format. Erkannte Variablennamen: `PROJECT_ID`, `ORGANISATION_ID`. Vor IaC-Nutzung das Mapping zu den Plattformvariablen festlegen. Zielprojekt-Lesezugriff und ausgewählte Dienst-Metadaten wurden geprüft; Schreibrechte sind noch nicht nachgewiesen. Siehe [Plattformprüfung](platform-check.md). +Locally provided files `landing-zone-configurator.env` and `landing-zone-configurator-credentials.json` remain in repository root and are excluded from Git. They concern the operator platform, not customer deployments. Do not copy values into documentation, manifests or Git. After user correction, `.env` uses checked `NAME=WERT` format. Detected variable names: `PROJECT_ID`, `ORGANISATION_ID`. Define mapping to platform variables before IaC use. Target-project read access and selected service metadata were checked; write permissions are not yet demonstrated. See [platform check](platform-check.md). + +App infrastructure and customer Landing Zones have separate states, credentials and release cycles. The app must not depend on a Landing Zone that would first need to be created by the same app. STACKIT documents CF provisioning through Terraform; specific resource coverage still needs demonstrating in the spike. [CF with Terraform](https://docs.stackit.cloud/products/runtime/cloud-foundry/how-tos/provision-cloud-foundry-via-terraform/) + + +### Platform setup + +- [ ] Define operator project, region, CF org/spaces, quotas and operating roles. +- [ ] Provision platform remote state and bootstrap identity upfront; restricted operating identity afterwards. +- [ ] Declare CF apps/processes, routes, domain/TLS, bindings, health checks and scaling. +- [ ] Provision PostgreSQL Flex, secret store, artifact buckets, IAM, ACLs/network rules and monitoring. +- [ ] Enable/provision Model Serving or explicitly connect existing service; check provider/API coverage. +- [ ] Provide Runner and, if necessary, customer-specific network connection through dedicated modules. +- [ ] Manage GitHub App, callback/webhook URLs and keys; document registration steps that cannot be automated. +- [ ] Pin provider versions; supplement missing resources only through documented idempotent API/CLI steps. +- [ ] Inject secrets into CF protectively. `sensitive = true` does not prevent inclusion in Terraform state; avoid passing secret values through IaC resource parameters where possible. +- [ ] Separate development, staging and production; no customer secrets in development. + + +### CI/CD and operation + +- [ ] Parser/compiler fixtures for all eight templates; semantic import/export comparison. +- [ ] Check domain rules, version migrations and feature coverage. +- [ ] Authorization, RLS, Runner isolation and secret-redaction tests. +- [ ] Dependency/image scans, reproducible builds, IaC validation and staging smoke test. +- [ ] Qualify pinned engine/providers with real test organization; existing repository tests partly need STACKIT API access. +- [ ] Blue/green or tested CF rollout; backward-compatible DB migrations and app rollback. +- [ ] Practically rehearse DB, secrets and state backup/restore including required keys. +- [ ] Test CF restart, lost Runner, DB outage, token revocation and partially failed Apply. +- [ ] Metrics: queue age, Runner heartbeat, error rates, Plan/Apply duration, drift errors, AI usage and tenant quotas. +- [ ] Define RPO/RTO, availability, retention, budget, support paths and emergency access before first customer release. + + +## 14. Roadmap and acceptance + +Multi-tenancy is part of every phase. Functionality can grow incrementally; customer isolation must not be deferred to a later phase. Estimate effort and dates only after spikes and team definition. + + +### P0 – feasibility and binding decisions + + +#### Development foundation – first completed step + +- [x] Confirm stack and pin runtime/package versions. +- [x] Create dedicated npm workspace with lockfile, React/Vite and Fastify. +- [x] Create shared contracts and initial tenant/role policy. +- [x] Successfully run local lint, type checking, build and five tests. +- [x] Create separate Configurator CI workflow (not yet run on GitHub). +- [x] Check platform read-only and document limitations/results. +- [ ] Implement full sessions, DB/RLS and tenant-separated persistence. + +This foundation replaces none of the following architecture spikes. Startup details: [development guide](../app/README.md). + +- [x] Document requirements, repository baseline and architecture design. +- [x] Confirm multiple independent customers from the start and initially configuration changes only. +- [ ] GitHub spike: user token, upstream/target installation, fork, multiple owners, commit/PR, revocation and refresh. +- [ ] CF Runner spike: isolation, limits, cancellation, secret handover and private targets. +- [ ] State spike: first run, real locking, concurrent CLI access, restore. +- [ ] Secret-store spike: policies, tenant separation, rotation and delegation. +- [ ] Clarify service plans, regions, IaC resource coverage and optional IdP. +- [ ] Model Serving spike: auth, model, structured proposals, limits and evaluation. + +**Acceptance:** Critical assumptions are evidenced or replaced by agreed alternatives. Record architecture decisions with evidence. + + +### P1 – tenants, GitHub, templates and editor + +- [ ] Tenant onboarding, roles, invitations, sessions and server-side object authorization. +- [ ] Repository selection, fork flow and concurrent saving. +- [ ] Catalogue/import all eight templates and label support. +- [ ] Fully implement business model/compiler and editor initially for standalone and simple hub-and-spoke. +- [ ] Desired topology, drafts, Git versioning and upgrade metadata. +- [ ] Negative tests against foreign tenants and field loss during import. + +**Acceptance:** Copy template → change business settings → check graph → save in selected fork → load semantically unchanged. No secrets in commit or overwriting others' changes. + + +### P2 – secure deployments and operational foundation + +- [ ] Staging/production foundation through IaC, backups and Observability. +- [x] Implement personal credential profiles: upload, Secrets Manager storage, own metadata and deletion. +- [x] Check STACKIT authentication and organization read access; save result per profile. +- [x] Bind saved Git configuration, organization, code reference and secret version in a preparation. +- [ ] Broader deployment permissions, delegations and customer-specific remote state. +- [ ] Runner, queue, manifest, Plan redaction, approval and exact Apply. +- [ ] Execute standalone and simple hub-and-spoke in separate test organizations. +- [ ] Check isolation, quotas, crash, cancellation, permission revocation, restore and partial failures. + +**Acceptance:** At least two independent test customers can work separately. Foreign data/secrets are inaccessible; stale plans are rejected; Runner failure causes no blind second Apply. Operational goals and runbooks are defined. + + +### P3 – chat and complete feature coverage + +- [ ] Integrate Model Serving with follow-ups, schema patches, diff and adoption. +- [ ] Versioned knowledge and evaluation suite. +- [ ] Cover multi-area, multi-region, Kubernetes, firewall/HA/VPN and further services. +- [ ] Demonstrate special bootstrap workflows and network connectivity. +- [ ] Graphically show Plan delta and known actual state. + +**Acceptance:** Chat and form produce equivalent validated configurations. All templates have traceable support status. Repository limitations remain visible; no invented features and no Apply through chat. + + +### P4 – optional operational expansion + +- [ ] Drift detection with explicit background delegation and status messages. +- [ ] Correction after approval, later narrow automatic allowlist with emergency stop. +- [ ] Optional STACKIT IdP after feasibility evidence. +- [ ] Custom Terraform code only after separate security/Runner decision. +- [ ] Extended team processes, audit export and customer-specific isolation options. + +**Acceptance:** Automatic correction respects its policy even for unknown or destructive plans. Failure/revocation leads to controlled pause rather than uncontrolled retries. + + +## 15. Decision register + +| ID | Decision | Recommendation / result | Status | Owner | +| --- | --- | --- | --- | --- | +| D01 | Target audience | Multiple independent customer organizations from the start | Confirmed | Product | +| D02 | Terraform modifications | V1 configurations only, custom code later | Confirmed | Product | +| D03 | GitHub integration | GitHub App with user token; demonstrate fork prerequisites | Open | Backend | +| D04 | Multiple forks | Multiple owners/repos; branches/configs as additional variants | Spike | Product/Backend | +| D05 | Persistence | PostgreSQL Flex, tenant isolation plus RLS | Proposal | Platform | +| D06 | Runner hosting | Separate CF Runners, otherwise explicitly SKE/compute | Critical spike | Platform/Security | +| D07 | State ownership | LZA bootstrap, then migration to created customer backend | Decided; recovery/migration to implement | Architecture | +| D08 | Secret management | Secret store with run delegation and tenant policies | Critical spike | Security | +| D09 | Configuration format | Business JSON plus native landing-zone.tfvars | Standalone implemented; versioned deployment manifest outstanding | Architecture | +| D10 | Engine | Pinned OpenTofu 1.12.6 first; qualify Terraform separately | Proposal | Maintainer | +| D11 | STACKIT IdP | Optional, client registration not demonstrated | Open | IAM | +| D12 | Drift correction | Approval first, automatic allowlist later | Proposal | Product/Operations | +| D13 | AI model | STACKIT service with evaluated model and tenant limits | Spike | AI/Product | +| D14 | Operational goals | RPO/RTO, retention, availability and budget before customer release | Open | Operations | +| D15 | Product name and structure | Landing Zone Configurator under own top-level directory | Confirmed / skeleton created | Product | +| D16 | Application language | TypeScript for web/API/worker; Go for bounded HCL adapter | Confirmed, see ADR 0001 | Development | +| D17 | Service provisioning | All Configurator services and activations through IaC | Confirmed | Platform | +| D18 | First environment | lzc-dev in eu01; backend access initially approx. 90 days | Environment confirmed; lifetime as operational default | Platform | + + +## 16. Risks and Definition of Done + +| Risk | Countermeasure / evidence | +| --- | --- | +| Cross-tenant access | RLS plus object authorization, separate secrets/states, negative tests | +| Runner reads operator secrets | No backend bindings; targeted isolation test | +| Fork API does not fit onboarding | Early GitHub spike; manual fork/connect flow as clear alternative | +| UI and Terraform diverge | Versioned catalogue, compiler fixtures and migration checks | +| Secret in plan/state/log/chat | Protected artifacts, redaction before logging, negative tests | +| Private API unreachable from CF | Network spike, dedicated Runner profile in target network | +| Two processes write the same state | Backend lock plus canonical state ID and platform lease | +| Initially open firewall | Secure bootstrap, password rotation and error runbook before approval | +| Unexpected Destroy/Create | Stable keys, visible replacements and specific Plan approval | +| Customers block each other's capacity | Tenant quotas, fair queue, rate limits and backoff | +| AI disregards topic/schema | Backend enforces tools/data access; evaluation and fallback | +| Backup cannot be restored | Restore rehearsals including key material | + +For each feature: + +- [ ] Business behavior, mapping and limitations documented. +- [ ] Editor, chat, compiler and graph use the same semantics. +- [ ] Authorization, tenant separation and relevant error cases checked. +- [ ] No secrets in Git, frontend or unprotected artifacts. +- [ ] Migration and operation documented where required. +- [ ] Acceptance evidence and issue/PR link recorded. + + +## 17. Source status and ongoing planning + +Local analysis: repository source `2161871`. External primary sources were checked on 2026-09-29 after network access was restored and linked directly at relevant statements. Documentation replaces no integration tests. Specific service plans/quotas, GitHub fork UX, secret policies, S3 locking, private Runner connectivity and STACKIT IdP client registration remain particularly open. Object Storage and Model Serving are activated automatically by their provider resources; the earlier 404 is thus clarified. + +**Next planning step:** Prioritize P0 spikes for GitHub, Runner/network, state and secrets and assign owners. Then decide D03/D06/D07/D08 and estimate the first vertical workflow from login to approved Apply. + +| Date | Result / decision | Responsible | Evidence | +| --- | --- | --- | --- | +| 2026-09-29 | Architecture design and repository feature mapping created | To be assigned | This document | +| 2026-09-29 | Multiple independent customers from start; V1 configurations only | User decision | Planning discussion, D01/D02 | +| 2026-09-29 | TypeScript/React/Fastify confirmed; local development foundation and separate CI created | Development | ADR 0001, app workspace | +| 2026-09-29 | Object Storage 404 clarified as not enabled; provider enables at first bucket | Development | platform-check.md | +| 2026-09-29 | lzc-dev/eu01 confirmed; first real bootstrap Plan with 3 Create successful | User / Development | infra/README.md | -App-Infrastruktur und Kunden-Landing-Zones haben getrennte States, Credentials und Release-Zyklen. Die App darf nicht von einer Landing Zone abhängen, die erst durch dieselbe App erzeugt werden müsste. STACKIT dokumentiert CF-Provisionierung via Terraform; die konkrete Ressourcenabdeckung ist dennoch im Spike nachzuweisen. [CF mit Terraform](https://docs.stackit.cloud/products/runtime/cloud-foundry/how-tos/provision-cloud-foundry-via-terraform/) +Template for ongoing work packages: -### Plattformaufbau +```markdown +### : +- Status: offen / in Arbeit / blockiert / erledigt +- Owner: +- Ziel und Abnahmekriterium: +- Abhängigkeiten / Entscheidungen: +- Aufwand / Zieltermin: +- Issue / PR: +- [ ] Umsetzung +- [ ] Relevante Prüfungen und Abnahmenachweis +- [ ] Dokumentation und Betrieb +``` -- [ ] Betreiberprojekt, Region, CF-Org/-Spaces, Quoten und Betriebsrollen festlegen. -- [ ] Plattform-Remote-State und Bootstrap-Identität vorab provisionieren; anschließend eingeschränkte Betriebsidentität. -- [ ] CF-Apps/Prozesse, Routes, Domain/TLS, Bindings, Health Checks und Skalierung deklarieren. -- [ ] PostgreSQL Flex, Secret Store, Artefakt-Buckets, IAM, ACLs/Netzregeln und Monitoring provisionieren. -- [ ] Model Serving aktivieren/provisionieren oder vorhandenen Service explizit anbinden; Provider-/API-Abdeckung prüfen. -- [ ] Runner und gegebenenfalls kundenspezifische Netzverbindung über eigene Module bereitstellen. -- [ ] GitHub App, Callback-/Webhook-URLs und Schlüssel verwalten; nicht automatisierbare Registrierungsschritte dokumentieren. -- [ ] Provider-Versionen pinnen; fehlende Ressourcen nur über dokumentierte idempotente API-/CLI-Schritte ergänzen. -- [ ] Secrets geschützt in CF injizieren. `sensitive = true` verhindert keine Aufnahme in Terraform-State; Secret-Werte möglichst nicht durch IaC-Ressourcenparameter schleusen. -- [ ] Entwicklungs-, Staging- und Produktionsumgebung trennen; keine Kundensecrets in Entwicklung. + +## 18. CI/CD by lifecycle -### CI/CD und Betrieb +The [CI/CD concept](cicd.md) defines separate workflows for rare bootstrap, platform changes, frequent app releases and optional drift detection. It includes state/secret dependencies, lifecycle ownership and a checkable implementation sequence. Deployment workflows are planned; validation CI already exists. Next technical step: independent management backend and secure CI key custody before first cloud Apply. -- [ ] Parser-/Compiler-Fixtures für alle acht Templates; semantischer Import-/Export-Vergleich. -- [ ] Fachregeln, Versionsmigrationen und Feature-Abdeckung prüfen. -- [ ] Autorisierungs-, RLS-, Runner-Isolations- und Secret-Redaktionstests. -- [ ] Dependency-/Image-Scans, reproduzierbare Builds, IaC-Validate und Staging-Smoke-Test. -- [ ] Gepinnte Engine/Provider mit realer Testorganisation qualifizieren; bestehende Repo-Tests benötigen teilweise STACKIT-API-Zugriff. -- [ ] Blue/green oder getesteter CF-Rollout; rückwärtskompatible DB-Migrationen und App-Rollback. -- [ ] Backup/Restore von DB, Secrets und State einschließlich benötigter Schlüssel praktisch üben. -- [ ] CF-Restart, verlorenen Runner, DB-Ausfall, Token-Widerruf und teilweise fehlgeschlagenen Apply testen. -- [ ] Metriken: Queue-Alter, Runner-Heartbeat, Fehlerquoten, Plan-/Apply-Dauer, Drift-Fehler, KI-Verbrauch und Mandantenquoten. -- [ ] RPO/RTO, Verfügbarkeit, Retention, Budget, Supportwege und Notfallzugriffe vor erster Kundenfreigabe festlegen. +Management backend: separate bucket created in existing project by `seed`/`seed-protection`. Bootstrap connected to S3; CI key handover and deployment workflows remain next steps. -## 14. Roadmap und Abnahme +CI status: bootstrap workflow and environment setup implemented locally; secret upload awaits explicit approval. S3 locking acceptance failed (second process not blocked despite lock); remote Applies are technically blocked. Backend/locking strategy must be decided before deployment. See [CI operations](../infra/ci/README.md). -Mehrmandantenfähigkeit ist Teil jeder Phase. Funktionsumfang kann schrittweise wachsen; Kundenisolation darf nicht auf eine spätere Phase verschoben werden. Aufwand und Termine erst nach Spikes und Teamzuschnitt schätzen. +Confirmed follow-up decision: keep S3, initially deploy exclusively through serialized GitHub Actions. Local remote Applies remain blocked; all mutating workflows use one shared concurrency group. User explicitly approved the specific secret transfer into the three named GitHub environments. -### P0 – Machbarkeit und verbindliche Entscheidungen + +## Feature branch and code ownership -#### Entwicklungsbasis – erster abgeschlossener Schritt +Development is on `feature/landing-zone-configurator`; adoption into `main` is explicitly not currently planned. Only `@lweberru` is registered as CODEOWNER for `/landing-zone-configurator/` and Configurator workflows under `/.github/workflows/`. Shared repository files keep existing owners. -- [x] Stack bestätigen und Runtime-/Paketversionen pinnen. -- [x] Eigenen npm-Workspace mit Lockfile, React/Vite und Fastify anlegen. -- [x] Gemeinsame Verträge und initiale Tenant-/Rollen-Policy anlegen. -- [x] Lokales Linting, Typecheck, Build und fünf Tests erfolgreich ausführen. -- [x] Separate Configurator-CI als Workflow anlegen (noch nicht auf GitHub ausgeführt). -- [x] Plattform lesend prüfen und Grenzen/Ergebnisse dokumentieren. -- [ ] Vollständige Sessions, DB/RLS und tenantgetrennte Persistenz implementieren. +GitHub environment rules and deployment workflow still allow only `main`. Feature-branch development therefore enables no cloud deployments. Later test operation from the feature branch needs targeted adaptation of these rules; the branch is not automatically merged to main for this. -Diese Basis ersetzt keinen der folgenden Architektur-Spikes. Details zum Start: [Entwicklungsanleitung](../app/README.md). +GitHub evaluates CODEOWNERS for PRs from the respective target branch: a later PR to main initially uses its previous rule. CODEOWNERS also overrides no branch-protection rules; own PRs cannot be self-approved. -- [x] Anforderungen, Repo-Ausgangslage und Architekturentwurf dokumentieren. -- [x] Mehrere unabhängige Kunden ab Beginn und zunächst nur Konfigurationsänderungen bestätigen. -- [ ] GitHub-Spike: User Token, Upstream-/Zielinstallation, Fork, mehrere Owner, Commit/PR, Widerruf und Refresh. -- [ ] CF-Runner-Spike: Isolation, Limits, Abbruch, Secret-Übergabe und private Ziele. -- [ ] State-Spike: erster Run, echtes Locking, konkurrierender CLI-Zugriff, Restore. -- [ ] Secret-Store-Spike: Policies, Mandantentrennung, Rotation und Delegation. -- [ ] Service-Pläne, Regionen, IaC-Ressourcenabdeckung und optionalen IdP klären. -- [ ] Model-Serving-Spike: Auth, Modell, strukturierte Vorschläge, Limits und Evaluation. +Feature-branch test approved: push trigger for bootstrap Plan on `feature/landing-zone-configurator`, matching additional branch rule exclusively in Plan environment. Apply/recovery remain main-only. No merge to main needed for the test. -**Abnahme:** Kritische Annahmen sind belegt oder durch beschlossene Alternativen ersetzt. Architekturentscheidungen mit Nachweisen erfassen. +Bootstrap Apply completed: GitHub run 36601941540 on feature branch, three resources created. Encrypted remote state independently checked; one-time commit approval removed. Next step: separate backend root for versioning workload state bucket. main remains unchanged. -### P1 – Mandanten, GitHub, Templates und Editor +Backend Apply completed: run 36602706599, workload state bucket versioning enabled and directly verified through S3. Encrypted backend state checked; one-time approvals removed. [Platform preparation](platform-readiness.md) documents selected catalogue values and open network parameters. -- [ ] Tenant-Onboarding, Rollen, Einladungen, Sessions und serverseitige Objekt-Autorisierung. -- [ ] Repository-Auswahl, Fork-Flow und konkurrierendes Speichern. -- [ ] Alle acht Templates katalogisieren, importieren und Unterstützung kennzeichnen. -- [ ] Fachmodell/Compiler und Editor zunächst für Standalone und einfaches Hub-Spoke vollständig umsetzen. -- [ ] Soll-Topologie, Entwürfe, Git-Versionierung und Upgrade-Metadaten. -- [ ] Negativtests gegen fremde Mandanten und Verlust von Feldern beim Import. +Network correction: CF egress addresses are undocumented/unstable (user note). Previous requirement for fixed CF CIDRs is dropped. Instead, check service-specific supported access models: documented STACKIT networks for PostgreSQL with connectivity test; Secrets Manager separately. Plan migrations as CF task. Do not treat service bindings as network approval. See [platform preparation](platform-readiness.md). -**Abnahme:** Template kopieren → fachlich ändern → Grafik prüfen → im ausgewählten Fork speichern → semantisch unverändert laden. Keine Secrets im Commit und kein Überschreiben fremder Änderungen. +Platform attempt 2026-09-30: Plan with nine Creates and validation successful; Apply run 36632950493 aborted after 45 minutes. Partial inventory exists (CF active, Secrets Manager Running, PostgreSQL last PROGRESSING), platform state missing. One-time approval removed and platform CI temporarily disabled. Next step is controlled state recovery and improved termination handling, not another original Apply. Details and checklist: [platform operational status](platform-readiness.md#vorfall-2026-09-30-erster-plattform-apply-unvollständig). -### P2 – Sichere Deployments und Betriebsgrundlage +Platform recovery completed (2026-09-30): run 36675347654 imported partial inventory and completed platform. Nine resources independently checked in encrypted remote state; PostgreSQL READY, CF active, Secrets Manager Running. Lost technical credentials replaced in a controlled way. Job timeout increased to 100 minutes, orderly OpenTofu termination and encrypted diagnostic/state artifacts added. One-time approvals removed. Next expansion after no-op acceptance: CF runtime/bindings and access tests from CF. [Current acceptance](platform-readiness.md#erfolgreiche-recovery-und-plattform-abnahme). -- [ ] Staging-/Produktionsgrundlage per IaC, Backups und Observability. -- [x] Persönliche Credential-Profile: Upload, Secrets-Manager-Ablage, eigene Metadaten und Löschung implementieren. -- [x] STACKIT-Anmeldung und Organisations-Lesezugriff prüfen; Ergebnis pro Profil speichern. -- [x] Gespeicherte Git-Konfiguration, Organisation, Code-Referenz und Secret-Version in einer Vorbereitung binden. -- [ ] Weitergehende Deployment-Rechte, Delegationen und kundenbezogener Remote State. -- [ ] Runner, Queue, Manifest, Plan-Redaktion, Freigabe und exakter Apply. -- [ ] Standalone und einfaches Hub-Spoke in getrennten Testorganisationen ausführen. -- [ ] Isolation, Quoten, Crash, Abbruch, Rechteentzug, Restore und partielle Fehler prüfen. +No-op acceptance completed: platform run 36675895279 shows `no-op` for all nine resources; recovery/Apply correctly skipped. Validation 36675895374 successful. Platform is thus consistently under IaC management. -**Abnahme:** Mindestens zwei unabhängige Testkunden können getrennt arbeiten. Fremde Daten/Secrets sind unerreichbar; veraltete Plans werden abgewiesen; Runner-Ausfall erzeugt keinen blinden zweiten Apply. Betriebsziele und Runbooks sind festgelegt. +CI decision 2026-09-30: at user request, replace custom JavaScript deployment Runner with direct visible OpenTofu steps in GitHub Actions. Small helpers exclusively prepare credentials, check plan integrity and protect state snapshots. Normal CLI logs are output live again; JSON credential/state output remains private. Separate completed recovery from regular workflow. Local validation and seed operation also use direct `tofu` commands. [Current operations guide](../infra/ci/README.md). -### P3 – Chat und vollständige Feature-Abdeckung +CI simplification accepted: real direct OpenTofu Plans for bootstrap (36677111141), platform (36677111032) and backend (36677367229), each without changes; Apply skipped in each. Native logs visible and checked against known credentials. Validation including Linux timeout test successful. Temporary backend selection removed; feature branch remains separate from main. -- [ ] Model Serving mit Rückfragen, Schema-Patches, Diff und Übernahme integrieren. -- [ ] Versioniertes Wissen und Evaluationssuite. -- [ ] Multi-Area, Multi-Region, Kubernetes, Firewall/HA/VPN und weitere Services abdecken. -- [ ] Spezielle Bootstrap-Abläufe und Netzkonnektivität nachweisen. -- [ ] Plan-Delta und bekannten Ist-Stand grafisch zeigen. + +## Current milestone: CF hosting and service connections -**Abnahme:** Chat und Formular erzeugen äquivalente validierte Konfigurationen. Alle Templates haben nachvollziehbaren Unterstützungsstatus. Repo-Grenzen bleiben sichtbar; keine frei erfundenen Features und kein Apply durch Chat. +Owner: `@lweberru`. All changes remain on `feature/landing-zone-configurator`. +User approval of 2026-09-30 covers necessary Configurator deployment Applies until MVP. +Specific plans are still reviewed; this approval does not permit changing customer +resources or other projects. -### P4 – Optionaler Betriebsausbau +- [x] Separate runtime IaC for CF space and roles. +- [x] Separate PostgreSQL/Secrets runtime identities; no migration or provisioning access in app. +- [x] Declarative CF manifest under `deploy/cloud-foundry/`; OpenTofu and release have separate responsibilities. +- [x] Independent release pipeline with direct `cf push`, versioned Node runtime package and connection test as CF task. +- [x] Public HTTPS route, UI/JS delivery and protected API (401) checked. +- [x] PostgreSQL: login, SELECT and verified TLS connection from CF successful. +- [x] Secrets Manager: login, TLS, authenticated KV read endpoint and rejection without token checked from CF. +- [x] Final [release run 36683898762](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898762) fully successful; [validation 36683898795](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898795) also green. -- [ ] Drift Detection mit expliziter Hintergrunddelegation und Statusmeldungen. -- [ ] Correction nach Freigabe, später enge automatische Allowlist mit Not-Aus. -- [ ] Optional STACKIT-IdP nach Machbarkeitsnachweis. -- [ ] Eigener Terraform-Code erst nach gesonderter Sicherheits-/Runner-Entscheidung. -- [ ] Erweiterte Teamprozesse, Audit-Export und kundenspezifische Isolationsoptionen. +Evidence and network correction: [platform operational status](platform-readiness.md). +Skeleton is not yet a usable Configurator and processes no customer configurations +or personal cloud credentials. -**Abnahme:** Automatische Korrektur hält ihre Policy auch bei unbekannten oder destruktiven Plans ein. Ausfall/Widerruf führt zu kontrollierter Pause statt unkontrollierten Wiederholungen. +Next business milestone: -## 15. Entscheidungsregister +- [ ] Decide GitHub App/OAuth integration, register callback URL and implement user login. +- [ ] Secure tenants, memberships and sessions with DB schema/migrations/RLS. +- [ ] Import one existing Accelerator template as first vertical workflow, edit business settings and save in personal fork. +- [ ] Personal deployment credentials: add tenant-specific access rules, secret-write identity and write/read/rotation test. +- [ ] Then integrate Plan/Apply Runner, approvals, graphical configuration and bounded chat. -| ID | Entscheidung | Empfehlung / Ergebnis | Status | Owner | -| --- | --- | --- | --- | --- | -| D01 | Zielgruppe | Mehrere unabhängige Kundenorganisationen ab Beginn | Bestätigt | Produkt | -| D02 | Terraform-Modifikationen | V1 nur Konfigurationen, eigener Code später | Bestätigt | Produkt | -| D03 | GitHub-Integration | GitHub App mit User Token; Fork-Voraussetzungen nachweisen | Offen | Backend | -| D04 | Mehrere Forks | Mehrere Owner/Repos; Branches/Configs als zusätzliche Varianten | Spike | Produkt/Backend | -| D05 | Persistenz | PostgreSQL Flex, Tenant-Isolation plus RLS | Vorschlag | Plattform | -| D06 | Runner-Hosting | Separate CF-Runner, sonst explizit SKE/Compute | Kritischer Spike | Plattform/Security | -| D07 | State-Eigentum | LZA-Bootstrap, anschließend Migration zum erzeugten Kunden-Backend | Entschieden; Recovery/Migration umzusetzen | Architektur | -| D08 | Secret-Verwaltung | Secret Store mit Run-Delegation und Tenant-Policies | Kritischer Spike | Security | -| D09 | Config-Format | Fach-JSON plus native landing-zone.tfvars | Standalone implementiert; versioniertes Deployment-Manifest offen | Architektur | -| D10 | Engine | Gepinntes OpenTofu 1.12.6 zuerst; Terraform separat qualifizieren | Vorschlag | Maintainer | -| D11 | STACKIT-IdP | Optional, Client-Registrierung nicht nachgewiesen | Offen | IAM | -| D12 | Drift Correction | Freigabe zuerst, automatische Allowlist später | Vorschlag | Produkt/Betrieb | -| D13 | KI-Modell | STACKIT-Service mit evaluiertem Modell und Tenant-Limits | Spike | KI/Produkt | -| D14 | Betriebsziele | RPO/RTO, Retention, Verfügbarkeit und Budget vor Kundenfreigabe | Offen | Betrieb | -| D15 | Produktname und Struktur | Landing Zone Configurator unter eigenem Top-Level-Verzeichnis | Bestätigt / Gerüst angelegt | Produkt | -| D16 | Anwendungssprache | TypeScript für Web/API/Worker; Go für begrenzten HCL-Adapter | Bestätigt, siehe ADR 0001 | Entwicklung | -| D17 | Dienstbereitstellung | Sämtliche Configurator-Dienste und Aktivierungen via IaC | Bestätigt | Plattform | -| D18 | Erste Umgebung | lzc-dev in eu01; Backend-Zugang zunächst ca. 90 Tage | Umgebung bestätigt; Laufzeit als Betriebsdefault | Plattform | - -## 16. Risiken und Definition of Done - -| Risiko | Gegenmaßnahme / Nachweis | -| --- | --- | -| Tenant-übergreifender Zugriff | RLS plus Objekt-Autorisierung, getrennte Secrets/States, Negativtests | -| Runner liest Betreiber-Secrets | Keine Backend-Bindings; gezielter Isolationstest | -| Fork-API passt nicht zum Onboarding | Früher GitHub-Spike; manueller Fork-/Connect-Flow als klare Alternative | -| UI und Terraform divergieren | Versionierter Katalog, Compiler-Fixtures und Migrationsprüfungen | -| Secret in Plan/State/Log/Chat | Geschützte Artefakte, Redaktion vor Logging, negative Tests | -| Private API aus CF unerreichbar | Netz-Spike, dediziertes Runner-Profil im Zielnetz | -| Zwei Prozesse schreiben denselben State | Backend-Lock plus kanonische State-ID und Plattform-Lease | -| Initial offene Firewall | Sicherer Bootstrap, Passwortrotation und Fehler-Runbook vor Freigabe | -| Unerwartetes Destroy/Create | Stabile Schlüssel, sichtbare Ersetzungen und konkrete Plan-Freigabe | -| Kunden blockieren gegenseitig Kapazitäten | Tenant-Quoten, faire Queue, Rate Limits und Backoff | -| KI missachtet Thema/Schema | Backend erzwingt Tools und Datenzugriffe; Evaluation und Fallback | -| Backup nicht wiederherstellbar | Restore-Übungen einschließlich Schlüsselmaterial | - -Für jedes Feature: - -- [ ] Fachliches Verhalten, Mapping und Grenzen dokumentiert. -- [ ] Editor, Chat, Compiler und Grafik nutzen dieselbe Semantik. -- [ ] Autorisierung, Mandantentrennung und relevante Fehlerfälle geprüft. -- [ ] Keine Secrets in Git, Frontend oder ungeschützten Artefakten. -- [ ] Migration und Betrieb dokumentiert, sofern erforderlich. -- [ ] Akzeptanznachweis und Issue-/PR-Link hinterlegt. - -## 17. Quellenstatus und laufende Planung - -Lokale Analyse: Repo-Stand `2161871`. Externe Primärquellen wurden am 2026-09-29 nach Wiederherstellung des Netzwerkzugriffs geprüft und direkt an den relevanten Aussagen verlinkt. Dokumentation ersetzt keine Integrationstests. Offen bleiben insbesondere konkrete Service-Pläne/-Quoten, die GitHub-Fork-UX, Secret-Policies, S3-Locking, private Runner-Konnektivität und STACKIT-IdP-Client-Registrierung. Object Storage und Model Serving werden durch ihre Provider-Ressourcen automatisch aktiviert; der frühere 404 ist damit geklärt. - -**Nächster Planungsschritt:** P0-Spikes für GitHub, Runner/Netz, State und Secrets priorisieren und Verantwortliche zuweisen. Danach D03/D06/D07/D08 entscheiden und den ersten vertikalen Ablauf von Login bis freigegebenem Apply schätzen. - -| Datum | Ergebnis / Entscheidung | Verantwortlich | Nachweis | -| --- | --- | --- | --- | -| 2026-09-29 | Architekturentwurf und Repo-Feature-Mapping erstellt | Noch zuzuweisen | Dieses Dokument | -| 2026-09-29 | Mehrere unabhängige Kunden ab Beginn; V1 nur Konfigurationen | Benutzerentscheidung | Planungsgespräch, D01/D02 | -| 2026-09-29 | TypeScript/React/Fastify bestätigt; lokale Entwicklungsbasis und getrennte CI angelegt | Entwicklung | ADR 0001, App-Workspace | -| 2026-09-29 | Object Storage 404 als nicht aktiviert geklärt; Provider aktiviert bei erstem Bucket | Entwicklung | platform-check.md | -| 2026-09-29 | lzc-dev/eu01 bestätigt; erster echter Bootstrap-Plan mit 3 Create erfolgreich | Benutzer / Entwicklung | infra/README.md | +Before production additionally: dedicated CF deployer with space-only permissions, narrower credential publication for releases, rotation, restore acceptance, rolling deployment and defined rollback. These are not marked complete by the first connectivity test. -Vorlage für laufende Arbeitspakete: + +## Portal design and start of login milestone (2026-09-30) -```markdown -### : -- Status: offen / in Arbeit / blockiert / erledigt -- Owner: -- Ziel und Abnahmekriterium: -- Abhängigkeiten / Entscheidungen: -- Aufwand / Zieltermin: -- Issue / PR: -- [ ] Umsetzung -- [ ] Relevante Prüfungen und Abnahmenachweis -- [ ] Dokumentation und Betrieb -``` +New confirmed requirement: look and feel should be identical to official STACKIT Portal. Reference is the project start page opened by the user. [Design comparison and progress](design-reference.md) document acceptance. Public portal assets were subsequently successfully captured without login through `curl`. Original NDS tokens and font definitions are documented with their brand/theme selectors; [retrieval tool](../tools/portal-reference/README.md). Rendered project view and active brand/theme selection are not yet visually confirmed. + +[GitHub App draft](../deploy/github/README.md) and tested PKCE/state/session-token helpers are prepared. This enables no login yet and does not mean completed session, RLS or token-store integration. + + +## Template selection and first editor (2026-09-30) + +- [x] Import eight real repository templates through pinned Go/HCL adapter. +- [x] Template catalogue with SHA-256, search and graphical organization structure. +- [x] Standalone copy: edit foundations, Landing Zones, sandboxes, environments and Secrets Manager selection. +- [x] Check placeholders, missing information and duplicate project identifiers; preserve untouched attributes. +- [x] Download versioned local draft; clearly label GitHub saving as follow-up. +- [x] Document original Nebula tokens, STACKIT logo, DIN 2014 and Univia Pro with provenance. +- [x] App tests, HCL tests and desktop/mobile browser workflow successful locally. +- [x] Include catalogue freshness and browser workflow in validation/release pipeline. +- [x] Accept feature-branch release on CF and connection tests. +- [ ] Visually confirm portal parity and close remaining component/icon differences. +- [ ] Implement GitHub login, RLS/tenant model and saving in selected fork. + +Important limits: editor currently edits only standalone; complex templates are readable previews. At that time, drafts lived only in tab memory; resumption documented below now adds browser storage. Download initially was an `.lzc.json` draft. Current status adds native `.tfvars` and editable JSON storage in fork (see [forks and navigation](forks-and-navigation.md)). No customer deployment occurs. + +Existing standalone template contains no explicit Corporate assignment although `variables.tf` defaults to `true`. Edited copy sets `corporate: false`, matching its missing network hub; Accelerator itself stays unchanged. Later export additionally needs schema/Plan acceptance. + +Acceptance of this status: commit `76db252` on `feature/landing-zone-configurator`. [Validation 36689446249](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36689446249) and [release 36689446170](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36689446170) successful. Pipeline checks 16 app tests, HCL adapter and four browser cases (desktop/mobile). CF push, service connection tests and public smoke checks successful. Additionally checked on live URL: eight templates, standalone editor, health 200, session without login 401 and no JavaScript runtime errors. No infrastructure change or merge to main. + + +### Customer Plan, 2026-09-30 + +User confirms personal access test and complete deployment preparation. Customer Plan may be tested; **customer Apply only after fresh explicit approval**, no Destroy. Configurator infrastructure approval does not cover it. D07: adopt existing LZA bootstrap followed by customer backend. Value-free Plan analysis and local real OpenTofu contract test implemented; production customer Runner still outstanding. [Implementation and acceptance](plan-execution.md). + + +### Plan-only execution + +Persisted personal Plan jobs and isolated CF tasks in a dedicated organization implemented; initial provisioning only after confirmation of empty state. Direct init/validate/plan/show commands, fixed engine/providers, sanitized action counts and cancellation. No Apply/Destroy endpoint. Durable bootstrap-state backup and exact Apply artifacts remain open prerequisites. [Acceptance](plan-execution.md). + + +### Resumption and folder checks, 2026-09-30 -## 18. CI/CD nach Lebenszyklus +- [x] Automatic fork list and account-bound resumption in same browser, including local draft, last page and original Git write baseline. +- [ ] Cross-device personal workspaces in PostgreSQL. +- [x] Check Accelerator folder hierarchy and document recommendation. +- [x] Implement folder editor and structure preview after explicit business confirmation. -Das [CI/CD-Konzept](cicd.md) definiert getrennte Workflows für seltenen Bootstrap, Plattformänderungen, häufige App-Releases und optionale Drift-Erkennung. Es enthält State-/Secret-Abhängigkeiten, Lifecycle-Ownership und eine abhakbare Umsetzungsreihenfolge. Deployment-Workflows sind geplant; die Validierungs-CI besteht bereits. Nächster technischer Schritt: unabhängiges Verwaltungs-Backend und sichere CI-Schlüsselhaltung vor dem ersten Cloud-Apply. +Details: [working state](forks-and-navigation.md#arbeitsstand-beim-wiederkommen), [common editor](common-editor.md). -Verwaltungs-Backend: separater Bucket im bestehenden Projekt durch `seed`/`seed-protection` angelegt. Bootstrap an S3 angebunden; CI-Schlüsselübergabe und Deployment-Workflows bleiben nächste Schritte. +Resumption/folder acceptance: code `21b5529`, [release 36729582680](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36729582680) successful. Current limits: [MVP scope](mvp-scope.md). User opens existing configuration once to save first local working state. Further visits in same browser restore it. Configuration changes require a new immutable deployment preparation. Personal initial Plan can now be tested; Apply stays blocked. -CI-Stand: Bootstrap-Workflow und Environment-Einrichtung lokal implementiert; Secret-Upload wartet auf explizite Freigabe. S3-Locking-Abnahme fehlgeschlagen (zweiter Prozess trotz Lock nicht blockiert); Remote-Applies sind technisch gesperrt. Backend-/Sperrstrategie muss vor Deployment entschieden werden. Siehe [CI-Betrieb](../infra/ci/README.md). + +### Architecture correction: common feature model, 2026-09-30 -Bestätigte Folgeentscheidung: S3 beibehalten, Deployments vorerst ausschließlich über serialisierte GitHub Actions. Lokale Remote-Applies bleiben gesperrt; alle mutierenden Workflows nutzen eine gemeinsame Concurrency-Gruppe. Benutzer hat den konkreten Secret-Transfer in die drei benannten GitHub Environments ausdrücklich genehmigt. +User requires all Accelerator capabilities regardless of selected example. Templates are presets; standalone editor is not a sustainable data-model boundary. [Common feature model and implementation plan](common-feature-model.md) and [generated input inventory](accelerator-inputs.json) form the foundation. -## Feature-Branch und Code Ownership +Fixed Public/sandbox assignment in the published project step remains open. Unpublished Corporate single-area prototype was saved and not delivered. Correction uses a common project/network structure with multiple areas and regions, then complete feature coverage. -Die Entwicklung erfolgt auf `feature/landing-zone-configurator`; eine Übernahme nach `main` ist derzeit ausdrücklich nicht vorgesehen. Für `/landing-zone-configurator/` und Configurator-Workflows unter `/.github/workflows/` ist ausschließlich `@lweberru` als CODEOWNER eingetragen. Gemeinsame Repository-Dateien behalten ihre bestehenden Owner. + +### Accelerator limitations and issue tracking, 2026-09-30 -Die GitHub-Environment-Regeln und der Deployment-Workflow erlauben weiterhin ausschließlich `main`. Feature-Branch-Entwicklung aktiviert daher keine Cloud-Deployments. Ein späterer Testbetrieb vom Feature-Branch braucht eine gezielte Anpassung dieser Regeln; der Branch wird dafür nicht automatisch nach main übernommen. +[Limitations and issue register](accelerator-limitations.md) is part of the common feature model. #37 remains separate workstream for private SNA Kubernetes APIs; #65 covers multi-appliance firewall policies. Additionally created: #80 (regional namespace assignment), #81 (Object Lock default), #82 (folder description) and #83 (missing root contract for module options). -GitHub wertet CODEOWNERS für Pull Requests aus dem jeweiligen Zielbranch aus: Für einen späteren PR nach main gilt zunächst die dortige bisherige Regel. CODEOWNERS setzt außerdem keine Branch-Protection-Regeln außer Kraft; eigene PRs können nicht selbst freigegeben werden. +Registering these limitations implements no runtime check yet. Backend capability checks and editor notices must be implemented before approving affected extended configurations. No customer Apply executed. -Feature-Branch-Test freigegeben: Push-Trigger für Bootstrap-Plan auf `feature/landing-zone-configurator`, entsprechende zusätzliche Branch-Regel ausschließlich im Plan-Environment. Apply/Recovery bleiben main-only. Kein Merge nach main für den Test erforderlich. + +### Common configuration core, 2026-09-30 -Bootstrap-Apply abgeschlossen: GitHub Run 36601941540 auf dem Feature-Branch, drei Ressourcen erstellt. Verschlüsselter Remote-State unabhängig geprüft; einmalige Commit-Freigabe entfernt. Nächster Schritt: separater Backend-Root zur Versionierung des Workload-State-Buckets. main bleibt unverändert. +- [x] Template-independent v3 document and field catalogue for all 28 root inputs. +- [x] Lossless import/export of all eight templates; checked legacy migration. +- [x] Common project/area projections and first reference/capability rules. +- [x] Add native HCL roundtrips and direct OpenTofu variable contract tests in CI. +- [x] Record newly discovered standalone default bug as Accelerator issue #84. +- [x] Switch common editor, working-state/fork storage and API to new core. +- [ ] Remaining feature editors, credential bindings and server-side execution checking. -Backend-Apply abgeschlossen: Run 36602706599, Versionierung für den Workload-State-Bucket aktiviert und direkt über S3 verifiziert. Verschlüsselter Backend-State geprüft; einmalige Freigaben entfernt. Die [Plattform-Vorbereitung](platform-readiness.md) dokumentiert die ausgewählten Katalogwerte und offenen Netzwerkparameter. +Product API initially remains restricted to v1/v2. No customer execution or changes to Accelerator modules. Details in [domain README](../app/packages/domain/README.md). -Netzwerk-Korrektur: CF-Egress-Adressen sind nicht dokumentiert/stabil (Benutzerhinweis). Die bisherige Anforderung fester CF-CIDRs entfällt. Stattdessen dienstspezifische, unterstützte Zugangsmodelle prüfen: dokumentierte STACKIT-Netze für PostgreSQL mit Konnektivitätstest; Secrets Manager separat. Migrationen als CF-Task vorsehen. Service-Bindings nicht als Netzwerkfreigabe behandeln. Siehe [Plattform-Vorbereitung](platform-readiness.md). + +### Common editor and release +- [x] Seven editor areas, German business labels, optional settings. +- [x] Unify project types and Corporate region/area selection. +- [x] v3 saving, resumption, legacy migration and server-side execution block. +- [x] Desktop/mobile browser tests for new and existing workflows. +- [x] Publication with CF/database/Secrets Manager connection tests. -Plattform-Versuch 2026-09-30: Plan mit neun Creates und Validierung erfolgreich; Apply-Run 36632950493 nach 45 Minuten abgebrochen. Teilbestand existiert (CF aktiv, Secrets Manager Running, PostgreSQL zuletzt PROGRESSING), Plattform-State fehlt. Einmalige Freigabe entfernt und Plattform-CI vorübergehend deaktiviert. Nächster Schritt ist die kontrollierte State-Recovery und verbesserte Abbruchbehandlung, nicht ein erneuter ursprünglicher Apply. Details und Checkliste: [Plattform-Betriebsstand](platform-readiness.md#vorfall-2026-09-30-erster-plattform-apply-unvollständig). +Details and user checklist: [common editor](common-editor.md). +Live acceptance: code `527bd95`, release `36745965953`, validation `36745965890` successful. New v3 configurations are editable and savable; their deployment execution remains blocked server-side. [Acceptance](common-editor.md#live-abnahme). -Plattform-Recovery abgeschlossen (2026-09-30): Run 36675347654 importierte den Teilbestand und vervollständigte die Plattform. Neun Ressourcen im verschlüsselten Remote-State unabhängig geprüft; PostgreSQL READY, CF aktiv, Secrets Manager Running. Verlorene technische Credentials kontrolliert ersetzt. Job-Timeout auf 100 Minuten erhöht, geordneten OpenTofu-Abbruch und verschlüsselte Diagnose-/State-Artefakte ergänzt. Einmalfreigaben entfernt. Nächster Ausbauschritt nach No-op-Abnahme: CF-Runtime/Bindings und Zugriffstests aus CF. [Aktuelle Abnahme](platform-readiness.md#erfolgreiche-recovery-und-plattform-abnahme). + +### Editor improvements: platform services, selection fields and standalone (#84) +- [x] Platform Kubernetes explicitly disableable with empty cluster list; existing dependencies remain checkable. +- [x] Central Observability and audit logging in platform tab; distinguish telemetry router from Observability. +- [x] Known enum values and regional/project/network references as selection fields. +- [x] Explicitly distinguish Accelerator default from template values. +- [x] New standalone drafts with explicit Public project; retain unchanged imports and existing exports. +- [x] 96 application tests, 22 desktop/mobile checks and 11 native OpenTofu variable tests successful. +- [ ] Connect regional live catalogues for product plans, machine types and versions. +- [x] Publication `10a6ec8` and live acceptance of this improvement status; release 36752620332 successful. -No-op-Abnahme abgeschlossen: Plattform-Run 36675895279 zeigt für alle neun Ressourcen `no-op`; Recovery/Apply korrekt übersprungen. Validierung 36675895374 erfolgreich. Die Plattform ist damit konsistent unter IaC-Verwaltung. + +### Binding interaction principles and component view +Decision: [design principles and VPN implementation plan](editor-design-principles.md). Product/module names, active components with add catalogue, progressive detail disclosure and product workflows close to documentation are binding guidelines. Complete feature coverage must not become a permanently expanded variable form. Implementation and acceptance are tracked in the linked plan. -CI-Entscheidung 2026-09-30: Auf Benutzerwunsch den eigenen JavaScript-Deployment-Runner durch direkte, sichtbare OpenTofu-Schritte in GitHub Actions ersetzen. Kleine Hilfsprogramme bereiten ausschließlich Credentials vor, prüfen Planintegrität und schützen State-Snapshots. Normale CLI-Logs werden wieder live ausgegeben; JSON-Credential-/State-Ausgaben bleiben privat. Abgeschlossene Recovery vom regulären Ablauf trennen. Auch lokale Validierung und Seed-Bedienung verwenden direkte `tofu`-Befehle. [Aktuelle Betriebsanleitung](../infra/ci/README.md). + +### Platform Landing Zone and Application self-service (architecture discussion) +Target design and open decisions: [Platform/Application architecture](platform-application-architecture.md). -CI-Vereinfachung abgenommen: echte direkte OpenTofu-Pläne für Bootstrap (36677111141), Plattform (36677111032) und Backend (36677367229) jeweils ohne Änderungen; Apply jeweils übersprungen. Native Logs sichtbar und gegen bekannte Credentials geprüft. Validierung einschließlich Linux-Timeout-Test erfolgreich. Temporäre Backend-Auswahl entfernt; Feature-Branch bleibt getrennt von main. +- [x] Distinguish platform resources, published Application templates and instances in business terms. +- [x] Plan two tenant-specific personas; treat Configurator permissions, STACKIT IAM and Git access separately. +- [x] Plan separate Accelerator roots, separate states and versioned platform contract as target. +- [x] User confirms immutable published versions, explicit upgrades and direct or approval-required provisioning selectable per template by Platform Engineer. +- [ ] Technically verify STACKIT login/OIDC client and delegated bootstrap access. +- [ ] Decide Application Owner Git storage, team assignment and template scope. +- [ ] Design Accelerator contracts and legacy migration; no automatic state splitting. +- [ ] Implement server-side authorization and template instantiation before introducing role views. +Ongoing region/SNA and VPN UI work continues independently. It is intended for the future Platform Engineer view. Until implementation, today's permissions and explicit customer Apply approval requirement remain. -## Aktueller Meilenstein: CF-Hosting und Service-Verbindungen + +### Region/SNA view and VPN configuration: local test status 2026-10-01 -Owner: `@lweberru`. Alle Änderungen bleiben auf `feature/landing-zone-configurator`. -Die Benutzerfreigabe vom 2026-09-30 umfasst notwendige Configurator-Deployment- -Applies bis zum MVP. Konkrete Pläne werden weiterhin geprüft; die Freigabe ist -keine Erlaubnis, Kundenressourcen oder fremde Projekte zu ändern. +- [x] Connectivity displayed by regions with SNAs and optional services; previous engine input forms retained. +- [x] New regions addable for regional configurations; no automatic conversion of existing configurations to regional modules. +- [x] VPN wizard for gateway, routing, connections/tunnels and summary. +- [x] Basic mandatory VPN information also checked in common validation model; no claim of complete provider/product validation. +- [x] VPN replication-to-all-SNAs limit checked against main and recorded as issue #85. +- [x] Lint/TypeScript/build, 97 application tests and 24 desktop/mobile browser cases successful; mobile VPN view visually checked. +- [ ] Publication and live acceptance; this status is not deployed yet. -- [x] Separate Runtime-IaC für CF-Space und Rollen. -- [x] Separate PostgreSQL-/Secrets-Laufzeitidentitäten; kein Migrations- oder Provisionierungszugang in der App. -- [x] Deklaratives CF-Manifest unter `deploy/cloud-foundry/`; OpenTofu und Release haben getrennte Zuständigkeiten. -- [x] Unabhängige Release-Pipeline mit direktem `cf push`, versioniertem Node-Runtime-Paket und Verbindungstest als CF-Task. -- [x] Öffentliche HTTPS-Route, UI-/JS-Auslieferung und gesperrte API (401) geprüft. -- [x] PostgreSQL: Login, SELECT und geprüfte TLS-Verbindung aus CF erfolgreich. -- [x] Secrets Manager: Login, TLS, authentifizierter KV-Lese-Endpunkt und Ablehnung ohne Token aus CF geprüft. -- [x] Abschließender [Release-Run 36683898762](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898762) vollständig erfolgreich; [Validierung 36683898795](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898795) ebenfalls grün. +VPN PSKs, dynamic product catalogues, actual VPN execution and new self-service role architecture remain separate work packages. No customer Apply. -Nachweise und Netzkorrektur: [Plattform-Betriebsstand](platform-readiness.md). -Das Grundgerüst ist noch kein nutzbarer Configurator und verarbeitet keine -Kundenkonfigurationen oder persönlichen Cloud-Zugangsdaten. + +### Publication and entry into self-service (2026-10-01) -Nächster fachlicher Meilenstein: +- [x] Editor release `78d8f7c` published on lzc-dev; release 36830339767 and validation 36830339847 successful. +- [x] Region view, components and VPN with two tunnels checked directly live; health/session checks successful. +- [x] Prototype `src/application` for one new application instance, separate from combined root. +- [x] Pure template/platform contract compiler with owner from server context and isolated state key. +- [x] Four compiler tests (101 application tests overall) and four native mock Plan tests successful; `tofu validate` successful with existing Observability deprecation warnings. +- [ ] Separate platform publication, immutable template persistence and identity/role management. +- [ ] Server API, instance idempotency, restricted credentials, queue/Runner and actual authorized customer Plan. -- [ ] GitHub-App/OAuth-Integration festlegen, Callback-URL registrieren und Benutzerlogin umsetzen. -- [ ] Mandanten, Mitgliedschaften und Sessions mit Datenbankschema/Migrationen/RLS absichern. -- [ ] Ein vorhandenes Accelerator-Template als ersten vertikalen Ablauf importieren, fachlich bearbeiten und im persönlichen Fork speichern. -- [ ] Persönliche Deployment-Credentials: mandantenbezogene Zugriffsregeln, Secrets-Schreibidentität und Write/Read/Rotation-Test ergänzen. -- [ ] Danach Plan/Apply-Runner, Freigaben, grafische Konfiguration und begrenzten Chat integrieren. +Prototype activates no new permission or Apply. Besides optional services, Application root creates automation and Object Storage resources already contained in the module; this is part of the template scope to publish. Existing states are not changed. -Vor Produktion zusätzlich: eigener CF-Deployer mit nur Space-Rechten, schmalere -Credential-Veröffentlichung für Releases, Rotation, Restore-Abnahme, Rolling -Deployment und definierter Rollback. Diese Punkte werden nicht durch den ersten -Konnektivitätstest als erledigt markiert. + +### VPN BGP extension recorded +- [x] Compare open and closed VPN/BGP issues; no dedicated open BGP issue exists. +- [x] Create [#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) for BGP support, including checking historical provider blocker with current pinned version. +- [ ] Implement Accelerator support and tests; then update Configurator schema, wizard and engine approval. -## Portal-Design und Beginn des Login-Meilensteins (2026-09-30) +BGP remains blocked in Configurator until then. No change to live deployment. -Neue bestätigte Anforderung: Das Look & Feel soll identisch zum offiziellen -STACKIT Portal werden. Referenz ist die vom Benutzer geöffnete Projektstartseite. -[Design-Abgleich und Fortschritt](design-reference.md) dokumentieren die Abnahme. -Die öffentlichen Portal-Assets wurden anschließend erfolgreich ohne Anmeldung per -`curl` erfasst. Originale NDS-Tokens und Schriftdefinitionen sind mit ihren -Marken-/Theme-Selektoren dokumentiert; [Abrufwerkzeug](../tools/portal-reference/README.md). -Die gerenderte Projektansicht und ihre aktive Marken-/Theme-Auswahl sind noch -nicht visuell bestätigt. + +### User management and API-backed product options -Der [GitHub-App-Entwurf](../deploy/github/README.md) und die getesteten -PKCE-/State-/Session-Token-Helfer sind vorbereitet. Dies aktiviert noch keinen -Login und bedeutet keine abgeschlossene Session-, RLS- oder Token-Store-Integration. +- [x] Separate internal user identity from external GitHub identity (migration 006). +- [x] Implement draft organization tenants, role memberships and management (migration 007). +- [x] Keep personal GitHub tokens separate during tenant switch; do not automatically promote existing users. +- [x] Query current product options through personal STACKIT access: Git performance classes, VPN plans, SKE versions, node flavors, zones and volume types. +- [x] Preserve existing values when catalogue entries are missing; make individual product API failures visible. +- [ ] Live acceptance of new management and product catalogues with user accounts and selected personal STACKIT access. +- [ ] Clarify STACKIT IDP ticket and verify organization binding. +- [ ] Recheck product availability server-side immediately before Plan/deployment; catalogues alone guarantee neither quota nor capacity. +- [ ] Add further dynamic fields as product APIs become available. +Organization tenants remain management drafts until verified STACKIT binding; customer Apply still requires approval unchanged. Details in [Platform/Application architecture](platform-application-architecture.md). -## Template-Auswahl und erster Editor (2026-09-30) +Test status for commit `59b0a04`: lint/TypeScript/build, 114 application tests, 17 PostgreSQL integration tests and all 30 desktop/mobile browser cases successful. Organization view additionally checked visually and for mobile overflow. Validation workflow [36836376140](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36836376140) successful. Catalogue tests use controlled API responses; a live query with personal user access remains outstanding. -- [x] Acht echte Repository-Templates über einen gepinnten Go/HCL-Adapter importieren. -- [x] Template-Katalog mit SHA-256, Suche und grafischer Organisationsstruktur. -- [x] Standalone-Kopie: Grundlagen, Landing Zones, Sandboxes, Umgebungen und Secrets-Manager-Auswahl bearbeiten. -- [x] Platzhalter, fehlende Angaben und doppelte Projektkennungen prüfen; unberührte Attribute erhalten. -- [x] Versionierten lokalen Entwurf herunterladen; GitHub-Speicherung klar als Folgeschritt kennzeichnen. -- [x] Originale Nebula-Tokens, STACKIT-Logo, DIN 2014 und Univia Pro mit Herkunft dokumentieren. -- [x] App-Tests, HCL-Tests und Browserablauf für Desktop/Mobil lokal erfolgreich. -- [x] Katalog-Aktualität und Browserablauf in Validierungs-/Release-Pipeline aufnehmen. -- [x] Feature-Branch-Release auf CF und Verbindungstests abnehmen. -- [ ] Portal-Parität visuell bestätigen und verbleibende Komponenten-/Icon-Abweichungen schließen. -- [ ] GitHub-Login, RLS/Mandantenmodell und Speicherung im ausgewählten Fork umsetzen. +- [x] Commit `59b0a04` published on lzc-dev: [release 36836376110](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36836376110) successful, including migrations, CF deployment and Runner checks. +- [x] Live health, new organization page and network deep link checked; delivered bundle `index-DxHvyiWG.js`. Anonymous organization API access rejected with 401. +- [ ] User acceptance: personal product catalogue query and organization member management with two accounts. -Wichtige Grenzen: Der Editor bearbeitet bisher nur Standalone; komplexe Templates -sind lesbare Vorschauen. Im damaligen Stand lagen Entwürfe nur im Tab-Arbeitsspeicher; -die unten dokumentierte Wiederaufnahme ergänzt nun Browserspeicherung. Der Download -war zunächst ein `.lzc.json`-Entwurf. Der aktuelle Stand ergänzt native `.tfvars` -und bearbeitbare JSON-Ablage im Fork (siehe [Forks und Navigation](forks-and-navigation.md)). Es findet kein Kunden-Deployment statt. + +### Feedback on components, catalogues and workspaces -Die bestehende Standalone-Vorlage enthält keine explizite Corporate-Zuordnung, -obwohl `variables.tf` standardmäßig `true` verwendet. Die bearbeitete Kopie setzt -`corporate: false`, passend zu ihrem fehlenden Netzwerk-Hub; der Accelerator selbst -bleibt unverändert. Ein späterer Export benötigt zusätzlich Schema-/Plan-Abnahme. +- [x] Check diagnostic bastion against Accelerator: VM in cluster project/SNA network; independent component recorded as [#87](https://github.com/stackitcloud/stackit-landing-zone/issues/87). +- [x] Explain central and cluster-specific Observability separately; reference instead of creation recorded as [#88](https://github.com/stackitcloud/stackit-landing-zone/issues/88). Check permitted project/region relationships before implementation. +- [x] Add deletion of empty unverified organization drafts as auditable archiving; no cloud resources deleted. +- [x] Explain user identifier with UUID example, copy function and understandable validation; remove whitespace on paste. +- [x] Catch accidental duplicate creation of same-name accessible workspaces for same organization ID server-side. +- [ ] Implement independent bastion root contract and secure Observability references in Accelerator; no changes to existing resource addresses without migration concept. +- [x] Add Observability plan selection for eu01 and bastion machine types, public images and IaaS zones; eu02 Observability remains manual without verified API source. +- [x] Check PIM v2 offering catalogue and distinguish from technical product catalogues; no automatic SKU-to-provider-ID adapter introduced. +- [x] Local checks of this extension: 117 application tests, 18 PostgreSQL tests, 30 desktop/mobile browser cases and lint/TypeScript/build successful. -Abnahme dieses Stands: Commit `76db252` auf `feature/landing-zone-configurator`. -[Validierung 36689446249](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36689446249) -und [Release 36689446170](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36689446170) -sind erfolgreich. Die Pipeline prüft 16 App-Tests, den HCL-Adapter und vier -Browserfälle (Desktop/Mobil). CF-Push, Service-Verbindungstests und öffentliche -Smoke-Checks waren erfolgreich. Zusätzlich auf der Live-URL geprüft: acht -Templates, Standalone-Editor, Health 200, Session ohne Login 401 und keine -JavaScript-Laufzeitfehler. Keine Infrastrukturänderung und kein Merge nach main. +Published on lzc-dev with commit `3532645`: [release 36840987284](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36840987284) and [validation 36840987238](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36840987238) successful. Migration 008, Cloud Foundry deployment and final checks successful; live health and organization page return HTTP 200, bundle `index-DqgRf507.js`. No real workspaces deleted during development/publication; no customer Apply execution. Product APIs tested with controlled responses; personal live acceptance of newly added catalogues remains outstanding. -### Kunden-Plan, 2026-09-30 + +### Invitation-based member management -Benutzer bestätigt persönlichen Zugangstest und vollständige Deployment-Vorbereitung. -Kunden-Plan darf getestet werden; **Kunden-Apply ausschließlich nach neuer ausdrücklicher -Freigabe**, kein Destroy. Die Configurator-Infrastrukturfreigabe gilt dafür nicht. -D07: bestehenden LZA-Bootstrap mit anschließendem Kunden-Backend übernehmen. Wertfreie Plan-Auswertung und lokaler echter -OpenTofu-Vertragstest umgesetzt; produktiver Kunden-Runner noch offen. -[Umsetzung und Abnahme](plan-execution.md). +- [x] Replace UUID input with role selection and one-time invitation link. +- [x] Seven-day validity, list and revoke open invitations; no email delivery. +- [x] Store token only hashed; joining after login and explicit confirmation. +- [x] First GitHub login creates internal user; invitation intent retained in same browser tab. +- [x] No role escalation of existing members through invitations; old API no longer adds unknown members. +- [x] Audit and protection against concurrent multiple acceptance, revocation, expiry and archived tenants. +- [ ] Later optional email delivery / selection of verified STACKIT organization members. -### Plan-only-Ausführung +Local acceptance: lint/TypeScript/build, 118 application tests, 21 real PostgreSQL tests and 32 desktop/mobile browser cases successful. Browser checking covers creation/revocation and invitation continuation after login; DB checking particularly covers concurrent acceptance, hash storage, expiry, revocation, archived tenants and revoked management permissions. -Persistierte persönliche Plan-Aufträge und isolierte CF-Tasks in eigener Organisation -umgesetzt; Erstbereitstellung nur nach Bestätigung eines leeren States. Direkte -init/validate/plan/show-Befehle, feste Engine/Provider, bereinigte Aktionszahlen und -Abbruch. Kein Apply-/Destroy-Endpunkt. Dauerhafte Bootstrap-State-Sicherung und -exakte Apply-Artefakte bleiben offene Voraussetzungen. [Abnahme](plan-execution.md). - -### Wiederaufnahme und Ordnerprüfung, 2026-09-30 - -- [x] Automatische Fork-Liste und kontogebundene Wiederaufnahme im selben Browser - einschließlich lokalem Entwurf, letzter Seite und ursprünglicher Git-Schreibbasis. -- [ ] Geräteübergreifende persönliche Arbeitsbereiche in PostgreSQL. -- [x] Ordnerhierarchie des Accelerators prüfen und Empfehlung dokumentieren. -- [x] Ordner-Editor und Strukturvorschau nach ausdrücklicher fachlicher Bestätigung umsetzen. - -Details: [Arbeitsstand](forks-and-navigation.md#arbeitsstand-beim-wiederkommen), -[gemeinsamer Editor](common-editor.md). - - -Abnahme Wiederaufnahme/Ordner: Code `21b5529`, -[Release 36729582680](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36729582680) -erfolgreich. Aktuelle Grenzen siehe [MVP-Umfang](mvp-scope.md). -Der Benutzer öffnet seine bestehende Konfiguration einmal, um den ersten lokalen -Arbeitsstand zu speichern. Weitere Besuche im selben Browser stellen ihn wieder her. -Nach Konfigurationsänderungen ist eine neue unveränderliche Deployment-Vorbereitung -nötig. Persönlicher Initial-Plan kann jetzt getestet werden; Apply bleibt gesperrt. - -### Architekturkorrektur: gemeinsames Feature-Modell, 2026-09-30 - -Benutzer fordert alle Accelerator-Funktionen unabhängig vom gewählten Beispiel. -Templates sind Presets; der Standalone-Editor ist keine tragfähige Grenze des -Datenmodells. [Gemeinsames Funktionsmodell und Umsetzungsplan](common-feature-model.md) -und [generiertes Eingabeinventar](accelerator-inputs.json) sind die Grundlage. - -Die feste Public-/Sandbox-Zuordnung im veröffentlichten Projekte-Schritt ist noch -offen. Der unveröffentlichte Corporate-Einzelbereich-Prototyp wurde gesichert und -nicht ausgeliefert. Die Korrektur erfolgt als gemeinsame Projekt-/Netzwerkstruktur -mit mehreren Bereichen und Regionen, anschließend vollständiger Feature-Abdeckung. - -### Accelerator-Grenzen und Issue-Verfolgung, 2026-09-30 - -[Grenzen- und Issue-Register](accelerator-limitations.md) ist Bestandteil des -gemeinsamen Feature-Modells. #37 bleibt der separate Arbeitsstrang für private -SNA-Kubernetes-APIs; #65 deckt Multi-Appliance-Firewall-Policies ab. -Zusätzlich wurden #80 (regionale Namespace-Zuordnung), #81 (Object-Lock-Default), -#82 (Ordnerbeschreibung) und #83 (fehlender Root-Vertrag für Moduloptionen) angelegt. - -Die Registrierung dieser Grenzen implementiert noch keine Laufzeitprüfung. -Capability-Prüfungen im Backend und Hinweise im Editor sind vor Freigabe der -betroffenen erweiterten Konfigurationen umzusetzen. Kein Kunden-Apply ausgeführt. - -### Gemeinsamer Konfigurationskern, 2026-09-30 - -- [x] Templateunabhängiges v3-Dokument und Feldkatalog für alle 28 Root-Eingaben. -- [x] Verlustfreier Import/Export aller acht Vorlagen; geprüfte Legacy-Migration. -- [x] Gemeinsame Projekt-/Bereichsprojektionen und erste Referenz-/Capability-Regeln. -- [x] Native HCL-Roundtrips und direkte OpenTofu-Variablenvertragstests in CI ergänzen. -- [x] Neu entdeckten Standalone-Defaultfehler als Accelerator-Issue #84 erfassen. -- [x] Gemeinsamen Editor, Arbeitsstand/Fork-Speicher und API auf den neuen Kern umstellen. -- [ ] Übrige Feature-Editoren, Credential-Bindings und serverseitige Ausführungsprüfung. - -Die Produkt-API bleibt vorerst auf v1/v2 beschränkt. Keine Kunden-Ausführung und -keine Änderungen an Accelerator-Modulen. Details im -[Domain-README](../app/packages/domain/README.md). - -### Gemeinsamer Editor und Release - -- [x] Sieben Editor-Bereiche, deutsche Fachbezeichnungen, optionale Einstellungen. -- [x] Projektarten und Corporate-Region-/Bereichsauswahl vereinheitlichen. -- [x] v3-Speicherung, Wiederaufnahme, Legacy-Migration und serverseitige Ausführungssperre. -- [x] Desktop-/Mobil-Browsertests für neue und bestehende Abläufe. -- [x] Veröffentlichung mit CF-/Datenbank-/Secrets-Manager-Verbindungstests. - -Details und Benutzer-Prüfliste: [gemeinsamer Editor](common-editor.md). - -Live-Abnahme: Code `527bd95`, Release `36745965953`, Validate `36745965890` erfolgreich. -Neue v3-Konfigurationen sind bearbeitbar und speicherbar; ihre Deployment-Ausführung -bleibt serverseitig gesperrt. [Abnahme](common-editor.md#live-abnahme). - - -### Editor-Nachbesserungen: Plattformdienste, Auswahlfelder und Standalone (#84) - -- [x] Plattform-Kubernetes ausdrücklich über leere Clusterliste deaktivierbar; bestehende Abhängigkeiten bleiben prüfbar. -- [x] Zentrales Observability und Audit-Protokollierung im Plattform-Reiter; Telemetry Router von Observability unterschieden. -- [x] Bekannte Enum-Werte und regionale/Projekt-/Netzwerkreferenzen als Auswahlfelder. -- [x] Accelerator-Standard ausdrücklich von Vorlagenwerten unterschieden. -- [x] Neue Standalone-Entwürfe mit explizitem Public-Projekt; unveränderte Imports und bestehende Exporte beibehalten. -- [x] 96 Anwendungstests, 22 Desktop-/Mobilprüfungen und 11 native OpenTofu-Variablentests erfolgreich. -- [ ] Regionale Live-Kataloge für Produktpläne, Maschinentypen und Versionen anbinden. -- [x] Veröffentlichung `10a6ec8` und Live-Abnahme dieses Nachbesserungsstands; Release 36752620332 erfolgreich. - -### Verbindliche Bedienprinzipien und Komponentenansicht - -Entscheidung: [Designprinzipien und VPN-Umsetzungsplan](editor-design-principles.md). -Produkt-/Modulnamen, aktive Komponenten mit Hinzufügen-Katalog, progressive -Detailanzeige und dokumentationsnahe Produktabläufe sind verbindliche Leitlinien. -Die vollständige Feature-Abdeckung darf nicht zu einem dauerhaft aufgeklappten -Variablenformular führen. Umsetzung und Abnahme werden im verlinkten Plan verfolgt. - -### Platform Landing Zone und Application Self-Service (Architekturdiskussion) - -Zielbild und offene Entscheidungen: [Platform-/Application-Architektur](platform-application-architecture.md). - -- [x] Plattformressourcen, veröffentlichte Application Templates und Instanzen fachlich getrennt. -- [x] Zwei mandantenbezogene Personas vorgesehen; Configurator-Rechte, STACKIT-IAM und Git-Zugriff getrennt behandelt. -- [x] Separate Accelerator-Roots, getrennte States und versionierter Plattformvertrag als Ziel eingeplant. -- [x] Benutzer bestätigt unveränderliche veröffentlichte Versionen, ausdrückliche Upgrades und je Template vom Platform Engineer wählbare direkte oder genehmigungspflichtige Bereitstellung. -- [ ] STACKIT-Login/OIDC-Client und delegierten Bootstrap-Zugriff technisch verifizieren. -- [ ] Application-Owner-Git-Ablage, Team-Zuordnung und Templateumfang entscheiden. -- [ ] Accelerator-Verträge und Bestandsmigration entwerfen; keine automatische State-Aufteilung. -- [ ] Serverseitige Autorisierung und Templateinstanziierung vor Einführung der Rollenansichten implementieren. - -Die laufende Regions-/SNA- und VPN-Oberfläche wird unabhängig davon weitergebaut. -Sie gehört perspektivisch zur Platform-Engineer-Sicht. Bis zur Umsetzung bleiben -heutige Berechtigungen und die ausdrückliche Freigabepflicht für Kunden-Apply bestehen. - -### Regions-/SNA-Ansicht und VPN-Konfiguration: lokaler Prüfstand 2026-10-01 - -- [x] Connectivity nach Regionen mit SNAs und optionalen Diensten dargestellt; bisherige Engine-Eingabeformen bleiben erhalten. -- [x] Neue Regionen für regionale Konfigurationen hinzufügbar; Bestandsumstellung auf regionale Module nicht automatisiert. -- [x] VPN-Assistent für Gateway, Routing, Verbindungen/Tunnel und Zusammenfassung. -- [x] Grundlegende VPN-Pflichtangaben auch im gemeinsamen Validierungsmodell geprüft; keine Aussage über vollständige Provider-/Produktvalidierung. -- [x] Grenze der VPN-Replikation auf alle SNAs gegen main geprüft und als Issue #85 erfasst. -- [x] Lint/TypeScript/Build, 97 Anwendungstests und 24 Desktop-/Mobil-Browserfälle erfolgreich; mobile VPN-Ansicht visuell geprüft. -- [ ] Veröffentlichung und Live-Abnahme; dieser Stand ist noch nicht deployed. - -VPN-PSKs, dynamische Produktkataloge, tatsächliche VPN-Ausführung und die neue -Self-Service-Rollenarchitektur bleiben gesonderte Arbeitspakete. Kein Kunden-Apply. - - -### Veröffentlichung und Einstieg in Self-Service (2026-10-01) - -- [x] Editor-Release `78d8f7c` auf lzc-dev veröffentlicht; Release 36830339767 und Validate 36830339847 erfolgreich. -- [x] Regionsansicht, Komponenten und VPN mit zwei Tunneln direkt live geprüft; Gesundheits-/Sitzungsprüfungen erfolgreich. -- [x] Prototyp `src/application` für eine neue Anwendungsinstanz, getrennt vom kombinierten Root. -- [x] Reiner Template-/Plattformvertrag-Compiler mit Owner aus Serverkontext und isoliertem State-Key. -- [x] Vier Compiler-Tests (101 Anwendungstests insgesamt) und vier native Mock-Plan-Tests erfolgreich; `tofu validate` erfolgreich mit bestehenden Observability-Deprecation-Warnungen. -- [ ] Separate Plattform-Veröffentlichung, unveränderliche Template-Persistenz und Identitäts-/Rollenverwaltung. -- [ ] Server-API, Instanz-Idempotenz, eingeschränkte Credentials, Queue/Runner und tatsächlicher autorisierter Kunden-Plan. - -Der Prototyp aktiviert keine neue Berechtigung und keinen Apply. Der Application- -Root erzeugt neben optionalen Diensten die bereits im Modul enthaltenen -Automations- und Object-Storage-Ressourcen; dies ist Teil des zu veröffentlichenden -Templateumfangs. Bestehende States werden nicht umgestellt. - - -### VPN-BGP-Erweiterung erfasst - -- [x] Offene und geschlossene VPN-/BGP-Issues abgeglichen; kein dediziertes offenes BGP-Issue vorhanden. -- [x] [#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) für BGP-Unterstützung angelegt, einschließlich Prüfung des historischen Provider-Blockers mit der aktuellen gepinnten Version. -- [ ] Accelerator-Unterstützung und Tests umsetzen; anschließend Configurator-Schema, Assistent und Engine-Freigabe aktualisieren. - -BGP bleibt bis dahin im Configurator gesperrt. Keine Änderung am Live-Deployment. - -### Benutzerverwaltung und API-gestützte Produktoptionen - -- [x] Interne Benutzeridentität von externer GitHub-Identität getrennt (Migration 006). -- [x] Entwurfs-Organisationstenants, Rollenmitgliedschaften und Verwaltung implementiert (Migration 007). -- [x] Persönliche GitHub-Token beim Tenant-Wechsel getrennt halten; bestehende Benutzer nicht automatisch hochstufen. -- [x] Aktuelle Produktoptionen über persönlichen STACKIT-Zugang abfragen: Git-Leistungsklassen, VPN-Pläne, SKE-Versionen, Node-Flavors, Zonen und Volume-Typen. -- [x] Bestandswerte bei fehlenden Katalogeinträgen erhalten; Ausfall einzelner Produkt-APIs sichtbar machen. -- [ ] Live-Abnahme der neuen Verwaltung und Produktkataloge mit Benutzerkonten und ausgewähltem persönlichem STACKIT-Zugang. -- [ ] STACKIT-IDP-Ticket klären und Organisationsbindung verifizieren. -- [ ] Serverseitige Produktverfügbarkeit unmittelbar vor Plan/Deployment erneut prüfen; Kataloge allein garantieren weder Quote noch Kapazität. -- [ ] Weitere dynamische Felder nach Produkt-API-Verfügbarkeit ergänzen. - -Organisationstenants bleiben bis zur verifizierten STACKIT-Anbindung Verwaltungsentwürfe; -Kunden-Apply bleibt unverändert freigabepflichtig. Details in der -[Platform-/Application-Architektur](platform-application-architecture.md). - -Prüfstand für Commit `59b0a04`: Lint/TypeScript/Build, 114 Anwendungstests, -17 PostgreSQL-Integrationstests und alle 30 Desktop-/Mobil-Browserfälle erfolgreich. -Die Organisationsansicht wurde zusätzlich auf mobilen Überlauf geprüft und visuell -kontrolliert. Validate-Workflow -[36836376140](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36836376140) -ist erfolgreich. Die Katalogtests verwenden kontrollierte API-Antworten; eine -Live-Abfrage mit einem persönlichen Benutzerzugang steht noch aus. - -- [x] Commit `59b0a04` auf lzc-dev veröffentlicht: [Release 36836376110](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36836376110) erfolgreich, einschließlich Migrationen, CF-Deployment und Runner-Prüfungen. -- [x] Live-Gesundheit, neue Organisationsseite und Netzwerk-Deep-Link geprüft; ausgeliefertes Bundle `index-DxHvyiWG.js`. Anonymer Zugriff auf die Organisations-API wird mit 401 abgewiesen. -- [ ] Benutzerabnahme: persönliche Produktkatalog-Abfrage und Organisations-Mitgliederverwaltung mit zwei Benutzerkonten. - -### Rückmeldungen zu Komponenten, Katalogen und Arbeitsbereichen - -- [x] Diagnose-Bastion gegen Accelerator geprüft: VM im Cluster-Projekt/SNA-Netz; unabhängige Komponente als [#87](https://github.com/stackitcloud/stackit-landing-zone/issues/87) erfasst. -- [x] Zentrale und clusterbezogene Observability getrennt erklärt; Referenz statt Neuanlage als [#88](https://github.com/stackitcloud/stackit-landing-zone/issues/88) erfasst. Zulässige Projekt-/Regionsbeziehungen vor Umsetzung prüfen. -- [x] Löschen leerer unverifizierter Organisationsentwürfe als auditierbare Archivierung ergänzt; keine Cloud-Ressourcen werden gelöscht. -- [x] Benutzerkennung mit UUID-Beispiel, Kopierfunktion und verständlicher Validierung erklärt; Leerzeichen beim Einfügen entfernt. -- [x] Versehentliche doppelte Anlage gleichnamiger zugänglicher Arbeitsbereiche für dieselbe Organisations-ID serverseitig abgefangen. -- [ ] Unabhängigen Bastion-Root-Vertrag und sichere Observability-Referenzen im Accelerator implementieren; keine Änderung bestehender Ressourcenadressen ohne Migrationskonzept. - -- [x] Observability-Plan-Auswahl für eu01 sowie Bastion-Maschinentypen, öffentliche Images und IaaS-Zonen ergänzt; eu02-Observability bleibt mangels verifizierter API-Quelle manuell. -- [x] PIM-v2-Angebotskatalog geprüft und gegenüber technischen Produktkatalogen abgegrenzt; kein automatischer SKU-zu-Provider-ID-Adapter eingeführt. -- [x] Lokale Prüfung dieser Erweiterung: 117 Anwendungstests, 18 PostgreSQL-Tests, 30 Desktop-/Mobil-Browserfälle sowie Lint/TypeScript/Build erfolgreich. - -Veröffentlicht auf lzc-dev mit Commit `3532645`: -[Release 36840987284](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36840987284) -und [Validierung 36840987238](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36840987238) -erfolgreich. Migration 008, Cloud-Foundry-Deployment und Abschlussprüfungen erfolgreich; -Live-Health und Organisationsseite liefern HTTP 200, Bundle `index-DqgRf507.js`. -Keine realen Arbeitsbereiche während der Entwicklung/Veröffentlichung gelöscht; -keine Kunden-Apply-Ausführung. Produkt-APIs mit kontrollierten Antworten getestet, -persönliche Live-Abnahme der neu ergänzten Kataloge bleibt offen. - -### Einladungsbasierte Mitgliederverwaltung - -- [x] UUID-Eingabe durch Rollenwahl und einmaligen Einladungslink ersetzt. -- [x] Sieben Tage Gültigkeit, offene Einladungen auflisten und widerrufen; keine E-Mail-Zustellung. -- [x] Token nur gehasht speichern; Beitritt nach Anmeldung und ausdrücklicher Bestätigung. -- [x] GitHub-Erstanmeldung legt den internen Benutzer an; Einladungsabsicht bleibt im selben Browser-Tab erhalten. -- [x] Keine Rolleneskalation vorhandener Mitglieder über Einladungen; alte API fügt keine unbekannten Mitglieder mehr hinzu. -- [x] Audit sowie Schutz vor paralleler Mehrfachannahme, Widerruf, Ablauf und archivierten Tenants. -- [ ] Spätere optionale Zustellung per E-Mail / Auswahl verifizierter STACKIT-Organisationsmitglieder. - -Lokale Abnahme: Lint/TypeScript/Build, 118 Anwendungstests, 21 echte PostgreSQL- -Tests und 32 Desktop-/Mobil-Browserfälle erfolgreich. Browserprüfung deckt das -Erstellen/Widerrufen und die Einladungsfortsetzung nach dem Login ab; DB-Prüfung -deckt insbesondere konkurrierende Annahme, Hashspeicherung, Ablauf, Widerruf, -archivierte Tenants und entzogene Verwaltungsrechte ab. - -Einladungsablauf auf lzc-dev veröffentlicht mit Commit `dde3379`: -[Release 36846494967](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36846494967) -und [Validierung 36846494917](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36846494917) -erfolgreich. Migration 009 und Abschlussprüfungen erfolgreich. Live-Health und -Organisationsseite HTTP 200, Bundle `index-DFtM2hCS.js`; anonyme Einladungsabfrage -HTTP 401. Keine realen Einladungen durch Entwicklung/Deployment erzeugt oder -versendet. Benutzerabnahme mit zweitem Konto bleibt offen. +Invitation workflow published on lzc-dev with commit `dde3379`: [release 36846494967](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36846494967) and [validation 36846494917](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36846494917) successful. Migration 009 and final checks successful. Live health and organization page HTTP 200, bundle `index-DFtM2hCS.js`; anonymous invitation query HTTP 401. No real invitations created or sent by development/deployment. User acceptance with second account remains outstanding. diff --git a/landing-zone-configurator/docs/platform-application-architecture.de.md b/landing-zone-configurator/docs/platform-application-architecture.de.md new file mode 100644 index 0000000..f6e4918 --- /dev/null +++ b/landing-zone-configurator/docs/platform-application-architecture.de.md @@ -0,0 +1,326 @@ + + +# Platform Landing Zone und Application Landing Zones + +[English](platform-application-architecture.md) | [Deutsch](platform-application-architecture.de.md) + +**Historische Designreferenz, kein aktueller Implementierungs- oder Abnahmenachweis.** +Die folgenden Abschnitte bewahren den Entwurf und seine damaligen offenen Fragen. +Fuer die aktuelle Implementierung gelten [Architektur](architecture.de.md), +[MVP-Grenzen](mvp-scope.de.md), [Benutzeranleitung](user-guide.de.md) und die +[technischen Vertraege](development.de.md). + +Der Erstellungsablauf ist inzwischen auf [Projekt-Template-Entwürfe](project-template-drafts.de.md) +umgestellt: neue Plattformkonfigurationen erzeugen keine Anwendungsinstanzen. +Die Implementierung der Veroeffentlichung, Tenant-Bindung und Bestellungen ist +in den aktuellen Vertraegen und Tests beschrieben, nicht in diesem Entwurfsstand. + +Dieser Entwurf erweitert [Planung](planning.de.md), [gemeinsames Feature-Modell](common-feature-model.de.md) und [Editor-Designprinzipien](editor-design-principles.de.md). Er ersetzt keine bestehenden Konfigurationen, State-Adressen oder Berechtigungen. Kunden-Apply bleibt bis zu einer ausdrücklichen Freigabe gesperrt. Die laufende Arbeit an Regions-/SNA-Ansicht und VPN bleibt unabhängig davon nutzbar. + + + +## Ziel und Abgrenzung + +Eine Platform Landing Zone stellt Governance, freigegebene Ordner, Connectivity einschließlich STACKIT Network Areas (SNAs), zentrale Plattformdienste und deren Infrastrukturprojekte bereit. Anwendungsprojekte gehören künftig zu eigenständigen Application Landing Zones. Ein Application Owner bestellt eine Instanz aus einem veröffentlichten Projekt-Template; er bearbeitet nicht die organisationsweite Plattformkonfiguration. + +Der aktuelle Accelerator verbindet diese Lebenszyklen im Root `src/main.tf`: zentrale Module und Anwendungsprojekte (`landing_zones`, Sandboxes, Namespace-Dienste) teilen Konfiguration und Ausführung. Zwei Ansichten allein reichen deshalb nicht. Benötigt werden getrennte Accelerator-Einstiegspunkte, ein freigegebener Plattformvertrag und unabhängig verwaltete Anwendungsinstanzen. + + + +## Rollen und Benutzerverwaltung + +Zwei fachliche Rollen gelten **pro Tenant**, nicht global. Ein Benutzer kann beide Rollen haben und in verschiedenen Kundenorganisationen unterschiedlich berechtigt sein. Anmeldung, Configurator-Mitgliedschaft, STACKIT-Rechte und GitHub-Zugriff bleiben getrennte Nachweise. + +| Fähigkeit | Platform Engineer | Application Owner | +|---|---|---| +| Plattform konfigurieren und deren Plan anfordern | Ja, im eigenen Tenant | Nein | +| Projekt-Templates erstellen, prüfen, versionieren und veröffentlichen | Ja | Nein | +| Veröffentlichte, für ihn zugelassene Templates sehen | Ja | Ja | +| Eigene Anwendungsinstanz bestellen und deren Plan sehen | Ja | Ja | +| Instanzen anderer Benutzer sehen/verändern | Nur nach Tenant-Policy | Nur durch explizite Teamfreigabe | +| Plattform-Credentials lesen oder herunterladen | Nein; nur autorisierte Nutzung | Nein | +| Kunden-Apply | Zusätzliche Run-Freigabe/Policy | Zusätzliche Run-Freigabe/Policy | +| Tenant-Mitglieder/Rollen verwalten | Separat delegierte Verwaltungsfähigkeit | Nein | + +Die vorgeschlagenen bisherigen Rollen Viewer/Editor/Deployer/Tenant-Admin aus dem Hauptplan werden für dieses Zielbild nicht zusätzlich als vier sichtbare Produktrollen eingeführt. Feinere technische Fähigkeiten (Mitgliederverwaltung, Credential-Delegation, Apply-Freigabe) bleiben explizite Grants. Ein Platform Engineer erhält nicht automatisch alle Verwaltungsrechte. Mitgliederverwaltung wird als tenantgebundene Fähigkeit innerhalb der Platform-Engineer-Rolle delegiert, nicht als dritte fachliche Persona. Rollen-/Einladungsänderungen benötigen erneute serverseitige Prüfung und Audit-Eintrag; niemand darf sich selbst weitergehende Rechte erteilen. + +Die Umstellung von bisherigen Viewer-/Editor-/Deployer-/Admin-Modellen erfolgt schrittweise nach Inventarisierung der tatsächlich gespeicherten Mitgliedschaften. Es gibt keine pauschale Zuordnung „Editor wird Platform Engineer“ und keine automatische Rechteerweiterung. Neue Rollen werden ausdrücklich durch berechtigte Tenant-Verantwortliche bestätigt; bis dahin bleiben vorhandene Zugriffe unter ihrem bisherigen, höchstens gleichwertigen Umfang. Migrationstests müssen auch kombinierte Rollen, Widerruf und offene Jobs abdecken. + +PostgreSQL speichert externe Identitätsverknüpfungen, Tenant-Mitgliedschaften, Rollen, Einladungen und Audit-Ereignisse. Keine eigene Passwortverwaltung. Jede API, Queue-Nachricht, Artefaktabfrage und Secret-Nutzung prüft den Tenant und die Objektberechtigung serverseitig. Ein Rollenwechsel im Browser ist kein Sicherheitsmechanismus. + + + +## Identität, STACKIT-Onboarding und Bootstrap + +**Verifiziert:** STACKIT verwendet rollenbasierte, additive Berechtigungen. Rollen auf Organisationen und Ordnern werden vererbt; eine schwächere Projektrolle hebt diese Rechte nicht auf. Ein Configurator-Login allein gewährt keine STACKIT-API-Berechtigung. [STACKIT Rollenmodell](https://docs.stackit.cloud/platform/access-and-identity/roles-permissions/roles-permissions/) + +**Verifiziert:** Vor einer weiteren Rollenzuweisung muss der Benutzer laut Resource-Manager-Dokumentation bereits eine der genannten Organisationsrollen besitzen. STACKIT empfiehlt dafür `organization.viewer`; diese gewährt minimale Organisationssicht ohne geerbten Zugriff auf Ordner und Projekte. Daher nicht vorsorglich Reader oder Owner auf einen gesamten Anwendungsordner vergeben. Den vollständigen Onboarding- und Portalablauf mit realem Testbenutzer prüfen. [Resource Manager Access Control](https://docs.stackit.cloud/platform/resource-manager/basics/access-control/) + +**Noch offen:** Ein freigegebener STACKIT-IdP-Client für unsere eigene App einschließlich Discovery, Clientregistrierung, Claims, Logout und API-Delegation. Die öffentliche OIDC-Anleitung beschreibt einen externen IdP, dem STACKIT vertraut; sie belegt keinen beliebig registrierbaren Configurator-Client beim STACKIT-IdP. [STACKIT IdP](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/getting-started/), [OIDC-Federation](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/how-tos/generic-oidc-1_0-federation-guide/) + +Vorgeschlagener Ablauf: + +1. Benutzer authentifiziert sich über einen freigegebenen IdP; bis zur Klärung bleibt GitHub als bestehender Login erhalten. +2. STACKIT-Benutzerkonto und konkrete Organisation werden gesondert verifiziert. Keine automatische Verknüpfung allein anhand übereinstimmender E-Mail-Adressen; stabile Issuer-/Subject-Kennung speichern. +3. Ein berechtigter Organisationsadministrator bestätigt Tenant-Zuordnung und erste Platform-Engineer-Mitgliedschaft. Besitz eines Service-Account-Schlüssels beweist keine persönliche Organisationsmitgliedschaft. +4. Fehlende Organisationsmitgliedschaft des Application Owners wird als expliziter Onboarding-Schritt behandelt. Er erhält nur die für das Onboarding nötige Rolle und später die freigegebene Projektrolle. +5. Für Bootstrap werden temporär autorisierte Berechtigungen benötigt, um Projekt, initialen Service Account und Backend anzulegen. Eine Anmeldung allein erzeugt diese Rechte nicht. Unterstützte Benutzer-API-Delegation erst nachweisen; andernfalls bleibt ein dokumentierter einmaliger Administrator-/Service-Account-Bootstrap nötig. +6. Nach Bootstrap temporäre Berechtigungen entfernen und Plattform-/Anwendungs-Provisionierung mit getrennten, eingeschränkten Ausführungsidentitäten betreiben. + +Die konkrete Permission-Matrix für Projektanlage, Rollenzuweisung, Netzwerkzuordnung und Dienstanlage ist per API/Provider-Spike nachzuweisen. Keine pauschale Zusage, dass `organization.viewer` für Provisionierung reicht: Diese Rolle betrifft die Benutzeraufnahme, nicht die Provisionierungsidentität. + + + +## Projekt-Templates und Instanzen + +Konkretisierung: [Template-Eingaben, feste Vorgaben und Ressourcenverknüpfungen](template-parameters-and-bindings.de.md). Der Entwurfseditor unterstützt fünf freigegebene Parameterfelder und eine lokale Bestellvorschau. Veröffentlichung und produktive Application-Instanziierung bleiben offen. + + +**Entschieden:** Veröffentlichte Template-Versionen bleiben unveränderlich. Bestehende Instanzen erhalten neue Versionen nur durch ein ausdrücklich angefordertes Upgrade mit eigenem Plan. + +Ein veröffentlichtes `ApplicationTemplateVersion` enthält: + +- Tenant, stabile Template-ID, Version, Status (`draft`, `published`, `retired`), Autor und Freigabe. +- Gepinnte Accelerator-Version, Compiler-/Schemasversion und Kompatibilität zum Plattformvertrag. +- Anwendungsprofil, etwa VM-Projekt, eigenes Kubernetes-Projekt oder Namespace auf einem zentralen Kubernetes-Cluster. Diese drei Varianten sind fachlich verschieden; ein Namespace ist kein eigenständiger Cluster. +- Feste Vorgaben: erlaubte Zielordner, Regionen und SNAs, Public-/Corporate-Typ, verpflichtende Dienste, Rollen, Namensregeln und Quoten. +- Explizit freigegebene Eingaben mit Typ, Auswahlwerten, Erklärung und Default, beispielsweise Name, Umgebung und zulässige Größenklasse. +- Deklarative Dienstkonfiguration, etwa STACKIT Secrets Manager und STACKIT Observability, sowie sichere Credential-Referenzen. Keine Secretwerte oder beliebigen Terraform-Skripte. +- Dokumentierte Ergebnisse, Voraussetzungen, technische Grenzen und Zuständigkeit für Betrieb/Löschung. + +Eine `ApplicationInstance` bindet eine konkrete Template-Version, zulässige Benutzereingaben, verifizierten Antragsteller/Projektverantwortlichen, Plattformvertragsversion, State-Identität und Ausführungsrevision. Templates werden kopiert/instanziiert, spätere Änderungen aktualisieren bestehende Instanzen nicht automatisch. Updates sind eigene Pläne mit sichtbarem Diff und Freigabe. + +Der Server setzt Organisation, Ordner, zulässige Region/SNA und Verantwortlichen aus verifizierten Bindungen. Er übernimmt diese Werte nicht ungeprüft aus Formular, Chat oder API. Der STACKIT-Projektverantwortliche muss ein geeignetes menschliches Konto sein; die Produktrolle Application Owner bedeutet nicht automatisch unbegrenzte STACKIT-IAM-Owner-Rechte. Welche konkrete Projektrolle/Owner-Zuweisung fachlich nötig ist, wird je Template festgelegt und mit der API getestet. + +**Wichtige offene Grenze:** Das bestehende Anwendungsprojektmodul ist kein vollständiger VM-/Kubernetes-Workload-Katalog. Vor Benennung eines Templates als „VM“ oder „Kubernetes“ muss klar sein, ob nur Projekt und Basisdienste oder tatsächlich VMs/Cluster/Namespaces erstellt werden. Nicht vorhandene Accelerator-Funktionen sind eigene Erweiterungen. + + + +## Accelerator-Vertrag, State und Ausführung + +Vorgeschlagene neue Roots (konkrete Pfade noch zu entscheiden): `platform` für zentrale Ressourcen und `application` für genau eine Anwendungsinstanz. Bestehendes `src` bleibt während der Migration kompatibel. Wiederverwendbare Module werden geteilt; kein Kopieren kompletter Plattformkonfigurationen pro Bestellung. + +Die Plattform veröffentlicht einen **nicht sensitiven, versionierten Vertrag**: Organisations-ID, freigegebene Ordner-IDs, Regionen, SNA-/Netzwerkreferenzen, erlaubte zentrale Cluster-/Dienstreferenzen, Fähigkeiten und Policy-Version. Anwendungen konsumieren nur diesen Vertrag, nicht den vollständigen Plattform-State. Server und Runner prüfen Freigabe, Aktualität und Zielorganisation vor jedem Plan und Apply. Es gibt keinen direkten `terraform_remote_state`-Zugriff der Anwendungsinstanzen auf den Plattform-State und keine Weitergabe seiner Backend-Credentials. + +```mermaid +flowchart LR + PE[Platform Engineer] --> PL[Platform Landing Zone] + PL --> PC[Versionierter Plattformvertrag ohne Secrets] + PE --> TV[Veröffentlichte Template-Version] + AO[Application Owner] --> REQ[Zulässige Eingaben und verifizierte Identität] + TV --> CHECK[Serverseitige Policy-Prüfung] + PC --> CHECK + REQ --> CHECK + CHECK --> PLAN[Plan pro Anwendungsinstanz] + PLAN --> APPROVE[Apply-Freigabe gemäß geltender Regel] + APPROVE --> APP[Application Landing Zone] + PL --> PS[Plattform-State] + APP --> AS[Eigener Anwendungs-State] +``` + +Getrennte Backend-Keys und Berechtigungen für Bootstrap, Plattform und jede Anwendungsinstanz; Tenant-Trennung bleibt erforderlich. Der vorhandene Accelerator-Bootstrap bleibt Grundlage der Backend-Bereitstellung. Keine Umstellung auf einen neuen zentralen Kunden-State ohne gesonderte Entscheidung. State-Locks und Queue-Locks pro Instanz verhindern konkurrierende Mutationen; geteilte Quoten/Netzwerkänderungen brauchen zusätzliche tenantweite Koordination. + +Eine zentrale Plattformressource hat genau einen State-Eigentümer. Anwendungs-States dürfen sie referenzieren, aber nicht erneut verwalten. Entfernen einer SNA/eines Clusters wird blockiert, solange Anwendungsinstanzen davon abhängen. Laufende Ausführungen müssen vor Vertragsänderungen berücksichtigt werden. + +Anwendungsjobs bekommen eine eingeschränkte, tenantgebundene Ausführungsidentität und ausschließlich freigegebene Ressourcenreferenzen. Die Template-Instanziierung ist kein Weg, den organisationsweiten Bootstrap-Service-Account zu delegieren. Retry/Idempotenz über Instanz-ID und Bestellschlüssel, kein zweites Projekt bei erneutem Klick. Quoten werden atomar reserviert und nach Fehlern abgeglichen. + +Ein Klick auf „Bereitstellen“ startet zunächst Validierung und Plan. Automatischer Apply ist eine spätere explizite Produkt-/Tenant-Policy; die derzeitige persönliche Freigabepflicht für Kunden-Apply gilt unverändert. **Bestätigte Entscheidung:** Der Platform Engineer kann je Template sowohl direkte Bereitstellung als auch einen Genehmigungsablauf erlauben. Diese Policy wird serverseitig vor Plan und Apply geprüft; eine Änderung hebt die heutige Kunden-Apply-Freigabepflicht nicht vorzeitig auf. Der sichere Initialwert für neue Templates (Genehmigung erforderlich) ist ein Umsetzungsvorschlag. + + + +## GitHub und Application-Owner-Erlebnis + +Der Application Owner sollte keinen Fork auswählen müssen, nur um ein freigegebenes Template zu bestellen. Veröffentlichung kann durch den Platform Engineer aus seiner benutzergebundenen GitHub-Verbindung einen signierten/gehashten, unveränderlichen Snapshot in den Tenant-Katalog übernehmen. Lesen dieses veröffentlichten Snapshots ist kein Repositoryzugriff unter fremden Credentials. + +Offen bleibt, wie Instanzen im Git archiviert werden: persönliche GitHub-Verbindung des Application Owners oder vom Platform Engineer ausdrücklich ausgeführter Export/Review. Bis zur Entscheidung PostgreSQL plus unveränderliche Konfigurationsartefakte als vorgeschlagener Instanznachweis. Kein stiller Wechsel auf zentrale GitHub-Tokens und keine Hintergrundschreibzugriffe unter dem Token eines anderen Benutzers. Die ursprüngliche Vorgabe benutzergebundener Repositoryzugriffe bleibt erhalten. + + + +## UI-Auswirkungen + +Platform Engineer: Plattform, Projekt-Templates, Veröffentlichungen, Anwendungsübersicht und getrennt berechtigte Tenant-Verwaltung. Application Owner: freigegebene Projekt-Templates, eigene/zugewiesene Anwendungen, Status, Pläne und Zugänge. Aktueller Tenant und aktuelle Rolle sind stets sichtbar. + +Die aktuelle Komponentenansicht bleibt Grundlage des Plattformeditors. Der spätere Template-Editor nutzt dieselben Fachkomponenten, ergänzt jedoch „fest vorgeben“, „Application Owner auswählen lassen“ und „nicht verfügbar“. Ein unbekanntes Feld ist nicht automatisch eine freigegebene Variable. Der Chat verwendet dieselben Autorisierungs- und Templateschemas wie das Formular. + + + +## Migration ohne Ressourcenverlust + +- Bestehende Gesamtkonfigurationen, Hashes und State-Adressen bleiben unverändert lesbar. +- Zunächst neue reine Plattformen und neue Anwendungsinstanzen unterstützen. +- Bestehende Projekte und ihre gemeinsam verwalteten Ressourcen inventarisieren; eindeutigen zukünftigen State-Eigentümer festlegen. +- Separaten, getesteten Migrationslauf mit Backup, Locks, Import-/State-Move-Plan, Abbruch- und Rückkehrstrategie entwickeln. Cross-State-Migration ist kein gewöhnlicher UI-Speichervorgang. +- Vor und nach jeder Migration nachweisen, dass weder unerwartete Neuanlage noch Löschung geplant wird. Keine automatische Migration durch Login, Template-Auswahl oder Öffnen eines Dokuments. +- Bekannte Grenzen #22 (Folder-Destroy), #37 (privates Kubernetes), #65 (Firewall), #80 (regionale Namespace-Verkabelung) gelten auch für die neuen Roots. + + + +## Diskussionsentscheidungen und Umsetzung + +Empfehlungen für die nächste gemeinsame Entscheidung: + +1. Zwei Rollen pro Tenant; beide gleichzeitig möglich. Mitgliedschaftsverwaltung separat delegieren. +2. Application Owner benötigt zunächst ein bereits verifiziertes STACKIT-Konto; geführte Organisationsaufnahme, keine implizite Kontoerstellung. +3. Zuerst ein Template „Anwendungsprojekt mit Basisdiensten“, danach eigene Cluster/VMs und zentrale Namespace-Angebote jeweils nach nachgewiesenem Accelerator-Support. +4. Template-Veröffentlichung als unveränderlicher Tenant-Katalog-Snapshot; Git-Ablage der Instanzen gesondert entscheiden. +5. Erst Plattform- und Anwendungs-Plan getrennt implementieren, dann kontrollierter Apply; Bestandsmigration zuletzt. + + + +### Phase A – Verträge und IAM-Nachweis + +- [x] Zielbild, Rollentrennung und offene Annahmen dokumentieren. +- [x] Unveränderliche veröffentlichte Template-Versionen und explizite Upgrades vom Benutzer bestätigt. +- [x] Zukünftige Apply-Policy durch Platform Engineer je Template einstellbar: direkt oder genehmigungspflichtig. +- [ ] Entscheidungen zu Verantwortlichem/Team, Git-Ablage und Freigabeweg treffen. +- [ ] STACKIT-IdP-Client und delegierte Benutzer-API-Berechtigungen mit STACKIT klären. +- [ ] Organisationsaufnahme und minimale Rechte mit eigenem Testbenutzer nachweisen. +- [ ] Inventar bestehender Plattform-/Anwendungsressourcen und Capability-Matrix erstellen. +- [ ] Plattformvertrag, Template-Schema und getrennte State-Eigentümerschaft reviewen. + + + +### Phase B – Accelerator und reine Plan-Unterstützung + +- [ ] Neue Roots/Module und versionierten Plattformvertrag implementieren. +- [ ] Template-Compiler mit erlaubten Eingaben und festen Policies implementieren. +- [ ] Isolierte Anwendungs-States und eingeschränkte Runner-Credentials anbinden. +- [ ] Native OpenTofu-Vertragstests und Plan-Negativtests für fremde Ordner/SNAs/Organisationen. +- [ ] Separates Konzept für Bestandsmigration ausarbeiten; noch nicht ausführen. + +### Phase C – Configurator Self-Service + +- [ ] Tenant-Rollen, Einladungen, Identitätsverknüpfung und Audit-Log implementieren. +- [ ] Template-Entwurf, Veröffentlichung, Katalog und Stilllegung implementieren. +- [ ] Rollenabhängige Ansichten, Bestellformular und eigene Instanzen implementieren. +- [ ] API-/RLS-/Job-Negativtests gegen tenantfremde Zugriffe und Rolleneskalation. +- [ ] Idempotenz, Quoten, Fehlerwiederaufnahme und Template-Updates testen. +- [ ] Kunden-Apply erst nach konkreter Freigabe; bestätigte spätere Self-Service-Apply-Policy sicher implementieren. + + + +## Erster technischer Prototyp (2026-10-01, noch nicht an API/Runner angebunden) + +- `src/application` ist ein separater Root für genau eine neue Anwendungsinstanz, + mit Verweis auf freigegebene Plattformressourcen und eigenem S3-Backend-Key. +- `app/packages/domain/src/application-plan.ts` enthält einen reinen Compiler für + veröffentlichte Templates, verifizierten Serverkontext und streng begrenzte + Bestelleingaben. Tenant-, Organisations-, Revisions- und Zielbindung werden geprüft. +- Der Compiler übernimmt den Owner aus dem Serverkontext und Dienste aus dem + Template. Er ersetzt weder serverseitige Mitgliedschaftsprüfung noch tatsächliche + STACKIT-Identitätsprüfung, Veröffentlichung/Persistierung oder Job-Autorisierung. +- Vier native Mock-Plan-Tests prüfen Public/Corporate sowie Tenant-/Revisionsgrenzen; + vier Compiler-Tests prüfen isolierte State-Schlüssel, Bindungen und Eingabe-Injektion. +- Ausführung bleibt ausdrücklich deaktiviert; `direct` ist nur gespeicherte + zukünftige Policy. Kein API-Endpunkt, keine Rollenumschaltung und kein Kunden-Plan + wurden damit bereits freigeschaltet. + +Das geteilte Modul erzeugt außer den auswählbaren Diensten auch einen Automations- +Service-Account samt Schlüssel und Object-Storage-Buckets/Credentials. Dieser Umfang +muss beim Veröffentlichen des Basis-Templates und im Plan sichtbar sein. Die +Anwendungsinstanz verwendet für ihren ersten Lauf das vorhandene Bootstrap-Backend, +nicht ihren erst später erzeugten eigenen Bucket. + + + +## Umsetzungsschritt: unabhängige Benutzeridentität (2026-10-01) + +Die additive Migration `006_external_identities.sql` trennt externe Anmeldeidentitäten +von der internen Benutzer-UUID. Bestehende GitHub-Zuordnungen werden übernommen; +Benutzer-, Tenant-, Konfigurations- und Secret-Adressen bleiben unverändert. +GitHub-Anmeldung löst Benutzer jetzt über Provider, Issuer und unveränderliche +GitHub-ID auf. Die bisherigen GitHub-Spalten bleiben für bestehende Session- +und Repository-Schnittstellen vorübergehend erhalten und sind nun optional. +Es existiert noch kein OIDC-Login und keine öffentliche Account-Linking-API. +Identitätsverknüpfungen haben keine direkten Runtime-Tabellenrechte. + +STACKIT IDP bleibt der bevorzugte Hauptlogin. Das Ticket zur Registrierung eines +eigenen OIDC-Clients wurde vom Benutzer gestellt; die Antwort steht aus. +Die öffentliche [Federationsanleitung](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/how-tos/generic-oidc-1_0-federation-guide/) +beschreibt STACKIT als Relying Party und bestätigt diesen Registrierungsweg nicht. +Alternativ wird ein freigegebener Unternehmens-OIDC-Anbieter angebunden; ein +Identity Broker ist erst bei entsprechendem Bedarf vorgesehen. GitHub bleibt +bis zur Umstellung der Übergangslogin und später eine persönliche Verbindung. +Kein Zusammenführen von Konten allein anhand gleicher E-Mail-Adressen. + + + +### Nächste Implementierungsschritte + +- [x] Externe Identitäten separat speichern und bestehende UUIDs erhalten. +- [x] PostgreSQL-Tests: Bestandsmigration, GitHub-Umbenennung, Runtime-Zugriffsverbot, + issuergebundene Subjects und Benutzer ohne GitHub. +- [ ] Verifizierte OIDC-Anmeldung nach Client-Registrierung; Anbieter serverseitig + freigeben, Identität anhand von Issuer und Subject prüfen. +- [ ] Sichere Verknüpfung bestehender Benutzer mit erneutem Nachweis beider Konten. +- [ ] Organisationstenants von bisherigen persönlichen Arbeitsbereichen unterscheiden; + zunächst genau eine verifizierte STACKIT-Organisation je Organisationstenant. +- [ ] Mitgliedschaften mit Platform Engineer / Application Owner und separater + Mitgliederverwaltungsfähigkeit, Widerruf und Audit implementieren. +- [ ] Tenant-Wechsel mit unabhängiger persönlicher GitHub-Token-Bindung implementieren. +- [ ] Bestehende API-Rechte auf neue Rollen umstellen, bevor Application Owner Zugang erhalten. +- [ ] Oberfläche „Organisation & Mitglieder“ und Application-Katalog bereitstellen. + +Dieser Schritt aktiviert keine neuen Rollen, erteilt keine STACKIT-Rechte und +ändert weder die Kunden-Apply-Freigabe noch die bestehenden Tenant-Grenzen. + + + +## Organisation & Mitglieder: erster Verwaltungsstand + +Organisationstenants können jetzt getrennt vom persönlichen Arbeitsbereich angelegt +werden. Ihre STACKIT-Organisations-ID ist ausdrücklich **unverifiziert**. Ein Benutzer +kann mehrere Arbeitsbereiche besitzen bzw. ihnen angehören; die Oberfläche bietet +einen expliziten Wechsel mit vollständigem Neuladen. Die persönliche GitHub-Token- +Bindung bleibt beim Wechsel auf den ursprünglichen Benutzer-/Session-Pfad gebunden. + +Die Mitgliederverwaltung verwendet zunächst die interne UUID eines bereits +registrierten Benutzers. Es gibt keinen globalen Benutzerkatalog und keine automatische +Kontozusammenführung über E-Mail. Platform Engineer und Application Owner sind +kombinierbar. Mitgliederverwaltung ist eine gesonderte Fähigkeit für Platform Engineers. +Änderungen werden auditiert; der letzte Verwalter darf auch bei konkurrierenden +Änderungen nicht verloren gehen. Bestehende persönliche Mitgliedschaften werden +nicht auf die neuen Rollen hochgestuft. + +**Ausführungsgrenze dieses Stands:** Organisationstenants sind Verwaltungsentwürfe. +Credentials, Produktkatalog-Abfragen und die alten Plan-/Deployment-Endpunkte sind +dort serverseitig gesperrt. Application Owner erhalten auch keinen Zugriff auf die +bisherigen Plattform-/Git-Endpunkte. Der persönliche Arbeitsbereich bleibt für die +bisherige Konfiguration und autorisierte Plan-Nutzung verfügbar. Die neue Ansicht +aktiviert noch keinen Application-Katalog und keine Kunden-Apply-Funktion. + +- [x] Entwurfs-Organisationstenants und expliziter Tenant-Wechsel. +- [x] Rollenmitgliedschaften und separate Mitgliederverwaltung mit Audit. +- [x] Oberfläche „Organisation & Mitglieder“ und serverseitige Abgrenzung der alten APIs. +- [ ] STACKIT-Organisationsbindung und handelnde Benutzeridentität verifizieren. +- [ ] Erst danach tenantgebundene Credentials und organisationsweite Ausführung freigeben. +- [ ] Einladungen, STACKIT-Mitgliederabgleich und unveränderliche Application Templates. + + + +## Mitgliedseinladungen ersetzen manuelle Benutzerkennungen + +Neue Mitgliedschaften entstehen durch ausdrückliche Annahme eines Einladungslinks. +Der Verwalter wählt Rollen und gegebenenfalls Mitgliederverwaltung. Der Link ist +sieben Tage gültig, einmal verwendbar und bis zur Annahme widerrufbar. Er wird nur +bei Erstellung vollständig angezeigt; PostgreSQL speichert ausschließlich seinen +SHA-256-Hash. Der zufällige Token besitzt 256 Bit Entropie. Es wird keine E-Mail +verschickt. Der Link ist eine übertragbare Berechtigung und muss gezielt an die +gewünschte Person weitergegeben werden; er ist nicht an eine E-Mail-Adresse gebunden. + +Die Person meldet sich über den verfügbaren Login an; beim ersten GitHub-Login +entsteht automatisch ihr interner Benutzer. Sie sieht Arbeitsbereich und Rollen +und bestätigt den Beitritt. Der Token wird im URL-Fragment transportiert, sofort +von der sichtbaren URL entfernt und nur im aktuellen Tab über den Login hinweg +in Session Storage gehalten. Vorschau und Annahme erfordern Anmeldung, Annahme +zusätzlich Origin-/CSRF-Prüfung. Tokens erscheinen nicht in URL-Pfaden, Querystrings, +Audit-Ereignissen oder der Einladungsliste. Nach Annahme/Schließen wird der lokale +Token entfernt. Ein unterbrochener Ablauf lässt sich mit dem Link erneut öffnen. + +Der Server serialisiert Annahme, Widerruf und Mitgliedsverwaltung am Tenant. +Abgelaufene/verwendete/widerrufene Einladungen, archivierte Arbeitsbereiche und +Einladende ohne aktuelle Verwaltungsberechtigung werden abgewiesen. Bestehende +Mitglieder erhalten über eine Einladung keine zusätzlichen Rollen. Der alte +Mitglieds-Endpunkt darf nur noch existierende Mitgliedschaften bearbeiten. +Die UI benötigt keine internen Benutzerkennungen mehr. Einladungen verwalten und +annehmen erteilt keine STACKIT-IAM-Rechte und aktiviert kein Kunden-Apply. diff --git a/landing-zone-configurator/docs/platform-application-architecture.md b/landing-zone-configurator/docs/platform-application-architecture.md index 0560c77..c3d10df 100644 --- a/landing-zone-configurator/docs/platform-application-architecture.md +++ b/landing-zone-configurator/docs/platform-application-architecture.md @@ -1,92 +1,100 @@ -# Platform Landing Zone und Application Landing Zones +# Platform Landing Zone and Application Landing Zones -**Historische Designreferenz, kein aktueller Implementierungs- oder Abnahmenachweis.** -Die folgenden Abschnitte bewahren den Entwurf und seine damaligen offenen Fragen. -Fuer die aktuelle Implementierung gelten [Architektur](architecture.md), -[MVP-Grenzen](mvp-scope.md), [Benutzeranleitung](user-guide.md) und die -[technischen Vertraege](development.md). +[English](platform-application-architecture.md) | [Deutsch](platform-application-architecture.de.md) -Der Erstellungsablauf ist inzwischen auf [Projekt-Template-Entwürfe](project-template-drafts.md) -umgestellt: neue Plattformkonfigurationen erzeugen keine Anwendungsinstanzen. -Die Implementierung der Veroeffentlichung, Tenant-Bindung und Bestellungen ist -in den aktuellen Vertraegen und Tests beschrieben, nicht in diesem Entwurfsstand. + -Dieser Entwurf erweitert [Planung](planning.md), [gemeinsames Feature-Modell](common-feature-model.md) und [Editor-Designprinzipien](editor-design-principles.md). Er ersetzt keine bestehenden Konfigurationen, State-Adressen oder Berechtigungen. Kunden-Apply bleibt bis zu einer ausdrücklichen Freigabe gesperrt. Die laufende Arbeit an Regions-/SNA-Ansicht und VPN bleibt unabhängig davon nutzbar. +**Historical design reference, not current implementation or acceptance evidence.** +The following sections preserve the design and its questions open at that time. +For the current implementation, see [architecture](architecture.md), +[MVP boundaries](mvp-scope.md), [user guide](user-guide.md) and +[technical contracts](development.md). -## Ziel und Abgrenzung +The creation workflow has since switched to [project template drafts](project-template-drafts.md): +new platform configurations create no application instances. +Implementation of publication, tenant binding and orders is described in the current +contracts and tests, not in this design snapshot. -Eine Platform Landing Zone stellt Governance, freigegebene Ordner, Connectivity einschließlich STACKIT Network Areas (SNAs), zentrale Plattformdienste und deren Infrastrukturprojekte bereit. Anwendungsprojekte gehören künftig zu eigenständigen Application Landing Zones. Ein Application Owner bestellt eine Instanz aus einem veröffentlichten Projekt-Template; er bearbeitet nicht die organisationsweite Plattformkonfiguration. +This design extends [planning](planning.md), the [common feature model](common-feature-model.md) and [editor design principles](editor-design-principles.md). It replaces no existing configurations, state addresses or permissions. Customer Apply remains blocked until explicit approval. Ongoing work on region/SNA views and VPN remains independently usable. -Der aktuelle Accelerator verbindet diese Lebenszyklen im Root `src/main.tf`: zentrale Module und Anwendungsprojekte (`landing_zones`, Sandboxes, Namespace-Dienste) teilen Konfiguration und Ausführung. Zwei Ansichten allein reichen deshalb nicht. Benötigt werden getrennte Accelerator-Einstiegspunkte, ein freigegebener Plattformvertrag und unabhängig verwaltete Anwendungsinstanzen. + +## Goal and boundaries -## Rollen und Benutzerverwaltung +A Platform Landing Zone provides governance, approved folders, connectivity including STACKIT Network Areas (SNAs), central platform services and their infrastructure projects. Application projects will belong to independent Application Landing Zones. An Application Owner orders an instance from a published project template; they do not edit organization-wide platform configuration. -Zwei fachliche Rollen gelten **pro Tenant**, nicht global. Ein Benutzer kann beide Rollen haben und in verschiedenen Kundenorganisationen unterschiedlich berechtigt sein. Anmeldung, Configurator-Mitgliedschaft, STACKIT-Rechte und GitHub-Zugriff bleiben getrennte Nachweise. +The current Accelerator combines these lifecycles in root `src/main.tf`: central modules and application projects (`landing_zones`, sandboxes, namespace services) share configuration and execution. Two views alone are therefore insufficient. Separate Accelerator entry points, an approved platform contract and independently managed application instances are needed. -| Fähigkeit | Platform Engineer | Application Owner | -|---|---|---| -| Plattform konfigurieren und deren Plan anfordern | Ja, im eigenen Tenant | Nein | -| Projekt-Templates erstellen, prüfen, versionieren und veröffentlichen | Ja | Nein | -| Veröffentlichte, für ihn zugelassene Templates sehen | Ja | Ja | -| Eigene Anwendungsinstanz bestellen und deren Plan sehen | Ja | Ja | -| Instanzen anderer Benutzer sehen/verändern | Nur nach Tenant-Policy | Nur durch explizite Teamfreigabe | -| Plattform-Credentials lesen oder herunterladen | Nein; nur autorisierte Nutzung | Nein | -| Kunden-Apply | Zusätzliche Run-Freigabe/Policy | Zusätzliche Run-Freigabe/Policy | -| Tenant-Mitglieder/Rollen verwalten | Separat delegierte Verwaltungsfähigkeit | Nein | + +## Roles and user management + +Two business roles apply **per tenant**, not globally. A user can have both roles and different permissions in different customer organizations. Login, Configurator membership, STACKIT permissions and GitHub access remain separate evidence. -Die vorgeschlagenen bisherigen Rollen Viewer/Editor/Deployer/Tenant-Admin aus dem Hauptplan werden für dieses Zielbild nicht zusätzlich als vier sichtbare Produktrollen eingeführt. Feinere technische Fähigkeiten (Mitgliederverwaltung, Credential-Delegation, Apply-Freigabe) bleiben explizite Grants. Ein Platform Engineer erhält nicht automatisch alle Verwaltungsrechte. Mitgliederverwaltung wird als tenantgebundene Fähigkeit innerhalb der Platform-Engineer-Rolle delegiert, nicht als dritte fachliche Persona. Rollen-/Einladungsänderungen benötigen erneute serverseitige Prüfung und Audit-Eintrag; niemand darf sich selbst weitergehende Rechte erteilen. +| Capability | Platform Engineer | Application Owner | +|---|---|---| +| Configure platform and request its Plan | Yes, in own tenant | No | +| Create, review, version and publish project templates | Yes | No | +| See published templates approved for them | Yes | Yes | +| Order own application instance and see its Plan | Yes | Yes | +| See/change other users' instances | Only under tenant policy | Only through explicit team sharing | +| Read or download platform credentials | No; authorized use only | No | +| Customer Apply | Additional run approval/policy | Additional run approval/policy | +| Manage tenant members/roles | Separately delegated management capability | No | -Die Umstellung von bisherigen Viewer-/Editor-/Deployer-/Admin-Modellen erfolgt schrittweise nach Inventarisierung der tatsächlich gespeicherten Mitgliedschaften. Es gibt keine pauschale Zuordnung „Editor wird Platform Engineer“ und keine automatische Rechteerweiterung. Neue Rollen werden ausdrücklich durch berechtigte Tenant-Verantwortliche bestätigt; bis dahin bleiben vorhandene Zugriffe unter ihrem bisherigen, höchstens gleichwertigen Umfang. Migrationstests müssen auch kombinierte Rollen, Widerruf und offene Jobs abdecken. +The previously proposed Viewer/Editor/Deployer/Tenant Admin roles from the main plan will not additionally be introduced as four visible product roles for this target design. Finer technical capabilities (member management, credential delegation, Apply approval) remain explicit grants. A Platform Engineer does not automatically receive all management permissions. Member management is delegated as a tenant-bound capability within the Platform Engineer role, not as a third business persona. Role/invitation changes require renewed server-side checking and an audit entry; nobody may grant themselves broader permissions. -PostgreSQL speichert externe Identitätsverknüpfungen, Tenant-Mitgliedschaften, Rollen, Einladungen und Audit-Ereignisse. Keine eigene Passwortverwaltung. Jede API, Queue-Nachricht, Artefaktabfrage und Secret-Nutzung prüft den Tenant und die Objektberechtigung serverseitig. Ein Rollenwechsel im Browser ist kein Sicherheitsmechanismus. +Transition from previous Viewer/Editor/Deployer/Admin models proceeds incrementally after inventorying actually stored memberships. There is no blanket mapping of “Editor becomes Platform Engineer” and no automatic permission expansion. New roles are explicitly confirmed by authorized tenant representatives; until then, existing access remains within its previous, at most equivalent scope. Migration tests must also cover combined roles, revocation and open jobs. -## Identität, STACKIT-Onboarding und Bootstrap +PostgreSQL stores external identity links, tenant memberships, roles, invitations and audit events. No custom password management. Every API, queue message, artifact query and secret use checks tenant and object authorization server-side. A role switch in the browser is not a security mechanism. -**Verifiziert:** STACKIT verwendet rollenbasierte, additive Berechtigungen. Rollen auf Organisationen und Ordnern werden vererbt; eine schwächere Projektrolle hebt diese Rechte nicht auf. Ein Configurator-Login allein gewährt keine STACKIT-API-Berechtigung. [STACKIT Rollenmodell](https://docs.stackit.cloud/platform/access-and-identity/roles-permissions/roles-permissions/) + +## Identity, STACKIT onboarding and bootstrap -**Verifiziert:** Vor einer weiteren Rollenzuweisung muss der Benutzer laut Resource-Manager-Dokumentation bereits eine der genannten Organisationsrollen besitzen. STACKIT empfiehlt dafür `organization.viewer`; diese gewährt minimale Organisationssicht ohne geerbten Zugriff auf Ordner und Projekte. Daher nicht vorsorglich Reader oder Owner auf einen gesamten Anwendungsordner vergeben. Den vollständigen Onboarding- und Portalablauf mit realem Testbenutzer prüfen. [Resource Manager Access Control](https://docs.stackit.cloud/platform/resource-manager/basics/access-control/) +**Verified:** STACKIT uses role-based, additive permissions. Roles on organizations and folders are inherited; a weaker project role does not cancel these permissions. A Configurator login alone grants no STACKIT API permission. [STACKIT role model](https://docs.stackit.cloud/platform/access-and-identity/roles-permissions/roles-permissions/) -**Noch offen:** Ein freigegebener STACKIT-IdP-Client für unsere eigene App einschließlich Discovery, Clientregistrierung, Claims, Logout und API-Delegation. Die öffentliche OIDC-Anleitung beschreibt einen externen IdP, dem STACKIT vertraut; sie belegt keinen beliebig registrierbaren Configurator-Client beim STACKIT-IdP. [STACKIT IdP](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/getting-started/), [OIDC-Federation](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/how-tos/generic-oidc-1_0-federation-guide/) +**Verified:** According to Resource Manager documentation, before another role assignment the user must already possess one of the listed organization roles. STACKIT recommends `organization.viewer` for this; it provides minimal organization visibility without inherited access to folders and projects. Therefore do not preemptively assign Reader or Owner to an entire application folder. Test the complete onboarding and portal workflow with a real test user. [Resource Manager Access Control](https://docs.stackit.cloud/platform/resource-manager/basics/access-control/) -Vorgeschlagener Ablauf: +**Still open:** An approved STACKIT IdP client for our own app, including discovery, client registration, claims, logout and API delegation. The public OIDC guide describes an external IdP trusted by STACKIT; it does not establish that a Configurator client can be freely registered at the STACKIT IdP. [STACKIT IdP](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/getting-started/), [OIDC federation](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/how-tos/generic-oidc-1_0-federation-guide/) -1. Benutzer authentifiziert sich über einen freigegebenen IdP; bis zur Klärung bleibt GitHub als bestehender Login erhalten. -2. STACKIT-Benutzerkonto und konkrete Organisation werden gesondert verifiziert. Keine automatische Verknüpfung allein anhand übereinstimmender E-Mail-Adressen; stabile Issuer-/Subject-Kennung speichern. -3. Ein berechtigter Organisationsadministrator bestätigt Tenant-Zuordnung und erste Platform-Engineer-Mitgliedschaft. Besitz eines Service-Account-Schlüssels beweist keine persönliche Organisationsmitgliedschaft. -4. Fehlende Organisationsmitgliedschaft des Application Owners wird als expliziter Onboarding-Schritt behandelt. Er erhält nur die für das Onboarding nötige Rolle und später die freigegebene Projektrolle. -5. Für Bootstrap werden temporär autorisierte Berechtigungen benötigt, um Projekt, initialen Service Account und Backend anzulegen. Eine Anmeldung allein erzeugt diese Rechte nicht. Unterstützte Benutzer-API-Delegation erst nachweisen; andernfalls bleibt ein dokumentierter einmaliger Administrator-/Service-Account-Bootstrap nötig. -6. Nach Bootstrap temporäre Berechtigungen entfernen und Plattform-/Anwendungs-Provisionierung mit getrennten, eingeschränkten Ausführungsidentitäten betreiben. +Proposed workflow: -Die konkrete Permission-Matrix für Projektanlage, Rollenzuweisung, Netzwerkzuordnung und Dienstanlage ist per API/Provider-Spike nachzuweisen. Keine pauschale Zusage, dass `organization.viewer` für Provisionierung reicht: Diese Rolle betrifft die Benutzeraufnahme, nicht die Provisionierungsidentität. +1. User authenticates through an approved IdP; GitHub remains the existing login until clarification. +2. STACKIT user account and specific organization are verified separately. No automatic linking solely through matching email addresses; store stable issuer/subject identifier. +3. An authorized organization administrator confirms tenant assignment and first Platform Engineer membership. Possessing a service-account key does not demonstrate personal organization membership. +4. Missing organization membership of the Application Owner is treated as an explicit onboarding step. They receive only the role needed for onboarding and later the approved project role. +5. Bootstrap needs temporarily authorized permissions to create project, initial service account and backend. Login alone does not create these permissions. First demonstrate supported user API delegation; otherwise a documented one-time administrator/service-account bootstrap remains necessary. +6. After bootstrap, remove temporary permissions and operate platform/application provisioning with separate, restricted execution identities. -## Projekt-Templates und Instanzen +The specific permission matrix for project creation, role assignment, network assignment and service creation must be demonstrated through an API/provider spike. No blanket promise that `organization.viewer` suffices for provisioning: this role concerns user admission, not the provisioning identity. -Konkretisierung: [Template-Eingaben, feste Vorgaben und Ressourcenverknüpfungen](template-parameters-and-bindings.md). Der Entwurfseditor unterstützt fünf freigegebene Parameterfelder und eine lokale Bestellvorschau. Veröffentlichung und produktive Application-Instanziierung bleiben offen. + +## Project templates and instances +Details: [template inputs, fixed settings and resource bindings](template-parameters-and-bindings.md). The draft editor supports five approved parameter fields and a local order preview. Publication and production Application instantiation remain outstanding. -**Entschieden:** Veröffentlichte Template-Versionen bleiben unveränderlich. Bestehende Instanzen erhalten neue Versionen nur durch ein ausdrücklich angefordertes Upgrade mit eigenem Plan. +**Decided:** Published template versions remain immutable. Existing instances receive new versions only through an explicitly requested upgrade with its own Plan. -Ein veröffentlichtes `ApplicationTemplateVersion` enthält: +A published `ApplicationTemplateVersion` contains: -- Tenant, stabile Template-ID, Version, Status (`draft`, `published`, `retired`), Autor und Freigabe. -- Gepinnte Accelerator-Version, Compiler-/Schemasversion und Kompatibilität zum Plattformvertrag. -- Anwendungsprofil, etwa VM-Projekt, eigenes Kubernetes-Projekt oder Namespace auf einem zentralen Kubernetes-Cluster. Diese drei Varianten sind fachlich verschieden; ein Namespace ist kein eigenständiger Cluster. -- Feste Vorgaben: erlaubte Zielordner, Regionen und SNAs, Public-/Corporate-Typ, verpflichtende Dienste, Rollen, Namensregeln und Quoten. -- Explizit freigegebene Eingaben mit Typ, Auswahlwerten, Erklärung und Default, beispielsweise Name, Umgebung und zulässige Größenklasse. -- Deklarative Dienstkonfiguration, etwa STACKIT Secrets Manager und STACKIT Observability, sowie sichere Credential-Referenzen. Keine Secretwerte oder beliebigen Terraform-Skripte. -- Dokumentierte Ergebnisse, Voraussetzungen, technische Grenzen und Zuständigkeit für Betrieb/Löschung. +- Tenant, stable template ID, version, status (`draft`, `published`, `retired`), author and approval. +- Pinned Accelerator version, compiler/schema version and compatibility with the platform contract. +- Application profile, such as VM project, dedicated Kubernetes project or namespace on a central Kubernetes cluster. These three variants are distinct business concepts; a namespace is not an independent cluster. +- Fixed settings: permitted target folders, regions and SNAs, Public/Corporate type, mandatory services, roles, naming rules and quotas. +- Explicitly exposed inputs with type, selection values, explanation and default, e.g. name, environment and permitted size class. +- Declarative service configuration, such as STACKIT Secrets Manager and STACKIT Observability, and secure credential references. No secret values or arbitrary Terraform scripts. +- Documented results, prerequisites, technical limitations and responsibility for operation/deletion. -Eine `ApplicationInstance` bindet eine konkrete Template-Version, zulässige Benutzereingaben, verifizierten Antragsteller/Projektverantwortlichen, Plattformvertragsversion, State-Identität und Ausführungsrevision. Templates werden kopiert/instanziiert, spätere Änderungen aktualisieren bestehende Instanzen nicht automatisch. Updates sind eigene Pläne mit sichtbarem Diff und Freigabe. +An `ApplicationInstance` binds a specific template version, permitted user inputs, verified requester/project owner, platform contract version, state identity and execution revision. Templates are copied/instantiated; later changes do not automatically update existing instances. Updates are separate Plans with a visible diff and approval. -Der Server setzt Organisation, Ordner, zulässige Region/SNA und Verantwortlichen aus verifizierten Bindungen. Er übernimmt diese Werte nicht ungeprüft aus Formular, Chat oder API. Der STACKIT-Projektverantwortliche muss ein geeignetes menschliches Konto sein; die Produktrolle Application Owner bedeutet nicht automatisch unbegrenzte STACKIT-IAM-Owner-Rechte. Welche konkrete Projektrolle/Owner-Zuweisung fachlich nötig ist, wird je Template festgelegt und mit der API getestet. +The server sets organization, folder, permitted region/SNA and owner from verified bindings. It does not adopt these values unchecked from form, chat or API. The STACKIT project owner must be a suitable human account; the Application Owner product role does not automatically mean unlimited STACKIT IAM owner permissions. The specific project role/owner assignment required for business purposes is defined per template and tested with the API. -**Wichtige offene Grenze:** Das bestehende Anwendungsprojektmodul ist kein vollständiger VM-/Kubernetes-Workload-Katalog. Vor Benennung eines Templates als „VM“ oder „Kubernetes“ muss klar sein, ob nur Projekt und Basisdienste oder tatsächlich VMs/Cluster/Namespaces erstellt werden. Nicht vorhandene Accelerator-Funktionen sind eigene Erweiterungen. +**Important open boundary:** The existing application-project module is not a complete VM/Kubernetes workload catalogue. Before naming a template “VM” or “Kubernetes”, it must be clear whether only project and basic services, or actual VMs/clusters/namespaces, are created. Missing Accelerator capabilities are separate extensions. -## Accelerator-Vertrag, State und Ausführung + +## Accelerator contract, state and execution -Vorgeschlagene neue Roots (konkrete Pfade noch zu entscheiden): `platform` für zentrale Ressourcen und `application` für genau eine Anwendungsinstanz. Bestehendes `src` bleibt während der Migration kompatibel. Wiederverwendbare Module werden geteilt; kein Kopieren kompletter Plattformkonfigurationen pro Bestellung. +Proposed new roots (specific paths still to be decided): `platform` for central resources and `application` for exactly one application instance. Existing `src` remains compatible during migration. Reusable modules are shared; no copying of complete platform configurations for every order. -Die Plattform veröffentlicht einen **nicht sensitiven, versionierten Vertrag**: Organisations-ID, freigegebene Ordner-IDs, Regionen, SNA-/Netzwerkreferenzen, erlaubte zentrale Cluster-/Dienstreferenzen, Fähigkeiten und Policy-Version. Anwendungen konsumieren nur diesen Vertrag, nicht den vollständigen Plattform-State. Server und Runner prüfen Freigabe, Aktualität und Zielorganisation vor jedem Plan und Apply. Es gibt keinen direkten `terraform_remote_state`-Zugriff der Anwendungsinstanzen auf den Plattform-State und keine Weitergabe seiner Backend-Credentials. +The platform publishes a **non-sensitive, versioned contract**: organization ID, approved folder IDs, regions, SNA/network references, permitted central cluster/service references, capabilities and policy version. Applications consume only this contract, not the full platform state. Server and Runner check approval, currency and target organization before every Plan and Apply. Application instances have no direct `terraform_remote_state` access to platform state and do not receive its backend credentials. ```mermaid flowchart LR @@ -104,187 +112,134 @@ flowchart LR APP --> AS[Eigener Anwendungs-State] ``` -Getrennte Backend-Keys und Berechtigungen für Bootstrap, Plattform und jede Anwendungsinstanz; Tenant-Trennung bleibt erforderlich. Der vorhandene Accelerator-Bootstrap bleibt Grundlage der Backend-Bereitstellung. Keine Umstellung auf einen neuen zentralen Kunden-State ohne gesonderte Entscheidung. State-Locks und Queue-Locks pro Instanz verhindern konkurrierende Mutationen; geteilte Quoten/Netzwerkänderungen brauchen zusätzliche tenantweite Koordination. +Separate backend keys and permissions for bootstrap, platform and every application instance; tenant separation remains required. Existing Accelerator bootstrap remains the basis of backend provisioning. No switch to new centralized customer state without a separate decision. State locks and queue locks per instance prevent concurrent mutations; shared quotas/network changes need additional tenant-wide coordination. + +A central platform resource has exactly one state owner. Application states may reference it but not manage it again. Removing an SNA/cluster is blocked while application instances depend on it. Running executions must be considered before contract changes. + +Application jobs receive a restricted, tenant-bound execution identity and exclusively approved resource references. Template instantiation is not a way to delegate the organization-wide bootstrap service account. Retry/idempotency through instance ID and order key, no second project on another click. Quotas are reserved atomically and reconciled after errors. + +Clicking “Deploy” initially starts validation and Plan. Automatic Apply is a later explicit product/tenant policy; the current personal approval requirement for customer Apply applies unchanged. **Confirmed decision:** The Platform Engineer can allow both direct deployment and an approval workflow per template. This policy is checked server-side before Plan and Apply; a change does not prematurely lift today's customer Apply approval requirement. The safe initial value for new templates (approval required) is an implementation proposal. + + +## GitHub and the Application Owner experience + +The Application Owner should not need to select a fork merely to order an approved template. Through their user-bound GitHub connection, the Platform Engineer can publish a signed/hashed, immutable snapshot to the tenant catalogue. Reading this published snapshot is not repository access under another person's credentials. + +How instances are archived in Git remains open: the Application Owner's personal GitHub connection or export/review explicitly performed by the Platform Engineer. Until decided, PostgreSQL plus immutable configuration artifacts are proposed instance evidence. No silent switch to centralized GitHub tokens and no background writes under another user's token. The original requirement for user-bound repository access remains. + + +## UI impact + +Platform Engineer: platform, project templates, publications, application overview and separately authorized tenant management. Application Owner: approved project templates, own/assigned applications, status, Plans and access. Current tenant and current role are always visible. + +The current component view remains the basis of the platform editor. The later template editor uses the same business components but adds “fix value”, “let Application Owner choose” and “unavailable”. An unknown field is not automatically an exposed variable. Chat uses the same authorization and template schemas as the form. + + +## Migration without resource loss + +- Existing combined configurations, hashes and state addresses remain readable unchanged. +- Initially support new platform-only configurations and new application instances. +- Inventory existing projects and their jointly managed resources; define a unique future state owner. +- Develop a separate, tested migration run with backup, locks, import/state-move plan, abort and rollback strategy. Cross-state migration is not an ordinary UI save. +- Before and after every migration, demonstrate that no unexpected creation or deletion is planned. No automatic migration through login, template selection or opening a document. +- Known limitations #22 (folder destroy), #37 (private Kubernetes), #65 (firewall), #80 (regional namespace wiring) also apply to the new roots. + + +## Discussion decisions and implementation + +Recommendations for the next joint decision: + +1. Two roles per tenant; both possible simultaneously. Delegate membership management separately. +2. Application Owner initially needs an already verified STACKIT account; guided organization admission, no implicit account creation. +3. First a template “Application project with basic services”, then dedicated clusters/VMs and central namespace offerings, each after demonstrated Accelerator support. +4. Template publication as immutable tenant catalogue snapshot; decide Git storage of instances separately. +5. First implement platform and application Plan separately, then controlled Apply; legacy migration last. + + +### Phase A – contracts and IAM evidence + +- [x] Document target design, role separation and open assumptions. +- [x] Immutable published template versions and explicit upgrades confirmed by user. +- [x] Future Apply policy configurable by Platform Engineer per template: direct or requiring approval. +- [ ] Decide owner/team, Git storage and approval path. +- [ ] Clarify STACKIT IdP client and delegated user API permissions with STACKIT. +- [ ] Demonstrate organization admission and minimal permissions with a dedicated test user. +- [ ] Create inventory of existing platform/application resources and capability matrix. +- [ ] Review platform contract, template schema and separate state ownership. + + +### Phase B – Accelerator and Plan-only support + +- [ ] Implement new roots/modules and versioned platform contract. +- [ ] Implement template compiler with permitted inputs and fixed policies. +- [ ] Connect isolated application states and restricted Runner credentials. +- [ ] Native OpenTofu contract tests and negative Plan tests for foreign folders/SNAs/organizations. +- [ ] Develop separate concept for legacy migration; do not execute yet. + + +### Phase C – Configurator self-service + +- [ ] Implement tenant roles, invitations, identity linking and audit log. +- [ ] Implement template draft, publication, catalogue and retirement. +- [ ] Implement role-dependent views, order form and own instances. +- [ ] API/RLS/job negative tests against cross-tenant access and role escalation. +- [ ] Test idempotency, quotas, error recovery and template updates. +- [ ] Customer Apply only after specific approval; securely implement the confirmed later self-service Apply policy. + + +## First technical prototype (2026-10-01, not yet connected to API/Runner) + +- `src/application` is a separate root for exactly one new application instance, referencing approved platform resources and having its own S3 backend key. +- `app/packages/domain/src/application-plan.ts` contains a pure compiler for published templates, verified server context and strictly limited order inputs. Tenant, organization, revision and target binding are checked. +- The compiler takes owner from server context and services from the template. It replaces neither server-side membership checking nor actual STACKIT identity verification, publication/persistence or job authorization. +- Four native mock Plan tests check Public/Corporate and tenant/revision boundaries; four compiler tests check isolated state keys, bindings and input injection. +- Execution remains explicitly disabled; `direct` is only stored future policy. This has not yet enabled any API endpoint, role switching or customer Plan. + +Besides selectable services, the shared module also creates an automation service account with key and Object Storage buckets/credentials. This scope must be visible when publishing the base template and in the Plan. For its first run, the application instance uses the existing bootstrap backend, not its own bucket created only later. + + +## Implementation step: independent user identity (2026-10-01) + +Additive migration `006_external_identities.sql` separates external login identities from the internal user UUID. Existing GitHub mappings are adopted; user, tenant, configuration and secret addresses remain unchanged. GitHub login now resolves users through provider, issuer and immutable GitHub ID. Previous GitHub columns are temporarily retained for existing session and repository interfaces and are now optional. There is no OIDC login or public account-linking API yet. Identity links have no direct runtime table permissions. + +STACKIT IDP remains the preferred primary login. The user has submitted the ticket for registering a custom OIDC client; the response is pending. The public [federation guide](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/how-tos/generic-oidc-1_0-federation-guide/) describes STACKIT as relying party and does not confirm this registration path. Alternatively, an approved enterprise OIDC provider will be connected; an identity broker is planned only if needed. GitHub remains the transitional login until the switch and later a personal connection. No account merging solely on matching email addresses. + + +### Next implementation steps + +- [x] Store external identities separately and preserve existing UUIDs. +- [x] PostgreSQL tests: legacy migration, GitHub rename, prohibited runtime access, issuer-bound subjects and users without GitHub. +- [ ] Verified OIDC login after client registration; approve provider server-side, check identity by issuer and subject. +- [ ] Secure linking of existing users with renewed proof of both accounts. +- [ ] Distinguish organization tenants from previous personal workspaces; initially exactly one verified STACKIT organization per organization tenant. +- [ ] Implement memberships with Platform Engineer / Application Owner and separate member-management capability, revocation and audit. +- [ ] Implement tenant switching with independent personal GitHub token binding. +- [ ] Migrate existing API permissions to new roles before Application Owners receive access. +- [ ] Provide “Organization & members” UI and Application catalogue. + +This step activates no new roles, grants no STACKIT permissions and changes neither customer Apply approval nor existing tenant boundaries. -Eine zentrale Plattformressource hat genau einen State-Eigentümer. Anwendungs-States dürfen sie referenzieren, aber nicht erneut verwalten. Entfernen einer SNA/eines Clusters wird blockiert, solange Anwendungsinstanzen davon abhängen. Laufende Ausführungen müssen vor Vertragsänderungen berücksichtigt werden. + +## Organization & members: first management status -Anwendungsjobs bekommen eine eingeschränkte, tenantgebundene Ausführungsidentität und ausschließlich freigegebene Ressourcenreferenzen. Die Template-Instanziierung ist kein Weg, den organisationsweiten Bootstrap-Service-Account zu delegieren. Retry/Idempotenz über Instanz-ID und Bestellschlüssel, kein zweites Projekt bei erneutem Klick. Quoten werden atomar reserviert und nach Fehlern abgeglichen. +Organization tenants can now be created separately from the personal workspace. Their STACKIT organization ID is explicitly **unverified**. A user can own or belong to multiple workspaces; the UI offers an explicit switch with full reload. Personal GitHub token binding remains bound to the original user/session path during switching. -Ein Klick auf „Bereitstellen“ startet zunächst Validierung und Plan. Automatischer Apply ist eine spätere explizite Produkt-/Tenant-Policy; die derzeitige persönliche Freigabepflicht für Kunden-Apply gilt unverändert. **Bestätigte Entscheidung:** Der Platform Engineer kann je Template sowohl direkte Bereitstellung als auch einen Genehmigungsablauf erlauben. Diese Policy wird serverseitig vor Plan und Apply geprüft; eine Änderung hebt die heutige Kunden-Apply-Freigabepflicht nicht vorzeitig auf. Der sichere Initialwert für neue Templates (Genehmigung erforderlich) ist ein Umsetzungsvorschlag. +Member management initially uses the internal UUID of an already registered user. There is no global user catalogue or automatic account merging through email. Platform Engineer and Application Owner can be combined. Member management is a separate capability for Platform Engineers. Changes are audited; the last manager must not be lost even under concurrent changes. Existing personal memberships are not promoted to new roles. -## GitHub und Application-Owner-Erlebnis +**Execution boundary of this status:** Organization tenants are management drafts. Credentials, product catalogue queries and old Plan/deployment endpoints are blocked there server-side. Application Owners also receive no access to previous platform/Git endpoints. The personal workspace remains available for previous configuration and authorized Plan use. The new view does not yet activate an Application catalogue or customer Apply. -Der Application Owner sollte keinen Fork auswählen müssen, nur um ein freigegebenes Template zu bestellen. Veröffentlichung kann durch den Platform Engineer aus seiner benutzergebundenen GitHub-Verbindung einen signierten/gehashten, unveränderlichen Snapshot in den Tenant-Katalog übernehmen. Lesen dieses veröffentlichten Snapshots ist kein Repositoryzugriff unter fremden Credentials. +- [x] Draft organization tenants and explicit tenant switching. +- [x] Role memberships and separate member management with audit. +- [x] “Organization & members” UI and server-side separation of old APIs. +- [ ] Verify STACKIT organization binding and acting user identity. +- [ ] Only then enable tenant-bound credentials and organization-wide execution. +- [ ] Invitations, STACKIT member reconciliation and immutable Application templates. -Offen bleibt, wie Instanzen im Git archiviert werden: persönliche GitHub-Verbindung des Application Owners oder vom Platform Engineer ausdrücklich ausgeführter Export/Review. Bis zur Entscheidung PostgreSQL plus unveränderliche Konfigurationsartefakte als vorgeschlagener Instanznachweis. Kein stiller Wechsel auf zentrale GitHub-Tokens und keine Hintergrundschreibzugriffe unter dem Token eines anderen Benutzers. Die ursprüngliche Vorgabe benutzergebundener Repositoryzugriffe bleibt erhalten. + +## Member invitations replace manual user identifiers -## UI-Auswirkungen +New memberships arise through explicit acceptance of an invitation link. The manager chooses roles and, if applicable, member management. The link is valid for seven days, usable once and revocable until acceptance. It is displayed in full only at creation; PostgreSQL stores exclusively its SHA-256 hash. The random token has 256 bits of entropy. No email is sent. The link is a transferable authorization and must be deliberately passed to the intended person; it is not bound to an email address. -Platform Engineer: Plattform, Projekt-Templates, Veröffentlichungen, Anwendungsübersicht und getrennt berechtigte Tenant-Verwaltung. Application Owner: freigegebene Projekt-Templates, eigene/zugewiesene Anwendungen, Status, Pläne und Zugänge. Aktueller Tenant und aktuelle Rolle sind stets sichtbar. +The person signs in through the available login; their internal user is created automatically at first GitHub login. They see workspace and roles and confirm joining. The token is transported in the URL fragment, immediately removed from the visible URL and held only in the current tab's session storage across login. Preview and acceptance require login; acceptance additionally requires Origin/CSRF checking. Tokens do not appear in URL paths, query strings, audit events or the invitation list. After acceptance/closing, the local token is removed. An interrupted workflow can be reopened with the link. -Die aktuelle Komponentenansicht bleibt Grundlage des Plattformeditors. Der spätere Template-Editor nutzt dieselben Fachkomponenten, ergänzt jedoch „fest vorgeben“, „Application Owner auswählen lassen“ und „nicht verfügbar“. Ein unbekanntes Feld ist nicht automatisch eine freigegebene Variable. Der Chat verwendet dieselben Autorisierungs- und Templateschemas wie das Formular. - -## Migration ohne Ressourcenverlust - -- Bestehende Gesamtkonfigurationen, Hashes und State-Adressen bleiben unverändert lesbar. -- Zunächst neue reine Plattformen und neue Anwendungsinstanzen unterstützen. -- Bestehende Projekte und ihre gemeinsam verwalteten Ressourcen inventarisieren; eindeutigen zukünftigen State-Eigentümer festlegen. -- Separaten, getesteten Migrationslauf mit Backup, Locks, Import-/State-Move-Plan, Abbruch- und Rückkehrstrategie entwickeln. Cross-State-Migration ist kein gewöhnlicher UI-Speichervorgang. -- Vor und nach jeder Migration nachweisen, dass weder unerwartete Neuanlage noch Löschung geplant wird. Keine automatische Migration durch Login, Template-Auswahl oder Öffnen eines Dokuments. -- Bekannte Grenzen #22 (Folder-Destroy), #37 (privates Kubernetes), #65 (Firewall), #80 (regionale Namespace-Verkabelung) gelten auch für die neuen Roots. - -## Diskussionsentscheidungen und Umsetzung - -Empfehlungen für die nächste gemeinsame Entscheidung: - -1. Zwei Rollen pro Tenant; beide gleichzeitig möglich. Mitgliedschaftsverwaltung separat delegieren. -2. Application Owner benötigt zunächst ein bereits verifiziertes STACKIT-Konto; geführte Organisationsaufnahme, keine implizite Kontoerstellung. -3. Zuerst ein Template „Anwendungsprojekt mit Basisdiensten“, danach eigene Cluster/VMs und zentrale Namespace-Angebote jeweils nach nachgewiesenem Accelerator-Support. -4. Template-Veröffentlichung als unveränderlicher Tenant-Katalog-Snapshot; Git-Ablage der Instanzen gesondert entscheiden. -5. Erst Plattform- und Anwendungs-Plan getrennt implementieren, dann kontrollierter Apply; Bestandsmigration zuletzt. - -### Phase A – Verträge und IAM-Nachweis - -- [x] Zielbild, Rollentrennung und offene Annahmen dokumentieren. -- [x] Unveränderliche veröffentlichte Template-Versionen und explizite Upgrades vom Benutzer bestätigt. -- [x] Zukünftige Apply-Policy durch Platform Engineer je Template einstellbar: direkt oder genehmigungspflichtig. -- [ ] Entscheidungen zu Verantwortlichem/Team, Git-Ablage und Freigabeweg treffen. -- [ ] STACKIT-IdP-Client und delegierte Benutzer-API-Berechtigungen mit STACKIT klären. -- [ ] Organisationsaufnahme und minimale Rechte mit eigenem Testbenutzer nachweisen. -- [ ] Inventar bestehender Plattform-/Anwendungsressourcen und Capability-Matrix erstellen. -- [ ] Plattformvertrag, Template-Schema und getrennte State-Eigentümerschaft reviewen. - -### Phase B – Accelerator und reine Plan-Unterstützung - -- [ ] Neue Roots/Module und versionierten Plattformvertrag implementieren. -- [ ] Template-Compiler mit erlaubten Eingaben und festen Policies implementieren. -- [ ] Isolierte Anwendungs-States und eingeschränkte Runner-Credentials anbinden. -- [ ] Native OpenTofu-Vertragstests und Plan-Negativtests für fremde Ordner/SNAs/Organisationen. -- [ ] Separates Konzept für Bestandsmigration ausarbeiten; noch nicht ausführen. - -### Phase C – Configurator Self-Service - -- [ ] Tenant-Rollen, Einladungen, Identitätsverknüpfung und Audit-Log implementieren. -- [ ] Template-Entwurf, Veröffentlichung, Katalog und Stilllegung implementieren. -- [ ] Rollenabhängige Ansichten, Bestellformular und eigene Instanzen implementieren. -- [ ] API-/RLS-/Job-Negativtests gegen tenantfremde Zugriffe und Rolleneskalation. -- [ ] Idempotenz, Quoten, Fehlerwiederaufnahme und Template-Updates testen. -- [ ] Kunden-Apply erst nach konkreter Freigabe; bestätigte spätere Self-Service-Apply-Policy sicher implementieren. - -## Erster technischer Prototyp (2026-10-01, noch nicht an API/Runner angebunden) - -- `src/application` ist ein separater Root für genau eine neue Anwendungsinstanz, - mit Verweis auf freigegebene Plattformressourcen und eigenem S3-Backend-Key. -- `app/packages/domain/src/application-plan.ts` enthält einen reinen Compiler für - veröffentlichte Templates, verifizierten Serverkontext und streng begrenzte - Bestelleingaben. Tenant-, Organisations-, Revisions- und Zielbindung werden geprüft. -- Der Compiler übernimmt den Owner aus dem Serverkontext und Dienste aus dem - Template. Er ersetzt weder serverseitige Mitgliedschaftsprüfung noch tatsächliche - STACKIT-Identitätsprüfung, Veröffentlichung/Persistierung oder Job-Autorisierung. -- Vier native Mock-Plan-Tests prüfen Public/Corporate sowie Tenant-/Revisionsgrenzen; - vier Compiler-Tests prüfen isolierte State-Schlüssel, Bindungen und Eingabe-Injektion. -- Ausführung bleibt ausdrücklich deaktiviert; `direct` ist nur gespeicherte - zukünftige Policy. Kein API-Endpunkt, keine Rollenumschaltung und kein Kunden-Plan - wurden damit bereits freigeschaltet. - -Das geteilte Modul erzeugt außer den auswählbaren Diensten auch einen Automations- -Service-Account samt Schlüssel und Object-Storage-Buckets/Credentials. Dieser Umfang -muss beim Veröffentlichen des Basis-Templates und im Plan sichtbar sein. Die -Anwendungsinstanz verwendet für ihren ersten Lauf das vorhandene Bootstrap-Backend, -nicht ihren erst später erzeugten eigenen Bucket. - -## Umsetzungsschritt: unabhängige Benutzeridentität (2026-10-01) - -Die additive Migration `006_external_identities.sql` trennt externe Anmeldeidentitäten -von der internen Benutzer-UUID. Bestehende GitHub-Zuordnungen werden übernommen; -Benutzer-, Tenant-, Konfigurations- und Secret-Adressen bleiben unverändert. -GitHub-Anmeldung löst Benutzer jetzt über Provider, Issuer und unveränderliche -GitHub-ID auf. Die bisherigen GitHub-Spalten bleiben für bestehende Session- -und Repository-Schnittstellen vorübergehend erhalten und sind nun optional. -Es existiert noch kein OIDC-Login und keine öffentliche Account-Linking-API. -Identitätsverknüpfungen haben keine direkten Runtime-Tabellenrechte. - -STACKIT IDP bleibt der bevorzugte Hauptlogin. Das Ticket zur Registrierung eines -eigenen OIDC-Clients wurde vom Benutzer gestellt; die Antwort steht aus. -Die öffentliche [Federationsanleitung](https://docs.stackit.cloud/platform/access-and-identity/stackit-idp/how-tos/generic-oidc-1_0-federation-guide/) -beschreibt STACKIT als Relying Party und bestätigt diesen Registrierungsweg nicht. -Alternativ wird ein freigegebener Unternehmens-OIDC-Anbieter angebunden; ein -Identity Broker ist erst bei entsprechendem Bedarf vorgesehen. GitHub bleibt -bis zur Umstellung der Übergangslogin und später eine persönliche Verbindung. -Kein Zusammenführen von Konten allein anhand gleicher E-Mail-Adressen. - -### Nächste Implementierungsschritte - -- [x] Externe Identitäten separat speichern und bestehende UUIDs erhalten. -- [x] PostgreSQL-Tests: Bestandsmigration, GitHub-Umbenennung, Runtime-Zugriffsverbot, - issuergebundene Subjects und Benutzer ohne GitHub. -- [ ] Verifizierte OIDC-Anmeldung nach Client-Registrierung; Anbieter serverseitig - freigeben, Identität anhand von Issuer und Subject prüfen. -- [ ] Sichere Verknüpfung bestehender Benutzer mit erneutem Nachweis beider Konten. -- [ ] Organisationstenants von bisherigen persönlichen Arbeitsbereichen unterscheiden; - zunächst genau eine verifizierte STACKIT-Organisation je Organisationstenant. -- [ ] Mitgliedschaften mit Platform Engineer / Application Owner und separater - Mitgliederverwaltungsfähigkeit, Widerruf und Audit implementieren. -- [ ] Tenant-Wechsel mit unabhängiger persönlicher GitHub-Token-Bindung implementieren. -- [ ] Bestehende API-Rechte auf neue Rollen umstellen, bevor Application Owner Zugang erhalten. -- [ ] Oberfläche „Organisation & Mitglieder“ und Application-Katalog bereitstellen. - -Dieser Schritt aktiviert keine neuen Rollen, erteilt keine STACKIT-Rechte und -ändert weder die Kunden-Apply-Freigabe noch die bestehenden Tenant-Grenzen. - -## Organisation & Mitglieder: erster Verwaltungsstand - -Organisationstenants können jetzt getrennt vom persönlichen Arbeitsbereich angelegt -werden. Ihre STACKIT-Organisations-ID ist ausdrücklich **unverifiziert**. Ein Benutzer -kann mehrere Arbeitsbereiche besitzen bzw. ihnen angehören; die Oberfläche bietet -einen expliziten Wechsel mit vollständigem Neuladen. Die persönliche GitHub-Token- -Bindung bleibt beim Wechsel auf den ursprünglichen Benutzer-/Session-Pfad gebunden. - -Die Mitgliederverwaltung verwendet zunächst die interne UUID eines bereits -registrierten Benutzers. Es gibt keinen globalen Benutzerkatalog und keine automatische -Kontozusammenführung über E-Mail. Platform Engineer und Application Owner sind -kombinierbar. Mitgliederverwaltung ist eine gesonderte Fähigkeit für Platform Engineers. -Änderungen werden auditiert; der letzte Verwalter darf auch bei konkurrierenden -Änderungen nicht verloren gehen. Bestehende persönliche Mitgliedschaften werden -nicht auf die neuen Rollen hochgestuft. - -**Ausführungsgrenze dieses Stands:** Organisationstenants sind Verwaltungsentwürfe. -Credentials, Produktkatalog-Abfragen und die alten Plan-/Deployment-Endpunkte sind -dort serverseitig gesperrt. Application Owner erhalten auch keinen Zugriff auf die -bisherigen Plattform-/Git-Endpunkte. Der persönliche Arbeitsbereich bleibt für die -bisherige Konfiguration und autorisierte Plan-Nutzung verfügbar. Die neue Ansicht -aktiviert noch keinen Application-Katalog und keine Kunden-Apply-Funktion. - -- [x] Entwurfs-Organisationstenants und expliziter Tenant-Wechsel. -- [x] Rollenmitgliedschaften und separate Mitgliederverwaltung mit Audit. -- [x] Oberfläche „Organisation & Mitglieder“ und serverseitige Abgrenzung der alten APIs. -- [ ] STACKIT-Organisationsbindung und handelnde Benutzeridentität verifizieren. -- [ ] Erst danach tenantgebundene Credentials und organisationsweite Ausführung freigeben. -- [ ] Einladungen, STACKIT-Mitgliederabgleich und unveränderliche Application Templates. - -## Mitgliedseinladungen ersetzen manuelle Benutzerkennungen - -Neue Mitgliedschaften entstehen durch ausdrückliche Annahme eines Einladungslinks. -Der Verwalter wählt Rollen und gegebenenfalls Mitgliederverwaltung. Der Link ist -sieben Tage gültig, einmal verwendbar und bis zur Annahme widerrufbar. Er wird nur -bei Erstellung vollständig angezeigt; PostgreSQL speichert ausschließlich seinen -SHA-256-Hash. Der zufällige Token besitzt 256 Bit Entropie. Es wird keine E-Mail -verschickt. Der Link ist eine übertragbare Berechtigung und muss gezielt an die -gewünschte Person weitergegeben werden; er ist nicht an eine E-Mail-Adresse gebunden. - -Die Person meldet sich über den verfügbaren Login an; beim ersten GitHub-Login -entsteht automatisch ihr interner Benutzer. Sie sieht Arbeitsbereich und Rollen -und bestätigt den Beitritt. Der Token wird im URL-Fragment transportiert, sofort -von der sichtbaren URL entfernt und nur im aktuellen Tab über den Login hinweg -in Session Storage gehalten. Vorschau und Annahme erfordern Anmeldung, Annahme -zusätzlich Origin-/CSRF-Prüfung. Tokens erscheinen nicht in URL-Pfaden, Querystrings, -Audit-Ereignissen oder der Einladungsliste. Nach Annahme/Schließen wird der lokale -Token entfernt. Ein unterbrochener Ablauf lässt sich mit dem Link erneut öffnen. - -Der Server serialisiert Annahme, Widerruf und Mitgliedsverwaltung am Tenant. -Abgelaufene/verwendete/widerrufene Einladungen, archivierte Arbeitsbereiche und -Einladende ohne aktuelle Verwaltungsberechtigung werden abgewiesen. Bestehende -Mitglieder erhalten über eine Einladung keine zusätzlichen Rollen. Der alte -Mitglieds-Endpunkt darf nur noch existierende Mitgliedschaften bearbeiten. -Die UI benötigt keine internen Benutzerkennungen mehr. Einladungen verwalten und -annehmen erteilt keine STACKIT-IAM-Rechte und aktiviert kein Kunden-Apply. +The server serializes acceptance, revocation and member management on the tenant. Expired/used/revoked invitations, archived workspaces and inviters without current management permission are rejected. Existing members receive no additional roles through an invitation. The old membership endpoint may only edit existing memberships. The UI no longer needs internal user identifiers. Managing and accepting invitations grants no STACKIT IAM permissions and activates no customer Apply. diff --git a/landing-zone-configurator/docs/platform-check.de.md b/landing-zone-configurator/docs/platform-check.de.md new file mode 100644 index 0000000..c6466b7 --- /dev/null +++ b/landing-zone-configurator/docs/platform-check.de.md @@ -0,0 +1,92 @@ + + +# Lesende Plattformprüfung + +[English](platform-check.md) | [Deutsch](platform-check.de.md) + +Stand: 2026-09-29. Ziel: Betreiberprojekt aus der lokalen `landing-zone-configurator.env`, Authentisierung mit der zugehörigen Service-Account-Datei. IDs, Schlüssel und Tokens werden hier bewusst nicht wiederholt. + + + +## Ergebnis + +| Prüfung | Beobachtung | Aussage / Grenze | +| --- | --- | --- | +| Service-Account-Authentisierung | Kurzlebiger Token erfolgreich bezogen | Kein persistenter CLI-Login geändert | +| Projekt lesen | Erfolgreich; zurückgegebene Projekt-ID stimmt mit Eingabe überein | Projekt-Lesezugriff nachgewiesen; keine Prüfung von Schreibrechten oder Organisationszuordnung | +| CF-Organisationen | HTTP 200; 0 Einträge | Im abgefragten Projekt/Region keine Organisation sichtbar | +| CF-Plattformangebote | HTTP 200; 2 Einträge | Angebote erreichbar; konkrete Foundation/Quota noch auswählen | +| PostgreSQL-Flex-Instanzen | HTTP 200; 0 Einträge | Keine Instanz sichtbar | +| PostgreSQL-Flavors | HTTP 200; 10 Einträge | Angebot lesbar; HA, Größe, Backup und Kosten noch entscheiden | +| Secrets-Manager-Instanzen | HTTP 200; 0 Einträge | Keine Instanz sichtbar; konkrete Policies/Isolation noch nicht prüfbar | +| Model-Serving-Katalog | HTTP 200; 10 Modelle | Allgemeiner Katalog lesbar; kein Nachweis projektbezogener Aktivierung, Inferenzrechte oder gebuchter Kapazität | +| Object-Storage-Service-Status | HTTP 404 | Nach Abgleich mit der offiziellen CLI: Dienst im Projekt/Region noch nicht aktiviert; der erste IaC-Bucket aktiviert ihn | + +Die erste Abfrage verwendete `eu01` als Probe-Region. Anschließend wurden **lzc-dev/eu01** als erste Entwicklungsumgebung bestätigt und lokal eingetragen. Leere Listen sind keine Zusage, dass Erstellen erlaubt ist. Listenantworten beschreiben die aktuelle Sicht des Service Accounts, nicht sämtliche eventuell anderswo vorhandenen Ressourcen. + +Der Object-Storage-404 trat sowohl über die installierte STACKIT-CLI als auch direkt am dokumentierten v2-Service-Status-Endpunkt auf. Die offizielle CLI behandelt genau diesen Service-Status-404 in `ProjectEnabled` als nicht aktiviert. Der Provider aktiviert Object Storage beim Erstellen des ersten Buckets. Es wurde kein Bucket angelegt und es gab keinen fehlgeschlagenen Zugriff auf einen von uns erstellten Bucket. + +Quellen: [CLI-Auswertung](https://github.com/stackitcloud/stackit-cli/blob/main/internal/pkg/services/object-storage/utils/utils.go), [Bucket-Aktivierung im gepinnten Provider](https://github.com/stackitcloud/terraform-provider-stackit/blob/v0.114.0/stackit/internal/services/objectstorage/bucket/resource.go). + + + +## Wiederholen + +Siehe [Entwicklungsanleitung](../app/README.de.md): `npm run platform:check`. Das Skript nutzt Node.js-Systemzertifikate, begrenzte Timeouts, keine HTTP-Redirects mit Token und gibt nur aggregierte Metadaten aus. Es liefert Exitcode 1 bei unerwarteten Fehlern. Der bekannte Object-Storage-404 ist jetzt eine erfolgreiche Statusbestimmung mit `enabled: false`; das bedeutet noch keine Deployment-Bereitschaft. + +Installierte STACKIT-CLI beim Test: `0.61.0`. Deshalb wurden die Dienstlisten direkt über die bestätigten APIs nachgeprüft; die CLI bleibt für den Token-Austausch und Projekt-Lesezugriff im Skript. Eine ältere CLI-Ausgabe ohne JSON wurde nicht als leere Liste gewertet. + +API-Verträge aus dem offiziellen SDK: [SCF](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/scf), [PostgreSQL Flex](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/postgresflex), [Secrets Manager](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/secretsmanager), [Model Serving](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/modelserving), [Object Storage](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/objectstorage). + + + +## Konsequenzen für den nächsten Schritt + +- [x] Projekt-Lesezugriff mit bereitgestellter Identität bestätigen. +- [x] CF-/DB-/Secret-Angebote beziehungsweise Bestandslisten und Modellkatalog lesen. +- [x] Zielregion eu01 und Name lzc-dev für Entwicklung bestätigen. +- [ ] CF-Foundation/Quota festlegen. +- [x] Object-Storage-404 klären: noch nicht aktiviert; Aktivierung als Teil der Bucket-IaC. +- [x] State-Bootstrap und separaten Versionierungs-Root implementieren; erster realer Bootstrap-Plan erfolgreich. +- [ ] Bootstrap/Versionierung anwenden und S3-Locking sowie Restore praktisch testen. +- [ ] Erforderliche Create-/Update-Rechte anhand der geplanten Ressourcen prüfen; aus den GETs nicht ableiten. +- [ ] CF-Organisation und technischen CF-Zugang per IaC planen. +- [ ] DB-Plan, Secret-Policies und Modell-/Kapazitätsauswahl entscheiden. +- [ ] Runner-Isolation, private Erreichbarkeit und S3-Locking praktisch nachweisen. + +STACKIT-Projekt-Service-Account und CF-Runtime-Service-Account sind unterschiedliche Zugänge. Der offizielle IaC-Leitfaden provisioniert eine CF-Organisation und einen technischen Org-Manager über den STACKIT-Provider; anschließend verwaltet der CF-Provider die Runtime-Ressourcen. Die vorhandene JSON-Datei ist deshalb nicht automatisch ein funktionierender `cf login`-Zugang. Der Bootstrap und die sichere Ablage der erzeugten Zugangsdaten bleiben zu planen. [Offizieller CF-IaC-Leitfaden](https://github.com/stackitcloud/terraform-provider-stackit/blob/main/docs/guides/scf_cloudfoundry.md) + + + +## Lokale Entwicklungsprüfung + +- [x] Reproduzierbare Installation mit Node.js 24.21.0, npm 11.19.0 und `npm ci`. +- [x] Biome-Lint/Format und strikte TypeScript-Prüfung einschließlich Testcode. +- [x] Produktionsbuild von API, gemeinsamen Paketen und React-Oberfläche. +- [x] Fünf Tests: Tenant-Grenze, Rollenabgrenzung, ungültige Identitäten, Health-Vertrag, abgewiesene gefälschte Login-Header. +- [x] HTTP-Smoke-Test: gebaute API, Vite-UI-Dokument und Entwicklungsproxy; Prozesse danach beendet. +- [ ] Visuelle Browser-Abnahme (noch keine funktionale Editoroberfläche). +- [ ] GitHub-CI-Ausführung (Workflow angelegt, noch nicht gepusht/ausgeführt). +- [ ] CF-Deployment (noch keine Cloud-Mutation). + + + +## IaC-Fortschritt nach der Bestandsaufnahme + +Die bestätigte Umgebung ist lzc-dev/eu01. Ein echter Bootstrap-Plan wurde erfolgreich erstellt und anschließend aus der verschlüsselten Plan-Datei überprüft: **3 Create, 0 Update, 0 Delete**. Geplant sind Bucket, Credential-Gruppe und S3-Zugang bis 2026-12-28. Kein Apply wurde ausgeführt. + +Die erste gemeinsame Planung mit S3-Versionierung schlug fehl, weil der S3-Provider bereits zum Plan-Zeitpunkt gültige Credentials braucht. Die endgültige Struktur verwendet deshalb getrennte Roots `bootstrap`, `backend` (Versionierung) und `platform`. Alle drei sind validiert; sieben Mock-Plan-Tests und drei Tests für Plan-Hash/Kontext/Ablauf bestehen. Die IaC-CI ist entsprechend erweitert. + +Der bereinigte Plattform-Check wurde erneut ausgeführt und endet jetzt erfolgreich: Object Storage meldet nachvollziehbar `enabled: false` mit anstehender IaC-Provisionierung. Dies ist kein Nachweis einer bereits angelegten Umgebung. + + + +## Erstes Verwaltungs-Backend angewendet + +Seed: 3 Ressourcen erstellt, Seed-Protection: Versionierung aktiviert. Bootstrap-Remote-Backend initialisiert und Plan erfolgreich. S3-Versionierung, Auslesen einer früheren Testobjekt-Version und Hash-verifizierte Sicherung der verschlüsselten Seed-States erfolgreich. Schlüssel verbleiben separat lokal; unabhängige dauerhafte Schlüsselverwahrung und konkurrierender Lock-Test stehen aus. + + + +## S3-Locking: negatives Integrationsergebnis + +Zwei getrennte OpenTofu-Datenverzeichnisse, derselbe isolierte S3-State-Key: erster Apply hält eine sichtbare `.tflock`, zweiter Plan mit `-lock-timeout=0s` läuft dennoch erfolgreich. Separater Test mit AWS CLI: wiederholtes `put-object --if-none-match '*'` auf ein bestehendes Testobjekt wird nicht mit 412 abgewiesen. Native S3-Sperrwirkung ist damit am getesteten eu01-Endpunkt nicht gegeben. Testobjekte und Versionen wurden entfernt; produktive States wurden nicht verändert. diff --git a/landing-zone-configurator/docs/platform-check.md b/landing-zone-configurator/docs/platform-check.md index 865ae48..198cce7 100644 --- a/landing-zone-configurator/docs/platform-check.md +++ b/landing-zone-configurator/docs/platform-check.md @@ -1,74 +1,85 @@ -# Lesende Plattformprüfung +# Read-only platform check -Stand: 2026-09-29. Ziel: Betreiberprojekt aus der lokalen `landing-zone-configurator.env`, Authentisierung mit der zugehörigen Service-Account-Datei. IDs, Schlüssel und Tokens werden hier bewusst nicht wiederholt. +[English](platform-check.md) | [Deutsch](platform-check.de.md) -## Ergebnis + -| Prüfung | Beobachtung | Aussage / Grenze | +As of: 2026-09-29. Target: the operator project from the local `landing-zone-configurator.env`, authenticated with its associated service-account file. IDs, keys and tokens are deliberately not repeated here. + + +## Results + +| Check | Observation | Conclusion / limitation | | --- | --- | --- | -| Service-Account-Authentisierung | Kurzlebiger Token erfolgreich bezogen | Kein persistenter CLI-Login geändert | -| Projekt lesen | Erfolgreich; zurückgegebene Projekt-ID stimmt mit Eingabe überein | Projekt-Lesezugriff nachgewiesen; keine Prüfung von Schreibrechten oder Organisationszuordnung | -| CF-Organisationen | HTTP 200; 0 Einträge | Im abgefragten Projekt/Region keine Organisation sichtbar | -| CF-Plattformangebote | HTTP 200; 2 Einträge | Angebote erreichbar; konkrete Foundation/Quota noch auswählen | -| PostgreSQL-Flex-Instanzen | HTTP 200; 0 Einträge | Keine Instanz sichtbar | -| PostgreSQL-Flavors | HTTP 200; 10 Einträge | Angebot lesbar; HA, Größe, Backup und Kosten noch entscheiden | -| Secrets-Manager-Instanzen | HTTP 200; 0 Einträge | Keine Instanz sichtbar; konkrete Policies/Isolation noch nicht prüfbar | -| Model-Serving-Katalog | HTTP 200; 10 Modelle | Allgemeiner Katalog lesbar; kein Nachweis projektbezogener Aktivierung, Inferenzrechte oder gebuchter Kapazität | -| Object-Storage-Service-Status | HTTP 404 | Nach Abgleich mit der offiziellen CLI: Dienst im Projekt/Region noch nicht aktiviert; der erste IaC-Bucket aktiviert ihn | +| Service-account authentication | Short-lived token successfully obtained | No persistent CLI login changed | +| Read project | Successful; returned project ID matches the input | Project read access demonstrated; no verification of write permissions or organization membership | +| CF organizations | HTTP 200; 0 entries | No organization visible in the queried project/region | +| CF platform offerings | HTTP 200; 2 entries | Offerings accessible; specific foundation/quota still to be selected | +| PostgreSQL Flex instances | HTTP 200; 0 entries | No instance visible | +| PostgreSQL flavors | HTTP 200; 10 entries | Offering readable; HA, size, backup and costs still to be decided | +| Secrets Manager instances | HTTP 200; 0 entries | No instance visible; specific policies/isolation cannot yet be checked | +| Model Serving catalogue | HTTP 200; 10 models | General catalogue readable; not evidence of project-specific activation, inference permissions or booked capacity | +| Object Storage service status | HTTP 404 | Cross-checked against the official CLI: service not yet enabled in the project/region; the first IaC bucket enables it | -Die erste Abfrage verwendete `eu01` als Probe-Region. Anschließend wurden **lzc-dev/eu01** als erste Entwicklungsumgebung bestätigt und lokal eingetragen. Leere Listen sind keine Zusage, dass Erstellen erlaubt ist. Listenantworten beschreiben die aktuelle Sicht des Service Accounts, nicht sämtliche eventuell anderswo vorhandenen Ressourcen. +The first query used `eu01` as a probe region. Subsequently, **lzc-dev/eu01** was confirmed as the first development environment and recorded locally. Empty lists are not a promise that creation is permitted. List responses describe the service account's current view, not all resources that may exist elsewhere. -Der Object-Storage-404 trat sowohl über die installierte STACKIT-CLI als auch direkt am dokumentierten v2-Service-Status-Endpunkt auf. Die offizielle CLI behandelt genau diesen Service-Status-404 in `ProjectEnabled` als nicht aktiviert. Der Provider aktiviert Object Storage beim Erstellen des ersten Buckets. Es wurde kein Bucket angelegt und es gab keinen fehlgeschlagenen Zugriff auf einen von uns erstellten Bucket. +The Object Storage 404 occurred both through the installed STACKIT CLI and directly at the documented v2 service-status endpoint. The official CLI treats exactly this service-status 404 in `ProjectEnabled` as not enabled. The provider enables Object Storage when creating the first bucket. No bucket was created, and there was no failed attempt to access a bucket created by us. -Quellen: [CLI-Auswertung](https://github.com/stackitcloud/stackit-cli/blob/main/internal/pkg/services/object-storage/utils/utils.go), [Bucket-Aktivierung im gepinnten Provider](https://github.com/stackitcloud/terraform-provider-stackit/blob/v0.114.0/stackit/internal/services/objectstorage/bucket/resource.go). +Sources: [CLI handling](https://github.com/stackitcloud/stackit-cli/blob/main/internal/pkg/services/object-storage/utils/utils.go), [bucket activation in the pinned provider](https://github.com/stackitcloud/terraform-provider-stackit/blob/v0.114.0/stackit/internal/services/objectstorage/bucket/resource.go). -## Wiederholen + +## Repeating the check -Siehe [Entwicklungsanleitung](../app/README.md): `npm run platform:check`. Das Skript nutzt Node.js-Systemzertifikate, begrenzte Timeouts, keine HTTP-Redirects mit Token und gibt nur aggregierte Metadaten aus. Es liefert Exitcode 1 bei unerwarteten Fehlern. Der bekannte Object-Storage-404 ist jetzt eine erfolgreiche Statusbestimmung mit `enabled: false`; das bedeutet noch keine Deployment-Bereitschaft. +See the [development instructions](../app/README.md): `npm run platform:check`. The script uses Node.js system certificates, bounded timeouts, no HTTP redirects carrying tokens, and outputs only aggregated metadata. It returns exit code 1 for unexpected errors. The known Object Storage 404 is now a successful status determination with `enabled: false`; this does not yet mean deployment readiness. -Installierte STACKIT-CLI beim Test: `0.61.0`. Deshalb wurden die Dienstlisten direkt über die bestätigten APIs nachgeprüft; die CLI bleibt für den Token-Austausch und Projekt-Lesezugriff im Skript. Eine ältere CLI-Ausgabe ohne JSON wurde nicht als leere Liste gewertet. +Installed STACKIT CLI during the test: `0.61.0`. Service lists were therefore cross-checked directly through the confirmed APIs; the script still uses the CLI for token exchange and project read access. Older CLI output without JSON was not interpreted as an empty list. -API-Verträge aus dem offiziellen SDK: [SCF](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/scf), [PostgreSQL Flex](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/postgresflex), [Secrets Manager](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/secretsmanager), [Model Serving](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/modelserving), [Object Storage](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/objectstorage). +API contracts from the official SDK: [SCF](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/scf), [PostgreSQL Flex](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/postgresflex), [Secrets Manager](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/secretsmanager), [Model Serving](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/modelserving), [Object Storage](https://github.com/stackitcloud/stackit-sdk-go/tree/main/services/objectstorage). -## Konsequenzen für den nächsten Schritt + +## Implications for the next step -- [x] Projekt-Lesezugriff mit bereitgestellter Identität bestätigen. -- [x] CF-/DB-/Secret-Angebote beziehungsweise Bestandslisten und Modellkatalog lesen. -- [x] Zielregion eu01 und Name lzc-dev für Entwicklung bestätigen. -- [ ] CF-Foundation/Quota festlegen. -- [x] Object-Storage-404 klären: noch nicht aktiviert; Aktivierung als Teil der Bucket-IaC. -- [x] State-Bootstrap und separaten Versionierungs-Root implementieren; erster realer Bootstrap-Plan erfolgreich. -- [ ] Bootstrap/Versionierung anwenden und S3-Locking sowie Restore praktisch testen. -- [ ] Erforderliche Create-/Update-Rechte anhand der geplanten Ressourcen prüfen; aus den GETs nicht ableiten. -- [ ] CF-Organisation und technischen CF-Zugang per IaC planen. -- [ ] DB-Plan, Secret-Policies und Modell-/Kapazitätsauswahl entscheiden. -- [ ] Runner-Isolation, private Erreichbarkeit und S3-Locking praktisch nachweisen. +- [x] Confirm project read access with the provided identity. +- [x] Read CF/DB/secret offerings or inventories and the model catalogue. +- [x] Confirm target region eu01 and name lzc-dev for development. +- [ ] Define CF foundation/quota. +- [x] Clarify the Object Storage 404: not yet enabled; activation as part of bucket IaC. +- [x] Implement state bootstrap and a separate versioning root; first real bootstrap plan successful. +- [ ] Apply bootstrap/versioning and practically test S3 locking and restore. +- [ ] Verify required create/update permissions against the planned resources; do not infer them from GETs. +- [ ] Plan the CF organization and technical CF access through IaC. +- [ ] Decide DB plan, secret policies and model/capacity selection. +- [ ] Practically demonstrate Runner isolation, private connectivity and S3 locking. -STACKIT-Projekt-Service-Account und CF-Runtime-Service-Account sind unterschiedliche Zugänge. Der offizielle IaC-Leitfaden provisioniert eine CF-Organisation und einen technischen Org-Manager über den STACKIT-Provider; anschließend verwaltet der CF-Provider die Runtime-Ressourcen. Die vorhandene JSON-Datei ist deshalb nicht automatisch ein funktionierender `cf login`-Zugang. Der Bootstrap und die sichere Ablage der erzeugten Zugangsdaten bleiben zu planen. [Offizieller CF-IaC-Leitfaden](https://github.com/stackitcloud/terraform-provider-stackit/blob/main/docs/guides/scf_cloudfoundry.md) +The STACKIT project service account and CF runtime service account are different credentials. The official IaC guide provisions a CF organization and a technical org manager through the STACKIT provider; the CF provider then manages runtime resources. The existing JSON file is therefore not automatically a working `cf login` credential. Bootstrap and secure storage of the generated credentials still need to be planned. [Official CF IaC guide](https://github.com/stackitcloud/terraform-provider-stackit/blob/main/docs/guides/scf_cloudfoundry.md) -## Lokale Entwicklungsprüfung + +## Local development checks -- [x] Reproduzierbare Installation mit Node.js 24.21.0, npm 11.19.0 und `npm ci`. -- [x] Biome-Lint/Format und strikte TypeScript-Prüfung einschließlich Testcode. -- [x] Produktionsbuild von API, gemeinsamen Paketen und React-Oberfläche. -- [x] Fünf Tests: Tenant-Grenze, Rollenabgrenzung, ungültige Identitäten, Health-Vertrag, abgewiesene gefälschte Login-Header. -- [x] HTTP-Smoke-Test: gebaute API, Vite-UI-Dokument und Entwicklungsproxy; Prozesse danach beendet. -- [ ] Visuelle Browser-Abnahme (noch keine funktionale Editoroberfläche). -- [ ] GitHub-CI-Ausführung (Workflow angelegt, noch nicht gepusht/ausgeführt). -- [ ] CF-Deployment (noch keine Cloud-Mutation). +- [x] Reproducible installation with Node.js 24.21.0, npm 11.19.0 and `npm ci`. +- [x] Biome lint/format and strict TypeScript checking, including test code. +- [x] Production build of API, shared packages and React UI. +- [x] Five tests: tenant boundary, role separation, invalid identities, health contract, rejected forged login headers. +- [x] HTTP smoke test: built API, Vite UI document and development proxy; processes stopped afterwards. +- [ ] Visual browser acceptance (no functional editor UI yet). +- [ ] GitHub CI execution (workflow created, not yet pushed/executed). +- [ ] CF deployment (no cloud mutation yet). -## IaC-Fortschritt nach der Bestandsaufnahme + +## IaC progress after the inventory -Die bestätigte Umgebung ist lzc-dev/eu01. Ein echter Bootstrap-Plan wurde erfolgreich erstellt und anschließend aus der verschlüsselten Plan-Datei überprüft: **3 Create, 0 Update, 0 Delete**. Geplant sind Bucket, Credential-Gruppe und S3-Zugang bis 2026-12-28. Kein Apply wurde ausgeführt. +The confirmed environment is lzc-dev/eu01. A real bootstrap plan was successfully created and then checked from the encrypted plan file: **3 Create, 0 Update, 0 Delete**. The plan includes a bucket, credential group and S3 access until 2026-12-28. No Apply was executed. -Die erste gemeinsame Planung mit S3-Versionierung schlug fehl, weil der S3-Provider bereits zum Plan-Zeitpunkt gültige Credentials braucht. Die endgültige Struktur verwendet deshalb getrennte Roots `bootstrap`, `backend` (Versionierung) und `platform`. Alle drei sind validiert; sieben Mock-Plan-Tests und drei Tests für Plan-Hash/Kontext/Ablauf bestehen. Die IaC-CI ist entsprechend erweitert. +The first combined plan with S3 versioning failed because the S3 provider already needs valid credentials at plan time. The final structure therefore uses separate roots `bootstrap`, `backend` (versioning) and `platform`. All three are validated; seven mock plan tests and three tests for plan hash/context/expiry pass. IaC CI has been extended accordingly. -Der bereinigte Plattform-Check wurde erneut ausgeführt und endet jetzt erfolgreich: Object Storage meldet nachvollziehbar `enabled: false` mit anstehender IaC-Provisionierung. Dies ist kein Nachweis einer bereits angelegten Umgebung. +The corrected platform check was run again and now completes successfully: Object Storage reports an understandable `enabled: false` with IaC provisioning pending. This is not evidence of an environment already having been created. -## Erstes Verwaltungs-Backend angewendet + +## First management backend applied -Seed: 3 Ressourcen erstellt, Seed-Protection: Versionierung aktiviert. Bootstrap-Remote-Backend initialisiert und Plan erfolgreich. S3-Versionierung, Auslesen einer früheren Testobjekt-Version und Hash-verifizierte Sicherung der verschlüsselten Seed-States erfolgreich. Schlüssel verbleiben separat lokal; unabhängige dauerhafte Schlüsselverwahrung und konkurrierender Lock-Test stehen aus. +Seed: 3 resources created; seed protection: versioning enabled. Bootstrap remote backend initialized and plan successful. S3 versioning, reading a previous test-object version and hash-verified backup of encrypted seed states successful. Keys remain separately local; independent durable key custody and a concurrent lock test are outstanding. -## S3-Locking: negatives Integrationsergebnis + +## S3 locking: negative integration result -Zwei getrennte OpenTofu-Datenverzeichnisse, derselbe isolierte S3-State-Key: erster Apply hält eine sichtbare `.tflock`, zweiter Plan mit `-lock-timeout=0s` läuft dennoch erfolgreich. Separater Test mit AWS CLI: wiederholtes `put-object --if-none-match '*'` auf ein bestehendes Testobjekt wird nicht mit 412 abgewiesen. Native S3-Sperrwirkung ist damit am getesteten eu01-Endpunkt nicht gegeben. Testobjekte und Versionen wurden entfernt; produktive States wurden nicht verändert. +Two separate OpenTofu data directories, the same isolated S3 state key: the first Apply holds a visible `.tflock`, yet the second Plan with `-lock-timeout=0s` succeeds. Separate test with AWS CLI: repeated `put-object --if-none-match '*'` on an existing test object is not rejected with 412. Native S3 locking is therefore ineffective at the tested eu01 endpoint. Test objects and versions were removed; production states were not changed. diff --git a/landing-zone-configurator/docs/platform-readiness.de.md b/landing-zone-configurator/docs/platform-readiness.de.md new file mode 100644 index 0000000..4c19e1e --- /dev/null +++ b/landing-zone-configurator/docs/platform-readiness.de.md @@ -0,0 +1,222 @@ + + +# Plattform-Betriebsstand nach Bootstrap und Backend + +[English](platform-readiness.md) | [Deutsch](platform-readiness.de.md) + +**Aktuell (2026-09-30):** Plattform-Recovery und Apply erfolgreich. Neun Ressourcen sind im verschlüsselten Remote-State erfasst. PostgreSQL ist `READY`, CF aktiv, Secrets Manager `Running`. [Recovery-/Apply-Run 36675347654](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347654). CF-Runtime und Zugriffstests sind weiterhin offen. + + + +## Abgeschlossen + +- [x] Bootstrap-State-Bucket und S3-Zugang via CI erstellt. +- [x] Versionierung dieses Buckets via Backend-Root aktiviert: [Run 36602706599](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36602706599), Commit `d68c0a1a1199c34cf529ef0a87d62943c35a0585`. +- [x] `Enabled` direkt über S3 API sowie verschlüsselten Backend-State unabhängig geprüft. +- [x] Einmalige Commit-/Root-Freigaben nach Apply entfernt. +- [x] Begleitende App-/IaC-Validierung erfolgreich: [Run 36602706648](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36602706648). + + + +## Aus Katalogen vorbereitete Entwicklungsparameter + +Die folgenden Werte wurden anhand der Projektkataloge ausgewählt. Verbindliche Deployment-Eingaben einschließlich getrennter Netzwerk-ACLs stehen in `infra/environments/lzc-dev.tfvars.json`. + +| Parameter | Auswahl | Grund | +| --- | --- | --- | +| Foundation | Öffentliche CF `01.cf.eu01` | Geplante Anwendung für unabhängige Kunden | +| CF Quota | small: 10 GiB RAM, 10 Service-Instanzen | Raum für Web/API/Worker und zusätzliche Instanzen bei Deployments; default ist auf drei App-Instanzen begrenzt | +| PostgreSQL | Version 17, Flavor 2.16 | Verfügbar: 2 CPUs und 16 GiB RAM | +| Speicher | 20 GiB, premium-perf2-stackit | Im Katalog verfügbar, gültiger Größenbereich 5–4000 GiB | +| Backups | Täglich 02:00, Retention 32 Tage | Entwicklungsdefault; Produktivziele separat festlegen | + + + +## Plattform und verbleibende Abnahmen + +- [x] Netzwerkannahme korrigiert: CF-Egress-IP-Adressen sind laut Betreiberwissen nicht dokumentiert und nicht stabil; keine CF-spezifische IP-Allowlist voraussetzen. +- [ ] Dokumentierte STACKIT-Service-Netze für PostgreSQL als Zugangsmodell evaluieren und Zugriff aus CF testen. +- [ ] Zugangsmodell des Secrets Managers separat klären; PostgreSQL-Netzfreigaben nicht ungeprüft übertragen. +- [x] Migrationen als CF-Tasks vorgesehen; technische Umsetzung und Operator-Zugriff noch offen. +- [x] Plattform-CI mit getrennten Environments und eigenem State-Key anbinden. +- [x] Konkreten Plattform-Plan prüfen und anschließend deployen. + +Der erste Plattform-Apply wurde wegen des Job-Zeitlimits abgebrochen. Der Teilbestand wurde inzwischen erfolgreich importiert und das Deployment vervollständigt; siehe die Recovery-Abnahme unten. Alle Arbeiten verbleiben auf `feature/landing-zone-configurator`. + + + +## Korrigiertes Netzwerkmodell + +Die Anwendung darf nicht von einzelnen, beobachteten CF-Ausgangs-IP-Adressen abhängen. Auch eine einmalige Messung per Test-App würde keine stabile Allowlist ergeben. Service-Bindings liefern Zugangsdaten und Verbindungsparameter; sie sind kein Nachweis, dass eine Netzwerk-ACL umgangen oder automatisch gepflegt wird. + +Für PostgreSQL Flex nennt die offizielle Dokumentation `193.148.160.0/19` und `45.129.40.0/21` ausdrücklich für den Zugriff aus STACKIT-Diensten. Diese dokumentierten Anbieter-Netze sind ein Kandidat für den Konnektivitätstest, keine exklusiven Netze unserer Anwendung oder unseres Mandanten. TLS mit Zertifikatsprüfung, getrennte App-/Migrationsidentitäten und Datenbankautorisierung bleiben erforderlich. Änderungen der unterstützten Netze müssen über IaC nachvollzogen werden; die Adressen sind keine zugesicherten CF-Egress-CIDRs. + +Für den Secrets Manager muss dessen unterstütztes Zugangsmodell unabhängig geprüft werden. Der bisherige gemeinsame Parameter `service_access_cidrs` für beide Dienste darf vor dem Plattform-Apply nicht einfach mit den PostgreSQL-Netzen gefüllt werden. Separate ACL-Eingaben sind bei unterschiedlichen Dienstanforderungen vorzusehen. Ein eigener Zugangsproxy ist erst dann zu planen, wenn das unterstützte direkte Zugangsmodell nicht ausreicht. Keine pauschale Öffnung auf `0.0.0.0/0` aus dieser Korrektur ableiten. + +Datenbankmigrationen sollen später als CF-Task mit separater Migrationsidentität laufen. GitHub Actions startet und überwacht die Task; dafür muss die Datenbank nicht für wechselnde GitHub-Runner-IP-Adressen geöffnet werden. Der technische Nachweis einschließlich Credentials-Bindung steht noch aus. + +Quellen: [PostgreSQL-Instanzen und ACLs](https://docs.stackit.cloud/products/databases/postgresql-flex/how-tos/create-and-manage-instances-for-postgresql-flex/), [Secrets-Manager-Konfiguration](https://docs.stackit.cloud/products/security/secrets-manager/getting-started/configure-the-secrets-manager/), [CF-Service-Bindings](https://docs.cloudfoundry.org/devguide/services/application-binding.html). + + + +## Konkreter Plattform-Entwurf + +Die versionierte Datei `infra/environments/lzc-dev.tfvars.json` enthält jetzt die ausgewählten Katalogparameter. Datenbank und Secrets Manager verwenden unabhängige ACL-Variablen. Für den Entwicklungsentwurf sind beide bewusst auf die STACKIT-Netze `193.148.160.0/19` und `45.129.40.0/21` begrenzt. Für PostgreSQL sind diese Netze dokumentiert; beim Secrets Manager ist dies eine explizite Netzfreigabe als Ausgangskonfiguration, keine Behauptung einer dokumentierten CF-Netzgarantie. Erreichbarkeit und Authentifizierung sind aus einer CF-Test-App beziehungsweise CF-Task vor Nutzung mit Kundendaten zu prüfen. Bei fehlender Erreichbarkeit wird die Netzkonfiguration anhand von Nachweisen angepasst, nicht pauschal geöffnet. + +Die eigene Pipeline `configurator-platform.yml` verwendet denselben Serialisierungsmechanismus wie Bootstrap, aber eigene GitHub-Environments und einen separaten Verschlüsselungsschlüssel. Sie liest Bootstrap-/Backend-Outputs geschützt im Arbeitsspeicher, prüft den angewendeten Versionierungsstatus und verwendet anschließend den Workload-State-Bucket. Plattformparameter, Commit, Root und Plan-Hash sind an die Apply-Prüfung gebunden. + +Die gesonderte Freigabe zur Secret-Hinterlegung in `lzc-dev-platform-plan` und `lzc-dev-platform-apply` liegt vor. Die Bereitstellung wird nun über einen frischen CI-Plan und einen daran gebundenen Apply ausgeführt. + +Lokaler technischer Nachweis: echter Plattform-Plan erfolgreich, **9 Create / 0 Update / 0 Delete** (CF-Organisation und Manager, PostgreSQL-Instanz/Datenbank/Migrationsnutzer, Secrets-Manager-Instanz/Provisionierungsnutzer, Artefakt-Bucket und Model-Serving-Token). Sechs Plattform-Mock-Tests, 16 Node-Tests und Workflow-Prüfung erfolgreich. Der lokale Provider-Download hing; die Prüfung wurde mit bereits installierten, gegen das Lockfile geprüften Provider-Binaries wiederholt. Dieser lokale Nachweis führte keinen Apply aus. Die Plattform-Pipeline ist nach der genehmigten Environment-/Secret-Einrichtung über `LZC_PLATFORM_CI_ENABLED` aktiviert. + + + +## Vorfall 2026-09-30: erster Plattform-Apply unvollständig + +- [x] Secrets mit ausdrücklicher Benutzerfreigabe in die beiden Plattform-Environments übertragen; Werte nicht protokolliert. +- [x] CI-Plan und verschlüsseltes Artefakt geprüft: Commit `3322dd99a37a495fda8ba46fc4eb6284895d4316`, neun Create, keine Update/Delete; Hash und Run-Zuordnung geprüft. +- [x] [Validierung 36632950763](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36632950763) erfolgreich. +- [x] Genehmigten Apply gestartet: [Run 36632950493](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36632950493). +- [ ] Plattform-Apply erfolgreich abschließen: Job nach 45 Minuten durch GitHub abgebrochen (`maximum execution time of 45m0s`). +- [x] Einmalige Variable `LZC_PLATFORM_APPLY_COMMIT` entfernt und `LZC_PLATFORM_CI_ENABLED=false` gesetzt; keine automatischen Wiederholungen. + +Direkte API-Prüfung nach dem Abbruch: PostgreSQL `lzc-dev-db` wechselte von `PENDING` nach `PROGRESSING`; Secrets Manager `lzc-dev-secrets` meldete `Running`, die CF-Organisation `active`. Das belegt einen Teilbestand, nicht die Vollständigkeit aller neun Ressourcen oder die Nutzbarkeit der Anwendung. Die serverseitige Datenbankbereitstellung läuft unabhängig vom beendeten Runner weiter. + +Der erwartete Plattform-State im Workload-Bucket ist nicht vorhanden (`NoSuchKey`). Auch die Objektversionsliste enthält keinen Plattform-State, aber ein verbliebenes `.tflock`-Objekt. Dieses ist kein Ersatz für den State und wurde nicht entfernt. Es wurde kein weiterer Apply gestartet. Der ursprüngliche Plan darf nicht wiederverwendet werden: Er plant neue Ressourcen und kennt den inzwischen vorhandenen Teilbestand nicht. + + + +### Wiederaufnahme und Abnahme (abgeschlossen, Details unten) + +- [x] PostgreSQL-Endzustand über die API prüfen (`READY`); bei weiterhin festhängender Bereitstellung STACKIT-Service-Diagnose mit Instanz-ID aus dem lokalen Inventar veranlassen. +- [x] Vollständiges Inventar aller neun geplanten Ressourcen einschließlich technischer Benutzer und Model-Serving-Token erstellen; IDs und Zugangsdaten geschützt behandeln. +- [x] State-Recovery über einen dedizierten, serialisierten CI-Weg durchführen: vorhandene importierbare Ressourcen importieren, nicht wiederherstellbare Einmal-Credentials kontrolliert rotieren. Keine Doppelanlage oder ungeprüfte Löschung. +- [x] Verbliebenes Lock erst nach Prüfung auf beendete Runner und vor kontrollierter Recovery behandeln; native S3-Sperre bleibt als unzuverlässig dokumentiert. +- [x] CI-Prozesssteuerung verbessern: rechtzeitiger geordneter OpenTofu-Abbruch vor dem äußeren Job-Zeitlimit, geschützte Diagnose und verschlüsselte Recovery-Artefakte. Nur das Timeout zu erhöhen behebt den fehlenden State nicht. +- [x] Nach Recovery frischen Plan prüfen; erst dann Plattform-CI wieder aktivieren und neue konkrete Apply-Freigabe setzen. +- [x] Verschlüsselten Remote-State, vollständige Ressourcen und anschließenden No-op-Plan unabhängig verifizieren. +- [ ] CF-Runtime (Space, Apps, Bindings, separate Laufzeitidentitäten) per IaC erstellen und PostgreSQL-/Secrets-Zugriff aus CF testen. + + + + +## Erfolgreiche Recovery und Plattform-Abnahme + +Commit `1843069ce6914c26d04a7461d0799fc1c58794d7`, [Run 36675347654](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347654): Recovery, Plan und Apply erfolgreich. [Validierungs-Run 36675347681](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347681) ebenfalls erfolgreich. + +Sechs vorhandene Ressourcen wurden importiert, ohne die Instanzen, CF-Organisation oder den Artefakt-Bucket neu anzulegen. Der verwaiste Model-Serving-Token wurde widerrufen. Der frisch geprüfte Plan erstellte Datenbank, Migrationsbenutzer und neuen Model-Serving-Token; CF-Manager und Secrets-Provisionierungsbenutzer wurden wegen der verlorenen Passwörter ersetzt. Das PostgreSQL-Update betraf berechnete Flavor-Metadaten, bei unveränderter Flavor-ID und unveränderten Infrastrukturparametern. + +Unabhängige Abnahme: + +- [x] Verschlüsseltes State-Objekt im Workload-Bucket vorhanden; neun verwaltete Ressourcen geprüft. +- [x] Beide getrennten Netzwerk-ACLs entsprechen den geplanten Netzen. +- [x] PostgreSQL `READY`, Datenbank `configurator` mit Owner `configurator_migration` vorhanden. +- [x] CF-Organisation aktiv und Secrets Manager `Running`. +- [x] Neue technische Benutzer und genau ein neuer aktiver Configurator-Model-Serving-Token in der API bestätigt; alte Identitäten ersetzt. +- [x] Erforderliche Passwörter und Token im verschlüsselten State vorhanden, ohne Werte auszugeben. +- [x] Geschützte Diagnose und State-Snapshot aus GitHub heruntergeladen; authentifizierte Entschlüsselung und JSON-Integrität geprüft. +- [x] Beide Einmalvariablen `LZC_PLATFORM_RECOVERY_COMMIT` und `LZC_PLATFORM_APPLY_COMMIT` entfernt. Plattform-CI wieder für Plan-Läufe aktiv. +- [x] Abschließenden Plan ohne Änderungen bestätigen: [Run 36675895279](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675895279), alle neun Ressourcen `no-op`; Recovery/Apply übersprungen. Commit, Run und Plan-Hash unabhängig geprüft. [Begleitende Validierung](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675895374) erfolgreich. + +Plattform-Jobs haben jetzt ein äußeres Zeitlimit von 100 Minuten. OpenTofu-Apply erhält maximal 70 Minuten und danach bis zu zehn Minuten zum geordneten Beenden; eine zusätzliche Gesamtlaufzeitgrenze des Skripts hält Puffer für Artefakte frei. 22 lokale Tests einschließlich Abbruchverhalten, verschlüsselter Diagnose und Recovery-Sperren sowie Workflow-Prüfung bestanden. + +Nächster Ausbau: CF-Space und App-/Task-Runtime per IaC, getrennte Laufzeitidentitäten/Bindings und echte TLS-/Authentifizierungstests aus CF. Die Infrastrukturabnahme belegt noch keinen erfolgreichen App-Zugriff auf Datenbank oder Secrets Manager. + + + + +## CI-Vereinfachung 2026-09-30 + +Die Workflows führen OpenTofu jetzt direkt aus. Der bisherige Deployment-Runner, Prozessmanager und automatische Einmal-Recovery-Pfad sind entfernt. Normale Plan-/Apply-Logs erscheinen live; Credential-Outputs und State-Snapshots bleiben gezielt geschützt. GNU `timeout` übernimmt SIGINT und die anschließende Wartezeit; keine eigene Signalsteuerung. Die geltenden Zeitlimits und Befehle stehen in der [CI-Betriebsanleitung](../infra/ci/README.de.md). Das historische Recovery-Inventar liegt unter `docs/incidents`, ohne aktive Ausführung. + + +Abnahme der direkten CLI-Pipelines: Bootstrap-Run 36677111141 und Plattform-Run 36677111032 erfolgreich, jeweils `No changes`, Apply übersprungen. Die normalen Init-/Plan-Details sind live sichtbar. Logs gegen bekannte Deployment-Credentials und State-Schlüssel geprüft, keine Treffer. Validierung 36677111055 erfolgreich, einschließlich des GNU-Timeout-Tests in allen fünf Linux-Matrix-Jobs. Keine Infrastrukturänderung durch den Umbau. + + +Backend-Abnahme des Umbaus: [Run 36677367229](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677367229) hat Root `backend` mit getrennten Management-/Workload-Zugängen geplant: `No changes`, Apply übersprungen. Root, Commit, Run, Plan-Hash und verschlüsseltes Artefakt geprüft. Native Logs sichtbar und ohne bekannte Credential-Werte. [Validierung 36677367252](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677367252) erfolgreich. Temporäre Root-Auswahl entfernt; keine Apply-Freigaben gesetzt. Bootstrap, Backend und Plattform wurden damit lesend geprüft, ohne Cloud-Apply oder State-Migration durch den Umbau. + + + + +## CF-Runtime und erster App-Release (2026-09-30) + +- [x] Separater Runtime-Root mit verschlüsseltem S3-State und Cloud-Foundry-Provider 1.17.0. +- [x] Space `configurator`, explizite `organization_user`-Mitgliedschaft und `space_developer`-Rolle erstellt. +- [x] Eigene PostgreSQL-Login-Rolle `configurator_app` und Secrets-Manager-Benutzer mit Read-only-Recht. +- [x] [Runtime-Apply 36681789484](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36681789484) erfolgreich; fünf Ressourcen unabhängig im verschlüsselten Remote-State bestätigt. +- [x] Web/API über getrennten Release-Workflow mit direkten `cf`-Befehlen bereitgestellt; Model-Serving-Token nur im Backend-Environment. +- [x] [Release 36682016739](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36682016739): Build und CF-Push erfolgreich, Anwendung gestartet. Native CLI-Logs auf bekannte Credential-Werte geprüft: keine Treffer. +- [ ] PostgreSQL-Verbindung: erster CF-Task scheitert nach 15 Sekunden; Netz-/TCP-Diagnose folgt. +- [ ] Secrets Manager: erster CF-Task erhält HTTP 403 beim Login; laut [STACKIT-Diagnose](https://docs.stackit.cloud/products/security/secrets-manager/how-tos/handle-authentication-lockouts/) Hinweis auf Quell-IP-ACL. + +Der erste Runtime-Apply erstellte Space und Benutzer, scheiterte aber an der fehlenden +CF-Organisationsmitgliedschaft. Der State blieb vollständig erhalten. Ein frischer +Plan ergänzte ausschließlich die zwei noch fehlenden Rollen; kein Import oder +Credential-Reset war erforderlich. + +Die CF-Foundation erlaubt öffentliche Ziele in ihrer globalen `public_networks`- +Security-Group. Das ist noch kein Nachweis für den jeweiligen Dienstpfad. Die bisher +verwendeten zwei STACKIT-Netze decken außerdem nicht den aktuellen öffentlichen +Adresskatalog ab. Die offizielle API `GET /v2/networks/public-ip-ranges` liefert +regionale Netze; Änderungen werden anhand des realen CF-Tests und eines neuen +IaC-Plans beurteilt. Keine beobachtete Einzel-IP wird als stabiler CF-Egress zugesagt. +Quelle für den aktuellen Katalog: [STACKIT IP-Ranges](https://docs.stackit.cloud/products/logging-and-monitoring/logme/how-tos/create-and-manage-logme-services/). + + + + +### Nachgewiesener ACL-Fehler und Korrekturplan + +Der Diagnose-Task in [Release 36682707060](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36682707060) +löst den PostgreSQL-Host korrekt auf, bekommt aber keine TCP-Verbindung. Ein +HTTPS-Aufruf desselben CF-Tasks zur eigenen Configurator-Route liefert HTTP 200; +der zugehörige CF-Router-Logeintrag zeigt eine Quelle aus `45.135.244.0/22`. +Dieses eu01-Netz ist im aktuellen STACKIT-IP-Katalog enthalten und wird auch in +der [STACKIT LogMe-FAQ](https://docs.stackit.cloud/products/logging-and-monitoring/logme/faq/) +als STACKIT-Standardnetz aufgeführt. Es fehlte in beiden expliziten ACLs. + +Der neue IaC-Plan ergänzt deshalb genau `45.135.244.0/22` in den getrennten +PostgreSQL- und Secrets-ACLs. Die beobachtete Einzel-IP wird nicht konfiguriert. +Dies bleibt eine Freigabe eines geteilten STACKIT-Netzes, keine mandanteneigene +oder zugesichert stabile CF-Ausgangsadresse. TLS, Benutzerrechte und spätere +Mandantenautorisierung bleiben separate Schutzschichten. Bei Netzänderungen +Katalog und CF-Test erneut prüfen; kein automatisches Öffnen weiterer Netze. + + + + +## Abnahme CF-Hosting und Dienstverbindungen abgeschlossen + +[Release 36683898762](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898762) +auf Commit `795a18a`: **vollständig erfolgreich**. +[Validierung 36683898795](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898795) +ist ebenfalls erfolgreich (App mit neun Tests und alle sechs IaC-Roots). + +- [x] [ACL-Apply 36683137454](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683137454): zwei In-place-Updates, keine Neuanlage/Löschung. Beide Dienst-ACLs unabhängig im verschlüsselten Remote-State geprüft. +- [x] App `landing-zone-configurator` im Space `configurator` gestartet; deklaratives Manifest unter `deploy/cloud-foundry/`. +- [x] PostgreSQL: DNS und TCP erreichbar, Laufzeitbenutzer authentifiziert, `SELECT 1` und `pg_stat_ssl` erfolgreich, Zertifikats-/Hostname-Prüfung aktiv. +- [x] Secrets Manager: TLS und Userpass-Login erfolgreich; reservierter KV-Pfad verweigert anonymen Zugriff und akzeptiert den authentifizierten Aufruf; Sitzungstoken danach widerrufen. +- [x] CF-Tasks `network-36683898762` und `connections-36683898762` sind `SUCCEEDED`. +- [x] HTTPS-Startseite und JavaScript-Asset ausgeliefert; `/healthz` HTTP 200, `/api/v1/session` HTTP 401. +- [x] Alle zehn Backend-Variablen mit verschlüsselten Runtime-Ausgaben verglichen; keine Projekt-/S3-/CF-Deployment-Credentials in der App. +- [x] Erfolgreiche Runtime-/ACL-/Release-Logs auf bekannte Schlüssel, Passwörter und Token geprüft, ohne Treffer. +- [x] Einmalige Runtime-/Plattform-Apply-Variablen entfernt; Feature-Branch beibehalten, kein Merge nach main. + +Der Secrets Manager unterstützt nicht die allgemeine Vault-System-API +`sys/capabilities-self` (im Test HTTP 404). Der endgültige Test nutzt den +[dokumentierten KV-Lese-Endpunkt](https://docs.stackit.cloud/products/security/secrets-manager/how-tos/cli-and-api/) +mit anonymem Negativtest. Für den absichtlich nicht angelegten Operator-Probe-Key +ist authentifiziertes HTTP 404 zulässig; HTTP 404 auch ohne Token würde den Test +fehlschlagen lassen. Es werden weder Kunden-Secrets gelesen noch Probe-Secrets +angelegt. **Ein Secret-Write/Read-Roundtrip, Mandantenautorisierung und Rotation +sind damit noch nicht abgenommen.** Die Laufzeitidentität ist in IaC read-only. + +Dev-Adresse: [lzc-dev Configurator](https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud). +Die kurze Route wird mit dem naechsten Release eingerichtet; die Live-Umstellung +und die aktualisierten OAuth-Callbacks muessen danach separat geprueft werden. +Dies ist das technische App-Grundgerüst. GitHub-Login, persistentes Mandantenschema, +Template-Editor, persönliche Credentials, Kunden-Plan/Apply und Chat folgen in der +[aktuellen MVP-Checkliste](planning.de.md#aktueller-meilenstein-cf-hosting-und-service-verbindungen). + +Die stehende Benutzerfreigabe für notwendige Configurator-Applies gilt bis MVP; +Planprüfung, Environment-Schutz und die gemeinsame CI-Concurrency bleiben aktiv. diff --git a/landing-zone-configurator/docs/platform-readiness.md b/landing-zone-configurator/docs/platform-readiness.md index abdea75..438fede 100644 --- a/landing-zone-configurator/docs/platform-readiness.md +++ b/landing-zone-configurator/docs/platform-readiness.md @@ -1,194 +1,167 @@ -# Plattform-Betriebsstand nach Bootstrap und Backend +# Platform operational status after bootstrap and backend -**Aktuell (2026-09-30):** Plattform-Recovery und Apply erfolgreich. Neun Ressourcen sind im verschlüsselten Remote-State erfasst. PostgreSQL ist `READY`, CF aktiv, Secrets Manager `Running`. [Recovery-/Apply-Run 36675347654](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347654). CF-Runtime und Zugriffstests sind weiterhin offen. +[English](platform-readiness.md) | [Deutsch](platform-readiness.de.md) -## Abgeschlossen + -- [x] Bootstrap-State-Bucket und S3-Zugang via CI erstellt. -- [x] Versionierung dieses Buckets via Backend-Root aktiviert: [Run 36602706599](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36602706599), Commit `d68c0a1a1199c34cf529ef0a87d62943c35a0585`. -- [x] `Enabled` direkt über S3 API sowie verschlüsselten Backend-State unabhängig geprüft. -- [x] Einmalige Commit-/Root-Freigaben nach Apply entfernt. -- [x] Begleitende App-/IaC-Validierung erfolgreich: [Run 36602706648](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36602706648). +**Current (2026-09-30):** Platform recovery and Apply successful. Nine resources are recorded in the encrypted remote state. PostgreSQL is `READY`, CF active, Secrets Manager `Running`. [Recovery/Apply run 36675347654](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347654). CF runtime and access tests remain outstanding. -## Aus Katalogen vorbereitete Entwicklungsparameter + +## Completed -Die folgenden Werte wurden anhand der Projektkataloge ausgewählt. Verbindliche Deployment-Eingaben einschließlich getrennter Netzwerk-ACLs stehen in `infra/environments/lzc-dev.tfvars.json`. +- [x] Bootstrap state bucket and S3 access created through CI. +- [x] Versioning of this bucket enabled through the backend root: [run 36602706599](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36602706599), commit `d68c0a1a1199c34cf529ef0a87d62943c35a0585`. +- [x] `Enabled` independently checked directly through the S3 API and encrypted backend state. +- [x] One-time commit/root approvals removed after Apply. +- [x] Accompanying app/IaC validation successful: [run 36602706648](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36602706648). -| Parameter | Auswahl | Grund | -| --- | --- | --- | -| Foundation | Öffentliche CF `01.cf.eu01` | Geplante Anwendung für unabhängige Kunden | -| CF Quota | small: 10 GiB RAM, 10 Service-Instanzen | Raum für Web/API/Worker und zusätzliche Instanzen bei Deployments; default ist auf drei App-Instanzen begrenzt | -| PostgreSQL | Version 17, Flavor 2.16 | Verfügbar: 2 CPUs und 16 GiB RAM | -| Speicher | 20 GiB, premium-perf2-stackit | Im Katalog verfügbar, gültiger Größenbereich 5–4000 GiB | -| Backups | Täglich 02:00, Retention 32 Tage | Entwicklungsdefault; Produktivziele separat festlegen | - -## Plattform und verbleibende Abnahmen - -- [x] Netzwerkannahme korrigiert: CF-Egress-IP-Adressen sind laut Betreiberwissen nicht dokumentiert und nicht stabil; keine CF-spezifische IP-Allowlist voraussetzen. -- [ ] Dokumentierte STACKIT-Service-Netze für PostgreSQL als Zugangsmodell evaluieren und Zugriff aus CF testen. -- [ ] Zugangsmodell des Secrets Managers separat klären; PostgreSQL-Netzfreigaben nicht ungeprüft übertragen. -- [x] Migrationen als CF-Tasks vorgesehen; technische Umsetzung und Operator-Zugriff noch offen. -- [x] Plattform-CI mit getrennten Environments und eigenem State-Key anbinden. -- [x] Konkreten Plattform-Plan prüfen und anschließend deployen. - -Der erste Plattform-Apply wurde wegen des Job-Zeitlimits abgebrochen. Der Teilbestand wurde inzwischen erfolgreich importiert und das Deployment vervollständigt; siehe die Recovery-Abnahme unten. Alle Arbeiten verbleiben auf `feature/landing-zone-configurator`. + +## Development parameters prepared from catalogues -## Korrigiertes Netzwerkmodell +The following values were selected from the project catalogues. Binding deployment inputs, including separate network ACLs, are in `infra/environments/lzc-dev.tfvars.json`. -Die Anwendung darf nicht von einzelnen, beobachteten CF-Ausgangs-IP-Adressen abhängen. Auch eine einmalige Messung per Test-App würde keine stabile Allowlist ergeben. Service-Bindings liefern Zugangsdaten und Verbindungsparameter; sie sind kein Nachweis, dass eine Netzwerk-ACL umgangen oder automatisch gepflegt wird. - -Für PostgreSQL Flex nennt die offizielle Dokumentation `193.148.160.0/19` und `45.129.40.0/21` ausdrücklich für den Zugriff aus STACKIT-Diensten. Diese dokumentierten Anbieter-Netze sind ein Kandidat für den Konnektivitätstest, keine exklusiven Netze unserer Anwendung oder unseres Mandanten. TLS mit Zertifikatsprüfung, getrennte App-/Migrationsidentitäten und Datenbankautorisierung bleiben erforderlich. Änderungen der unterstützten Netze müssen über IaC nachvollzogen werden; die Adressen sind keine zugesicherten CF-Egress-CIDRs. - -Für den Secrets Manager muss dessen unterstütztes Zugangsmodell unabhängig geprüft werden. Der bisherige gemeinsame Parameter `service_access_cidrs` für beide Dienste darf vor dem Plattform-Apply nicht einfach mit den PostgreSQL-Netzen gefüllt werden. Separate ACL-Eingaben sind bei unterschiedlichen Dienstanforderungen vorzusehen. Ein eigener Zugangsproxy ist erst dann zu planen, wenn das unterstützte direkte Zugangsmodell nicht ausreicht. Keine pauschale Öffnung auf `0.0.0.0/0` aus dieser Korrektur ableiten. +| Parameter | Selection | Reason | +| --- | --- | --- | +| Foundation | Public CF `01.cf.eu01` | Planned application for independent customers | +| CF quota | small: 10 GiB RAM, 10 service instances | Room for web/API/worker and additional instances during deployments; default is limited to three app instances | +| PostgreSQL | Version 17, flavor 2.16 | Available: 2 CPUs and 16 GiB RAM | +| Storage | 20 GiB, premium-perf2-stackit | Available in the catalogue, valid size range 5–4000 GiB | +| Backups | Daily at 02:00, retention 32 days | Development default; define production targets separately | -Datenbankmigrationen sollen später als CF-Task mit separater Migrationsidentität laufen. GitHub Actions startet und überwacht die Task; dafür muss die Datenbank nicht für wechselnde GitHub-Runner-IP-Adressen geöffnet werden. Der technische Nachweis einschließlich Credentials-Bindung steht noch aus. + +## Platform and remaining acceptance checks -Quellen: [PostgreSQL-Instanzen und ACLs](https://docs.stackit.cloud/products/databases/postgresql-flex/how-tos/create-and-manage-instances-for-postgresql-flex/), [Secrets-Manager-Konfiguration](https://docs.stackit.cloud/products/security/secrets-manager/getting-started/configure-the-secrets-manager/), [CF-Service-Bindings](https://docs.cloudfoundry.org/devguide/services/application-binding.html). +- [x] Network assumption corrected: according to operator knowledge, CF egress IP addresses are undocumented and unstable; do not assume a CF-specific IP allowlist. +- [ ] Evaluate documented STACKIT service networks as a PostgreSQL access model and test access from CF. +- [ ] Clarify the Secrets Manager access model separately; do not transfer PostgreSQL network allowances without checking. +- [x] Migrations planned as CF tasks; technical implementation and operator access still outstanding. +- [x] Connect platform CI with separate environments and its own state key. +- [x] Review the specific platform plan and then deploy. -## Konkreter Plattform-Entwurf +The first platform Apply was aborted because of the job time limit. The partial inventory has since been successfully imported and deployment completed; see recovery acceptance below. All work remains on `feature/landing-zone-configurator`. -Die versionierte Datei `infra/environments/lzc-dev.tfvars.json` enthält jetzt die ausgewählten Katalogparameter. Datenbank und Secrets Manager verwenden unabhängige ACL-Variablen. Für den Entwicklungsentwurf sind beide bewusst auf die STACKIT-Netze `193.148.160.0/19` und `45.129.40.0/21` begrenzt. Für PostgreSQL sind diese Netze dokumentiert; beim Secrets Manager ist dies eine explizite Netzfreigabe als Ausgangskonfiguration, keine Behauptung einer dokumentierten CF-Netzgarantie. Erreichbarkeit und Authentifizierung sind aus einer CF-Test-App beziehungsweise CF-Task vor Nutzung mit Kundendaten zu prüfen. Bei fehlender Erreichbarkeit wird die Netzkonfiguration anhand von Nachweisen angepasst, nicht pauschal geöffnet. + +## Corrected network model -Die eigene Pipeline `configurator-platform.yml` verwendet denselben Serialisierungsmechanismus wie Bootstrap, aber eigene GitHub-Environments und einen separaten Verschlüsselungsschlüssel. Sie liest Bootstrap-/Backend-Outputs geschützt im Arbeitsspeicher, prüft den angewendeten Versionierungsstatus und verwendet anschließend den Workload-State-Bucket. Plattformparameter, Commit, Root und Plan-Hash sind an die Apply-Prüfung gebunden. +The application must not depend on individual observed CF outbound IP addresses. Even a one-time measurement through a test app would not yield a stable allowlist. Service bindings provide credentials and connection parameters; they are not evidence that a network ACL is bypassed or automatically maintained. -Die gesonderte Freigabe zur Secret-Hinterlegung in `lzc-dev-platform-plan` und `lzc-dev-platform-apply` liegt vor. Die Bereitstellung wird nun über einen frischen CI-Plan und einen daran gebundenen Apply ausgeführt. +For PostgreSQL Flex, the official documentation explicitly lists `193.148.160.0/19` and `45.129.40.0/21` for access from STACKIT services. These documented provider networks are a candidate for the connectivity test, not networks exclusive to our application or tenant. TLS with certificate verification, separate app/migration identities and database authorization remain necessary. Changes to supported networks must be tracked through IaC; these addresses are not guaranteed CF egress CIDRs. -Lokaler technischer Nachweis: echter Plattform-Plan erfolgreich, **9 Create / 0 Update / 0 Delete** (CF-Organisation und Manager, PostgreSQL-Instanz/Datenbank/Migrationsnutzer, Secrets-Manager-Instanz/Provisionierungsnutzer, Artefakt-Bucket und Model-Serving-Token). Sechs Plattform-Mock-Tests, 16 Node-Tests und Workflow-Prüfung erfolgreich. Der lokale Provider-Download hing; die Prüfung wurde mit bereits installierten, gegen das Lockfile geprüften Provider-Binaries wiederholt. Dieser lokale Nachweis führte keinen Apply aus. Die Plattform-Pipeline ist nach der genehmigten Environment-/Secret-Einrichtung über `LZC_PLATFORM_CI_ENABLED` aktiviert. +The Secrets Manager's supported access model must be checked independently. The previous shared `service_access_cidrs` parameter for both services must not simply be filled with the PostgreSQL networks before the platform Apply. Separate ACL inputs must be provided where service requirements differ. A dedicated access proxy should only be planned if the supported direct access model is insufficient. Do not infer blanket opening to `0.0.0.0/0` from this correction. -## Vorfall 2026-09-30: erster Plattform-Apply unvollständig +Database migrations should later run as a CF task with a separate migration identity. GitHub Actions starts and monitors the task; the database need not be opened to changing GitHub Runner IP addresses for this. Technical evidence, including credential binding, is still outstanding. -- [x] Secrets mit ausdrücklicher Benutzerfreigabe in die beiden Plattform-Environments übertragen; Werte nicht protokolliert. -- [x] CI-Plan und verschlüsseltes Artefakt geprüft: Commit `3322dd99a37a495fda8ba46fc4eb6284895d4316`, neun Create, keine Update/Delete; Hash und Run-Zuordnung geprüft. -- [x] [Validierung 36632950763](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36632950763) erfolgreich. -- [x] Genehmigten Apply gestartet: [Run 36632950493](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36632950493). -- [ ] Plattform-Apply erfolgreich abschließen: Job nach 45 Minuten durch GitHub abgebrochen (`maximum execution time of 45m0s`). -- [x] Einmalige Variable `LZC_PLATFORM_APPLY_COMMIT` entfernt und `LZC_PLATFORM_CI_ENABLED=false` gesetzt; keine automatischen Wiederholungen. +Sources: [PostgreSQL instances and ACLs](https://docs.stackit.cloud/products/databases/postgresql-flex/how-tos/create-and-manage-instances-for-postgresql-flex/), [Secrets Manager configuration](https://docs.stackit.cloud/products/security/secrets-manager/getting-started/configure-the-secrets-manager/), [CF service bindings](https://docs.cloudfoundry.org/devguide/services/application-binding.html). -Direkte API-Prüfung nach dem Abbruch: PostgreSQL `lzc-dev-db` wechselte von `PENDING` nach `PROGRESSING`; Secrets Manager `lzc-dev-secrets` meldete `Running`, die CF-Organisation `active`. Das belegt einen Teilbestand, nicht die Vollständigkeit aller neun Ressourcen oder die Nutzbarkeit der Anwendung. Die serverseitige Datenbankbereitstellung läuft unabhängig vom beendeten Runner weiter. + +## Specific platform design -Der erwartete Plattform-State im Workload-Bucket ist nicht vorhanden (`NoSuchKey`). Auch die Objektversionsliste enthält keinen Plattform-State, aber ein verbliebenes `.tflock`-Objekt. Dieses ist kein Ersatz für den State und wurde nicht entfernt. Es wurde kein weiterer Apply gestartet. Der ursprüngliche Plan darf nicht wiederverwendet werden: Er plant neue Ressourcen und kennt den inzwischen vorhandenen Teilbestand nicht. +The versioned file `infra/environments/lzc-dev.tfvars.json` now contains the selected catalogue parameters. Database and Secrets Manager use independent ACL variables. For the development design, both are deliberately restricted to the STACKIT networks `193.148.160.0/19` and `45.129.40.0/21`. These networks are documented for PostgreSQL; for Secrets Manager this is an explicit network allowance as an initial configuration, not a claim of a documented CF network guarantee. Connectivity and authentication must be tested from a CF test app or CF task before use with customer data. If connectivity fails, adapt network configuration based on evidence rather than opening it indiscriminately. -### Wiederaufnahme und Abnahme (abgeschlossen, Details unten) +The separate pipeline `configurator-platform.yml` uses the same serialization mechanism as bootstrap, but its own GitHub environments and a separate encryption key. It reads bootstrap/backend outputs protected in memory, checks the applied versioning status and then uses the workload state bucket. Platform parameters, commit, root and plan hash are bound to the Apply check. -- [x] PostgreSQL-Endzustand über die API prüfen (`READY`); bei weiterhin festhängender Bereitstellung STACKIT-Service-Diagnose mit Instanz-ID aus dem lokalen Inventar veranlassen. -- [x] Vollständiges Inventar aller neun geplanten Ressourcen einschließlich technischer Benutzer und Model-Serving-Token erstellen; IDs und Zugangsdaten geschützt behandeln. -- [x] State-Recovery über einen dedizierten, serialisierten CI-Weg durchführen: vorhandene importierbare Ressourcen importieren, nicht wiederherstellbare Einmal-Credentials kontrolliert rotieren. Keine Doppelanlage oder ungeprüfte Löschung. -- [x] Verbliebenes Lock erst nach Prüfung auf beendete Runner und vor kontrollierter Recovery behandeln; native S3-Sperre bleibt als unzuverlässig dokumentiert. -- [x] CI-Prozesssteuerung verbessern: rechtzeitiger geordneter OpenTofu-Abbruch vor dem äußeren Job-Zeitlimit, geschützte Diagnose und verschlüsselte Recovery-Artefakte. Nur das Timeout zu erhöhen behebt den fehlenden State nicht. -- [x] Nach Recovery frischen Plan prüfen; erst dann Plattform-CI wieder aktivieren und neue konkrete Apply-Freigabe setzen. -- [x] Verschlüsselten Remote-State, vollständige Ressourcen und anschließenden No-op-Plan unabhängig verifizieren. -- [ ] CF-Runtime (Space, Apps, Bindings, separate Laufzeitidentitäten) per IaC erstellen und PostgreSQL-/Secrets-Zugriff aus CF testen. +Separate approval to store secrets in `lzc-dev-platform-plan` and `lzc-dev-platform-apply` has been given. Provisioning is now executed through a fresh CI plan and an Apply bound to it. +Local technical evidence: real platform plan successful, **9 Create / 0 Update / 0 Delete** (CF organization and manager, PostgreSQL instance/database/migration user, Secrets Manager instance/provisioning user, artifact bucket and Model Serving token). Six platform mock tests, 16 Node tests and workflow checking successful. The local provider download hung; checking was repeated with already installed provider binaries verified against the lockfile. This local evidence involved no Apply. After approved environment/secret setup, the platform pipeline is enabled through `LZC_PLATFORM_CI_ENABLED`. -## Erfolgreiche Recovery und Plattform-Abnahme + +## Incident 2026-09-30: first platform Apply incomplete -Commit `1843069ce6914c26d04a7461d0799fc1c58794d7`, [Run 36675347654](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347654): Recovery, Plan und Apply erfolgreich. [Validierungs-Run 36675347681](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347681) ebenfalls erfolgreich. +- [x] Secrets transferred to both platform environments with explicit user approval; values not logged. +- [x] CI plan and encrypted artifact checked: commit `3322dd99a37a495fda8ba46fc4eb6284895d4316`, nine Create, no Update/Delete; hash and run association checked. +- [x] [Validation 36632950763](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36632950763) successful. +- [x] Approved Apply started: [run 36632950493](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36632950493). +- [ ] Complete platform Apply successfully: job aborted by GitHub after 45 minutes (`maximum execution time of 45m0s`). +- [x] One-time variable `LZC_PLATFORM_APPLY_COMMIT` removed and `LZC_PLATFORM_CI_ENABLED=false` set; no automatic retries. -Sechs vorhandene Ressourcen wurden importiert, ohne die Instanzen, CF-Organisation oder den Artefakt-Bucket neu anzulegen. Der verwaiste Model-Serving-Token wurde widerrufen. Der frisch geprüfte Plan erstellte Datenbank, Migrationsbenutzer und neuen Model-Serving-Token; CF-Manager und Secrets-Provisionierungsbenutzer wurden wegen der verlorenen Passwörter ersetzt. Das PostgreSQL-Update betraf berechnete Flavor-Metadaten, bei unveränderter Flavor-ID und unveränderten Infrastrukturparametern. +Direct API check after the abort: PostgreSQL `lzc-dev-db` moved from `PENDING` to `PROGRESSING`; Secrets Manager `lzc-dev-secrets` reported `Running`, the CF organization `active`. This demonstrates a partial inventory, not completeness of all nine resources or application usability. Server-side database provisioning continues independently of the terminated Runner. -Unabhängige Abnahme: +The expected platform state in the workload bucket is absent (`NoSuchKey`). The object version list likewise contains no platform state, but a remaining `.tflock` object. This is no substitute for state and was not removed. No further Apply was started. The original plan must not be reused: it plans new resources and is unaware of the partial inventory now present. -- [x] Verschlüsseltes State-Objekt im Workload-Bucket vorhanden; neun verwaltete Ressourcen geprüft. -- [x] Beide getrennten Netzwerk-ACLs entsprechen den geplanten Netzen. -- [x] PostgreSQL `READY`, Datenbank `configurator` mit Owner `configurator_migration` vorhanden. -- [x] CF-Organisation aktiv und Secrets Manager `Running`. -- [x] Neue technische Benutzer und genau ein neuer aktiver Configurator-Model-Serving-Token in der API bestätigt; alte Identitäten ersetzt. -- [x] Erforderliche Passwörter und Token im verschlüsselten State vorhanden, ohne Werte auszugeben. -- [x] Geschützte Diagnose und State-Snapshot aus GitHub heruntergeladen; authentifizierte Entschlüsselung und JSON-Integrität geprüft. -- [x] Beide Einmalvariablen `LZC_PLATFORM_RECOVERY_COMMIT` und `LZC_PLATFORM_APPLY_COMMIT` entfernt. Plattform-CI wieder für Plan-Läufe aktiv. -- [x] Abschließenden Plan ohne Änderungen bestätigen: [Run 36675895279](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675895279), alle neun Ressourcen `no-op`; Recovery/Apply übersprungen. Commit, Run und Plan-Hash unabhängig geprüft. [Begleitende Validierung](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675895374) erfolgreich. + +### Resumption and acceptance (completed, details below) -Plattform-Jobs haben jetzt ein äußeres Zeitlimit von 100 Minuten. OpenTofu-Apply erhält maximal 70 Minuten und danach bis zu zehn Minuten zum geordneten Beenden; eine zusätzliche Gesamtlaufzeitgrenze des Skripts hält Puffer für Artefakte frei. 22 lokale Tests einschließlich Abbruchverhalten, verschlüsselter Diagnose und Recovery-Sperren sowie Workflow-Prüfung bestanden. +- [x] Check PostgreSQL final state through the API (`READY`); if provisioning remains stuck, request STACKIT service diagnostics using the instance ID from the local inventory. +- [x] Create a full inventory of all nine planned resources, including technical users and Model Serving token; protect IDs and credentials. +- [x] Perform state recovery through a dedicated, serialized CI path: import existing importable resources, rotate unrecoverable one-time credentials in a controlled manner. No duplicate creation or unchecked deletion. +- [x] Handle remaining lock only after checking that Runners have terminated and before controlled recovery; native S3 locking remains documented as unreliable. +- [x] Improve CI process control: timely orderly OpenTofu termination before the outer job time limit, protected diagnostics and encrypted recovery artifacts. Merely increasing the timeout does not repair missing state. +- [x] Review a fresh plan after recovery; only then re-enable platform CI and set new specific Apply approval. +- [x] Independently verify encrypted remote state, complete resources and subsequent no-op plan. +- [ ] Create CF runtime (space, apps, bindings, separate runtime identities) through IaC and test PostgreSQL/Secrets access from CF. -Nächster Ausbau: CF-Space und App-/Task-Runtime per IaC, getrennte Laufzeitidentitäten/Bindings und echte TLS-/Authentifizierungstests aus CF. Die Infrastrukturabnahme belegt noch keinen erfolgreichen App-Zugriff auf Datenbank oder Secrets Manager. + +## Successful recovery and platform acceptance +Commit `1843069ce6914c26d04a7461d0799fc1c58794d7`, [run 36675347654](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347654): recovery, Plan and Apply successful. [Validation run 36675347681](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675347681) also successful. -## CI-Vereinfachung 2026-09-30 +Six existing resources were imported without recreating instances, CF organization or artifact bucket. The orphaned Model Serving token was revoked. The freshly reviewed plan created the database, migration user and new Model Serving token; CF manager and Secrets provisioning user were replaced because their passwords had been lost. The PostgreSQL update concerned computed flavor metadata, with unchanged flavor ID and infrastructure parameters. -Die Workflows führen OpenTofu jetzt direkt aus. Der bisherige Deployment-Runner, Prozessmanager und automatische Einmal-Recovery-Pfad sind entfernt. Normale Plan-/Apply-Logs erscheinen live; Credential-Outputs und State-Snapshots bleiben gezielt geschützt. GNU `timeout` übernimmt SIGINT und die anschließende Wartezeit; keine eigene Signalsteuerung. Die geltenden Zeitlimits und Befehle stehen in der [CI-Betriebsanleitung](../infra/ci/README.md). Das historische Recovery-Inventar liegt unter `docs/incidents`, ohne aktive Ausführung. +Independent acceptance: +- [x] Encrypted state object present in the workload bucket; nine managed resources checked. +- [x] Both separate network ACLs match the planned networks. +- [x] PostgreSQL `READY`, database `configurator` with owner `configurator_migration` present. +- [x] CF organization active and Secrets Manager `Running`. +- [x] New technical users and exactly one new active Configurator Model Serving token confirmed in the API; old identities replaced. +- [x] Required passwords and token present in encrypted state without outputting values. +- [x] Protected diagnostics and state snapshot downloaded from GitHub; authenticated decryption and JSON integrity checked. +- [x] Both one-time variables `LZC_PLATFORM_RECOVERY_COMMIT` and `LZC_PLATFORM_APPLY_COMMIT` removed. Platform CI active again for Plan runs. +- [x] Confirm final plan without changes: [run 36675895279](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675895279), all nine resources `no-op`; recovery/Apply skipped. Commit, run and plan hash independently checked. [Accompanying validation](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36675895374) successful. -Abnahme der direkten CLI-Pipelines: Bootstrap-Run 36677111141 und Plattform-Run 36677111032 erfolgreich, jeweils `No changes`, Apply übersprungen. Die normalen Init-/Plan-Details sind live sichtbar. Logs gegen bekannte Deployment-Credentials und State-Schlüssel geprüft, keine Treffer. Validierung 36677111055 erfolgreich, einschließlich des GNU-Timeout-Tests in allen fünf Linux-Matrix-Jobs. Keine Infrastrukturänderung durch den Umbau. +Platform jobs now have an outer time limit of 100 minutes. OpenTofu Apply receives at most 70 minutes followed by up to ten minutes for orderly termination; an additional overall script runtime limit leaves a buffer for artifacts. 22 local tests, including termination behavior, encrypted diagnostics and recovery guards, and workflow checking passed. +Next expansion: CF space and app/task runtime through IaC, separate runtime identities/bindings and real TLS/authentication tests from CF. Infrastructure acceptance does not yet demonstrate successful app access to database or Secrets Manager. -Backend-Abnahme des Umbaus: [Run 36677367229](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677367229) hat Root `backend` mit getrennten Management-/Workload-Zugängen geplant: `No changes`, Apply übersprungen. Root, Commit, Run, Plan-Hash und verschlüsseltes Artefakt geprüft. Native Logs sichtbar und ohne bekannte Credential-Werte. [Validierung 36677367252](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677367252) erfolgreich. Temporäre Root-Auswahl entfernt; keine Apply-Freigaben gesetzt. Bootstrap, Backend und Plattform wurden damit lesend geprüft, ohne Cloud-Apply oder State-Migration durch den Umbau. + +## CI simplification 2026-09-30 +Workflows now run OpenTofu directly. The previous deployment Runner, process manager and automatic one-time recovery path have been removed. Normal Plan/Apply logs appear live; credential outputs and state snapshots remain specifically protected. GNU `timeout` handles SIGINT and the subsequent grace period; no custom signal control. Applicable time limits and commands are in the [CI operations guide](../infra/ci/README.md). The historical recovery inventory is under `docs/incidents`, without active execution. -## CF-Runtime und erster App-Release (2026-09-30) +Acceptance of the direct CLI pipelines: bootstrap run 36677111141 and platform run 36677111032 successful, both `No changes`, Apply skipped. Normal init/plan details are visible live. Logs checked against known deployment credentials and state keys, no matches. Validation 36677111055 successful, including the GNU timeout test in all five Linux matrix jobs. No infrastructure change from this restructuring. -- [x] Separater Runtime-Root mit verschlüsseltem S3-State und Cloud-Foundry-Provider 1.17.0. -- [x] Space `configurator`, explizite `organization_user`-Mitgliedschaft und `space_developer`-Rolle erstellt. -- [x] Eigene PostgreSQL-Login-Rolle `configurator_app` und Secrets-Manager-Benutzer mit Read-only-Recht. -- [x] [Runtime-Apply 36681789484](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36681789484) erfolgreich; fünf Ressourcen unabhängig im verschlüsselten Remote-State bestätigt. -- [x] Web/API über getrennten Release-Workflow mit direkten `cf`-Befehlen bereitgestellt; Model-Serving-Token nur im Backend-Environment. -- [x] [Release 36682016739](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36682016739): Build und CF-Push erfolgreich, Anwendung gestartet. Native CLI-Logs auf bekannte Credential-Werte geprüft: keine Treffer. -- [ ] PostgreSQL-Verbindung: erster CF-Task scheitert nach 15 Sekunden; Netz-/TCP-Diagnose folgt. -- [ ] Secrets Manager: erster CF-Task erhält HTTP 403 beim Login; laut [STACKIT-Diagnose](https://docs.stackit.cloud/products/security/secrets-manager/how-tos/handle-authentication-lockouts/) Hinweis auf Quell-IP-ACL. +Backend acceptance of the restructuring: [run 36677367229](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677367229) planned root `backend` with separate management/workload credentials: `No changes`, Apply skipped. Root, commit, run, plan hash and encrypted artifact checked. Native logs visible and free of known credential values. [Validation 36677367252](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677367252) successful. Temporary root selection removed; no Apply approvals set. Bootstrap, backend and platform have thus been checked read-only, without cloud Apply or state migration from the restructuring. -Der erste Runtime-Apply erstellte Space und Benutzer, scheiterte aber an der fehlenden -CF-Organisationsmitgliedschaft. Der State blieb vollständig erhalten. Ein frischer -Plan ergänzte ausschließlich die zwei noch fehlenden Rollen; kein Import oder -Credential-Reset war erforderlich. + +## CF runtime and first app release (2026-09-30) -Die CF-Foundation erlaubt öffentliche Ziele in ihrer globalen `public_networks`- -Security-Group. Das ist noch kein Nachweis für den jeweiligen Dienstpfad. Die bisher -verwendeten zwei STACKIT-Netze decken außerdem nicht den aktuellen öffentlichen -Adresskatalog ab. Die offizielle API `GET /v2/networks/public-ip-ranges` liefert -regionale Netze; Änderungen werden anhand des realen CF-Tests und eines neuen -IaC-Plans beurteilt. Keine beobachtete Einzel-IP wird als stabiler CF-Egress zugesagt. -Quelle für den aktuellen Katalog: [STACKIT IP-Ranges](https://docs.stackit.cloud/products/logging-and-monitoring/logme/how-tos/create-and-manage-logme-services/). +- [x] Separate runtime root with encrypted S3 state and Cloud Foundry provider 1.17.0. +- [x] Space `configurator`, explicit `organization_user` membership and `space_developer` role created. +- [x] Dedicated PostgreSQL login role `configurator_app` and Secrets Manager user with read-only permission. +- [x] [Runtime Apply 36681789484](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36681789484) successful; five resources independently confirmed in encrypted remote state. +- [x] Web/API deployed through separate release workflow with direct `cf` commands; Model Serving token only in backend environment. +- [x] [Release 36682016739](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36682016739): build and CF push successful, application started. Native CLI logs checked for known credential values: no matches. +- [ ] PostgreSQL connection: first CF task fails after 15 seconds; network/TCP diagnostics to follow. +- [ ] Secrets Manager: first CF task receives HTTP 403 at login; according to [STACKIT diagnostics](https://docs.stackit.cloud/products/security/secrets-manager/how-tos/handle-authentication-lockouts/), an indication of a source-IP ACL. +The first runtime Apply created the space and users but failed because CF organization membership was missing. State remained fully intact. A fresh plan added only the two missing roles; no import or credential reset was required. -### Nachgewiesener ACL-Fehler und Korrekturplan +The CF foundation permits public targets in its global `public_networks` security group. This is not yet evidence for each service path. Furthermore, the two STACKIT networks used so far do not cover the current public address catalogue. The official API `GET /v2/networks/public-ip-ranges` returns regional networks; changes are assessed using the real CF test and a new IaC plan. No observed individual IP is promised as stable CF egress. Source for the current catalogue: [STACKIT IP ranges](https://docs.stackit.cloud/products/logging-and-monitoring/logme/how-tos/create-and-manage-logme-services/). -Der Diagnose-Task in [Release 36682707060](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36682707060) -löst den PostgreSQL-Host korrekt auf, bekommt aber keine TCP-Verbindung. Ein -HTTPS-Aufruf desselben CF-Tasks zur eigenen Configurator-Route liefert HTTP 200; -der zugehörige CF-Router-Logeintrag zeigt eine Quelle aus `45.135.244.0/22`. -Dieses eu01-Netz ist im aktuellen STACKIT-IP-Katalog enthalten und wird auch in -der [STACKIT LogMe-FAQ](https://docs.stackit.cloud/products/logging-and-monitoring/logme/faq/) -als STACKIT-Standardnetz aufgeführt. Es fehlte in beiden expliziten ACLs. + +### Demonstrated ACL error and correction plan -Der neue IaC-Plan ergänzt deshalb genau `45.135.244.0/22` in den getrennten -PostgreSQL- und Secrets-ACLs. Die beobachtete Einzel-IP wird nicht konfiguriert. -Dies bleibt eine Freigabe eines geteilten STACKIT-Netzes, keine mandanteneigene -oder zugesichert stabile CF-Ausgangsadresse. TLS, Benutzerrechte und spätere -Mandantenautorisierung bleiben separate Schutzschichten. Bei Netzänderungen -Katalog und CF-Test erneut prüfen; kein automatisches Öffnen weiterer Netze. +The diagnostic task in [release 36682707060](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36682707060) resolves the PostgreSQL host correctly but cannot establish a TCP connection. An HTTPS call from the same CF task to its own Configurator route returns HTTP 200; the corresponding CF router log entry shows a source from `45.135.244.0/22`. This eu01 network is in the current STACKIT IP catalogue and is also listed as a STACKIT standard network in the [STACKIT LogMe FAQ](https://docs.stackit.cloud/products/logging-and-monitoring/logme/faq/). It was missing from both explicit ACLs. +The new IaC plan therefore adds exactly `45.135.244.0/22` to the separate PostgreSQL and Secrets ACLs. The observed individual IP is not configured. This remains an allowance for a shared STACKIT network, not a tenant-owned or guaranteed stable CF outbound address. TLS, user permissions and subsequent tenant authorization remain separate protection layers. When networks change, recheck the catalogue and CF test; no automatic opening of further networks. -## Abnahme CF-Hosting und Dienstverbindungen abgeschlossen + +## CF hosting and service-connection acceptance completed -[Release 36683898762](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898762) -auf Commit `795a18a`: **vollständig erfolgreich**. -[Validierung 36683898795](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898795) -ist ebenfalls erfolgreich (App mit neun Tests und alle sechs IaC-Roots). +[Release 36683898762](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898762) on commit `795a18a`: **fully successful**. [Validation 36683898795](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683898795) also successful (app with nine tests and all six IaC roots). -- [x] [ACL-Apply 36683137454](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683137454): zwei In-place-Updates, keine Neuanlage/Löschung. Beide Dienst-ACLs unabhängig im verschlüsselten Remote-State geprüft. -- [x] App `landing-zone-configurator` im Space `configurator` gestartet; deklaratives Manifest unter `deploy/cloud-foundry/`. -- [x] PostgreSQL: DNS und TCP erreichbar, Laufzeitbenutzer authentifiziert, `SELECT 1` und `pg_stat_ssl` erfolgreich, Zertifikats-/Hostname-Prüfung aktiv. -- [x] Secrets Manager: TLS und Userpass-Login erfolgreich; reservierter KV-Pfad verweigert anonymen Zugriff und akzeptiert den authentifizierten Aufruf; Sitzungstoken danach widerrufen. -- [x] CF-Tasks `network-36683898762` und `connections-36683898762` sind `SUCCEEDED`. -- [x] HTTPS-Startseite und JavaScript-Asset ausgeliefert; `/healthz` HTTP 200, `/api/v1/session` HTTP 401. -- [x] Alle zehn Backend-Variablen mit verschlüsselten Runtime-Ausgaben verglichen; keine Projekt-/S3-/CF-Deployment-Credentials in der App. -- [x] Erfolgreiche Runtime-/ACL-/Release-Logs auf bekannte Schlüssel, Passwörter und Token geprüft, ohne Treffer. -- [x] Einmalige Runtime-/Plattform-Apply-Variablen entfernt; Feature-Branch beibehalten, kein Merge nach main. +- [x] [ACL Apply 36683137454](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36683137454): two in-place updates, no creation/deletion. Both service ACLs independently checked in encrypted remote state. +- [x] App `landing-zone-configurator` started in space `configurator`; declarative manifest under `deploy/cloud-foundry/`. +- [x] PostgreSQL: DNS and TCP reachable, runtime user authenticated, `SELECT 1` and `pg_stat_ssl` successful, certificate/hostname verification active. +- [x] Secrets Manager: TLS and userpass login successful; reserved KV path denies anonymous access and accepts the authenticated call; session token subsequently revoked. +- [x] CF tasks `network-36683898762` and `connections-36683898762` are `SUCCEEDED`. +- [x] HTTPS home page and JavaScript asset served; `/healthz` HTTP 200, `/api/v1/session` HTTP 401. +- [x] All ten backend variables compared with encrypted runtime outputs; no project/S3/CF deployment credentials in the app. +- [x] Successful runtime/ACL/release logs checked for known keys, passwords and tokens, without matches. +- [x] One-time runtime/platform Apply variables removed; feature branch retained, no merge to main. -Der Secrets Manager unterstützt nicht die allgemeine Vault-System-API -`sys/capabilities-self` (im Test HTTP 404). Der endgültige Test nutzt den -[dokumentierten KV-Lese-Endpunkt](https://docs.stackit.cloud/products/security/secrets-manager/how-tos/cli-and-api/) -mit anonymem Negativtest. Für den absichtlich nicht angelegten Operator-Probe-Key -ist authentifiziertes HTTP 404 zulässig; HTTP 404 auch ohne Token würde den Test -fehlschlagen lassen. Es werden weder Kunden-Secrets gelesen noch Probe-Secrets -angelegt. **Ein Secret-Write/Read-Roundtrip, Mandantenautorisierung und Rotation -sind damit noch nicht abgenommen.** Die Laufzeitidentität ist in IaC read-only. +Secrets Manager does not support the general Vault system API `sys/capabilities-self` (HTTP 404 in the test). The final test uses the [documented KV read endpoint](https://docs.stackit.cloud/products/security/secrets-manager/how-tos/cli-and-api/) with an anonymous negative test. For the deliberately uncreated operator probe key, authenticated HTTP 404 is permitted; HTTP 404 without a token would also cause the test to fail. No customer secrets are read and no probe secrets are created. **A secret write/read roundtrip, tenant authorization and rotation have not yet been accepted.** The runtime identity is read-only in IaC. -Dev-Adresse: [lzc-dev Configurator](https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud). -Die kurze Route wird mit dem naechsten Release eingerichtet; die Live-Umstellung -und die aktualisierten OAuth-Callbacks muessen danach separat geprueft werden. -Dies ist das technische App-Grundgerüst. GitHub-Login, persistentes Mandantenschema, -Template-Editor, persönliche Credentials, Kunden-Plan/Apply und Chat folgen in der -[aktuellen MVP-Checkliste](planning.md#aktueller-meilenstein-cf-hosting-und-service-verbindungen). +Dev address: [lzc-dev Configurator](https://lzc-dev-configurator.apps.01.cf.eu01.stackit.cloud). The short route will be set up with the next release; the live switch and updated OAuth callbacks must then be checked separately. This is the technical app skeleton. GitHub login, persistent tenant schema, template editor, personal credentials, customer Plan/Apply and chat follow in the [current MVP checklist](planning.md#aktueller-meilenstein-cf-hosting-und-service-verbindungen). -Die stehende Benutzerfreigabe für notwendige Configurator-Applies gilt bis MVP; -Planprüfung, Environment-Schutz und die gemeinsame CI-Concurrency bleiben aktiv. +Standing user approval for necessary Configurator Applies is valid until MVP; plan review, environment protection and shared CI concurrency remain active. diff --git a/landing-zone-configurator/docs/project-template-drafts.de.md b/landing-zone-configurator/docs/project-template-drafts.de.md new file mode 100644 index 0000000..e1bd9c5 --- /dev/null +++ b/landing-zone-configurator/docs/project-template-drafts.de.md @@ -0,0 +1,379 @@ + + +# Plattformkonfiguration und Projekt-Template-Entwürfe + +[English](project-template-drafts.md) | [Deutsch](project-template-drafts.de.md) + +Stand: 2026-10-09. Bestell-, Plan-, Apply-, Destroy- und Drift-Ablauf. + + + +## Application-Destroy und Drift + +Die Bestelldetails bieten **Destroy** und **Drift**, wenn das aktive, qualifizierte +Application-Runner-Paket diese Operationen explizit unterstuetzt. Bestehende +Template-Versionen, Bestellungen, Sources, Artefakte und State-Keys bleiben +unveraendert. Beide Aktionen verwenden den S3-State derselben Application-Instanz. + +**Destroy-Plan erstellen** erzeugt mit `tofu plan -destroy` einen gespeicherten +Loeschplan. Nach Pruefung der Ressourcen und separater Loeschbestaetigung wird +genau dieses Binary angewendet, nicht ein neu berechneter Plan. Die API bindet +die Bestaetigung an Instanz und Artefakt-Hash; ein Plan-/Reiterwechsel setzt die +UI-Bestaetigung zurueck. Anlegen, Aendern, Ersetzen und Ordnerloeschung bleiben +gesperrt. Abschlussstatus und redigierte Ausfuehrungslogs stehen im Destroy-Reiter. +Nach erfolgreichem Destroy kann die Bestellung separat archiviert werden; +State, Artefakte und Audit-Historie bleiben dabei erhalten. Provider-seitige +Projektloeschung kann weiterhin eine nachgelagerte Purge-Phase haben. + +**Drift pruefen** erstellt einen lesenden Plan mit explizitem Refresh und zeigt +zwei getrennte Vergleiche: gespeicherter State gegen Cloud sowie Cloud gegen die +unveraenderlich bestellte Soll-Konfiguration. Sensible Attribute werden maskiert. +Die Pruefung kann weder im UI noch ueber API/Worker angewendet werden. Erfasst +werden nur Ressourcen dieses Application-States, nicht beliebige zusaetzliche +Ressourcen im Projekt. Drift ist daher keine vollstaendige Cloud-Inventarisierung. + +Aktuelle Besteller-/IAM-/Gruppenrechte, technische Delegation, passendes +Runner-Paket und State-Locking bleiben erforderlich. Aktive Ausfuehrungen und +ungeklaerter Recovery-State sperren Maintenance. Ein abgeschlossenes +`reconciliation_required` mit abgelaufenem Ticket und ohne Recovery-Beleg erlaubt +gezielt Destroy/Drift, aber keinen normalen Apply-Neustart. Der alte Abschluss +wird dabei weder veraendert noch als Erfolg interpretiert. Fuer archivierte +Bestellungen besteht weiterhin keine Ausfuehrungsmoeglichkeit. + + + +## Observability ohne ACL-Parameter + +Die ACL-Einrichtung ist im MVP vollständig benutzerverwaltet und nicht Teil +von Editor, Bestellung oder automatischer Ressourcenverknüpfung. Observability +kann ohne ACL-Pflichteingaben und ohne ungeklärte Egress-Bindung aktiviert +werden. Gespeicherte feste ACL-Werte werden nicht gelöscht. Die neue native +Application-Revision schützt spätere ACL-Änderungen durch `ignore_changes`. +Details und Provider-Grenzen stehen im +[aktuellen Parametervertrag](template-parameters-and-bindings.de.md). + +Bereits veröffentlichte Versionen bleiben unverändert an ihre alte Quelle +gebunden. Für den neuen Runner ist eine neue Veröffentlichung und Bestellung +nötig; bestehende Aufträge und Plan-Artefakte werden nicht umgeschrieben. + + + +## Application-Bestellung, Vorschau und Apply + +Eine Bestellung ohne angeforderten Apply kann auch nach einem erfolgreichen +oder fehlgeschlagenen, abgeschlossenen Plan gelöscht werden. Laufende oder +ungeklärte Ausführungen und jede Apply-Anforderung sperren das Löschen weiterhin. +Die Löschung entfernt die Bestellung aus dem Self-Service; Job-Historie und +verschlüsselte Plan-Artefakte bleiben unverändert erhalten. Danach kann kein +Apply mehr aus diesen Plans gestartet werden. Löschen ist kein Cloud-Destroy. + +Bei einer direkt freigegebenen Template-Version mit aktiver Execution-Delegation +startet **Bestellen** unmittelbar den Cloud-Plan. Separate Bestätigungen für +Plan-Vorbereitung und Plan-Start entfallen. Eine fachliche Bestellfreigabe bleibt +nur bei `approval-required` notwendig; danach startet der Application Owner den +Plan mit einem Klick. Die Bestellung bleibt auch bei einem fehlgeschlagenen +Plan-Start erhalten und kann ohne erneute Bestellung weiterbearbeitet werden. + +Ein erfolgreicher Plan liefert eine Ressourcen-Vorschau aus dem verschlüsselten, +gespeicherten Plan-Artefakt: Ressourcentyp, konkrete Änderung und zugelassene +Eigenschaften wie Projektname, Region oder Netzwerk-CIDR. Sensible Werte werden +maskiert; unbekannte Werte werden als erst nach Apply bekannt angezeigt. Rohes +Plan-JSON, Secrets und dynamische Ressourcenadressen werden nicht ausgegeben. + +**Application Landing Zone erstellen** startet mit einem Klick den Apply genau +dieses gespeicherten Plans, ohne weitere Checkbox oder Freigabeschleife. Hash, +Runner-Paket, Bestellung, aktueller Plan und Execution-Delegation werden erneut +geprüft. Der Plan muss innerhalb einer Stunde erstellt worden sein; derselbe +Plan kann nur einmal angewendet werden. Für Apply wird eine neue, kurzlebige +Runner-Berechtigung erzeugt, nicht die Plan-Berechtigung wiederverwendet. + +Apply läuft niemals automatisch. Ein möglicherweise teilweise ausgeführter +Apply wird als `reconciliation_required` gesperrt und nicht automatisch erneut +gestartet. Die Vorschau und damit Apply sind aktuell für den qualifizierten +lokalen Runner verfügbar; ein Runner ohne sichere Saved-Plan-Inspektion meldet +Apply als deaktiviert. Frühere Hinweise auf einen reinen Plan-Pfad oder einen +noch fehlenden Application-Apply sind durch diesen Stand überholt. + + + +## Fachlicher Ablauf + +Der Platform Engineer definiert zentrale Plattformdienste und die dafür nötigen +Infrastrukturprojekte. Im Schritt **Projekt-Templates** erstellt er Vorlagen für +spätere Anwendungsprojekte. Die Plattformkonfiguration erzeugt diese Projekte +nicht selbst. Der Application Owner bestellt später eine Instanz einer +veröffentlichten Template-Version im separaten Application-Self-Service. + +Neue Entwürfe aus allen acht Accelerator-Vorlagen nutzen diesen Ablauf. +`landing_zones`, `sandboxes` und `landing_zone_namespace_services` aus den +Beispielen werden zu Template-Entwürfen. Plattform, Connectivity, Governance, +zentrale Dienste und deren Projekte bleiben Teil der Plattformkonfiguration. +Die Vorschau zeigt Plattformressourcen und Template-Entwürfe getrennt. + +Ein Template enthält eine eigene ID und Kennung, Anzeigenamen, Projektart +(Public/Corporate/Sandbox), Region sowie die festen Modul-/Service-Einstellungen. +Corporate-Templates referenzieren eine SNA ihrer Region. Die Projektart bestimmt +die Ordnerrolle. Secrets Manager und Observability können als automatisch +bereitzustellende Dienste vorgegeben werden; weitere unterstützte Modulwerte +bleiben erhalten. Dies beschreibt ein Anwendungsprojekt mit Basisdiensten, noch +kein eigenständiges VM- oder Kubernetes-Workload-Angebot. + +Konkreter Projektname und Projektkürzel gehören zur späteren Bestellung. Der +Projektverantwortliche muss serverseitig aus einer verifizierten STACKIT-Identität +kommen. Feste zusätzliche Administratorzuweisungen (z. B. Sandbox `owner_emails`) +sind davon getrennte Plattformpolicy; Beispieladressen müssen vor Speicherung +bereinigt werden. Namespace-Service-Einstellungen werden als Template-Metadaten +erhalten. Das ist keine Freigabe ihrer späteren Clusteranbindung/Ausführung. + + + +## Template-Eingaben und Verknüpfungen + +Die bisherigen festen Einstellungen sind noch kein vollständiger Template-Vertrag. +Stage soll normalerweise eine begrenzte Bestelleingabe sein; Dienstbeziehungen +wie „Observability nur aus eigenem Projektnetz“ brauchen typisierte Bindungen. +[Wertquellen, Instanziierung und Umsetzungsplan](template-parameters-and-bindings.de.md). +Parameter-Policy, fünf freigegebene Felder und lokale Bestellvorschau sind implementiert. Veröffentlichung, weitere Feldbindungen und echte Bestellungen bleiben offen. + + + +## Speicherung und Export + +Das bisherige Dokumentformat v3 besitzt nun optional `projectTemplates`. + +- Ohne das Feld bleibt es eine bisherige Gesamtkonfiguration mit konkreten Projekten. +- Mit dem Feld ist es ein Plattformentwurf; auch eine leere Liste kennzeichnet diesen Modus. +- Plattformentwürfe dürfen keine konkreten `landing_zones`, `sandboxes` oder + `landing_zone_namespace_services` enthalten. Mischformen werden beim Einlesen, + Speichern und Exportieren abgewiesen. +- Template-Einstellungen werden gegen den bestehenden Accelerator-Eingabevertrag + geprüft; konkrete Instanz-/Owner-Felder sind in den Template-Einstellungen verboten. +- Das JSON im persönlichen Fork erhält die Template-Entwürfe. Der deterministische + tfvars-Export enthält nur die Plattform und explizit leere Anwendungssammlungen. +- Erstbereitstellungspläne für erlaubte Plattform-Teilkonfigurationen planen daher + **nur die Plattform**, keine Template-Instanzen. Die übrigen Runner-Sperren bleiben wirksam. + +Das optionale Feld erhält die Lesbarkeit alter Dokumente ohne automatische +Umdeutung. Die Veröffentlichung bekommt später einen eigenen tenantgebundenen, +unveränderlichen Versionsvertrag; ein editierbarer Fork-Entwurf ist keine +veröffentlichte Version und keine Bereitstellungsberechtigung. + + + +## Bestehende Konfigurationen + +Der bisherige Projekteditor ist für vorhandene Dokumente unter **Projekte (Bestand)** +weiter verfügbar. Neue Konfigurationen werden nicht mehr über den alten +Standalone-Erstellungsbutton angelegt. + +**Als neue Plattformkonfiguration übernehmen** erstellt nach ausdrücklicher +Bestätigung eine Kopie mit neuer Konfigurations-ID. Die Fork-Verknüpfung wird auf +Neuanlage zurückgesetzt; der bestehende Datensatz wird nicht überschrieben. +Namespace-Einstellungen ohne zugehöriges Quellprojekt blockieren die Kopie, +statt verloren zu gehen. SNA-Referenzen aus Templates verhindern das versehentliche +Entfernen des referenzierten Bereichs. + +Das ist ausschließlich eine Konfigurationskopie. Es ist keine State-Migration, +kein Import bestehender Ressourcen und keine Anweisung, die Plattform parallel +neu auszurollen. Bereits bestehende Ressourcen benötigen den separat geplanten +Migrations-/State-Lebenszyklus. + + + +## Bestellfreigabe (2026-10-07) + +Unter **Application Landing Zones > Bestellungen > Details anzeigen** kann ein +Platform Engineer eine fremde Bestellung mit `approval-required` freigeben oder +ablehnen. Die Entscheidung muss ausdruecklich bestaetigt werden; fuer eine +Ablehnung ist eine Begruendung erforderlich. Selbstfreigaben sind gesperrt. + +Migration 040 speichert Entscheidung, Entscheider, Zeitpunkt und Begruendung als +unveraenderlichen, tenantgebundenen Nachweis. Wiederholungen derselben Entscheidung +liefern denselben Nachweis; eine widerspruechliche Entscheidung wird abgewiesen. +Der Besteller sieht den Status und die Begruendung seiner eigenen Bestellung. +Bestehende Bestellungen ohne Nachweis bleiben ausstehend; bei `direct` ist keine +Bestellfreigabe erforderlich. Die veroeffentlichte Template-Version bleibt erhalten. + +Die fachliche Freigabe startet weder einen Runner noch einen Cloud-Plan oder Apply. +Die Runner-Aktivierung erfolgt separat. Neue Jobs, Credential-Grants, +Claims, Dispatches und Runner-Tickets fuer freigabepflichtige Bestellungen werden +ohne positiven Entscheidungsnachweis auch in der Datenbank gesperrt. Bestehende +Credential-, Backend-, Identitaets- und Ausfuehrungspruefungen bleiben erhalten. + +Qualifiziert mit echten PostgreSQL-Rollen-/Tenant-Tests und Desktop-/Mobil- +Browserfaellen. Ein privater Restore des lokalen Schemas 039 wurde zweimal nach 040 +migriert; alle 37 bisherigen Fach-/Auth-Tabellen blieben unveraendert. + + + +## Application-Plan im UI (2026-10-07) + +Nach einer Bestellfreigabe kann der Besteller in den Bestelldetails die +**Plan-Vorbereitung bestaetigen** und **Plan vorbereiten**. Das erzeugt einen +kurzlebigen, idempotenten Plan-Job fuer die eigene Bestellung; es startet keinen +Runner und fuehrt keinen Cloud-Plan aus. + +Der im Plattformvertrag gebundene technische Platform Engineer sieht diesen Job +in denselben Bestelldetails. Er waehlt ein bereits registriertes **State-Backend** +und bestaetigt dessen Freigabe. Der State-Key bleibt der unveraenderliche +Application-Instanz-Key, nicht der Plattform-State-Key. Ein separater Klick nach +**Cloud-Plan bestaetigen** startet den isolierten Application-Plan-Runner. +Die technische Freigabe und der Start bleiben an dieselbe Sitzung gebunden. + +Die UI liest die wirkliche Server-Capability statt die bei Bestellung gespeicherten +Sperrhinweise als aktuellen Runner-Status zu behandeln. Laufende Jobs werden +aktualisiert. Reloads loesen keine Mutationen aus. Ein verlorener Prepare-Response +oder ein Fehler beim anschliessenden Statusabruf verwendet beim Retry denselben +Idempotenzschluessel. Abgelaufene Jobs koennen neu vorbereitet werden. + +Migration 041 ergaenzt ausschliesslich SELECT-Sichtbarkeit fuer den bereits +gebundenen technischen Freigeber. Fremde Tenants und ungebundene Platform Engineers +erhalten keine Jobs; die INSERT-, Credential-, Backend- und Dispatch-Gates bleiben +erhalten. Die Job-Liste enthaelt keine Schluessel, rohen States, Planartefakte oder +Runner-Ausgaben, sondern Status und die validierte Plan-Zusammenfassung. + +Lokal ist das separat qualifizierte Application-Paket ueber +`LZC_APPLICATION_EXECUTION_ENABLED=true` und +`LZC_APPLICATION_RUNNER_PACKAGE_DIR` angebunden. Das vorhandene Plattform-Paket +bleibt unveraendert. **Application-Apply ist noch nicht implementiert**: +`applyEnabled=false`, keine automatische Erstellung nach Bestellfreigabe oder +erfolgreichem Plan. Ein echter Cloud-Plan wurde durch diesen Rollout nicht gestartet. + +Qualifikation: 31 echte PostgreSQL-Tests, 16 neue Desktop-/Mobile-Plan-Faelle, +vollstaendiger Organisations-Browserlauf mit 60 Faellen vor dem zusaetzlichen +GET-Ausfall-Test und 412 kanonische Unit-Tests bestanden. Ein privater Restore von +040 wurde zweimal nach 041 migriert; alle 38 bestehenden Tabellen blieben dabei +inhaltlich unveraendert. Im laufenden lokalen Rollout blieb die Bestellentscheidung +erhalten; eine normale erneute Anmeldung ergaenzte eine Sitzung und erneuerte nur +Verifikationszeit und Gueltigkeit der bestehenden STACKIT-Identitaet. + + + +## Aktueller Katalogstand (2026-10-06) + +Tenantgebundene Veroeffentlichung, unveraenderliche Versionen, freigegebene +Anwendereingaben und forklose Application-Owner-Bestellungen sind implementiert. +Platform Engineer waehlen beim Publizieren `approval-required` (Standard) oder +`direct`. Die Policy gehoert zur unveraenderlichen Version und wird serverseitig +in die Bestellung uebernommen; eine Policy-Aenderung erzeugt eine neue Version. +Clients koennen sie bei Bestellung oder Plan-Input nicht ueberschreiben. + +Eine ausdruecklich bestaetigte Stilllegung erzeugt einen unveraenderlichen, +idempotenten Nachweis. Stillgelegte Versionen verschwinden aus der AO-Auswahl; +neue Bestellungen werden auch serverseitig gesperrt. Bestehende Instanzen und +idempotente Bestellwiederholungen bleiben erhalten. Parallel laufende Bestellung +und Stilllegung verwenden dieselbe transaktionale Sperre. Erneutes Publizieren +stillgelegter Inhalte erzeugt eine neue Version statt die alte wiederzubeleben. + +Die zweisprachige Publisher-Oberflaeche nutzt explizite API-Capabilities. Die +laufende Kunden-API verwendet Migrationen bis 034. Gruppenfreigaben aus +Migration 035 sind auf einer isolierten Testdatenbank qualifiziert, aber noch +nicht in der Kunden-API aktiviert. `direct` aktiviert weder Cloud-Ausfuehrung noch einen +automatischen Apply; eine ausdrueckliche Kunden-Apply-Freigabe bleibt erforderlich. + + + +### Gruppenfreigaben + +Jeder Arbeitsbereich erhaelt automatisch die Default-Gruppe `Application Owners`. +Application Owner werden beim Beitritt oder Rollenwechsel automatisch aufgenommen; +bei Rollenentzug werden ihre Gruppenmitgliedschaften entfernt. Die Default-Gruppe +kann nicht manuell bearbeitet werden. Bestehende Veroeffentlichungen werden bei +Migration 035 dieser Gruppe zugeordnet; Versionsinhalte, Quellen und Instanzen +bleiben unveraendert. + +Gruppenanlage und Mitgliedschaftsaenderungen erfordern die aktuelle +Mitgliederverwaltungsberechtigung des Arbeitsbereichs. Custom-Gruppen nehmen nur +Application Owner desselben Arbeitsbereichs auf. Platform Engineers waehlen die +Freigabegruppen beim Veroeffentlichen oder bestaetigen eine separate Aenderung der +Freigaben einer vorhandenen Version. Eine leere Freigabeliste sperrt die Version +fuer Application Owner, ohne deren Instanzen oder State zu loeschen. + +Gruppenfreigaben sind auditierte Nutzungsrechte, kein Bestandteil der +unveraenderlichen Versionsinhalte. AO-Katalog und neue Bestellungen werden +serverseitig gefiltert. Aktuelle Rechte werden auch vor Jobvorbereitung, +Backend-Freigabe, Grant-Claim und Runner-Ticket-Verbrauch sowie vor und nach dem +Secret-/Backend-Zugriff geprueft. Gruppenentzug waehrend eines Credential-Zugriffs +verhindert die Rueckgabe des Secrets. AO erhalten weder Gruppenverwaltung noch +technische Credentials. API-Mutationen erfordern Tenantbindung, Origin und CSRF. + +Die UI aktiviert diese Controls nur mit `groupAccessEnabled`. Tests pruefen +Default-Mitgliedschaft, eingeschraenkte Gruppen, fremde Nutzer, direkte +SQL-Claims/Tickets, Entzug waehrend Secret-Zugriff und Desktop-/Mobil-Bedienung. +Dies ist noch keine Abnahme von Application-Plan/Apply, Drift oder Upgrades. + + + +## Noch offen + + + +### Neue Runner-Bindung und Loeschung vor Ausfuehrung (2026-10-07) + +Neue Template-Versionen koennen die vom Application-Dienst angebotene +qualifizierte Accelerator-Revision verwenden. Die Veroeffentlichung zeigt die +Revision und erfordert eine ausdrueckliche Bestaetigung fuer jede neue Version. +Bestehende Versionen und Bestellungen werden niemals automatisch umgebunden. +Nicht unterstuetzte Bestandsrevisionen erhalten beim Planversuch eine konkrete +Fehlermeldung statt eines scheinbaren Dienstausfalls. + +Besteller koennen eigene, Platform Engineers die sichtbaren Bestellungen ihres +Arbeitsbereichs mit ausdruecklicher Bestaetigung loeschen. Voraussetzung ist, +dass noch kein Dispatch, Runner-Ticket oder Credential-Claim existiert. +Vorbereitete Jobs und Backend-Freigaben allein verhindern die Loeschung nicht; +nach der Loeschung duerfen sie jedoch nicht mehr ausgefuehrt werden. + +Migration 042 ergaenzt einen unveraenderlichen, tenantgeschuetzten Loeschvermerk. +Die Bestellung verschwindet aus der Liste; Versionsinhalte, Freigaben und +Idempotenzhistorie bleiben erhalten. Replays erzeugen keine neue Bestellung. +Gemeinsame Zeilensperren serialisieren Loeschung und Ausfuehrungsfreigaben. +Es werden weder Cloud-Ressourcen noch Terraform-State geloescht. Der Umgang +mit bereits ausgefuehrten Bestellungen und Application-Apply bleibt offen. + +[#92](https://github.com/stackitcloud/stackit-landing-zone/issues/92) bleibt fuer +die produktive Veroeffentlichungsabnahme unter autoritativ verifizierter +Tenantbindung offen. Private Entwuerfe werden nicht im AO-Katalog angezeigt. + +[#91](https://github.com/stackitcloud/stackit-landing-zone/issues/91) und +[#93](https://github.com/stackitcloud/stackit-landing-zone/issues/93) liefern die +verifizierte Organisations-/Benutzerbindung und Instanziierung mit eigenem State. +Die bisherige Sperre für Kunden-Apply bleibt bestehen. + + + +### Delegierte Application-Plan-Ausfuehrung (2026-10-08) + +Der Platform Owner richtet im Publikationsbereich einmal pro freigegebenem +Plattformvertrag die Ausfuehrung mit einem registrierten State Backend ein. +Die Berechtigung bindet unveraenderlich den Service Account des Vertrags, +Credential-Version und Key-ID sowie Backend-Identitaet und verschluesselte +Backend-Credentials. Bestehende Vertraege erhalten keine automatische Delegation. + +Neue Plan-Jobs einer dazu gebundenen Template-Version uebernehmen diese +Berechtigung und den instanzspezifischen State-Key. Der Application Owner startet +den Plan explizit selbst, ohne zweite technische Backend-Freigabe und ohne aktive +Platform-Owner-Sitzung. Bei `approval-required` bleibt zuvor die fachliche +Bestellfreigabe erforderlich; `direct` benoetigt sie nicht. Alte Jobs und +Template-Versionen werden nicht nachtraeglich umgebunden. + +Der Platform Owner kann die Berechtigung widerrufen. Vor weiteren Runner-Zugriffen +werden aktuelle Rollen, Bestelleridentitaet, Gruppenfreigabe, Credential- und +Backend-Bindung erneut geprueft. Eine neue Delegation reaktiviert keine alten Jobs. +Secret und Backend-Credentials bleiben serverseitig und werden nur einmal an den +gebundenen Runner ausgegeben. Neue Publikationen uebernehmen die angebotene, +qualifizierte Runner-Revision ohne zusaetzliche Pflicht-Checkbox. + +Application-Apply bleibt unimplementiert. Ein erfolgreicher Plan erzeugt keine +Cloud-Ressourcen und ist keine Apply-Freigabe. + + + +## Prüfungen + +- [x] Alle acht Quellvorlagen werden ohne Verlust von Plattform-/Projektpolicy konvertiert. +- [x] Persönliche Instanzfelder gelangen nicht in Projektvorlagen. +- [x] Legacy-Dokumente bleiben beim Einlesen unverändert; Kopien benötigen eine neue ID. +- [x] Git-Speicherung erhält Metadaten; tfvars und Deployment-Vorbereitung enthalten keine daraus erzeugten Projekte. +- [x] Gemischte Template-/Instanzdokumente werden abgewiesen. +- [x] Native OpenTofu-Variablenprüfung bestätigt leere Anwendungs-, Sandbox- und Namespace-Sammlungen im Plattformexport. +- [x] Browserprüfung einschließlich Bestandskopie/Speicherung erfolgreich; CI-Validierung und [Release 36855011827](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36855011827) für `0e62c5e` erfolgreich. Live-SPA liefert HTTP 200 mit dem erwarteten Bundle `index-bjLShEoG.js`. diff --git a/landing-zone-configurator/docs/project-template-drafts.md b/landing-zone-configurator/docs/project-template-drafts.md index 25835db..039286b 100644 --- a/landing-zone-configurator/docs/project-template-drafts.md +++ b/landing-zone-configurator/docs/project-template-drafts.md @@ -1,345 +1,161 @@ -# Plattformkonfiguration und Projekt-Template-Entwürfe - -Stand: 2026-10-09. Bestell-, Plan-, Apply-, Destroy- und Drift-Ablauf. - -## Application-Destroy und Drift - -Die Bestelldetails bieten **Destroy** und **Drift**, wenn das aktive, qualifizierte -Application-Runner-Paket diese Operationen explizit unterstuetzt. Bestehende -Template-Versionen, Bestellungen, Sources, Artefakte und State-Keys bleiben -unveraendert. Beide Aktionen verwenden den S3-State derselben Application-Instanz. - -**Destroy-Plan erstellen** erzeugt mit `tofu plan -destroy` einen gespeicherten -Loeschplan. Nach Pruefung der Ressourcen und separater Loeschbestaetigung wird -genau dieses Binary angewendet, nicht ein neu berechneter Plan. Die API bindet -die Bestaetigung an Instanz und Artefakt-Hash; ein Plan-/Reiterwechsel setzt die -UI-Bestaetigung zurueck. Anlegen, Aendern, Ersetzen und Ordnerloeschung bleiben -gesperrt. Abschlussstatus und redigierte Ausfuehrungslogs stehen im Destroy-Reiter. -Nach erfolgreichem Destroy kann die Bestellung separat archiviert werden; -State, Artefakte und Audit-Historie bleiben dabei erhalten. Provider-seitige -Projektloeschung kann weiterhin eine nachgelagerte Purge-Phase haben. - -**Drift pruefen** erstellt einen lesenden Plan mit explizitem Refresh und zeigt -zwei getrennte Vergleiche: gespeicherter State gegen Cloud sowie Cloud gegen die -unveraenderlich bestellte Soll-Konfiguration. Sensible Attribute werden maskiert. -Die Pruefung kann weder im UI noch ueber API/Worker angewendet werden. Erfasst -werden nur Ressourcen dieses Application-States, nicht beliebige zusaetzliche -Ressourcen im Projekt. Drift ist daher keine vollstaendige Cloud-Inventarisierung. - -Aktuelle Besteller-/IAM-/Gruppenrechte, technische Delegation, passendes -Runner-Paket und State-Locking bleiben erforderlich. Aktive Ausfuehrungen und -ungeklaerter Recovery-State sperren Maintenance. Ein abgeschlossenes -`reconciliation_required` mit abgelaufenem Ticket und ohne Recovery-Beleg erlaubt -gezielt Destroy/Drift, aber keinen normalen Apply-Neustart. Der alte Abschluss -wird dabei weder veraendert noch als Erfolg interpretiert. Fuer archivierte -Bestellungen besteht weiterhin keine Ausfuehrungsmoeglichkeit. - -## Observability ohne ACL-Parameter - -Die ACL-Einrichtung ist im MVP vollständig benutzerverwaltet und nicht Teil -von Editor, Bestellung oder automatischer Ressourcenverknüpfung. Observability -kann ohne ACL-Pflichteingaben und ohne ungeklärte Egress-Bindung aktiviert -werden. Gespeicherte feste ACL-Werte werden nicht gelöscht. Die neue native -Application-Revision schützt spätere ACL-Änderungen durch `ignore_changes`. -Details und Provider-Grenzen stehen im -[aktuellen Parametervertrag](template-parameters-and-bindings.md). - -Bereits veröffentlichte Versionen bleiben unverändert an ihre alte Quelle -gebunden. Für den neuen Runner ist eine neue Veröffentlichung und Bestellung -nötig; bestehende Aufträge und Plan-Artefakte werden nicht umgeschrieben. - -## Application-Bestellung, Vorschau und Apply - -Eine Bestellung ohne angeforderten Apply kann auch nach einem erfolgreichen -oder fehlgeschlagenen, abgeschlossenen Plan gelöscht werden. Laufende oder -ungeklärte Ausführungen und jede Apply-Anforderung sperren das Löschen weiterhin. -Die Löschung entfernt die Bestellung aus dem Self-Service; Job-Historie und -verschlüsselte Plan-Artefakte bleiben unverändert erhalten. Danach kann kein -Apply mehr aus diesen Plans gestartet werden. Löschen ist kein Cloud-Destroy. - -Bei einer direkt freigegebenen Template-Version mit aktiver Execution-Delegation -startet **Bestellen** unmittelbar den Cloud-Plan. Separate Bestätigungen für -Plan-Vorbereitung und Plan-Start entfallen. Eine fachliche Bestellfreigabe bleibt -nur bei `approval-required` notwendig; danach startet der Application Owner den -Plan mit einem Klick. Die Bestellung bleibt auch bei einem fehlgeschlagenen -Plan-Start erhalten und kann ohne erneute Bestellung weiterbearbeitet werden. - -Ein erfolgreicher Plan liefert eine Ressourcen-Vorschau aus dem verschlüsselten, -gespeicherten Plan-Artefakt: Ressourcentyp, konkrete Änderung und zugelassene -Eigenschaften wie Projektname, Region oder Netzwerk-CIDR. Sensible Werte werden -maskiert; unbekannte Werte werden als erst nach Apply bekannt angezeigt. Rohes -Plan-JSON, Secrets und dynamische Ressourcenadressen werden nicht ausgegeben. - -**Application Landing Zone erstellen** startet mit einem Klick den Apply genau -dieses gespeicherten Plans, ohne weitere Checkbox oder Freigabeschleife. Hash, -Runner-Paket, Bestellung, aktueller Plan und Execution-Delegation werden erneut -geprüft. Der Plan muss innerhalb einer Stunde erstellt worden sein; derselbe -Plan kann nur einmal angewendet werden. Für Apply wird eine neue, kurzlebige -Runner-Berechtigung erzeugt, nicht die Plan-Berechtigung wiederverwendet. - -Apply läuft niemals automatisch. Ein möglicherweise teilweise ausgeführter -Apply wird als `reconciliation_required` gesperrt und nicht automatisch erneut -gestartet. Die Vorschau und damit Apply sind aktuell für den qualifizierten -lokalen Runner verfügbar; ein Runner ohne sichere Saved-Plan-Inspektion meldet -Apply als deaktiviert. Frühere Hinweise auf einen reinen Plan-Pfad oder einen -noch fehlenden Application-Apply sind durch diesen Stand überholt. - -## Fachlicher Ablauf - -Der Platform Engineer definiert zentrale Plattformdienste und die dafür nötigen -Infrastrukturprojekte. Im Schritt **Projekt-Templates** erstellt er Vorlagen für -spätere Anwendungsprojekte. Die Plattformkonfiguration erzeugt diese Projekte -nicht selbst. Der Application Owner bestellt später eine Instanz einer -veröffentlichten Template-Version im separaten Application-Self-Service. - -Neue Entwürfe aus allen acht Accelerator-Vorlagen nutzen diesen Ablauf. -`landing_zones`, `sandboxes` und `landing_zone_namespace_services` aus den -Beispielen werden zu Template-Entwürfen. Plattform, Connectivity, Governance, -zentrale Dienste und deren Projekte bleiben Teil der Plattformkonfiguration. -Die Vorschau zeigt Plattformressourcen und Template-Entwürfe getrennt. - -Ein Template enthält eine eigene ID und Kennung, Anzeigenamen, Projektart -(Public/Corporate/Sandbox), Region sowie die festen Modul-/Service-Einstellungen. -Corporate-Templates referenzieren eine SNA ihrer Region. Die Projektart bestimmt -die Ordnerrolle. Secrets Manager und Observability können als automatisch -bereitzustellende Dienste vorgegeben werden; weitere unterstützte Modulwerte -bleiben erhalten. Dies beschreibt ein Anwendungsprojekt mit Basisdiensten, noch -kein eigenständiges VM- oder Kubernetes-Workload-Angebot. - -Konkreter Projektname und Projektkürzel gehören zur späteren Bestellung. Der -Projektverantwortliche muss serverseitig aus einer verifizierten STACKIT-Identität -kommen. Feste zusätzliche Administratorzuweisungen (z. B. Sandbox `owner_emails`) -sind davon getrennte Plattformpolicy; Beispieladressen müssen vor Speicherung -bereinigt werden. Namespace-Service-Einstellungen werden als Template-Metadaten -erhalten. Das ist keine Freigabe ihrer späteren Clusteranbindung/Ausführung. - -## Template-Eingaben und Verknüpfungen - -Die bisherigen festen Einstellungen sind noch kein vollständiger Template-Vertrag. -Stage soll normalerweise eine begrenzte Bestelleingabe sein; Dienstbeziehungen -wie „Observability nur aus eigenem Projektnetz“ brauchen typisierte Bindungen. -[Wertquellen, Instanziierung und Umsetzungsplan](template-parameters-and-bindings.md). -Parameter-Policy, fünf freigegebene Felder und lokale Bestellvorschau sind implementiert. Veröffentlichung, weitere Feldbindungen und echte Bestellungen bleiben offen. - -## Speicherung und Export - -Das bisherige Dokumentformat v3 besitzt nun optional `projectTemplates`. - -- Ohne das Feld bleibt es eine bisherige Gesamtkonfiguration mit konkreten Projekten. -- Mit dem Feld ist es ein Plattformentwurf; auch eine leere Liste kennzeichnet diesen Modus. -- Plattformentwürfe dürfen keine konkreten `landing_zones`, `sandboxes` oder - `landing_zone_namespace_services` enthalten. Mischformen werden beim Einlesen, - Speichern und Exportieren abgewiesen. -- Template-Einstellungen werden gegen den bestehenden Accelerator-Eingabevertrag - geprüft; konkrete Instanz-/Owner-Felder sind in den Template-Einstellungen verboten. -- Das JSON im persönlichen Fork erhält die Template-Entwürfe. Der deterministische - tfvars-Export enthält nur die Plattform und explizit leere Anwendungssammlungen. -- Erstbereitstellungspläne für erlaubte Plattform-Teilkonfigurationen planen daher - **nur die Plattform**, keine Template-Instanzen. Die übrigen Runner-Sperren bleiben wirksam. - -Das optionale Feld erhält die Lesbarkeit alter Dokumente ohne automatische -Umdeutung. Die Veröffentlichung bekommt später einen eigenen tenantgebundenen, -unveränderlichen Versionsvertrag; ein editierbarer Fork-Entwurf ist keine -veröffentlichte Version und keine Bereitstellungsberechtigung. - -## Bestehende Konfigurationen - -Der bisherige Projekteditor ist für vorhandene Dokumente unter **Projekte (Bestand)** -weiter verfügbar. Neue Konfigurationen werden nicht mehr über den alten -Standalone-Erstellungsbutton angelegt. - -**Als neue Plattformkonfiguration übernehmen** erstellt nach ausdrücklicher -Bestätigung eine Kopie mit neuer Konfigurations-ID. Die Fork-Verknüpfung wird auf -Neuanlage zurückgesetzt; der bestehende Datensatz wird nicht überschrieben. -Namespace-Einstellungen ohne zugehöriges Quellprojekt blockieren die Kopie, -statt verloren zu gehen. SNA-Referenzen aus Templates verhindern das versehentliche -Entfernen des referenzierten Bereichs. - -Das ist ausschließlich eine Konfigurationskopie. Es ist keine State-Migration, -kein Import bestehender Ressourcen und keine Anweisung, die Plattform parallel -neu auszurollen. Bereits bestehende Ressourcen benötigen den separat geplanten -Migrations-/State-Lebenszyklus. - -## Bestellfreigabe (2026-10-07) - -Unter **Application Landing Zones > Bestellungen > Details anzeigen** kann ein -Platform Engineer eine fremde Bestellung mit `approval-required` freigeben oder -ablehnen. Die Entscheidung muss ausdruecklich bestaetigt werden; fuer eine -Ablehnung ist eine Begruendung erforderlich. Selbstfreigaben sind gesperrt. - -Migration 040 speichert Entscheidung, Entscheider, Zeitpunkt und Begruendung als -unveraenderlichen, tenantgebundenen Nachweis. Wiederholungen derselben Entscheidung -liefern denselben Nachweis; eine widerspruechliche Entscheidung wird abgewiesen. -Der Besteller sieht den Status und die Begruendung seiner eigenen Bestellung. -Bestehende Bestellungen ohne Nachweis bleiben ausstehend; bei `direct` ist keine -Bestellfreigabe erforderlich. Die veroeffentlichte Template-Version bleibt erhalten. - -Die fachliche Freigabe startet weder einen Runner noch einen Cloud-Plan oder Apply. -Die Runner-Aktivierung erfolgt separat. Neue Jobs, Credential-Grants, -Claims, Dispatches und Runner-Tickets fuer freigabepflichtige Bestellungen werden -ohne positiven Entscheidungsnachweis auch in der Datenbank gesperrt. Bestehende -Credential-, Backend-, Identitaets- und Ausfuehrungspruefungen bleiben erhalten. - -Qualifiziert mit echten PostgreSQL-Rollen-/Tenant-Tests und Desktop-/Mobil- -Browserfaellen. Ein privater Restore des lokalen Schemas 039 wurde zweimal nach 040 -migriert; alle 37 bisherigen Fach-/Auth-Tabellen blieben unveraendert. - -## Application-Plan im UI (2026-10-07) - -Nach einer Bestellfreigabe kann der Besteller in den Bestelldetails die -**Plan-Vorbereitung bestaetigen** und **Plan vorbereiten**. Das erzeugt einen -kurzlebigen, idempotenten Plan-Job fuer die eigene Bestellung; es startet keinen -Runner und fuehrt keinen Cloud-Plan aus. - -Der im Plattformvertrag gebundene technische Platform Engineer sieht diesen Job -in denselben Bestelldetails. Er waehlt ein bereits registriertes **State-Backend** -und bestaetigt dessen Freigabe. Der State-Key bleibt der unveraenderliche -Application-Instanz-Key, nicht der Plattform-State-Key. Ein separater Klick nach -**Cloud-Plan bestaetigen** startet den isolierten Application-Plan-Runner. -Die technische Freigabe und der Start bleiben an dieselbe Sitzung gebunden. - -Die UI liest die wirkliche Server-Capability statt die bei Bestellung gespeicherten -Sperrhinweise als aktuellen Runner-Status zu behandeln. Laufende Jobs werden -aktualisiert. Reloads loesen keine Mutationen aus. Ein verlorener Prepare-Response -oder ein Fehler beim anschliessenden Statusabruf verwendet beim Retry denselben -Idempotenzschluessel. Abgelaufene Jobs koennen neu vorbereitet werden. - -Migration 041 ergaenzt ausschliesslich SELECT-Sichtbarkeit fuer den bereits -gebundenen technischen Freigeber. Fremde Tenants und ungebundene Platform Engineers -erhalten keine Jobs; die INSERT-, Credential-, Backend- und Dispatch-Gates bleiben -erhalten. Die Job-Liste enthaelt keine Schluessel, rohen States, Planartefakte oder -Runner-Ausgaben, sondern Status und die validierte Plan-Zusammenfassung. - -Lokal ist das separat qualifizierte Application-Paket ueber -`LZC_APPLICATION_EXECUTION_ENABLED=true` und -`LZC_APPLICATION_RUNNER_PACKAGE_DIR` angebunden. Das vorhandene Plattform-Paket -bleibt unveraendert. **Application-Apply ist noch nicht implementiert**: -`applyEnabled=false`, keine automatische Erstellung nach Bestellfreigabe oder -erfolgreichem Plan. Ein echter Cloud-Plan wurde durch diesen Rollout nicht gestartet. - -Qualifikation: 31 echte PostgreSQL-Tests, 16 neue Desktop-/Mobile-Plan-Faelle, -vollstaendiger Organisations-Browserlauf mit 60 Faellen vor dem zusaetzlichen -GET-Ausfall-Test und 412 kanonische Unit-Tests bestanden. Ein privater Restore von -040 wurde zweimal nach 041 migriert; alle 38 bestehenden Tabellen blieben dabei -inhaltlich unveraendert. Im laufenden lokalen Rollout blieb die Bestellentscheidung -erhalten; eine normale erneute Anmeldung ergaenzte eine Sitzung und erneuerte nur -Verifikationszeit und Gueltigkeit der bestehenden STACKIT-Identitaet. - -## Aktueller Katalogstand (2026-10-06) - -Tenantgebundene Veroeffentlichung, unveraenderliche Versionen, freigegebene -Anwendereingaben und forklose Application-Owner-Bestellungen sind implementiert. -Platform Engineer waehlen beim Publizieren `approval-required` (Standard) oder -`direct`. Die Policy gehoert zur unveraenderlichen Version und wird serverseitig -in die Bestellung uebernommen; eine Policy-Aenderung erzeugt eine neue Version. -Clients koennen sie bei Bestellung oder Plan-Input nicht ueberschreiben. - -Eine ausdruecklich bestaetigte Stilllegung erzeugt einen unveraenderlichen, -idempotenten Nachweis. Stillgelegte Versionen verschwinden aus der AO-Auswahl; -neue Bestellungen werden auch serverseitig gesperrt. Bestehende Instanzen und -idempotente Bestellwiederholungen bleiben erhalten. Parallel laufende Bestellung -und Stilllegung verwenden dieselbe transaktionale Sperre. Erneutes Publizieren -stillgelegter Inhalte erzeugt eine neue Version statt die alte wiederzubeleben. - -Die zweisprachige Publisher-Oberflaeche nutzt explizite API-Capabilities. Die -laufende Kunden-API verwendet Migrationen bis 034. Gruppenfreigaben aus -Migration 035 sind auf einer isolierten Testdatenbank qualifiziert, aber noch -nicht in der Kunden-API aktiviert. `direct` aktiviert weder Cloud-Ausfuehrung noch einen -automatischen Apply; eine ausdrueckliche Kunden-Apply-Freigabe bleibt erforderlich. - -### Gruppenfreigaben - -Jeder Arbeitsbereich erhaelt automatisch die Default-Gruppe `Application Owners`. -Application Owner werden beim Beitritt oder Rollenwechsel automatisch aufgenommen; -bei Rollenentzug werden ihre Gruppenmitgliedschaften entfernt. Die Default-Gruppe -kann nicht manuell bearbeitet werden. Bestehende Veroeffentlichungen werden bei -Migration 035 dieser Gruppe zugeordnet; Versionsinhalte, Quellen und Instanzen -bleiben unveraendert. - -Gruppenanlage und Mitgliedschaftsaenderungen erfordern die aktuelle -Mitgliederverwaltungsberechtigung des Arbeitsbereichs. Custom-Gruppen nehmen nur -Application Owner desselben Arbeitsbereichs auf. Platform Engineers waehlen die -Freigabegruppen beim Veroeffentlichen oder bestaetigen eine separate Aenderung der -Freigaben einer vorhandenen Version. Eine leere Freigabeliste sperrt die Version -fuer Application Owner, ohne deren Instanzen oder State zu loeschen. - -Gruppenfreigaben sind auditierte Nutzungsrechte, kein Bestandteil der -unveraenderlichen Versionsinhalte. AO-Katalog und neue Bestellungen werden -serverseitig gefiltert. Aktuelle Rechte werden auch vor Jobvorbereitung, -Backend-Freigabe, Grant-Claim und Runner-Ticket-Verbrauch sowie vor und nach dem -Secret-/Backend-Zugriff geprueft. Gruppenentzug waehrend eines Credential-Zugriffs -verhindert die Rueckgabe des Secrets. AO erhalten weder Gruppenverwaltung noch -technische Credentials. API-Mutationen erfordern Tenantbindung, Origin und CSRF. - -Die UI aktiviert diese Controls nur mit `groupAccessEnabled`. Tests pruefen -Default-Mitgliedschaft, eingeschraenkte Gruppen, fremde Nutzer, direkte -SQL-Claims/Tickets, Entzug waehrend Secret-Zugriff und Desktop-/Mobil-Bedienung. -Dies ist noch keine Abnahme von Application-Plan/Apply, Drift oder Upgrades. - -## Noch offen - -### Neue Runner-Bindung und Loeschung vor Ausfuehrung (2026-10-07) - -Neue Template-Versionen koennen die vom Application-Dienst angebotene -qualifizierte Accelerator-Revision verwenden. Die Veroeffentlichung zeigt die -Revision und erfordert eine ausdrueckliche Bestaetigung fuer jede neue Version. -Bestehende Versionen und Bestellungen werden niemals automatisch umgebunden. -Nicht unterstuetzte Bestandsrevisionen erhalten beim Planversuch eine konkrete -Fehlermeldung statt eines scheinbaren Dienstausfalls. - -Besteller koennen eigene, Platform Engineers die sichtbaren Bestellungen ihres -Arbeitsbereichs mit ausdruecklicher Bestaetigung loeschen. Voraussetzung ist, -dass noch kein Dispatch, Runner-Ticket oder Credential-Claim existiert. -Vorbereitete Jobs und Backend-Freigaben allein verhindern die Loeschung nicht; -nach der Loeschung duerfen sie jedoch nicht mehr ausgefuehrt werden. - -Migration 042 ergaenzt einen unveraenderlichen, tenantgeschuetzten Loeschvermerk. -Die Bestellung verschwindet aus der Liste; Versionsinhalte, Freigaben und -Idempotenzhistorie bleiben erhalten. Replays erzeugen keine neue Bestellung. -Gemeinsame Zeilensperren serialisieren Loeschung und Ausfuehrungsfreigaben. -Es werden weder Cloud-Ressourcen noch Terraform-State geloescht. Der Umgang -mit bereits ausgefuehrten Bestellungen und Application-Apply bleibt offen. - -[#92](https://github.com/stackitcloud/stackit-landing-zone/issues/92) bleibt fuer -die produktive Veroeffentlichungsabnahme unter autoritativ verifizierter -Tenantbindung offen. Private Entwuerfe werden nicht im AO-Katalog angezeigt. - -[#91](https://github.com/stackitcloud/stackit-landing-zone/issues/91) und -[#93](https://github.com/stackitcloud/stackit-landing-zone/issues/93) liefern die -verifizierte Organisations-/Benutzerbindung und Instanziierung mit eigenem State. -Die bisherige Sperre für Kunden-Apply bleibt bestehen. - -### Delegierte Application-Plan-Ausfuehrung (2026-10-08) - -Der Platform Owner richtet im Publikationsbereich einmal pro freigegebenem -Plattformvertrag die Ausfuehrung mit einem registrierten State Backend ein. -Die Berechtigung bindet unveraenderlich den Service Account des Vertrags, -Credential-Version und Key-ID sowie Backend-Identitaet und verschluesselte -Backend-Credentials. Bestehende Vertraege erhalten keine automatische Delegation. - -Neue Plan-Jobs einer dazu gebundenen Template-Version uebernehmen diese -Berechtigung und den instanzspezifischen State-Key. Der Application Owner startet -den Plan explizit selbst, ohne zweite technische Backend-Freigabe und ohne aktive -Platform-Owner-Sitzung. Bei `approval-required` bleibt zuvor die fachliche -Bestellfreigabe erforderlich; `direct` benoetigt sie nicht. Alte Jobs und -Template-Versionen werden nicht nachtraeglich umgebunden. - -Der Platform Owner kann die Berechtigung widerrufen. Vor weiteren Runner-Zugriffen -werden aktuelle Rollen, Bestelleridentitaet, Gruppenfreigabe, Credential- und -Backend-Bindung erneut geprueft. Eine neue Delegation reaktiviert keine alten Jobs. -Secret und Backend-Credentials bleiben serverseitig und werden nur einmal an den -gebundenen Runner ausgegeben. Neue Publikationen uebernehmen die angebotene, -qualifizierte Runner-Revision ohne zusaetzliche Pflicht-Checkbox. - -Application-Apply bleibt unimplementiert. Ein erfolgreicher Plan erzeugt keine -Cloud-Ressourcen und ist keine Apply-Freigabe. - -## Prüfungen - -- [x] Alle acht Quellvorlagen werden ohne Verlust von Plattform-/Projektpolicy konvertiert. -- [x] Persönliche Instanzfelder gelangen nicht in Projektvorlagen. -- [x] Legacy-Dokumente bleiben beim Einlesen unverändert; Kopien benötigen eine neue ID. -- [x] Git-Speicherung erhält Metadaten; tfvars und Deployment-Vorbereitung enthalten keine daraus erzeugten Projekte. -- [x] Gemischte Template-/Instanzdokumente werden abgewiesen. -- [x] Native OpenTofu-Variablenprüfung bestätigt leere Anwendungs-, Sandbox- und Namespace-Sammlungen im Plattformexport. -- [x] Browserprüfung einschließlich Bestandskopie/Speicherung erfolgreich; CI-Validierung und [Release 36855011827](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36855011827) für `0e62c5e` erfolgreich. Live-SPA liefert HTTP 200 mit dem erwarteten Bundle `index-bjLShEoG.js`. +# Platform configuration and project template drafts + +[English](project-template-drafts.md) | [Deutsch](project-template-drafts.de.md) + + + +As of: 2026-10-09. Order, Plan, Apply, Destroy and drift workflow. + + +## Application Destroy and drift + +Order details offer **Destroy** and **Drift** when the active, qualified Application Runner package explicitly supports these operations. Existing template versions, orders, sources, artifacts and state keys remain unchanged. Both actions use the S3 state of the same Application instance. + +**Create Destroy plan** uses `tofu plan -destroy` to create a saved deletion plan. After resource review and separate deletion confirmation, exactly this binary is applied, not a newly calculated plan. The API binds confirmation to the instance and artifact hash; changing the plan/tab resets UI confirmation. Creation, modification, replacement and folder deletion remain blocked. Final status and redacted execution logs are available in the Destroy tab. After successful Destroy, the order can be archived separately; state, artifacts and audit history are retained. Provider-side project deletion may still have a subsequent purge phase. + +**Check drift** creates a read-only plan with explicit refresh and shows two separate comparisons: saved state versus cloud and cloud versus the immutably ordered desired configuration. Sensitive attributes are masked. The check cannot be applied through either UI or API/worker. Only resources of this Application state are covered, not arbitrary additional resources in the project. Drift is therefore not a complete cloud inventory. + +Current requester/IAM/group permissions, technical delegation, a matching Runner package and state locking remain required. Active executions and unresolved recovery state block maintenance. A completed `reconciliation_required` with an expired ticket and no recovery evidence specifically permits Destroy/drift, but not restarting a normal Apply. The old completion is neither changed nor interpreted as success. Archived orders still cannot be executed. + + +## Observability without ACL parameters + +In the MVP, ACL setup is entirely user-managed and not part of the editor, order or automatic resource binding. Observability can be enabled without mandatory ACL inputs or unresolved egress binding. Saved fixed ACL values are not deleted. The new native Application revision protects subsequent ACL changes through `ignore_changes`. Details and provider limitations are in the [current parameter contract](template-parameters-and-bindings.md). + +Already published versions remain bound unchanged to their old source. The new Runner requires a new publication and order; existing orders and plan artifacts are not rewritten. + + +## Application ordering, preview and Apply + +An order without a requested Apply can be deleted even after a successful or failed, completed Plan. Running or unresolved executions and any Apply request continue to block deletion. Deletion removes the order from self-service; job history and encrypted plan artifacts remain unchanged. No Apply can then be started from these plans. Deletion is not cloud Destroy. + +For a directly approved template version with active execution delegation, **Order** starts the cloud Plan immediately. Separate confirmations for Plan preparation and Plan start are no longer needed. Business order approval remains necessary only for `approval-required`; afterwards, the Application Owner starts the Plan with one click. The order is retained even if Plan startup fails and can be continued without ordering again. + +A successful Plan provides a resource preview from the encrypted, saved plan artifact: resource type, specific change and permitted properties such as project name, region or network CIDR. Sensitive values are masked; unknown values are shown as known only after Apply. Raw plan JSON, secrets and dynamic resource addresses are not output. + +**Create Application Landing Zone** starts Apply of exactly this saved plan with one click, without another checkbox or approval loop. Hash, Runner package, order, current plan and execution delegation are checked again. The plan must have been created within the last hour; the same plan can be applied only once. A new short-lived Runner authorization is created for Apply, rather than reusing Plan authorization. + +Apply never runs automatically. A potentially partially executed Apply is blocked as `reconciliation_required` and is not automatically restarted. Preview, and therefore Apply, is currently available for the qualified local Runner; a Runner without secure saved-plan inspection reports Apply as disabled. Earlier notes about a Plan-only path or Application Apply not yet being available are superseded by this status. + + +## Business workflow + +The Platform Engineer defines central platform services and the infrastructure projects required for them. In the **Project templates** step, they create templates for future application projects. Platform configuration does not create those projects itself. The Application Owner later orders an instance of a published template version in separate Application self-service. + +New drafts from all eight Accelerator templates use this workflow. `landing_zones`, `sandboxes` and `landing_zone_namespace_services` from the examples become template drafts. Platform, connectivity, governance, central services and their projects remain part of platform configuration. The preview shows platform resources and template drafts separately. + +A template contains its own ID and key, display name, project type (Public/Corporate/Sandbox), region and fixed module/service settings. Corporate templates reference an SNA in their region. Project type determines the folder role. Secrets Manager and Observability can be specified as automatically provisioned services; other supported module values are retained. This describes an application project with basic services, not yet an independent VM or Kubernetes workload offering. + +The specific project name and abbreviation belong to the later order. The project owner must come server-side from a verified STACKIT identity. Fixed additional administrator assignments (e.g. sandbox `owner_emails`) are separate platform policy; example addresses must be cleaned up before saving. Namespace service settings are retained as template metadata. This does not approve their later cluster binding/execution. + + +## Template inputs and bindings + +The previous fixed settings do not yet constitute a complete template contract. Stage should normally be a bounded order input; service relationships such as “Observability only from the project's own network” need typed bindings. [Value sources, instantiation and implementation plan](template-parameters-and-bindings.md). Parameter policy, five approved fields and local order preview are implemented. Publication, further field bindings and real orders remain outstanding. + + +## Storage and export + +The existing v3 document format now has optional `projectTemplates`. + +- Without the field, it remains an existing combined configuration with concrete projects. +- With the field, it is a platform draft; even an empty list identifies this mode. +- Platform drafts must not contain concrete `landing_zones`, `sandboxes` or `landing_zone_namespace_services`. Mixed forms are rejected during reading, saving and export. +- Template settings are checked against the existing Accelerator input contract; concrete instance/owner fields are prohibited in template settings. +- JSON in the personal fork retains template drafts. Deterministic tfvars export contains only the platform and explicitly empty application collections. +- Initial-provisioning plans for permitted platform subsets therefore plan **only the platform**, not template instances. Other Runner guards remain effective. + +The optional field preserves readability of old documents without automatic reinterpretation. Publication will later receive its own tenant-bound, immutable version contract; an editable fork draft is not a published version or provisioning authorization. + + +## Existing configurations + +The previous project editor remains available for existing documents under **Projects (legacy)**. New configurations are no longer created through the old standalone creation button. + +**Adopt as new platform configuration** creates a copy with a new configuration ID after explicit confirmation. Fork binding is reset to new creation; the existing record is not overwritten. Namespace settings without an associated source project block the copy rather than being lost. SNA references from templates prevent accidental removal of the referenced area. + +This is exclusively a configuration copy. It is not a state migration, import of existing resources or instruction to roll out the platform again in parallel. Existing resources require the separately planned migration/state lifecycle. + + +## Order approval (2026-10-07) + +Under **Application Landing Zones > Orders > Show details**, a Platform Engineer can approve or reject another person's order with `approval-required`. The decision must be explicitly confirmed; rejection requires a reason. Self-approval is blocked. + +Migration 040 stores decision, decision-maker, time and reason as immutable, tenant-bound evidence. Repeating the same decision returns the same evidence; a contradictory decision is rejected. The requester sees the status and reason for their own order. Existing orders without evidence remain pending; `direct` requires no order approval. The published template version is retained. + +Business approval starts neither a Runner nor a cloud Plan or Apply. Runner activation is separate. New jobs, credential grants, claims, dispatches and Runner tickets for orders requiring approval are blocked in the database as well unless positive decision evidence exists. Existing credential, backend, identity and execution checks are retained. + +Qualified with real PostgreSQL role/tenant tests and desktop/mobile browser cases. A private restore of local schema 039 was migrated to 040 twice; all 37 previous business/auth tables remained unchanged. + + +## Application Plan in the UI (2026-10-07) + +After order approval, the requester can **Confirm Plan preparation** and **Prepare Plan** in order details. This creates a short-lived, idempotent Plan job for their own order; it does not start a Runner or execute a cloud Plan. + +The technical Platform Engineer bound in the platform contract sees this job in the same order details. They select an already registered **State backend** and confirm its release. The state key remains the immutable Application instance key, not the platform state key. A separate click after **Confirm cloud Plan** starts the isolated Application Plan Runner. Technical release and startup remain bound to the same session. + +The UI reads the actual server capability rather than treating blocking notices stored at ordering as current Runner status. Running jobs are refreshed. Reloads trigger no mutations. A lost Prepare response or an error in the subsequent status request uses the same idempotency key on retry. Expired jobs can be prepared again. + +Migration 041 adds only SELECT visibility for the already bound technical approver. Foreign tenants and unbound Platform Engineers receive no jobs; INSERT, credential, backend and dispatch gates remain intact. The job list contains no keys, raw states, plan artifacts or Runner output, only status and the validated plan summary. + +Locally, the separately qualified Application package is connected through `LZC_APPLICATION_EXECUTION_ENABLED=true` and `LZC_APPLICATION_RUNNER_PACKAGE_DIR`. The existing platform package remains unchanged. **Application Apply is not yet implemented**: `applyEnabled=false`, no automatic creation after order approval or successful Plan. This rollout did not start a real cloud Plan. + +Qualification: 31 real PostgreSQL tests, 16 new desktop/mobile Plan cases, the full organization browser run with 60 cases before the additional GET-failure test, and 412 canonical unit tests passed. A private restore from 040 was migrated to 041 twice; the contents of all 38 existing tables remained unchanged. In the running local rollout, the order decision was retained; normal re-login added a session and renewed only verification time and validity of the existing STACKIT identity. + + +## Current catalogue status (2026-10-06) + +Tenant-bound publication, immutable versions, approved user inputs and forkless Application Owner orders are implemented. At publication, Platform Engineers select `approval-required` (default) or `direct`. Policy belongs to the immutable version and is copied into the order server-side; changing policy creates a new version. Clients cannot override it at ordering or in Plan input. + +Explicitly confirmed retirement creates immutable, idempotent evidence. Retired versions disappear from AO selection; new orders are blocked server-side as well. Existing instances and idempotent order repetitions are retained. Concurrent ordering and retirement use the same transactional lock. Republishing retired content creates a new version instead of reviving the old one. + +The bilingual publisher UI uses explicit API capabilities. The running customer API uses migrations through 034. Group access from migration 035 is qualified on an isolated test database but is not yet activated in the customer API. `direct` enables neither cloud execution nor automatic Apply; explicit customer Apply approval remains necessary. + + +### Group access + +Every workspace automatically receives the default group `Application Owners`. Application Owners are added automatically on joining or role change; their group memberships are removed on role revocation. The default group cannot be edited manually. Migration 035 assigns existing publications to this group; version content, sources and instances remain unchanged. + +Group creation and membership changes require current workspace member-management permission. Custom groups accept only Application Owners from the same workspace. Platform Engineers select access groups when publishing or confirm a separate change to access for an existing version. An empty access list blocks the version for Application Owners without deleting their instances or state. + +Group access is an audited usage permission, not part of immutable version content. AO catalogue and new orders are filtered server-side. Current permissions are also checked before job preparation, backend release, grant claim and Runner ticket consumption, and before and after secret/backend access. Revoking group access during credential access prevents returning the secret. AOs receive neither group management nor technical credentials. API mutations require tenant binding, Origin and CSRF. + +The UI enables these controls only with `groupAccessEnabled`. Tests cover default membership, restricted groups, foreign users, direct SQL claims/tickets, revocation during secret access and desktop/mobile operation. This is not yet acceptance of Application Plan/Apply, drift or upgrades. + + +## Still outstanding + + +### New Runner binding and deletion before execution (2026-10-07) + +New template versions can use the qualified Accelerator revision offered by the Application service. Publication shows the revision and requires explicit confirmation for each new version. Existing versions and orders are never rebound automatically. Unsupported legacy revisions receive a specific error message when attempting a Plan instead of an apparent service outage. + +Requesters can delete their own orders, and Platform Engineers visible orders of their workspace, with explicit confirmation. This requires that no dispatch, Runner ticket or credential claim exists yet. Prepared jobs and backend releases alone do not prevent deletion; after deletion, however, they must no longer be executed. + +Migration 042 adds an immutable, tenant-protected deletion marker. The order disappears from the list; version content, approvals and idempotency history are retained. Replays do not create a new order. Shared row locks serialize deletion and execution releases. Neither cloud resources nor Terraform state are deleted. Handling already executed orders and Application Apply remains outstanding. + +[#92](https://github.com/stackitcloud/stackit-landing-zone/issues/92) remains open for production publication acceptance under authoritatively verified tenant binding. Private drafts are not shown in the AO catalogue. + +[#91](https://github.com/stackitcloud/stackit-landing-zone/issues/91) and [#93](https://github.com/stackitcloud/stackit-landing-zone/issues/93) provide verified organization/user binding and instantiation with separate state. The existing customer Apply block remains. + + +### Delegated Application Plan execution (2026-10-08) + +In the publication area, the Platform Owner sets up execution with a registered state backend once per approved platform contract. Authorization immutably binds the contract's service account, credential version and key ID, as well as backend identity and encrypted backend credentials. Existing contracts receive no automatic delegation. + +New Plan jobs for a template version bound to this contract inherit this authorization and the instance-specific state key. The Application Owner explicitly starts the Plan themselves, without a second technical backend release and without an active Platform Owner session. For `approval-required`, prior business order approval remains required; `direct` does not need it. Old jobs and template versions are not rebound retroactively. + +The Platform Owner can revoke authorization. Before further Runner access, current roles, requester identity, group access, credential and backend binding are checked again. A new delegation does not reactivate old jobs. Secret and backend credentials stay server-side and are issued only once to the bound Runner. New publications adopt the offered, qualified Runner revision without an additional mandatory checkbox. + +Application Apply remains unimplemented. A successful Plan creates no cloud resources and is not Apply approval. + + +## Checks + +- [x] All eight source templates are converted without loss of platform/project policy. +- [x] Personal instance fields do not enter project templates. +- [x] Legacy documents remain unchanged on reading; copies require a new ID. +- [x] Git storage retains metadata; tfvars and deployment preparation contain no projects generated from it. +- [x] Mixed template/instance documents are rejected. +- [x] Native OpenTofu variable checking confirms empty application, sandbox and namespace collections in platform export. +- [x] Browser checks including legacy copy/save successful; CI validation and [release 36855011827](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36855011827) for `0e62c5e` successful. Live SPA serves HTTP 200 with the expected bundle `index-bjLShEoG.js`. diff --git a/landing-zone-configurator/docs/template-parameters-and-bindings.de.md b/landing-zone-configurator/docs/template-parameters-and-bindings.de.md new file mode 100644 index 0000000..dc702b4 --- /dev/null +++ b/landing-zone-configurator/docs/template-parameters-and-bindings.de.md @@ -0,0 +1,458 @@ + + +# Projekt-Templates: Eingaben, feste Vorgaben und Ressourcenverknüpfungen + +[English](template-parameters-and-bindings.md) | [Deutsch](template-parameters-and-bindings.de.md) + + + +## Aktueller MVP: ACL-Einrichtung durch den Benutzer + +Stand: 2026-10-08. Die Observability-ACL ist kein Configurator-Parameter mehr. +Editor, Bestellformular und Vorschau bieten weder CIDR-Auswahl noch +Projektnetz-Bindung an. Eine aktivierte Observability-Instanz erzeugt keinen +ACL-Pflichtfeld- oder Egress-Qualifikationsblocker. Der Benutzer richtet die +Zugriffsquellen selbst direkt in STACKIT ein; der Configurator ermittelt oder +konfiguriert keinen automatischen Zugangsweg. + +Gespeicherte ACL-Werte und alte Policies bleiben in ihren Vorlagen erhalten. +Alte ACL-Bestelleingaben und Policies werden bei neuer Auflösung ignoriert; +vorhandene feste Werte bleiben als Kompatibilitätswerte erhalten. Es wird kein +privates Projektnetz in Internet-Quelladressen übersetzt. + +Die neue native Application-Revision `88149782bf8e91dcdbb43a203b54337886023f7f` +verwendet `ignore_changes = [acl]`, damit spätere manuelle ACL-Änderungen keinen +Terraform-Änderungsplan auslösen. Der STACKIT-Provider setzt beim Erstellen +weiterhin den anfänglichen ACL-Wert und überträgt bei anderen Instance-Updates +den eingelesenen Wert erneut. Eine gleichzeitige manuelle Änderung zwischen +Plan und Apply ist dadurch nicht gegen Überschreiben geschützt. + +Neue Veröffentlichungen nutzen die aktiv angebotene Runner-Revision. +Bestehende veröffentlichte Versionen, Bestellungen und Saved Plans werden nicht +umgebunden. Für sie ist eine neue Veröffentlichung mit anschließender neuer +Bestellung erforderlich; alte Pakete und Historie bleiben erhalten. Die +folgenden ACL-Bindungsbeschreibungen dokumentieren den früheren Entwurfsstand, +nicht den aktuellen MVP. + +Stand: 2026-10-06. Parametervertrag, Template-Editor, tenantgebundener Testkatalog, persistente Bestellaufträge und serverbasierte Applied-Platform-Bindung implementiert. Live-Aktivierung und menschliche Abnahme, Application-Cloud-Plan und produktive Instanziierung bleiben offen. Dieser Stand ist lokal, noch nicht veröffentlicht. +Ergänzt [Projekt-Template-Entwürfe](project-template-drafts.de.md) und die +[Plattform-/Application-Architektur](platform-application-architecture.de.md). + + + +## Serverbasierte Plattformbindung + +Bei aktivierter Capability `appliedPlatformsEnabled` waehlt der Platform Engineer +eine erfolgreich angewendete Plattform seines aktiven Tenants und laesst den +Server die nicht geheimen Plattformziele vorpruefen. Nur abgeschlossene Applies +mit weiterhin passender, unverriegelter State-Version und aktuellem menschlichen +Nachweis fuer die verifizierte Organisation stehen zur Auswahl. +Der normale Weg verlangt keinen JSON-Transfer; der Datei-Import bleibt lediglich +als Kompatibilitaetsweg fuer aeltere APIs erhalten. + +Die Vorschau liefert Ziele und einen Source-Beleg aus Apply-ID, State-Key und +Version, urspruenglicher Vertragsrevision und SHA-256 des validierten Dokuments. +Zur ausdruecklichen Freigabe sendet der Browser nur diesen Beleg, Zustimmung und +die gewaehlte technische Profil-ID. Ziele und Organisation kommen erneut vom +Server, nicht aus kopierten Browserdaten. Menschlicher Nachweis, aktueller State +und technischer Zugriff werden erneut geprueft. Aenderungen waehrend der Pruefung +verhindern die Uebernahme. Die Quelle bleibt append-only und tenantgebunden; +konkurrierende Wiederholungen mit demselben geprueften Zugang sind idempotent. + +Die Freigabe reserviert keine neue Cloud-Ausfuehrung und aendert keine vorhandene +Application-Instanz. Alte Bestellungen behalten ihre Vertragsrevision; ein neuer +Plattform-Apply bindet sie nicht automatisch um. Die API-Erweiterung und Migration +036 sind lokal qualifiziert, aber nicht Teil des laufenden Login-only-Standes 034. +Gruppenmigration 035 und Source-Migration 036 benoetigen eine separate Aktivierung. +Echte Application-Plans, explizite Applies, Drift und Upgrades bleiben eigenstaendige +Folgeschritte in #93. Der eigenstaendige Accelerator bleibt unabhaengig nutzbar. + + + +## Aufgaben in der Oberflaeche + +Der Editor-Schritt **Template-Entwürfe** bearbeitet unveröffentlichte Vorlagen. +Die Seite **Application Landing Zones** trennt die weiteren Aufgaben in Reiter: +**Katalog** für veröffentlichte Versionen und Bestellformulare sowie +**Bestellungen** für gespeicherte Instanzen und deren Details. +Platform Engineers sehen zusätzlich **Veröffentlichung** und +**Plattformanbindung**; berechtigte Gruppenmanager sehen **Gruppen**. +Application Owner erhalten keine Verwaltungsreiter. Nach erfolgreicher +Veröffentlichung öffnet sich der Katalog, nach einer Bestellung deren Auftragsbereich. + +Die Plattformanbindung ist keine Veröffentlichung eines Templates und keine +Cloud-Ausführung. Der normale, serverbasierte Weg benötigt keinen Datei-Upload. +Bei älteren APIs liegt der bisherige Upload eingeklappt unter +**Kompatibilitätsimport**. Hier gehört ausschließlich der exportierte JSON-Vertrag +einer tatsächlich angewendeten Platform Landing Zone hinein, nicht ein beliebiges +JSON, Terraform-State, tfvars oder Zugangsdaten. Der Vertrag enthält die +Organisations-ID und freigegebene Zielordner mit ihren Plattformreferenzen; +der Server prüft ihn vor einer ausdrücklichen Freigabe. + +Diese UI-Trennung ist lokal qualifiziert. Sie aktiviert weder die Migrationen +035/036 noch ein Backend-Feature oder eine Application-Cloud-Ausführung. + + + +## Implementierter Umfang + +`ProjectTemplateDraft.parameterPolicy` (Version 1) definiert die Wertquelle je +freigegebenem Feld. Die fünf ersten Felder sind Stage, Secrets-Manager-Aktivierung, +Observability-Aktivierung, Observability-Leistungsklasse und Observability-ACL. +Zusätzlich können Projektrollen über `source: context` und die typisierte Variable +`verified-project-owner` bei der Instanziierung zugeordnet werden. Alle anderen +Einstellungen bleiben fest; Sandbox-Parameter sind noch nicht qualifiziert. +String-Eingaben benötigen eine explizite Auswahlliste, ACL-Eingaben eine Auswahl +zulässiger CIDRs; eine leere ACL-Bestellung ist gesperrt. Eine noch leere, erforderliche +ACL-Auswahlliste ohne Vorauswahl darf als Entwurf bearbeitet werden; die Vorschau +und Auflösung bleiben bis zur gültigen Bestelleingabe gesperrt. Feste ältere Einstellungen +werden nicht automatisch umgedeutet. Defaults, Pflichtfelder, Herkunft und +unzulässige Overrides werden durch denselben Domain-Resolver geprüft, den der +Application-Compiler verwendet. Dies gilt auch beim Speichern der Template-Policy. + +Neue Vorlagen erlauben Stage-Auswahl; neue Preset-Entwürfe behalten die Stage des +Beispiels als Vorauswahl, neu hinzugefügte Vorlagen verwenden `dev`. Die +explizite Übernahme einer bestehenden Konfiguration als Plattformkopie behält +hingegen feste Vorgaben. Das JSON im Fork speichert die Policy; der Plattform- +tfvars-Export enthält weiterhin keine Template-Instanzen. + +Unter **Bestellung testen** erzeugt der Editor aus der Policy ein lokales Formular +mit wirksamen Werten und Herkunft. Das ist keine öffentliche Application-Owner- +Bestellung und führt keine Cloudzugriffe aus. Der veröffentlichte Application- +Vertragsprototyp Version 2 akzeptiert diese Policy und prüft Bestelleingaben, +Tenant-/Plattformbindung und konkrete Dienstwerte erneut. Version 1 bleibt +kompatibel. Ausführung bleibt ausdrücklich deaktiviert. + +Die Projektnetz-Bindung wird symbolisch gespeichert und ist sowohl in der +Vorschau als auch nativ im Application-Root gesperrt. Ihre produktive Egress- +Auflösung wird in [#96](https://github.com/stackitcloud/stackit-landing-zone/issues/96) +verfolgt. Der Runner-Pin bleibt unverändert; diese Ergänzungen geben keine +produktive Ausführung frei. + + + +## Tenantgebundener Testkatalog und Bestellungen + +Die Seite `/applications` trennt veröffentlichte Versionen von bearbeitbaren +Projekt-Template-Entwürfen. Der Server speichert den vollständigen validierten +Snapshot samt Policy, Tenant, Template-ID, fortlaufender Version, Veröffentlichendem, +Zeitpunkt und festem Accelerator-Pin. Gleicher Snapshot mit gleichem Pin liefert +dieselbe letzte Version; Änderungen erzeugen eine neue. Frühere Versionen werden +weder verändert noch automatisch auf Bestellungen übertragen. Sandbox-Veröffentlichungen +und leere Bestell-Auswahllisten bleiben gesperrt. + +Platform Engineers veröffentlichen aus dem aktuellen Entwurf. Application Owner +sehen nur Versionen ihres aktiven Tenants und benötigen keinen persönlichen Fork. +Der persönliche Arbeitsbereich erlaubt seinem bisherigen Admin die Vorbereitung +dieses Testkatalogs. Unverifizierte Organisationsarbeitsbereiche dürfen damit Daten +vorbereiten, erhalten aber keine STACKIT-Ausführungsrechte. Eine Katalogversion ist +noch keine für reale Kunden verifiziert freigegebene Ressourcenvorlage. + +Die Bestellung enthält nur Versions-ID, Projektname, erlaubte Parameter und einen +UUID-Idempotenzschlüssel. Tenant und Antragsteller stammen aus der serverseitig +aufgelösten Session; Owner-E-Mail, Plattform-ID und feste Einstellungen sind nicht +überschreibbar. Derselbe Schlüssel desselben Antragstellers im selben Tenant mit +identischen Eingaben liefert dieselbe Instanz. Abweichende Eingaben ergeben HTTP 409. +Der Browser behält den Schlüssel für Wiederholung und Netzwerk-Retry des laufenden +Bestellformulars. Ein neu geöffnetes oder geändertes Formular ist ein neuer Auftrag; +es besteht keine automatische Zusammenführung nach Projektnamen. + +Jede Bestellung erhält eine eigene serverseitige Instanz-ID und reserviert +`applications///terraform.tfstate` als State-Key. Die Bestellung +erzeugt **noch keine State-Datei und kein STACKIT-Projekt**. Feste Einstellungen, +aufgelöste Eingaben und Qualifizierungsblocker werden dauerhaft gespeichert. +Application Owner sehen nur eigene Aufträge, Platform Engineers die Aufträge ihres +Tenants. PostgreSQL erzwingt RLS, aktuelle Produktrollen und unveränderliche Versionen; +ein Wechsel des aktiven Tenants während der Anfrage wird abgewiesen. Ein Arbeitsbereich +mit veröffentlichten Versionen oder Bestellungen kann nicht als leerer Entwurf +archiviert werden. + +Der Planstatus ist stets `blocked` und `executionEnabled=false`. Die Oberfläche +weist fehlende verifizierte STACKIT-Benutzeridentität, fehlenden freigegebenen +Plattformvertrag und den noch nicht freigegebenen Application-Runner aus. Ein +GitHub-Login oder ein Service-Account-Key wird nicht als menschlicher STACKIT-Nachweis +umgedeutet. Es gibt keine erfundenen Ressourcenanzahlen und keine Apply-Aktion. +Unaufgelöste Projektrollen und Egress-Bindungen bleiben zusätzliche Blocker. +Der vorhandene Application-Compiler wird dadurch nicht als Ausführungsbroker ausgegeben. + +Migration `010_application_catalogue.sql` und `LZC_APPLICATIONS_ENABLED=true` sind +für den Backend-Betrieb erforderlich; das Flag ist standardmäßig aus. Die neue +Migration wurde ausschließlich in der wegwerfbaren lokalen PostgreSQL-Testdatenbank +angewendet, nicht auf der CF-Datenbank. Bestehender Runner-Pin, Plattformvertrag und +Deployment-Pipeline werden nicht automatisch erweitert. + +Nachweise: Domain-/API-Tests, echte PostgreSQL-Session/RLS samt HTTP-Durchstich, +parallele Idempotenzprüfung, Rollenentzug und Desktop-/Mobil-Browserfälle. +Die Browserfälle verwenden simulierte API-Antworten; sie ersetzen keine Live-Abnahme +mit verifizierten STACKIT-Identitäten und keinen echten Cloud-Plan. + + + +## Lokales Projektnetz als Template-Vorgabe + +Ein Projektnetz ist Teil der Landing Zone, nicht erst der späteren VM-Anwendung. +Public-Projekt-Templates können deshalb mit `settings.network_enabled: true` +ein lokales, nicht SNA-geroutetes Netz anlegen. `network_prefix_length` legt +optional die Präfixlänge fest; ohne Vorgabe wird sie vom Dienst bestimmt. +Die Präfixlänge beschreibt die Netzgröße: `/24` umfasst 256 IPv4-Adressen, +`/25` 128 und `/26` 64. Größere Präfixzahlen bedeuten kleinere Netze; nicht alle +Adressen sind für VMs verfügbar. +Die Oberfläche bietet diese Einstellungen direkt im Projekt-Template an. +Netzanlage und Größe bleiben zunächst feste Vorgaben, keine Bestelleingaben. + +Bestehende Public-Templates ohne Netzoption bleiben unverändert. Corporate- +Templates behalten ihr automatisch erzeugtes geroutetes Netz und ihre SNA- +Zuordnung. Sandbox-Netze sind von dieser Erweiterung nicht erfasst. Eine Vorlage +für ein VM-Netz erstellt damit das Projekt und sein Netz, nicht bereits die VM. + +Die Einstellungen werden mit dem Template-Dokument im Fork gespeichert und +erzeugen beim Plattform-Export keine Projekte oder Netze. Der Application-Vertrag +Version 2 übernimmt sie als feste Vorgaben in den nativen Application-Root; +Version 1 bleibt unverändert. Das Modul gibt eine nicht geheime Netzreferenz aus. +Modul-, Application- und Standalone-Mockpläne prüfen lokale Netzanlage ohne SNA +sowie den Erhalt bisheriger Konfigurationen. Produktive Instanziierung und ein +realer Cloud-Apply sind weiterhin nicht freigegeben. + +Das lokale Netz ist keine automatische Observability-ACL-Quelle. Die +[Instanz-ACL](https://docs.stackit.cloud/products/logging-and-monitoring/observability/how-tos/control-instance-access/) +filtert die am Internet-Endpunkt sichtbaren Quelladressen gemeinsam für Grafana, +Metrics, Logs und Traces. Eine leere ACL stellt uneingeschränkten Netzwerkzugriff +wieder her. Private Netz-CIDRs dürfen daher nicht ohne nachgewiesene Egress- +Semantik als Quelladressen übernommen werden. + + + +## Kataloge und verifizierte Instanziierungsvariablen + +Die geladenen STACKIT-Produktkataloge gelten auch für die erlaubten Bestellwerte. +Bei der Freigabe der Observability-Leistungsklasse werden die aktuellen Optionen +angeboten und können über Checkboxen eingeschränkt werden. Nicht mehr im Katalog +enthaltene Bestandswerte bleiben erkennbar erhalten. Ohne verfügbaren Katalog bleibt +die manuelle Eingabe möglich; sie ist kein Nachweis der Cloud-Verfügbarkeit. +Dieselbe Katalogzuordnung wird im strukturierten Editor für Git, VPN, SKE, +Observability, Bastion und die neuen IAM-Felder verwendet. Nicht alle diese +Plattformfelder sind bereits als Projekt-Bestellparameter qualifiziert. + +Für Projektrollen definiert die Policy `source: context`, +`variable: verified-project-owner` und eine Rollenliste. Es werden keine persönlichen +E-Mail-Adressen oder frei interpretierbaren Platzhalter im Template gespeichert. +Die lokale Vorschau zeigt die unaufgelöste Identität und einen Blocker. Der Compiler +bindet ausschließlich `context.verified_stackit_email`, niemals GitHub-Login oder +eine vom Besteller übergebene Benutzerkennung. Bestehende feste Zuweisungen bleiben +erhalten. Doppelte Zuweisungen derselben Rolle an dieselbe Identität werden vermieden. +Die zusätzlichen Rollenzuweisungen und festen `custom_roles` werden im Application- +Vertrag Version 2 bis zum nativen Root weitergegeben; Version 1 bleibt unverändert. +Das ist weiterhin ein nicht zur produktiven Ausführung freigegebener Prototyp. + +Bei fest ausgeschaltetem Observability blendet der Template-Editor Leistungsklasse, +Zugriffsquellen, Instanzname und die entsprechenden Vorschauwerte aus. Gespeicherte +Werte und Policies bleiben erhalten und erscheinen beim Wiedereinschalten wieder. +Ist die Aktivierung erst bei der Bestellung wählbar, bleiben die benötigten +Template-Vorgaben konfigurierbar. Strukturierte Template-Dienste mit explizit +ausgeschaltetem `enabled`- oder benanntem `*_enabled`-Schalter blenden ihre +zugehörigen Details ebenfalls aus, ohne diese zu löschen. + +STACKIT-Rollenvorlagen übernehmen Name, Beschreibung und Permissions als bearbeitbare +eigene Rolle mit einem `application-`-Namenspräfix. Keine projektgebundene Rollen-ID +des Referenzprojekts wird übertragen. Eine angezeigte Rolle ist keine Zusicherung, +dass dieselbe Definition im späteren Zielprojekt existiert; sie muss dort als eigene +Rolle definiert oder als verfügbare Zielrolle vor Veröffentlichung qualifiziert werden. + +Public-Projektvorlagen mit aktiviertem lokalem Netz können die Observability- +Bindung ebenso wie Corporate-Vorlagen als symbolischen Entwurf auswählen. +Ohne Projektnetz ist die Auswahl gesperrt. Die ACL-Bindung wird nur bei aktiviertem +Observability ausgewertet. Wird Observability bei der Bestellung ausgeschaltet, +bleibt das Projektnetz erhalten; die inaktive ACL-Bindung erzeugt weder eine +Ressourcenbindung noch einen Qualifikationsblocker. Die Template-Policy bleibt +unverändert. Ein symbolischer Snapshot darf im Testkatalog gespeichert werden; +produktive Freigabe und Ausführung der aktiven ACL-Bindung bleiben für beide +Netzarten ohne nachgewiesene öffentliche Egress-Adresse gesperrt. + + + +## Ausgangsproblem und überprüfte Accelerator-Grenzen + +Die jetzigen `ProjectTemplateDraft.settings` bewahren hauptsächlich konkrete +Accelerator-Einstellungen. Sie unterscheiden weder feste Policy von überschreibbaren +Defaults noch Ressourcenbindungen von literalen Werten. Der vorhandene +Application-Vertrag ist ein nicht freigegebener Prototyp und muss entsprechend +weiterentwickelt werden. Die Oberfläche darf keine vollständige Parametrisierung suggerieren. + +- `env` ist derzeit eine feste Einstellung, für neue Public-/Corporate-Entwürfe `dev`. + In `src/main.tf` fließt der Wert in Naming und DNS ein. +- `src/modules/landing-zone/8-observability.tf` übergibt `var.observability.acl` + unverändert. Eine Bindung an ein erzeugtes Netzwerk fehlt. +- `src/modules/landing-zone/3-network.tf` erzeugt weiterhin ein geroutetes Netzwerk + bei `corporate=true`, zusätzlich jetzt ein lokales Netz für Public-Projekte bei + `network_enabled=true`. Beide sind Modulressourcen; Sandbox gesondert qualifizieren. +- Die spätere ACL muss die am Dienst wirksame Quelladresse berücksichtigen: + Ein Projekt-CIDR ist bei NAT oder anderen Zugriffswegen möglicherweise nicht + die tatsächlich sichtbare Quelladresse. Die Produkt-/Netzwerksemantik ist vor + Ausführungsfreigabe mit Provider und realem Verbindungstest nachzuweisen. + + + +## Wertquellen statt frei interpretierbarer Platzhalter + +Jede freigegebene fachliche Eigenschaft erhält genau eine Wertquelle: + +| Quelle | Platform Engineer definiert | Application Owner sieht | +| --- | --- | --- | +| Fest vorgegeben | Konkreten typisierten Wert, z. B. Secrets Manager verpflichtend | Erklärte, schreibgeschützte Vorgabe | +| Bei Bestellung ausfüllen | Typ, Pflichtfeld, zulässige Werte/Grenzen, Erklärung, optionalen Default | Eingabe oder Dropdown innerhalb dieser Grenzen | +| Automatisch verknüpft | Freigegebene typisierte Ressourcenreferenz, z. B. eigenes Projektnetz | Beziehung und später aufgelösten Wert, kein Freitextfeld | +| Aus verifiziertem Kontext | Serverseitige Identitäts-/Tenant-/Plattformbindung | Herkunft und wirksamen Wert, keine überschreibbare ID | + +Das sind keine vier Optionen für jedes Feld: Organisation/Antragsteller dürfen +beispielsweise nur aus verifiziertem Kontext stammen; eine Dienstleistungsklasse +kann nur zugelassene Werte anbieten. Ein serverseitiges Feldregister bestimmt, +welche Quellen und Referenztypen je Ziel zulässig sind. Unbekannte Felder sind +nicht automatisch veränderbar. Keine beliebigen HCL-/JavaScript-Ausdrücke, +String-Interpolation oder ausführbaren Template-Skripte. + +Ein Default ist ein Vorschlag für eine erlaubte Bestelleingabe und keine feste +Policy. Pflicht, Zulässigkeit und Änderbarkeit sind getrennte Eigenschaften. +Secrets werden ausschließlich über autorisierte Secret-Referenzen eingebunden; +sie sind keine normalen Template-Parameter oder Vorschauwerte. + + + +## Umgebung / Stage + +Die **Auswahl einer konkreten Stage gehört normalerweise zur Bestellung**. +Das Template legt fest, welche Stages erlaubt sind und welche vorausgewählt ist, +beispielsweise `dev`, `test`, `prod` mit Default `dev`. Ein bewusstes +„Nur Produktion“-Angebot darf `prod` fest vorgeben. Die Auswahlwerte sind +Template-Policy, keine behauptete abschließende Accelerator-Enumeration. + +Stage ist zunächst nur bei Anlage wählbar. Da sie im heutigen Accelerator Namen +und DNS beeinflusst, wird eine spätere Änderung erst mit qualifiziertem +Updatevertrag, sichtbarem Ressourcen-Diff und möglicher Ersatzwirkung angeboten. +Keine automatische Umbenennung bestehender Ressourcen. Der Application-Compiler +muss ihre konkrete Wirkung in Naming/Labels/DNS ausdrücklich abbilden; der aktuelle +Application-Prototyp erfüllt diesen Vertrag noch nicht. + + + +## Beispiel: STACKIT Observability und eigenes Projektnetz + +Der Platform Engineer definiert: + +- STACKIT Observability wird erstellt (oder ist innerhalb definierter Policy optional). +- Leistungsklasse fest oder Auswahl aus freigegebenen, für das Ziel gültigen Klassen. +- Zugriffsregel: **Eigenes Projektnetz** statt einer vorab ausgedachten CIDR. +- Referenz auf das konkrete, von dieser Instanz verwaltete Netzwerk. Bei mehreren + Netzen ist ein explizites Netz oder eine ausdrücklich definierte Menge erforderlich. + +Das gespeicherte Template enthält eine typisierte Referenz, sinngemäß +`Observability → Zugriffsquellen → Projektnetz dieser Instanz`. Es enthält noch +keine vom Besteller einzutragende CIDR. Der Compiler übersetzt diese Beziehung +innerhalb eines States in eine echte OpenTofu-Ressourcenreferenz. Ist die Adresse +beim Plan unbekannt, zeigt die Vorschau „wird bei Bereitstellung ermittelt“ mit +Herkunft an; der Abhängigkeitsgraph löst sie beim Apply auf. Keine Vorabauflösung +per API auf ein noch nicht existierendes Netz und keine CIDR-Platzhalter in tfvars. + +Fehlt das Netz oder passt sein Adresstyp/Zugriffsweg nicht, ist die Kombination +nicht veröffentlichbar bzw. nicht instanziierbar. **Kein stiller Rückfall auf +leere ACL oder `0.0.0.0/0`.** Bei Observability bedeutet eine leere ACL Vollzugriff +auf Netzwerkebene. Auch eine Public-Vorlage mit lokalem Netz benötigt eine +qualifizierte Egress-Strategie, bevor sie „eigenes Projektnetz“ als ausführbare +ACL-Quelle anbieten kann. Als symbolischer Entwurf ist die Bindung auswählbar. + + + +## Allgemeine Verknüpfungen und State-Eigentum + +Referenzen benötigen Ressourcentyp, erlaubtes Ausgabeattribut, Tenant/Instanz- +oder Plattformbezug und Kardinalität. Beispiele sind Cluster für Namespace, +SNA für Corporate-Netz, Zielordner für Projekt, Observability-Anbindung und +verifizierter Antragsteller für eine genehmigte IAM-Zuweisung. Nicht alle diese +Verknüpfungen werden bereits vom Accelerator unterstützt. + +Referenzen innerhalb einer Instanz werden im OpenTofu-Graph verbunden. +Plattformreferenzen kommen aus einer geprüften Vertragsversion, niemals aus +beliebigen fremden State-Dateien oder Benutzer-UUIDs. Auflösung prüft Tenant, +Region, Typ, Berechtigung, Existenz und Lebenszyklus; Zyklen werden abgewiesen. +Ein Template darf nicht über einen Parameter auf fremde Tenants zugreifen. + +Eine gemeinsam genutzte Plattforminstanz bleibt im Plattform-State. Wenn eine +Application deren ACL erweitern müsste, darf ihr State diese ACL nicht ebenfalls +verwalten. Dafür ist ein eigener, autorisierter Registrierungs-/Abmeldeablauf beim +Plattformeigentümer nötig, einschließlich Parallelität und Rücknahme bei Löschung. +Bis dieser existiert, wird die Kombination nicht zur Ausführung freigegeben. + + + +## Veröffentlichung, Bestellung und Änderungen + +1. Editor: Pro freigegebenem Feld sichtbare Quelle und bei Bestelleingaben Constraints. +2. Veröffentlichung: Typen, Defaults, Bindungsgraph, Pflichtabhängigkeiten und + Compiler-/Accelerator-Fähigkeiten prüfen; unveränderliche Version erzeugen. +3. Bestellung: Formular ausschließlich aus freigegebenem Eingabeschema erzeugen. +4. Server: unbekannte/gesperrte Inputs ablehnen, erlaubte Werte erneut prüfen, + Kontext binden und deterministisch kompilieren. Gleiches gilt für Chat/API. +5. Plan: konkrete Werte und noch unbekannte Ressourcenwerte samt Herkunft zeigen. + Plan/Freigabe an Template-Version, Eingaben, Plattformvertrag und Compiler binden. +6. Update: nur ausdrücklich als veränderbar qualifizierte Eingaben zulassen; + Template-Upgrade bleibt explizit. Vorlagenänderungen verändern keine Instanzen. + +Persistiert werden Template-Policy, Bestelleingaben und Auflösungsnachweis getrennt. +Jedes wirksame Feld hat eine Herkunft. Bestehende Entwürfe behalten ihre Werte +zunächst als feste Vorgaben; der Platform Engineer macht sie ausdrücklich zu +Bestelleingaben oder Bindungen. Keine automatische Freigabe bisher gesperrter Werte. + + + +## Umsetzungsreihenfolge / Abnahme + +- [x] Lücke und konkrete Accelerator-Grenzen im Code geprüft. +- [x] Versionierten Parameter-/Binding-Vertrag mit fünf freigegebenen Feldern implementieren (#92); weitere Felder bleiben fest. +- [x] Stage als erste vollständige Bestelleingabe mit Default, Auswahl und festen Werten; + unverändertes Lesen alter Entwürfe, explizite Konvertierung. +- [x] Template-Editor und lokale Bestellvorschau aus demselben Vertrag erzeugen. +- [x] Veröffentlichten Tenant-Katalog anbinden (#92/#93); reale unveraenderliche Version 1 lokal abgenommen. +- [ ] Echte Application-Owner-Bestellung mit anschliessendem Plan/Apply abnehmen (#93). +- [x] Compiler prüft Policy unabhängig vom Formular bei manipulierten Eingaben; Tests für + unbekannte Felder, unzulässige Defaults, Tenantwechsel und Versionsbindung. +- [ ] Accelerator-Modul um typisierte Projekt-Netz-/Observability-Bindung erweitern; + erst Provider-/ACL-/Egress-Semantik nachweisen, dann native Graph-/Plan-Tests. +- [ ] Fehlendes Netz, deaktivierter Quelldienst, mehrere Netze und zyklische oder + regionsfremde Bindungen verhindern Veröffentlichung/Instanziierung. +- [ ] Plan mit unbekannten Ressourcenwerten und später korrekter ACL qualifizieren; + echter Kunden-Apply ausschließlich nach ausdrücklicher Freigabe. +- [ ] Weitere Dienstverknüpfungen nach demselben Muster ergänzen; gemeinsame + Plattform-ACLs erst nach Umsetzung des einzelnen State-Eigentümers freigeben. + +Diese Arbeiten sind Voraussetzung eines nutzbaren Application-Self-Service, +kein nachträglicher Komfortausbau eines bereits vollständigen MVP. + + + +## Validierung und Bereitstellung + +- Lokale Domain-/App-Tests und native Application-Mockpläne prüfen die neue Policy + sowie Stage-Naming, Legacy-Erhalt und die harte Netzwerkbindungs-Sperre. +- Browserprüfung und Release-Nachweis werden nach erfolgreicher Bereitstellung ergänzt. +- Kein Kunden-Apply und keine automatische Änderung vorhandener Projekte. + + + +### Reale Template-Veroeffentlichung (2026-10-06) + +Das bestehende Public-Template wurde als Version 1 aus dem gespeicherten Entwurf +veroeffentlicht: Region eu01, lokales Projektnetz, freigegebener serverbasierter +Plattformvertrag, Ziel `public-eu01`, automatische Gruppe **Application Owners** +und **Bereitstellung mit Freigabe**. Der Vertrag stammt aus dem erfolgreichen +aktuellen Plattform-Apply mit State-Version 6; alte Applies und rohe States sind +keine frei waehlbaren Quellen. Der Katalog zeigt dieselbe Version nach Reload. +Veroeffentlichung erzeugt keine Cloud-Ressourcen, Application-Ausfuehrung bleibt +deaktiviert. Eine echte Application-Owner-Bestellung und Cloud-Ausfuehrung sind +damit noch nicht abgenommen. + +Eigene Gruppen werden in **Benutzerverwaltung** angelegt, mit Mitgliedern +besetzt und geloescht; die Veroeffentlichung verwaltet nur deren Template-Freigaben. +**Erfolgreicher Plattform-Apply** zeigt Konfigurationsname und Abschlussdatum +statt eines State-Key-Hashes. Auswaehlbar sind nur erfolgreiche, aktuelle, +unverriegelte Applies im verifizierten Arbeitsbereich mit gueltigem menschlichem +Organisationsnachweis. Dessen Erneuerung bleibt auch nach Organisationsbindung +in der Benutzerverwaltung erreichbar. diff --git a/landing-zone-configurator/docs/template-parameters-and-bindings.md b/landing-zone-configurator/docs/template-parameters-and-bindings.md index 397bcc5..97bf018 100644 --- a/landing-zone-configurator/docs/template-parameters-and-bindings.md +++ b/landing-zone-configurator/docs/template-parameters-and-bindings.md @@ -1,422 +1,187 @@ -# Projekt-Templates: Eingaben, feste Vorgaben und Ressourcenverknüpfungen - -## Aktueller MVP: ACL-Einrichtung durch den Benutzer - -Stand: 2026-10-08. Die Observability-ACL ist kein Configurator-Parameter mehr. -Editor, Bestellformular und Vorschau bieten weder CIDR-Auswahl noch -Projektnetz-Bindung an. Eine aktivierte Observability-Instanz erzeugt keinen -ACL-Pflichtfeld- oder Egress-Qualifikationsblocker. Der Benutzer richtet die -Zugriffsquellen selbst direkt in STACKIT ein; der Configurator ermittelt oder -konfiguriert keinen automatischen Zugangsweg. - -Gespeicherte ACL-Werte und alte Policies bleiben in ihren Vorlagen erhalten. -Alte ACL-Bestelleingaben und Policies werden bei neuer Auflösung ignoriert; -vorhandene feste Werte bleiben als Kompatibilitätswerte erhalten. Es wird kein -privates Projektnetz in Internet-Quelladressen übersetzt. - -Die neue native Application-Revision `88149782bf8e91dcdbb43a203b54337886023f7f` -verwendet `ignore_changes = [acl]`, damit spätere manuelle ACL-Änderungen keinen -Terraform-Änderungsplan auslösen. Der STACKIT-Provider setzt beim Erstellen -weiterhin den anfänglichen ACL-Wert und überträgt bei anderen Instance-Updates -den eingelesenen Wert erneut. Eine gleichzeitige manuelle Änderung zwischen -Plan und Apply ist dadurch nicht gegen Überschreiben geschützt. - -Neue Veröffentlichungen nutzen die aktiv angebotene Runner-Revision. -Bestehende veröffentlichte Versionen, Bestellungen und Saved Plans werden nicht -umgebunden. Für sie ist eine neue Veröffentlichung mit anschließender neuer -Bestellung erforderlich; alte Pakete und Historie bleiben erhalten. Die -folgenden ACL-Bindungsbeschreibungen dokumentieren den früheren Entwurfsstand, -nicht den aktuellen MVP. - -Stand: 2026-10-06. Parametervertrag, Template-Editor, tenantgebundener Testkatalog, persistente Bestellaufträge und serverbasierte Applied-Platform-Bindung implementiert. Live-Aktivierung und menschliche Abnahme, Application-Cloud-Plan und produktive Instanziierung bleiben offen. Dieser Stand ist lokal, noch nicht veröffentlicht. -Ergänzt [Projekt-Template-Entwürfe](project-template-drafts.md) und die -[Plattform-/Application-Architektur](platform-application-architecture.md). - -## Serverbasierte Plattformbindung - -Bei aktivierter Capability `appliedPlatformsEnabled` waehlt der Platform Engineer -eine erfolgreich angewendete Plattform seines aktiven Tenants und laesst den -Server die nicht geheimen Plattformziele vorpruefen. Nur abgeschlossene Applies -mit weiterhin passender, unverriegelter State-Version und aktuellem menschlichen -Nachweis fuer die verifizierte Organisation stehen zur Auswahl. -Der normale Weg verlangt keinen JSON-Transfer; der Datei-Import bleibt lediglich -als Kompatibilitaetsweg fuer aeltere APIs erhalten. - -Die Vorschau liefert Ziele und einen Source-Beleg aus Apply-ID, State-Key und -Version, urspruenglicher Vertragsrevision und SHA-256 des validierten Dokuments. -Zur ausdruecklichen Freigabe sendet der Browser nur diesen Beleg, Zustimmung und -die gewaehlte technische Profil-ID. Ziele und Organisation kommen erneut vom -Server, nicht aus kopierten Browserdaten. Menschlicher Nachweis, aktueller State -und technischer Zugriff werden erneut geprueft. Aenderungen waehrend der Pruefung -verhindern die Uebernahme. Die Quelle bleibt append-only und tenantgebunden; -konkurrierende Wiederholungen mit demselben geprueften Zugang sind idempotent. - -Die Freigabe reserviert keine neue Cloud-Ausfuehrung und aendert keine vorhandene -Application-Instanz. Alte Bestellungen behalten ihre Vertragsrevision; ein neuer -Plattform-Apply bindet sie nicht automatisch um. Die API-Erweiterung und Migration -036 sind lokal qualifiziert, aber nicht Teil des laufenden Login-only-Standes 034. -Gruppenmigration 035 und Source-Migration 036 benoetigen eine separate Aktivierung. -Echte Application-Plans, explizite Applies, Drift und Upgrades bleiben eigenstaendige -Folgeschritte in #93. Der eigenstaendige Accelerator bleibt unabhaengig nutzbar. - -## Aufgaben in der Oberflaeche - -Der Editor-Schritt **Template-Entwürfe** bearbeitet unveröffentlichte Vorlagen. -Die Seite **Application Landing Zones** trennt die weiteren Aufgaben in Reiter: -**Katalog** für veröffentlichte Versionen und Bestellformulare sowie -**Bestellungen** für gespeicherte Instanzen und deren Details. -Platform Engineers sehen zusätzlich **Veröffentlichung** und -**Plattformanbindung**; berechtigte Gruppenmanager sehen **Gruppen**. -Application Owner erhalten keine Verwaltungsreiter. Nach erfolgreicher -Veröffentlichung öffnet sich der Katalog, nach einer Bestellung deren Auftragsbereich. - -Die Plattformanbindung ist keine Veröffentlichung eines Templates und keine -Cloud-Ausführung. Der normale, serverbasierte Weg benötigt keinen Datei-Upload. -Bei älteren APIs liegt der bisherige Upload eingeklappt unter -**Kompatibilitätsimport**. Hier gehört ausschließlich der exportierte JSON-Vertrag -einer tatsächlich angewendeten Platform Landing Zone hinein, nicht ein beliebiges -JSON, Terraform-State, tfvars oder Zugangsdaten. Der Vertrag enthält die -Organisations-ID und freigegebene Zielordner mit ihren Plattformreferenzen; -der Server prüft ihn vor einer ausdrücklichen Freigabe. - -Diese UI-Trennung ist lokal qualifiziert. Sie aktiviert weder die Migrationen -035/036 noch ein Backend-Feature oder eine Application-Cloud-Ausführung. - -## Implementierter Umfang - -`ProjectTemplateDraft.parameterPolicy` (Version 1) definiert die Wertquelle je -freigegebenem Feld. Die fünf ersten Felder sind Stage, Secrets-Manager-Aktivierung, -Observability-Aktivierung, Observability-Leistungsklasse und Observability-ACL. -Zusätzlich können Projektrollen über `source: context` und die typisierte Variable -`verified-project-owner` bei der Instanziierung zugeordnet werden. Alle anderen -Einstellungen bleiben fest; Sandbox-Parameter sind noch nicht qualifiziert. -String-Eingaben benötigen eine explizite Auswahlliste, ACL-Eingaben eine Auswahl -zulässiger CIDRs; eine leere ACL-Bestellung ist gesperrt. Eine noch leere, erforderliche -ACL-Auswahlliste ohne Vorauswahl darf als Entwurf bearbeitet werden; die Vorschau -und Auflösung bleiben bis zur gültigen Bestelleingabe gesperrt. Feste ältere Einstellungen -werden nicht automatisch umgedeutet. Defaults, Pflichtfelder, Herkunft und -unzulässige Overrides werden durch denselben Domain-Resolver geprüft, den der -Application-Compiler verwendet. Dies gilt auch beim Speichern der Template-Policy. - -Neue Vorlagen erlauben Stage-Auswahl; neue Preset-Entwürfe behalten die Stage des -Beispiels als Vorauswahl, neu hinzugefügte Vorlagen verwenden `dev`. Die -explizite Übernahme einer bestehenden Konfiguration als Plattformkopie behält -hingegen feste Vorgaben. Das JSON im Fork speichert die Policy; der Plattform- -tfvars-Export enthält weiterhin keine Template-Instanzen. - -Unter **Bestellung testen** erzeugt der Editor aus der Policy ein lokales Formular -mit wirksamen Werten und Herkunft. Das ist keine öffentliche Application-Owner- -Bestellung und führt keine Cloudzugriffe aus. Der veröffentlichte Application- -Vertragsprototyp Version 2 akzeptiert diese Policy und prüft Bestelleingaben, -Tenant-/Plattformbindung und konkrete Dienstwerte erneut. Version 1 bleibt -kompatibel. Ausführung bleibt ausdrücklich deaktiviert. - -Die Projektnetz-Bindung wird symbolisch gespeichert und ist sowohl in der -Vorschau als auch nativ im Application-Root gesperrt. Ihre produktive Egress- -Auflösung wird in [#96](https://github.com/stackitcloud/stackit-landing-zone/issues/96) -verfolgt. Der Runner-Pin bleibt unverändert; diese Ergänzungen geben keine -produktive Ausführung frei. - -## Tenantgebundener Testkatalog und Bestellungen - -Die Seite `/applications` trennt veröffentlichte Versionen von bearbeitbaren -Projekt-Template-Entwürfen. Der Server speichert den vollständigen validierten -Snapshot samt Policy, Tenant, Template-ID, fortlaufender Version, Veröffentlichendem, -Zeitpunkt und festem Accelerator-Pin. Gleicher Snapshot mit gleichem Pin liefert -dieselbe letzte Version; Änderungen erzeugen eine neue. Frühere Versionen werden -weder verändert noch automatisch auf Bestellungen übertragen. Sandbox-Veröffentlichungen -und leere Bestell-Auswahllisten bleiben gesperrt. - -Platform Engineers veröffentlichen aus dem aktuellen Entwurf. Application Owner -sehen nur Versionen ihres aktiven Tenants und benötigen keinen persönlichen Fork. -Der persönliche Arbeitsbereich erlaubt seinem bisherigen Admin die Vorbereitung -dieses Testkatalogs. Unverifizierte Organisationsarbeitsbereiche dürfen damit Daten -vorbereiten, erhalten aber keine STACKIT-Ausführungsrechte. Eine Katalogversion ist -noch keine für reale Kunden verifiziert freigegebene Ressourcenvorlage. - -Die Bestellung enthält nur Versions-ID, Projektname, erlaubte Parameter und einen -UUID-Idempotenzschlüssel. Tenant und Antragsteller stammen aus der serverseitig -aufgelösten Session; Owner-E-Mail, Plattform-ID und feste Einstellungen sind nicht -überschreibbar. Derselbe Schlüssel desselben Antragstellers im selben Tenant mit -identischen Eingaben liefert dieselbe Instanz. Abweichende Eingaben ergeben HTTP 409. -Der Browser behält den Schlüssel für Wiederholung und Netzwerk-Retry des laufenden -Bestellformulars. Ein neu geöffnetes oder geändertes Formular ist ein neuer Auftrag; -es besteht keine automatische Zusammenführung nach Projektnamen. - -Jede Bestellung erhält eine eigene serverseitige Instanz-ID und reserviert -`applications///terraform.tfstate` als State-Key. Die Bestellung -erzeugt **noch keine State-Datei und kein STACKIT-Projekt**. Feste Einstellungen, -aufgelöste Eingaben und Qualifizierungsblocker werden dauerhaft gespeichert. -Application Owner sehen nur eigene Aufträge, Platform Engineers die Aufträge ihres -Tenants. PostgreSQL erzwingt RLS, aktuelle Produktrollen und unveränderliche Versionen; -ein Wechsel des aktiven Tenants während der Anfrage wird abgewiesen. Ein Arbeitsbereich -mit veröffentlichten Versionen oder Bestellungen kann nicht als leerer Entwurf -archiviert werden. - -Der Planstatus ist stets `blocked` und `executionEnabled=false`. Die Oberfläche -weist fehlende verifizierte STACKIT-Benutzeridentität, fehlenden freigegebenen -Plattformvertrag und den noch nicht freigegebenen Application-Runner aus. Ein -GitHub-Login oder ein Service-Account-Key wird nicht als menschlicher STACKIT-Nachweis -umgedeutet. Es gibt keine erfundenen Ressourcenanzahlen und keine Apply-Aktion. -Unaufgelöste Projektrollen und Egress-Bindungen bleiben zusätzliche Blocker. -Der vorhandene Application-Compiler wird dadurch nicht als Ausführungsbroker ausgegeben. - -Migration `010_application_catalogue.sql` und `LZC_APPLICATIONS_ENABLED=true` sind -für den Backend-Betrieb erforderlich; das Flag ist standardmäßig aus. Die neue -Migration wurde ausschließlich in der wegwerfbaren lokalen PostgreSQL-Testdatenbank -angewendet, nicht auf der CF-Datenbank. Bestehender Runner-Pin, Plattformvertrag und -Deployment-Pipeline werden nicht automatisch erweitert. - -Nachweise: Domain-/API-Tests, echte PostgreSQL-Session/RLS samt HTTP-Durchstich, -parallele Idempotenzprüfung, Rollenentzug und Desktop-/Mobil-Browserfälle. -Die Browserfälle verwenden simulierte API-Antworten; sie ersetzen keine Live-Abnahme -mit verifizierten STACKIT-Identitäten und keinen echten Cloud-Plan. - -## Lokales Projektnetz als Template-Vorgabe - -Ein Projektnetz ist Teil der Landing Zone, nicht erst der späteren VM-Anwendung. -Public-Projekt-Templates können deshalb mit `settings.network_enabled: true` -ein lokales, nicht SNA-geroutetes Netz anlegen. `network_prefix_length` legt -optional die Präfixlänge fest; ohne Vorgabe wird sie vom Dienst bestimmt. -Die Präfixlänge beschreibt die Netzgröße: `/24` umfasst 256 IPv4-Adressen, -`/25` 128 und `/26` 64. Größere Präfixzahlen bedeuten kleinere Netze; nicht alle -Adressen sind für VMs verfügbar. -Die Oberfläche bietet diese Einstellungen direkt im Projekt-Template an. -Netzanlage und Größe bleiben zunächst feste Vorgaben, keine Bestelleingaben. - -Bestehende Public-Templates ohne Netzoption bleiben unverändert. Corporate- -Templates behalten ihr automatisch erzeugtes geroutetes Netz und ihre SNA- -Zuordnung. Sandbox-Netze sind von dieser Erweiterung nicht erfasst. Eine Vorlage -für ein VM-Netz erstellt damit das Projekt und sein Netz, nicht bereits die VM. - -Die Einstellungen werden mit dem Template-Dokument im Fork gespeichert und -erzeugen beim Plattform-Export keine Projekte oder Netze. Der Application-Vertrag -Version 2 übernimmt sie als feste Vorgaben in den nativen Application-Root; -Version 1 bleibt unverändert. Das Modul gibt eine nicht geheime Netzreferenz aus. -Modul-, Application- und Standalone-Mockpläne prüfen lokale Netzanlage ohne SNA -sowie den Erhalt bisheriger Konfigurationen. Produktive Instanziierung und ein -realer Cloud-Apply sind weiterhin nicht freigegeben. - -Das lokale Netz ist keine automatische Observability-ACL-Quelle. Die -[Instanz-ACL](https://docs.stackit.cloud/products/logging-and-monitoring/observability/how-tos/control-instance-access/) -filtert die am Internet-Endpunkt sichtbaren Quelladressen gemeinsam für Grafana, -Metrics, Logs und Traces. Eine leere ACL stellt uneingeschränkten Netzwerkzugriff -wieder her. Private Netz-CIDRs dürfen daher nicht ohne nachgewiesene Egress- -Semantik als Quelladressen übernommen werden. - -## Kataloge und verifizierte Instanziierungsvariablen - -Die geladenen STACKIT-Produktkataloge gelten auch für die erlaubten Bestellwerte. -Bei der Freigabe der Observability-Leistungsklasse werden die aktuellen Optionen -angeboten und können über Checkboxen eingeschränkt werden. Nicht mehr im Katalog -enthaltene Bestandswerte bleiben erkennbar erhalten. Ohne verfügbaren Katalog bleibt -die manuelle Eingabe möglich; sie ist kein Nachweis der Cloud-Verfügbarkeit. -Dieselbe Katalogzuordnung wird im strukturierten Editor für Git, VPN, SKE, -Observability, Bastion und die neuen IAM-Felder verwendet. Nicht alle diese -Plattformfelder sind bereits als Projekt-Bestellparameter qualifiziert. - -Für Projektrollen definiert die Policy `source: context`, -`variable: verified-project-owner` und eine Rollenliste. Es werden keine persönlichen -E-Mail-Adressen oder frei interpretierbaren Platzhalter im Template gespeichert. -Die lokale Vorschau zeigt die unaufgelöste Identität und einen Blocker. Der Compiler -bindet ausschließlich `context.verified_stackit_email`, niemals GitHub-Login oder -eine vom Besteller übergebene Benutzerkennung. Bestehende feste Zuweisungen bleiben -erhalten. Doppelte Zuweisungen derselben Rolle an dieselbe Identität werden vermieden. -Die zusätzlichen Rollenzuweisungen und festen `custom_roles` werden im Application- -Vertrag Version 2 bis zum nativen Root weitergegeben; Version 1 bleibt unverändert. -Das ist weiterhin ein nicht zur produktiven Ausführung freigegebener Prototyp. - -Bei fest ausgeschaltetem Observability blendet der Template-Editor Leistungsklasse, -Zugriffsquellen, Instanzname und die entsprechenden Vorschauwerte aus. Gespeicherte -Werte und Policies bleiben erhalten und erscheinen beim Wiedereinschalten wieder. -Ist die Aktivierung erst bei der Bestellung wählbar, bleiben die benötigten -Template-Vorgaben konfigurierbar. Strukturierte Template-Dienste mit explizit -ausgeschaltetem `enabled`- oder benanntem `*_enabled`-Schalter blenden ihre -zugehörigen Details ebenfalls aus, ohne diese zu löschen. - -STACKIT-Rollenvorlagen übernehmen Name, Beschreibung und Permissions als bearbeitbare -eigene Rolle mit einem `application-`-Namenspräfix. Keine projektgebundene Rollen-ID -des Referenzprojekts wird übertragen. Eine angezeigte Rolle ist keine Zusicherung, -dass dieselbe Definition im späteren Zielprojekt existiert; sie muss dort als eigene -Rolle definiert oder als verfügbare Zielrolle vor Veröffentlichung qualifiziert werden. - -Public-Projektvorlagen mit aktiviertem lokalem Netz können die Observability- -Bindung ebenso wie Corporate-Vorlagen als symbolischen Entwurf auswählen. -Ohne Projektnetz ist die Auswahl gesperrt. Die ACL-Bindung wird nur bei aktiviertem -Observability ausgewertet. Wird Observability bei der Bestellung ausgeschaltet, -bleibt das Projektnetz erhalten; die inaktive ACL-Bindung erzeugt weder eine -Ressourcenbindung noch einen Qualifikationsblocker. Die Template-Policy bleibt -unverändert. Ein symbolischer Snapshot darf im Testkatalog gespeichert werden; -produktive Freigabe und Ausführung der aktiven ACL-Bindung bleiben für beide -Netzarten ohne nachgewiesene öffentliche Egress-Adresse gesperrt. - -## Ausgangsproblem und überprüfte Accelerator-Grenzen - -Die jetzigen `ProjectTemplateDraft.settings` bewahren hauptsächlich konkrete -Accelerator-Einstellungen. Sie unterscheiden weder feste Policy von überschreibbaren -Defaults noch Ressourcenbindungen von literalen Werten. Der vorhandene -Application-Vertrag ist ein nicht freigegebener Prototyp und muss entsprechend -weiterentwickelt werden. Die Oberfläche darf keine vollständige Parametrisierung suggerieren. - -- `env` ist derzeit eine feste Einstellung, für neue Public-/Corporate-Entwürfe `dev`. - In `src/main.tf` fließt der Wert in Naming und DNS ein. -- `src/modules/landing-zone/8-observability.tf` übergibt `var.observability.acl` - unverändert. Eine Bindung an ein erzeugtes Netzwerk fehlt. -- `src/modules/landing-zone/3-network.tf` erzeugt weiterhin ein geroutetes Netzwerk - bei `corporate=true`, zusätzlich jetzt ein lokales Netz für Public-Projekte bei - `network_enabled=true`. Beide sind Modulressourcen; Sandbox gesondert qualifizieren. -- Die spätere ACL muss die am Dienst wirksame Quelladresse berücksichtigen: - Ein Projekt-CIDR ist bei NAT oder anderen Zugriffswegen möglicherweise nicht - die tatsächlich sichtbare Quelladresse. Die Produkt-/Netzwerksemantik ist vor - Ausführungsfreigabe mit Provider und realem Verbindungstest nachzuweisen. - -## Wertquellen statt frei interpretierbarer Platzhalter - -Jede freigegebene fachliche Eigenschaft erhält genau eine Wertquelle: - -| Quelle | Platform Engineer definiert | Application Owner sieht | +# Project templates: inputs, fixed settings and resource bindings + +[English](template-parameters-and-bindings.md) | [Deutsch](template-parameters-and-bindings.de.md) + + + + +## Current MVP: user-managed ACL setup + +As of: 2026-10-08. The Observability ACL is no longer a Configurator parameter. Editor, order form and preview offer neither CIDR selection nor project-network binding. An enabled Observability instance produces no mandatory-ACL-field or egress-qualification blocker. Users configure access sources themselves directly in STACKIT; the Configurator neither determines nor configures an automatic access path. + +Saved ACL values and old policies remain in their templates. Old ACL order inputs and policies are ignored during new resolution; existing fixed values remain as compatibility values. No private project network is translated into Internet source addresses. + +The new native Application revision `88149782bf8e91dcdbb43a203b54337886023f7f` uses `ignore_changes = [acl]` so subsequent manual ACL changes do not trigger a Terraform change plan. The STACKIT provider still sets the initial ACL value at creation and resends the value it read during other instance updates. A concurrent manual change between Plan and Apply is therefore not protected against overwriting. + +New publications use the actively offered Runner revision. Existing published versions, orders and saved plans are not rebound. They require a new publication followed by a new order; old packages and history are retained. The following ACL binding descriptions document the earlier design, not the current MVP. + +As of: 2026-10-06. Parameter contract, template editor, tenant-bound test catalogue, persistent orders and server-based applied-platform binding implemented. Live activation and human acceptance, Application cloud Plan and production instantiation remain outstanding. This status is local, not yet published. Supplements [project template drafts](project-template-drafts.md) and the [Platform/Application architecture](platform-application-architecture.md). + + +## Server-based platform binding + +With capability `appliedPlatformsEnabled` enabled, the Platform Engineer selects a successfully applied platform of their active tenant and has the server precheck its non-secret platform targets. Only completed Applies with a still-matching, unlocked state version and current human evidence for the verified organization are available. The normal path requires no JSON transfer; file import remains only as a compatibility path for older APIs. + +The preview provides targets and source evidence comprising Apply ID, state key and version, original contract revision and SHA-256 of the validated document. For explicit approval, the browser sends only this evidence, consent and the selected technical profile ID. Targets and organization come from the server again, not copied browser data. Human evidence, current state and technical access are checked again. Changes during checking prevent adoption. The source remains append-only and tenant-bound; concurrent repetitions with the same checked access are idempotent. + +Approval reserves no new cloud execution and changes no existing Application instance. Old orders retain their contract revision; a new platform Apply does not rebind them automatically. The API extension and migration 036 are locally qualified but not part of the running login-only status 034. Group migration 035 and source migration 036 need separate activation. Real Application Plans, explicit Applies, drift and upgrades remain independent follow-up steps in #93. The standalone Accelerator remains independently usable. + + +## Tasks in the UI + +The editor step **Template drafts** edits unpublished templates. The **Application Landing Zones** page separates further tasks into tabs: **Catalogue** for published versions and order forms and **Orders** for saved instances and their details. Platform Engineers additionally see **Publication** and **Platform binding**; authorized group managers see **Groups**. Application Owners receive no management tabs. Successful publication opens the catalogue; ordering opens its order area. + +Platform binding is neither template publication nor cloud execution. The normal, server-based path needs no file upload. For older APIs, the previous upload is collapsed under **Compatibility import**. This accepts exclusively the exported JSON contract of an actually applied Platform Landing Zone, not arbitrary JSON, Terraform state, tfvars or credentials. The contract contains the organization ID and approved target folders with their platform references; the server checks it before explicit approval. + +This UI separation is locally qualified. It activates neither migrations 035/036 nor a backend feature or Application cloud execution. + + +## Implemented scope + +`ProjectTemplateDraft.parameterPolicy` (version 1) defines the value source for each approved field. The first five fields are stage, Secrets Manager activation, Observability activation, Observability performance class and Observability ACL. Additionally, project roles can be assigned at instantiation through `source: context` and the typed variable `verified-project-owner`. All other settings remain fixed; sandbox parameters are not yet qualified. String inputs need an explicit selection list, ACL inputs a selection of permitted CIDRs; an empty ACL order is blocked. A still-empty required ACL selection list without a preselection may be edited as a draft; preview and resolution remain blocked until valid order input exists. Older fixed settings are not automatically reinterpreted. Defaults, required fields, provenance and prohibited overrides are checked by the same domain resolver used by the Application compiler. This also applies when saving template policy. + +New templates allow stage selection; new preset drafts keep the example's stage as preselection, newly added templates use `dev`. Explicit adoption of an existing configuration as a platform copy instead retains fixed settings. JSON in the fork saves the policy; platform tfvars export still contains no template instances. + +Under **Test order**, the editor creates a local form from the policy, showing effective values and provenance. This is not a public Application Owner order and performs no cloud access. Published Application contract prototype version 2 accepts this policy and rechecks order inputs, tenant/platform binding and concrete service values. Version 1 remains compatible. Execution remains explicitly disabled. + +The project-network binding is stored symbolically and blocked both in preview and natively in the Application root. Its production egress resolution is tracked in [#96](https://github.com/stackitcloud/stackit-landing-zone/issues/96). The Runner pin remains unchanged; these additions do not approve production execution. + + +## Tenant-bound test catalogue and orders + +The `/applications` page separates published versions from editable project template drafts. The server stores the complete validated snapshot with policy, tenant, template ID, sequential version, publisher, timestamp and fixed Accelerator pin. The same snapshot with the same pin returns the same latest version; changes create a new one. Earlier versions are neither changed nor automatically transferred to orders. Sandbox publications and empty order selection lists remain blocked. + +Platform Engineers publish from the current draft. Application Owners see only versions of their active tenant and need no personal fork. The personal workspace allows its previous admin to prepare this test catalogue. Unverified organization workspaces may prepare data this way but receive no STACKIT execution permissions. A catalogue version is not yet a resource template verifiably approved for real customers. + +The order contains only version ID, project name, permitted parameters and a UUID idempotency key. Tenant and requester come from the server-resolved session; owner email, platform ID and fixed settings cannot be overridden. The same key for the same requester in the same tenant with identical inputs returns the same instance. Different inputs return HTTP 409. The browser retains the key for repetition and network retry of the running order form. A newly opened or modified form is a new order; there is no automatic merging by project name. + +Each order receives its own server-side instance ID and reserves `applications///terraform.tfstate` as its state key. Ordering creates **neither a state file nor a STACKIT project yet**. Fixed settings, resolved inputs and qualification blockers are stored persistently. Application Owners see only their own orders; Platform Engineers see orders of their tenant. PostgreSQL enforces RLS, current product roles and immutable versions; switching the active tenant during a request is rejected. A workspace with published versions or orders cannot be archived as an empty draft. + +Plan status is always `blocked` and `executionEnabled=false`. The UI identifies missing verified STACKIT user identity, missing approved platform contract and the Application Runner not yet being approved. A GitHub login or service-account key is not reinterpreted as human STACKIT evidence. There are no invented resource counts or Apply action. Unresolved project roles and egress bindings remain additional blockers. This does not present the existing Application compiler as an execution broker. + +Migration `010_application_catalogue.sql` and `LZC_APPLICATIONS_ENABLED=true` are required for backend operation; the flag is off by default. The new migration was applied exclusively in the disposable local PostgreSQL test database, not in the CF database. Existing Runner pin, platform contract and deployment pipeline are not automatically extended. + +Evidence: domain/API tests, real PostgreSQL session/RLS with an HTTP end-to-end path, concurrent idempotency checks, role revocation and desktop/mobile browser cases. Browser cases use simulated API responses; they replace neither live acceptance with verified STACKIT identities nor a real cloud Plan. + + +## Local project network as a template setting + +A project network is part of the Landing Zone, not just the later VM application. Public project templates can therefore create a local, non-SNA-routed network with `settings.network_enabled: true`. `network_prefix_length` optionally sets the prefix length; without a setting, the service determines it. Prefix length describes network size: `/24` comprises 256 IPv4 addresses, `/25` 128 and `/26` 64. Larger prefix numbers mean smaller networks; not all addresses are available for VMs. The UI offers these settings directly in the project template. Network creation and size initially remain fixed settings, not order inputs. + +Existing Public templates without a network option remain unchanged. Corporate templates retain their automatically created routed network and SNA assignment. Sandbox networks are not covered by this extension. A template for a VM network therefore creates the project and its network, not yet the VM. + +Settings are saved with the template document in the fork and create no projects or networks during platform export. Application contract version 2 passes them as fixed settings to the native Application root; version 1 remains unchanged. The module outputs a non-secret network reference. Module, Application and standalone mock plans check local network creation without SNA and preservation of existing configurations. Production instantiation and a real cloud Apply are still not approved. + +The local network is not an automatic Observability ACL source. The [instance ACL](https://docs.stackit.cloud/products/logging-and-monitoring/observability/how-tos/control-instance-access/) filters source addresses visible at the Internet endpoint jointly for Grafana, metrics, logs and traces. An empty ACL restores unrestricted network access. Private network CIDRs must therefore not be adopted as source addresses without demonstrated egress semantics. + + +## Catalogues and verified instantiation variables + +Loaded STACKIT product catalogues also apply to permitted order values. When exposing the Observability performance class, current options are offered and can be restricted through checkboxes. Existing values no longer in the catalogue remain visibly retained. Without an available catalogue, manual input remains possible; it is not evidence of cloud availability. The same catalogue mapping is used in the structured editor for Git, VPN, SKE, Observability, bastion and the new IAM fields. Not all these platform fields are already qualified as project order parameters. + +For project roles, policy defines `source: context`, `variable: verified-project-owner` and a role list. No personal email addresses or freely interpretable placeholders are stored in the template. Local preview shows the unresolved identity and a blocker. The compiler binds exclusively `context.verified_stackit_email`, never GitHub login or a user identifier supplied by the requester. Existing fixed assignments are retained. Duplicate assignments of the same role to the same identity are avoided. Additional role assignments and fixed `custom_roles` are passed through Application contract version 2 to the native root; version 1 remains unchanged. This is still a prototype not approved for production execution. + +When Observability is fixed off, the template editor hides performance class, access sources, instance name and corresponding preview values. Saved values and policies are retained and reappear when re-enabled. If activation is selectable only at ordering, required template settings remain configurable. Structured template services with an explicitly disabled `enabled` or named `*_enabled` switch likewise hide their associated details without deleting them. + +STACKIT role templates copy name, description and permissions into an editable custom role with an `application-` name prefix. No project-bound role ID from the reference project is transferred. A displayed role is no assurance that the same definition exists in the later target project; it must be defined there as a custom role or qualified as an available target role before publication. + +Public project templates with a local network enabled can select the Observability binding as a symbolic draft just like Corporate templates. Without a project network, selection is blocked. The ACL binding is evaluated only when Observability is enabled. If Observability is disabled at ordering, the project network remains; the inactive ACL binding produces neither a resource binding nor a qualification blocker. Template policy remains unchanged. A symbolic snapshot may be stored in the test catalogue; production approval and execution of the active ACL binding remain blocked for both network types without a demonstrated public egress address. + + +## Initial problem and verified Accelerator limitations + +Current `ProjectTemplateDraft.settings` mainly preserve concrete Accelerator settings. They distinguish neither fixed policy from overridable defaults nor resource bindings from literal values. The existing Application contract is an unapproved prototype and must be developed accordingly. The UI must not suggest complete parameterization. + +- `env` is currently a fixed setting, `dev` for new Public/Corporate drafts. In `src/main.tf`, the value flows into naming and DNS. +- `src/modules/landing-zone/8-observability.tf` passes `var.observability.acl` unchanged. Binding to a created network is missing. +- `src/modules/landing-zone/3-network.tf` still creates a routed network when `corporate=true`, now additionally a local network for Public projects when `network_enabled=true`. Both are module resources; qualify sandbox separately. +- The later ACL must consider the source address effective at the service: a project CIDR may not be the actual visible source address with NAT or other access paths. Product/network semantics must be demonstrated with the provider and a real connection test before execution approval. + + +## Value sources instead of freely interpretable placeholders + +Each approved business property receives exactly one value source: + +| Source | Platform Engineer defines | Application Owner sees | | --- | --- | --- | -| Fest vorgegeben | Konkreten typisierten Wert, z. B. Secrets Manager verpflichtend | Erklärte, schreibgeschützte Vorgabe | -| Bei Bestellung ausfüllen | Typ, Pflichtfeld, zulässige Werte/Grenzen, Erklärung, optionalen Default | Eingabe oder Dropdown innerhalb dieser Grenzen | -| Automatisch verknüpft | Freigegebene typisierte Ressourcenreferenz, z. B. eigenes Projektnetz | Beziehung und später aufgelösten Wert, kein Freitextfeld | -| Aus verifiziertem Kontext | Serverseitige Identitäts-/Tenant-/Plattformbindung | Herkunft und wirksamen Wert, keine überschreibbare ID | - -Das sind keine vier Optionen für jedes Feld: Organisation/Antragsteller dürfen -beispielsweise nur aus verifiziertem Kontext stammen; eine Dienstleistungsklasse -kann nur zugelassene Werte anbieten. Ein serverseitiges Feldregister bestimmt, -welche Quellen und Referenztypen je Ziel zulässig sind. Unbekannte Felder sind -nicht automatisch veränderbar. Keine beliebigen HCL-/JavaScript-Ausdrücke, -String-Interpolation oder ausführbaren Template-Skripte. - -Ein Default ist ein Vorschlag für eine erlaubte Bestelleingabe und keine feste -Policy. Pflicht, Zulässigkeit und Änderbarkeit sind getrennte Eigenschaften. -Secrets werden ausschließlich über autorisierte Secret-Referenzen eingebunden; -sie sind keine normalen Template-Parameter oder Vorschauwerte. - -## Umgebung / Stage - -Die **Auswahl einer konkreten Stage gehört normalerweise zur Bestellung**. -Das Template legt fest, welche Stages erlaubt sind und welche vorausgewählt ist, -beispielsweise `dev`, `test`, `prod` mit Default `dev`. Ein bewusstes -„Nur Produktion“-Angebot darf `prod` fest vorgeben. Die Auswahlwerte sind -Template-Policy, keine behauptete abschließende Accelerator-Enumeration. - -Stage ist zunächst nur bei Anlage wählbar. Da sie im heutigen Accelerator Namen -und DNS beeinflusst, wird eine spätere Änderung erst mit qualifiziertem -Updatevertrag, sichtbarem Ressourcen-Diff und möglicher Ersatzwirkung angeboten. -Keine automatische Umbenennung bestehender Ressourcen. Der Application-Compiler -muss ihre konkrete Wirkung in Naming/Labels/DNS ausdrücklich abbilden; der aktuelle -Application-Prototyp erfüllt diesen Vertrag noch nicht. - -## Beispiel: STACKIT Observability und eigenes Projektnetz - -Der Platform Engineer definiert: - -- STACKIT Observability wird erstellt (oder ist innerhalb definierter Policy optional). -- Leistungsklasse fest oder Auswahl aus freigegebenen, für das Ziel gültigen Klassen. -- Zugriffsregel: **Eigenes Projektnetz** statt einer vorab ausgedachten CIDR. -- Referenz auf das konkrete, von dieser Instanz verwaltete Netzwerk. Bei mehreren - Netzen ist ein explizites Netz oder eine ausdrücklich definierte Menge erforderlich. - -Das gespeicherte Template enthält eine typisierte Referenz, sinngemäß -`Observability → Zugriffsquellen → Projektnetz dieser Instanz`. Es enthält noch -keine vom Besteller einzutragende CIDR. Der Compiler übersetzt diese Beziehung -innerhalb eines States in eine echte OpenTofu-Ressourcenreferenz. Ist die Adresse -beim Plan unbekannt, zeigt die Vorschau „wird bei Bereitstellung ermittelt“ mit -Herkunft an; der Abhängigkeitsgraph löst sie beim Apply auf. Keine Vorabauflösung -per API auf ein noch nicht existierendes Netz und keine CIDR-Platzhalter in tfvars. - -Fehlt das Netz oder passt sein Adresstyp/Zugriffsweg nicht, ist die Kombination -nicht veröffentlichbar bzw. nicht instanziierbar. **Kein stiller Rückfall auf -leere ACL oder `0.0.0.0/0`.** Bei Observability bedeutet eine leere ACL Vollzugriff -auf Netzwerkebene. Auch eine Public-Vorlage mit lokalem Netz benötigt eine -qualifizierte Egress-Strategie, bevor sie „eigenes Projektnetz“ als ausführbare -ACL-Quelle anbieten kann. Als symbolischer Entwurf ist die Bindung auswählbar. - -## Allgemeine Verknüpfungen und State-Eigentum - -Referenzen benötigen Ressourcentyp, erlaubtes Ausgabeattribut, Tenant/Instanz- -oder Plattformbezug und Kardinalität. Beispiele sind Cluster für Namespace, -SNA für Corporate-Netz, Zielordner für Projekt, Observability-Anbindung und -verifizierter Antragsteller für eine genehmigte IAM-Zuweisung. Nicht alle diese -Verknüpfungen werden bereits vom Accelerator unterstützt. - -Referenzen innerhalb einer Instanz werden im OpenTofu-Graph verbunden. -Plattformreferenzen kommen aus einer geprüften Vertragsversion, niemals aus -beliebigen fremden State-Dateien oder Benutzer-UUIDs. Auflösung prüft Tenant, -Region, Typ, Berechtigung, Existenz und Lebenszyklus; Zyklen werden abgewiesen. -Ein Template darf nicht über einen Parameter auf fremde Tenants zugreifen. - -Eine gemeinsam genutzte Plattforminstanz bleibt im Plattform-State. Wenn eine -Application deren ACL erweitern müsste, darf ihr State diese ACL nicht ebenfalls -verwalten. Dafür ist ein eigener, autorisierter Registrierungs-/Abmeldeablauf beim -Plattformeigentümer nötig, einschließlich Parallelität und Rücknahme bei Löschung. -Bis dieser existiert, wird die Kombination nicht zur Ausführung freigegeben. - -## Veröffentlichung, Bestellung und Änderungen - -1. Editor: Pro freigegebenem Feld sichtbare Quelle und bei Bestelleingaben Constraints. -2. Veröffentlichung: Typen, Defaults, Bindungsgraph, Pflichtabhängigkeiten und - Compiler-/Accelerator-Fähigkeiten prüfen; unveränderliche Version erzeugen. -3. Bestellung: Formular ausschließlich aus freigegebenem Eingabeschema erzeugen. -4. Server: unbekannte/gesperrte Inputs ablehnen, erlaubte Werte erneut prüfen, - Kontext binden und deterministisch kompilieren. Gleiches gilt für Chat/API. -5. Plan: konkrete Werte und noch unbekannte Ressourcenwerte samt Herkunft zeigen. - Plan/Freigabe an Template-Version, Eingaben, Plattformvertrag und Compiler binden. -6. Update: nur ausdrücklich als veränderbar qualifizierte Eingaben zulassen; - Template-Upgrade bleibt explizit. Vorlagenänderungen verändern keine Instanzen. - -Persistiert werden Template-Policy, Bestelleingaben und Auflösungsnachweis getrennt. -Jedes wirksame Feld hat eine Herkunft. Bestehende Entwürfe behalten ihre Werte -zunächst als feste Vorgaben; der Platform Engineer macht sie ausdrücklich zu -Bestelleingaben oder Bindungen. Keine automatische Freigabe bisher gesperrter Werte. - -## Umsetzungsreihenfolge / Abnahme - -- [x] Lücke und konkrete Accelerator-Grenzen im Code geprüft. -- [x] Versionierten Parameter-/Binding-Vertrag mit fünf freigegebenen Feldern implementieren (#92); weitere Felder bleiben fest. -- [x] Stage als erste vollständige Bestelleingabe mit Default, Auswahl und festen Werten; - unverändertes Lesen alter Entwürfe, explizite Konvertierung. -- [x] Template-Editor und lokale Bestellvorschau aus demselben Vertrag erzeugen. -- [x] Veröffentlichten Tenant-Katalog anbinden (#92/#93); reale unveraenderliche Version 1 lokal abgenommen. -- [ ] Echte Application-Owner-Bestellung mit anschliessendem Plan/Apply abnehmen (#93). -- [x] Compiler prüft Policy unabhängig vom Formular bei manipulierten Eingaben; Tests für - unbekannte Felder, unzulässige Defaults, Tenantwechsel und Versionsbindung. -- [ ] Accelerator-Modul um typisierte Projekt-Netz-/Observability-Bindung erweitern; - erst Provider-/ACL-/Egress-Semantik nachweisen, dann native Graph-/Plan-Tests. -- [ ] Fehlendes Netz, deaktivierter Quelldienst, mehrere Netze und zyklische oder - regionsfremde Bindungen verhindern Veröffentlichung/Instanziierung. -- [ ] Plan mit unbekannten Ressourcenwerten und später korrekter ACL qualifizieren; - echter Kunden-Apply ausschließlich nach ausdrücklicher Freigabe. -- [ ] Weitere Dienstverknüpfungen nach demselben Muster ergänzen; gemeinsame - Plattform-ACLs erst nach Umsetzung des einzelnen State-Eigentümers freigeben. - -Diese Arbeiten sind Voraussetzung eines nutzbaren Application-Self-Service, -kein nachträglicher Komfortausbau eines bereits vollständigen MVP. - -## Validierung und Bereitstellung - -- Lokale Domain-/App-Tests und native Application-Mockpläne prüfen die neue Policy - sowie Stage-Naming, Legacy-Erhalt und die harte Netzwerkbindungs-Sperre. -- Browserprüfung und Release-Nachweis werden nach erfolgreicher Bereitstellung ergänzt. -- Kein Kunden-Apply und keine automatische Änderung vorhandener Projekte. - -### Reale Template-Veroeffentlichung (2026-10-06) - -Das bestehende Public-Template wurde als Version 1 aus dem gespeicherten Entwurf -veroeffentlicht: Region eu01, lokales Projektnetz, freigegebener serverbasierter -Plattformvertrag, Ziel `public-eu01`, automatische Gruppe **Application Owners** -und **Bereitstellung mit Freigabe**. Der Vertrag stammt aus dem erfolgreichen -aktuellen Plattform-Apply mit State-Version 6; alte Applies und rohe States sind -keine frei waehlbaren Quellen. Der Katalog zeigt dieselbe Version nach Reload. -Veroeffentlichung erzeugt keine Cloud-Ressourcen, Application-Ausfuehrung bleibt -deaktiviert. Eine echte Application-Owner-Bestellung und Cloud-Ausfuehrung sind -damit noch nicht abgenommen. - -Eigene Gruppen werden in **Benutzerverwaltung** angelegt, mit Mitgliedern -besetzt und geloescht; die Veroeffentlichung verwaltet nur deren Template-Freigaben. -**Erfolgreicher Plattform-Apply** zeigt Konfigurationsname und Abschlussdatum -statt eines State-Key-Hashes. Auswaehlbar sind nur erfolgreiche, aktuelle, -unverriegelte Applies im verifizierten Arbeitsbereich mit gueltigem menschlichem -Organisationsnachweis. Dessen Erneuerung bleibt auch nach Organisationsbindung -in der Benutzerverwaltung erreichbar. +| Fixed | Concrete typed value, e.g. mandatory Secrets Manager | Explained, read-only setting | +| Fill in at ordering | Type, required field, permitted values/limits, explanation, optional default | Input or dropdown within these limits | +| Automatically bound | Approved typed resource reference, e.g. own project network | Relationship and later resolved value, no free-text field | +| From verified context | Server-side identity/tenant/platform binding | Provenance and effective value, no overridable ID | + +These are not four options for every field: organization/requester, for example, may come only from verified context; a service performance class can offer only approved values. A server-side field registry determines permitted sources and reference types per target. Unknown fields are not automatically mutable. No arbitrary HCL/JavaScript expressions, string interpolation or executable template scripts. + +A default is a suggestion for a permitted order input, not fixed policy. Requirement, admissibility and mutability are separate properties. Secrets are incorporated exclusively through authorized secret references; they are not ordinary template parameters or preview values. + + +## Environment / stage + +**Selecting a specific stage normally belongs to ordering**. The template defines permitted stages and the preselected one, for example `dev`, `test`, `prod` with default `dev`. A deliberate “production only” offering may fix `prod`. Selection values are template policy, not a claimed exhaustive Accelerator enumeration. + +Stage is initially selectable only at creation. Since it affects names and DNS in today's Accelerator, later changes will only be offered with a qualified update contract, visible resource diff and potential replacement impact. No automatic renaming of existing resources. The Application compiler must explicitly represent its concrete effect on naming/labels/DNS; the current Application prototype does not yet fulfill this contract. + + +## Example: STACKIT Observability and own project network + +The Platform Engineer defines: + +- STACKIT Observability is created (or optional within defined policy). +- Performance class fixed or selected from approved classes valid for the target. +- Access rule: **Own project network** instead of an invented advance CIDR. +- Reference to the concrete network managed by this instance. With multiple networks, an explicit network or explicitly defined set is required. + +The saved template contains a typed reference, conceptually `Observability → Zugriffsquellen → Projektnetz dieser Instanz`. It does not yet contain a CIDR for the requester to enter. Within one state, the compiler translates this relationship into a real OpenTofu resource reference. If the address is unknown during Plan, preview shows “determined at provisioning” with provenance; the dependency graph resolves it at Apply. No advance API resolution against a network that does not yet exist and no CIDR placeholders in tfvars. + +If the network is missing or its address type/access path does not match, the combination cannot be published or instantiated. **No silent fallback to empty ACL or `0.0.0.0/0`.** For Observability, an empty ACL means full network-level access. Even a Public template with a local network needs a qualified egress strategy before it can offer “own project network” as an executable ACL source. The binding is selectable as a symbolic draft. + + +## General bindings and state ownership + +References need resource type, permitted output attribute, tenant/instance or platform scope, and cardinality. Examples include cluster for namespace, SNA for Corporate network, target folder for project, Observability connection and verified requester for an approved IAM assignment. Not all these bindings are already supported by the Accelerator. + +References within an instance are connected in the OpenTofu graph. Platform references come from a checked contract version, never arbitrary foreign state files or user UUIDs. Resolution checks tenant, region, type, permission, existence and lifecycle; cycles are rejected. A template must not access foreign tenants through a parameter. + +A shared platform instance remains in platform state. If an Application would need to extend its ACL, its state must not also manage that ACL. This requires a separate authorized registration/deregistration workflow with the platform owner, including concurrency and rollback on deletion. Until that exists, the combination is not approved for execution. + + +## Publication, ordering and changes + +1. Editor: visible source per approved field and constraints for order inputs. +2. Publication: check types, defaults, binding graph, mandatory dependencies and compiler/Accelerator capabilities; create immutable version. +3. Ordering: generate form exclusively from the approved input schema. +4. Server: reject unknown/blocked inputs, recheck permitted values, bind context and compile deterministically. The same applies to chat/API. +5. Plan: show concrete values and still-unknown resource values with provenance. Bind Plan/approval to template version, inputs, platform contract and compiler. +6. Update: allow only inputs explicitly qualified as mutable; template upgrades remain explicit. Template changes do not change instances. + +Template policy, order inputs and resolution evidence are persisted separately. Every effective field has provenance. Existing drafts initially retain their values as fixed settings; the Platform Engineer explicitly makes them order inputs or bindings. No automatic release of previously blocked values. + + +## Implementation sequence / acceptance + +- [x] Gap and concrete Accelerator limitations checked in code. +- [x] Implement versioned parameter/binding contract with five approved fields (#92); other fields remain fixed. +- [x] Stage as the first complete order input with default, selection and fixed values; unchanged reading of old drafts, explicit conversion. +- [x] Generate template editor and local order preview from the same contract. +- [x] Connect published tenant catalogue (#92/#93); real immutable version 1 accepted locally. +- [ ] Accept a real Application Owner order followed by Plan/Apply (#93). +- [x] Compiler checks policy independently of the form for manipulated inputs; tests for unknown fields, invalid defaults, tenant switches and version binding. +- [ ] Extend Accelerator module with typed project-network/Observability binding; first demonstrate provider/ACL/egress semantics, then native graph/plan tests. +- [ ] Missing network, disabled source service, multiple networks and cyclic or cross-region bindings prevent publication/instantiation. +- [ ] Qualify Plan with unknown resource values and later correct ACL; real customer Apply exclusively after explicit approval. +- [ ] Add further service bindings following the same pattern; release shared platform ACLs only after implementing single-state ownership. + +This work is a prerequisite for usable Application self-service, not a later convenience enhancement to an already complete MVP. + + +## Validation and deployment + +- Local domain/app tests and native Application mock plans check the new policy and stage naming, legacy preservation and the hard network-binding block. +- Browser checking and release evidence will be added after successful deployment. +- No customer Apply or automatic change to existing projects. + + +### Real template publication (2026-10-06) + +The existing Public template was published as version 1 from the saved draft: region eu01, local project network, approved server-based platform contract, target `public-eu01`, automatic group **Application Owners** and **Deployment with approval**. The contract comes from the successful current platform Apply with state version 6; old Applies and raw states are not freely selectable sources. The catalogue shows the same version after reload. Publication creates no cloud resources; Application execution remains disabled. A real Application Owner order and cloud execution have therefore not yet been accepted. + +Custom groups are created, populated with members and deleted in **User management**; publication manages only their template access. **Successful platform Apply** shows configuration name and completion date instead of a state-key hash. Only successful, current, unlocked Applies in the verified workspace with valid human organization evidence are selectable. Renewing this evidence remains accessible in user management even after organization binding. diff --git a/landing-zone-configurator/docs/user-guide.de.md b/landing-zone-configurator/docs/user-guide.de.md new file mode 100644 index 0000000..b60495d --- /dev/null +++ b/landing-zone-configurator/docs/user-guide.de.md @@ -0,0 +1,98 @@ + +# Configurator-Benutzerhandbuch + +[English](user-guide.md) | [Deutsch](user-guide.de.md) + + +## Zugang und Rollen + +Melde dich mit STACKIT an. Die Authentifizierung allein gewährt weder Zugriff auf eine +Organisation noch die Berechtigung, Infrastruktur bereitzustellen. Wähle die verifizierte +Arbeitsumgebung deiner Organisation. + +- **Platform Engineers** konfigurieren die gemeinsame Plattform und bereiten Projektvorlagen vor. +- **Application Owners** nutzen die Vorlagen und Instanzen, für die sie zugriffsberechtigt sind. +- Mitgliederverwaltung, Zugangsdatenverwendung und Ausführungsfreigaben sind getrennte + Fähigkeiten. Eine Rolle in einer Umgebung gewährt keine Rechte in einer anderen. + +Verbinde GitHub separat, wenn du Repository- und Fork-Funktionen nutzen möchtest. Eine +GitHub-Verbindung ersetzt weder die STACKIT-Anmeldung noch Cloud-Berechtigungen. + + +## Konfiguration erstellen und prüfen + +Beginne mit einer Plattformvorlage oder einer bestehenden Konfiguration. Vorlagen sind +Ausgangspunkte, keine Empfehlung, jeden optionalen Dienst einzuschalten. +Prüfe im Editor Grundlagen, Governance, Netzwerk und Plattformdienste. +Prüfe geerbte Werte ebenso wie die Felder, die du änderst. + +Der Editor validiert native Accelerator-Eingaben. Eine nicht gesetzte Überschreibung, +ein explizites `null` und ein konfigurierter Wert können unterschiedliche Bedeutungen +haben; das Entfernen einer Überschreibung führt zu nativen Standards zurück. Validierung +beweist weder regionale Produktverfügbarkeit noch Netzwerkerreichbarkeit, +Service-Account-Berechtigungen oder Kapazität. + +Speichere Änderungen ausdrücklich. Bei einem Fork ist das Speichern im Repository eine +separate Aktion. Exporte unterstützen den unabhängigen Terraform/OpenTofu-Workflow. + + +## Assistant-Vorschläge + +Der Assistant erläutert geprüftes Dienstwissen und schlägt unterstützte Editoränderungen +vor. Nenne Anforderungen und konkrete Entscheidungen; bei fehlenden Angaben muss er +nachfragen, statt Netzwerkadressen, Produktverfügbarkeit oder Zugangsdaten zu erfinden. + +1. Prüfe die vorgeschlagenen Unterschiede Feld für Feld. +2. Übernimm nur die gewünschten Änderungen in den aktuellen Entwurf. +3. Speichere den Entwurf separat. +4. Prüfe Plan und autorisiere Apply separat, wenn ein Deployment beabsichtigt ist. + +Vorschläge speichern oder veröffentlichen keine Vorlagen, vergeben keine Rollen und +stellen keine Infrastruktur bereit. Der Server prüft bei der Übernahme erneut deine +Berechtigung und die Entwurfsrevision. Aktualisiere und prüfe einen neuen Vorschlag, wenn +sich die zugrunde liegende Konfiguration geändert hat. Gib niemals Passwörter, +API-Tokens, VPN-Schlüssel, Kubeconfigs, State oder rohe Plans im Chat ein. +Nutze den separaten autorisierten Zugangsdaten-Workflow. + +Bei DNS beschreiben `primary` und `secondary` autoritative Zonenrollen, nicht +öffentliche/private Sichtbarkeit. Die native Secondary-Einrichtung ist unvollständig; +gehe nicht davon aus, dass die Rollenauswahl die Primary-Server-Replikation konfiguriert. + + +## Vorlagen und Application-Instanzen + +Platform Engineers erstellen, prüfen und veröffentlichen Projektvorlagenversionen. +Veröffentlichte Versionen sind unveränderlich. Application Owners wählen eine erlaubte +Version und geben deren freigegebene Parameter an. Ein Vorlagenentwurf ist keine +Application-Instanz, und eine Veröffentlichung deployt keine Instanz. Bestehende +Instanzen werden bei Veröffentlichung einer neuen Version nicht stillschweigend aktualisiert. + + +## Plan und Apply + +Wähle die richtige Umgebung und das richtige Ziel, binde die autorisierten technischen +Zugangsdaten, erstelle eine Vorbereitung und fordere anschließend einen Plan an. Verfolge +die Job-Ausgabe und prüfe die resultierenden Änderungen, Quell-/Konfigurationsversion +und State-Bindung. + +Aktive Plattformjobs streamen **OpenTofu-Ausgabe**, sobald sie verfügbar ist, einschließlich +nativen Plan-Fortschritts vor dem abschließenden Diff. **Ausgabe folgen** kann ausgeschaltet +werden, um frühere Zeilen zu prüfen. Klappe die Konsole ein, um die Verbindung zu trennen; +beim erneuten Öffnen erscheint die zuletzt erfasste Ausgabe, ohne den Job neu zu starten. +Der abschließende normale Plan-Text bleibt nach Abschluss und Neuladen verfügbar. +Die Ausgabe ist auf 2 MiB begrenzt; Kürzung und Verbindungsfehler werden angezeigt. +OpenTofu kann während langer Operationen still bleiben: Phase und verstrichene Zeit +sind keine geschätzte Prozentangabe. + +Apply verwendet den geprüften gespeicherten Plan und benötigt eine eigene Autorisierung. +Geänderte Eingaben, Quellen, State oder eine abgelaufene Freigabe können eine neue +Vorbereitung erfordern. Starte keine parallelen Infrastrukturschreibzugriffe auf denselben +State. UI-Jobstatus und Diagnose-ID helfen Betreibern bei der Fehleranalyse; +ein erneuter Versuch ersetzt nicht die Behebung einer abgelaufenen oder inkonsistenten Vorbereitung. + +Destroy, Upgrades und Drift-Prüfungen sind eigenständige Operationen mit eigener +Autorisierung. Eine erfolgreiche Konfigurationsvalidierung oder ein Plan beweisen nicht, +dass private Endpunkte während Apply erreichbar sind. + +Siehe [MVP-Umfang und Grenzen](mvp-scope.de.md) für bewusste Ausschlüsse und +[Architektur](architecture.de.md) für Komponenten und State-Grenzen. diff --git a/landing-zone-configurator/docs/user-guide.md b/landing-zone-configurator/docs/user-guide.md index f42b0ae..54612ac 100644 --- a/landing-zone-configurator/docs/user-guide.md +++ b/landing-zone-configurator/docs/user-guide.md @@ -1,5 +1,7 @@ # Configurator user guide +[English](user-guide.md) | [Deutsch](user-guide.de.md) + ## Access and roles Sign in with STACKIT. Authentication does not by itself grant access to an diff --git a/landing-zone-configurator/docs/vpn-configuration-scope.de.md b/landing-zone-configurator/docs/vpn-configuration-scope.de.md new file mode 100644 index 0000000..2c5269b --- /dev/null +++ b/landing-zone-configurator/docs/vpn-configuration-scope.de.md @@ -0,0 +1,44 @@ + + +# STACKIT VPN: Umfang des geführten Editors + +[English](vpn-configuration-scope.md) | [Deutsch](vpn-configuration-scope.de.md) + +Stand: 2026-10-01. Der Assistent beschreibt den vom Accelerator unterstützten Vertrag, keine vollständige Nachbildung des STACKIT Portals. + + + +## Bedienung + +1. Gateway: Anzeigename, Leistungsplan und Verfügbarkeitszonen der beiden Tunnel. +2. Routing: Route-based mit statischen Routen oder Policy-based mit lokalen/entfernten Netzen. BGP ist im aktuellen Modul nicht unterstützt; [#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) verfolgt die Erweiterung. +3. Verbindungen: stabile Verbindungskennung, Gegenstellenadressen für zwei Tunnel, optional erweiterte Peering-/IPsec-Einstellungen. +4. Zusammenfassung: erzeugte STACKIT-Ressourcen und verbleibende Arbeiten an der Gegenstelle. + +Navigation, Öffnen und Schließen verändern keine Konfiguration. Änderungen an einem Feld erhalten alle übrigen Werte, insbesondere Tunnel- und Routing-Einstellungen. Ein Wechsel des Routingverfahrens löscht bestehende Felder nicht; abweichende Routingfelder bleiben unter den weiteren Einstellungen zugänglich. Der Assistent ist keine semantische VPN-Verbindungsprüfung. Produktkataloge für Pläne und Verfügbarkeitszonen werden noch nicht abgefragt; dafür wird keine vermeintlich vollständige statische Auswahl vorgetäuscht. + + + +## Bestätigte Accelerator-Grenze: identisches VPN pro SNA + +Die [VPN-Ressourcen](../../src/modules/connectivity/7-vpn.tf) erzeugen ein Gateway für **jeden** Eintrag von `var.network_areas`. Die Verbindungen werden über das kartesische Produkt der SNA-Schlüssel und der VPN-Verbindungsschlüssel erzeugt. Jede SNA erhält damit dieselben Gateway-Einstellungen und alle konfigurierten Verbindungen. `connectivity.vpn` enthält keinen `network_area_key` und keine Auswahl einzelner SNAs; dasselbe gilt innerhalb einer regionalen Connectivity-Konfiguration. + +Der Editor macht diese Vervielfachung sichtbar und bietet keinen irreführenden SNA-Auswahlschalter an. Für eine spätere gezielte Zuordnung muss zuerst der Accelerator-Vertrag erweitert werden. Das ist unabhängig von automatischem Inter-Region-Routing und von Firewall-Policy-Automation. + + + +## Zugangsdaten und Ausführung + +Der [Root-Vertrag](../../src/variables.tf) hält Pre-Shared Keys getrennt unter `vpn_pre_shared_keys`; [das Modul](../../src/modules/connectivity/7-vpn.tf) liest pro Verbindungskennung zwei Schlüssel. Die Schlüssel werden nicht in den Topologieeditor oder die committierbare Konfiguration aufgenommen. Die geschützte Schlüsselanbindung ist noch offen. + +Der gemeinsame Editor kann diese Konfiguration speichern und exportieren. VPN-Deployments über diesen Editor sind weiterhin gesperrt. Ein späterer Deployment-Flow muss Schlüsselreferenzen, Routing-Plausibilität, verfügbare Produktparameter und die Auswirkungen der Vervielfachung pro SNA prüfen. Selbst nach einem erfolgreichen STACKIT-Deployment müssen das entfernte VPN-Gerät eingerichtet und die Verbindung geprüft werden. Ein Gateway ohne konfigurierte Verbindungen ist noch kein funktionsfähiges VPN. + + + +## Dokumentationsanschluss + +Der Assistent verlinkt die [STACKIT VPN-Dokumentation](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/), die [Gateway-/Verbindungsoptionen](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/basics/gateway-and-connection-options/) und die [Verbindungsanlage](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/connection-create/). Fachliche Reihenfolge und Begriffe folgen Gateway → Routing → Verbindung → Tunnel. Eine Gleichheit mit dem jeweils aktuellen Portal wird nicht behauptet. + + +Die fehlende selektive SNA-Zuordnung wurde nach Abgleich mit aktuellem `main` und +bestehenden Issues als [#85](https://github.com/stackitcloud/stackit-landing-zone/issues/85) erfasst. diff --git a/landing-zone-configurator/docs/vpn-configuration-scope.md b/landing-zone-configurator/docs/vpn-configuration-scope.md index 375620d..14c061d 100644 --- a/landing-zone-configurator/docs/vpn-configuration-scope.md +++ b/landing-zone-configurator/docs/vpn-configuration-scope.md @@ -1,32 +1,39 @@ -# STACKIT VPN: Umfang des geführten Editors + +# STACKIT VPN: scope of the guided editor -Stand: 2026-10-01. Der Assistent beschreibt den vom Accelerator unterstützten Vertrag, keine vollständige Nachbildung des STACKIT Portals. +[English](vpn-configuration-scope.md) | [Deutsch](vpn-configuration-scope.de.md) -## Bedienung +As of 2026-10-01. The assistant describes the contract supported by the Accelerator, not a complete replica of the STACKIT Portal. -1. Gateway: Anzeigename, Leistungsplan und Verfügbarkeitszonen der beiden Tunnel. -2. Routing: Route-based mit statischen Routen oder Policy-based mit lokalen/entfernten Netzen. BGP ist im aktuellen Modul nicht unterstützt; [#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) verfolgt die Erweiterung. -3. Verbindungen: stabile Verbindungskennung, Gegenstellenadressen für zwei Tunnel, optional erweiterte Peering-/IPsec-Einstellungen. -4. Zusammenfassung: erzeugte STACKIT-Ressourcen und verbleibende Arbeiten an der Gegenstelle. + +## Usage -Navigation, Öffnen und Schließen verändern keine Konfiguration. Änderungen an einem Feld erhalten alle übrigen Werte, insbesondere Tunnel- und Routing-Einstellungen. Ein Wechsel des Routingverfahrens löscht bestehende Felder nicht; abweichende Routingfelder bleiben unter den weiteren Einstellungen zugänglich. Der Assistent ist keine semantische VPN-Verbindungsprüfung. Produktkataloge für Pläne und Verfügbarkeitszonen werden noch nicht abgefragt; dafür wird keine vermeintlich vollständige statische Auswahl vorgetäuscht. +1. Gateway: display name, performance plan and availability zones of both tunnels. +2. Routing: route-based with static routes or policy-based with local/remote networks. BGP is not supported by the current module; [#86](https://github.com/stackitcloud/stackit-landing-zone/issues/86) tracks the extension. +3. Connections: stable connection identifier, peer addresses for two tunnels, optional advanced peering/IPsec settings. +4. Summary: generated STACKIT resources and remaining work on the peer. -## Bestätigte Accelerator-Grenze: identisches VPN pro SNA +Navigation, opening and closing do not change any configuration. Changes to one field preserve all other values, especially tunnel and routing settings. Switching the routing method does not delete existing fields; fields for other routing methods remain accessible under additional settings. The assistant is not a semantic VPN connection check. Product catalogues for plans and availability zones are not yet queried; no supposedly complete static selection is presented instead. -Die [VPN-Ressourcen](../../src/modules/connectivity/7-vpn.tf) erzeugen ein Gateway für **jeden** Eintrag von `var.network_areas`. Die Verbindungen werden über das kartesische Produkt der SNA-Schlüssel und der VPN-Verbindungsschlüssel erzeugt. Jede SNA erhält damit dieselben Gateway-Einstellungen und alle konfigurierten Verbindungen. `connectivity.vpn` enthält keinen `network_area_key` und keine Auswahl einzelner SNAs; dasselbe gilt innerhalb einer regionalen Connectivity-Konfiguration. + +## Confirmed Accelerator limitation: identical VPN per SNA -Der Editor macht diese Vervielfachung sichtbar und bietet keinen irreführenden SNA-Auswahlschalter an. Für eine spätere gezielte Zuordnung muss zuerst der Accelerator-Vertrag erweitert werden. Das ist unabhängig von automatischem Inter-Region-Routing und von Firewall-Policy-Automation. +The [VPN resources](../../src/modules/connectivity/7-vpn.tf) create a gateway for **every** entry in `var.network_areas`. Connections are created using the Cartesian product of SNA keys and VPN connection keys. Each SNA therefore receives the same gateway settings and all configured connections. `connectivity.vpn` contains no `network_area_key` and no selection of individual SNAs; the same applies within a regional connectivity configuration. -## Zugangsdaten und Ausführung +The editor makes this duplication visible and does not offer a misleading SNA selector. Future targeted assignment requires extending the Accelerator contract first. This is independent of automatic inter-region routing and firewall policy automation. -Der [Root-Vertrag](../../src/variables.tf) hält Pre-Shared Keys getrennt unter `vpn_pre_shared_keys`; [das Modul](../../src/modules/connectivity/7-vpn.tf) liest pro Verbindungskennung zwei Schlüssel. Die Schlüssel werden nicht in den Topologieeditor oder die committierbare Konfiguration aufgenommen. Die geschützte Schlüsselanbindung ist noch offen. + +## Credentials and execution -Der gemeinsame Editor kann diese Konfiguration speichern und exportieren. VPN-Deployments über diesen Editor sind weiterhin gesperrt. Ein späterer Deployment-Flow muss Schlüsselreferenzen, Routing-Plausibilität, verfügbare Produktparameter und die Auswirkungen der Vervielfachung pro SNA prüfen. Selbst nach einem erfolgreichen STACKIT-Deployment müssen das entfernte VPN-Gerät eingerichtet und die Verbindung geprüft werden. Ein Gateway ohne konfigurierte Verbindungen ist noch kein funktionsfähiges VPN. +The [root contract](../../src/variables.tf) keeps pre-shared keys separately under `vpn_pre_shared_keys`; [the module](../../src/modules/connectivity/7-vpn.tf) reads two keys per connection identifier. Keys are not included in the topology editor or committable configuration. Protected key binding remains open. -## Dokumentationsanschluss +The common editor can save and export this configuration. VPN deployments through this editor remain blocked. A future deployment flow must check key references, routing plausibility, available product parameters and the effects of duplication per SNA. Even after a successful STACKIT deployment, the remote VPN device must be configured and the connection tested. A gateway without configured connections is not yet a functioning VPN. -Der Assistent verlinkt die [STACKIT VPN-Dokumentation](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/), die [Gateway-/Verbindungsoptionen](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/basics/gateway-and-connection-options/) und die [Verbindungsanlage](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/connection-create/). Fachliche Reihenfolge und Begriffe folgen Gateway → Routing → Verbindung → Tunnel. Eine Gleichheit mit dem jeweils aktuellen Portal wird nicht behauptet. + +## Documentation integration +The assistant links to the [STACKIT VPN documentation](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/), [gateway/connection options](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/basics/gateway-and-connection-options/) and [connection creation](https://docs.stackit.cloud/products/network/connectivity-hybrid-multi-cloud/vpn/getting-started/connection-create/). The domain sequence and terminology follow gateway → routing → connection → tunnel. No equivalence with the current portal is claimed. -Die fehlende selektive SNA-Zuordnung wurde nach Abgleich mit aktuellem `main` und -bestehenden Issues als [#85](https://github.com/stackitcloud/stackit-landing-zone/issues/85) erfasst. + +The missing selective SNA assignment was recorded as [#85](https://github.com/stackitcloud/stackit-landing-zone/issues/85) +after comparison with current `main` and existing issues. diff --git a/landing-zone-configurator/infra/README.de.md b/landing-zone-configurator/infra/README.de.md new file mode 100644 index 0000000..c905657 --- /dev/null +++ b/landing-zone-configurator/infra/README.de.md @@ -0,0 +1,99 @@ + + +# Configurator-Infrastruktur + +[English](README.md) | [Deutsch](README.de.md) + +Alle Configurator-Dienste werden per OpenTofu verwaltet. Die Infrastruktur bleibt vom eigentlichen Landing Zone Accelerator getrennt. OpenTofu **1.12.6** und Provider-Versionen sind gepinnt; jeder ausführbare Root hat ein versioniertes Lockfile. + + + +## Roots und Reihenfolge + +| Root | Aufgabe | State | +| --- | --- | --- | +| `seed` | Verwaltungs-Bucket und dessen S3-Zugang | lokal verschlüsselt, mit verschlüsselter Remote-Sicherung | +| `seed-protection` | Versionierung des Verwaltungs-Buckets | lokal verschlüsselt, mit verschlüsselter Remote-Sicherung | +| `bootstrap` | Workload-State-Bucket und dessen S3-Zugang | Verwaltungs-Bucket | +| `backend` | Versionierung des Workload-State-Buckets | Verwaltungs-Bucket | +| `platform` | CF-Organisation/Manager, PostgreSQL/Datenbank/Migrationsnutzer, Secrets Manager/Provisionierungsnutzer, Artefakt-Bucket und Model-Serving-Token | Workload-Bucket | +| `runtime` | CF-Space, Organisations-/Space-Rollen, PostgreSQL-/Secrets-Laufzeitbenutzer | Workload-Bucket, eigener Schlüssel | + +Bootstrap, Backend, Plattform und Runtime sind in `lzc-dev/eu01` provisioniert. Die Plattform enthält neun verwaltete Ressourcen; der [Betriebsstand](../docs/platform-readiness.de.md) dokumentiert Abnahme und offene Konnektivitätsarbeiten. + +Der STACKIT-Provider aktiviert Object Storage und Model Serving bei der ersten Ressourcenerstellung. Für Bucket-Versionierung spricht der AWS-Provider ausschließlich die STACKIT-S3-API an; es werden keine AWS-Ressourcen angelegt. + +Die Plattform verwaltet getrennte Model-Serving-Token für die Anwendung und die synthetischen Assistant-Tests. Der sensitive Output `assistant_test_model_serving_token` gehört ausschließlich in das GitHub Environment `assistant-tests`, nicht in die CF-Anwendungsbindung. Beide Token haben eine Laufzeit von 90 Tagen; eine bewusste Rotation über `credential_generation` erfordert danach die Aktualisierung der jeweiligen Bindung beziehungsweise des CI-Secrets. Das bestehende Anwendungstoken wird beim Hinzufügen des Testtokens nicht verändert. + + + +## Deployment: direkte OpenTofu-Schritte in CI + +[Bootstrap-Workflow](../../.github/workflows/configurator-bootstrap.yml), [Plattform-Workflow](../../.github/workflows/configurator-platform.yml) und [Runtime-Workflow](../../.github/workflows/configurator-runtime.yml) führen `tofu init`, `validate`, `plan` und `apply` direkt aus. Normale CLI-Ausgaben sind live sichtbar. Kleine Hilfsprogramme bereiten Credentials vor, prüfen das gespeicherte Plan-Artefakt und verschlüsseln Recovery-Snapshots; sie führen keine Deployments aus. + +[CI-Betriebsanleitung](ci/README.de.md): Environments, Planfreigabe, Timeouts, State-Sicherung und Feature-Branch-Tests. Remote-Applies ausschließlich über die gemeinsam serialisierte CI; keine parallelen lokalen Applies. S3-Locking hat den Integrationstest nicht bestanden und wird nicht als funktionierender Schutz behauptet. + + + +## Lokal validieren, ohne Cloud-Zugriff + +Benötigt werden OpenTofu 1.12.6 und Node.js 24.21.0 für die reine Umgebungs-Vorbereitung. Aus `landing-zone-configurator/`, beispielhaft für `platform`: + +```sh +node infra/prepare-local.mjs platform --validation +( + . .local/validation/platform/environment.sh + tofu -chdir=infra/platform init -backend=false -lockfile=readonly -input=false + tofu -chdir=infra/platform validate -no-color + tofu -chdir=infra/platform test -no-color +) +tofu -chdir=infra fmt -check -recursive +node --test infra/prepare-local.test.mjs infra/plan-guard.test.mjs infra/state-key.test.mjs infra/ci/*.test.mjs +``` + +Die Vorbereitung erzeugt nur eine private Umgebungsdatei und einen lokalen Testschlüssel. Sie führt keinen OpenTofu-Befehl aus. Die Testumgebung liegt separat unter `.local/validation/` und verwendet keine produktiven Backend-Schlüssel. Für andere Roots `platform` durch den jeweiligen Namen ersetzen. Die Tests verwenden Mock-Provider. CI macht dieselben OpenTofu-Aufrufe direkt mit temporären Testschlüsseln. + + + +## Seltene lokale Seed-Operationen + +Der Verwaltungs-Seed existiert bereits. Folgende Befehle sind der dokumentierte Bedienweg für bewusst geplante Seed-Änderungen, kein notwendiger Schritt vor einem App-Deployment. Nur ein Operator arbeitet am Seed. Vor Änderungen unabhängige Schlüsselsicherung prüfen. + +Eingaben bleiben in den ignorierten Dateien `landing-zone-configurator.env` und `landing-zone-configurator-credentials.json` im Repository-Root. Die env-Datei verwendet `NAME=WERT`: `PROJECT_ID`, `REGION`, `NAME_PREFIX`, `STATE_CREDENTIAL_EXPIRATION`. Credentials und State-Schlüssel niemals in Git übernehmen. + +```sh +node infra/prepare-local.mjs seed +( + . .local/seed/environment.sh + tofu -chdir=infra/seed init -lockfile=readonly -backend-config=../../.local/seed/backend.hcl + tofu -chdir=infra/seed plan -out=../../.local/seed/review.tfplan + # Erst nach Prüfung des konkreten Plans: + tofu -chdir=infra/seed apply ../../.local/seed/review.tfplan + umask 077 + tofu -chdir=infra/seed output -json > .local/seed/outputs.json +) +node infra/prepare-local.mjs seed-protection +( + . .local/seed-protection/environment.sh + tofu -chdir=infra/seed-protection init -lockfile=readonly -backend-config=../../.local/seed-protection/backend.hcl + tofu -chdir=infra/seed-protection plan -out=../../.local/seed-protection/review.tfplan + # Erst nach Prüfung des konkreten Plans: + tofu -chdir=infra/seed-protection apply ../../.local/seed-protection/review.tfplan +) +rm -f .local/seed/outputs.json .local/seed/environment.sh .local/seed-protection/environment.sh +``` + +Die Shell-Dateien enthalten sensible Werte, sind mit Modus 0600 angelegt und von Git ausgeschlossen. Die Umgebungen gelten nur in den gezeigten Subshells. Bereits vorhandene Schlüssel werden wiederverwendet; bei verlorenem Schlüssel eines bestehenden Workspace wird kein neuer erzeugt. Die Vorbereitung erlaubt Cloud-Konfiguration lokal ausschließlich für die beiden Seed-Roots. + + + +## Recovery und verbleibende Arbeiten + +Verschlüsselte Seed-Sicherungen liegen im Verwaltungs-Bucket unter `recovery/seed/terraform.tfstate` und `recovery/seed-protection/terraform.tfstate`; nach Seed-Änderungen erneuern. State-Schlüssel separat und unabhängig vom Bucket verwahren. Die Kopie im selben Bucket schützt nicht vor Verlust des gesamten Buckets. + +Bei einem fehlgeschlagenen Apply zuerst CI-Logs, verschlüsselte Recovery-Artefakte und tatsächlichen Ressourcenbestand prüfen. Keinen alten Plan blind wiederholen, keinen existierenden State überschreiben. Imports und Credential-Rotation müssen zum konkreten Vorfall passen und unter derselben Single-Writer-Regel erfolgen. Der frühere automatische Einmal-Recovery-Pfad wurde nach Abschluss entfernt. + +Die App und ihre CF-Umgebungsvariablen werden im separaten [Release-Workflow](../../.github/workflows/configurator-release.yml) durch das deklarative [CF-Manifest](../deploy/cloud-foundry/manifest.yml) verwaltet. Verbindungstests aus CF sind erfolgreich. Offen sind Anwendungsschema/RLS, automatisierte Credential-Rotation sowie ein vollständiger getesteter Betriebs-/Restore-Prozess. [Planung](../docs/planning.de.md). + + +Direkte CLI-Pipelines geprüft (2026-09-30): [Bootstrap 36677111141](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111141) und [Plattform 36677111032](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111032) zeigen jeweils `No changes`, mit sichtbaren nativen Init-/Plan-Logs und übersprungenem Apply. [Validierung 36677111055](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111055) bestätigt auch den GNU-Timeout-Test auf Linux. Aktuelle weitere Abnahmen stehen im [Plattform-Betriebsstand](../docs/platform-readiness.de.md). diff --git a/landing-zone-configurator/infra/README.md b/landing-zone-configurator/infra/README.md index 7027f5e..6b810d3 100644 --- a/landing-zone-configurator/infra/README.md +++ b/landing-zone-configurator/infra/README.md @@ -1,33 +1,43 @@ -# Configurator-Infrastruktur +# Configurator infrastructure -Alle Configurator-Dienste werden per OpenTofu verwaltet. Die Infrastruktur bleibt vom eigentlichen Landing Zone Accelerator getrennt. OpenTofu **1.12.6** und Provider-Versionen sind gepinnt; jeder ausführbare Root hat ein versioniertes Lockfile. +[English](README.md) | [Deutsch](README.de.md) -## Roots und Reihenfolge + -| Root | Aufgabe | State | +All Configurator services are managed through OpenTofu. The infrastructure remains separate from the actual Landing Zone Accelerator. OpenTofu **1.12.6** and provider versions are pinned; each executable root has a versioned lockfile. + + + +## Roots and order + +| Root | Purpose | State | | --- | --- | --- | -| `seed` | Verwaltungs-Bucket und dessen S3-Zugang | lokal verschlüsselt, mit verschlüsselter Remote-Sicherung | -| `seed-protection` | Versionierung des Verwaltungs-Buckets | lokal verschlüsselt, mit verschlüsselter Remote-Sicherung | -| `bootstrap` | Workload-State-Bucket und dessen S3-Zugang | Verwaltungs-Bucket | -| `backend` | Versionierung des Workload-State-Buckets | Verwaltungs-Bucket | -| `platform` | CF-Organisation/Manager, PostgreSQL/Datenbank/Migrationsnutzer, Secrets Manager/Provisionierungsnutzer, Artefakt-Bucket und Model-Serving-Token | Workload-Bucket | -| `runtime` | CF-Space, Organisations-/Space-Rollen, PostgreSQL-/Secrets-Laufzeitbenutzer | Workload-Bucket, eigener Schlüssel | +| `seed` | Management bucket and its S3 access | Locally encrypted, with encrypted remote backup | +| `seed-protection` | Management bucket versioning | Locally encrypted, with encrypted remote backup | +| `bootstrap` | Workload state bucket and its S3 access | Management bucket | +| `backend` | Workload state bucket versioning | Management bucket | +| `platform` | CF organization/manager, PostgreSQL/database/migration user, Secrets Manager/provisioning user, artifact bucket and Model Serving token | Workload bucket | +| `runtime` | CF space, organization/space roles, PostgreSQL/Secrets runtime users | Workload bucket, separate key | + +Bootstrap, backend, platform and runtime are provisioned in `lzc-dev/eu01`. The platform contains nine managed resources; the [operational status](../docs/platform-readiness.md) documents acceptance and outstanding connectivity work. -Bootstrap, Backend, Plattform und Runtime sind in `lzc-dev/eu01` provisioniert. Die Plattform enthält neun verwaltete Ressourcen; der [Betriebsstand](../docs/platform-readiness.md) dokumentiert Abnahme und offene Konnektivitätsarbeiten. +The STACKIT provider enables Object Storage and Model Serving when the first resource is created. For bucket versioning, the AWS provider addresses only the STACKIT S3 API; no AWS resources are created. -Der STACKIT-Provider aktiviert Object Storage und Model Serving bei der ersten Ressourcenerstellung. Für Bucket-Versionierung spricht der AWS-Provider ausschließlich die STACKIT-S3-API an; es werden keine AWS-Ressourcen angelegt. +The platform manages separate Model Serving tokens for the application and synthetic Assistant tests. The sensitive output `assistant_test_model_serving_token` belongs exclusively in the GitHub Environment `assistant-tests`, not in the CF application binding. Both tokens have a lifetime of 90 days; deliberate rotation through `credential_generation` then requires updating the respective binding or CI secret. Adding the test token does not change the existing application token. -Die Plattform verwaltet getrennte Model-Serving-Token für die Anwendung und die synthetischen Assistant-Tests. Der sensitive Output `assistant_test_model_serving_token` gehört ausschließlich in das GitHub Environment `assistant-tests`, nicht in die CF-Anwendungsbindung. Beide Token haben eine Laufzeit von 90 Tagen; eine bewusste Rotation über `credential_generation` erfordert danach die Aktualisierung der jeweiligen Bindung beziehungsweise des CI-Secrets. Das bestehende Anwendungstoken wird beim Hinzufügen des Testtokens nicht verändert. + -## Deployment: direkte OpenTofu-Schritte in CI +## Deployment: direct OpenTofu steps in CI -[Bootstrap-Workflow](../../.github/workflows/configurator-bootstrap.yml), [Plattform-Workflow](../../.github/workflows/configurator-platform.yml) und [Runtime-Workflow](../../.github/workflows/configurator-runtime.yml) führen `tofu init`, `validate`, `plan` und `apply` direkt aus. Normale CLI-Ausgaben sind live sichtbar. Kleine Hilfsprogramme bereiten Credentials vor, prüfen das gespeicherte Plan-Artefakt und verschlüsseln Recovery-Snapshots; sie führen keine Deployments aus. +The [bootstrap workflow](../../.github/workflows/configurator-bootstrap.yml), [platform workflow](../../.github/workflows/configurator-platform.yml) and [runtime workflow](../../.github/workflows/configurator-runtime.yml) execute `tofu init`, `validate`, `plan` and `apply` directly. Normal CLI output is visible live. Small utilities prepare credentials, check the saved Plan artifact and encrypt recovery snapshots; they do not execute deployments. -[CI-Betriebsanleitung](ci/README.md): Environments, Planfreigabe, Timeouts, State-Sicherung und Feature-Branch-Tests. Remote-Applies ausschließlich über die gemeinsam serialisierte CI; keine parallelen lokalen Applies. S3-Locking hat den Integrationstest nicht bestanden und wird nicht als funktionierender Schutz behauptet. +[CI operations guide](ci/README.md): environments, Plan approval, timeouts, state backup and feature-branch tests. Remote Applies exclusively through jointly serialized CI; no parallel local Applies. S3 locking failed the integration test and is not claimed as working protection. -## Lokal validieren, ohne Cloud-Zugriff + -Benötigt werden OpenTofu 1.12.6 und Node.js 24.21.0 für die reine Umgebungs-Vorbereitung. Aus `landing-zone-configurator/`, beispielhaft für `platform`: +## Validate locally without cloud access + +OpenTofu 1.12.6 and Node.js 24.21.0 are required for environment preparation only. From `landing-zone-configurator/`, using `platform` as an example: ```sh node infra/prepare-local.mjs platform --validation @@ -41,13 +51,15 @@ tofu -chdir=infra fmt -check -recursive node --test infra/prepare-local.test.mjs infra/plan-guard.test.mjs infra/state-key.test.mjs infra/ci/*.test.mjs ``` -Die Vorbereitung erzeugt nur eine private Umgebungsdatei und einen lokalen Testschlüssel. Sie führt keinen OpenTofu-Befehl aus. Die Testumgebung liegt separat unter `.local/validation/` und verwendet keine produktiven Backend-Schlüssel. Für andere Roots `platform` durch den jeweiligen Namen ersetzen. Die Tests verwenden Mock-Provider. CI macht dieselben OpenTofu-Aufrufe direkt mit temporären Testschlüsseln. +Preparation creates only a private environment file and a local test key. It runs no OpenTofu command. The test environment resides separately under `.local/validation/` and uses no production backend keys. For other roots, replace `platform` with the respective name. Tests use mock providers. CI makes the same OpenTofu calls directly with temporary test keys. + + -## Seltene lokale Seed-Operationen +## Rare local seed operations -Der Verwaltungs-Seed existiert bereits. Folgende Befehle sind der dokumentierte Bedienweg für bewusst geplante Seed-Änderungen, kein notwendiger Schritt vor einem App-Deployment. Nur ein Operator arbeitet am Seed. Vor Änderungen unabhängige Schlüsselsicherung prüfen. +The management seed already exists. The following commands are the documented operating procedure for deliberately planned seed changes, not a necessary step before an app deployment. Only one operator works on the seed. Check independent key backups before making changes. -Eingaben bleiben in den ignorierten Dateien `landing-zone-configurator.env` und `landing-zone-configurator-credentials.json` im Repository-Root. Die env-Datei verwendet `NAME=WERT`: `PROJECT_ID`, `REGION`, `NAME_PREFIX`, `STATE_CREDENTIAL_EXPIRATION`. Credentials und State-Schlüssel niemals in Git übernehmen. +Inputs remain in the ignored files `landing-zone-configurator.env` and `landing-zone-configurator-credentials.json` in the repository root. The env file uses `NAME=WERT`: `PROJECT_ID`, `REGION`, `NAME_PREFIX`, `STATE_CREDENTIAL_EXPIRATION`. Never add credentials and state keys to Git. ```sh node infra/prepare-local.mjs seed @@ -71,15 +83,17 @@ node infra/prepare-local.mjs seed-protection rm -f .local/seed/outputs.json .local/seed/environment.sh .local/seed-protection/environment.sh ``` -Die Shell-Dateien enthalten sensible Werte, sind mit Modus 0600 angelegt und von Git ausgeschlossen. Die Umgebungen gelten nur in den gezeigten Subshells. Bereits vorhandene Schlüssel werden wiederverwendet; bei verlorenem Schlüssel eines bestehenden Workspace wird kein neuer erzeugt. Die Vorbereitung erlaubt Cloud-Konfiguration lokal ausschließlich für die beiden Seed-Roots. +The shell files contain sensitive values, are created with mode 0600 and are excluded from Git. The environments apply only within the subshells shown. Existing keys are reused; no new key is generated when an existing workspace's key is lost. Preparation allows local cloud configuration only for the two seed roots. + + -## Recovery und verbleibende Arbeiten +## Recovery and remaining work -Verschlüsselte Seed-Sicherungen liegen im Verwaltungs-Bucket unter `recovery/seed/terraform.tfstate` und `recovery/seed-protection/terraform.tfstate`; nach Seed-Änderungen erneuern. State-Schlüssel separat und unabhängig vom Bucket verwahren. Die Kopie im selben Bucket schützt nicht vor Verlust des gesamten Buckets. +Encrypted seed backups reside in the management bucket under `recovery/seed/terraform.tfstate` and `recovery/seed-protection/terraform.tfstate`; refresh them after seed changes. Keep state keys separate and independent of the bucket. A copy in the same bucket does not protect against loss of the entire bucket. -Bei einem fehlgeschlagenen Apply zuerst CI-Logs, verschlüsselte Recovery-Artefakte und tatsächlichen Ressourcenbestand prüfen. Keinen alten Plan blind wiederholen, keinen existierenden State überschreiben. Imports und Credential-Rotation müssen zum konkreten Vorfall passen und unter derselben Single-Writer-Regel erfolgen. Der frühere automatische Einmal-Recovery-Pfad wurde nach Abschluss entfernt. +After a failed Apply, first check CI logs, encrypted recovery artifacts and the actual resource inventory. Do not blindly repeat an old Plan or overwrite existing state. Imports and credential rotation must fit the specific incident and follow the same single-writer rule. The former automatic one-time recovery path was removed after completion. -Die App und ihre CF-Umgebungsvariablen werden im separaten [Release-Workflow](../../.github/workflows/configurator-release.yml) durch das deklarative [CF-Manifest](../deploy/cloud-foundry/manifest.yml) verwaltet. Verbindungstests aus CF sind erfolgreich. Offen sind Anwendungsschema/RLS, automatisierte Credential-Rotation sowie ein vollständiger getesteter Betriebs-/Restore-Prozess. [Planung](../docs/planning.md). +The app and its CF environment variables are managed in the separate [release workflow](../../.github/workflows/configurator-release.yml) through the declarative [CF manifest](../deploy/cloud-foundry/manifest.yml). Connection tests from CF succeeded. Outstanding work includes the application schema/RLS, automated credential rotation and a complete, tested operations/restore process. [Planning](../docs/planning.md). -Direkte CLI-Pipelines geprüft (2026-09-30): [Bootstrap 36677111141](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111141) und [Plattform 36677111032](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111032) zeigen jeweils `No changes`, mit sichtbaren nativen Init-/Plan-Logs und übersprungenem Apply. [Validierung 36677111055](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111055) bestätigt auch den GNU-Timeout-Test auf Linux. Aktuelle weitere Abnahmen stehen im [Plattform-Betriebsstand](../docs/platform-readiness.md). +Direct CLI pipelines verified (2026-09-30): [bootstrap 36677111141](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111141) and [platform 36677111032](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111032) each show `No changes`, with visible native init/Plan logs and Apply skipped. [Validation 36677111055](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36677111055) also confirms the GNU timeout test on Linux. Further current acceptance results are in the [platform operational status](../docs/platform-readiness.md). diff --git a/landing-zone-configurator/infra/backend/README.de.md b/landing-zone-configurator/infra/backend/README.de.md new file mode 100644 index 0000000..f01a286 --- /dev/null +++ b/landing-zone-configurator/infra/backend/README.de.md @@ -0,0 +1,13 @@ + + +# Remote-State-Absicherung + +[English](README.md) | [Deutsch](README.de.md) + +Dieser Root verwaltet `aws_s3_bucket_versioning` am STACKIT-S3-Endpunkt. Es werden keine AWS-Ressourcen angelegt. Voraussetzung sind der Bucket und S3-Credentials aus dem bereits angewendeten Bootstrap-Root. + +Der echte Erstplan hat gezeigt, dass der S3-Provider existierende Credentials bereits zur Planung benötigt. Deshalb ist diese Konfiguration ein eigener Root und kein `-target`-Sonderlauf innerhalb des Bootstrap-Roots. + +Der Wrapper übergibt Credentials ausschließlich im Prozessumfeld. Dieser Root nutzt einen eigenen State-Key im Verwaltungs-Bucket. Provider-Zugang zum Workload-Bucket und Backend-Zugang zum Verwaltungs-Bucket werden getrennt übergeben. Der Plattform-Root darf erst nach angewendeter Versionierung sein Remote-Backend initialisieren. [Operator-Anleitung](../README.de.md). + +Dieser Root wurde noch nicht angewendet. Der gleichartige Seed-Protection-Root hat Versionierung am Verwaltungs-Bucket erfolgreich aktiviert; Versionswiederherstellung wurde dort geprüft. Konkurrierende OpenTofu-Zugriffe und vollständiges Disaster Recovery bleiben zu testen. diff --git a/landing-zone-configurator/infra/backend/README.md b/landing-zone-configurator/infra/backend/README.md index 2d8b7ae..22dcb30 100644 --- a/landing-zone-configurator/infra/backend/README.md +++ b/landing-zone-configurator/infra/backend/README.md @@ -1,9 +1,13 @@ -# Remote-State-Absicherung +# Remote state protection -Dieser Root verwaltet `aws_s3_bucket_versioning` am STACKIT-S3-Endpunkt. Es werden keine AWS-Ressourcen angelegt. Voraussetzung sind der Bucket und S3-Credentials aus dem bereits angewendeten Bootstrap-Root. +[English](README.md) | [Deutsch](README.de.md) -Der echte Erstplan hat gezeigt, dass der S3-Provider existierende Credentials bereits zur Planung benötigt. Deshalb ist diese Konfiguration ein eigener Root und kein `-target`-Sonderlauf innerhalb des Bootstrap-Roots. + -Der Wrapper übergibt Credentials ausschließlich im Prozessumfeld. Dieser Root nutzt einen eigenen State-Key im Verwaltungs-Bucket. Provider-Zugang zum Workload-Bucket und Backend-Zugang zum Verwaltungs-Bucket werden getrennt übergeben. Der Plattform-Root darf erst nach angewendeter Versionierung sein Remote-Backend initialisieren. [Operator-Anleitung](../README.md). +This root manages `aws_s3_bucket_versioning` at the STACKIT S3 endpoint. No AWS resources are created. The bucket and S3 credentials from the already applied bootstrap root are prerequisites. -Dieser Root wurde noch nicht angewendet. Der gleichartige Seed-Protection-Root hat Versionierung am Verwaltungs-Bucket erfolgreich aktiviert; Versionswiederherstellung wurde dort geprüft. Konkurrierende OpenTofu-Zugriffe und vollständiges Disaster Recovery bleiben zu testen. +The real initial Plan showed that the S3 provider already needs existing credentials during planning. This configuration is therefore a separate root, not a special `-target` run within the bootstrap root. + +The wrapper passes credentials only through the process environment. This root uses its own state key in the management bucket. Provider access to the workload bucket and backend access to the management bucket are passed separately. The platform root may initialize its remote backend only after versioning has been applied. [Operator instructions](../README.md). + +This root has not yet been applied. The equivalent seed-protection root successfully enabled versioning on the management bucket; version recovery was verified there. Concurrent OpenTofu access and complete disaster recovery remain to be tested. diff --git a/landing-zone-configurator/infra/bootstrap/README.de.md b/landing-zone-configurator/infra/bootstrap/README.de.md new file mode 100644 index 0000000..19c28a4 --- /dev/null +++ b/landing-zone-configurator/infra/bootstrap/README.de.md @@ -0,0 +1,21 @@ +# State-Bootstrap + +[English](README.md) | [Deutsch](README.de.md) + +Dieser Root erstellt drei Ressourcen: State-Bucket, Credential-Gruppe und befristeten S3-Zugang. Die erste Bucket-Erstellung aktiviert Object Storage automatisch im vorhandenen Projekt. + +Dieser Root nutzt den separaten, bereits per Seed-IaC erstellten Verwaltungs-Bucket als verschlüsseltes S3-Backend. Der nachgelagerte [Backend-Root](../backend/README.de.md) aktiviert die Versionierung mit den dann verfügbaren S3-Credentials. Der Plattform-Root nutzt anschließend den geschützten Bucket. + +Erster echter Plan am 2026-09-29 für lzc-dev/eu01 erfolgreich: **3 anlegen, 0 ändern, 0 löschen**. Geplantes Credential-Ablaufdatum: 2026-12-28. Kein Apply ausgeführt. Der gespeicherte Plan liegt verschlüsselt und Git-ignoriert unter `.local/bootstrap/review.tfplan` und ist nur 24 Stunden verwendbar. + +[Operator-Anleitung](../README.de.md). Mock-Tests weisen die Struktur nach; Aktivierung, S3-Kompatibilität und Berechtigungen zum Schreiben sind erst durch den anschließenden Integrationstest belegt. + +Aktuell: Remote-Backend initialisiert, echter Plan mit 3 Create erfolgreich; für diesen Root weiterhin kein Apply. + + + +## Erster CI-Apply erfolgreich + +Am 2026-09-29 wurde Bootstrap auf dem Feature-Branch über [Run 36601941540](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36601941540) angewendet: drei Ressourcen erstellt, keine Änderungen oder Löschungen. Der verschlüsselte State im Verwaltungs-Bucket enthält alle drei Ressourcen. Die einmalige Commit-Freigabe wurde anschließend entfernt. Die zuvor genannten Angaben „kein Apply“ beschreiben den früheren Planungsstand. + +Der nächste Infrastruktur-Schritt ist der separate Backend-Root zur Versionierung des neu erstellten Workload-State-Buckets. Dieser Root wurde noch nicht angewendet. diff --git a/landing-zone-configurator/infra/bootstrap/README.md b/landing-zone-configurator/infra/bootstrap/README.md index 52bbe50..04d7a0f 100644 --- a/landing-zone-configurator/infra/bootstrap/README.md +++ b/landing-zone-configurator/infra/bootstrap/README.md @@ -1,17 +1,21 @@ -# State-Bootstrap +# State bootstrap -Dieser Root erstellt drei Ressourcen: State-Bucket, Credential-Gruppe und befristeten S3-Zugang. Die erste Bucket-Erstellung aktiviert Object Storage automatisch im vorhandenen Projekt. +[English](README.md) | [Deutsch](README.de.md) -Dieser Root nutzt den separaten, bereits per Seed-IaC erstellten Verwaltungs-Bucket als verschlüsseltes S3-Backend. Der nachgelagerte [Backend-Root](../backend/README.md) aktiviert die Versionierung mit den dann verfügbaren S3-Credentials. Der Plattform-Root nutzt anschließend den geschützten Bucket. +This root creates three resources: a state bucket, a credential group and time-limited S3 access. Initial bucket creation automatically enables Object Storage in the existing project. -Erster echter Plan am 2026-09-29 für lzc-dev/eu01 erfolgreich: **3 anlegen, 0 ändern, 0 löschen**. Geplantes Credential-Ablaufdatum: 2026-12-28. Kein Apply ausgeführt. Der gespeicherte Plan liegt verschlüsselt und Git-ignoriert unter `.local/bootstrap/review.tfplan` und ist nur 24 Stunden verwendbar. +This root uses the separate management bucket, already created through seed IaC, as an encrypted S3 backend. The downstream [backend root](../backend/README.md) enables versioning using the S3 credentials then available. The platform root subsequently uses the protected bucket. -[Operator-Anleitung](../README.md). Mock-Tests weisen die Struktur nach; Aktivierung, S3-Kompatibilität und Berechtigungen zum Schreiben sind erst durch den anschließenden Integrationstest belegt. +First real Plan on 2026-09-29 for lzc-dev/eu01 succeeded: **3 to create, 0 to change, 0 to delete**. Planned credential expiry: 2026-12-28. No Apply executed. The saved Plan is encrypted and Git-ignored under `.local/bootstrap/review.tfplan` and usable for only 24 hours. -Aktuell: Remote-Backend initialisiert, echter Plan mit 3 Create erfolgreich; für diesen Root weiterhin kein Apply. +[Operator instructions](../README.md). Mock tests demonstrate the structure; activation, S3 compatibility and write permissions are demonstrated only by the subsequent integration test. -## Erster CI-Apply erfolgreich +Current: remote backend initialized, real Plan with 3 creates successful; still no Apply for this root. -Am 2026-09-29 wurde Bootstrap auf dem Feature-Branch über [Run 36601941540](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36601941540) angewendet: drei Ressourcen erstellt, keine Änderungen oder Löschungen. Der verschlüsselte State im Verwaltungs-Bucket enthält alle drei Ressourcen. Die einmalige Commit-Freigabe wurde anschließend entfernt. Die zuvor genannten Angaben „kein Apply“ beschreiben den früheren Planungsstand. + -Der nächste Infrastruktur-Schritt ist der separate Backend-Root zur Versionierung des neu erstellten Workload-State-Buckets. Dieser Root wurde noch nicht angewendet. +## First CI Apply succeeded + +On 2026-09-29, bootstrap was applied on the feature branch through [run 36601941540](https://github.com/stackitcloud/stackit-landing-zone/actions/runs/36601941540): three resources created, no changes or deletions. The encrypted state in the management bucket contains all three resources. The one-time commit approval was subsequently removed. The preceding “no Apply” statements describe the earlier planning status. + +The next infrastructure step is the separate backend root to enable versioning on the newly created workload state bucket. This root has not yet been applied. diff --git a/landing-zone-configurator/infra/ci/README.de.md b/landing-zone-configurator/infra/ci/README.de.md new file mode 100644 index 0000000..774a2db --- /dev/null +++ b/landing-zone-configurator/infra/ci/README.de.md @@ -0,0 +1,162 @@ +# OpenTofu in GitHub Actions + +[English](README.md) | [Deutsch](README.de.md) + +Die zentrale [Workflow-Uebersicht](../../../docs/workflows.de.md) beschreibt alle +Pipelines, automatische und manuelle Ausloeser, Eingaben und den Start im +GitHub-UI. Diese Seite vertieft die Operator- und Freigabevertraege. + +Die ausführbaren Deployments stehen direkt in den Workflows: + +- [Configurator Bootstrap](../../../.github/workflows/configurator-bootstrap.yml): `bootstrap` oder `backend`. +- [Configurator Platform](../../../.github/workflows/configurator-platform.yml): `platform`. +- [Configurator Runtime](../../../.github/workflows/configurator-runtime.yml): `runtime`. +- [Configurator Release](../../../.github/workflows/configurator-release.yml): gebautes Web/API-Paket mit direkten `cf`-Befehlen ausliefern. +- [Validierung](../../../.github/workflows/validate-configurator.yml): Formatierung, Validierung und Mock-Tests aller sechs Roots ohne Cloud-Credentials. + +Jeder Deployment-Job zeigt die einzelnen Schritte: Credential-Vorbereitung, gegebenenfalls Lesen der vorherigen Backend-Outputs, `tofu init`, `tofu validate`, `tofu plan` beziehungsweise `tofu apply`. Es gibt keinen eigenen JavaScript-Deployment-Runner. Einmalige Recovery-Operationen gehören nicht in diesen normalen Ablauf. + + + +## Plan und Apply + +Plan und Apply sind getrennte Jobs. Der Plan wird mit `-out` gespeichert und durch die native OpenTofu-Konfiguration verschlüsselt. Der Apply lädt genau das Plan-Artefakt desselben Runs herunter. Nach Prüfung des Plans erfolgt die Freigabe im geschützten GitHub Environment. Eine kleine Integritätsprüfung bindet das Artefakt an Hash, Commit, Repository, Run, Root, Eingaben und IaC-Dateien; Pläne sind höchstens 24 Stunden gültig. OpenTofu prüft zusätzlich, ob der State seit der Planung verändert wurde. Re-runs sind gesperrt: einen neuen Run mit frischem Plan starten. + +Die zentralen Befehle stehen sichtbar im Workflow, beispielsweise: + +```sh +tofu -chdir="infra/$LZC_ROOT" init -input=false -lockfile=readonly -backend-config="$LZC_PRIVATE/$LZC_ROOT.backend.hcl" +tofu -chdir="infra/$LZC_ROOT" validate -no-color +tofu -chdir=infra/platform plan -input=false -no-color -var-file=../environments/lzc-dev.tfvars.json -out="$LZC_PLAN" +timeout --foreground --signal=INT --kill-after=10m 70m \ + tofu -chdir=infra/platform apply -input=false -no-color "$LZC_PLAN" +``` + +Die Workflows enthalten alle benötigten Umgebungsvariablen, Vorbereitungsschritte und Optionen. Diese Ausschnitte sind keine Anleitung für einen parallelen lokalen Apply. + + + +## Logs und Secrets + +Normale OpenTofu-Ausgaben erscheinen live im jeweiligen Schritt: Ressourcenänderungen, Fortschritt, Warnungen und Fehler. `sensitive`-Attribute/Outputs werden von OpenTofu maskiert; zusätzlich registriert die Vorbereitung die übergebenen Backend-Zugangsdaten und Verschlüsselungsschlüssel mit GitHubs `add-mask`. Kein `TF_LOG=DEBUG` und kein Shell-`set -x` für Deployment-Secrets. + +`tofu output -json` und State-Ausgaben können sensible Werte enthalten. Deshalb werden ausschließlich diese Ausgaben direkt in private Dateien unter `$RUNNER_TEMP/lzc-private` umgeleitet, mit `umask 077`. Sie werden nicht als Klartext-Artefakte hochgeladen. Die Credential-Vorbereitung führt selbst keine OpenTofu-Befehle aus. Zum Jobende werden die temporären Dateien entfernt. + +Quellen: [OpenTofu sensitive outputs](https://opentofu.org/docs/language/values/outputs/#sensitive--suppressing-values-in-cli-output), [GNU timeout](https://www.gnu.org/software/coreutils/manual/html_node/timeout-invocation.html). + + + +## Kleine Hilfsprogramme + +| Datei | Begrenzte Aufgabe | +| --- | --- | +| `prepare.mjs` | Private Credential-/Backend-Dateien und Umgebungsvariablen vorbereiten; vorhandene Workload-Outputs/Versionierung prüfen. Keine Prozessausführung. | +| `prepare-release.mjs` | Private Backend-Konfiguration und erlaubte App-Variablen für CF vorbereiten. Keine Prozessausführung. | +| `buildpack-source.mjs` | Im isolierten Release-Job den geschützten, SHA-gebundenen Buildpack-Tag anlegen; im Deployment nur lesend prüfen. Keine Tag-Updates oder -Löschungen. | +| `review.mjs` | Verschlüsselten Plan mit Manifest versehen beziehungsweise vor Apply prüfen. Keine Prozessausführung. | +| `protect-state.mjs`, `artifact.mjs` | Bereits erfasste State-Dateien für Recovery verschlüsseln. Keine Prozessausführung. | +| `context.mjs` | Eingaben, Workflow-Identität und Planbindung prüfen. | +| `configure-github.mjs` | Separates Operator-Werkzeug für Environment-Regeln und ausdrücklich freigegebene Secret-Transfers. Kein Bestandteil eines Deployments. | + + + +## Backend- und Schlüsseltrennung + +Bootstrap und Backend verwenden den Verwaltungs-Bucket. Der Plattform-Job initialisiert zunächst diese beiden Roots und liest ihre Outputs privat. Erst nach Prüfung der Bucket-Versionierung wechselt er für seinen eigenen State zu den Workload-S3-Credentials. Jeder Root behält seinen separaten State-Verschlüsselungsschlüssel. Seed-Schlüssel werden nicht an diese Deployment-Jobs übergeben. + +| Environment | Zweck | +| --- | --- | +| `lzc-dev-bootstrap-plan` / `lzc-dev-bootstrap-apply` | Bootstrap-/Backend-Plan und freizugebender Apply | +| `lzc-dev-platform-plan` / `lzc-dev-platform-apply` | Plattform-Plan und freizugebender Apply | +| `lzc-dev-runtime-plan` / `lzc-dev-runtime-apply` | Space, Rollen und Laufzeitbenutzer | +| `lzc-dev-release` | CF-Release; Workload-S3-Zugang und Plattform-/Runtime-State-Schlüssel, kein Projekt-Service-Account | +| `lzc-dev-recovery` | Separat geschützte Seed-Recovery-Secrets, kein automatischer Recovery-Job | +| `assistant-tests` | Nur der dedizierte Model-Serving-Testtoken; keine Cloud-, State- oder Ausführungs-Credentials | + +Die Konfiguration steht in `github-environments.json`, `github-platform-environments.json`, `github-runtime-environments.json` und `github-release-environments.json`. Änderungen an Secret-Zielen oder Schlüsselübertragungen benötigen die entsprechende Benutzerautorisierung. Das Operator-Werkzeug lautet `node infra/ci/configure-github.mjs` beziehungsweise mit `--platform`, `--runtime` oder `--release` für die jeweiligen Environments. + +Für die Assistant-Qualifikation verwaltet `github-assistant-environments.json` ausschließlich `assistant-tests`, beschränkt auf `main` und `feature/landing-zone-configurator`. Nach dem freigegebenen Plattform-Apply liest `node infra/ci/configure-github.mjs --assistant` den neuen Testtoken aus der privaten, unverändert verschlüsselten Recovery-Datei `.local/assistant-test-platform-state.enc.json` und überträgt nur `LZC_MODEL_SERVING_TOKEN` über stdin an `gh secret set`. Dafür Node.js 24.21.0 verwenden; dieser Modus benötigt weder Seed-Zugriff noch einen OpenTofu-Unterprozess. Die Datei stammt aus der Recovery-Sicherung des erfolgreichen Applies und wird ausschließlich im Speicher entschlüsselt; vorhandene native State-Snapshots bleiben unverändert. Tokenwerte erscheinen weder im Terminal noch in Git; allgemeine STACKIT-Zugangsdaten und State-Schlüssel werden nicht an die Testumgebung übertragen. Das Environment benötigt keine manuelle Testfreigabe, erlaubt aber keine fremden Branches oder Tags. + + + +## Manuelle Ausloesung und Serialisierung + +Alle mutierenden Configurator-Workflows verwenden `concurrency.group: configurator-lzc-dev-mutation` und `cancel-in-progress: false`, einschließlich Plan und Freigabewartezeit. Native S3-Sperren haben den Integrationstest nicht bestanden; `backend-safety.json` hält diesen Befund fest. Lokale Remote-Applies und schreibende Parallelzugriffe außerhalb dieser CI-Gruppe bleiben im vereinbarten Betrieb ausgeschlossen. Direkte CLI-Aufrufe durch Credential-Inhaber lassen sich nicht durch einen lokalen Wrapper oder GitHub-Concurrency verhindern. + +Pushes und Pull Requests starten keine Infrastrukturplaene oder Deployments. +Bootstrap, Platform und Runtime werden ausschliesslich per `workflow_dispatch` +von `main` gestartet; Apply benoetigt zusaetzlich `apply=true` und die +Environment-Freigabe. Fuer den Backend-Root `root=backend` auswaehlen. +Die `LZC_PLATFORM_CI_ENABLED`-/`LZC_RUNTIME_CI_ENABLED`-Schalter bleiben zusaetzliche +Betreibergates, ersetzen aber keine manuelle Ausloesung. Alte Commit-SHA- +Freigabevariablen fuer Feature-Pushes werden nicht mehr ausgewertet. +Auch der Application-Release ist ausschliesslich manuell; ein Merge loest ihn +nicht aus. Die vorhandenen Workflows betreffen die Entwicklungsumgebung, +nicht eine neue Produktionsumgebung. + +Nach erfolgreicher Assistant-Qualifikation und Build veroeffentlicht der +isolierte Release-Job `publish_buildpack` den fehlenden Buildpack-Tag. +Das gilt auch fuer `build_only=true`, solange der qualifizierte Commit noch +Branch-HEAD ist; ein Build-only-Lauf fuehrt weiterhin kein Deployment aus. +Nur dieser Job besitzt `contents: write`; er hat kein Cloud-Environment und +keine Cloud-Credentials. Bei Artefakt-Promotion wird dieser schreibfaehige Job +uebersprungen. Der Deployment-Job prueft erneut die erfolgreichen +Qualifikations-/Build-Jobs und verlangt den bereits vorhandenen, exakt +SHA-gebundenen und unveraenderlich geschuetzten Tag. +Er bleibt lesend und prueft den Tag vor dem Lesen der Deployment-Credentials. +GitHub kann fuer das Taggen historischer Commits zusaetzlich `workflows: write` +verlangen; diese Berechtigung ist fuer `GITHUB_TOKEN` nicht verfuegbar. +Fehlt bei einem aelteren qualifizierten Build der Tag, ist ein ausdruecklich +autorisierter Operator-Backfill erforderlich: Quelle zuerst mit +`release-artifact.mjs source` validieren, dann `buildpack-source.mjs publish` +mit genau dieser Revision und Operator-Authentifizierung ausfuehren. +Den Operator-Token niemals in CI hinterlegen oder den Tag-Schutz lockern. +Ein fehlgeschlagenes Deployment macht einen zuvor +erfolgreich qualifizierten Build nicht ungueltig: Ein neuer manueller Run kann +ihn mit `release_run_id` uebernehmen, solange das Artefakt nicht abgelaufen ist. + +Die vorhandene Plan-Service-Account-Rolle ist nicht rein lesend. Deshalb dürfen diese Workflows ausschließlich vertrauenswürdigen Code ausführen; sie sind nicht für externe Pull Requests vorgesehen. + + + +## Timeouts und State-Sicherung + +Die Grenze steht direkt am jeweiligen `tofu`-Befehl und verwendet GNU `timeout`: + +| Schritt | Geordneter Abbruch nach | Zeit bis SIGKILL | Äußeres Joblimit | +| --- | --- | --- | --- | +| Plan | 15 Minuten | weitere 2 Minuten | 30 Minuten | +| Bootstrap-/Backend-Apply | 20 Minuten | weitere 5 Minuten | 45 Minuten | +| Plattform-Apply | 70 Minuten | weitere 10 Minuten | 100 Minuten | + +Ein Timeout sendet zunächst `SIGINT`, damit OpenTofu Provider beenden und State persistieren kann. Der Exit-Code bleibt ein Fehler, auch wenn der Prozess danach geordnet endet. Ein dauerhaft blockierter Prozess kann nach der zusätzlichen Wartezeit hart beendet werden. Die kurzen Init-Schritte haben eigene Grenzen; Snapshot und Upload liegen außerhalb des Apply-Kommandos und vor dem äußeren Joblimit. + +Nach einem gestarteten Apply versucht ein `always()`-Schritt ausdrücklich `tofu state pull`. `protect-state.mjs` verschlüsselt diesen Snapshot und einen gegebenenfalls vorhandenen `errored.tfstate` mit AES-256-GCM und einem per scrypt aus dem jeweiligen State-Schlüssel abgeleiteten Schlüssel. Das Format enthält `salt`, `nonce`, `tag` und `data` als Base64; der State kann zusätzlich OpenTofu-verschlüsselt sein. Nur diese geschützten Dateien werden sieben Tage als Recovery-Artefakt aufbewahrt. Plan-Artefakte bleiben einen Tag erhalten. Abrupte Runner-Verluste können weiterhin manuelle Recovery erfordern. + + + +## Betriebsnachweise + +Die bestehende Infrastruktur wird durch diese CI-Anpassung weder ersetzt noch +migriert. Historische Recovery-Inventare sind keine Pipeline-Eingaben und +gehoeren in die private Betriebsdokumentation. Fuer die aktuellen State- und +Recovery-Vertraege gelten [Architektur](../../docs/architecture.de.md) und +[Plattform-Betriebsstand](../../docs/platform-readiness.de.md). + + + +## Runtime und Release + +Der Runtime-Root liest vorhandene Plattform-Ausgaben und verwaltet den CF-Space, +die ausdrücklich benötigte `organization_user`-Mitgliedschaft vor `space_developer`, +sowie separate PostgreSQL-/Secrets-Laufzeitbenutzer. Sein verschlüsselter State +liegt im Workload-Bucket. Der erste Teil-Apply wurde regulär gespeichert; ein +frischer Plan ergänzte die fehlenden CF-Rollen ohne Duplikate oder Recovery-Import. + +`LZC_RUNTIME_CI_ENABLED` und `LZC_RELEASE_CI_ENABLED` aktivieren die entsprechenden +Workflows. Die Benutzerfreigabe vom 2026-09-30 umfasst notwendige Configurator- +Deployment-Applies bis MVP; Scope-/Planprüfung und Environment-Freigaben bleiben. +Der Release-Workflow baut ohne Cloud-Secrets, lädt ein Paket desselben Runs und +prüft dessen SHA-256. Erst der geschützte Deploy-Job liest Zugangsdaten. Die normalen +`cf push`-/Task-Logs bleiben sichtbar; Umgebungswerte sind maskiert. Der API-Zugang +bleibt bis zur Login-Implementierung gesperrt. [Release-Details](../../deploy/cloud-foundry/README.de.md). diff --git a/landing-zone-configurator/infra/ci/README.md b/landing-zone-configurator/infra/ci/README.md index 31b9998..eadcc89 100644 --- a/landing-zone-configurator/infra/ci/README.md +++ b/landing-zone-configurator/infra/ci/README.md @@ -1,24 +1,28 @@ # OpenTofu in GitHub Actions -Die zentrale [Workflow-Uebersicht](../../../docs/workflows.md) beschreibt alle -Pipelines, automatische und manuelle Ausloeser, Eingaben und den Start im -GitHub-UI. Diese Seite vertieft die Operator- und Freigabevertraege. +[English](README.md) | [Deutsch](README.de.md) -Die ausführbaren Deployments stehen direkt in den Workflows: +The central [workflow overview](../../../docs/workflows.md) describes all +pipelines, automatic and manual triggers, inputs and starting them in the +GitHub UI. This page expands on operator and approval contracts. -- [Configurator Bootstrap](../../../.github/workflows/configurator-bootstrap.yml): `bootstrap` oder `backend`. +Executable deployments are defined directly in the workflows: + +- [Configurator Bootstrap](../../../.github/workflows/configurator-bootstrap.yml): `bootstrap` or `backend`. - [Configurator Platform](../../../.github/workflows/configurator-platform.yml): `platform`. - [Configurator Runtime](../../../.github/workflows/configurator-runtime.yml): `runtime`. -- [Configurator Release](../../../.github/workflows/configurator-release.yml): gebautes Web/API-Paket mit direkten `cf`-Befehlen ausliefern. -- [Validierung](../../../.github/workflows/validate-configurator.yml): Formatierung, Validierung und Mock-Tests aller sechs Roots ohne Cloud-Credentials. +- [Configurator Release](../../../.github/workflows/configurator-release.yml): deliver the built Web/API package with direct `cf` commands. +- [Validation](../../../.github/workflows/validate-configurator.yml): formatting, validation and mock tests for all six roots without cloud credentials. + +Each deployment job shows the individual steps: credential preparation, reading previous backend outputs if applicable, `tofu init`, `tofu validate`, `tofu plan` or `tofu apply`. There is no custom JavaScript deployment runner. One-time recovery operations do not belong in this normal process. -Jeder Deployment-Job zeigt die einzelnen Schritte: Credential-Vorbereitung, gegebenenfalls Lesen der vorherigen Backend-Outputs, `tofu init`, `tofu validate`, `tofu plan` beziehungsweise `tofu apply`. Es gibt keinen eigenen JavaScript-Deployment-Runner. Einmalige Recovery-Operationen gehören nicht in diesen normalen Ablauf. + -## Plan und Apply +## Plan and Apply -Plan und Apply sind getrennte Jobs. Der Plan wird mit `-out` gespeichert und durch die native OpenTofu-Konfiguration verschlüsselt. Der Apply lädt genau das Plan-Artefakt desselben Runs herunter. Nach Prüfung des Plans erfolgt die Freigabe im geschützten GitHub Environment. Eine kleine Integritätsprüfung bindet das Artefakt an Hash, Commit, Repository, Run, Root, Eingaben und IaC-Dateien; Pläne sind höchstens 24 Stunden gültig. OpenTofu prüft zusätzlich, ob der State seit der Planung verändert wurde. Re-runs sind gesperrt: einen neuen Run mit frischem Plan starten. +Plan and Apply are separate jobs. The Plan is saved with `-out` and encrypted by the native OpenTofu configuration. Apply downloads exactly the Plan artifact from the same run. After reviewing the Plan, approval is granted in the protected GitHub Environment. A small integrity check binds the artifact to its hash, commit, repository, run, root, inputs and IaC files; Plans are valid for at most 24 hours. OpenTofu additionally checks whether state has changed since planning. Re-runs are blocked: start a new run with a fresh Plan. -Die zentralen Befehle stehen sichtbar im Workflow, beispielsweise: +The central commands are visible in the workflow, for example: ```sh tofu -chdir="infra/$LZC_ROOT" init -input=false -lockfile=readonly -backend-config="$LZC_PRIVATE/$LZC_ROOT.backend.hcl" @@ -28,117 +32,131 @@ timeout --foreground --signal=INT --kill-after=10m 70m \ tofu -chdir=infra/platform apply -input=false -no-color "$LZC_PLAN" ``` -Die Workflows enthalten alle benötigten Umgebungsvariablen, Vorbereitungsschritte und Optionen. Diese Ausschnitte sind keine Anleitung für einen parallelen lokalen Apply. +The workflows contain all required environment variables, preparation steps and options. These excerpts are not instructions for a parallel local Apply. + + + +## Logs and secrets -## Logs und Secrets +Normal OpenTofu output appears live in the respective step: resource changes, progress, warnings and errors. OpenTofu masks `sensitive` attributes/outputs; preparation additionally registers the supplied backend credentials and encryption keys with GitHub's `add-mask`. No `TF_LOG=DEBUG` or shell `set -x` for deployment secrets. -Normale OpenTofu-Ausgaben erscheinen live im jeweiligen Schritt: Ressourcenänderungen, Fortschritt, Warnungen und Fehler. `sensitive`-Attribute/Outputs werden von OpenTofu maskiert; zusätzlich registriert die Vorbereitung die übergebenen Backend-Zugangsdaten und Verschlüsselungsschlüssel mit GitHubs `add-mask`. Kein `TF_LOG=DEBUG` und kein Shell-`set -x` für Deployment-Secrets. +`tofu output -json` and state output can contain sensitive values. Therefore, only these outputs are redirected directly into private files under `$RUNNER_TEMP/lzc-private`, with `umask 077`. They are not uploaded as plaintext artifacts. Credential preparation itself runs no OpenTofu commands. Temporary files are removed at the end of the job. -`tofu output -json` und State-Ausgaben können sensible Werte enthalten. Deshalb werden ausschließlich diese Ausgaben direkt in private Dateien unter `$RUNNER_TEMP/lzc-private` umgeleitet, mit `umask 077`. Sie werden nicht als Klartext-Artefakte hochgeladen. Die Credential-Vorbereitung führt selbst keine OpenTofu-Befehle aus. Zum Jobende werden die temporären Dateien entfernt. +Sources: [OpenTofu sensitive outputs](https://opentofu.org/docs/language/values/outputs/#sensitive--suppressing-values-in-cli-output), [GNU timeout](https://www.gnu.org/software/coreutils/manual/html_node/timeout-invocation.html). -Quellen: [OpenTofu sensitive outputs](https://opentofu.org/docs/language/values/outputs/#sensitive--suppressing-values-in-cli-output), [GNU timeout](https://www.gnu.org/software/coreutils/manual/html_node/timeout-invocation.html). + -## Kleine Hilfsprogramme +## Small utilities -| Datei | Begrenzte Aufgabe | +| File | Limited responsibility | | --- | --- | -| `prepare.mjs` | Private Credential-/Backend-Dateien und Umgebungsvariablen vorbereiten; vorhandene Workload-Outputs/Versionierung prüfen. Keine Prozessausführung. | -| `prepare-release.mjs` | Private Backend-Konfiguration und erlaubte App-Variablen für CF vorbereiten. Keine Prozessausführung. | -| `buildpack-source.mjs` | Im isolierten Release-Job den geschützten, SHA-gebundenen Buildpack-Tag anlegen; im Deployment nur lesend prüfen. Keine Tag-Updates oder -Löschungen. | -| `review.mjs` | Verschlüsselten Plan mit Manifest versehen beziehungsweise vor Apply prüfen. Keine Prozessausführung. | -| `protect-state.mjs`, `artifact.mjs` | Bereits erfasste State-Dateien für Recovery verschlüsseln. Keine Prozessausführung. | -| `context.mjs` | Eingaben, Workflow-Identität und Planbindung prüfen. | -| `configure-github.mjs` | Separates Operator-Werkzeug für Environment-Regeln und ausdrücklich freigegebene Secret-Transfers. Kein Bestandteil eines Deployments. | +| `prepare.mjs` | Prepare private credential/backend files and environment variables; check existing workload outputs/versioning. No process execution. | +| `prepare-release.mjs` | Prepare private backend configuration and allowed app variables for CF. No process execution. | +| `buildpack-source.mjs` | Create the protected, SHA-bound buildpack tag in the isolated release job; verify read-only during deployment. No tag updates or deletions. | +| `review.mjs` | Add a manifest to the encrypted Plan or check it before Apply. No process execution. | +| `protect-state.mjs`, `artifact.mjs` | Encrypt already captured state files for recovery. No process execution. | +| `context.mjs` | Check inputs, workflow identity and Plan binding. | +| `configure-github.mjs` | Separate operator tool for environment rules and explicitly authorized secret transfers. Not part of a deployment. | -## Backend- und Schlüsseltrennung + -Bootstrap und Backend verwenden den Verwaltungs-Bucket. Der Plattform-Job initialisiert zunächst diese beiden Roots und liest ihre Outputs privat. Erst nach Prüfung der Bucket-Versionierung wechselt er für seinen eigenen State zu den Workload-S3-Credentials. Jeder Root behält seinen separaten State-Verschlüsselungsschlüssel. Seed-Schlüssel werden nicht an diese Deployment-Jobs übergeben. +## Backend and key separation -| Environment | Zweck | +Bootstrap and backend use the management bucket. The platform job first initializes these two roots and reads their outputs privately. Only after checking bucket versioning does it switch to the workload S3 credentials for its own state. Each root retains its separate state encryption key. Seed keys are not passed to these deployment jobs. + +| Environment | Purpose | | --- | --- | -| `lzc-dev-bootstrap-plan` / `lzc-dev-bootstrap-apply` | Bootstrap-/Backend-Plan und freizugebender Apply | -| `lzc-dev-platform-plan` / `lzc-dev-platform-apply` | Plattform-Plan und freizugebender Apply | -| `lzc-dev-runtime-plan` / `lzc-dev-runtime-apply` | Space, Rollen und Laufzeitbenutzer | -| `lzc-dev-release` | CF-Release; Workload-S3-Zugang und Plattform-/Runtime-State-Schlüssel, kein Projekt-Service-Account | -| `lzc-dev-recovery` | Separat geschützte Seed-Recovery-Secrets, kein automatischer Recovery-Job | -| `assistant-tests` | Nur der dedizierte Model-Serving-Testtoken; keine Cloud-, State- oder Ausführungs-Credentials | - -Die Konfiguration steht in `github-environments.json`, `github-platform-environments.json`, `github-runtime-environments.json` und `github-release-environments.json`. Änderungen an Secret-Zielen oder Schlüsselübertragungen benötigen die entsprechende Benutzerautorisierung. Das Operator-Werkzeug lautet `node infra/ci/configure-github.mjs` beziehungsweise mit `--platform`, `--runtime` oder `--release` für die jeweiligen Environments. - -Für die Assistant-Qualifikation verwaltet `github-assistant-environments.json` ausschließlich `assistant-tests`, beschränkt auf `main` und `feature/landing-zone-configurator`. Nach dem freigegebenen Plattform-Apply liest `node infra/ci/configure-github.mjs --assistant` den neuen Testtoken aus der privaten, unverändert verschlüsselten Recovery-Datei `.local/assistant-test-platform-state.enc.json` und überträgt nur `LZC_MODEL_SERVING_TOKEN` über stdin an `gh secret set`. Dafür Node.js 24.21.0 verwenden; dieser Modus benötigt weder Seed-Zugriff noch einen OpenTofu-Unterprozess. Die Datei stammt aus der Recovery-Sicherung des erfolgreichen Applies und wird ausschließlich im Speicher entschlüsselt; vorhandene native State-Snapshots bleiben unverändert. Tokenwerte erscheinen weder im Terminal noch in Git; allgemeine STACKIT-Zugangsdaten und State-Schlüssel werden nicht an die Testumgebung übertragen. Das Environment benötigt keine manuelle Testfreigabe, erlaubt aber keine fremden Branches oder Tags. - -## Manuelle Ausloesung und Serialisierung - -Alle mutierenden Configurator-Workflows verwenden `concurrency.group: configurator-lzc-dev-mutation` und `cancel-in-progress: false`, einschließlich Plan und Freigabewartezeit. Native S3-Sperren haben den Integrationstest nicht bestanden; `backend-safety.json` hält diesen Befund fest. Lokale Remote-Applies und schreibende Parallelzugriffe außerhalb dieser CI-Gruppe bleiben im vereinbarten Betrieb ausgeschlossen. Direkte CLI-Aufrufe durch Credential-Inhaber lassen sich nicht durch einen lokalen Wrapper oder GitHub-Concurrency verhindern. - -Pushes und Pull Requests starten keine Infrastrukturplaene oder Deployments. -Bootstrap, Platform und Runtime werden ausschliesslich per `workflow_dispatch` -von `main` gestartet; Apply benoetigt zusaetzlich `apply=true` und die -Environment-Freigabe. Fuer den Backend-Root `root=backend` auswaehlen. -Die `LZC_PLATFORM_CI_ENABLED`-/`LZC_RUNTIME_CI_ENABLED`-Schalter bleiben zusaetzliche -Betreibergates, ersetzen aber keine manuelle Ausloesung. Alte Commit-SHA- -Freigabevariablen fuer Feature-Pushes werden nicht mehr ausgewertet. -Auch der Application-Release ist ausschliesslich manuell; ein Merge loest ihn -nicht aus. Die vorhandenen Workflows betreffen die Entwicklungsumgebung, -nicht eine neue Produktionsumgebung. - -Nach erfolgreicher Assistant-Qualifikation und Build veroeffentlicht der -isolierte Release-Job `publish_buildpack` den fehlenden Buildpack-Tag. -Das gilt auch fuer `build_only=true`, solange der qualifizierte Commit noch -Branch-HEAD ist; ein Build-only-Lauf fuehrt weiterhin kein Deployment aus. -Nur dieser Job besitzt `contents: write`; er hat kein Cloud-Environment und -keine Cloud-Credentials. Bei Artefakt-Promotion wird dieser schreibfaehige Job -uebersprungen. Der Deployment-Job prueft erneut die erfolgreichen -Qualifikations-/Build-Jobs und verlangt den bereits vorhandenen, exakt -SHA-gebundenen und unveraenderlich geschuetzten Tag. -Er bleibt lesend und prueft den Tag vor dem Lesen der Deployment-Credentials. -GitHub kann fuer das Taggen historischer Commits zusaetzlich `workflows: write` -verlangen; diese Berechtigung ist fuer `GITHUB_TOKEN` nicht verfuegbar. -Fehlt bei einem aelteren qualifizierten Build der Tag, ist ein ausdruecklich -autorisierter Operator-Backfill erforderlich: Quelle zuerst mit -`release-artifact.mjs source` validieren, dann `buildpack-source.mjs publish` -mit genau dieser Revision und Operator-Authentifizierung ausfuehren. -Den Operator-Token niemals in CI hinterlegen oder den Tag-Schutz lockern. -Ein fehlgeschlagenes Deployment macht einen zuvor -erfolgreich qualifizierten Build nicht ungueltig: Ein neuer manueller Run kann -ihn mit `release_run_id` uebernehmen, solange das Artefakt nicht abgelaufen ist. - -Die vorhandene Plan-Service-Account-Rolle ist nicht rein lesend. Deshalb dürfen diese Workflows ausschließlich vertrauenswürdigen Code ausführen; sie sind nicht für externe Pull Requests vorgesehen. - -## Timeouts und State-Sicherung - -Die Grenze steht direkt am jeweiligen `tofu`-Befehl und verwendet GNU `timeout`: - -| Schritt | Geordneter Abbruch nach | Zeit bis SIGKILL | Äußeres Joblimit | +| `lzc-dev-bootstrap-plan` / `lzc-dev-bootstrap-apply` | Bootstrap/backend Plan and Apply requiring approval | +| `lzc-dev-platform-plan` / `lzc-dev-platform-apply` | Platform Plan and Apply requiring approval | +| `lzc-dev-runtime-plan` / `lzc-dev-runtime-apply` | Space, roles and runtime users | +| `lzc-dev-release` | CF release; workload S3 access and platform/runtime state keys, no project service account | +| `lzc-dev-recovery` | Separately protected seed recovery secrets, no automatic recovery job | +| `assistant-tests` | Only the dedicated Model Serving test token; no cloud, state or execution credentials | + +Configuration is in `github-environments.json`, `github-platform-environments.json`, `github-runtime-environments.json` and `github-release-environments.json`. Changes to secret destinations or key transfers require the corresponding user authorization. The operator tool is `node infra/ci/configure-github.mjs`, or with `--platform`, `--runtime` or `--release` for the respective environments. + +For Assistant qualification, `github-assistant-environments.json` manages only `assistant-tests`, restricted to `main` and `feature/landing-zone-configurator`. After the approved platform Apply, `node infra/ci/configure-github.mjs --assistant` reads the new test token from the private, unchanged encrypted recovery file `.local/assistant-test-platform-state.enc.json` and transfers only `LZC_MODEL_SERVING_TOKEN` through stdin to `gh secret set`. Use Node.js 24.21.0; this mode requires neither seed access nor an OpenTofu subprocess. The file comes from the recovery backup of the successful Apply and is decrypted exclusively in memory; existing native state snapshots remain unchanged. Token values appear neither in the terminal nor in Git; general STACKIT credentials and state keys are not transferred to the test environment. The environment requires no manual test approval but allows no other branches or tags. + + + +## Manual triggering and serialization + +All mutating Configurator workflows use `concurrency.group: configurator-lzc-dev-mutation` and `cancel-in-progress: false`, including Plan and approval wait time. Native S3 locks failed the integration test; `backend-safety.json` records this finding. Local remote Applies and concurrent writes outside this CI group remain excluded under the agreed operating model. Direct CLI calls by credential holders cannot be prevented by a local wrapper or GitHub concurrency. + +Pushes and pull requests start no infrastructure Plans or deployments. +Bootstrap, Platform and Runtime are started exclusively through `workflow_dispatch` +from `main`; Apply additionally requires `apply=true` and +environment approval. For the backend root, select `root=backend`. +The `LZC_PLATFORM_CI_ENABLED`/`LZC_RUNTIME_CI_ENABLED` switches remain additional +operator gates but do not replace manual triggering. Old commit SHA +approval variables for feature pushes are no longer evaluated. +Application release is also exclusively manual; a merge does not +trigger it. The existing workflows concern the development environment, +not a new production environment. + +After successful Assistant qualification and build, the +isolated release job `publish_buildpack` publishes the missing buildpack tag. +This also applies to `build_only=true`, as long as the qualified commit is still +branch HEAD; a build-only run still performs no deployment. +Only this job has `contents: write`; it has no cloud environment and +no cloud credentials. This write-capable job is skipped +during artifact promotion. The deployment job rechecks the successful +qualification/build jobs and requires the already existing, exactly +SHA-bound and immutably protected tag. +It remains read-only and checks the tag before reading deployment credentials. +GitHub may additionally require `workflows: write` for tagging historical +commits; this permission is unavailable for `GITHUB_TOKEN`. +If an older qualified build lacks the tag, an explicitly +authorized operator backfill is required: first validate the source with +`release-artifact.mjs source`, then run `buildpack-source.mjs publish` +with exactly that revision and operator authentication. +Never store the operator token in CI or weaken tag protection. +A failed deployment does not invalidate a previously +successfully qualified build: a new manual run can +adopt it using `release_run_id` as long as the artifact has not expired. + +The existing Plan service account role is not read-only. Therefore, these workflows may execute only trusted code; they are not intended for external pull requests. + + + +## Timeouts and state backup + +The limit is set directly on each `tofu` command and uses GNU `timeout`: + +| Step | Graceful termination after | Time until SIGKILL | Outer job limit | | --- | --- | --- | --- | -| Plan | 15 Minuten | weitere 2 Minuten | 30 Minuten | -| Bootstrap-/Backend-Apply | 20 Minuten | weitere 5 Minuten | 45 Minuten | -| Plattform-Apply | 70 Minuten | weitere 10 Minuten | 100 Minuten | +| Plan | 15 minutes | Another 2 minutes | 30 minutes | +| Bootstrap/backend Apply | 20 minutes | Another 5 minutes | 45 minutes | +| Platform Apply | 70 minutes | Another 10 minutes | 100 minutes | + +A timeout first sends `SIGINT` so OpenTofu can stop providers and persist state. The exit code remains an error even if the process subsequently ends gracefully. A permanently blocked process can be forcibly terminated after the additional wait. Short init steps have their own limits; snapshot and upload occur outside the Apply command and before the outer job limit. + +After an Apply has started, an `always()` step explicitly attempts `tofu state pull`. `protect-state.mjs` encrypts this snapshot and any existing `errored.tfstate` using AES-256-GCM and a key derived through scrypt from the respective state key. The format contains `salt`, `nonce`, `tag` and `data` as Base64; state may additionally be OpenTofu-encrypted. Only these protected files are retained for seven days as recovery artifacts. Plan artifacts are retained for one day. Abrupt Runner loss may still require manual recovery. -Ein Timeout sendet zunächst `SIGINT`, damit OpenTofu Provider beenden und State persistieren kann. Der Exit-Code bleibt ein Fehler, auch wenn der Prozess danach geordnet endet. Ein dauerhaft blockierter Prozess kann nach der zusätzlichen Wartezeit hart beendet werden. Die kurzen Init-Schritte haben eigene Grenzen; Snapshot und Upload liegen außerhalb des Apply-Kommandos und vor dem äußeren Joblimit. + -Nach einem gestarteten Apply versucht ein `always()`-Schritt ausdrücklich `tofu state pull`. `protect-state.mjs` verschlüsselt diesen Snapshot und einen gegebenenfalls vorhandenen `errored.tfstate` mit AES-256-GCM und einem per scrypt aus dem jeweiligen State-Schlüssel abgeleiteten Schlüssel. Das Format enthält `salt`, `nonce`, `tag` und `data` als Base64; der State kann zusätzlich OpenTofu-verschlüsselt sein. Nur diese geschützten Dateien werden sieben Tage als Recovery-Artefakt aufbewahrt. Plan-Artefakte bleiben einen Tag erhalten. Abrupte Runner-Verluste können weiterhin manuelle Recovery erfordern. +## Operational evidence -## Betriebsnachweise +This CI adjustment neither replaces nor migrates existing infrastructure. +Historical recovery inventories are not pipeline inputs and +belong in private operations documentation. The current state and +recovery contracts are defined in [architecture](../../docs/architecture.md) and +[platform operational status](../../docs/platform-readiness.md). -Die bestehende Infrastruktur wird durch diese CI-Anpassung weder ersetzt noch -migriert. Historische Recovery-Inventare sind keine Pipeline-Eingaben und -gehoeren in die private Betriebsdokumentation. Fuer die aktuellen State- und -Recovery-Vertraege gelten [Architektur](../../docs/architecture.md) und -[Plattform-Betriebsstand](../../docs/platform-readiness.md). + -## Runtime und Release +## Runtime and release -Der Runtime-Root liest vorhandene Plattform-Ausgaben und verwaltet den CF-Space, -die ausdrücklich benötigte `organization_user`-Mitgliedschaft vor `space_developer`, -sowie separate PostgreSQL-/Secrets-Laufzeitbenutzer. Sein verschlüsselter State -liegt im Workload-Bucket. Der erste Teil-Apply wurde regulär gespeichert; ein -frischer Plan ergänzte die fehlenden CF-Rollen ohne Duplikate oder Recovery-Import. +The runtime root reads existing platform outputs and manages the CF space, +the explicitly required `organization_user` membership before `space_developer`, +and separate PostgreSQL/Secrets runtime users. Its encrypted state +resides in the workload bucket. The first partial Apply was saved normally; a +fresh Plan added the missing CF roles without duplicates or recovery imports. -`LZC_RUNTIME_CI_ENABLED` und `LZC_RELEASE_CI_ENABLED` aktivieren die entsprechenden -Workflows. Die Benutzerfreigabe vom 2026-09-30 umfasst notwendige Configurator- -Deployment-Applies bis MVP; Scope-/Planprüfung und Environment-Freigaben bleiben. -Der Release-Workflow baut ohne Cloud-Secrets, lädt ein Paket desselben Runs und -prüft dessen SHA-256. Erst der geschützte Deploy-Job liest Zugangsdaten. Die normalen -`cf push`-/Task-Logs bleiben sichtbar; Umgebungswerte sind maskiert. Der API-Zugang -bleibt bis zur Login-Implementierung gesperrt. [Release-Details](../../deploy/cloud-foundry/README.md). +`LZC_RUNTIME_CI_ENABLED` and `LZC_RELEASE_CI_ENABLED` enable the corresponding +workflows. The user authorization of 2026-09-30 covers necessary Configurator +deployment Applies until MVP; scope/Plan review and environment approvals remain. +The release workflow builds without cloud secrets, downloads a package from the same run and +checks its SHA-256. Only the protected deploy job reads credentials. Normal +`cf push`/task logs remain visible; environment values are masked. API access +remains blocked until login is implemented. [Release details](../../deploy/cloud-foundry/README.md). diff --git a/landing-zone-configurator/infra/environments/README.de.md b/landing-zone-configurator/infra/environments/README.de.md new file mode 100644 index 0000000..016b41f --- /dev/null +++ b/landing-zone-configurator/infra/environments/README.de.md @@ -0,0 +1,7 @@ + + +# Umgebungen + +[English](README.md) | [Deutsch](README.de.md) + +Hier später secretfreie Parameter für getrennte Entwicklungs-, Staging- und Produktionsumgebungen ablegen. Ein genanntes Betreiberprojekt bedeutet noch nicht, dass alle Umgebungen darin gemeinsam betrieben werden sollen. Zuordnung offen. diff --git a/landing-zone-configurator/infra/environments/README.md b/landing-zone-configurator/infra/environments/README.md index d7f635f..b644c7e 100644 --- a/landing-zone-configurator/infra/environments/README.md +++ b/landing-zone-configurator/infra/environments/README.md @@ -1,3 +1,7 @@ -# Umgebungen +# Environments -Hier später secretfreie Parameter für getrennte Entwicklungs-, Staging- und Produktionsumgebungen ablegen. Ein genanntes Betreiberprojekt bedeutet noch nicht, dass alle Umgebungen darin gemeinsam betrieben werden sollen. Zuordnung offen. +[English](README.md) | [Deutsch](README.de.md) + + + +Store secret-free parameters for separate development, staging and production environments here later. Naming an operator project does not yet mean that all environments should be operated together in it. Assignment remains open. diff --git a/landing-zone-configurator/infra/modules/README.de.md b/landing-zone-configurator/infra/modules/README.de.md new file mode 100644 index 0000000..a63a226 --- /dev/null +++ b/landing-zone-configurator/infra/modules/README.de.md @@ -0,0 +1,7 @@ + + +# Plattformmodule + +[English](README.md) | [Deutsch](README.de.md) + +Nur Module für Configurator-Infrastruktur. Accelerator-Module unter dem Root-`src/modules/` bleiben unabhängig. diff --git a/landing-zone-configurator/infra/modules/README.md b/landing-zone-configurator/infra/modules/README.md index 8df34e3..6b354ab 100644 --- a/landing-zone-configurator/infra/modules/README.md +++ b/landing-zone-configurator/infra/modules/README.md @@ -1,3 +1,7 @@ -# Plattformmodule +# Platform modules -Nur Module für Configurator-Infrastruktur. Accelerator-Module unter dem Root-`src/modules/` bleiben unabhängig. +[English](README.md) | [Deutsch](README.de.md) + + + +Modules for Configurator infrastructure only. Accelerator modules under the root `src/modules/` remain independent. diff --git a/landing-zone-configurator/infra/platform/README.de.md b/landing-zone-configurator/infra/platform/README.de.md new file mode 100644 index 0000000..bbdb6a7 --- /dev/null +++ b/landing-zone-configurator/infra/platform/README.de.md @@ -0,0 +1,23 @@ + + +# Configurator-Plattform + +[English](README.md) | [Deutsch](README.de.md) + +Dieser Root verwaltet CF-Organisation und technischen Org-Manager, PostgreSQL Flex samt Datenbank/Migrationsnutzer, Secrets Manager samt Provisionierungsnutzer, Artefakt-Bucket und AI Model Serving inklusive Auth-Token. Der STACKIT-Provider aktiviert Model Serving bei der Token-Erstellung. + +Region, Foundation, Quota, DB-Plan und verifizierte Quell-CIDRs sind explizite Eingaben. Keine offene Standard-ACL. Der Datenbank-Owner ist für Migrationen vorgesehen, nicht als späterer App-Benutzer; App-Rollen/RLS und Secret-Policies werden in der Runtime-Schicht ergänzt. + +Voraussetzung: erfolgreich angewendeter State-Bootstrap und Backend-Root mit aktivierter Versionierung. Die Pipeline übergibt dessen Backend-Zugang aus einer privaten temporären Output-Datei; normale OpenTofu-Ausgaben bleiben sichtbar. [IaC-Anleitung](../README.de.md). + +Ein `sensitive`-Output maskiert nur die Anzeige. Provider-erzeugte Credentials liegen im verschlüsselten State. Nachgelagerte IaC erhält nur die benötigten Outputs; keine Anbindung der unbeschränkten Provisionierungsidentitäten an Kunden-Runner. + + + +## Isolierte Plan-Runner + +`6-plan-runners.tf` provisioniert eine separate CF-Organisation `lzc-dev-runners` und +deren Manager. Der initiale geprüfte Plan enthält genau zwei Neuanlagen und keine Änderungen +oder Löschungen. Dies ist Configurator-Infrastruktur, kein Kunden-Landing-Zone-Apply. +Der Manager wird ausschließlich vom vertrauenswürdigen Dispatcher und der Release-Pipeline verwendet; +einzelne Runner-Apps erhalten ein kurzlebiges Ticket pro Job, niemals diese Identität. diff --git a/landing-zone-configurator/infra/platform/README.md b/landing-zone-configurator/infra/platform/README.md index 0e33b08..88ce730 100644 --- a/landing-zone-configurator/infra/platform/README.md +++ b/landing-zone-configurator/infra/platform/README.md @@ -1,12 +1,16 @@ -# Configurator-Plattform +# Configurator platform -Dieser Root verwaltet CF-Organisation und technischen Org-Manager, PostgreSQL Flex samt Datenbank/Migrationsnutzer, Secrets Manager samt Provisionierungsnutzer, Artefakt-Bucket und AI Model Serving inklusive Auth-Token. Der STACKIT-Provider aktiviert Model Serving bei der Token-Erstellung. +[English](README.md) | [Deutsch](README.de.md) -Region, Foundation, Quota, DB-Plan und verifizierte Quell-CIDRs sind explizite Eingaben. Keine offene Standard-ACL. Der Datenbank-Owner ist für Migrationen vorgesehen, nicht als späterer App-Benutzer; App-Rollen/RLS und Secret-Policies werden in der Runtime-Schicht ergänzt. + -Voraussetzung: erfolgreich angewendeter State-Bootstrap und Backend-Root mit aktivierter Versionierung. Die Pipeline übergibt dessen Backend-Zugang aus einer privaten temporären Output-Datei; normale OpenTofu-Ausgaben bleiben sichtbar. [IaC-Anleitung](../README.md). +This root manages the CF organization and technical org manager, PostgreSQL Flex with database/migration user, Secrets Manager with provisioning user, artifact bucket and AI Model Serving including an auth token. The STACKIT provider enables Model Serving when creating the token. -Ein `sensitive`-Output maskiert nur die Anzeige. Provider-erzeugte Credentials liegen im verschlüsselten State. Nachgelagerte IaC erhält nur die benötigten Outputs; keine Anbindung der unbeschränkten Provisionierungsidentitäten an Kunden-Runner. +Region, foundation, quota, DB plan and verified source CIDRs are explicit inputs. No open default ACL. The database owner is intended for migrations, not as the future app user; app roles/RLS and secret policies are added in the runtime layer. + +Prerequisites: successfully applied state bootstrap and backend root with versioning enabled. The pipeline passes its backend access through a private temporary output file; normal OpenTofu output remains visible. [IaC instructions](../README.md). + +A `sensitive` output masks only the display. Provider-generated credentials reside in encrypted state. Downstream IaC receives only the required outputs; unrestricted provisioning identities are not bound to customer Runners. ## Isolated plan runners diff --git a/landing-zone-configurator/infra/runtime/README.de.md b/landing-zone-configurator/infra/runtime/README.de.md new file mode 100644 index 0000000..0c482c1 --- /dev/null +++ b/landing-zone-configurator/infra/runtime/README.de.md @@ -0,0 +1,27 @@ + + +# Configurator-Runtime-Infrastruktur + +[English](README.md) | [Deutsch](README.de.md) + +Dieser Root erstellt den Space `configurator` in der bestehenden CF-Organisation `lzc-dev`, +weist der Deployment-Identität die Organisationsmitgliedschaft und die Space-Developer-Rolle zu und erstellt separate +PostgreSQL- und schreibgeschützte Secrets-Manager-Anwendungsbenutzer. Die Datenbankmigrations- +und Secrets-Provisionierungszugangsdaten der Plattform sind keine Anwendungszugangsdaten. + +Apply läuft ausschließlich in `.github/workflows/configurator-runtime.yml` mit sichtbaren +Schritten für `tofu init`, `tofu plan` und `tofu apply`. State wird mit einem eigenen +Schlüssel unter `configurator/lzc-dev/runtime/terraform.tfstate` im Workload-Bucket verschlüsselt. +Dieselbe Concurrency-Gruppe `configurator-lzc-dev-mutation` auf Workflow-Ebene serialisiert +alle Configurator-Mutationen. Lokale Applies auf Remote-State werden nicht unterstützt. + +Plattform-Outputs liefern CF-Authentifizierung und bestehende Service-IDs über private +Dateien. Der sensitive Output `app_environment` ist ausschließlich für die Backend-CF- +Anwendung bestimmt; niemals in Logs, Frontend-Builds oder unverschlüsselten Artefakten offenlegen. +Die App hat noch keine Datenbankschema-Berechtigungen, und der Secrets-Zugriff ist für diesen +Konnektivitätsmeilenstein schreibgeschützt. Tenant-Autorisierung und schreibende Credential-Operationen benötigen +eine separate Anwendungsimplementierung, bevor Benutzer aufgenommen werden. + +Benutzerfreigabe (2026-09-30): Notwendige Configurator-Deployment-Applies sind +bis zum MVP-Meilenstein genehmigt. Gespeicherte Pläne werden weiterhin auf ihren Umfang geprüft, und +die GitHub-Environment-Freigabe bleibt erhalten. Änderungen bleiben auf dem Feature-Branch. diff --git a/landing-zone-configurator/infra/runtime/README.md b/landing-zone-configurator/infra/runtime/README.md index 8a1f593..ba10320 100644 --- a/landing-zone-configurator/infra/runtime/README.md +++ b/landing-zone-configurator/infra/runtime/README.md @@ -1,5 +1,7 @@ # Configurator runtime infrastructure +[English](README.md) | [Deutsch](README.de.md) + This root creates the `configurator` space in the existing `lzc-dev` CF organization, assigns the deployment identity organization membership and the space developer role, and creates separate PostgreSQL and read-only Secrets Manager application users. The platform's database diff --git a/landing-zone-configurator/infra/seed-protection/README.de.md b/landing-zone-configurator/infra/seed-protection/README.de.md new file mode 100644 index 0000000..8c78b65 --- /dev/null +++ b/landing-zone-configurator/infra/seed-protection/README.de.md @@ -0,0 +1,5 @@ +# seed-protection + +[English](README.md) | [Deutsch](README.de.md) + +Lokale IaC-Seed-Stufe für den unabhängigen Verwaltungs-Bucket. Ablauf und Recovery stehen in [der IaC-Anleitung](../README.de.md). State ist verschlüsselt; Schlüssel niemals in Git oder den Bucket hochladen. diff --git a/landing-zone-configurator/infra/seed-protection/README.md b/landing-zone-configurator/infra/seed-protection/README.md index cc2e7f8..6fc2974 100644 --- a/landing-zone-configurator/infra/seed-protection/README.md +++ b/landing-zone-configurator/infra/seed-protection/README.md @@ -1,3 +1,5 @@ # seed-protection -Lokale IaC-Seed-Stufe für den unabhängigen Verwaltungs-Bucket. Ablauf und Recovery stehen in [der IaC-Anleitung](../README.md). State ist verschlüsselt; Schlüssel niemals in Git oder den Bucket hochladen. +[English](README.md) | [Deutsch](README.de.md) + +Local IaC seed stage for the independent management bucket. Process and recovery are described in the [IaC instructions](../README.md). State is encrypted; never upload keys to Git or the bucket. diff --git a/landing-zone-configurator/infra/seed/README.de.md b/landing-zone-configurator/infra/seed/README.de.md new file mode 100644 index 0000000..2b16066 --- /dev/null +++ b/landing-zone-configurator/infra/seed/README.de.md @@ -0,0 +1,5 @@ +# seed + +[English](README.md) | [Deutsch](README.de.md) + +Lokale IaC-Seed-Stufe für den unabhängigen Verwaltungs-Bucket. Ablauf und Recovery stehen in [der IaC-Anleitung](../README.de.md). State ist verschlüsselt; Schlüssel niemals in Git oder den Bucket hochladen. diff --git a/landing-zone-configurator/infra/seed/README.md b/landing-zone-configurator/infra/seed/README.md index a80963b..2acd9b6 100644 --- a/landing-zone-configurator/infra/seed/README.md +++ b/landing-zone-configurator/infra/seed/README.md @@ -1,3 +1,5 @@ # seed -Lokale IaC-Seed-Stufe für den unabhängigen Verwaltungs-Bucket. Ablauf und Recovery stehen in [der IaC-Anleitung](../README.md). State ist verschlüsselt; Schlüssel niemals in Git oder den Bucket hochladen. +[English](README.md) | [Deutsch](README.de.md) + +Local IaC seed stage for the independent management bucket. Process and recovery are described in the [IaC instructions](../README.md). State is encrypted; never upload keys to Git or the bucket. diff --git a/landing-zone-configurator/runner/README.de.md b/landing-zone-configurator/runner/README.de.md new file mode 100644 index 0000000..3270473 --- /dev/null +++ b/landing-zone-configurator/runner/README.de.md @@ -0,0 +1,292 @@ +# OpenTofu-Runner + +[English](README.md) | [Deutsch](README.de.md) + +Isolierte Laufzeit und Run-Protokoll; getrennt von API und Worker. Gepinnte Engine, Provider und Accelerator-Revision. Die Implementierungssprache des kleinen Supervisors bleibt offen; eigene Go-Laufzeit nur bei nachgewiesenem Vorteil. + +Keine Backend-/Model-Serving-Bindings; nur runbezogene Kunden-Credentials und State-Zugriffe. CF-Eignung, Limits und private Konnektivität vor Implementierung nachweisen. + + + +## Plattform-Plan und freigegebener Apply + +Der Worker startet nur durch seinen expliziten Prozesseinstieg. Der importierbare +Supervisor unter `app/apps/worker/src/runner.ts` startet beim Import keine Jobs. +Es gibt keinen `AllowApply`-Umgebungsschalter. Ausschließlich ein vom Broker +ausgestellter `platform-apply`-Auftrag darf einen gespeicherten Plan ausführen. +Die API muss davor eine explizite Freigabe prüfen und das Artefakt an Auftrag, +Mandant, Konfigurationshash, Accelerator-Commit, Engine und Provider-Lock binden. +Diese Bindung und die Verschlüsselung werden nicht durch den Worker ersetzt. + +`POST /api/runner/input` verwendet das runbezogene Bearer-Ticket. Fehlender Modus +bedeutet weiterhin `initial-plan-only`; dieser Modus bleibt backendlos und kann +nicht anwenden. `platform-plan` und `platform-apply` verwenden das vom Broker +gelieferte Backend. `kind:"s3"` wird durch den gemeinsamen Vertrag validiert: +`{kind:"s3",descriptor:{bucket,endpoint:"https://object.storage.eu01.onstackit.cloud",region:"eu01",key,useLockfile:true},credentials:{accessKeyId,secretAccessKey}}`. +Vor `init` ersetzt der Worker ausschließlich in der privaten Arbeitskopie die +gehashte Quelldatei durch `backend.tf.json` aus dem gemeinsamen Renderer, mit +nativem S3-Backend und `use_lockfile:true`. AWS-Credentials stehen nur in der +expliziten Child-Umgebung (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, +`AWS_REGION`, `AWS_DEFAULT_REGION`), nicht in Backend-Datei oder CLI-Flags. +Native S3-Jobs erhalten keine `TF_HTTP_*`-Variablen oder geerbten AWS-Profile. + +Das temporäre `kind:"bootstrap"` benötigt exakt die stabilen Broker-Adressen +`/api/runner/state`, `/api/runner/state/lock` +und `/api/runner/state/unlock`, Benutzer `runner` und dem eigenen Ticket als +Passwort. Fremde Origins, Query-Parameter und andere Credentials werden vor +`init` abgewiesen. Der bekannte gepinnte `backend.tf` wird ausschließlich in +einem privaten temporären Arbeitsverzeichnis durch ein HTTP-Backend ersetzt. +Ein Backend ohne `kind` wird nur nach derselben strikten Bootstrap-Prüfung akzeptiert. +HTTP-Authentifizierung wird nur per Child-ENV gesetzt, nicht per Backend-Datei +oder CLI-Konfiguration. Engine **1.12.6**, immutable Accelerator-Commit und +Provider-Lock bleiben unverändert; `init` nutzt `-lockfile=readonly`. + +`platform-plan` meldet `initializing`, `validating`, `planning` und erzeugt +`plan.bin`. Nur dessen bereinigte Zählwerte gehen in die Zusammenfassung. +Unmittelbar vor der Erfolgsmeldung lädt der Worker das binäre Artefakt über +`POST /api/runner/artifact` als `{data:base64,summary}` hoch. Die vom Broker +zurückgegebene SHA256 muss exakt stimmen. Erst danach meldet er +`{status:"succeeded",summary,artifactSha256}`. Uploadfehler berechtigen nicht +zum Apply. Artefakte sind auf 16 MiB begrenzt. + +`platform-apply` erhält zusätzlich `plan:{data:base64,sha256}`. Kanonisches +Base64, Größe und SHA256 werden vor `init` geprüft. Nach `initializing` und +`validating` folgt `applying`; OpenTofu erhält nur `saved-plan.bin`, niemals +einen neuen Plan, `-auto-approve` oder ein Apply-Varfile. Es gibt keinen +automatischen Apply-Retry, Force-Unlock, Destroy oder Cancel. Provider-Logs, +Plan-JSON und Secrets bleiben privat und werden anschließend entfernt. +Der Worker meldet beim Apply nur Erfolg oder einen festen Fehlercode, keine +Provider-Ausgabe oder Planwerte. + +Nur nach erfolgreichem Bootstrap-Apply ruft der Worker +`POST /api/runner/migration` mit `{phase:"prepare"}` auf. Die Antwort muss +`{backend:S3RunnerBackend}` enthalten; Ziel, Credentials und leeres bzw. +verifiziert übereinstimmendes Ziel werden vom Broker aus dem Management-State +bestimmt, nicht vom Browser. Der Worker validiert den vollständigen S3-Vertrag, +schreibt das native Backend und führt ausschließlich +`tofu init -migrate-state -force-copy -input=false -no-color -lockfile=readonly` +mit bisheriger HTTP- und neuer AWS-Umgebung aus. Kein Replan oder weiterer Apply. +Erst nach erfolgreichem `POST /api/runner/migration` mit `{phase:"complete"}` +folgt `{status:"succeeded"}`. Migrationsfehler melden `state_failed`. + +Der HTTP-Broker muss State dauerhaft und verschlüsselt in PostgreSQL speichern +und State/Artefakte ausschließlich im gebundenen Auftrag bereitstellen. Ein +lokaler State ist nicht das reguläre Backend. Auch bei einem fehlgeschlagenen +Apply darf der Broker bereits gespeicherten State nicht löschen. Eine vorhandene +`errored.tfstate` wird vor der terminalen Fehlermeldung auf höchstens 16 MiB, +State-Version 4, UUID-Lineage und nichtnegative ganzzahlige Serial geprüft. +`POST /api/runner/recovery` erhält `{data:,sha256:}` +und muss nach dauerhafter verschlüsselter Speicherung `{sha256:}` +bestätigen. Erst dann löscht der Worker die lokale Notfallkopie. Der Auftrag +bleibt fehlgeschlagen (`{status:"failed",errorCode:"state_failed"}`), auch wenn +Tofu trotz Recovery-Datei mit Exit-Code 0 endet. Ein Recovery-Upload hat auch +nach Job-Timeout ein eigenes, begrenztes Zustellfenster von 60 Sekunden. +Bei fehlender/falscher Bestätigung oder ungültiger Datei bleibt ausschließlich +die private `errored.tfstate` erhalten; Credentials, Logs und übrige Dateien +werden entfernt. Der Broker muss daraus `recovery_required` ableiten und das +CF-Cleanup verhindern. Ohne bestätigte Zustellung besteht kein Nachweis gegen +harten Runner-Verlust; die lokale Kopie ist keine persistente CF-Ablage. +Bei Zeitablauf beendet der Worker die Prozessgruppe zunächst mit SIGTERM, +danach gegebenenfalls SIGKILL. Remote-State und Locks werden dabei nicht gelöscht; +Recovery und eine eventuelle Lock-Freigabe erfordern eine bewusste Prüfung. + + + +## Lokale Entwicklung + +Die gewöhnlichen Worker-Unit-Tests verwenden ein ausführbares Fake-Tofu und einen +gemockten Broker. Keine echten Kunden-Credentials, kein Cloud-Apply und kein +echter Runner-Dispatch für die lokale Validierung: + +```sh +cd landing-zone-configurator/app +npm exec --yes --package=node@24.21.0 --package=npm@11.19.0 -- node node_modules/vitest/vitest.mjs run tests/platform-worker.test.ts +npm exec --yes --package=node@24.21.0 --package=npm@11.19.0 -- node --test ../infra/ci/runner-evidence.test.mjs +``` + +Vor einer echten Inbetriebnahme sind API-Freigabe, additive Stage-/Result- +Schemas, verschlüsselter State-/Artefakt-Broker einschließlich Job-Bindung, +State-Lock-Verhalten und das gepinnte staged Runner-Paket gemeinsam abzunehmen. +Ein älterer Broker ohne diese Erweiterungen ist nicht apply-fähig. + + + +## Erstbereitstellung: qualifizierte Plattformdienste + +Die gemeinsame Ausführungsprüfung erlaubt zusätzlich zum bisherigen +Governance-/Public-Projekt-Umfang in **eu01**: + +- `audit_logs`: Logs-Instanz, Lese-/Schreibtoken, Telemetry Router mit + Logs- und S3-Archivziel sowie sensibler Ablage im Secrets Manager. + Ohne `link_scopes` gilt die nachgewiesene Organisation; explizite Ziele + müssen dieselbe Organisation sein. Ordner-, Projekt- oder fremde + Organisationsziele bleiben ohne eigenen Zugehörigkeitsnachweis gesperrt. + Der native Object-Lock-Standard bleibt unverändert: `{}` aktiviert + GOVERNANCE-Retention, `s3_object_lock = false` deaktiviert sie ausdrücklich. +- `observability`: Instanz, Aufbewahrung/ACL und generierte Zugangsdaten + einschließlich sensibler Ablage im Secrets Manager. +- `connectivity`: Einzelbereich (`network_area`) oder mehrere + `network_areas`, bereichsgebundene DNS-Zonen sowie einzelne und + bereichsgebundene Firewall-Appliances einschließlich HA als + **Infrastruktur-Plan ohne Apply**. Ein VPN-Gateway ohne Verbindungen + benötigt keine PSKs und ist ebenfalls qualifiziert. +- `devops`: DevOps-Projekt und optional STACKIT Git mit Flavor und ACL. + Dies benötigt weder ein GitHub-Repository noch ein GitHub-Token. + +Firewall-API-Policy/Bootstrap, Appliance-Apply, VPN-Verbindungen mit PSKs, regionale Connectivity, +Kubernetes, Federation und zusätzliche Corporate-/Projektfunktionen bleiben +gesondert gesperrt. Die Diagnose benennt bei Connectivity jetzt die konkrete +Policy-/Bootstrap-/VPN-Abhängigkeit statt die gesamte Komponente zu sperren. +Gespeicherte Konfigurationen und Exporte werden dabei nicht umgeschrieben. + +Es gibt keine neuen Ausführungs- oder Credential-Nebenwege: dieselben +gespeicherten Eingaben und Hashes durchlaufen Vorbereitung, Organisations-/ +Identitätsprüfung, Credential-Versionierung, Mandantenprüfung, einmaliges +Runner-Ticket und explizite Plan-/Apply-Freigaben. Der vorhandene native Root +enthält diese Dienste bereits; es werden keine Ersatzressourcen generiert. + +`deploy/runner/package.sh` qualifiziert vor dem Archivieren den tatsächlich +gepackten Root samt Provider-Lock. Zwölf freigegebene native **Mock-Provider-Planläufe** +prüfen die Ressourcen einschließlich Audit-Routing/Archiv, sensibler +Vault-Ablage, Git-ACL, mehrerer Netzwerkbereiche, Legacy-Einzelbereich und +Governance-Baseline, VPN-Gateway sowie einzelne, HA- und gemischte +bereichsgebundene Firewalls. Diese Appliance-Pläne verwenden den tatsächlichen, +vorher SHA256-geprüften QCOW2-Pfad, niemals `/dev/null`. +Zwei zusätzliche, weiterhin gesperrte Firewall-/HA-Policy-Planproben belegen +die während Bootstrap fehlende Policy; eine erwartete native Validierungsverletzung belegt die +PSK-Pflicht für VPN-Verbindungen. Root-Dateien müssen in beide Richtungen mit dem gepinnten +Git-Commit übereinstimmen. Keine Kunden-Credentials, Cloud-Pläne oder Applies +werden dafür verwendet; alle Provider sind gemockt, die Umgebung ist bereinigt. +Ein weiterer **realer Vault-Provider-Test** verwendet dieselbe gepackte +Userpass-Konfiguration mit erst nach Apply bekannten Login-Ausgaben, ersetzt +aber ausschließlich die Adresse durch einen verweigernden Loopback-Server. +Vault 5.11.0 kann neue Secret-Ressourcen dabei ohne Authentifizierungsversuch +planen (null HTTP-Anfragen). Das widerlegt einen pauschalen +Vault-Bootstrap-Planblocker, qualifiziert aber weder Live-Authentifizierung, +Berechtigungen, Erreichbarkeit noch eine bestehende Vault-Secret-Abfrage. +Die Provider-Version und Prüfsummen stammen aus dem gepackten Lock; für den +isolierten Test bleibt nur dessen Vault-Eintrag erhalten. +Ein zusätzlicher **realer STACKIT-Provider-Test** mit dem gepackten +0.114.0-Lock plant das tatsächliche QCOW2 und weist einen fehlenden Image-Pfad +nativ zurück. Er verwendet ausschließlich synthetische Test-Authentifizierung, +einen verweigernden Loopback-IaaS-Endpunkt und Loopback-Proxies; alle +API-/Proxy-Aufrufe müssen null bleiben. Die Image-ID bleibt berechnet, es wird +keine vorhandene oder erfundene Cloud-Image-ID eingesetzt. Der Provider +validiert die Datei im Plan; Image-Erzeugung und Upload erfolgen erst im +weiterhin gesperrten Apply. +Das sind je gepinnter Revision 15 native Vertragsfälle und drei reale +Offline-Provider-Proben. Zusätzlich prüfen zwei artefaktgebundene Tests die +positive Paketinspektion und den tatsächlich gepackten Worker mit dem echten +Image in beiden Planmodi; nur dessen Engine/Broker sind dabei Fakes. +Diese zwei Tests laufen automatisch beim Paketieren und sind in gewöhnlichen +Unit-Läufen ohne `LZC_FIREWALL_IMAGE_PACKAGE` bewusst übersprungen. +Dies ist kein Nachweis eines live provisionierten Dienstes oder eines Plans +gegen einen echten STACKIT-Endpunkt. Ein realer Runner-Plan benötigt weiterhin +die vorhandenen, organisations-/auftragsgebundenen STACKIT-Berechtigungen +und Provider-Erreichbarkeit; diese Prüfung ersetzt keine Live-Abnahme. + + + +### Verifiziertes Appliance-Image und verbleibende Plan-/Apply-Grenzen + +- **Appliance-Image:** Beide freigegebenen nativen Revisionen verwenden in + `src/modules/connectivity/5-firewall.tf:6,47` ohne + `firewall-image.qcow2` tatsächlich `/dev/null` als Image-Quelle. + Deshalb übernimmt `package.sh` über `scripts/prepare-firewall-image.mjs` + genau das bereits in `.github/workflows/verify-deployment.yml` gepinnte + öffentliche Image: + `https://opnsense.object.storage.eu01.onstackit.cloud/opnsense-26.1-amd64-21-05-2026.qcow2`, + SHA256 `5d0fb1cb4375eb258859cafc688f1e5e6f830f54f8d86b9e8bb815611bae1068` + (993525760 Bytes, rund 948 MiB). + Der private, ignorierte Cache liegt unter `.local/firewall-images/.qcow2`. + Download, vorhandener Cache und jede immutable Root-Kopie werden + streaming-basiert geprüft; falsche Bytes oder Symlinks brechen ab. + `platform-source.json` bindet Commit und Image-SHA. Die lokale + Paketinspektion und der Worker prüfen die tatsächlichen Image-Bytes; + CF übernimmt die Capability nur aus dem inspizierten, an das Droplet + gebundenen Paket. Alte Pakete ohne qualifiziertes Image dürfen weiterhin + Governance-/Dienstpläne, aber keine Appliance-Pläne ausführen + (`runner_firewall_image_unavailable`). + Die automatische Qualifikation prüft außerdem das vollständige Paket + plus unabhängige initialisierte Image-/Root-/Provider-Arbeitskopie und + 256 MiB Reserve gegen das unveränderte 4096-MiB-Droplet-Limit. + Reflink-Einsparungen werden dabei nicht vorausgesetzt. + Gemessen inklusive Application-Root: maximal 1362381112 Bytes Paket, + 1377552902 Bytes initialisierte Arbeitskopie und 268435456 Bytes Reserve, + insgesamt 3008369470 Bytes (2,80 GiB) von 4294967296 Bytes. + Die Release-Pipeline übernimmt weiterhin den vollständigen Root per + `cp -R` nach `inspection` und vergleicht ihn vor Deployment bytegleich. + Lokale, vollständige Archive haben etwa 1,17 GB. Hosted-Archive lassen nur + die QCOW2-Datei aus und müssen kleiner als 384 MiB bleiben. Der auf den + freigegebenen Release-Commit gepinnte finale Buildpack stellt die Datei + beim Staging aus dem regionalen Object Storage SHA-geprüft wieder her. + Der temporäre Download wird ohne zweite Dateikopie in die Anwendung verschoben; + eine zusätzliche große CF-Build-Cache-Kopie entfällt. Das gespeicherte Droplet + ist der dauerhafte Image-Cache und enthält die vollständige + Datei; es gibt keinen Laufzeit-Download pro Auftrag. Die API-Inspektionskopie + wird identisch behandelt. CI vergleicht beide wiederhergestellten Roots + bytegleich mit dem qualifizierten Paket und prüft dieselbe Paketidentität. + Damit bleibt das gemessene Laufzeit-Diskbudget unverändert. Cache und + Downloadfehler brechen Staging ab, bevor die Web-Anwendung ersetzt wird. +- **HA ist nicht selbst ein Plan-Authentifizierungsblocker:** Die zwei + `terraform_data.firewall_ha_*`-Provisioner in `5-firewall.tf` verwenden den + Administrationszugang erst beim Apply; CARP-Zugänge entstehen nativ. + Appliance-/HA-Infrastrukturpläne sind mit dem qualifizierten Image möglich. + Damit ist weder ein sicherer Administrationszugang beim Apply noch eine + vollständige Firewall-Policy bereitgestellt. Die API zeigt solche Pläne + nicht als apply-fähig an und weist selbst eine explizite Apply-Freigabe mit + `configuration_apply_not_supported` zurück. Der Worker akzeptiert den + gebundenen Appliance-Vertrag ausschließlich für Plattform-Planmodi. +- **Konfigurierte Policy:** `_firewall-bootstrap.tf:30-34,41-61,88-96` + schaltet bei `firewall_bootstrap=true` die Policy im ersten Plan ab und + plant erst den Apply-Provisioner, der API-Zugänge erzeugt. Ohne Bootstrap + wird stattdessen ein vorhandenes Secrets-Manager-Secret gelesen. Deshalb + kann die unveränderte native Greenfield-Root-Konfiguration nicht sämtliche + konfigurierte Policy schon im ersten Plan abbilden. Kleinste erforderliche + Produktentscheidung ist ein sichtbar mehrstufiger, jeweils neu bestätigter + Infrastruktur-/Credential-/Policy-Workflow; alternativ wäre eine Änderung + des nativen Bootstrap-Vertrags nötig. Policy still auszulassen oder + `unset`-Zugänge als vollständig zu deklarieren ist keine Lösung. +- **VPN-Verbindungen:** `modules/connectivity/variables.tf:274-285` verlangt + pro Connection beide PSKs; `7-vpn.tf` indiziert genau diese Schlüssel. + Öffentliche Konfigurationen schließen `vpn_pre_shared_keys` aus + (`features.ts`), und `credentials/key.ts` sowie der Worker binden derzeit + einen STACKIT-Service-Account-Key, keinen VPN-Secret-Satz. Die bereinigte + Child-Umgebung übernimmt keine geerbten `TF_VAR_*`. Kleinste Voraussetzung + ist daher ein eigener autorisierter, versionierter, mandanten-/auftrags- + und Connection-Key-gebundener PSK-Vertrag. Weder erfundene PSKs noch Werte + im Entwurf, Chat oder allgemeiner Umgebung dürfen diesen ersetzen. + +Manuell gegen ein bestehendes, unverändertes **image-qualifiziertes** Runner-Paket: + +```sh +cd landing-zone-configurator/app +npm run build:packages +LZC_TEST_RUNNER_ROOT=/absolute/path/to/runner bash scripts/test-initial-plan-contract.sh +``` + + + +## Nativer lokaler Runner + +Der lokale Starter kann mit `npm run dev:execution` denselben Worker-Vertrag +gegen den festgelegten Broker `http://127.0.0.1:3000` betreiben. Nur der explizite +lokale Modus erlaubt diese Origin; CF-Worker bleiben an die feste HTTPS-Origin +gebunden. `LZC_LOCAL_RUNNER_PACKAGE=true` erzeugt über das bestehende +Paketierungsskript ein natives `runner-local`-Paket mit OpenTofu 1.12.6 und +Host-Provider-Mirror. Paketinhalt, Zod, Node-Laufzeit und Provider-Mirror werden +vor dem Dispatch fingerprint-geprüft; Änderungen invalidieren die Paketbindung. + +Der Dispatcher speichert seine Identität vor dem Start, erbt keine Cloud- oder +Backend-Credentials aus dem API-Prozess und verwirft rohe Prozessausgaben. +Credentials kommen nur über das gebundene Job-Ticket. Private Job-Verzeichnisse +liegen unter `~/.local/share/landing-zone-configurator/runner-jobs`. Recovery +bleibt dort bis zur dauerhaften Bestätigung erhalten und verhindert Cleanup. +Nach einem API-Verlust erfordern unklare Prozesse einen operativen Abgleich; +der Adapter signalisiert keine ungeprüften Prozess-IDs und wiederholt kein Apply. + +Die Kunden-State-Lifecycle bleibt unverändert: Accelerator-Bootstrap mit dem +ausgewählten Service Account, anschließend Migration zum Terraform-verwalteten +Management-S3-Bucket. Ein lokaler erfolgreicher Dispatch belegt nicht den echten +Kunden-Apply oder die Live-S3-Migration. Der native Adapter ist eine lokale +Entwicklungsfunktion, keine produktive Sandbox-Isolation. diff --git a/landing-zone-configurator/runner/README.md b/landing-zone-configurator/runner/README.md index 1393684..3113877 100644 --- a/landing-zone-configurator/runner/README.md +++ b/landing-zone-configurator/runner/README.md @@ -1,96 +1,102 @@ -# OpenTofu-Runner +# OpenTofu Runner -Isolierte Laufzeit und Run-Protokoll; getrennt von API und Worker. Gepinnte Engine, Provider und Accelerator-Revision. Die Implementierungssprache des kleinen Supervisors bleibt offen; eigene Go-Laufzeit nur bei nachgewiesenem Vorteil. +[English](README.md) | [Deutsch](README.de.md) -Keine Backend-/Model-Serving-Bindings; nur runbezogene Kunden-Credentials und State-Zugriffe. CF-Eignung, Limits und private Konnektivität vor Implementierung nachweisen. +Isolated runtime and run protocol; separate from the API and worker. Pinned engine, providers and Accelerator revision. The implementation language of the small supervisor remains open; a dedicated Go runtime only with a demonstrated benefit. -## Plattform-Plan und freigegebener Apply +No backend/Model Serving bindings; only run-specific customer credentials and state access. Demonstrate CF suitability, limits and private connectivity before implementation. -Der Worker startet nur durch seinen expliziten Prozesseinstieg. Der importierbare -Supervisor unter `app/apps/worker/src/runner.ts` startet beim Import keine Jobs. -Es gibt keinen `AllowApply`-Umgebungsschalter. Ausschließlich ein vom Broker -ausgestellter `platform-apply`-Auftrag darf einen gespeicherten Plan ausführen. -Die API muss davor eine explizite Freigabe prüfen und das Artefakt an Auftrag, -Mandant, Konfigurationshash, Accelerator-Commit, Engine und Provider-Lock binden. -Diese Bindung und die Verschlüsselung werden nicht durch den Worker ersetzt. + -`POST /api/runner/input` verwendet das runbezogene Bearer-Ticket. Fehlender Modus -bedeutet weiterhin `initial-plan-only`; dieser Modus bleibt backendlos und kann -nicht anwenden. `platform-plan` und `platform-apply` verwenden das vom Broker -gelieferte Backend. `kind:"s3"` wird durch den gemeinsamen Vertrag validiert: +## Platform Plan and approved Apply + +The worker starts only through its explicit process entrypoint. The importable +supervisor in `app/apps/worker/src/runner.ts` starts no jobs on import. +There is no `AllowApply` environment switch. Only a broker-issued +`platform-apply` job may execute a saved Plan. +The API must first verify explicit approval and bind the artifact to the job, +tenant, configuration hash, Accelerator commit, engine and provider lock. +The worker does not replace this binding or encryption. + +`POST /api/runner/input` uses the run-specific bearer ticket. An absent mode +continues to mean `initial-plan-only`; this mode remains backend-free and cannot +apply. `platform-plan` and `platform-apply` use the broker-supplied +backend. `kind:"s3"` is validated by the shared contract: `{kind:"s3",descriptor:{bucket,endpoint:"https://object.storage.eu01.onstackit.cloud",region:"eu01",key,useLockfile:true},credentials:{accessKeyId,secretAccessKey}}`. -Vor `init` ersetzt der Worker ausschließlich in der privaten Arbeitskopie die -gehashte Quelldatei durch `backend.tf.json` aus dem gemeinsamen Renderer, mit -nativem S3-Backend und `use_lockfile:true`. AWS-Credentials stehen nur in der -expliziten Child-Umgebung (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, -`AWS_REGION`, `AWS_DEFAULT_REGION`), nicht in Backend-Datei oder CLI-Flags. -Native S3-Jobs erhalten keine `TF_HTTP_*`-Variablen oder geerbten AWS-Profile. - -Das temporäre `kind:"bootstrap"` benötigt exakt die stabilen Broker-Adressen +Before `init`, the worker replaces the hashed source file only in the private +working copy with `backend.tf.json` from the shared renderer, using +the native S3 backend and `use_lockfile:true`. AWS credentials reside only in the +explicit child environment (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, +`AWS_REGION`, `AWS_DEFAULT_REGION`), not in the backend file or CLI flags. +Native S3 jobs receive no `TF_HTTP_*` variables or inherited AWS profiles. + +The temporary `kind:"bootstrap"` requires exactly the stable broker addresses `/api/runner/state`, `/api/runner/state/lock` -und `/api/runner/state/unlock`, Benutzer `runner` und dem eigenen Ticket als -Passwort. Fremde Origins, Query-Parameter und andere Credentials werden vor -`init` abgewiesen. Der bekannte gepinnte `backend.tf` wird ausschließlich in -einem privaten temporären Arbeitsverzeichnis durch ein HTTP-Backend ersetzt. -Ein Backend ohne `kind` wird nur nach derselben strikten Bootstrap-Prüfung akzeptiert. -HTTP-Authentifizierung wird nur per Child-ENV gesetzt, nicht per Backend-Datei -oder CLI-Konfiguration. Engine **1.12.6**, immutable Accelerator-Commit und -Provider-Lock bleiben unverändert; `init` nutzt `-lockfile=readonly`. - -`platform-plan` meldet `initializing`, `validating`, `planning` und erzeugt -`plan.bin`. Nur dessen bereinigte Zählwerte gehen in die Zusammenfassung. -Unmittelbar vor der Erfolgsmeldung lädt der Worker das binäre Artefakt über -`POST /api/runner/artifact` als `{data:base64,summary}` hoch. Die vom Broker -zurückgegebene SHA256 muss exakt stimmen. Erst danach meldet er -`{status:"succeeded",summary,artifactSha256}`. Uploadfehler berechtigen nicht -zum Apply. Artefakte sind auf 16 MiB begrenzt. - -`platform-apply` erhält zusätzlich `plan:{data:base64,sha256}`. Kanonisches -Base64, Größe und SHA256 werden vor `init` geprüft. Nach `initializing` und -`validating` folgt `applying`; OpenTofu erhält nur `saved-plan.bin`, niemals -einen neuen Plan, `-auto-approve` oder ein Apply-Varfile. Es gibt keinen -automatischen Apply-Retry, Force-Unlock, Destroy oder Cancel. Provider-Logs, -Plan-JSON und Secrets bleiben privat und werden anschließend entfernt. -Der Worker meldet beim Apply nur Erfolg oder einen festen Fehlercode, keine -Provider-Ausgabe oder Planwerte. - -Nur nach erfolgreichem Bootstrap-Apply ruft der Worker -`POST /api/runner/migration` mit `{phase:"prepare"}` auf. Die Antwort muss -`{backend:S3RunnerBackend}` enthalten; Ziel, Credentials und leeres bzw. -verifiziert übereinstimmendes Ziel werden vom Broker aus dem Management-State -bestimmt, nicht vom Browser. Der Worker validiert den vollständigen S3-Vertrag, -schreibt das native Backend und führt ausschließlich +and `/api/runner/state/unlock`, user `runner` and its own ticket as +password. Foreign origins, query parameters and other credentials are rejected before +`init`. The known pinned `backend.tf` is replaced with an HTTP backend +only in a private temporary working directory. +A backend without `kind` is accepted only after the same strict bootstrap check. +HTTP authentication is set only through child ENV, not through a backend file +or CLI configuration. Engine **1.12.6**, immutable Accelerator commit and +provider lock remain unchanged; `init` uses `-lockfile=readonly`. + +`platform-plan` reports `initializing`, `validating`, `planning` and creates +`plan.bin`. Only its sanitized counts enter the summary. +Immediately before reporting success, the worker uploads the binary artifact through +`POST /api/runner/artifact` as `{data:base64,summary}`. The SHA256 returned by the +broker must match exactly. Only then does it report +`{status:"succeeded",summary,artifactSha256}`. Upload errors do not authorize +Apply. Artifacts are limited to 16 MiB. + +`platform-apply` additionally receives `plan:{data:base64,sha256}`. Canonical +Base64, size and SHA256 are checked before `init`. After `initializing` and +`validating` comes `applying`; OpenTofu receives only `saved-plan.bin`, never +a new Plan, `-auto-approve` or an Apply varfile. There is no +automatic Apply retry, force-unlock, Destroy or Cancel. Provider logs, +Plan JSON and secrets remain private and are subsequently removed. +For Apply, the worker reports only success or a fixed error code, no +provider output or Plan values. + +Only after a successful bootstrap Apply does the worker call +`POST /api/runner/migration` with `{phase:"prepare"}`. The response must +contain `{backend:S3RunnerBackend}`; the broker determines the target, credentials +and an empty or verified matching target from management state, +not from the browser. The worker validates the complete S3 contract, +writes the native backend and runs only `tofu init -migrate-state -force-copy -input=false -no-color -lockfile=readonly` -mit bisheriger HTTP- und neuer AWS-Umgebung aus. Kein Replan oder weiterer Apply. -Erst nach erfolgreichem `POST /api/runner/migration` mit `{phase:"complete"}` -folgt `{status:"succeeded"}`. Migrationsfehler melden `state_failed`. - -Der HTTP-Broker muss State dauerhaft und verschlüsselt in PostgreSQL speichern -und State/Artefakte ausschließlich im gebundenen Auftrag bereitstellen. Ein -lokaler State ist nicht das reguläre Backend. Auch bei einem fehlgeschlagenen -Apply darf der Broker bereits gespeicherten State nicht löschen. Eine vorhandene -`errored.tfstate` wird vor der terminalen Fehlermeldung auf höchstens 16 MiB, -State-Version 4, UUID-Lineage und nichtnegative ganzzahlige Serial geprüft. -`POST /api/runner/recovery` erhält `{data:,sha256:}` -und muss nach dauerhafter verschlüsselter Speicherung `{sha256:}` -bestätigen. Erst dann löscht der Worker die lokale Notfallkopie. Der Auftrag -bleibt fehlgeschlagen (`{status:"failed",errorCode:"state_failed"}`), auch wenn -Tofu trotz Recovery-Datei mit Exit-Code 0 endet. Ein Recovery-Upload hat auch -nach Job-Timeout ein eigenes, begrenztes Zustellfenster von 60 Sekunden. -Bei fehlender/falscher Bestätigung oder ungültiger Datei bleibt ausschließlich -die private `errored.tfstate` erhalten; Credentials, Logs und übrige Dateien -werden entfernt. Der Broker muss daraus `recovery_required` ableiten und das -CF-Cleanup verhindern. Ohne bestätigte Zustellung besteht kein Nachweis gegen -harten Runner-Verlust; die lokale Kopie ist keine persistente CF-Ablage. -Bei Zeitablauf beendet der Worker die Prozessgruppe zunächst mit SIGTERM, -danach gegebenenfalls SIGKILL. Remote-State und Locks werden dabei nicht gelöscht; -Recovery und eine eventuelle Lock-Freigabe erfordern eine bewusste Prüfung. - -## Lokale Entwicklung - -Die gewöhnlichen Worker-Unit-Tests verwenden ein ausführbares Fake-Tofu und einen -gemockten Broker. Keine echten Kunden-Credentials, kein Cloud-Apply und kein -echter Runner-Dispatch für die lokale Validierung: +with the previous HTTP and new AWS environment. No replan or further Apply. +Only after a successful `POST /api/runner/migration` with `{phase:"complete"}` +does `{status:"succeeded"}` follow. Migration errors report `state_failed`. + +The HTTP broker must store state durably and encrypted in PostgreSQL +and provide state/artifacts only within the bound job. Local +state is not the regular backend. Even after a failed +Apply, the broker must not delete already stored state. An existing +`errored.tfstate` is checked before the terminal failure report for a maximum of 16 MiB, +state version 4, UUID lineage and a nonnegative integer serial. +`POST /api/runner/recovery` receives `{data:,sha256:}` +and must acknowledge `{sha256:}` after durable encrypted +storage. Only then does the worker delete the local emergency copy. The job +remains failed (`{status:"failed",errorCode:"state_failed"}`), even if +Tofu exits with code 0 despite the recovery file. A recovery upload has its own +bounded delivery window of 60 seconds even after job timeout. +If the acknowledgment is missing/incorrect or the file invalid, only +the private `errored.tfstate` is retained; credentials, logs and all other files +are removed. The broker must derive `recovery_required` from this and prevent +CF cleanup. Without confirmed delivery, there is no evidence of protection against +hard Runner loss; the local copy is not persistent CF storage. +On timeout, the worker first terminates the process group with SIGTERM, +then SIGKILL if necessary. Remote state and locks are not deleted; +recovery and any lock release require deliberate review. + + + +## Local development + +Ordinary worker unit tests use an executable fake Tofu and a +mock broker. No real customer credentials, cloud Apply or +real Runner dispatch for local validation: ```sh cd landing-zone-configurator/app @@ -98,156 +104,159 @@ npm exec --yes --package=node@24.21.0 --package=npm@11.19.0 -- node node_modules npm exec --yes --package=node@24.21.0 --package=npm@11.19.0 -- node --test ../infra/ci/runner-evidence.test.mjs ``` -Vor einer echten Inbetriebnahme sind API-Freigabe, additive Stage-/Result- -Schemas, verschlüsselter State-/Artefakt-Broker einschließlich Job-Bindung, -State-Lock-Verhalten und das gepinnte staged Runner-Paket gemeinsam abzunehmen. -Ein älterer Broker ohne diese Erweiterungen ist nicht apply-fähig. - -## Erstbereitstellung: qualifizierte Plattformdienste - -Die gemeinsame Ausführungsprüfung erlaubt zusätzlich zum bisherigen -Governance-/Public-Projekt-Umfang in **eu01**: - -- `audit_logs`: Logs-Instanz, Lese-/Schreibtoken, Telemetry Router mit - Logs- und S3-Archivziel sowie sensibler Ablage im Secrets Manager. - Ohne `link_scopes` gilt die nachgewiesene Organisation; explizite Ziele - müssen dieselbe Organisation sein. Ordner-, Projekt- oder fremde - Organisationsziele bleiben ohne eigenen Zugehörigkeitsnachweis gesperrt. - Der native Object-Lock-Standard bleibt unverändert: `{}` aktiviert - GOVERNANCE-Retention, `s3_object_lock = false` deaktiviert sie ausdrücklich. -- `observability`: Instanz, Aufbewahrung/ACL und generierte Zugangsdaten - einschließlich sensibler Ablage im Secrets Manager. -- `connectivity`: Einzelbereich (`network_area`) oder mehrere - `network_areas`, bereichsgebundene DNS-Zonen sowie einzelne und - bereichsgebundene Firewall-Appliances einschließlich HA als - **Infrastruktur-Plan ohne Apply**. Ein VPN-Gateway ohne Verbindungen - benötigt keine PSKs und ist ebenfalls qualifiziert. -- `devops`: DevOps-Projekt und optional STACKIT Git mit Flavor und ACL. - Dies benötigt weder ein GitHub-Repository noch ein GitHub-Token. - -Firewall-API-Policy/Bootstrap, Appliance-Apply, VPN-Verbindungen mit PSKs, regionale Connectivity, -Kubernetes, Federation und zusätzliche Corporate-/Projektfunktionen bleiben -gesondert gesperrt. Die Diagnose benennt bei Connectivity jetzt die konkrete -Policy-/Bootstrap-/VPN-Abhängigkeit statt die gesamte Komponente zu sperren. -Gespeicherte Konfigurationen und Exporte werden dabei nicht umgeschrieben. - -Es gibt keine neuen Ausführungs- oder Credential-Nebenwege: dieselben -gespeicherten Eingaben und Hashes durchlaufen Vorbereitung, Organisations-/ -Identitätsprüfung, Credential-Versionierung, Mandantenprüfung, einmaliges -Runner-Ticket und explizite Plan-/Apply-Freigaben. Der vorhandene native Root -enthält diese Dienste bereits; es werden keine Ersatzressourcen generiert. - -`deploy/runner/package.sh` qualifiziert vor dem Archivieren den tatsächlich -gepackten Root samt Provider-Lock. Zwölf freigegebene native **Mock-Provider-Planläufe** -prüfen die Ressourcen einschließlich Audit-Routing/Archiv, sensibler -Vault-Ablage, Git-ACL, mehrerer Netzwerkbereiche, Legacy-Einzelbereich und -Governance-Baseline, VPN-Gateway sowie einzelne, HA- und gemischte -bereichsgebundene Firewalls. Diese Appliance-Pläne verwenden den tatsächlichen, -vorher SHA256-geprüften QCOW2-Pfad, niemals `/dev/null`. -Zwei zusätzliche, weiterhin gesperrte Firewall-/HA-Policy-Planproben belegen -die während Bootstrap fehlende Policy; eine erwartete native Validierungsverletzung belegt die -PSK-Pflicht für VPN-Verbindungen. Root-Dateien müssen in beide Richtungen mit dem gepinnten -Git-Commit übereinstimmen. Keine Kunden-Credentials, Cloud-Pläne oder Applies -werden dafür verwendet; alle Provider sind gemockt, die Umgebung ist bereinigt. -Ein weiterer **realer Vault-Provider-Test** verwendet dieselbe gepackte -Userpass-Konfiguration mit erst nach Apply bekannten Login-Ausgaben, ersetzt -aber ausschließlich die Adresse durch einen verweigernden Loopback-Server. -Vault 5.11.0 kann neue Secret-Ressourcen dabei ohne Authentifizierungsversuch -planen (null HTTP-Anfragen). Das widerlegt einen pauschalen -Vault-Bootstrap-Planblocker, qualifiziert aber weder Live-Authentifizierung, -Berechtigungen, Erreichbarkeit noch eine bestehende Vault-Secret-Abfrage. -Die Provider-Version und Prüfsummen stammen aus dem gepackten Lock; für den -isolierten Test bleibt nur dessen Vault-Eintrag erhalten. -Ein zusätzlicher **realer STACKIT-Provider-Test** mit dem gepackten -0.114.0-Lock plant das tatsächliche QCOW2 und weist einen fehlenden Image-Pfad -nativ zurück. Er verwendet ausschließlich synthetische Test-Authentifizierung, -einen verweigernden Loopback-IaaS-Endpunkt und Loopback-Proxies; alle -API-/Proxy-Aufrufe müssen null bleiben. Die Image-ID bleibt berechnet, es wird -keine vorhandene oder erfundene Cloud-Image-ID eingesetzt. Der Provider -validiert die Datei im Plan; Image-Erzeugung und Upload erfolgen erst im -weiterhin gesperrten Apply. -Das sind je gepinnter Revision 15 native Vertragsfälle und drei reale -Offline-Provider-Proben. Zusätzlich prüfen zwei artefaktgebundene Tests die -positive Paketinspektion und den tatsächlich gepackten Worker mit dem echten -Image in beiden Planmodi; nur dessen Engine/Broker sind dabei Fakes. -Diese zwei Tests laufen automatisch beim Paketieren und sind in gewöhnlichen -Unit-Läufen ohne `LZC_FIREWALL_IMAGE_PACKAGE` bewusst übersprungen. -Dies ist kein Nachweis eines live provisionierten Dienstes oder eines Plans -gegen einen echten STACKIT-Endpunkt. Ein realer Runner-Plan benötigt weiterhin -die vorhandenen, organisations-/auftragsgebundenen STACKIT-Berechtigungen -und Provider-Erreichbarkeit; diese Prüfung ersetzt keine Live-Abnahme. - -### Verifiziertes Appliance-Image und verbleibende Plan-/Apply-Grenzen - -- **Appliance-Image:** Beide freigegebenen nativen Revisionen verwenden in - `src/modules/connectivity/5-firewall.tf:6,47` ohne - `firewall-image.qcow2` tatsächlich `/dev/null` als Image-Quelle. - Deshalb übernimmt `package.sh` über `scripts/prepare-firewall-image.mjs` - genau das bereits in `.github/workflows/verify-deployment.yml` gepinnte - öffentliche Image: +Before real commissioning, API approval, additive stage/result +schemas, encrypted state/artifact broker including job binding, +state lock behavior and the pinned staged Runner package must be accepted together. +An older broker without these extensions is not Apply-capable. + + + +## Initial provisioning: qualified platform services + +The shared execution check permits the following in **eu01**, in addition to the previous +governance/Public project scope: + +- `audit_logs`: Logs instance, read/write token, Telemetry Router with + Logs and S3 archive destinations and sensitive storage in Secrets Manager. + Without `link_scopes`, the verified organization applies; explicit targets + must be that same organization. Folder, project or other + organization targets remain blocked without their own membership evidence. + The native Object Lock default remains unchanged: `{}` enables + GOVERNANCE retention; `s3_object_lock = false` explicitly disables it. +- `observability`: instance, retention/ACL and generated credentials + including sensitive storage in Secrets Manager. +- `connectivity`: single area (`network_area`) or multiple + `network_areas`, area-bound DNS zones and single and + area-bound firewall appliances including HA as an + **infrastructure Plan without Apply**. A VPN gateway without connections + needs no PSKs and is also qualified. +- `devops`: DevOps project and optional STACKIT Git with flavor and ACL. + This requires neither a GitHub repository nor a GitHub token. + +Firewall API policy/bootstrap, appliance Apply, VPN connections with PSKs, regional connectivity, +Kubernetes, federation and additional Corporate/project features remain +separately blocked. Connectivity diagnostics now identify the specific +policy/bootstrap/VPN dependency instead of blocking the entire component. +Saved configurations and exports are not rewritten. + +There are no new execution or credential side channels: the same +saved inputs and hashes pass through preparation, organization/ +identity verification, credential versioning, tenant checks, a one-time +Runner ticket and explicit Plan/Apply approvals. The existing native root +already contains these services; no replacement resources are generated. + +Before archiving, `deploy/runner/package.sh` qualifies the actual +packaged root and provider lock. Twelve approved native **mock-provider Plan runs** +check resources including audit routing/archive, sensitive +Vault storage, Git ACL, multiple network areas, legacy single area and +governance baseline, VPN gateway and single, HA and mixed +area-bound firewalls. These appliance Plans use the actual +previously SHA256-verified QCOW2 path, never `/dev/null`. +Two additional, still blocked firewall/HA policy Plan probes demonstrate +the policy missing during bootstrap; an expected native validation violation demonstrates the +PSK requirement for VPN connections. Root files must match the pinned +Git commit in both directions. No customer credentials, cloud Plans or Applies +are used; all providers are mocked and the environment is sanitized. +A further **real Vault provider test** uses the same packaged +userpass configuration with login outputs known only after Apply, +but replaces only the address with a rejecting loopback server. +Vault 5.11.0 can plan new secret resources without attempting authentication +(zero HTTP requests). This disproves a blanket +Vault bootstrap Plan blocker, but qualifies neither live authentication, +permissions, reachability nor an existing Vault secret query. +The provider version and checksums come from the packaged lock; only its +Vault entry is retained for the isolated test. +An additional **real STACKIT provider test** using the packaged +0.114.0 lock plans the actual QCOW2 and natively rejects a missing image path. +It uses only synthetic test authentication, +a rejecting loopback IaaS endpoint and loopback proxies; all +API/proxy calls must remain at zero. The image ID remains computed; no +existing or invented cloud image ID is used. The provider +validates the file during Plan; image creation and upload occur only during +the still blocked Apply. +For each pinned revision, these are 15 native contract cases and three real +offline provider probes. In addition, two artifact-bound tests check +positive package inspection and the actual packaged worker with the real +image in both Plan modes; only its engine/broker are fakes. +These two tests run automatically during packaging and are deliberately skipped in ordinary +unit runs without `LZC_FIREWALL_IMAGE_PACKAGE`. +This is not evidence of a live provisioned service or a Plan +against a real STACKIT endpoint. A real Runner Plan still needs +the existing organization/job-bound STACKIT permissions +and provider reachability; this check does not replace live acceptance. + + + +### Verified appliance image and remaining Plan/Apply boundaries + +- **Appliance image:** Both approved native revisions actually use `/dev/null` + as the image source in `src/modules/connectivity/5-firewall.tf:6,47` + without `firewall-image.qcow2`. + Therefore, through `scripts/prepare-firewall-image.mjs`, `package.sh` includes + exactly the public image already pinned in `.github/workflows/verify-deployment.yml`: `https://opnsense.object.storage.eu01.onstackit.cloud/opnsense-26.1-amd64-21-05-2026.qcow2`, SHA256 `5d0fb1cb4375eb258859cafc688f1e5e6f830f54f8d86b9e8bb815611bae1068` - (993525760 Bytes, rund 948 MiB). - Der private, ignorierte Cache liegt unter `.local/firewall-images/.qcow2`. - Download, vorhandener Cache und jede immutable Root-Kopie werden - streaming-basiert geprüft; falsche Bytes oder Symlinks brechen ab. - `platform-source.json` bindet Commit und Image-SHA. Die lokale - Paketinspektion und der Worker prüfen die tatsächlichen Image-Bytes; - CF übernimmt die Capability nur aus dem inspizierten, an das Droplet - gebundenen Paket. Alte Pakete ohne qualifiziertes Image dürfen weiterhin - Governance-/Dienstpläne, aber keine Appliance-Pläne ausführen + (993525760 bytes, around 948 MiB). + The private, ignored cache resides under `.local/firewall-images/.qcow2`. + The download, existing cache and every immutable root copy are + verified through streaming; incorrect bytes or symlinks abort. + `platform-source.json` binds the commit and image SHA. Local + package inspection and the worker check the actual image bytes; + CF adopts the capability only from the inspected package + bound to the droplet. Old packages without a qualified image may still + execute governance/service Plans, but no appliance Plans (`runner_firewall_image_unavailable`). - Die automatische Qualifikation prüft außerdem das vollständige Paket - plus unabhängige initialisierte Image-/Root-/Provider-Arbeitskopie und - 256 MiB Reserve gegen das unveränderte 4096-MiB-Droplet-Limit. - Reflink-Einsparungen werden dabei nicht vorausgesetzt. - Gemessen inklusive Application-Root: maximal 1362381112 Bytes Paket, - 1377552902 Bytes initialisierte Arbeitskopie und 268435456 Bytes Reserve, - insgesamt 3008369470 Bytes (2,80 GiB) von 4294967296 Bytes. - Die Release-Pipeline übernimmt weiterhin den vollständigen Root per - `cp -R` nach `inspection` und vergleicht ihn vor Deployment bytegleich. - Lokale, vollständige Archive haben etwa 1,17 GB. Hosted-Archive lassen nur - die QCOW2-Datei aus und müssen kleiner als 384 MiB bleiben. Der auf den - freigegebenen Release-Commit gepinnte finale Buildpack stellt die Datei - beim Staging aus dem regionalen Object Storage SHA-geprüft wieder her. - Der temporäre Download wird ohne zweite Dateikopie in die Anwendung verschoben; - eine zusätzliche große CF-Build-Cache-Kopie entfällt. Das gespeicherte Droplet - ist der dauerhafte Image-Cache und enthält die vollständige - Datei; es gibt keinen Laufzeit-Download pro Auftrag. Die API-Inspektionskopie - wird identisch behandelt. CI vergleicht beide wiederhergestellten Roots - bytegleich mit dem qualifizierten Paket und prüft dieselbe Paketidentität. - Damit bleibt das gemessene Laufzeit-Diskbudget unverändert. Cache und - Downloadfehler brechen Staging ab, bevor die Web-Anwendung ersetzt wird. -- **HA ist nicht selbst ein Plan-Authentifizierungsblocker:** Die zwei - `terraform_data.firewall_ha_*`-Provisioner in `5-firewall.tf` verwenden den - Administrationszugang erst beim Apply; CARP-Zugänge entstehen nativ. - Appliance-/HA-Infrastrukturpläne sind mit dem qualifizierten Image möglich. - Damit ist weder ein sicherer Administrationszugang beim Apply noch eine - vollständige Firewall-Policy bereitgestellt. Die API zeigt solche Pläne - nicht als apply-fähig an und weist selbst eine explizite Apply-Freigabe mit - `configuration_apply_not_supported` zurück. Der Worker akzeptiert den - gebundenen Appliance-Vertrag ausschließlich für Plattform-Planmodi. -- **Konfigurierte Policy:** `_firewall-bootstrap.tf:30-34,41-61,88-96` - schaltet bei `firewall_bootstrap=true` die Policy im ersten Plan ab und - plant erst den Apply-Provisioner, der API-Zugänge erzeugt. Ohne Bootstrap - wird stattdessen ein vorhandenes Secrets-Manager-Secret gelesen. Deshalb - kann die unveränderte native Greenfield-Root-Konfiguration nicht sämtliche - konfigurierte Policy schon im ersten Plan abbilden. Kleinste erforderliche - Produktentscheidung ist ein sichtbar mehrstufiger, jeweils neu bestätigter - Infrastruktur-/Credential-/Policy-Workflow; alternativ wäre eine Änderung - des nativen Bootstrap-Vertrags nötig. Policy still auszulassen oder - `unset`-Zugänge als vollständig zu deklarieren ist keine Lösung. -- **VPN-Verbindungen:** `modules/connectivity/variables.tf:274-285` verlangt - pro Connection beide PSKs; `7-vpn.tf` indiziert genau diese Schlüssel. - Öffentliche Konfigurationen schließen `vpn_pre_shared_keys` aus - (`features.ts`), und `credentials/key.ts` sowie der Worker binden derzeit - einen STACKIT-Service-Account-Key, keinen VPN-Secret-Satz. Die bereinigte - Child-Umgebung übernimmt keine geerbten `TF_VAR_*`. Kleinste Voraussetzung - ist daher ein eigener autorisierter, versionierter, mandanten-/auftrags- - und Connection-Key-gebundener PSK-Vertrag. Weder erfundene PSKs noch Werte - im Entwurf, Chat oder allgemeiner Umgebung dürfen diesen ersetzen. - -Manuell gegen ein bestehendes, unverändertes **image-qualifiziertes** Runner-Paket: + Automatic qualification additionally checks the complete package + plus an independently initialized image/root/provider working copy and + 256 MiB reserve against the unchanged 4096-MiB droplet limit. + Reflink savings are not assumed. + Measured including the application root: at most 1362381112 bytes for the package, + 1377552902 bytes for the initialized working copy and 268435456 bytes reserve, + totaling 3008369470 bytes (2.80 GiB) out of 4294967296 bytes. + The release pipeline continues to copy the complete root through + `cp -R` to `inspection` and compares it byte-for-byte before deployment. + Local complete archives are about 1.17 GB. Hosted archives omit only + the QCOW2 file and must remain smaller than 384 MiB. The final buildpack, pinned to + the approved release commit, restores the file during staging + from regional Object Storage with SHA verification. + The temporary download is moved into the application without a second file copy; + an additional large CF build-cache copy is omitted. The stored droplet + is the durable image cache and contains the complete + file; there is no runtime download per job. The API inspection copy + is treated identically. CI compares both restored roots + byte-for-byte with the qualified package and checks the same package identity. + This keeps the measured runtime disk budget unchanged. Cache and + download errors abort staging before the web application is replaced. +- **HA is not itself a Plan authentication blocker:** The two + `terraform_data.firewall_ha_*` provisioners in `5-firewall.tf` use + administrative access only during Apply; CARP credentials are created natively. + Appliance/HA infrastructure Plans are possible with the qualified image. + This provides neither secure administrative access during Apply nor a + complete firewall policy. The API does not show such Plans as + Apply-capable and rejects even explicit Apply approval with + `configuration_apply_not_supported`. The worker accepts the + bound appliance contract only for platform Plan modes. +- **Configured policy:** `_firewall-bootstrap.tf:30-34,41-61,88-96` + disables policy in the first Plan when `firewall_bootstrap=true` and + initially plans only the Apply provisioner that creates API credentials. Without bootstrap, + an existing Secrets Manager secret is read instead. Therefore, + the unchanged native greenfield root configuration cannot represent all + configured policy in the first Plan. The smallest required + product decision is a visibly multistage infrastructure/credential/policy + workflow, with fresh confirmation at every stage; alternatively, + the native bootstrap contract would need to change. Silently omitting policy or + declaring `unset` credentials complete is not a solution. +- **VPN connections:** `modules/connectivity/variables.tf:274-285` requires + both PSKs per connection; `7-vpn.tf` indexes exactly these keys. + Public configurations exclude `vpn_pre_shared_keys` + (`features.ts`), and `credentials/key.ts` and the worker currently bind + a STACKIT service account key, not a VPN secret set. The sanitized + child environment inherits no `TF_VAR_*`. The smallest prerequisite + is therefore a dedicated authorized, versioned PSK contract bound to tenant/job + and connection key. Neither invented PSKs nor values + in the draft, chat or general environment may replace it. + +Manually against an existing, unchanged **image-qualified** Runner package: ```sh cd landing-zone-configurator/app @@ -255,26 +264,28 @@ npm run build:packages LZC_TEST_RUNNER_ROOT=/absolute/path/to/runner bash scripts/test-initial-plan-contract.sh ``` -## Nativer lokaler Runner - -Der lokale Starter kann mit `npm run dev:execution` denselben Worker-Vertrag -gegen den festgelegten Broker `http://127.0.0.1:3000` betreiben. Nur der explizite -lokale Modus erlaubt diese Origin; CF-Worker bleiben an die feste HTTPS-Origin -gebunden. `LZC_LOCAL_RUNNER_PACKAGE=true` erzeugt über das bestehende -Paketierungsskript ein natives `runner-local`-Paket mit OpenTofu 1.12.6 und -Host-Provider-Mirror. Paketinhalt, Zod, Node-Laufzeit und Provider-Mirror werden -vor dem Dispatch fingerprint-geprüft; Änderungen invalidieren die Paketbindung. - -Der Dispatcher speichert seine Identität vor dem Start, erbt keine Cloud- oder -Backend-Credentials aus dem API-Prozess und verwirft rohe Prozessausgaben. -Credentials kommen nur über das gebundene Job-Ticket. Private Job-Verzeichnisse -liegen unter `~/.local/share/landing-zone-configurator/runner-jobs`. Recovery -bleibt dort bis zur dauerhaften Bestätigung erhalten und verhindert Cleanup. -Nach einem API-Verlust erfordern unklare Prozesse einen operativen Abgleich; -der Adapter signalisiert keine ungeprüften Prozess-IDs und wiederholt kein Apply. - -Die Kunden-State-Lifecycle bleibt unverändert: Accelerator-Bootstrap mit dem -ausgewählten Service Account, anschließend Migration zum Terraform-verwalteten -Management-S3-Bucket. Ein lokaler erfolgreicher Dispatch belegt nicht den echten -Kunden-Apply oder die Live-S3-Migration. Der native Adapter ist eine lokale -Entwicklungsfunktion, keine produktive Sandbox-Isolation. + + +## Native local Runner + +With `npm run dev:execution`, the local launcher can run the same worker contract +against the fixed broker `http://127.0.0.1:3000`. Only explicit +local mode permits this origin; CF workers remain bound to the fixed HTTPS origin. +`LZC_LOCAL_RUNNER_PACKAGE=true` creates a native `runner-local` package through +the existing packaging script, with OpenTofu 1.12.6 and +a host provider mirror. Package contents, Zod, Node runtime and provider mirror are +fingerprint-checked before dispatch; changes invalidate the package binding. + +The dispatcher stores its identity before starting, inherits no cloud or +backend credentials from the API process and discards raw process output. +Credentials arrive only through the bound job ticket. Private job directories +reside under `~/.local/share/landing-zone-configurator/runner-jobs`. Recovery +remains there until durable acknowledgment and prevents cleanup. +After API loss, ambiguous processes require operational reconciliation; +the adapter does not signal unverified process IDs or repeat Apply. + +The customer state lifecycle remains unchanged: Accelerator bootstrap with the +selected service account, followed by migration to the Terraform-managed +management S3 bucket. A successful local dispatch does not prove a real +customer Apply or live S3 migration. The native adapter is a local +development feature, not production sandbox isolation. diff --git a/landing-zone-configurator/tools/hcl-adapter/README.de.md b/landing-zone-configurator/tools/hcl-adapter/README.de.md new file mode 100644 index 0000000..c3b8ad2 --- /dev/null +++ b/landing-zone-configurator/tools/hcl-adapter/README.de.md @@ -0,0 +1,57 @@ + + +# HCL-Importadapter + +[English](README.md) | [Deutsch](README.de.md) + +Kleiner Go-Adapter mit [HashiCorp HCL v2](https://pkg.go.dev/github.com/hashicorp/hcl/v2/hclparse). +Er liest die eingecheckten `.tfvars` aus `src/config`, wertet ausschließlich +Ausdrücke ohne Variablen-/Funktionskontext aus und erzeugt den versionierten +JSON-Katalog für die Web-App. Kein Terraform/OpenTofu-Aufruf, kein Netzwerkdienst +und keine Secret-Auflösung. Fachregeln bleiben im TypeScript-Domain-Paket. + +Aus diesem Verzeichnis: + +```sh +# Einmal vor den Roundtrip-Tests: in ../../app npm ci und npm run build:packages +go test ./... +go run . # Katalog aktualisieren +go run . -check # CI: veralteten Katalog erkennen, keine Dateien ändern +``` + +`go.mod`/`go.sum` pinnen die Abhängigkeiten. CI verwendet Go 1.27.1. +Der Katalog enthält `schemaVersion: 1` und pro Template ID, Repository-Pfad, +SHA-256 der unveränderten Quelldatei sowie alle aktiven Attributwerte. +Kommentare sind keine Konfiguration und werden nicht importiert. Nicht unterstützte +Referenzen, Funktionen, HCL-Blöcke und Syntaxfehler brechen die Generierung ab. + +Der derzeitige Adapter verarbeitet nur vertrauenswürdige Repository-Vorlagen +beim Entwickeln/Build. Er ist keine API zum Ausführen beliebiger Benutzerdateien. +Es werden keine Defaultwerte aus `variables.tf` automatisch materialisiert. +Unberührte Attribute bleiben bei der Erstellung eines Standalone-Entwurfs erhalten. + +Bei Änderungen an `src/config` den Katalog neu erzeugen und gemeinsam committen. +Validierung und Release prüfen den Katalog gegen die Quellen; ein veralteter Stand +wird nicht veröffentlicht. Die Accelerator-Dateien selbst werden nicht verändert. + + + +## Accelerator-Eingabeinventar + +Alle Root-Variablen einschließlich verschachtelter Typen, optionaler Defaults und +Validierungsblöcke lassen sich aus dem vertrauenswürdigen Accelerator extrahieren: + +```sh +go run . -variables-source ../../../src/variables.tf -output ../../docs/accelerator-inputs.json +go run . -variables-source ../../../src/variables.tf -output ../../app/packages/domain/src/accelerator-inputs.json +go run . -variables-source ../../../src/variables.tf -output ../../docs/accelerator-inputs.json -check +``` + +Sensible Defaults werden ausgelassen. Der Typ `dynamic` bleibt ausdrücklich +unaufgelöst und benötigt ein fachliches Schema aus der Modulverdrahtung. +`nestedDefaults.children[""]` bezeichnet den Elementtyp einer Map/Liste. Das Inventar +ersetzt keine fachlichen Abhängigkeiten und erzeugt kein Terraform-Variablen-UI. + +Die zweite Inventardatei ist das Build-Artefakt im Domain-Paket. CI prüft beide +Dateien gegen dieselbe Quelle. Gemeinsamer Compiler und Legacy-Migration sind in +[Domain-README](../../app/packages/domain/README.de.md) beschrieben. diff --git a/landing-zone-configurator/tools/hcl-adapter/README.md b/landing-zone-configurator/tools/hcl-adapter/README.md index b9dcafc..095c6af 100644 --- a/landing-zone-configurator/tools/hcl-adapter/README.md +++ b/landing-zone-configurator/tools/hcl-adapter/README.md @@ -1,12 +1,16 @@ -# HCL-Importadapter +# HCL import adapter -Kleiner Go-Adapter mit [HashiCorp HCL v2](https://pkg.go.dev/github.com/hashicorp/hcl/v2/hclparse). -Er liest die eingecheckten `.tfvars` aus `src/config`, wertet ausschließlich -Ausdrücke ohne Variablen-/Funktionskontext aus und erzeugt den versionierten -JSON-Katalog für die Web-App. Kein Terraform/OpenTofu-Aufruf, kein Netzwerkdienst -und keine Secret-Auflösung. Fachregeln bleiben im TypeScript-Domain-Paket. +[English](README.md) | [Deutsch](README.de.md) -Aus diesem Verzeichnis: + + +Small Go adapter using [HashiCorp HCL v2](https://pkg.go.dev/github.com/hashicorp/hcl/v2/hclparse). +It reads the checked-in `.tfvars` from `src/config`, evaluates only +expressions without a variable/function context and generates the versioned +JSON catalogue for the web app. No Terraform/OpenTofu invocation, network service +or secret resolution. Domain rules remain in the TypeScript domain package. + +From this directory: ```sh # Einmal vor den Roundtrip-Tests: in ../../app npm ci und npm run build:packages @@ -15,25 +19,27 @@ go run . # Katalog aktualisieren go run . -check # CI: veralteten Katalog erkennen, keine Dateien ändern ``` -`go.mod`/`go.sum` pinnen die Abhängigkeiten. CI verwendet Go 1.27.1. -Der Katalog enthält `schemaVersion: 1` und pro Template ID, Repository-Pfad, -SHA-256 der unveränderten Quelldatei sowie alle aktiven Attributwerte. -Kommentare sind keine Konfiguration und werden nicht importiert. Nicht unterstützte -Referenzen, Funktionen, HCL-Blöcke und Syntaxfehler brechen die Generierung ab. +`go.mod`/`go.sum` pin dependencies. CI uses Go 1.27.1. +The catalogue contains `schemaVersion: 1` and, per template, its ID, repository path, +SHA-256 of the unchanged source file and all active attribute values. +Comments are not configuration and are not imported. Unsupported +references, functions, HCL blocks and syntax errors abort generation. + +The current adapter processes only trusted repository templates +during development/build. It is not an API for executing arbitrary user files. +No default values from `variables.tf` are materialized automatically. +Untouched attributes are preserved when creating a standalone draft. -Der derzeitige Adapter verarbeitet nur vertrauenswürdige Repository-Vorlagen -beim Entwickeln/Build. Er ist keine API zum Ausführen beliebiger Benutzerdateien. -Es werden keine Defaultwerte aus `variables.tf` automatisch materialisiert. -Unberührte Attribute bleiben bei der Erstellung eines Standalone-Entwurfs erhalten. +When changing `src/config`, regenerate the catalogue and commit it together with the changes. +Validation and release check the catalogue against the sources; an outdated version +is not published. The Accelerator files themselves are not changed. -Bei Änderungen an `src/config` den Katalog neu erzeugen und gemeinsam committen. -Validierung und Release prüfen den Katalog gegen die Quellen; ein veralteter Stand -wird nicht veröffentlicht. Die Accelerator-Dateien selbst werden nicht verändert. + -## Accelerator-Eingabeinventar +## Accelerator input inventory -Alle Root-Variablen einschließlich verschachtelter Typen, optionaler Defaults und -Validierungsblöcke lassen sich aus dem vertrauenswürdigen Accelerator extrahieren: +All root variables, including nested types, optional defaults and +validation blocks, can be extracted from the trusted Accelerator: ```sh go run . -variables-source ../../../src/variables.tf -output ../../docs/accelerator-inputs.json @@ -41,11 +47,11 @@ go run . -variables-source ../../../src/variables.tf -output ../../app/packages/ go run . -variables-source ../../../src/variables.tf -output ../../docs/accelerator-inputs.json -check ``` -Sensible Defaults werden ausgelassen. Der Typ `dynamic` bleibt ausdrücklich -unaufgelöst und benötigt ein fachliches Schema aus der Modulverdrahtung. -`nestedDefaults.children[""]` bezeichnet den Elementtyp einer Map/Liste. Das Inventar -ersetzt keine fachlichen Abhängigkeiten und erzeugt kein Terraform-Variablen-UI. +Sensitive defaults are omitted. The `dynamic` type explicitly remains +unresolved and requires a domain schema from the module wiring. +`nestedDefaults.children[""]` denotes a map/list element type. The inventory +does not replace domain dependencies or generate a Terraform variable UI. -Die zweite Inventardatei ist das Build-Artefakt im Domain-Paket. CI prüft beide -Dateien gegen dieselbe Quelle. Gemeinsamer Compiler und Legacy-Migration sind in -[Domain-README](../../app/packages/domain/README.md) beschrieben. +The second inventory file is the build artifact in the domain package. CI checks both +files against the same source. The common compiler and legacy migration are described in +the [domain README](../../app/packages/domain/README.md). diff --git a/landing-zone-configurator/tools/portal-reference/README.de.md b/landing-zone-configurator/tools/portal-reference/README.de.md new file mode 100644 index 0000000..d5b6623 --- /dev/null +++ b/landing-zone-configurator/tools/portal-reference/README.de.md @@ -0,0 +1,56 @@ + + +# Öffentliche STACKIT-Portal-Designreferenz abrufen + +[English](README.md) | [Deutsch](README.de.md) + +Vom Repository-Verzeichnis aus (Python 3 und curl erforderlich): + +```sh +python3 landing-zone-configurator/tools/portal-reference/fetch.py +``` + +Das Werkzeug lädt `https://portal.stackit.cloud/`, entdeckt die aktuellen +Stylesheet- und Haupt-JavaScript-Dateinamen im HTML und lädt diese direkt per +`curl`. Dadurch bleiben wechselnde Asset-Hashes ohne manuelles Nachführen nutzbar. +Keine Anmeldung, Bearer-Tokens, Cookies oder Projekt-API-Aufrufe erforderlich. + +Der grundlegende Abruf lässt sich auch direkt ausführen: + +```sh +curl -q --fail --silent --show-error --max-time 30 \ + https://portal.stackit.cloud/ --output /tmp/stackit-portal.html +``` + +`-q` unterbindet persönliche curlrc-Vorgaben. Zertifikate werden normal geprüft; +Redirects werden nicht verfolgt. Bei Zscaler-/Zertifikatsfehlern die Verbindung +prüfen und erneut ausführen; TLS-Prüfung nicht deaktivieren. + +Ausgabe im ignorierten Verzeichnis `landing-zone-configurator/.local/portal-reference/`: + +- `portal.html`, `stylesheet-*.css`, `main-*.js`: unveränderte öffentliche Quellen. +- `sources.json`: Quellen-URLs, Abrufzeitpunkt, Dateigrößen und SHA-256. +- `design-tokens.json`: NDS-Deklarationen nach Selektor und Font-Face-Definitionen. + +Das Verzeichnis enthält jeweils den letzten Abruf. Die Token-Extraktion ist eine +Quellenanalyse, kein vollständiger CSS-Parser oder Browser. Marken, Themes und +Media-Queries müssen getrennt ausgewertet werden. Ein HTTP-Erfolg bestätigt +keine gerenderte Projektansicht. Fonts werden nicht heruntergeladen; vollständige +Portal-Bundles werden nicht in die App übernommen oder eingecheckt. + +Erfasste Werte und offene visuelle Abnahme: [Designreferenz](../../docs/design-reference.de.md). + + + +## Semantische Tokens für die App + +Nach dem Abruf erzeugt `python3 landing-zone-configurator/tools/portal-reference/export-tokens.py` +den bewusst begrenzten Token-Snapshot `app/apps/web/src/nebula-tokens.css`. +Er verwendet ausschließlich `brand--digits` / `theme--light` und erhält die +Viewport-Regeln der ausgewählten Größen. Änderungen vor Übernahme prüfen; +anschließend `npm run format` im App-Verzeichnis ausführen. + +Die Token-Datei ist keine vollständige Nebula-Bibliothek. Die offizielle Referenz +ist [Nebula](https://styleguide.stackit.schwarz/), insbesondere die +[Token-Architektur](https://styleguide.stackit.schwarz/foundations/design-tokens/about-tokens/) +und die [Formularregeln](https://styleguide.stackit.schwarz/patterns/forms/design/). diff --git a/landing-zone-configurator/tools/portal-reference/README.md b/landing-zone-configurator/tools/portal-reference/README.md index 0b001ed..a5036a5 100644 --- a/landing-zone-configurator/tools/portal-reference/README.md +++ b/landing-zone-configurator/tools/portal-reference/README.md @@ -1,50 +1,56 @@ -# Öffentliche STACKIT-Portal-Designreferenz abrufen +# Fetch the public STACKIT portal design reference -Vom Repository-Verzeichnis aus (Python 3 und curl erforderlich): +[English](README.md) | [Deutsch](README.de.md) + + + +From the repository directory (requires Python 3 and curl): ```sh python3 landing-zone-configurator/tools/portal-reference/fetch.py ``` -Das Werkzeug lädt `https://portal.stackit.cloud/`, entdeckt die aktuellen -Stylesheet- und Haupt-JavaScript-Dateinamen im HTML und lädt diese direkt per -`curl`. Dadurch bleiben wechselnde Asset-Hashes ohne manuelles Nachführen nutzbar. -Keine Anmeldung, Bearer-Tokens, Cookies oder Projekt-API-Aufrufe erforderlich. +The tool downloads `https://portal.stackit.cloud/`, discovers the current +stylesheet and main JavaScript filenames in the HTML and downloads them directly +using `curl`. This accommodates changing asset hashes without manual updates. +No login, bearer tokens, cookies or project API calls required. -Der grundlegende Abruf lässt sich auch direkt ausführen: +The basic fetch can also be run directly: ```sh curl -q --fail --silent --show-error --max-time 30 \ https://portal.stackit.cloud/ --output /tmp/stackit-portal.html ``` -`-q` unterbindet persönliche curlrc-Vorgaben. Zertifikate werden normal geprüft; -Redirects werden nicht verfolgt. Bei Zscaler-/Zertifikatsfehlern die Verbindung -prüfen und erneut ausführen; TLS-Prüfung nicht deaktivieren. +`-q` suppresses personal curlrc settings. Certificates are verified normally; +redirects are not followed. For Zscaler/certificate errors, check the connection +and run again; do not disable TLS verification. + +Output in the ignored directory `landing-zone-configurator/.local/portal-reference/`: -Ausgabe im ignorierten Verzeichnis `landing-zone-configurator/.local/portal-reference/`: +- `portal.html`, `stylesheet-*.css`, `main-*.js`: unchanged public sources. +- `sources.json`: source URLs, fetch timestamp, file sizes and SHA-256. +- `design-tokens.json`: NDS declarations by selector and font-face definitions. -- `portal.html`, `stylesheet-*.css`, `main-*.js`: unveränderte öffentliche Quellen. -- `sources.json`: Quellen-URLs, Abrufzeitpunkt, Dateigrößen und SHA-256. -- `design-tokens.json`: NDS-Deklarationen nach Selektor und Font-Face-Definitionen. +The directory contains the latest fetch. Token extraction is +source analysis, not a complete CSS parser or browser. Brands, themes and +media queries must be evaluated separately. HTTP success does not confirm +a rendered project view. Fonts are not downloaded; complete +portal bundles are not incorporated into the app or checked in. -Das Verzeichnis enthält jeweils den letzten Abruf. Die Token-Extraktion ist eine -Quellenanalyse, kein vollständiger CSS-Parser oder Browser. Marken, Themes und -Media-Queries müssen getrennt ausgewertet werden. Ein HTTP-Erfolg bestätigt -keine gerenderte Projektansicht. Fonts werden nicht heruntergeladen; vollständige -Portal-Bundles werden nicht in die App übernommen oder eingecheckt. +Recorded values and outstanding visual acceptance: [design reference](../../docs/design-reference.md). -Erfasste Werte und offene visuelle Abnahme: [Designreferenz](../../docs/design-reference.md). + -## Semantische Tokens für die App +## Semantic tokens for the app -Nach dem Abruf erzeugt `python3 landing-zone-configurator/tools/portal-reference/export-tokens.py` -den bewusst begrenzten Token-Snapshot `app/apps/web/src/nebula-tokens.css`. -Er verwendet ausschließlich `brand--digits` / `theme--light` und erhält die -Viewport-Regeln der ausgewählten Größen. Änderungen vor Übernahme prüfen; -anschließend `npm run format` im App-Verzeichnis ausführen. +After fetching, `python3 landing-zone-configurator/tools/portal-reference/export-tokens.py` +generates the deliberately limited token snapshot `app/apps/web/src/nebula-tokens.css`. +It uses only `brand--digits` / `theme--light` and preserves the +viewport rules for the selected sizes. Review changes before adopting them; +then run `npm run format` in the app directory. -Die Token-Datei ist keine vollständige Nebula-Bibliothek. Die offizielle Referenz -ist [Nebula](https://styleguide.stackit.schwarz/), insbesondere die -[Token-Architektur](https://styleguide.stackit.schwarz/foundations/design-tokens/about-tokens/) -und die [Formularregeln](https://styleguide.stackit.schwarz/patterns/forms/design/). +The token file is not a complete Nebula library. The official reference +is [Nebula](https://styleguide.stackit.schwarz/), particularly the +[token architecture](https://styleguide.stackit.schwarz/foundations/design-tokens/about-tokens/) +and [form rules](https://styleguide.stackit.schwarz/patterns/forms/design/). diff --git a/src/README.de.md b/src/README.de.md new file mode 100644 index 0000000..9135b8a --- /dev/null +++ b/src/README.de.md @@ -0,0 +1,140 @@ + +# Accelerator-Root-Modul + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Root-Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [grafana](#requirement\_grafana) | 4.45.2 | +| [helm](#requirement\_helm) | 3.3.0 | +| [kubernetes](#requirement\_kubernetes) | 3.2.1 | +| [opnsense](#requirement\_opnsense) | 0.26.0 | +| [random](#requirement\_random) | 3.9.0 | +| [stackit](#requirement\_stackit) | 0.114.0 | +| [time](#requirement\_time) | 0.14.1 | +| [vault](#requirement\_vault) | 5.11.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [helm.platform](#provider\_helm.platform) | 3.3.0 | +| [kubernetes.platform](#provider\_kubernetes.platform) | 3.2.1 | +| [terraform](#provider\_terraform) | n/a | +| [vault](#provider\_vault) | 5.11.0 | + +## Modules + +| Name | Source | Version | +| ---- | ------ | ------- | +| [connectivity](#module\_connectivity) | ./modules/connectivity | n/a | +| [connectivity\_eu01](#module\_connectivity\_eu01) | ./modules/connectivity | n/a | +| [connectivity\_eu02](#module\_connectivity\_eu02) | ./modules/connectivity | n/a | +| [devops](#module\_devops) | ./modules/devops | n/a | +| [firewall\_config](#module\_firewall\_config) | ./modules/firewall-config | n/a | +| [governance](#module\_governance) | ./modules/governance | n/a | +| [landing\_zone](#module\_landing\_zone) | ./modules/landing-zone | n/a | +| [landing\_zone\_eu01](#module\_landing\_zone\_eu01) | ./modules/landing-zone | n/a | +| [landing\_zone\_eu02](#module\_landing\_zone\_eu02) | ./modules/landing-zone | n/a | +| [management](#module\_management) | ./modules/management | n/a | +| [namespace\_service\_demo](#module\_namespace\_service\_demo) | ./modules/namespace-service-demo | n/a | +| [platform\_kubernetes](#module\_platform\_kubernetes) | ./modules/platform-kubernetes | n/a | +| [platform\_kubernetes\_eu01](#module\_platform\_kubernetes\_eu01) | ./modules/platform-kubernetes | n/a | +| [platform\_kubernetes\_eu02](#module\_platform\_kubernetes\_eu02) | ./modules/platform-kubernetes | n/a | +| [sandboxes](#module\_sandboxes) | ./modules/sandboxes | n/a | + +## Resources + +| Name | Type | +| ---- | ---- | +| [helm_release.demo_envoy_gateway](https://registry.terraform.io/providers/hashicorp/helm/3.3.0/docs/resources/release) | resource | +| [helm_release.kyverno](https://registry.terraform.io/providers/hashicorp/helm/3.3.0/docs/resources/release) | resource | +| [kubernetes_manifest.landing_zone_gateway_class](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/manifest) | resource | +| [kubernetes_manifest.landing_zone_sample_gateway](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/manifest) | resource | +| [kubernetes_manifest.landing_zone_sample_http_route](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/manifest) | resource | +| [kubernetes_manifest.landing_zone_secret_enforcement_policy](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/manifest) | resource | +| [kubernetes_namespace_v1.landing_zone](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/namespace_v1) | resource | +| [kubernetes_pod_v1.landing_zone_sample_load](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/pod_v1) | resource | +| [kubernetes_role_binding_v1.landing_zone_user](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/role_binding_v1) | resource | +| [kubernetes_role_v1.landing_zone_user](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/role_v1) | resource | +| [kubernetes_secret_v1.landing_zone_user_token](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/secret_v1) | resource | +| [kubernetes_service_account_v1.landing_zone_user](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/service_account_v1) | resource | +| [kubernetes_service_v1.landing_zone_sample_load](https://registry.terraform.io/providers/hashicorp/kubernetes/3.2.1/docs/resources/service_v1) | resource | +| [terraform_data.firewall_api_bootstrap](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource | +| [vault_kv_secret_v2.firewall_api_credentials](https://registry.terraform.io/providers/hashicorp/vault/5.11.0/docs/resources/kv_secret_v2) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [audit\_logs](#input\_audit\_logs) | Audit log routing for the management module. A Telemetry Link streams audit events into a Telemetry Router, which forwards them to a Logs instance and archives them to object storage. link\_scopes defaults to a single organization-wide link. retention\_days applies to both the Logs instance and, when s3\_object\_lock is enabled, the archive bucket's default retention. s3\_object\_lock is off by default and turns on GOVERNANCE-mode WORM protection for the archive bucket, which is not cleanly reversible. Set to null to skip audit logs deployment. |
object({
retention_days = optional(number, 180)
acl = optional(list(string), ["0.0.0.0/0"])
s3_object_lock = optional(bool, true)
link_scopes = optional(list(object({
resource_type = string # organization, folder, project
resource_id = string
})), null)
})
| `null` | no | +| [company\_code](#input\_company\_code) | Company code used in resource naming conventions. | `string` | n/a | yes | +| [company\_name](#input\_company\_name) | Name of the company. | `string` | n/a | yes | +| [connectivity](#input\_connectivity) | Connectivity configuration including DNS zones, network areas, firewalls, and VPN. Use network\_areas with descriptive keys that reflect any business, security, tenant, or regional boundary; network\_area and firewall remain supported for existing single-area configurations. Use firewalls for per-area appliance settings. |
object({
naming_pattern = optional(string, null)
dns_zones = optional(map(object({
dns_name = string
network_area_key = optional(string, "default")
region = optional(string, null)
name = optional(string, null)
contact_email = optional(string, null)
type = optional(string, "primary")
acl = optional(string, null)
description = optional(string, null)
default_ttl = optional(number, 3600)
})), {})
network_area = optional(object({
ranges = list(string)
transfer_network = string
min_prefix_length = optional(number, 24)
max_prefix_length = optional(number, 28)
default_prefix_length = optional(number, 28)
# Unset means the STACKIT resolvers of var.region, see modules/connectivity/1-network-area.tf.
default_nameservers = optional(list(string), null)
}), null)
network_areas = optional(map(object({
name = optional(string, null)
ranges = list(string)
transfer_network = string
min_prefix_length = optional(number, 24)
max_prefix_length = optional(number, 28)
default_prefix_length = optional(number, 28)
default_nameservers = optional(list(string), null)
})), null)
firewall = optional(object({
zone = string
flavor = string
name = string
volume_performance_class = optional(string, "storage_premium_perf4")
volume_size = optional(number, 16)
lan_network_range = string
wan_network_range = string
lan_ip = optional(string, null)
wan_ip = optional(string, null)

# Active/passive CARP pair. Adds a second appliance in backup_zone and a CARP
# virtual IP on the LAN that replaces the primary's LAN IP as the next hop the
# landing zone routes point at, so a node failure never touches the routes.
# See docs/architecture.md#high-availability-optional.
ha = optional(object({
backup_zone = string
backup_name = optional(string, null) # defaults to "-backup"
backup_lan_ip = optional(string, null) # defaults to the 6th address of lan_network_range
backup_wan_ip = optional(string, null) # defaults to the 6th address of wan_network_range
lan_vip = optional(string, null) # defaults to the 7th address of lan_network_range
vhid = optional(number, 1)
}), null)
}), null)
firewalls = optional(map(object({
zone = string
flavor = string
name = string
volume_performance_class = optional(string, "storage_premium_perf4")
volume_size = optional(number, 16)
lan_network_range = string
wan_network_range = string
lan_ip = optional(string, null)
wan_ip = optional(string, null)
ha = optional(object({
backup_zone = string
backup_name = optional(string, null)
backup_lan_ip = optional(string, null)
backup_wan_ip = optional(string, null)
lan_vip = optional(string, null)
vhid = optional(number, 1)
}), null)
})), null)
vpn = optional(object({
display_name = optional(string, null)
plan_id = optional(string, "p100")
routing_type = optional(string, "ROUTE_BASED")
availability_zones = object({
tunnel1 = string
tunnel2 = string
})
connections = optional(map(object({
display_name = optional(string, null)
enabled = optional(bool, true)
local_subnets = optional(list(string), null)
remote_subnets = optional(list(string), null)
static_routes = optional(list(string), null)
tunnel1 = object({
remote_address = string
peering = optional(object({
local_address = string
remote_address = string
}), null)
phase1 = optional(object({
encryption_algorithms = optional(list(string), ["aes256"])
integrity_algorithms = optional(list(string), ["sha2_384"])
dh_groups = optional(list(string), ["ecp384"])
rekey_time = optional(number, null)
}), {})
phase2 = optional(object({
encryption_algorithms = optional(list(string), ["aes256"])
integrity_algorithms = optional(list(string), ["sha2_384"])
dh_groups = optional(list(string), ["ecp384"])
rekey_time = optional(number, null)
dpd_action = optional(string, null)
start_action = optional(string, null)
}), {})
})
tunnel2 = object({
remote_address = string
peering = optional(object({
local_address = string
remote_address = string
}), null)
phase1 = optional(object({
encryption_algorithms = optional(list(string), ["aes256"])
integrity_algorithms = optional(list(string), ["sha2_384"])
dh_groups = optional(list(string), ["ecp384"])
rekey_time = optional(number, null)
}), {})
phase2 = optional(object({
encryption_algorithms = optional(list(string), ["aes256"])
integrity_algorithms = optional(list(string), ["sha2_384"])
dh_groups = optional(list(string), ["ecp384"])
rekey_time = optional(number, null)
dpd_action = optional(string, null)
start_action = optional(string, null)
}), {})
})
})), {})
}), null)
})
| `null` | no | +| [connectivity\_regions](#input\_connectivity\_regions) | Regional connectivity configuration for the statically supported eu01 and eu02 hubs. Set to null to use the single-region connectivity input. | `map(any)` | `null` | no | +| [devops](#input\_devops) | DevOps module configuration. Set to null to skip deployment. |
object({
git_flavor = optional(string, null)
allowed_network_ranges = optional(list(string), ["0.0.0.0/0"])
})
| `null` | no | +| [federated\_identity\_providers](#input\_federated\_identity\_providers) | List of federated identity providers to configure for the management service account. |
list(object({
name = string
issuer = string
assertions = list(object({
item = string
operator = string
value = string
}))
}))
| `[]` | no | +| [firewall\_admin\_password](#input\_firewall\_admin\_password) | Password of firewall\_admin\_username, used once to derive the API key. Defaults to the password baked into the STACKIT OPNsense image. Override through TF\_VAR\_firewall\_admin\_password after rotating it, or set to null and supply firewall\_api\_credentials instead. | `string` | `"STACKIT123!"` | no | +| [firewall\_admin\_username](#input\_firewall\_admin\_username) | Login used to derive the API key from the appliance. The STACKIT OPNsense image ships with root. | `string` | `"root"` | no | +| [firewall\_api\_credentials](#input\_firewall\_api\_credentials) | OPNsense API key and secret. Bootstrap them once from the appliance login with src/modules/firewall-config/scripts/bootstrap-api-key.sh, then supply through TF\_VAR\_firewall\_api\_credentials or a gitignored tfvars file. Kept out of firewall\_config so the policy stays committable. |
object({
api_key = string
api_secret = string
})
| `null` | no | +| [firewall\_api\_secret\_version](#input\_firewall\_api\_secret\_version) | Write version of the OPNsense API key in the Secrets Manager. The key is only transmitted when this number changes, so bump it by one after a re-bootstrap has produced a fresh key, otherwise the Secrets Manager keeps serving the old one. | `number` | `1` | no | +| [firewall\_bootstrap](#input\_firewall\_bootstrap) | Pass -var firewall\_bootstrap=true on the two greenfield applies that create the OPNsense API key. It suppresses the Secrets Manager read, which would otherwise fail at plan time because the secret does not exist yet. Never set it on an established deployment: without the bootstrap cache file it plans the destruction of the policy and the stored key. The steady state needs no variable at all. | `bool` | `false` | no | +| [firewall\_config](#input\_firewall\_config) | Policy pushed to one OPNsense appliance through its API. Requires connectivity.firewall to be deployed and firewall\_api\_credentials to be set. Set to null to leave the appliance untouched. |
object({
# Defaults to https://, derived from connectivity.firewall.
endpoint = optional(string, null)
insecure = optional(bool, true)


aliases = optional(map(object({
type = optional(string, "network")
enabled = optional(bool, true)
description = optional(string, null)
content = optional(list(string), [])
update_freq = optional(number, null)
stats = optional(bool, false)
})), {})

routes = optional(map(object({
enabled = optional(bool, true)
network = string
gateway = string
description = optional(string, null)
})), {})

rules = optional(map(object({
sequence = optional(number, 100)
enabled = optional(bool, true)
action = optional(string, "pass")
direction = optional(string, "in")
interfaces = optional(list(string), ["lan"])
protocol = optional(string, "any")
ip_protocol = optional(string, "inet")
quick = optional(bool, true)
source_net = optional(string, "any")
source_port = optional(string, null)
source_invert = optional(bool, false)
destination_net = optional(string, "any")
destination_port = optional(string, null)
destination_invert = optional(bool, false)
log = optional(bool, false)
description = optional(string, null)
})), {})

outbound_nat = optional(map(object({
sequence = optional(number, 200)
enabled = optional(bool, true)
interface = optional(string, "wan")
protocol = optional(string, "any")
ip_protocol = optional(string, "inet")
source_net = optional(string, "any")
destination_net = optional(string, "any")
target_ip = optional(string, "wanip")
disable_nat = optional(bool, false)
log = optional(bool, false)
description = optional(string, null)
})), {})

port_forwards = optional(map(object({
sequence = optional(number, 100)
enabled = optional(bool, true)
interfaces = optional(list(string), ["wan"])
protocol = optional(string, "TCP")
ip_protocol = optional(string, "inet")
source_net = optional(string, "any")
destination_net = optional(string, "wanip")
destination_port = string
target_ip = string
target_port = optional(string, null)
nat_reflection = optional(string, "default")
log = optional(bool, true)
description = optional(string, null)
})), {})
})
| `null` | no | +| [labels](#input\_labels) | Additional labels to apply to all resources. | `map(string)` | `{}` | no | +| [landing\_zone\_namespace\_services](#input\_landing\_zone\_namespace\_services) | Map of namespace-service configurations per landing zone key. If a key is present, namespace service is enabled for that landing zone. |
map(object({
demo_enabled = optional(bool, false)
demo_metrics_ingestion = optional(object({
enabled = optional(bool, false)
target_urls = optional(list(string), [])
scheme = optional(string, "https")
metrics_path = optional(string, "/")
scrape_interval = optional(string, "70s")
scrape_timeout = optional(string, "30s")
}), {})
namespace = optional(string, null)
dns_subdomain = optional(string, null)
secretsmanager = optional(bool, true)
sample_load = optional(object({
enabled = optional(bool, false)
image = optional(string, "busybox:1.36")
}), {})
secrets_enforcement = optional(object({
enabled = optional(bool, false)
mode = optional(string, "audit")
allow_opaque_secret_types = optional(list(string), [])
break_glass = optional(object({
enabled = optional(bool, true)
ttl_hours = optional(number, 24)
principals = optional(list(string), [])
}), {})
}), {})
kubernetes_access = optional(object({
enabled = optional(bool, true)
service_account_name = optional(string, null)
}), {})
labels = optional(map(string), {})
annotations = optional(map(string), {})
}))
| `{}` | no | +| [landing\_zones](#input\_landing\_zones) | Map of landing zones to create. Public landing zones can create a local network with network\_enabled. Corporate landing zones use network\_area\_key to select a connectivity.network\_areas entry; set region to eu01 or eu02 with connectivity\_regions. |
map(object({
project_name = string
project_code = string
owner_email = string
# Set to true for corporate landing zones (connected to network area), false for public
corporate = optional(bool, true)
network_area_key = optional(string, "default")
region = optional(string, null)
env = optional(string, "dev")
role_assignments = optional(list(object({
role = string
subject = string
})), [])
network_enabled = optional(bool, false)
network_prefix_length = optional(number, null)
secretsmanager_enabled = optional(bool, true)
custom_roles = optional(list(object({
name = string
description = string
permissions = list(string)
})), [])
observability = optional(object({
enabled = optional(bool, false)
plan_name = optional(string, "Observability-Starter-EU01")
acl = optional(list(string), [])
name = optional(string, null)
}), {})
}))
| `{}` | no | +| [observability](#input\_observability) | Observability instance configuration for the management module. Set to null to skip observability deployment. |
object({
plan_name = optional(string, "Observability-Starter-EU01")
acl = optional(list(string), [])
logs_retention_days = optional(number, 30)
traces_retention_days = optional(number, 30)
metrics_retention_days = optional(number, 90)
metrics_retention_days_5m_downsampling = optional(number, 90)
metrics_retention_days_1h_downsampling = optional(number, 90)
})
| `null` | no | +| [organization\_auditors](#input\_organization\_auditors) | List of organization auditors. | `list(string)` | `[]` | no | +| [organization\_id](#input\_organization\_id) | Container ID of the root organization. | `string` | n/a | yes | +| [organization\_owners](#input\_organization\_owners) | List of organization owners. | `list(string)` | `[]` | no | +| [owner\_email](#input\_owner\_email) | Email address of the owner. Required for STACKIT resource manager. | `string` | n/a | yes | +| [platform\_contract\_namespace](#input\_platform\_contract\_namespace) | Optional stable UUID namespace for Application handoff; defaults to the organization ID for independent CLI use. This is metadata, not an authorization boundary. | `string` | `null` | no | +| [platform\_kubernetes](#input\_platform\_kubernetes) | Map of central, region-scoped platform Kubernetes deployments. Empty map skips deployment. |
map(object({
region = string
network = optional(object({
sna_enabled = optional(bool, false)
sna_network_area_id = optional(string, null)
network_area_key = optional(string, "default")
firewall_next_hop_ip = optional(string, null)
sna_network_prefix_length = optional(number, 24)
}), {})
dns = optional(object({
enabled = optional(bool, true)
create_zones = optional(bool, true)
zones = optional(list(string), [])
gateway_api = optional(bool, true)
}), {})
observability = optional(object({
enabled = optional(bool, true)
plan_name = optional(string, "Observability-Starter-EU01")
acl = optional(list(string), [])
name = optional(string, null)
}), {})
encrypted_volumes = optional(object({
enabled = optional(bool, false)
storage_class_name = optional(string, "stackit-encrypted-premium")
kms_keyring_name = optional(string, "ske-volume-keyring")
kms_key_name = optional(string, "ske-volume-key")
kms_key_version = optional(string, "1")
}), {})
debug_bastion = optional(object({
enabled = optional(bool, false)
name = optional(string, null)
availability_zone = optional(string, null)
machine_type = optional(string, "g2i.1")
image_id = optional(string, "7b10e105-295b-4369-b6e0-567ec940a02b")
boot_volume_size = optional(number, 20)
ssh_public_key = optional(string, null)
ssh_public_key_path = optional(string, "~/.ssh/id_rsa.pub")
ssh_allowed_cidrs = optional(list(string), ["0.0.0.0/0"])
assign_public_ip = optional(bool, true)
install_kubectl = optional(bool, true)
}), {})
role_assignments = optional(list(object({
role = string
subject = string
})), [])
cluster = object({
name = string
kubernetes_version_min = optional(string, null)
node_pools = optional(list(object({
name = string
machine_type = string
minimum = number
maximum = number
availability_zones = list(string)
allow_system_components = optional(bool, false)
volume_size = optional(number, 20)
volume_type = optional(string, "storage_premium_perf1")
os_name = optional(string, "flatcar")
labels = optional(map(string), {})
})), [
{
name = "system"
machine_type = "g3i.4"
minimum = 2
maximum = 2
availability_zones = ["eu01-1"]
allow_system_components = true
volume_size = 20
volume_type = "storage_premium_perf1"
os_name = "flatcar"
labels = {
"workload-role" = "system"
}
},
{
name = "application"
machine_type = "g3i.4"
minimum = 2
maximum = 2
availability_zones = ["eu01-2"]
allow_system_components = false
volume_size = 20
volume_type = "storage_premium_perf1"
os_name = "flatcar"
labels = {
"workload-role" = "application"
}
}
])
maintenance = optional(object({
enable_kubernetes_version_updates = optional(bool, true)
enable_machine_image_version_updates = optional(bool, true)
start = optional(string, "01:00:00Z")
end = optional(string, "02:00:00Z")
}), {})
})
}))
| `{}` | no | +| [platform\_kubernetes\_kube\_config\_override](#input\_platform\_kubernetes\_kube\_config\_override) | Optional raw kubeconfig used by kubernetes/helm platform providers when no platform\_kubernetes module output is available. | `string` | `null` | no | +| [region](#input\_region) | STACKIT region for regional resources. | `string` | `"eu01"` | no | +| [rm\_folder\_parent\_id](#input\_rm\_folder\_parent\_id) | ID of the parent folder under which the resource manager folders will be created. If not provided, the resource manager folders will be created under the organization. | `string` | `null` | no | +| [rm\_folders](#input\_rm\_folders) | Map of resource manager folders to create under the root organization. Folder descriptions are unsupported; omit description or leave it empty. |
map(object({
name = string
description = optional(string, null)
owner_emails = list(string)
reader_emails = list(string)
}))
|
{
"landing_zones_corporate": {
"name": "Landing Zones - Corporate",
"owner_emails": [],
"reader_emails": []
},
"landing_zones_public": {
"name": "Landing Zones - Public",
"owner_emails": [],
"reader_emails": []
},
"platform": {
"name": "Platform",
"owner_emails": [],
"reader_emails": []
},
"sandboxes": {
"name": "Sandboxes",
"owner_emails": [],
"reader_emails": []
}
}
| no | +| [sandboxes](#input\_sandboxes) | List of sandboxes to create. |
list(object({
project_name = string
owner_emails = optional(list(string))
project_owner_email = string
}))
| `[]` | no | +| [vpn\_pre\_shared\_keys](#input\_vpn\_pre\_shared\_keys) | Pre-shared keys per connectivity.vpn.connections key, one per tunnel. Kept out of the connectivity object so the topology stays committable; supply through TF\_VAR\_vpn\_pre\_shared\_keys or a gitignored tfvars file. Minimum 20 characters. |
map(object({
tunnel1 = string
tunnel2 = string
}))
| `{}` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [audit\_logs\_datasource\_url](#output\_audit\_logs\_datasource\_url) | Datasource URL of the audit Logs instance, usable as a Grafana datasource. | +| [audit\_logs\_instance\_id](#output\_audit\_logs\_instance\_id) | The ID of the Logs instance receiving audit logs. Null when audit\_logs is not configured. | +| [audit\_telemetry\_router\_id](#output\_audit\_telemetry\_router\_id) | The ID of the Telemetry Router collecting audit logs. | +| [connectivity\_firewall\_backup\_public\_ip](#output\_connectivity\_firewall\_backup\_public\_ip) | The public IP of the legacy default area's backup firewall. Null without connectivity.firewall.ha. | +| [connectivity\_firewall\_next\_hop\_ip](#output\_connectivity\_firewall\_next\_hop\_ip) | The legacy default area's next hop for corporate landing-zone routes. | +| [connectivity\_firewall\_next\_hop\_ips\_by\_area](#output\_connectivity\_firewall\_next\_hop\_ips\_by\_area) | Map of network area keys to firewall next-hop IPs. | +| [connectivity\_firewall\_public\_ip](#output\_connectivity\_firewall\_public\_ip) | The public IP of the legacy default area's primary firewall node. | +| [connectivity\_firewall\_public\_ips\_by\_area](#output\_connectivity\_firewall\_public\_ips\_by\_area) | Map of network area keys to primary firewall public IPs. | +| [connectivity\_network\_area\_id](#output\_connectivity\_network\_area\_id) | The network area ID of the legacy default connectivity area. | +| [connectivity\_network\_area\_ids\_by\_area](#output\_connectivity\_network\_area\_ids\_by\_area) | Map of connectivity network area keys to their IDs. | +| [connectivity\_network\_area\_ids\_by\_region](#output\_connectivity\_network\_area\_ids\_by\_region) | Map of regions to network area keys and IDs for regional connectivity deployments. | +| [connectivity\_project\_id](#output\_connectivity\_project\_id) | The project ID of the legacy default connectivity area. | +| [connectivity\_project\_ids\_by\_area](#output\_connectivity\_project\_ids\_by\_area) | Map of connectivity network area keys to their project IDs. | +| [connectivity\_vpn\_connection\_ids](#output\_connectivity\_vpn\_connection\_ids) | Map of hub VPN connection keys to their connection IDs. | +| [connectivity\_vpn\_gateway\_id](#output\_connectivity\_vpn\_gateway\_id) | The ID of the legacy default area's VPN gateway. | +| [connectivity\_vpn\_gateway\_ids\_by\_area](#output\_connectivity\_vpn\_gateway\_ids\_by\_area) | Map of network area keys to VPN gateway IDs. | +| [connectivity\_vpn\_internal\_next\_hop\_ips](#output\_connectivity\_vpn\_internal\_next\_hop\_ips) | Network area side IPs of the hub VPN gateway tunnels. | +| [connectivity\_vpn\_public\_ips](#output\_connectivity\_vpn\_public\_ips) | Public IPs of the hub VPN gateway tunnels. Configure the remote peer against these. | +| [devops\_project\_id](#output\_devops\_project\_id) | The project ID of the DevOps project. | +| [firewall\_admin\_url](#output\_firewall\_admin\_url) | Where to reach the OPNsense web GUI. Only reachable from inside the network area once the policy blocks the WAN. | +| [governance\_folder\_ids](#output\_governance\_folder\_ids) | Map of governance folder names to their container IDs. | +| [landing\_zone\_namespace\_demo\_samples](#output\_landing\_zone\_namespace\_demo\_samples) | Demo sample references for namespace services. | +| [landing\_zone\_projects](#output\_landing\_zone\_projects) | Map of landing zone project IDs. | +| [management\_bucket\_name\_tfstate](#output\_management\_bucket\_name\_tfstate) | The name of the Management tfstate object storage bucket. | +| [management\_project\_id](#output\_management\_project\_id) | The project ID of the Management project. | +| [platform\_contract](#output\_platform\_contract) | Non-secret Application handoff. The organization ID is the default CLI namespace; revision changes when exported references change. | +| [platform\_kubernetes\_projects](#output\_platform\_kubernetes\_projects) | Map of platform Kubernetes projects and cluster metadata per key. | +| [sandbox\_projects](#output\_sandbox\_projects) | The created sandbox projects. | + diff --git a/src/README.md b/src/README.md index 340af17..90ac98d 100644 --- a/src/README.md +++ b/src/README.md @@ -1,3 +1,9 @@ +# Accelerator root module + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this root module. + ## Requirements diff --git a/src/application/README.de.md b/src/application/README.de.md new file mode 100644 index 0000000..98d60ad --- /dev/null +++ b/src/application/README.de.md @@ -0,0 +1,149 @@ + +# Separates Application-Landing-Zone-Root + +[English](README.md) | [Deutsch](README.de.md) + +Dieses Root plant **eine neue Anwendungsinstanz** unter Wiederverwendung von `../modules/landing-zone`. +Es erstellt keine Plattformordner, SNAs, Plattformdienste oder anderen Anwendungen. +Es funktioniert mit manuell aufgelösten CLI-Eingaben oder vom Configurator erzeugten Eingaben. +Für die direkte CLI-Nutzung sind weder Configurator-API, Datenbank, Sitzung, Jobfreigabe +noch Template-Engine erforderlich. Migrieren Sie bestehenden kombinierten State nicht durch +Verzeichniswechsel oder das Löschen seiner `landing_zones`-Einträge: Dies kann destruktive Änderungen planen. + +Der Configurator löst Templates auf und prüft seine eigenen Identitäts-/Freigaberichtlinien. +CLI-Nutzer geben die aufgelösten Werte direkt an, einschließlich Eigentümer und +Diensteinstellungen. In beiden Betriebsarten setzen STACKIT IAM und Backend-Richtlinien +Berechtigungen durch; Eingabemetadaten, Template-Versionen und Herkunftslabels sind keine IAM-Grenze. + +Das wiederverwendete Modul erstellt ein Projekt, ein Automatisierungsdienstkonto mit Schlüssel, +Object-Storage-Buckets/-Zugangsdaten sowie die ausgewählten Secrets-Manager- und +Observability-Dienste. Corporate-Instanzen referenzieren eine plattformeigene SNA und +erstellen ihr Projektnetzwerk/Routing. Public-Instanzen können optional mit +`network_enabled` ein lokales Projektnetzwerk und optional mit `network_prefix_length` +eine Präfixlänge festlegen. Dieses Netzwerk wird nicht über die SNA geroutet; bisherige +öffentliche Eingaben ohne diese Option erstellen weiterhin kein Netzwerk. Templates mit +Schema 2 legen diese Werte fest, statt Überschreibungen bei Bestellungen zu erlauben. +Das Root stellt eine nicht geheime `project_network`-Referenz bereit, keine +Dienstzugangsdaten. Ein lokales Netzwerk qualifiziert sein privates CIDR nicht als +Observability-ACL-Quelle. Dieser Umfang muss bei Template-Veröffentlichung und Plan-Prüfung +sichtbar sein. Generierte Zugangsdaten verbleiben im geschützten Application-State; +sie werden nicht über Root-Ausgaben offengelegt. + + +## Unabhängiger zweiphasiger CLI-Ablauf + + +### Phase 1: Plattform + +Verwenden Sie das normale [Accelerator-Bootstrap-Verfahren](../../docs/getting-started.de.md). +Konfigurieren Sie für eine **neue**, reine Plattforminstallation ausdrücklich +`landing_zones = {}`, `sandboxes = []` und `landing_zone_namespace_services = {}` +vor dem ersten Apply. Behalten Sie die erforderlichen Plattformdienste und +Governance-Ordner bei. Das bestehende Root bleibt mit kombinierten Installationen +kompatibel; ein separates physisches Plattform-Root und die Migration bestehender +States werden hier nicht eingeführt. + +Exportieren Sie nach Prüfung und Anwendung des Plattformplans nur die nicht geheime Übergabe: + +```sh +tofu -chdir=src output -json platform_contract > platform-contract.json +``` + +Diese enthält Referenzen auf Organisation, Ordner, Region, SNA, Next-Hop und +Nameserver, nicht den vollständigen Plattform-State oder Zugangsdaten. Ihre Revision ist +eine deterministische UUID, abgeleitet aus Namespace und exportierten Referenzen. +Geänderte Referenzen ändern die Revision; bewahren Sie das geprüfte Artefakt mit der +Anwendungskonfiguration auf. `tenant_id` ist ein logischer Namespace, standardmäßig +die Organisations-UUID. Das optionale `platform_contract_namespace` erlaubt eine andere +stabile UUID, beispielsweise den vorgesehenen Configurator-Workspace. Für die +CLI-Nutzung ist keine vom Configurator ausgestellte UUID erforderlich. +Öffentliche Ziele sind `public-eu01`/`public-eu02`; Corporate-Zielschlüssel enthalten +einen stabilen Hash des Area-Schlüssels, damit beliebige Area-Namen keine ungültigen +oder kollidierenden normalisierten Zielnamen erzeugen können. Nur vorhandene +Governance-Ordner/SNAs werden exportiert. Ein exportiertes Ziel ist eine +Ressourcenreferenz, keine Berechtigung zur Bereitstellung dort. + + +### Phase 2: Anwendung + +Beginnen Sie mit [dem aufgelösten JSON-Beispiel](examples/application.tfvars.json.example). +Alle Beispiel-IDs sind fiktiv. Ersetzen Sie `platform_contract` durch das Artefakt aus +Phase 1 und füllen Sie die Anwendungswerte manuell aus. Template-Rendering ist nicht +erforderlich. Setzen Sie `application.tenant_id` und `application.platform_revision` +exakt aus diesem Artefakt; wählen Sie einen seiner Zielschlüssel. Vergeben Sie +`instance_id` einmalig (beispielsweise `uuidgen | tr '[:upper:]' '[:lower:]'`) und +halten Sie sie stabil. `template_id`/`template_version` dokumentieren die gewählte +Ausgangsbasis; ein veröffentlichtes Configurator-Template ist nicht erforderlich. +Eigentümer, Rollen, Netzwerk- und Diensteinstellungen müssen nach den +Bereitstellungsrichtlinien Ihrer Organisation geprüft werden. + +Stellen Sie **vor** dem ersten Application-Plan einen Application-State-Bucket bereit. +Verwenden Sie [das Backend-Beispiel](examples/backend.hcl.example), ersetzen Sie +Bucket/Schlüssel und halten Sie den Schlüssel +`applications///terraform.tfstate` eindeutig und unverändert. +Verwenden Sie angemessen eingeschränkte Backend-Zugangsdaten, keine Zugangsdaten, +die einem Application Owner Zugriff auf Plattform-State geben. Übergeben Sie S3-Zugangsdaten +über `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY` und Provider-Zugangsdaten über die +Standardumgebung des STACKIT-Providers. Speichern Sie keine Geheimnisse in einem der +Artefakte. Der projekteigene tfstate-Bucket kann seinen ersten Plan nicht selbst bootstrappen. + +Führen Sie mit geprüften Dateien namens `application.tfvars.json` und `backend.hcl` +im Application-Verzeichnis vom Repository-Root aus Folgendes aus: + +```sh +tofu -chdir=src/application init -backend-config=backend.hcl +tofu -chdir=src/application validate +tofu -chdir=src/application plan -var-file=application.tfvars.json -out=application.tfplan +tofu -chdir=src/application apply application.tfplan +tofu -chdir=src/application plan -var-file=application.tfvars.json +``` + +Prüfen Sie den gespeicherten Plan, bevor Sie ihn ausdrücklich anwenden. Halten Sie +State, gespeicherte Pläne und Zugangsdaten privat. Deaktivieren Sie niemals die +Sperrung, um einen anderen aktiven Job zu umgehen. Verwenden Sie pro Instanz eine +separate initialisierte Arbeitskopie; wechseln Sie Instanzschlüssel nicht beiläufig +im selben Arbeitsverzeichnis. Upgrades erfordern einen geprüften neuen Plan, keine +automatischen Änderungen bei Veröffentlichung eines Templates oder Plattformvertrags. + + +## Herkunft + +Ressourcen mit Label-Unterstützung erhalten `landing_zone_accelerator = "true"`. +Direkte CLI-Nutzung behauptet keine Configurator-Ausführung. Der Configurator setzt +`application.configurator_execution = true`, ergänzt +`landing_zone_configurator = "true"` und behält seine bisherigen `lzc_*`-Labels bei. +Labels sind beschreibend und können von berechtigten Cloud-Nutzern eingesehen/geändert +werden; sie sind kein manipulationssicherer Ausführungsnachweis. Bestehende festgelegte +Runner-Quellen werden durch diese Quelländerungen weder umgeschrieben noch aktiviert. + +Offline-Prüfungen (ohne Kundenzugangsdaten oder -ressourcen): + +```sh +tofu -chdir=src/application init -backend=false +tofu -chdir=src/application validate +tofu -chdir=src/application test +``` + +Die Configurator-Release-CI führt diese Prüfungen auch über `npm run test:plan` in +einer isolierten vorübergehenden Kopie mit leerer Zugangsdatenumgebung und deaktiviertem Backend aus. + +Tests verwenden ausschließlich Mock-Provider und Plan-Befehle. Mock-UUIDs sind +Testdaten. Bekannte Provider-Deprecation-Warnungen stammen aus bestehenden +Observability-Ausgaben des gemeinsamen Moduls. Die Root-/Provider-Lockdatei sollte +beibehalten werden, wenn dieser Prototyp in die geprüfte Runner-Revision übernommen wird. + +Das eingecheckte manuelle Beispiel ist in den Mock-Tests enthalten. Der unabhängige +Test für den reinen Plattformexport läuft ohne den Configurator: + +```sh +LZC_TEST_TOFU_BIN="$(command -v tofu)" bash src/tests/check-cli-contract.sh +``` + +Der Helfer benötigt außerdem Node.js für strukturierte JSON-Prüfungen. Er wertet das +tatsächliche Standalone-Beispiel aus und prüft zusätzlich zu den nativen Mock-Tests +ohne Zugangsdaten das Ordnerschema des geprüften Providers. + +Noch abzunehmen: echter, separat autorisierter zweiphasiger CLI-Plan/Apply, +Backend-Sperrung/-Wiederherstellung, minimal berechtigte Zugangsdaten, ausdrückliche +Migration bestehender States und vollständiger Configurator-Dispatch. Mock-Tests +sind keine Cloud-Abnahme. diff --git a/src/application/README.md b/src/application/README.md index ae3f406..5c606f3 100644 --- a/src/application/README.md +++ b/src/application/README.md @@ -1,5 +1,7 @@ # Separate Application Landing Zone root +[English](README.md) | [Deutsch](README.de.md) + This root plans **one new application instance**, reusing `../modules/landing-zone`. It does not create platform folders, SNAs, platform services or other applications. It works with manually resolved CLI inputs or Configurator-generated inputs. diff --git a/src/modules/connectivity/README.de.md b/src/modules/connectivity/README.de.md new file mode 100644 index 0000000..ebe9bbd --- /dev/null +++ b/src/modules/connectivity/README.de.md @@ -0,0 +1,113 @@ +# connectivity + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [random](#requirement\_random) | >= 3.9.0 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | +| [time](#requirement\_time) | >= 0.14.1 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [random](#provider\_random) | >= 3.9.0 | +| [stackit](#provider\_stackit) | >= 0.114.0 | +| [terraform](#provider\_terraform) | n/a | +| [time](#provider\_time) | >= 0.14.1 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [random_password.carp](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [stackit_authorization_project_role_assignment.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_role_assignment) | resource | +| [stackit_dns_zone.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/dns_zone) | resource | +| [stackit_image.firewall](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/image) | resource | +| [stackit_network.lan](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network) | resource | +| [stackit_network.wan](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network) | resource | +| [stackit_network_area.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_area) | resource | +| [stackit_network_area_region.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_area_region) | resource | +| [stackit_network_interface.lan](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_interface) | resource | +| [stackit_network_interface.lan_backup](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_interface) | resource | +| [stackit_network_interface.wan](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_interface) | resource | +| [stackit_network_interface.wan_backup](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_interface) | resource | +| [stackit_public_ip.wan-ip](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/public_ip) | resource | +| [stackit_public_ip.wan-ip_backup](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/public_ip) | resource | +| [stackit_resourcemanager_project.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource | +| [stackit_routing_table.wan](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/routing_table) | resource | +| [stackit_routing_table_route.wan](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/routing_table_route) | resource | +| [stackit_server.firewall](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/server) | resource | +| [stackit_server.firewall_backup](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/server) | resource | +| [stackit_volume.firewall](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/volume) | resource | +| [stackit_volume.firewall_backup](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/volume) | resource | +| [stackit_vpn_connection.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/vpn_connection) | resource | +| [stackit_vpn_gateway.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/vpn_gateway) | resource | +| [terraform_data.firewall_ha_backup](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource | +| [terraform_data.firewall_ha_primary](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource | +| [time_sleep.wait_before_network_area_region_destroy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [time_sleep.wait_for_network_area](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [stackit_vpn_gateway_status.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/data-sources/vpn_gateway_status) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [dns\_zones](#input\_dns\_zones) | Map of DNS zone keys to DNS zone configuration. Name defaults to dns\_name if not set. |
map(object({
dns_name = string
network_area_key = optional(string, "default")
name = optional(string, null)
contact_email = optional(string, null)
type = optional(string, "primary")
acl = optional(string, null)
description = optional(string, null)
default_ttl = optional(number, 3600)
}))
| `{}` | no | +| [firewall](#input\_firewall) | Firewall configuration. Set to null to skip firewall deployment (network area and routing are still created). lan\_network\_range and wan\_network\_range must be CIDRs within the network area range. lan\_ip and wan\_ip are optional; when omitted, the 5th address of the respective prefix is used (STACKIT reserves the first usable address as the gateway). Set ha for an active/passive CARP pair; the LAN VIP then replaces the primary's LAN IP as the platform next hop. |
object({
zone = string
flavor = string
name = string
volume_performance_class = optional(string, "storage_premium_perf4")
volume_size = optional(number, 16)
lan_network_range = string
wan_network_range = string
lan_ip = optional(string, null)
wan_ip = optional(string, null)

# Active/passive HA. Adds a second appliance in backup_zone plus a CARP virtual IP on
# the LAN that becomes the platform next hop. CARP runs in unicast mode (OPNsense
# >= 24.7) because the STACKIT fabric does not deliver advertisements sourced from
# the shared virtual MAC, so multicast CARP splits the brain.
# Node-local settings are pushed by scripts/configure-ha.sh during apply.
ha = optional(object({
backup_zone = string
backup_name = optional(string, null) # defaults to "-backup"
backup_lan_ip = optional(string, null) # defaults to the 6th address of lan_network_range
backup_wan_ip = optional(string, null) # defaults to the 6th address of wan_network_range
lan_vip = optional(string, null) # defaults to the 7th address of lan_network_range
vhid = optional(number, 1)
}), null)
})
| `null` | no | +| [firewall\_admin\_endpoint](#input\_firewall\_admin\_endpoint) | Base URL the HA configuration logs into the primary appliance with. Defaults to the primary's public IP, which is the only address reachable from outside the network area. Set it to the LAN address when OpenTofu runs inside the area, matching firewall\_config.endpoint. The backup node is always configured over its own public IP: before HA exists it has no other reachable address. | `string` | `null` | no | +| [firewall\_admin\_password](#input\_firewall\_admin\_password) | Password of firewall\_admin\_username. Defaults to the password baked into the STACKIT OPNsense image. Only used when firewall.ha is set. | `string` | `"STACKIT123!"` | no | +| [firewall\_admin\_username](#input\_firewall\_admin\_username) | Appliance login used to push the node-local HA settings. The STACKIT OPNsense image ships with root. Only used when firewall.ha is set. | `string` | `"root"` | no | +| [firewalls](#input\_firewalls) | Map of network area keys to firewall configuration. Use this for multiple network areas; keys must match network\_areas. |
map(object({
zone = string
flavor = string
name = string
volume_performance_class = optional(string, "storage_premium_perf4")
volume_size = optional(number, 16)
lan_network_range = string
wan_network_range = string
lan_ip = optional(string, null)
wan_ip = optional(string, null)
ha = optional(object({
backup_zone = string
backup_name = optional(string, null)
backup_lan_ip = optional(string, null)
backup_wan_ip = optional(string, null)
lan_vip = optional(string, null)
vhid = optional(number, 1)
}), null)
}))
| `null` | no | +| [labels](#input\_labels) | Additional labels to apply to all resources. | `map(string)` | `{}` | no | +| [naming\_pattern](#input\_naming\_pattern) | Naming prefix for all resources in this module, e.g. "myco-pltfm-hub-prod". | `string` | n/a | yes | +| [network\_areas](#input\_network\_areas) | Map of network area keys to configuration. Keys are stable references for DNS zones, landing zones, and outputs. |
map(object({
name = optional(string, null)
ranges = list(string)
transfer_network = string
max_prefix_length = optional(number, 28)
min_prefix_length = optional(number, 24)
default_prefix_length = optional(number, 28)
default_nameservers = optional(list(string), null)
}))
| `{}` | no | +| [organization\_id](#input\_organization\_id) | Organization ID, required for network area and route configuration. | `string` | n/a | yes | +| [owner\_email](#input\_owner\_email) | Email address of the owner for the project. Required for STACKIT resource manager. | `string` | n/a | yes | +| [parent\_container\_id](#input\_parent\_container\_id) | Parent container ID (folder or organization) where the project will be created. | `string` | n/a | yes | +| [project\_name](#input\_project\_name) | Name of the STACKIT project to create. Falls back to naming\_pattern if not set. | `string` | `null` | no | +| [region](#input\_region) | STACKIT region the network area region is created in. Also selects the default resolvers when network\_area.default\_nameservers is unset. | `string` | `"eu01"` | no | +| [role\_assignments](#input\_role\_assignments) | List of role assignments for the project. Subject can be a user email or service account email. |
list(object({
role = string
subject = string
}))
| `[]` | no | +| [vpn](#input\_vpn) | IPsec VPN gateway for the hub, attached to the network area through the connectivity project. Set to null to skip. The gateway is HA: it terminates two tunnels in separate availability zones, each with its own public IP. Connections are created in a second apply once the remote peer addresses are known. Supports POLICY\_BASED and ROUTE\_BASED routing. |
object({
display_name = optional(string, null)
plan_id = optional(string, "p100")
routing_type = optional(string, "ROUTE_BASED")
availability_zones = object({
tunnel1 = string
tunnel2 = string
})
connections = optional(map(object({
display_name = optional(string, null)
enabled = optional(bool, true)
local_subnets = optional(list(string), null)
remote_subnets = optional(list(string), null)
static_routes = optional(list(string), null)
tunnel1 = object({
remote_address = string
peering = optional(object({
local_address = string
remote_address = string
}), null)
phase1 = optional(object({
encryption_algorithms = optional(list(string), ["aes256"])
integrity_algorithms = optional(list(string), ["sha2_384"])
dh_groups = optional(list(string), ["ecp384"])
rekey_time = optional(number, null)
}), {})
phase2 = optional(object({
encryption_algorithms = optional(list(string), ["aes256"])
integrity_algorithms = optional(list(string), ["sha2_384"])
dh_groups = optional(list(string), ["ecp384"])
rekey_time = optional(number, null)
dpd_action = optional(string, null)
start_action = optional(string, null)
}), {})
})
tunnel2 = object({
remote_address = string
peering = optional(object({
local_address = string
remote_address = string
}), null)
phase1 = optional(object({
encryption_algorithms = optional(list(string), ["aes256"])
integrity_algorithms = optional(list(string), ["sha2_384"])
dh_groups = optional(list(string), ["ecp384"])
rekey_time = optional(number, null)
}), {})
phase2 = optional(object({
encryption_algorithms = optional(list(string), ["aes256"])
integrity_algorithms = optional(list(string), ["sha2_384"])
dh_groups = optional(list(string), ["ecp384"])
rekey_time = optional(number, null)
dpd_action = optional(string, null)
start_action = optional(string, null)
}), {})
})
})), {})
})
| `null` | no | +| [vpn\_pre\_shared\_keys](#input\_vpn\_pre\_shared\_keys) | Pre-shared keys per VPN connection key, one per tunnel. Kept separate from var.vpn so the connection topology stays committable; supply through TF\_VAR\_vpn\_pre\_shared\_keys or a gitignored tfvars file. Minimum 20 characters. |
map(object({
tunnel1 = string
tunnel2 = string
}))
| `{}` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [dns\_zone\_dns\_names](#output\_dns\_zone\_dns\_names) | Map of DNS zone keys to their DNS names | +| [dns\_zone\_ids](#output\_dns\_zone\_ids) | Map of DNS zone keys to their zone IDs | +| [firewall\_backup\_public\_ip](#output\_firewall\_backup\_public\_ip) | Map of network area keys to backup firewall WAN public IPs. Empty without HA. | +| [firewall\_cluster\_lan\_ips](#output\_firewall\_cluster\_lan\_ips) | Map of network area keys to LAN addresses of firewall HA pairs. Empty without HA. | +| [firewall\_next\_hop\_ip](#output\_firewall\_next\_hop\_ip) | Map of network area keys to the default-route next hop. The CARP LAN VIP under HA, otherwise the firewall LAN IP. | +| [firewall\_public\_ip](#output\_firewall\_public\_ip) | Map of network area keys to primary firewall WAN public IPs. | +| [network\_area\_id](#output\_network\_area\_id) | The ID of the created network area. | +| [network\_area\_nameservers](#output\_network\_area\_nameservers) | Resolvers configured as the network area default, either from network\_area.default\_nameservers or the STACKIT resolvers of the region. | +| [project\_container\_id](#output\_project\_container\_id) | The container ID of the created STACKIT project. | +| [project\_id](#output\_project\_id) | The project ID of the created STACKIT project. | +| [project\_name](#output\_project\_name) | The name of the created STACKIT project. | +| [vpn\_connection\_ids](#output\_vpn\_connection\_ids) | Map of network-area/connection keys to their VPN connection IDs. | +| [vpn\_gateway\_id](#output\_vpn\_gateway\_id) | Map of network area keys to VPN gateway IDs. | +| [vpn\_internal\_next\_hop\_ips](#output\_vpn\_internal\_next\_hop\_ips) | Map of VPN tunnel names to their network area side IP. Ping targets to verify a tunnel carries traffic into the SNA. | +| [vpn\_public\_ips](#output\_vpn\_public\_ips) | Map of VPN tunnel names to their public IP. These are the addresses the remote peer has to be configured against. | + + + +## Mehrere Network Areas + +Übergeben Sie `network_areas` als Map mit aussagekräftigen Schlüsseln wie `finance`, `research` oder `tenant_a`. Für jeden Schlüssel werden ein separates Connectivity-Projekt, eine Network Area, eine Routingtabelle und ein optionales VPN-Gateway erstellt. Referenzieren Sie einen Schlüssel über `dns_zones..network_area_key`; Nutzer dieses Moduls erhalten Maps mit denselben Schlüsseln. + +Verwenden Sie `firewalls`, um eine Appliance mit unabhängigen LAN-/WAN-CIDRs pro Network Area zu konfigurieren. Die bisherige Eingabe `firewall` bleibt für eine einzelne Area verfügbar und wird jeder konfigurierten Area zugeordnet. Die Eingabe `connectivity.network_area` des Root-Moduls bleibt für bisherige Konfigurationen mit einer einzelnen Area verfügbar und wird dem Schlüssel `default` zugeordnet. diff --git a/src/modules/connectivity/README.md b/src/modules/connectivity/README.md index 5d2a786..2c5a33b 100644 --- a/src/modules/connectivity/README.md +++ b/src/modules/connectivity/README.md @@ -1,3 +1,9 @@ +# connectivity + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this module. + ## Requirements diff --git a/src/modules/debug-bastion/README.de.md b/src/modules/debug-bastion/README.de.md new file mode 100644 index 0000000..af71da2 --- /dev/null +++ b/src/modules/debug-bastion/README.de.md @@ -0,0 +1,68 @@ +# debug-bastion + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [stackit](#provider\_stackit) | >= 0.114.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [stackit_key_pair.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/key_pair) | resource | +| [stackit_network_interface.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network_interface) | resource | +| [stackit_public_ip.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/public_ip) | resource | +| [stackit_security_group.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/security_group) | resource | +| [stackit_security_group_rule.ssh](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/security_group_rule) | resource | +| [stackit_server.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/server) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [assign\_public\_ip](#input\_assign\_public\_ip) | Whether to assign a public IP to bastion network interface. | `bool` | n/a | yes | +| [availability\_zone](#input\_availability\_zone) | Availability zone for the bastion server. | `string` | `null` | no | +| [boot\_volume\_size](#input\_boot\_volume\_size) | Boot volume size in GB. | `number` | n/a | yes | +| [enabled](#input\_enabled) | Whether debug bastion resources should be created. | `bool` | n/a | yes | +| [image\_id](#input\_image\_id) | Image ID for the bastion boot volume. | `string` | n/a | yes | +| [install\_kubectl](#input\_install\_kubectl) | Whether to install kubectl via cloud-init. | `bool` | n/a | yes | +| [machine\_type](#input\_machine\_type) | Machine type for the bastion server. | `string` | n/a | yes | +| [name](#input\_name) | Bastion server name. | `string` | n/a | yes | +| [network\_id](#input\_network\_id) | SNA network ID for the bastion network interface. | `string` | n/a | yes | +| [project\_id](#input\_project\_id) | STACKIT project ID where bastion resources are created. | `string` | n/a | yes | +| [short\_prefix](#input\_short\_prefix) | Short naming prefix for key/security-group resources. | `string` | n/a | yes | +| [sna\_enabled](#input\_sna\_enabled) | Whether SNA networking is enabled for the cluster. | `bool` | n/a | yes | +| [ssh\_allowed\_cidrs](#input\_ssh\_allowed\_cidrs) | CIDRs allowed for SSH ingress. | `list(string)` | n/a | yes | +| [ssh\_public\_key](#input\_ssh\_public\_key) | Optional inline SSH public key. | `string` | `null` | no | +| [ssh\_public\_key\_path](#input\_ssh\_public\_key\_path) | Path to SSH public key file when inline key is not provided. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [enabled](#output\_enabled) | Whether bastion resources are enabled. | +| [network\_interface\_id](#output\_network\_interface\_id) | Bastion network interface ID when enabled. | +| [public\_ip](#output\_public\_ip) | Bastion public IP when enabled and assign\_public\_ip=true. | +| [server\_id](#output\_server\_id) | Bastion server ID when enabled. | +| [ssh\_command](#output\_ssh\_command) | Ready-to-use SSH command when public IP is assigned. | +| [ssh\_user](#output\_ssh\_user) | Default SSH user for bastion access. | + diff --git a/src/modules/debug-bastion/README.md b/src/modules/debug-bastion/README.md index cdc1408..b9f6baa 100644 --- a/src/modules/debug-bastion/README.md +++ b/src/modules/debug-bastion/README.md @@ -1,3 +1,9 @@ +# debug-bastion + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this module. + ## Requirements diff --git a/src/modules/devops/README.de.md b/src/modules/devops/README.de.md new file mode 100644 index 0000000..87760c1 --- /dev/null +++ b/src/modules/devops/README.de.md @@ -0,0 +1,57 @@ +# devops + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [stackit](#provider\_stackit) | >= 0.114.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [stackit_authorization_project_role_assignment.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_role_assignment) | resource | +| [stackit_git.git](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/git) | resource | +| [stackit_resourcemanager_project.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [allowed\_network\_ranges](#input\_allowed\_network\_ranges) | List of allowed network ranges for Git instance ACL. | `list(string)` |
[
"0.0.0.0/0"
]
| no | +| [company\_name](#input\_company\_name) | Name of the company folder to create. | `string` | n/a | yes | +| [git\_flavor](#input\_git\_flavor) | The flavor of the Git instance. | `string` | `null` | no | +| [labels](#input\_labels) | Additional labels to apply to all folders. | `map(string)` | `{}` | no | +| [naming\_pattern](#input\_naming\_pattern) | Naming prefix for all resources in this module, e.g. "myco-pltfm-hub-prod". | `string` | n/a | yes | +| [network\_area\_id](#input\_network\_area\_id) | Network Area ID to deploy resources into. Required if network is enabled. | `string` | `null` | no | +| [owner\_email](#input\_owner\_email) | Email address of the owner for the folders. Required for STACKIT resource manager. | `string` | n/a | yes | +| [parent\_container\_id](#input\_parent\_container\_id) | Parent container ID (folder or organization) where the project will be created. | `string` | n/a | yes | +| [project\_name](#input\_project\_name) | Name of the STACKIT project to create. | `string` | `null` | no | +| [role\_assignments](#input\_role\_assignments) | List of role assignments for the project. Subject can be a user email or service account email. |
list(object({
role = string
subject = string
}))
| `[]` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [project\_container\_id](#output\_project\_container\_id) | The container ID of the created STACKIT project. | +| [project\_id](#output\_project\_id) | The project ID of the created STACKIT project. | +| [project\_name](#output\_project\_name) | The name of the created STACKIT project. | + diff --git a/src/modules/devops/README.md b/src/modules/devops/README.md index be23d6d..81dfb06 100644 --- a/src/modules/devops/README.md +++ b/src/modules/devops/README.md @@ -1,3 +1,9 @@ +# devops + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this module. + ## Requirements diff --git a/src/modules/firewall-config/README.de.md b/src/modules/firewall-config/README.de.md new file mode 100644 index 0000000..6642fcc --- /dev/null +++ b/src/modules/firewall-config/README.de.md @@ -0,0 +1,250 @@ +# firewall-config + +[English](README.md) | [Deutsch](README.de.md) + +Überträgt Firewallregeln, NAT und internetseitige Härtung über die API an eine +OPNsense-Appliance mithilfe des Providers +[`browningluke/opnsense`](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs). + +Die Appliance selbst wird vom Modul `connectivity` bereitgestellt (`connectivity.firewall`); +dieses Modul konfiguriert sie nur. Binden Sie es über die Root-Variable `firewall_config` +ein, statt es direkt aufzurufen – siehe `src/config/hub-and-spoke-firewall.tfvars`. + + +## Verwaltete Bestandteile + +- **Aliase** — benannte Netzwerk-, Host-, Port- oder FQDN-Gruppen, die Regeln und NAT-Einträge referenzieren. +- **Statische Routen** — teilen der Appliance mit, welche Präfixe hinter welchem Gateway liegen. +- **Filterregeln** — pass, block oder reject, pro Schnittstelle oder als Floating-Regel. +- **Outbound NAT** — ausgehender Verkehr der Landing Zones hinter der öffentlichen Adresse der Firewall. +- **Portweiterleitungen** — eingehende Freigaben aus dem Internet mit Schutzprüfung (siehe unten). + +Das Modul enthält keine eigene Richtlinie. Jede Regel kommt vom Aufrufer, sodass +die wirksame Konfiguration immer an einer Stelle lesbar ist, statt auf tfvars und +Modulinterna verteilt zu sein. + + +## Regelreihenfolge + +Alles hier Geschriebene landet im *Automation*-Regelsatz von OPNsense, der vor den +unter **Firewall → Rules** konfigurierten Regeln ausgewertet wird. Die vollständige Reihenfolge: + +1. Systemregeln (Anti-Lockout, DHCP, Loopback) +2. Automatisierte **und** manuelle Floating-Regeln — Priorität `200000` +3. Automatisierte **und** manuelle Schnittstellen*gruppen*regeln — `300000` +4. **Automatisierte** Regeln einzelner Schnittstellen — `400000` +5. **Manuelle** Regeln einzelner Schnittstellen + +Zwei Folgen für diese Topologie: + +- Die `Default allow LAN to any rule` des Images ist eine manuelle Schnittstellenregel + und steht daher in Schritt 5. Eine hier auf `lan` geschriebene `block`-Regel wird + zuerst erreicht und gewinnt. Dadurch ist eine Default-Deny-Richtlinie auf der + LAN-Seite möglich, ohne das Image anzupassen. +- Innerhalb eines Schritts gewinnt die niedrigste `sequence`. Regeln haben standardmäßig + `quick = true`, sodass der erste Treffer entscheidet. Lassen Sie Lücken zwischen Sequenznummern. + +`interfaces = []` erzeugt eine Floating-Regel (Schritt 2), die einzige Möglichkeit, +einer bereits im Image enthaltenen Floating-Regel zuvorzukommen. + + +## Routen + +Beide Appliance-Schnittstellen sind DHCP-Clients in einem `/28`; OPNsense kennt +anfangs daher nur diese beiden Präfixe und eine Standardroute über WAN. Die Landing +Zones liegen weiter innerhalb der Network Area und sind über das LAN-Gateway +erreichbar, was ausdrücklich angegeben werden muss: + +```hcl +routes = { + network-area-via-lan = { + network = "10.0.0.0/16" + gateway = "LAN_DHCP" + } +} +``` + +Ohne diese Route verlässt Verkehr zu Spokes die Appliance über WAN und tritt von +außen wieder in die Network Area ein. Er erreicht die Spokes weiterhin, da die +WAN-Routingtabelle Systemrouten enthält. Allerdings wird dadurch auch +Landing-Zone-zu-Landing-Zone-Verkehr über die WAN-Schnittstelle geführt, wo die +Egress-NAT-Regel die Quelladresse umschreibt. Der empfangende Spoke sieht dann die +Firewall statt des sendenden Spokes; quellbasierte Regeln verlieren ihre Aussagekraft. + +`gateway` muss ein bereits auf der Appliance vorhandenes Gateway benennen. Das +STACKIT-Image enthält `LAN_DHCP` und `WAN_DHCP`, wobei `WAN_DHCP` als Standard markiert ist. + + +## Domainbasierte Regeln + +Ein Alias mit `type = "host"` akzeptiert FQDNs, die die Appliance zeitgesteuert erneut +auflöst. Eine darauf verweisende Regel folgt daher Adressänderungen. +`type = "urltable"` lädt stattdessen eine Präfixliste von einer URL und benötigt +`update_freq` in Tagen. + +Dies bleibt Paketfilterung anhand aufgelöster Adressen, keine namensbasierte Filterung. +Ein Client, der denselben Namen zu einer der Appliance noch unbekannten Adresse +auflöst, wird blockiert. Alles andere, das eine bereits aufgelöste Adresse teilt, +wird durchgelassen. Für eine harte Garantie verwenden Sie einen Mirror mit stabiler +Adresse oder schalten Sie einen Proxy in den Pfad. + + +## Web-GUI gegenüber dem Internet schließen + +Das STACKIT-Image enthält eine **Floating**-Regel namens `Initial webUI Access Rule`, +die TCP/443 von jeder Quelle zur Firewall selbst zulässt. Nach einer einfachen +Bereitstellung antwortet die Web-GUI auf der öffentlichen IP. + +Zum Überschreiben sind zwei Regeln erforderlich, beide ebenfalls als Floating-Regeln: +OPNsense wertet Floating-Regeln (Prioritätsgruppe 200000) vor schnittstellengebundenen +Regeln (400000) aus. Eine WAN-gebundene Regel kann deshalb niemals zuerst greifen. +`src/config/hub-and-spoke-firewall.tfvars` enthält das ausgearbeitete Beispiel: + +| Sequenz | Regel | Wirkung | +| --- | --- | --- | +| 10 | pass TCP → `(self):443` von einem Management-Alias | erhält den Administrationszugriff | +| 20 | block TCP → `(self):443` von any, floating | schließt die GUI für alle anderen | + +An einer echten Appliance überprüft: Eine erlaubte Quelle erhielt `HTTP 200`, +während eine nicht gelistete Internetquelle verworfen wurde. + +> [!WARNING] +> Der Management-Alias muss das System, das OpenTofu ausführt, enthalten, bevor die +> Blockregel angewendet wird. Andernfalls trennt das Apply, das die GUI schließt, +> zugleich die für den nächsten Lauf erforderliche Verbindung; die Wiederherstellung +> erfolgt dann über die serielle Konsole. + +> [!NOTE] +> Eine Regel „RFC1918 auf WAN blockieren“ ist ein üblicher Härtungsreflex, passt +> jedoch nicht ungeprüft zu dieser Topologie: Die WAN-Schnittstelle der Appliance +> liegt auf einem Network-Area-Präfix (`wan_network_range`), nicht an einer +> Internetgrenze. Eine solche Regel kann legitimen internen Verkehr verwerfen. +> Testen Sie sie vor der Übernahme. + +## NAT + +OPNsense unterteilt NAT in drei Bereiche. Das Modul deckt die ersten beiden ab: + +| OPNsense-GUI | NAT-Richtung | Modulvariable | +| --- | --- | --- | +| Firewall → NAT → Outbound | Quell-NAT | `outbound_nat` | +| Firewall → NAT → Port Forward | Ziel-NAT, also eingehend | `port_forwards` | +| Firewall → NAT → One-to-One | bidirektional 1:1 | nicht verfügbar | + +Ohne mindestens einen `outbound_nat`-Eintrag haben die Landing Zones keine +Egress-Identität, da ihre Standardroute an dieser Appliance endet. Übersetzen Sie +auf `wanip`: Die öffentliche STACKIT-IP ist an die WAN-Schnittstellenadresse +gebunden. Jede andere Quelladresse wird daher an der Netzwerkgrenze nicht übersetzt +und erreicht niemals das Internet. + +Das Image belässt **Firewall → NAT → Outbound** auf `automatic`; die API kann +diesen Modus nicht ändern. Das muss sie auch nicht: Hier erzeugte Regeln sind +Automatisierungsregeln, die unabhängig vom Modus angewendet werden und vor allen +Einträgen unter `Firewall → NAT` greifen. Die automatisch von der Appliance +erzeugten Regeln decken nur ihre eigenen direkt verbundenen `/28`s ab und +kollidieren daher niemals mit Landing-Zone-Verkehr. + +`disable_nat = true` markiert Verkehr als unübersetzt *und beendet dafür die +Outbound-NAT-Verarbeitung*. Ein No-NAT-Eintrag funktioniert daher nur, wenn seine +`sequence` niedriger ist als die des zu übersteuernden Eintrags. + +> [!IMPORTANT] +> Eine Portweiterleitung schreibt nur die Zieladresse um. Die GUI bietet an, +> gleichzeitig die passende Filterregel zu erstellen; der Provider hat diese +> Option nicht. Jede Weiterleitung benötigt daher eine eigene Pass-Regel in +> `rules`, die den übersetzten Verkehr auf der WAN-Schnittstelle erlaubt. +> Ohne sie wird das Paket übersetzt und anschließend verworfen. + +Jeder Eintrag in `port_forwards` öffnet einen Pfad aus dem Internet. Daher weist +die Root-Variable eine aktivierte Weiterleitung zurück, deren `source_net` +weiterhin `any` ist. Grenzen Sie es ein oder deaktivieren Sie den Eintrag. + +NAT-Beschreibungen akzeptieren nur alphanumerische Zeichen, Leerzeichen und Punkte. +Map-Schlüssel in Kebab-Case werden automatisch bereinigt, wenn keine ausdrückliche +`description` angegeben ist. + + +## Erreichbarkeit + +Die API läuft auf der Web-GUI der Appliance an der LAN-Adresse innerhalb der +Network Area. Das System, das OpenTofu ausführt, muss sie von dort erreichen können – +eine Bastion im Hub, eine Landing Zone oder das Site-to-Site-VPN. Ein Runner im +öffentlichen Internet funktioniert nur, solange die GUI noch öffentlich erreichbar +ist; genau das entfernt die Blockregel. + + +## Provider-Auswahl + +Der generische Provider +[`Mastercard/restapi`](https://registry.terraform.io/providers/Mastercard/restapi/latest/docs) +kann diese API ebenfalls ansteuern. OPNsense beantwortet Lesezugriffe jedoch in +einer erweiterten Form (jedes Auswahlfeld wird zu einem Optionsobjekt mit +`selected`-Flags), die nie den geschriebenen Daten entspricht. Unterdrückt man die +daraus entstehende permanente Differenz mit `ignore_all_server_changes`, werden +auch Konfigurationsänderungen unterdrückt. Objekte werden dadurch faktisch nur +einmal beschreibbar: Das Ergänzen eines CIDRs zu einem Alias meldet `No changes`, +während die Appliance den alten Inhalt behält. + +`browningluke/opnsense` bildet die beiden Formen intern aufeinander ab, sodass +In-place-Updates und Drift-Erkennung funktionieren. Er wird von der Community +gepflegt, und sein Autor rät vom Produktionseinsatz ab. Wird ein nicht abgedeckter +Endpunkt benötigt, bleibt der generische Provider für dieses konkrete Objekt ein +brauchbarer Ausweg. + +Der folgende generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [opnsense](#requirement\_opnsense) | >= 0.26.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [opnsense](#provider\_opnsense) | >= 0.26.0 | +| [terraform](#provider\_terraform) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [opnsense_firewall_alias.this](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs/resources/firewall_alias) | resource | +| [opnsense_firewall_category.this](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs/resources/firewall_category) | resource | +| [opnsense_firewall_filter.this](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs/resources/firewall_filter) | resource | +| [opnsense_firewall_nat.this](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs/resources/firewall_nat) | resource | +| [opnsense_firewall_nat_port_forward.this](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs/resources/firewall_nat_port_forward) | resource | +| [opnsense_route.this](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs/resources/route) | resource | +| [terraform_data.ha_sync](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [admin\_password](#input\_admin\_password) | Password of admin\_username, used by the HA sync trigger. Defaults to the password baked into the STACKIT OPNsense image. Only used when ha\_sync is set. | `string` | `"STACKIT123!"` | no | +| [admin\_username](#input\_admin\_username) | Appliance login used by the HA sync trigger. Only used when ha\_sync is set. | `string` | `"root"` | no | +| [aliases](#input\_aliases) | Firewall aliases keyed by alias name. Reference an alias from a rule, route or NAT entry by using its key wherever a network is expected. type = "host" also accepts FQDNs, which the appliance re-resolves periodically. |
map(object({
type = optional(string, "network")
enabled = optional(bool, true)
description = optional(string, null)
content = optional(list(string), [])
update_freq = optional(number, null)
stats = optional(bool, false)
}))
| `{}` | no | +| [category\_name](#input\_category\_name) | OPNsense category every object created by this module is tagged with, so managed objects are recognisable in the GUI. | `string` | `"landing-zone"` | no | +| [endpoint](#input\_endpoint) | Base URL of the OPNsense API on the primary node, e.g. https://10.0.2.4. Only used by the HA sync trigger; the provider itself is configured in the root module. | `string` | `null` | no | +| [ha\_sync](#input\_ha\_sync) | Push this policy to the HA peer after every change (POST /api/core/hasync\_status/restart\_all on the primary). Required for the active/passive CARP pair: OPNsense's own config sync never fires on API writes, so without it the backup runs an empty ruleset. Enabled automatically when connectivity.firewall.ha is set. | `bool` | `false` | no | +| [outbound\_nat](#input\_outbound\_nat) | Additional outbound NAT rules keyed by name. target\_ip accepts an address, an alias, or ip such as wanip. |
map(object({
sequence = optional(number, 200)
enabled = optional(bool, true)
interface = optional(string, "wan")
protocol = optional(string, "any")
ip_protocol = optional(string, "inet")
source_net = optional(string, "any")
destination_net = optional(string, "any")
target_ip = optional(string, "wanip")
disable_nat = optional(bool, false)
log = optional(bool, false)
description = optional(string, null)
}))
| `{}` | no | +| [port\_forwards](#input\_port\_forwards) | Inbound port forwards from the internet keyed by name. Every entry punches a hole through the WAN, so keep the list short and set source\_net where possible. |
map(object({
sequence = optional(number, 100)
enabled = optional(bool, true)
interfaces = optional(list(string), ["wan"])
protocol = optional(string, "TCP")
ip_protocol = optional(string, "inet")
source_net = optional(string, "any")
destination_net = optional(string, "wanip")
destination_port = string
target_ip = string
target_port = optional(string, null)
nat_reflection = optional(string, "default")
log = optional(bool, true)
description = optional(string, null)
}))
| `{}` | no | +| [routes](#input\_routes) | Static routes keyed by name. gateway must name a gateway that exists on the appliance; the STACKIT image ships LAN\_DHCP and WAN\_DHCP. |
map(object({
enabled = optional(bool, true)
network = string
gateway = string
description = optional(string, null)
}))
| `{}` | no | +| [rules](#input\_rules) | Firewall filter rules keyed by name. An empty interfaces list creates a floating rule, which OPNsense evaluates before interface-bound rules. |
map(object({
sequence = optional(number, 100)
enabled = optional(bool, true)
action = optional(string, "pass")
direction = optional(string, "in")
interfaces = optional(list(string), ["lan"])
protocol = optional(string, "any")
ip_protocol = optional(string, "inet")
quick = optional(bool, true)
source_net = optional(string, "any")
source_port = optional(string, null)
source_invert = optional(bool, false)
destination_net = optional(string, "any")
destination_port = optional(string, null)
destination_invert = optional(bool, false)
log = optional(bool, false)
description = optional(string, null)
}))
| `{}` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [category](#output\_category) | Name and UUID of the category every object created by this module is tagged with. Filtering on the name in the OPNsense GUI shows exactly what OpenTofu manages and nothing else. | +| [managed\_objects](#output\_managed\_objects) | Names of the objects this module holds on the appliance, by kind. Read from the resources rather than the inputs, so it reflects what was actually pushed. | +| [rule\_evaluation\_order](#output\_rule\_evaluation\_order) | Filter rules in the order the appliance evaluates them. Every rule defaults to quick, so the first match decides and this is the list to read when a rule does not behave as expected. Derived from the inputs, so it is reviewable in a plan before anything is pushed. | + diff --git a/src/modules/firewall-config/README.md b/src/modules/firewall-config/README.md index f8f9286..1c0bb37 100644 --- a/src/modules/firewall-config/README.md +++ b/src/modules/firewall-config/README.md @@ -1,5 +1,7 @@ # firewall-config +[English](README.md) | [Deutsch](README.de.md) + Pushes firewall rules, NAT and internet-facing hardening to an OPNsense appliance through its API, using the [`browningluke/opnsense`](https://registry.terraform.io/providers/browningluke/opnsense/latest/docs) provider. diff --git a/src/modules/governance/README.de.md b/src/modules/governance/README.de.md new file mode 100644 index 0000000..dad61ed --- /dev/null +++ b/src/modules/governance/README.de.md @@ -0,0 +1,59 @@ +# governance + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | +| [time](#requirement\_time) | >= 0.14.1 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [stackit](#provider\_stackit) | 0.106.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [stackit_authorization_folder_role_assignment.owners](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_folder_role_assignment) | resource | +| [stackit_authorization_folder_role_assignment.readers](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_folder_role_assignment) | resource | +| [stackit_authorization_organization_role_assignment.auditor](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_organization_role_assignment) | resource | +| [stackit_authorization_organization_role_assignment.owner](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_organization_role_assignment) | resource | +| [stackit_authorization_project_custom_role.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_custom_role) | resource | +| [stackit_resourcemanager_folder.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_folder) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [custom\_roles](#input\_custom\_roles) | List of custom roles to create at the organization level. |
list(object({
name = string
description = string
permissions = list(string)
}))
| `[]` | no | +| [labels](#input\_labels) | Additional labels to apply to all folders. | `map(string)` | `{}` | no | +| [organization\_auditors](#input\_organization\_auditors) | List of organization role assignments for organization auditors. | `list(string)` | `[]` | no | +| [organization\_id](#input\_organization\_id) | Container ID of the root folder or organization under which the company folder will be created. | `string` | n/a | yes | +| [organization\_owners](#input\_organization\_owners) | List of organization role assignments for organization owners. | `list(string)` | `[]` | no | +| [owner\_email](#input\_owner\_email) | Email address of the owner for the folders. Required for STACKIT resource manager. | `string` | n/a | yes | +| [rm\_folder\_parent\_id](#input\_rm\_folder\_parent\_id) | ID of the parent folder under which the resource manager folders will be created. If not provided, the resource manager folders will be created under the organization. | `string` | `null` | no | +| [rm\_folders](#input\_rm\_folders) | Map of folder keys to folder configuration. Each folder has a display name and optional lists of owner and reader subjects. Descriptions are unsupported; omit description or leave it empty. |
map(object({
name = string
description = optional(string, null)
owner_emails = optional(list(string), [])
reader_emails = optional(list(string), [])
}))
|
{
"landing_zones_corporate": {
"name": "Landing Zones - Corporate",
"owner_emails": [],
"reader_emails": []
},
"landing_zones_public": {
"name": "Landing Zones - Public",
"owner_emails": [],
"reader_emails": []
},
"platform": {
"name": "Platform",
"owner_emails": [],
"reader_emails": []
},
"sandbox": {
"name": "Sandboxes",
"owner_emails": [],
"reader_emails": []
}
}
| no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [custom\_role\_ids](#output\_custom\_role\_ids) | Map of custom role names to their role IDs | +| [folder\_container\_ids](#output\_folder\_container\_ids) | Map of all folder keys to their container IDs for easy reference | +| [organization\_role\_assignments](#output\_organization\_role\_assignments) | Map of organization-level role assignment subjects grouped by role | + diff --git a/src/modules/governance/README.md b/src/modules/governance/README.md index 197dc54..dc7a7cf 100644 --- a/src/modules/governance/README.md +++ b/src/modules/governance/README.md @@ -1,3 +1,9 @@ +# governance + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this module. + ## Requirements diff --git a/src/modules/landing-zone/README.de.md b/src/modules/landing-zone/README.de.md new file mode 100644 index 0000000..bbf2462 --- /dev/null +++ b/src/modules/landing-zone/README.de.md @@ -0,0 +1,96 @@ +# landing-zone + +[English](README.md) | [Deutsch](README.de.md) + +Öffentliche Projekte können mit `network_enabled = true` ein lokales Projektnetzwerk aktivieren. +Corporate-Projekte behalten ihr geroutetes Netzwerk und ihre SNA-Integration. Wird die +Option weggelassen, bleiben bestehende öffentliche Projekte ohne Netzwerk unverändert. +Das optionale `network_prefix_length` gilt für beide Arten von Projektnetzwerken. + +Der folgende generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | +| [time](#requirement\_time) | >= 0.14.1 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [stackit](#provider\_stackit) | >= 0.114.0 | +| [time](#provider\_time) | >= 0.14.1 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [stackit_authorization_project_custom_role.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_custom_role) | resource | +| [stackit_authorization_project_role_assignment.sa_owner](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_role_assignment) | resource | +| [stackit_authorization_project_role_assignment.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_role_assignment) | resource | +| [stackit_dns_zone.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/dns_zone) | resource | +| [stackit_network.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network) | resource | +| [stackit_objectstorage_bucket.default](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_bucket) | resource | +| [stackit_objectstorage_bucket.tfstate](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_bucket) | resource | +| [stackit_objectstorage_credential.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_credential) | resource | +| [stackit_objectstorage_credentials_group.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_credentials_group) | resource | +| [stackit_observability_instance.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/observability_instance) | resource | +| [stackit_resourcemanager_project.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource | +| [stackit_routing_table.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/routing_table) | resource | +| [stackit_routing_table_route.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/routing_table_route) | resource | +| [stackit_secretsmanager_instance.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/secretsmanager_instance) | resource | +| [stackit_service_account.automation](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/service_account) | resource | +| [stackit_service_account_key.automation](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/service_account_key) | resource | +| [time_rotating.key_rotate](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/rotating) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [corporate](#input\_corporate) | Whether this landing zone uses corporate networking (network area + routing). Set to false for public internet. | `bool` | `false` | no | +| [custom\_roles](#input\_custom\_roles) | List of custom roles to create for the project. |
list(object({
name = string
description = string
permissions = list(string)
}))
| n/a | yes | +| [dns\_zone\_name](#input\_dns\_zone\_name) | Full DNS zone domain name for this landing zone. Set to null to skip DNS zone creation. | `string` | `null` | no | +| [firewall\_next\_hop\_ip](#input\_firewall\_next\_hop\_ip) | IP address of the firewall next hop. | `string` | `null` | no | +| [ipv4\_nameservers](#input\_ipv4\_nameservers) | List of IPv4 nameservers for the network. Null takes the network area defaults on creation and leaves an existing network untouched. | `list(string)` | `null` | no | +| [labels](#input\_labels) | Additional labels to apply to all resources. | `map(string)` | `{}` | no | +| [naming\_pattern](#input\_naming\_pattern) | Naming prefix for all resources in this module, e.g. "myco-pltfm-hub-prod". | `string` | n/a | yes | +| [network\_area\_id](#input\_network\_area\_id) | Network Area ID to deploy resources into. Required if corporate is true. | `string` | `null` | no | +| [network\_enabled](#input\_network\_enabled) | Create a local project network without SNA when corporate is false. Corporate networks are always created. | `bool` | `false` | no | +| [network\_prefix\_length](#input\_network\_prefix\_length) | CIDR block prefix length for the project's network range. | `number` | `null` | no | +| [observability](#input\_observability) | Optional observability instance configuration in the landing zone project. |
object({
enabled = optional(bool, false)
plan_name = optional(string, "Observability-Starter-EU01")
acl = optional(list(string), [])
name = optional(string, null)
})
| `{}` | no | +| [organization\_id](#input\_organization\_id) | Container ID of the root organization. | `string` | n/a | yes | +| [owner\_email](#input\_owner\_email) | Email address of the project owner. Required for project creation. | `string` | n/a | yes | +| [parent\_container\_id](#input\_parent\_container\_id) | Parent container ID (folder or organization) where the project will be created. | `string` | n/a | yes | +| [project\_name](#input\_project\_name) | Name of the STACKIT project to create. | `string` | `null` | no | +| [role\_assignments](#input\_role\_assignments) | List of role assignments for the project. Subject can be a user email or service account email. |
list(object({
role = string
subject = string
}))
| `[]` | no | +| [secretsmanager\_acls](#input\_secretsmanager\_acls) | List of ACL rules for the Secrets Manager instance. Set to empty list for no ACLs or null to skip Secrets Manager creation. | `list(string)` | `[]` | no | +| [secretsmanager\_enabled](#input\_secretsmanager\_enabled) | Whether to create a Secrets Manager instance in the landing zone project. | `bool` | `true` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [connected\_network\_area\_id](#output\_connected\_network\_area\_id) | The ID of the connected network area. | +| [dns\_zone\_dns\_name](#output\_dns\_zone\_dns\_name) | The DNS name of the landing zone's child DNS zone. | +| [dns\_zone\_id](#output\_dns\_zone\_id) | The ID of the landing zone's child DNS zone. | +| [landing\_zone\_type](#output\_landing\_zone\_type) | The type of the landing zone, either 'corporate' or 'public'. | +| [observability\_grafana\_admin\_password](#output\_observability\_grafana\_admin\_password) | The Grafana admin password of the optional landing zone observability instance. | +| [observability\_grafana\_admin\_user](#output\_observability\_grafana\_admin\_user) | The Grafana admin username of the optional landing zone observability instance. | +| [observability\_grafana\_url](#output\_observability\_grafana\_url) | The Grafana URL of the optional landing zone observability instance. | +| [observability\_instance\_id](#output\_observability\_instance\_id) | The optional observability instance ID in the landing zone project. | +| [observability\_metrics\_push\_url](#output\_observability\_metrics\_push\_url) | The Prometheus remote-write URL of the optional landing zone observability instance. | +| [project\_container\_id](#output\_project\_container\_id) | The container ID of the created STACKIT project. | +| [project\_id](#output\_project\_id) | The project ID of the created STACKIT project. | +| [project\_name](#output\_project\_name) | The name of the created STACKIT project. | +| [project\_network](#output\_project\_network) | Non-secret reference to the managed project network, or null when no network is created. | +| [secretsmanager\_instance\_id](#output\_secretsmanager\_instance\_id) | The ID of the landing zone Secrets Manager instance. | + diff --git a/src/modules/landing-zone/README.md b/src/modules/landing-zone/README.md index 35157a9..3aa100f 100644 --- a/src/modules/landing-zone/README.md +++ b/src/modules/landing-zone/README.md @@ -1,3 +1,7 @@ +# landing-zone + +[English](README.md) | [Deutsch](README.de.md) + Public projects can opt into a local project network with `network_enabled = true`. Corporate projects retain their routed network and SNA integration. Omitting the option preserves existing public projects without a network. The optional diff --git a/src/modules/management/README.de.md b/src/modules/management/README.de.md new file mode 100644 index 0000000..21c23ad --- /dev/null +++ b/src/modules/management/README.de.md @@ -0,0 +1,97 @@ +# management + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | +| [time](#requirement\_time) | >= 0.14.1 | +| [vault](#requirement\_vault) | >= 5.11.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [stackit](#provider\_stackit) | >= 0.114.0 | +| [time](#provider\_time) | >= 0.14.1 | +| [vault](#provider\_vault) | >= 5.11.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [stackit_authorization_organization_role_assignment.sa_owner](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_organization_role_assignment) | resource | +| [stackit_authorization_project_role_assignment.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_role_assignment) | resource | +| [stackit_logs_access_token.audit_read](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/logs_access_token) | resource | +| [stackit_logs_access_token.audit_write](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/logs_access_token) | resource | +| [stackit_logs_instance.audit](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/logs_instance) | resource | +| [stackit_objectstorage_bucket.audit_logs](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_bucket) | resource | +| [stackit_objectstorage_bucket.default](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_bucket) | resource | +| [stackit_objectstorage_bucket.tfstate](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_bucket) | resource | +| [stackit_objectstorage_compliance_lock.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_compliance_lock) | resource | +| [stackit_objectstorage_credential.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_credential) | resource | +| [stackit_objectstorage_credentials_group.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_credentials_group) | resource | +| [stackit_objectstorage_default_retention.audit_logs](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/objectstorage_default_retention) | resource | +| [stackit_observability_credential.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/observability_credential) | resource | +| [stackit_observability_instance.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/observability_instance) | resource | +| [stackit_resourcemanager_project.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource | +| [stackit_secretsmanager_instance.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/secretsmanager_instance) | resource | +| [stackit_secretsmanager_user.default](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/secretsmanager_user) | resource | +| [stackit_service_account.automation](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/service_account) | resource | +| [stackit_service_account_federated_identity_provider.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/service_account_federated_identity_provider) | resource | +| [stackit_service_account_key.automation](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/service_account_key) | resource | +| [stackit_telemetrylink.audit](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/telemetrylink) | resource | +| [stackit_telemetryrouter_access_token.audit_link](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/telemetryrouter_access_token) | resource | +| [stackit_telemetryrouter_destination.audit_archive](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/telemetryrouter_destination) | resource | +| [stackit_telemetryrouter_destination.audit_logs](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/telemetryrouter_destination) | resource | +| [stackit_telemetryrouter_instance.audit](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/telemetryrouter_instance) | resource | +| [time_rotating.automation](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/rotating) | resource | +| [vault_kv_secret_v2.audit_logs](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/kv_secret_v2) | resource | +| [vault_kv_secret_v2.object_storage_credentials](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/kv_secret_v2) | resource | +| [vault_kv_secret_v2.observability](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/kv_secret_v2) | resource | +| [vault_kv_secret_v2.service_account_key_automation](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/resources/kv_secret_v2) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [audit\_logs](#input\_audit\_logs) | Audit logs configuration. The router forwards to two destinations: OTLP into the Logs instance for querying, and S3 into the audit bucket for long-term archive. retention\_days applies to both, driving the Logs instance retention and, when s3\_object\_lock is enabled, the archive bucket's default retention. link\_scopes defaults to a single organization-wide link; set it to attach individual folders or projects instead. |
object({
retention_days = optional(number, 180)
acl = optional(list(string), null)
s3_object_lock = optional(bool, true)
link_scopes = optional(list(object({
resource_type = string # organization, folder, project
resource_id = string
})), null)
})
| `null` | no | +| [federated\_identity\_providers](#input\_federated\_identity\_providers) | List of federated identity providers to configure for the management service account. |
list(object({
name = string
issuer = string
assertions = list(object({
item = string
operator = string
value = string
}))
}))
| `[]` | no | +| [labels](#input\_labels) | Additional labels to apply to all folders. | `map(string)` | `{}` | no | +| [naming\_pattern](#input\_naming\_pattern) | Naming prefix for all resources in this module, e.g. "myco-pltfm-hub-prod". | `string` | n/a | yes | +| [observability](#input\_observability) | Observability instance configuration. Set to null to skip observability deployment. |
object({
plan_name = optional(string, "Observability-Starter-EU01")
acl = optional(list(string), [])
logs_retention_days = optional(number, 30)
traces_retention_days = optional(number, 30)
metrics_retention_days = optional(number, 90)
metrics_retention_days_5m_downsampling = optional(number, 90)
metrics_retention_days_1h_downsampling = optional(number, 90)
})
| `null` | no | +| [organization\_id](#input\_organization\_id) | Container ID of the root folder or organization under which the company folder will be created. | `string` | n/a | yes | +| [owner\_email](#input\_owner\_email) | Email address of the owner for the folders. Required for STACKIT resource manager. | `string` | n/a | yes | +| [parent\_container\_id](#input\_parent\_container\_id) | Parent container ID (folder or organization) where the project will be created. | `string` | n/a | yes | +| [project\_name](#input\_project\_name) | Name of the STACKIT project to create. | `string` | `null` | no | +| [role\_assignments](#input\_role\_assignments) | List of role assignments for the project. Subject can be a user email or service account email. |
list(object({
role = string
subject = string
}))
| `[]` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [audit\_logs\_bucket\_name](#output\_audit\_logs\_bucket\_name) | The name of the object storage bucket archiving audit logs. | +| [audit\_logs\_datasource\_url](#output\_audit\_logs\_datasource\_url) | Datasource URL of the audit Logs instance, usable as a Grafana datasource. | +| [audit\_logs\_instance\_id](#output\_audit\_logs\_instance\_id) | The ID of the Logs instance receiving audit logs. | +| [audit\_telemetry\_router\_id](#output\_audit\_telemetry\_router\_id) | The ID of the Telemetry Router collecting audit logs. | +| [bucket\_name\_tfstate](#output\_bucket\_name\_tfstate) | The name of the tfstate object storage bucket. | +| [project\_container\_id](#output\_project\_container\_id) | The container ID of the created STACKIT project. | +| [project\_id](#output\_project\_id) | The project ID of the created STACKIT project. | +| [project\_name](#output\_project\_name) | The name of the created STACKIT project. | +| [secretsmanager\_instance\_id](#output\_secretsmanager\_instance\_id) | The ID of the Secrets Manager instance, usable as the vault mount. | +| [secretsmanager\_password](#output\_secretsmanager\_password) | The password of the default Secrets Manager user. | +| [secretsmanager\_username](#output\_secretsmanager\_username) | The username of the default Secrets Manager user. | +| [service\_account\_email](#output\_service\_account\_email) | The email of the created service account. | + diff --git a/src/modules/management/README.md b/src/modules/management/README.md index c923065..c5db900 100644 --- a/src/modules/management/README.md +++ b/src/modules/management/README.md @@ -1,3 +1,9 @@ +# management + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this module. + ## Requirements diff --git a/src/modules/namespace-service-demo/README.de.md b/src/modules/namespace-service-demo/README.de.md new file mode 100644 index 0000000..c6b4e9a --- /dev/null +++ b/src/modules/namespace-service-demo/README.de.md @@ -0,0 +1,54 @@ +# namespace-service-demo + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [grafana](#requirement\_grafana) | >= 4.45.2 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [grafana.observability](#provider\_grafana.observability) | >= 4.45.2 | +| [stackit](#provider\_stackit) | >= 0.114.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [grafana_dashboard.namespace_overview](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/dashboard) | resource | +| [grafana_data_source.platform_prometheus](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/data_source) | resource | +| [grafana_folder.stackit_managed](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/folder) | resource | +| [stackit_observability_credential.platform_metrics_reader](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/observability_credential) | resource | +| [stackit_observability_scrapeconfig.namespace_demo_ingestion](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/observability_scrapeconfig) | resource | +| [stackit_secretsmanager_user.external_secret_demo](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/secretsmanager_user) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [dashboard\_folder\_title](#input\_dashboard\_folder\_title) | Folder title used for managed landing-zone demo dashboards. | `string` | `"STACKIT Managed Dashboards"` | no | +| [dashboard\_passwords](#input\_dashboard\_passwords) | Grafana admin passwords keyed by landing-zone key for dashboard demo imports. | `map(string)` | `{}` | no | +| [services](#input\_services) | Enabled namespace-service demo configurations keyed by landing-zone key. |
map(object({
namespace = string
use_secretsmanager = bool
landing_zone_project_id = string
secretsmanager_instance_id = string
observability_instance_id = optional(string)
observability_grafana_url = optional(string)
observability_admin_user = optional(string)
demo_metrics_ingestion_enabled = optional(bool, false)
demo_metrics_ingestion_target_urls = optional(list(string), [])
demo_metrics_ingestion_scheme = optional(string, "https")
demo_metrics_ingestion_metrics_path = optional(string, "/")
demo_metrics_ingestion_scrape_interval = optional(string, "60s")
demo_metrics_ingestion_scrape_timeout = optional(string, "30s")
platform_project_id = optional(string)
platform_observability_instance_id = optional(string)
platform_observability_targets_url = optional(string)
dns_zone_name = optional(string)
}))
| `{}` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [samples](#output\_samples) | Demo sample references for enabled namespace-service demos. | +| [secret\_access](#output\_secret\_access) | Credentials for demo Secrets Manager users keyed by landing zone. | + diff --git a/src/modules/namespace-service-demo/README.md b/src/modules/namespace-service-demo/README.md index 276c294..ab885c7 100644 --- a/src/modules/namespace-service-demo/README.md +++ b/src/modules/namespace-service-demo/README.md @@ -1,3 +1,9 @@ +# namespace-service-demo + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this module. + ## Requirements diff --git a/src/modules/platform-kubernetes/README.de.md b/src/modules/platform-kubernetes/README.de.md new file mode 100644 index 0000000..2dbbca9 --- /dev/null +++ b/src/modules/platform-kubernetes/README.de.md @@ -0,0 +1,86 @@ +# platform-kubernetes + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | +| [time](#requirement\_time) | >= 0.14.1 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [stackit](#provider\_stackit) | >= 0.114.0 | +| [time](#provider\_time) | >= 0.14.1 | + +## Modules + +| Name | Source | Version | +| ---- | ------ | ------- | +| [debug\_bastion](#module\_debug\_bastion) | ../debug-bastion | n/a | + +## Resources + +| Name | Type | +| ---- | ---- | +| [stackit_authorization_project_role_assignment.kms_admin](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_role_assignment) | resource | +| [stackit_authorization_project_role_assignment.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_role_assignment) | resource | +| [stackit_authorization_service_account_role_assignment.ske_impersonation](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_service_account_role_assignment) | resource | +| [stackit_dns_zone.ske_extension](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/dns_zone) | resource | +| [stackit_kms_key.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/kms_key) | resource | +| [stackit_kms_keyring.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/kms_keyring) | resource | +| [stackit_network.sna](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/network) | resource | +| [stackit_observability_instance.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/observability_instance) | resource | +| [stackit_resourcemanager_project.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource | +| [stackit_routing_table.sna_egress](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/routing_table) | resource | +| [stackit_routing_table_route.sna_default_route](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/routing_table_route) | resource | +| [stackit_service_account.kms_manager](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/service_account) | resource | +| [stackit_ske_cluster.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/ske_cluster) | resource | +| [stackit_ske_kubeconfig.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/ske_kubeconfig) | resource | +| [time_sleep.wait_for_network_area_membership](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [stackit_service_accounts.ske_internal](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/data-sources/service_accounts) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [cluster](#input\_cluster) | SKE cluster configuration. |
object({
name = string
kubernetes_version_min = optional(string, null)
node_pools = optional(list(object({
name = string
machine_type = string
minimum = number
maximum = number
availability_zones = list(string)
allow_system_components = optional(bool, false)
volume_size = optional(number, 20)
volume_type = optional(string, "storage_premium_perf1")
os_name = optional(string, "flatcar")
labels = optional(map(string), {})
})), [
{
name = "system"
machine_type = "g3i.4"
minimum = 2
maximum = 2
availability_zones = ["eu01-1"]
allow_system_components = true
volume_size = 20
volume_type = "storage_premium_perf1"
os_name = "flatcar"
labels = {
"workload-role" = "system"
}
},
{
name = "application"
machine_type = "g3i.4"
minimum = 2
maximum = 2
availability_zones = ["eu01-2"]
allow_system_components = false
volume_size = 20
volume_type = "storage_premium_perf1"
os_name = "flatcar"
labels = {
"workload-role" = "application"
}
}
])
maintenance = optional(object({
enable_kubernetes_version_updates = optional(bool, true)
enable_machine_image_version_updates = optional(bool, true)
start = optional(string, "01:00:00Z")
end = optional(string, "02:00:00Z")
}), {})
})
| n/a | yes | +| [debug\_bastion](#input\_debug\_bastion) | Optional debug bastion VM in the SNA network with SSH access to test SKE connectivity from inside the private network. |
object({
enabled = optional(bool, false)
name = optional(string, null)
availability_zone = optional(string, null)
machine_type = optional(string, "g2i.1")
image_id = optional(string, "7b10e105-295b-4369-b6e0-567ec940a02b")
boot_volume_size = optional(number, 20)
ssh_public_key = optional(string, null)
ssh_public_key_path = optional(string, "~/.ssh/id_rsa.pub")
ssh_allowed_cidrs = optional(list(string), ["0.0.0.0/0"])
assign_public_ip = optional(bool, true)
install_kubectl = optional(bool, true)
})
| `{}` | no | +| [dns](#input\_dns) | SKE DNS extension configuration. If create\_zones is true, zones are created in the platform project before cluster creation. gateway\_api enables Gateway API support for ExternalDNS. |
object({
enabled = optional(bool, true)
create_zones = optional(bool, true)
zones = optional(list(string), [])
gateway_api = optional(bool, true)
})
| `{}` | no | +| [encrypted\_volumes](#input\_encrypted\_volumes) | Optional encrypted volume setup for SKE via KMS and Kubernetes storage class. |
object({
enabled = optional(bool, false)
storage_class_name = optional(string, "stackit-encrypted-premium")
kms_keyring_name = optional(string, "ske-volume-keyring")
kms_key_name = optional(string, "ske-volume-key")
kms_key_version = optional(string, "1")
})
| `{}` | no | +| [labels](#input\_labels) | Additional labels to apply to resources in this module. | `map(string)` | `{}` | no | +| [naming\_pattern](#input\_naming\_pattern) | Naming prefix for resources in this module, e.g. myco-pltfm-k8s-eu01. | `string` | n/a | yes | +| [network](#input\_network) | Network settings for SKE. Set sna\_enabled=true and provide sna\_network\_area\_id for SNA; otherwise the cluster runs in public control-plane mode. |
object({
sna_enabled = optional(bool, false)
sna_network_area_id = optional(string, null)
firewall_next_hop_ip = optional(string, null)
sna_network_prefix_length = optional(number, 24)
})
| `{}` | no | +| [observability](#input\_observability) | Observability configuration for central cluster monitoring in the same project as the cluster. |
object({
enabled = optional(bool, true)
plan_name = optional(string, "Observability-Starter-EU01")
acl = optional(list(string), [])
name = optional(string, null)
})
| `{}` | no | +| [organization\_id](#input\_organization\_id) | Organization ID used for routing table resources in network-area scope. | `string` | n/a | yes | +| [owner\_email](#input\_owner\_email) | Email address of the project owner. Required for project creation. | `string` | n/a | yes | +| [parent\_container\_id](#input\_parent\_container\_id) | Parent container ID (folder or organization) where the project will be created. | `string` | n/a | yes | +| [project\_name](#input\_project\_name) | Name of the STACKIT project to create. | `string` | `null` | no | +| [region](#input\_region) | STACKIT region for the SKE cluster. | `string` | n/a | yes | +| [role\_assignments](#input\_role\_assignments) | List of role assignments for the project. Subject can be a user email or service account email. |
list(object({
role = string
subject = string
}))
| `[]` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [debug\_bastion](#output\_debug\_bastion) | Debug bastion metadata when enabled for private cluster troubleshooting. | +| [dns\_extension\_zones](#output\_dns\_extension\_zones) | DNS zones configured for SKE DNS extension. | +| [encrypted\_volume\_support](#output\_encrypted\_volume\_support) | Configuration values for encrypted SKE volumes when enabled. | +| [kube\_config](#output\_kube\_config) | Kubeconfig for the created SKE cluster. | +| [observability\_instance\_id](#output\_observability\_instance\_id) | The observability instance ID used for cluster extension. | +| [observability\_targets\_url](#output\_observability\_targets\_url) | The Prometheus query endpoint URL of the optional platform observability instance. | +| [project\_container\_id](#output\_project\_container\_id) | The container ID of the created STACKIT project. | +| [project\_id](#output\_project\_id) | The project ID of the created STACKIT project. | +| [project\_name](#output\_project\_name) | The name of the created STACKIT project. | +| [ske\_cluster\_name](#output\_ske\_cluster\_name) | The name of the created SKE cluster. | +| [ske\_cluster\_region](#output\_ske\_cluster\_region) | The region of the created SKE cluster. | + diff --git a/src/modules/platform-kubernetes/README.md b/src/modules/platform-kubernetes/README.md index b8b49aa..b69faea 100644 --- a/src/modules/platform-kubernetes/README.md +++ b/src/modules/platform-kubernetes/README.md @@ -1,3 +1,9 @@ +# platform-kubernetes + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this module. + ## Requirements diff --git a/src/modules/sandboxes/README.de.md b/src/modules/sandboxes/README.de.md new file mode 100644 index 0000000..e3a2fa3 --- /dev/null +++ b/src/modules/sandboxes/README.de.md @@ -0,0 +1,47 @@ +# sandboxes + +[English](README.md) | [Deutsch](README.de.md) + +Die folgende generierte technische Referenz dokumentiert dieses Modul. +Der generatorverwaltete technische Block bleibt unverändert auf Englisch; +maßgeblich ist die [kanonische englische Referenz](README.de.md). + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.11 | +| [stackit](#requirement\_stackit) | >= 0.114.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [stackit](#provider\_stackit) | >= 0.114.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [stackit_authorization_project_role_assignment.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/authorization_project_role_assignment) | resource | +| [stackit_resourcemanager_project.this](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/resources/resourcemanager_project) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [naming\_prefix](#input\_naming\_prefix) | Naming prefix for all resources in this module. | `string` | n/a | yes | +| [parent\_container\_id](#input\_parent\_container\_id) | Parent container ID (folder or organization) where the project will be created. | `string` | n/a | yes | +| [sandboxes](#input\_sandboxes) | List of sandboxes to create. |
list(object({
project_name = string
owner_emails = optional(list(string))
project_owner_email = string
}))
| `[]` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [projects](#output\_projects) | The created STACKIT projects with their IDs, container IDs, and names. | + diff --git a/src/modules/sandboxes/README.md b/src/modules/sandboxes/README.md index 55d523a..23c33f8 100644 --- a/src/modules/sandboxes/README.md +++ b/src/modules/sandboxes/README.md @@ -1,3 +1,9 @@ +# sandboxes + +[English](README.md) | [Deutsch](README.de.md) + +The generated technical reference below documents this module. + ## Requirements