From e4175fc1ce20d739dc933f55d6fb56c48f094e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Weberru=C3=9F?= Date: Fri, 16 Oct 2026 23:22:16 +0000 Subject: [PATCH] fix(configurator): review bounded DNS role explanations Use existing reviewed native metadata for DNS field and primary/secondary semantics. Keep explicit DNS completion requests in the proposal flow and retain all unchanged factual and execution gates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../assistant/knowledge-topics.generated.ts | 4 ++-- .../app/apps/api/src/assistant/knowledge.ts | 2 ++ .../apps/api/src/assistant/model-serving.ts | 2 +- .../app/tests/assistant-scenarios.test.ts | 20 +++++++++++++++++++ .../app/tests/assistant.test.ts | 6 +++++- .../docs/assistant-knowledge/README.md | 7 ++++++- .../docs/assistant-test-catalogue.json | 2 +- 7 files changed, 37 insertions(+), 6 deletions(-) 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 d20a750..d71ccba 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 @@ -1512,12 +1512,12 @@ export const assistantKnowledgeTopics = { { path: "landing-zone-configurator/app/apps/api/src/assistant/model-serving.ts", sha256: - "eb8076781fb3f1a86bd2e1f9ec1f40787acdb202bb7d956c85e50c898771b852", + "e362e0e4433ecdc8cb651535d1540c9b2f5bae17647c6ade32fe470ca2b256d5", }, { path: "landing-zone-configurator/app/apps/api/src/assistant/knowledge.ts", sha256: - "d9f64d3eec6356d2958f5f86fa778ce998120baf1500eada26b00546f448da9e", + "906dc58635bc8d738e252777c7524caf59631fbff4f4a5d8f470aa85c82630b9", }, { path: "landing-zone-configurator/app/apps/api/src/assistant/topic-fields.ts", diff --git a/landing-zone-configurator/app/apps/api/src/assistant/knowledge.ts b/landing-zone-configurator/app/apps/api/src/assistant/knowledge.ts index 5b04bd2..993723a 100644 --- a/landing-zone-configurator/app/apps/api/src/assistant/knowledge.ts +++ b/landing-zone-configurator/app/apps/api/src/assistant/knowledge.ts @@ -54,6 +54,8 @@ export const assistantFirewallPolicyLimit = "Der Assistant kann aktuell keine Firewall-Regeln, NAT, Aliase oder Routen definieren oder als Vorschlag übernehmen. Die geführte Policy-Bearbeitung in Editor und Chat ist nicht Teil des MVP (GitHub-Issue #101). Im MVP pflegt der Firewall-Admin die Policy nach Bereitstellung manuell in OPNsense."; const fieldOverviewNotes: Record = { + "dns-zones": + "connectivity.dns_zones und regionale connectivity_regions-Einträge enthalten die Zonen mit stabilen Schlüsseln und den Feldern dns_name, name, description, default_ttl, type, contact_email, acl und network_area_key. SNA default_nameservers legt Resolver fest, keine autoritative Zone. type hat den nativen Default primary. Primary verwaltet die führenden DNS-Einträge bei STACKIT und wird für eine neue dort verwaltete Firmenzone empfohlen. Secondary repliziert eine Kopie vom externen Primary. Beide sind autoritativ; primary/secondary bezeichnet nicht public/private oder die Sichtbarkeit. Der native Accelerator bildet die benötigte Konfiguration externer Primary-Server für Secondary nicht ab; daher kein vollständiges Secondary-Setup und keine stille Umwandlung bestehender Secondary-Zonen. default_ttl hat den nativen Default 3600 Sekunden; 60 bis 99999999 sind im Editor zulässig. Kürzere TTL erleichtert Änderungen, verlängerte TTL hält Cache-Einträge länger. Kontakt und SNA-Zuordnung aus bestätigten Angaben erhalten; kein erfundener Kontakt. ACL wird im gepinnten Provider nicht durchgesetzt und ist kein Zugriffsschutz. Leere Zonen-Map bedeutet keine Zone. Eine freie Subdomain ist keine kostenlose DNS-Service-Zusage. Verfügbarkeit, Delegation, Propagation und Erreichbarkeit bleiben separat zu prüfen. Nur Feld- und Rollenübersicht: nichts geändert, gespeichert oder ausgeführt.", "devops-git": 'devops=null überspringt das DevOps-Modul. Das native Objekt enthält git_flavor (Standard null) und allowed_network_ranges (Schema-Default ["0.0.0.0/0"]). git_flavor=null erstellt keine Git-Instanz; auch ein reines ACL-Objekt aktiviert Git nicht. Der offene ACL-Default ist keine Zustimmung zu öffentlichem Zugriff: Zugriffsnetze bewusst wählen. Ein Flavor muss bei gewünschtem Git explizit gewählt und für Projekt/Region separat geprüft werden; kein automatisch aktivierter Git-Flavor. Das Root-Modul leitet Projekt, Ownership und Namen ab. Managed Git ist getrennt von GitHub-Anmeldung, Forks und Configurator-CI. Keine Verfügbarkeits-, Leistungs-, Backup- oder Migrationsgarantie; keine Zugangsdaten oder privaten Schlüssel im Chat. Diese Feldübersicht schlägt keine Konfiguration vor und speichert oder provisioniert nichts. Entwurfsübernahme, Speichern, autorisierter Plan und ausdrücklicher Apply bleiben getrennte Schritte.', vpn: "connectivity.vpn beziehungsweise connectivity_regions[*].vpn enthält display_name, plan_id, routing_type, availability_zones und connections. null deaktiviert die optionale VPN-Konfiguration. Native Schema-Defaults sind plan_id=p100 und routing_type=ROUTE_BASED; das ist kein Verfügbarkeits-, Berechtigungs- oder Leistungsnachweis. availability_zones benötigt tunnel1 und tunnel2. connections ist eine Map mit stabilen Verbindungsschlüsseln: display_name, enabled (Standard true), local_subnets, remote_subnets und static_routes sowie tunnel1 und tunnel2. Jeder Tunnel enthält remote_address, optionales peering mit local_address/remote_address sowie phase1 und phase2. Die Phasen konfigurieren encryption_algorithms, integrity_algorithms, dh_groups und rekey_time; phase2 zusätzlich dpd_action und start_action. Netze, Gegenstellen, Routing und Kompatibilität müssen getrennt geprüft werden; für reine SNA-interne Kommunikation ist kein VPN erforderlich. vpn_pre_shared_keys ist ein separater geschützter Eingang pro Verbindung mit tunnel1/tunnel2, nicht Teil des öffentlichen connectivity-Objekts. Werte ausschließlich außerhalb des Chats über TF_VAR_vpn_pre_shared_keys oder eine gitignorierte tfvars-Datei bereitstellen; keine PSK-Werte anfordern, anzeigen oder durch den Assistant exportieren. Feldübersicht ist kein Einrichtungsvorschlag: nichts gespeichert oder ausgeführt. Plan, geschützte Zugänge und Apply benötigen separate autorisierte Prüfung.", diff --git a/landing-zone-configurator/app/apps/api/src/assistant/model-serving.ts b/landing-zone-configurator/app/apps/api/src/assistant/model-serving.ts index 285ae0b..0304602 100644 --- a/landing-zone-configurator/app/apps/api/src/assistant/model-serving.ts +++ b/landing-zone-configurator/app/apps/api/src/assistant/model-serving.ts @@ -853,7 +853,7 @@ export class AssistantModelServing { { role: "system", content: - "Informational native-field questions use mode=advice, adviceTask=field-overview and adviceTaskSource=current: the USER asks about the native configuration contract, including fields, parameters, defaults, effects of null/default values, limits or prerequisites. A field overview is NOT restricted to listing field names. Questions whether a default enables/creates a component, or whether an assumed default is correct, still ask about native configuration semantics, not a live deployment. For example, Git flavor/default/no-instance and deliberate ACL questions are devops-git field-overview; do not classify them as other. Available topics mark reviewedFieldOverview when a reviewed answer exists. Select that component's topic, not configuration-lifecycle. Explaining how protected inputs are supplied separately is still a field overview, not a credential request or setup task. This includes VPN gateway/connection fields, site networks, tunnel parameters and separate PSK handling. Do not default adviceTask to other for such questions. Actual configuration/proposal requests remain draft; never infer them from an informational question.", + "Informational native-field questions use mode=advice, adviceTask=field-overview and adviceTaskSource=current: the USER asks about the native configuration contract, including fields, parameters, field meanings, enum roles, defaults, effects of null/default values, limits or prerequisites. A field overview is NOT restricted to listing field names. Questions whether a default enables/creates a component, or whether an assumed default is correct, still ask about native configuration semantics, not a live deployment. For example, Git flavor/default/no-instance and deliberate ACL questions are devops-git field-overview; DNS zone type primary/secondary, their authoritative roles versus visibility, and native Secondary prerequisites are dns-zones field-overview. This also applies when correcting earlier misleading field explanations. Do not classify these informational semantics as other. Available topics mark reviewedFieldOverview when a reviewed answer exists. Select that component's topic, not configuration-lifecycle. Explaining how protected inputs are supplied separately is still a field overview, not a credential request or setup task. This includes VPN gateway/connection fields, site networks, tunnel parameters and separate PSK handling. Do not default adviceTask to other for such questions. Actual configuration/proposal requests remain draft; never infer them from an informational question. Conversely, an explicit request to complete DNS settings or propose suitable remaining settings is topic=dns-zones, mode=draft, dnsTask=remaining-settings, adviceTask=other. It is NOT an informational overview or a request to ask all fields again. Missing contact values do not change that task classification: the downstream proposal flow resolves confirmed contact sources or asks only genuinely missing decisions.", }, { role: "user", content: message }, ], diff --git a/landing-zone-configurator/app/tests/assistant-scenarios.test.ts b/landing-zone-configurator/app/tests/assistant-scenarios.test.ts index 5ba8670..f3d7a93 100644 --- a/landing-zone-configurator/app/tests/assistant-scenarios.test.ts +++ b/landing-zone-configurator/app/tests/assistant-scenarios.test.ts @@ -466,6 +466,26 @@ it("requires native VPN defaults and separate PSK binding, rejecting invented ro ).toContain("incorrect_vpn_routing_type"); }); +it("qualifies reviewed DNS field semantics against the unchanged role and secondary-limit oracles", () => { + const explanation = buildAssistantKnowledge().topics.find( + (topic) => topic.id === "dns-zones", + )?.fieldOverview; + if (!explanation) throw new Error("missing_dns_overview"); + expect(explanation.length).toBeLessThanOrEqual(2400); + expect(assistantDnsRoleFailures(explanation, "roles")).toEqual([]); + for (const scenario of assistantScenarios.filter( + (entry) => entry.dnsRole === "roles" || entry.dnsRole === "secondary", + )) + expect( + validateAssistantScenario(scenario, { + explanation, + questions: [], + changes: [], + references: ["dns-zones"], + }).failures, + ).toEqual([]); +}); + it("rejects superficially successful foundation answers and validates exact restoration", () => { const scenario = assistantScenarios.find( (entry) => entry.id === "foundations-restoration", diff --git a/landing-zone-configurator/app/tests/assistant.test.ts b/landing-zone-configurator/app/tests/assistant.test.ts index 6d75371..8cf1369 100644 --- a/landing-zone-configurator/app/tests/assistant.test.ts +++ b/landing-zone-configurator/app/tests/assistant.test.ts @@ -2540,6 +2540,7 @@ it.each([ "sandbox-projects", "vpn", "devops-git", + "dns-zones", ])( "answers %s field overviews from reviewed native metadata, not incomplete model prose", async (topic) => { @@ -2552,6 +2553,9 @@ it.each([ expect(body.messages[0].content).toContain( '"reviewedFieldOverview":true', ); + expect(body.messages[0].content).toContain( + "mode=draft, dnsTask=remaining-settings, adviceTask=other", + ); return answer({ topic, mode: "advice", @@ -2580,7 +2584,7 @@ it.each([ ?.fieldOverview, ); expect(result.explanation.length).toBeLessThanOrEqual(3000); - if (topic === "vpn" || topic === "devops-git") + if (["vpn", "devops-git", "dns-zones"].includes(topic)) expect(result.explanation.length).toBeLessThanOrEqual(2400); if (topic === "vpn") { for (const field of [ diff --git a/landing-zone-configurator/docs/assistant-knowledge/README.md b/landing-zone-configurator/docs/assistant-knowledge/README.md index 91980ad..f1a570b 100644 --- a/landing-zone-configurator/docs/assistant-knowledge/README.md +++ b/landing-zone-configurator/docs/assistant-knowledge/README.md @@ -118,13 +118,18 @@ contract. Transport tests check this instruction's delivery; real-model factual criteria still decide whether the resulting answers qualify. For native field overviews, semantic intent classification selects the existing reviewed-metadata response when available, rather than generating the same static -contract again. VPN and DevOps Git use this path with a tested 2400-character bound, no questions +contract again. VPN, DevOps Git and DNS field/role semantics use this path with a +tested 2400-character bound, no questions or draft changes, native routing/plan defaults and the separate protected PSK binding. Its factual oracle requires these details and rejects invented static/dynamic routing types. DevOps requires its native fields and the `git_flavor=null` no-instance boundary, without implying an enabled default. This does not replace live availability checks or authorize configuration; unsupported overview topics retain the advice path. +DNS role explanations retain the existing primary/secondary, authoritative-role, +visibility and native Secondary-configuration-limit criteria, including correction +of earlier misleading advice. Actual DNS setup continues through the existing +reviewable proposal flow. CI needs `LZC_MODEL_SERVING_TOKEN` available to the protected `assistant-tests` environment. Local receipts do not certify that remote environment or authorize deployment. CI qualification jobs share a non-cancelling concurrency group to diff --git a/landing-zone-configurator/docs/assistant-test-catalogue.json b/landing-zone-configurator/docs/assistant-test-catalogue.json index e516e7f..124e763 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": "40c40462421ad8f292a21871ce9a82396c1300239c400de0f6de22e5d2bcef93", + "knowledgeSha256": "601ad8cd6a1e257f5f95207493e6df5a22b2cfd67fc84c7655d67ac36bcb4c38", "sourceDigests": { "scripts/assistant-scenarios.ts": "441273d9af541a14185062728a9f9a7044df0e8a7c51645a53eb970a341867d9", "scripts/assistant-tests.ts": "fb1ba4a3438fbcd6d12c0a87d9bc9beeae8066bb5b691a7e2901635a842bb5df"