<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>devs group Blog</title><description>Fachbeiträge zu Go, Kubernetes, KI-Architektur und Schweizer Regulierung, geschrieben vom Team der devs group.</description><link>https://devs-group.ch/</link><language>de-CH</language><lastBuildDate>Fri, 04 Sep 2026 00:00:00 GMT</lastBuildDate><item><title>Agenten, die niemand freigegeben hat</title><link>https://devs-group.ch/blog/agenten-governance-schatten-it/</link><guid isPermaLink="true">https://devs-group.ch/blog/agenten-governance-schatten-it/</guid><description>OpenClaw läuft lokal, ohne Beschaffung, mit weitreichenden Rechten. Agenten-Governance heisst: Positivliste, Rechteklassen, Erkennung.</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Wer nicht festlegt, welche Agenten mit welchen Rechten auf welchem Code laufen dürfen, hat diese Entscheidung trotzdem getroffen, nur unbewusst. Agentenplattformen wie OpenClaw laufen auf der Maschine der Entwicklerin, brauchen keine Beschaffung und stehen in keinem Verzeichnis. Agenten-Governance besteht deshalb aus drei Teilen: einer Positivliste, abgestuften Rechteklassen und einer Erkennung, die ohne Verdächtigungen auskommt.&lt;/p&gt;
&lt;p&gt;Der typische Auslöser ist ein Nebensatz im Daily. Jemand erwähnt, dass der Agent das Refactoring über Nacht gemacht hat, per Telegram angestossen, vom privaten MacBook aus. Und dann ist die Frage nicht mehr, ob so etwas im Einsatz ist, sondern seit wann.&lt;/p&gt;
&lt;h2 id=&quot;ein-repository-mit-386890-sternen-das-nie-durch-die-beschaffung-ging&quot;&gt;Ein Repository mit 386’890 Sternen, das nie durch die Beschaffung ging&lt;/h2&gt;
&lt;p&gt;OpenClaw steht am 20.08.2026 bei 386’890 GitHub-Sternen und ist damit das sechstmeistgesternte Repository überhaupt, deutlich vor React mit 247’443 (&lt;a href=&quot;https://api.github.com/search/repositories?q=stars:%3E250000&amp;amp;sort=stars&quot;&gt;GitHub-API&lt;/a&gt;, Abruf 20.08.2026). Das ist keine Herstellerangabe, sondern der Zählerstand der Plattform selbst.&lt;/p&gt;
&lt;p&gt;Was dahintersteckt: eine offene Agentenplattform von Peter Steinberger, die auf der eigenen Maschine läuft und über gewöhnliche Chat-Apps bedient wird, WhatsApp, Telegram, Discord, Slack, Teams. Das Projekt formuliert es selbst als «Your assistant. Your machine. Your rules.» Kein SaaS, also kein Vertrag, keine Rechnung, kein Beschaffungsvorgang, den ein CTO je zu sehen bekommt.&lt;/p&gt;
&lt;p&gt;Für die Inventarisierung ist auch die Namensgeschichte relevant. Aus dem Wochenendprojekt «WhatsApp Relay» vom November 2025 wurde «Clawd», danach «Moltbot», seit dem 29.01.2026 heisst es OpenClaw. Wer eine Liste erlaubter Werkzeuge pflegt und nach dem alten Namen sucht, findet nichts.&lt;/p&gt;
&lt;h2 id=&quot;welche-rechte-so-ein-agent-tatsächlich-hat&quot;&gt;Welche Rechte so ein Agent tatsächlich hat&lt;/h2&gt;
&lt;p&gt;OpenClaw kann Dateien lesen, Befehle ausführen, Plugins installieren und Netzwerkverbindungen aufbauen, und das Projekt sagt dazu selbst den entscheidenden Satz: «It is not a sandbox.» Die &lt;a href=&quot;https://docs.openclaw.ai/gateway/security&quot;&gt;Sicherheitsdokumentation&lt;/a&gt; beschreibt stattdessen Grenzen, etwa Pfadschutz und einen Proxy, räumt aber ein, dass ein Plugin mit Shell-Rechten weiterhin alles tun kann, was Shell-Rechte erlauben.&lt;/p&gt;
&lt;p&gt;Diese Offenheit ist ehrlicher als das Marketing der meisten kommerziellen Werkzeuge. Sie beschreibt aber genau die Klasse von Software, die auf einem Rechner mit Kundencode nicht unbeaufsichtigt laufen sollte.&lt;/p&gt;
&lt;p&gt;Dass die Rechteverwaltung dabei brechen kann, ist belegt. &lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2026-33579&quot;&gt;CVE-2026-33579&lt;/a&gt; beschreibt eine Privilege Escalation mit CVSS v4.0 9,4 und CVSS v3.1 9,9, eingestuft als CRITICAL durch die CNA VulnCheck, CWE-863, veröffentlicht am 31.03.2026. Betroffen sind alle Versionen vor 2026.3.28: Ein Aufrufer mit Pairing-, aber ohne Admin-Rechten konnte Geräteanfragen mit erweiterten Rechten inklusive Admin genehmigen, weil die Scope-Prüfung im Genehmigungspfad fehlte.&lt;/p&gt;
&lt;p&gt;Wenn Sie gerade nicht sagen können, welche Agenten auf Ihren Entwicklungsrechnern laufen und mit welchen Rechten: Genau diese Bestandsaufnahme machen wir in einem halben Tag mit Ihrem Team, ohne Werkzeugempfehlung am Ende. Schreiben Sie uns über &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;was-der-lokale-betrieb-unter-revdsg-auslöst&quot;&gt;Was der lokale Betrieb unter revDSG auslöst&lt;/h2&gt;
&lt;p&gt;Ein Agent, der Repository-Inhalte an ein Modell schickt, ist datenschutzrechtlich eine Bekanntgabe, und zwar meist ins Ausland. Enthält der Code Personendaten, etwa in Fixtures, Logs oder Migrationsskripten, greifen Art. 16 und Art. 9 des &lt;a href=&quot;https://www.fedlex.admin.ch/eli/cc/2022/491/de&quot;&gt;revDSG&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Besonders unangenehm ist Art. 9 Abs. 3: Ein Auftragsbearbeiter darf die Bearbeitung «nur mit vorgängiger Genehmigung des Verantwortlichen einem Dritten übertragen». Ein selbst installierter Agent, der einen zusätzlichen Modellanbieter anspricht, erzeugt exakt diesen ungenehmigten Dritten, und niemand im Unternehmen weiss davon.&lt;/p&gt;
&lt;p&gt;Die Sanktion trifft Menschen, nicht Abteilungen. Art. 61 revDSG stellt Bussen bis CHF 250’000 in Aussicht, gegen private Personen, auf Antrag, bei Vorsatz. Erfasst sind unter anderem die Bekanntgabe ins Ausland ohne die Voraussetzungen nach Art. 17 und die Übergabe an einen Auftragsbearbeiter ohne die Voraussetzungen nach Art. 9 Abs. 1 und 2.&lt;/p&gt;
&lt;p&gt;Wie sich das in Architektur übersetzt, haben wir in &lt;a href=&quot;https://devs-group.ch/blog/revdsg-konforme-ki-architektur/&quot;&gt;revDSG-konforme KI-Architektur&lt;/a&gt; Norm für Norm ausgeführt.&lt;/p&gt;
&lt;h2 id=&quot;drei-rechteklassen-statt-einer-einzigen-freigabe&quot;&gt;Drei Rechteklassen statt einer einzigen Freigabe&lt;/h2&gt;
&lt;p&gt;Eine binäre Freigabe scheitert, weil «erlaubt» für einen Autocomplete etwas anderes heisst als für einen Agenten, der nachts committet. Wir arbeiten deshalb mit drei Klassen, und die Klasse ergibt sich aus dem Zugriff, nicht aus dem Produktnamen.&lt;/p&gt;





































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Klasse&lt;/th&gt;&lt;th&gt;Sichtbarer Code&lt;/th&gt;&lt;th&gt;Ausführung&lt;/th&gt;&lt;th&gt;Netz&lt;/th&gt;&lt;th&gt;Freigabe durch&lt;/th&gt;&lt;th&gt;Typischer Fall&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;A&lt;/strong&gt; Assistenz&lt;/td&gt;&lt;td&gt;offener Arbeitsbereich, keine Secrets&lt;/td&gt;&lt;td&gt;keine&lt;/td&gt;&lt;td&gt;Modellanbieter der Positivliste&lt;/td&gt;&lt;td&gt;Team-Lead&lt;/td&gt;&lt;td&gt;Autocomplete, Chat im Editor&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;B&lt;/strong&gt; Beauftragt&lt;/td&gt;&lt;td&gt;ein Repository, Secrets über Vault&lt;/td&gt;&lt;td&gt;ja, in Container oder VM, Ergebnis als Pull Request&lt;/td&gt;&lt;td&gt;Positivliste plus freigegebene MCP-Server&lt;/td&gt;&lt;td&gt;Tech-Lead plus Datenschutzverantwortliche&lt;/td&gt;&lt;td&gt;Coding-Agent im Auftrag&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;C&lt;/strong&gt; Autonom&lt;/td&gt;&lt;td&gt;mehrere Repositories, Produktionsnähe&lt;/td&gt;&lt;td&gt;ja, ausserhalb der Arbeitszeit, ohne Beobachtung&lt;/td&gt;&lt;td&gt;jede ausgehende Verbindung möglich&lt;/td&gt;&lt;td&gt;Geschäftsleitung, befristet, mit Protokoll&lt;/td&gt;&lt;td&gt;Allzweck-Agent über Chat-App&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Die Linie, die zählt, liegt zwischen B und C. Alles, was in Klasse C fällt, gehört auf eine dedizierte Maschine mit eigenem Betriebssystem-Konto, nicht auf das Notebook, auf dem morgen ein Kundenprojekt geöffnet wird. Die OpenClaw-Dokumentation empfiehlt für geteilte Hosts von sich aus, Vertrauensgrenzen zu trennen, mit eigenen Betriebssystem-Nutzern oder eigenen Hosts.&lt;/p&gt;
&lt;div class=&quot;scroll-x scroll-x--diagram&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Diagramm, seitlich scrollbar&quot;&gt;&lt;svg id=&quot;mermaid-0&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot; class=&quot;flowchart&quot; style=&quot;width:567.5625px&quot; viewBox=&quot;0 0 567.5625 1209.625&quot; role=&quot;graphics-document document&quot; aria-roledescription=&quot;flowchart-v2&quot;&gt;&lt;style&gt;#mermaid-0{font-family:&quot;Geist&quot;,sans-serif;font-size:16px;fill:#f5f5f5;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-0 .error-icon{fill:#121315;}#mermaid-0 .error-text{fill:#edecea;stroke:#edecea;}#mermaid-0 .edge-thickness-normal{stroke-width:1px;}#mermaid-0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-0 .marker{fill:#c4c4c4;stroke:#c4c4c4;}#mermaid-0 .marker.cross{stroke:#c4c4c4;}#mermaid-0 svg{font-family:&quot;Geist&quot;,sans-serif;font-size:16px;}#mermaid-0 p{margin:0;}#mermaid-0 .label{font-family:&quot;Geist&quot;,sans-serif;color:#f5f5f5;}#mermaid-0 .cluster-label text{fill:#f5f5f5;}#mermaid-0 .cluster-label span{color:#f5f5f5;}#mermaid-0 .cluster-label span p{background-color:transparent;}#mermaid-0 .label text,#mermaid-0 span{fill:#f5f5f5;color:#f5f5f5;}#mermaid-0 .node rect,#mermaid-0 .node circle,#mermaid-0 .node ellipse,#mermaid-0 .node polygon,#mermaid-0 .node path{fill:#1b1d20;stroke:#363739;stroke-width:1px;}#mermaid-0 .rough-node .label text,#mermaid-0 .node .label text,#mermaid-0 .image-shape .label,#mermaid-0 .icon-shape .label{text-anchor:middle;}#mermaid-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-0 .rough-node .label,#mermaid-0 .node .label,#mermaid-0 .image-shape .label,#mermaid-0 .icon-shape .label{text-align:center;}#mermaid-0 .node.clickable{cursor:pointer;}#mermaid-0 .root .anchor path{fill:#c4c4c4!important;stroke-width:0;stroke:#c4c4c4;}#mermaid-0 .arrowheadPath{fill:#f6f5f3;}#mermaid-0 .edgePath .path{stroke:#c4c4c4;stroke-width:1px;}#mermaid-0 .flowchart-link{stroke:#c4c4c4;fill:none;}#mermaid-0 .edgeLabel{background-color:#090a0c;text-align:center;}#mermaid-0 .edgeLabel p{background-color:#090a0c;}#mermaid-0 .edgeLabel rect{opacity:0.5;background-color:#090a0c;fill:#090a0c;}#mermaid-0 .labelBkg{background-color:rgba(9, 10, 12, 0.5);}#mermaid-0 .cluster rect{fill:#121315;stroke:#232325;stroke-width:1px;}#mermaid-0 .cluster text{fill:#f5f5f5;}#mermaid-0 .cluster span{color:#f5f5f5;}#mermaid-0 .node .collapsed-indicator{fill:#232325;stroke:none;opacity:0.6;}#mermaid-0 .node .collapsed-separator{stroke:#232325;stroke-width:0.75px;}#mermaid-0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:&quot;Geist&quot;,sans-serif;font-size:12px;background:#121315;border:1px solid hsl(220, 0%, 17.6470588235%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#f5f5f5;}#mermaid-0 rect.text{fill:none;stroke-width:0;}#mermaid-0 .icon-shape,#mermaid-0 .image-shape{background-color:#090a0c;text-align:center;}#mermaid-0 .icon-shape p,#mermaid-0 .image-shape p{background-color:#090a0c;padding:2px;}#mermaid-0 .icon-shape .label rect,#mermaid-0 .image-shape .label rect{opacity:0.5;background-color:#090a0c;fill:#090a0c;}#mermaid-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-0 .node .neo-node{stroke:#363739;}#mermaid-0 [data-look=&quot;neo&quot;].node rect,#mermaid-0 [data-look=&quot;neo&quot;].cluster rect,#mermaid-0 [data-look=&quot;neo&quot;].node polygon{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].swimlane.cluster rect{filter:none;}#mermaid-0 [data-look=&quot;neo&quot;].node path{stroke:url(#mermaid-0-gradient);stroke-width:1px;}#mermaid-0 [data-look=&quot;neo&quot;].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].node .neo-line path{stroke:#363739;filter:none;}#mermaid-0 [data-look=&quot;neo&quot;].node circle{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].node circle .state-start{fill:#000000;}#mermaid-0 [data-look=&quot;neo&quot;].icon-shape .icon{fill:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].icon-shape .icon-neo path{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 :root{--mermaid-font-family:&quot;Geist&quot;,sans-serif;}&lt;/style&gt;&lt;g&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointEnd&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;5&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;8&quot; markerHeight=&quot;8&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 0 L 10 5 L 0 10 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointStart&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;4.5&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;8&quot; markerHeight=&quot;8&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 5 L 10 10 L 10 0 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointEnd-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 11.5 14&quot; refX=&quot;11.5&quot; refY=&quot;7&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;10.5&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 0 L 11.5 7 L 0 14 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointStart-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 11.5 14&quot; refX=&quot;1&quot; refY=&quot;7&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11.5&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;polygon points=&quot;0,7 11.5,14 11.5,0&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/polygon&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleEnd&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;11&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleStart&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;-1&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleEnd-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refY=&quot;5&quot; refX=&quot;12.25&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;14&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleStart-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;-2&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;14&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossEnd&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 11 11&quot; refX=&quot;12&quot; refY=&quot;5.2&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 l 9,9 M 10,1 l -9,9&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossStart&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 11 11&quot; refX=&quot;-1&quot; refY=&quot;5.2&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 l 9,9 M 10,1 l -9,9&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossEnd-margin&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 15 15&quot; refX=&quot;17.7&quot; refY=&quot;7.5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;12&quot; markerHeight=&quot;12&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 L 14,14 M 1,14 L 14,1&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2.5&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossStart-margin&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 15 15&quot; refX=&quot;-3.5&quot; refY=&quot;7.5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;12&quot; markerHeight=&quot;12&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 L 14,14 M 1,14 L 14,1&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2.5;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;g class=&quot;root&quot;&gt;&lt;g class=&quot;clusters&quot;&gt;&lt;/g&gt;&lt;g class=&quot;edgePaths&quot;&gt;&lt;path d=&quot;M194.914,86L194.914,90.167C194.914,94.333,194.914,102.667,194.914,110.333C194.914,118,194.914,125,194.914,128.5L194.914,132&quot; id=&quot;mermaid-0-L_A_B_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_A_B_0&quot; data-points=&quot;W3sieCI6MTk0LjkxNDA2MjUsInkiOjg2fSx7IngiOjE5NC45MTQwNjI1LCJ5IjoxMTF9LHsieCI6MTk0LjkxNDA2MjUsInkiOjEzNn1d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M145.747,296.457L133.057,310.819C120.367,325.18,94.988,353.902,82.299,392.43C69.609,430.958,69.609,479.292,69.609,503.458L69.609,527.625&quot; id=&quot;mermaid-0-L_B_K1_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_B_K1_0&quot; data-points=&quot;W3sieCI6MTQ1Ljc0NjUxMjkyNTU1MDU4LCJ5IjoyOTYuNDU3NDUwNDI1NTUwNn0seyJ4Ijo2OS42MDkzNzUsInkiOjM4Mi42MjV9LHsieCI6NjkuNjA5Mzc1LCJ5Ijo1MzEuNjI1fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M244.082,296.457L256.771,310.819C269.461,325.18,294.84,353.902,307.529,373.764C320.219,393.625,320.219,404.625,320.219,410.125L320.219,415.625&quot; id=&quot;mermaid-0-L_B_C_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_B_C_0&quot; data-points=&quot;W3sieCI6MjQ0LjA4MTYxMjA3NDQ0OTQyLCJ5IjoyOTYuNDU3NDUwNDI1NTUwNn0seyJ4IjozMjAuMjE4NzUsInkiOjM4Mi42MjV9LHsieCI6MzIwLjIxODc1LCJ5Ijo0MTkuNjI1fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M260.119,637.525L247.792,653.709C235.465,669.892,210.81,702.258,198.483,747.775C186.156,793.292,186.156,851.958,186.156,910.625C186.156,969.292,186.156,1027.958,187.114,1062.802C188.071,1097.645,189.986,1108.664,190.944,1114.174L191.901,1119.684&quot; id=&quot;mermaid-0-L_C_K3_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_C_K3_0&quot; data-points=&quot;W3sieCI6MjYwLjExODk3MTcyOTQ5LCJ5Ijo2MzcuNTI1MjIxNzI5NDl9LHsieCI6MTg2LjE1NjI1LCJ5Ijo3MzQuNjI1fSx7IngiOjE4Ni4xNTYyNSwieSI6OTEwLjYyNX0seyJ4IjoxODYuMTU2MjUsInkiOjEwODYuNjI1fSx7IngiOjE5Mi41ODU5ODg4OTgwMjYzMywieSI6MTEyMy42MjV9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M370.531,647.313L378.786,661.865C387.041,676.417,403.552,705.521,411.807,725.573C420.063,745.625,420.063,756.625,420.063,762.125L420.063,767.625&quot; id=&quot;mermaid-0-L_C_D_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_C_D_0&quot; data-points=&quot;W3sieCI6MzcwLjUzMDg2MDU2OTg0MjUsInkiOjY0Ny4zMTI4ODk0MzAxNTc1fSx7IngiOjQyMC4wNjI1LCJ5Ijo3MzQuNjI1fSx7IngiOjQyMC4wNjI1LCJ5Ijo3NzEuNjI1fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M434.887,1034.8L435.918,1043.438C436.95,1052.075,439.012,1069.35,440.043,1085.488C441.074,1101.625,441.074,1116.625,441.074,1124.125L441.074,1131.625&quot; id=&quot;mermaid-0-L_D_K2_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_D_K2_0&quot; data-points=&quot;W3sieCI6NDM0Ljg4NzE0NTU4MzQyNDIsInkiOjEwMzQuODAwMzU0NDE2NTc1OH0seyJ4Ijo0NDEuMDc0MjE4NzUsInkiOjEwODYuNjI1fSx7IngiOjQ0MS4wNzQyMTg3NSwieSI6MTEzNS42MjV9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M363.473,993.035L352.762,1008.634C342.051,1024.232,320.629,1055.428,302.347,1076.79C284.065,1098.151,268.923,1109.677,261.353,1115.439L253.782,1121.202&quot; id=&quot;mermaid-0-L_D_K3_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_D_K3_0&quot; data-points=&quot;W3sieCI6MzYzLjQ3Mjk3NDM3MzMxNDA2LCJ5Ijo5OTMuMDM1NDc0MzczMzE0MX0seyJ4IjoyOTkuMjA3MDMxMjUsInkiOjEwODYuNjI1fSx7IngiOjI1MC41OTg4ODk4MDI2MzE2LCJ5IjoxMTIzLjYyNX1d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabels&quot;&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_A_B_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(69.609375, 382.625)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_B_K1_0&quot; transform=&quot;translate(-15.609375, -12)&quot;&gt;&lt;foreignObject width=&quot;31.21875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;nein&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(320.21875, 382.625)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_B_C_0&quot; transform=&quot;translate(-6.4140625, -12)&quot;&gt;&lt;foreignObject width=&quot;12.828125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;ja&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(186.15625, 910.625)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_C_K3_0&quot; transform=&quot;translate(-15.609375, -12)&quot;&gt;&lt;foreignObject width=&quot;31.21875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;nein&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(420.0625, 734.625)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_C_D_0&quot; transform=&quot;translate(-6.4140625, -12)&quot;&gt;&lt;foreignObject width=&quot;12.828125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;ja&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(441.07421875, 1086.625)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_D_K2_0&quot; transform=&quot;translate(-15.609375, -12)&quot;&gt;&lt;foreignObject width=&quot;31.21875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;nein&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(314.04997, 1065.00945)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_D_K3_0&quot; transform=&quot;translate(-6.4140625, -12)&quot;&gt;&lt;foreignObject width=&quot;12.828125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;ja&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;nodes&quot;&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-A-0&quot; data-look=&quot;classic&quot; transform=&quot;translate(194.9140625, 47)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Agent soll eingesetzt werden&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-B-1&quot; data-look=&quot;classic&quot; transform=&quot;translate(194.9140625, 240.8125)&quot;&gt;&lt;polygon points=&quot;104.8125,0 209.625,-104.8125 104.8125,-209.625 0,-104.8125&quot; class=&quot;label-container&quot; transform=&quot;translate(-104.3125, 104.8125)&quot;&gt;&lt;/polygon&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-77.8125, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;155.625&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Führt er Befehle aus?&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-K1-3&quot; data-look=&quot;classic&quot; transform=&quot;translate(69.609375, 558.625)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-61.609375&quot; y=&quot;-27&quot; width=&quot;123.21875&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-31.609375, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;63.21875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Klasse A&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-C-5&quot; data-look=&quot;classic&quot; transform=&quot;translate(320.21875, 558.625)&quot;&gt;&lt;polygon points=&quot;139,0 278,-139 139,-278 0,-139&quot; class=&quot;label-container&quot; transform=&quot;translate(-138.5, 139)&quot;&gt;&lt;/polygon&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Läuft er in Container oder VM?&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-K3-7&quot; data-look=&quot;classic&quot; transform=&quot;translate(199.36328125, 1162.625)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Klasse C: dedizierte Maschine oder Nein&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-D-9&quot; data-look=&quot;classic&quot; transform=&quot;translate(420.0625, 910.625)&quot;&gt;&lt;polygon points=&quot;139,0 278,-139 139,-278 0,-139&quot; class=&quot;label-container&quot; transform=&quot;translate(-138.5, 139)&quot;&gt;&lt;/polygon&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Sieht er mehr als ein Repository?&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-K2-11&quot; data-look=&quot;classic&quot; transform=&quot;translate(441.07421875, 1162.625)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-61.7109375&quot; y=&quot;-27&quot; width=&quot;123.421875&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-31.7109375, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;63.421875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Klasse B&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;defs&gt;&lt;filter id=&quot;mermaid-0-drop-shadow&quot; height=&quot;130%&quot; width=&quot;130%&quot;&gt;&lt;feDropShadow dx=&quot;4&quot; dy=&quot;4&quot; stdDeviation=&quot;0&quot; flood-opacity=&quot;0.06&quot; flood-color=&quot;#000000&quot;&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;defs&gt;&lt;filter id=&quot;mermaid-0-drop-shadow-small&quot; height=&quot;150%&quot; width=&quot;150%&quot;&gt;&lt;feDropShadow dx=&quot;2&quot; dy=&quot;2&quot; stdDeviation=&quot;0&quot; flood-opacity=&quot;0.06&quot; flood-color=&quot;#000000&quot;&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;linearGradient id=&quot;mermaid-0-gradient&quot; gradientUnits=&quot;objectBoundingBox&quot; x1=&quot;0%&quot; y1=&quot;0%&quot; x2=&quot;100%&quot; y2=&quot;0%&quot;&gt;&lt;stop offset=&quot;0%&quot; stop-color=&quot;#363739&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;&lt;stop offset=&quot;100%&quot; stop-color=&quot;hsl(220, 0%, 17.6470588235%)&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;&lt;/linearGradient&gt;&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;Für Klasse B lässt sich der Rahmen konfigurativ festhalten. OpenClaw kennt dafür eine restriktive Grundhaltung, die als Vorgabe taugt, Gateway nur auf Loopback, Ausführung standardmässig verweigert:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json5&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  gateway&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    mode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;local&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    bind&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;loopback&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    auth&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;mode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;token&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;token&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&amp;lt;langes-zufaelliges-token&amp;gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  tools&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    deny&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;group:automation&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;group:runtime&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;gateway&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;cron&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    exec&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;deny&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ask&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;always&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  agents&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    defaults&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      sandbox&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;mode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;scope&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;agent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      workspaceAccess&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;ro&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die Datei selbst gehört abgeriegelt, &lt;code&gt;~/.openclaw&lt;/code&gt; auf 700 und &lt;code&gt;~/.openclaw/openclaw.json&lt;/code&gt; auf 600. Das Projekt liefert dafür eine Prüfung mit, die auch Konfigurationsdrift findet:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;openclaw&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; security&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; audit&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --deep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;openclaw&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; security&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; audit&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --fix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;wie-sie-den-einsatz-erkennen-ohne-jemanden-zu-jagen&quot;&gt;Wie Sie den Einsatz erkennen, ohne jemanden zu jagen&lt;/h2&gt;
&lt;p&gt;Erkennung heisst hier Inventar, nicht Überwachung: Sie fragen die Maschine, nicht die Kollegin. Drei Signale reichen für eine erste Runde, und alle drei lassen sich in einem Onboarding-Skript oder im MDM-Check unterbringen.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 1. Global installierte Agenten-Pakete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ls&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -g&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --depth=0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; 2&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/dev/null&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -Ei&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;openclaw|opencode|codex|claude-code&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 2. Konfigurationsverzeichnisse dauerhaft laufender Agenten&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ls&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -ld&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ~/.openclaw&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ~/.claude&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ~/.codex&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; 2&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/dev/null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 3. Der OpenClaw-Gateway lauscht per Vorgabe auf 127.0.0.1:18789&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;lsof&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -nP&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -iTCP:18789&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -sTCP:LISTEN&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; 2&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/dev/null&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der zweite Teil betrifft nicht die Rechner, sondern die Repositories. Ein Agent sieht alles, was das Arbeitsverzeichnis hergibt, und das ist regelmässig mehr als gedacht:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ls-files&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; wc&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -l&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -nIE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;(api[_-]?key|secret|BEGIN [A-Z ]*PRIVATE KEY)&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;:!*_test*&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; head&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn diese zweite Abfrage etwas findet, ist das Agenten-Thema nachrangig. Dann haben Sie ein Secret-Management-Problem, das jeden Klon des Repositories betrifft.&lt;/p&gt;
&lt;h2 id=&quot;werkzeugbindung-ist-das-zweite-leisere-risiko&quot;&gt;Werkzeugbindung ist das zweite, leisere Risiko&lt;/h2&gt;
&lt;p&gt;Wer Governance nur als Sicherheitsfrage denkt, übersieht die Konsolidierung im Markt. Windsurf existiert als eigene Marke nicht mehr: &lt;code&gt;windsurf.com&lt;/code&gt; antwortet am 20.08.2026 mit HTTP 308 auf &lt;code&gt;devin.ai/desktop&lt;/code&gt;, geprüft mit einem einfachen Redirect-Check. Cursor baut mit «Origin» seit dem 17.08.2026 eigenes Code-Hosting samt Repositories und Pull Requests, laut Changelog in offener Beta für alle zahlenden Pläne, mit einer Opt-out-Möglichkeit für Enterprise-Administratoren.&lt;/p&gt;
&lt;p&gt;Die Nutzungsanteile verschieben sich im gleichen Tempo. Die &lt;a href=&quot;https://blog.jetbrains.com/research/2026/08/ai-coding-agent-adoption-2026/&quot;&gt;JetBrains Developer Ecosystem Survey 2026&lt;/a&gt; mit über 15’000 Befragten, erhoben von Mai bis Juli 2026, misst eine Umverteilung innerhalb weniger Monate. Zu beachten: JetBrains ist im selben Markt tätig und damit kein neutraler Erheber.&lt;/p&gt;






























&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Werkzeug&lt;/th&gt;&lt;th&gt;Vorher&lt;/th&gt;&lt;th&gt;Erhebung Mai bis Juli 2026&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Claude Code&lt;/td&gt;&lt;td&gt;18 %&lt;/td&gt;&lt;td&gt;39 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GitHub Copilot&lt;/td&gt;&lt;td&gt;29 %&lt;/td&gt;&lt;td&gt;21 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Codex&lt;/td&gt;&lt;td&gt;3 %&lt;/td&gt;&lt;td&gt;16 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Cursor&lt;/td&gt;&lt;td&gt;18 %&lt;/td&gt;&lt;td&gt;12 %&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Ein Werkzeug, das binnen zwei Quartalen ein Drittel seiner Nutzerschaft abgibt oder verdoppelt, ist keine Plattformentscheidung, sondern eine Momentaufnahme. Bindend sollte deshalb nicht das Werkzeug sein, sondern das, was den Wechsel überlebt.&lt;/p&gt;
&lt;p&gt;Portabel sind heute drei Dinge: das Model Context Protocol in der Spezifikationsversion vom 28.07.2026, das Format &lt;code&gt;AGENTS.md&lt;/code&gt;, das laut agents.md über 60’000 Open-Source-Projekte nutzen und das unter dem Dach der Linux Foundation gepflegt wird, sowie A2A in Version 1.0, ebenfalls an die Linux Foundation übergeben.&lt;/p&gt;
&lt;p&gt;Wer seine Projektkonventionen dort ablegt statt in werkzeugeigenen Einstellungen, wechselt das Werkzeug ohne Migrationsprojekt. Wie ein eigener MCP-Server dabei aussieht, haben wir in &lt;a href=&quot;https://devs-group.ch/blog/mcp-server-in-go-produktiv-betreiben/&quot;&gt;MCP-Server in Go produktiv betreiben&lt;/a&gt; beschrieben.&lt;/p&gt;
&lt;p&gt;Die MCP-Spezifikation ist in der Sicherheitsfrage bemerkenswert deutlich: Tool-Beschreibungen und Annotationen seien als nicht vertrauenswürdig zu behandeln, sofern sie nicht von einem vertrauenswürdigen Server stammen. Zugleich hält sie fest, dass das Protokoll diese Prinzipien nicht erzwingen kann. Die Absicherung liegt beim Host, also bei Ihnen.&lt;/p&gt;
&lt;h2 id=&quot;was-in-die-richtlinie-gehört-und-wovon-wir-abraten&quot;&gt;Was in die Richtlinie gehört, und wovon wir abraten&lt;/h2&gt;
&lt;p&gt;Eine Agenten-Richtlinie passt auf zwei Seiten. Länger wird sie nur gelesen, wenn ein Audit ansteht.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Positivliste mit Version&lt;/strong&gt;, nicht nur mit Produktnamen. OpenClaw fährt seit dem 30.07.2026 einen Extended-Stable-Kanal, die erste solche Ausgabe ist 2026.6.33. Freigegeben wird ein Kanal, nicht «das Tool».&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rechteklasse pro Einsatz&lt;/strong&gt;, nach der Tabelle oben, dokumentiert mit einem Satz Begründung.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ausgehende Ziele benannt.&lt;/strong&gt; Welche Modellanbieter, welche MCP-Server. GitHub führte am 06.08.2026 MCP-Allowlists in den Enterprise-Einstellungen ein, das ist der richtige Hebel.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Private Abos sind kein Firmenzugang.&lt;/strong&gt; Nicht weil das Werkzeug damit nicht liefe, sondern weil der Vertrag ein anderer ist: Free, Pro und Max laufen unter Consumer-Bedingungen, bei denen die Trainingsnutzung an einer persönlichen Kontoeinstellung hängt, die der Arbeitgeber weder sieht noch steuert. Anthropic beschreibt das ausdrücklich für die Nutzung von Claude Code aus solchen Konten. Welche Tarif- und Bezugswege es stattdessen gibt, steht in &lt;a href=&quot;https://devs-group.ch/blog/coding-agenten-datenschutzkonform-nutzen/&quot;&gt;Coding-Agenten datenschutzkonform nutzen&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ein Meldeweg ohne Konsequenz.&lt;/strong&gt; Wer einen bisher nicht freigegebenen Agenten meldet, bekommt eine Klasse zugewiesen, keine Rüge.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wovon wir abraten: von einem Verbot. Ein Verbot erzeugt besser verstecktes Schatten-IT und kostet Sie genau die Information, die Sie brauchen.&lt;/p&gt;
&lt;p&gt;Ebenso raten wir davon ab, den Agenten seine eigene Arbeit abnehmen zu lassen. Review, Tests und Merge-Gate bleiben ausserhalb des Agenten, sonst prüft sich das System selbst. Warum das architektonisch zählt, steht in &lt;a href=&quot;https://devs-group.ch/blog/ki-code-ohne-technische-schulden/&quot;&gt;KI schreibt den Code. Wer schreibt die Architektur?&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Wann unsere Empfehlung nicht passt: In einem Zweipersonen-Team mit einem einzigen Repository ohne Personendaten ist die Rechteklassen-Matrix Overhead. Dort genügt eine gepflegte Liste im README und die Regel, dass kein Agent ohne Container Befehle ausführt.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;ist-openclaw-für-firmen-grundsätzlich-ungeeignet&quot;&gt;Ist OpenClaw für Firmen grundsätzlich ungeeignet?&lt;/h3&gt;
&lt;p&gt;Nein. OpenClaw ist ein technisch beeindruckendes Projekt mit einer offenen Sicherheitskommunikation, das seine Grenzen selbst benennt. Ungeeignet ist das Betriebsmodell auf einem Arbeitsgerät mit Kundencode: lokal, weitreichend berechtigt, über Consumer-Chat-Apps gesteuert. Auf einer dedizierten Maschine mit eigenem Betriebssystem-Konto, Loopback-Bindung und restriktiver Tool-Policy ist ein sanktionierter Einsatz möglich.&lt;/p&gt;
&lt;h3 id=&quot;woran-erkenne-ich-ob-ein-agent-personendaten-an-ein-modell-geschickt-hat&quot;&gt;Woran erkenne ich, ob ein Agent Personendaten an ein Modell geschickt hat?&lt;/h3&gt;
&lt;p&gt;Am ausgehenden Verkehr und an der Agenten-Sitzung, nicht am Repository. Praktikabel ist der umgekehrte Weg: Sie prüfen, welche Verzeichnisse der Agent lesen durfte, und behandeln alles darin als bekanntgegeben. Deshalb steht in Klasse B &lt;code&gt;workspaceAccess: &amp;quot;ro&amp;quot;&lt;/code&gt; und ein einzelnes Repository. Weniger Sichtbarkeit macht die datenschutzrechtliche Beurteilung nach Art. 16 revDSG erst führbar.&lt;/p&gt;
&lt;h3 id=&quot;reicht-ein-container-als-absicherung&quot;&gt;Reicht ein Container als Absicherung?&lt;/h3&gt;
&lt;p&gt;Ein Container begrenzt den Schaden, er verhindert ihn nicht. Er schützt das Dateisystem des Hosts und trennt Agenten voneinander, ändert aber nichts daran, welche Daten der Agent im Container sieht und wohin er sie sendet. Container plus enge Tool-Policy plus benannte ausgehende Ziele wirken zusammen. Einzeln wirkt keines der drei.&lt;/p&gt;
&lt;h3 id=&quot;was-tun-wir-mit-einem-agenten-der-seit-monaten-unbemerkt-läuft&quot;&gt;Was tun wir mit einem Agenten, der seit Monaten unbemerkt läuft?&lt;/h3&gt;
&lt;p&gt;Erst inventarisieren, dann einordnen, dann entscheiden. Version prüfen, insbesondere gegen CVE-2026-33579 und die Grenze 2026.3.28, Rechte und Zugriffsumfang festhalten, Secrets rotieren, die in seiner Reichweite lagen. Erst danach die Frage nach Weiterbetrieb oder Abschaltung stellen. Ein sofortiges Abschalten vernichtet die Information darüber, was der Agent überhaupt getan hat.&lt;/p&gt;
&lt;h2 id=&quot;der-nächste-schritt&quot;&gt;Der nächste Schritt&lt;/h2&gt;
&lt;p&gt;Nehmen Sie sich 30 Minuten mit einem unserer Engineers, ohne Verkaufsgespräch: Wir gehen Ihre Werkzeugliste durch, ordnen jeden Eintrag einer Rechteklasse zu und benennen die Stellen, an denen revDSG-Pflichten berührt sind. &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin buchen&lt;/a&gt; oder formlos über &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt&lt;/a&gt;, beides führt zur selben Person.&lt;/p&gt;
&lt;p&gt;Wenn daraus mehr wird als eine Richtlinie, etwa ein Agent, der in Ihrer Umgebung sauber abgegrenzt laufen soll, ist das unser Tagesgeschäft unter &lt;a href=&quot;https://devs-group.ch/leistungen/kuenstliche-intelligenz/&quot;&gt;Künstliche Intelligenz &amp;amp; Machine Learning&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>KI-gestützte Entwicklung</category><author>Robert Pupel</author></item><item><title>Guardrails für Coding-Agenten: nie der eigene Prüfer</title><link>https://devs-group.ch/blog/guardrails-fuer-coding-agenten/</link><guid isPermaLink="true">https://devs-group.ch/blog/guardrails-fuer-coding-agenten/</guid><description>Review-Tiefe nach Aufgabentyp staffeln statt nach Agenten-Confidence. Was in die CI-Pipeline gehört und was ein Mensch lesen muss.</description><pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ein Coding-Agent darf seine eigene Arbeit nicht abnehmen. Die Prüfung gehört in eine Instanz, die er nicht steuert: deterministische Gates in der CI und ein Mensch, der bei Eingriffen in bestehenden Code das ganze Diff liest. Wie tief geprüft wird, bestimmt der Aufgabentyp, nicht der Confidence-Wert des Agenten.&lt;/p&gt;
&lt;p&gt;Robert Pupel hat in &lt;a href=&quot;https://devs-group.ch/blog/ki-code-ohne-technische-schulden/&quot;&gt;KI schreibt den Code. Wer schreibt die Architektur?&lt;/a&gt; drei Regeln formuliert, die bei uns gelten. Dieser Beitrag beschreibt die Mechanik darunter: welche Gates in der Pipeline stehen, was sie auslöst und wo ein Mensch nicht ersetzbar ist. Guardrails für Coding-Agenten sind kein Prozessdokument, sondern Code im Repository.&lt;/p&gt;
&lt;h2 id=&quot;drei-quellen-die-unabhängig-zum-selben-schluss-kommen&quot;&gt;Drei Quellen, die unabhängig zum selben Schluss kommen&lt;/h2&gt;
&lt;p&gt;Forschung, Beratung und Praxis kamen 2026 aus verschiedenen Richtungen zur selben Regel: Ein Agent darf nicht sein eigener Prüfer sein.&lt;/p&gt;
&lt;p&gt;Der &lt;a href=&quot;https://www.thoughtworks.com/radar&quot;&gt;Thoughtworks Technology Radar Vol. 34&lt;/a&gt; vom April 2026 führt „Putting coding agents on a leash” als eines von vier Themen. Die Begründung dort: Weil Agenten bessere Ergebnisse liefern, steigen Menschen zunehmend aus der Schleife aus, und Teams beginnen deshalb, in Harnesses zu investieren. Thoughtworks ist eine Beratungsfirma, die KI-Transformationsprojekte verkauft, und deklariert den Radar selbst als Praktikermeinung, nicht als Empirie.&lt;/p&gt;
&lt;p&gt;Octomind, Anbieter eines Testwerkzeugs, hat im August 2026 die Selbstverifikation aus dem eigenen Agenten &lt;a href=&quot;https://octomind.run/blog/octomind-0-44-2-release&quot;&gt;entfernt&lt;/a&gt;. Der Satz aus dem Release, der das Problem präzise trifft: „a model that wants to be done has a way to &lt;em&gt;look&lt;/em&gt; done: advance the checklist, mark tasks complete, close the plan.” Ein externer Plan-Manager besitzt seither den Fortschritt, der Agent hat auf das Werkzeug keinen Zugriff mehr. Das ist eine Selbstauskunft eines Anbieters, aber eine mit nachvollziehbarer Mechanik.&lt;/p&gt;
&lt;p&gt;Die dritte Quelle ist die interessanteste, weil sie zählbar ist.&lt;/p&gt;
&lt;h2 id=&quot;was-932791-agentenerzeugte-pull-requests-zeigen&quot;&gt;Was 932’791 agentenerzeugte Pull Requests zeigen&lt;/h2&gt;
&lt;p&gt;Seit Februar 2026 existiert eine belastbare Datenbasis für Aussagen über Coding-Agenten. Der Datensatz &lt;strong&gt;AIDev&lt;/strong&gt; (Li, Zhang, Hassan, &lt;a href=&quot;https://arxiv.org/abs/2602.09185&quot;&gt;arXiv:2602.09185&lt;/a&gt;) sammelt 932’791 agentenerzeugte Pull Requests aus 116’211 Repositories von 72’189 Entwickelnden, erzeugt von fünf Agenten: OpenAI Codex, Devin, GitHub Copilot, Cursor und Claude Code. Offen, akademisch, ohne ausgewiesene Anbieterfinanzierung.&lt;/p&gt;
&lt;p&gt;Darauf aufbauend haben Ferdous, Banik, Chowdhury und Shamim 7’191 agentenerzeugte gegen 1’402 menschliche Pull Requests aus Python-Repositories verglichen und Breaking Changes über eine AST-Analyse erkannt (&lt;a href=&quot;https://arxiv.org/abs/2603.27524&quot;&gt;arXiv:2603.27524&lt;/a&gt;, eingereicht am 29.03.2026). Das Ergebnis ist kontraintuitiv:&lt;/p&gt;

























&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Kontext&lt;/th&gt;&lt;th&gt;Breaking-Change-Rate&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Neubau, &lt;strong&gt;Agenten&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;3,45 %&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Neubau, &lt;strong&gt;Menschen&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;7,40 %&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Agenten bei &lt;strong&gt;Refactoring&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;6,72 %&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Agenten bei &lt;strong&gt;Chore-Änderungen&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;9,35 %&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Auf der grünen Wiese brechen Agenten die Kompatibilität also seltener als Menschen. Sobald sie bestehenden Code anfassen, kehrt sich das Bild um. Genau umgekehrt zu dem, was die meisten Teams intuitiv absichern.&lt;/p&gt;
&lt;h2 id=&quot;die-confidence-trap-warum-der-selbstvertrauens-wert-als-filter-ausfällt&quot;&gt;Die Confidence Trap: warum der Selbstvertrauens-Wert als Filter ausfällt&lt;/h2&gt;
&lt;p&gt;Ein hoher Confidence-Wert des Agenten sagt nichts darüber, ob der Pull Request kompatibel bleibt. Dieselbe Arbeit von Ferdous et al. benennt das als „Confidence Trap”: Pull Requests mit hohem Selbstvertrauens-Wert enthalten trotzdem Breaking Changes. Die Autoren leiten daraus wörtlich die Notwendigkeit strengerer Prüfung bei Wartungsarbeiten ab, „regardless of reported confidence score”.&lt;/p&gt;
&lt;p&gt;Das ist die praktisch wichtigste Zahl des Jahres, weil sie einen verbreiteten Kurzschluss zerstört. Wer Merge-Gates an einer Selbsteinschätzung aufhängt, hat den Agenten zum Prüfer seiner selbst gemacht, nur mit mehr Schritten.&lt;/p&gt;
&lt;p&gt;Wenn Sie gerade einen Agenten auf ein bestehendes Go-Backend loslassen und nicht sicher sind, welche Gates dafür stehen müssen: Das ist ein 30-Minuten-Gespräch, kein Projekt. Wir schauen uns die Pipeline an, die Sie haben, und sagen, was fehlt.&lt;/p&gt;
&lt;h2 id=&quot;review-tiefe-nach-aufgabentyp-nicht-nach-confidence&quot;&gt;Review-Tiefe nach Aufgabentyp, nicht nach Confidence&lt;/h2&gt;
&lt;p&gt;Die Ableitung aus den Daten ist eine Matrix mit zwei Spuren. Sie ersetzt die Frage „wie sicher ist sich der Agent?” durch die Frage „was fasst dieser Pull Request an?”.&lt;/p&gt;



































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Aufgabentyp&lt;/th&gt;&lt;th&gt;Belegte Rate&lt;/th&gt;&lt;th&gt;Automatische Gates&lt;/th&gt;&lt;th&gt;Menschliche Prüfung&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Neubau&lt;/strong&gt;, neue Dateien, kein bestehender Code berührt&lt;/td&gt;&lt;td&gt;3,45 %&lt;/td&gt;&lt;td&gt;Build, Tests, &lt;code&gt;govulncheck&lt;/code&gt;, Lint, Coverage-Schwelle&lt;/td&gt;&lt;td&gt;Schnittstelle und Datenmodell lesen, nicht jede Zeile&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Refactoring&lt;/strong&gt; an bestehendem Code&lt;/td&gt;&lt;td&gt;6,72 %&lt;/td&gt;&lt;td&gt;zusätzlich &lt;code&gt;gorelease&lt;/code&gt; gegen den letzten Tag, gerenderter Manifest-Diff&lt;/td&gt;&lt;td&gt;vollständiges Diff, zweites Augenpaar&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Chore&lt;/strong&gt;, Abhängigkeiten, Build, Konfiguration&lt;/td&gt;&lt;td&gt;9,35 %&lt;/td&gt;&lt;td&gt;zusätzlich Lockfile-Diff, Image-Digest-Pinning, Manifest-Diff&lt;/td&gt;&lt;td&gt;vollständiges Diff, zweites Augenpaar&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Bearbeitung von Personendaten&lt;/strong&gt; berührt&lt;/td&gt;&lt;td&gt;keine&lt;/td&gt;&lt;td&gt;alles oben&lt;/td&gt;&lt;td&gt;Pflicht, unabhängig vom Aufgabentyp&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Die letzte Zeile ist kein Datenbefund, sondern Schweizer Recht. Art. 7 DSG verlangt Datenschutz durch Technik ab der Planung, Art. 2 DSV nennt Nachvollziehbarkeit als eines von vier Schutzzielen. Ein Merge, den niemand namentlich abgenommen hat, erfüllt das nicht. Was das für die Architektur bedeutet, steht in &lt;a href=&quot;https://devs-group.ch/blog/revdsg-konforme-ki-architektur/&quot;&gt;revDSG-konforme KI-Architektur&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;wie-die-zwei-spuren-in-einer-ci-pipeline-aussehen&quot;&gt;Wie die zwei Spuren in einer CI-Pipeline aussehen&lt;/h2&gt;
&lt;p&gt;Die Zuordnung zur Spur muss deterministisch und ausserhalb der Reichweite des Agenten passieren. Sie darf nicht davon abhängen, wie der Agent seinen Pull Request betitelt.&lt;/p&gt;
&lt;div class=&quot;scroll-x scroll-x--diagram&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Diagramm, seitlich scrollbar&quot;&gt;&lt;svg id=&quot;mermaid-0&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot; class=&quot;flowchart&quot; style=&quot;width:586px&quot; viewBox=&quot;0 0 586 926.078125&quot; role=&quot;graphics-document document&quot; aria-roledescription=&quot;flowchart-v2&quot;&gt;&lt;style&gt;#mermaid-0{font-family:&quot;Geist&quot;,sans-serif;font-size:16px;fill:#f5f5f5;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-0 .error-icon{fill:#121315;}#mermaid-0 .error-text{fill:#edecea;stroke:#edecea;}#mermaid-0 .edge-thickness-normal{stroke-width:1px;}#mermaid-0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-0 .marker{fill:#c4c4c4;stroke:#c4c4c4;}#mermaid-0 .marker.cross{stroke:#c4c4c4;}#mermaid-0 svg{font-family:&quot;Geist&quot;,sans-serif;font-size:16px;}#mermaid-0 p{margin:0;}#mermaid-0 .label{font-family:&quot;Geist&quot;,sans-serif;color:#f5f5f5;}#mermaid-0 .cluster-label text{fill:#f5f5f5;}#mermaid-0 .cluster-label span{color:#f5f5f5;}#mermaid-0 .cluster-label span p{background-color:transparent;}#mermaid-0 .label text,#mermaid-0 span{fill:#f5f5f5;color:#f5f5f5;}#mermaid-0 .node rect,#mermaid-0 .node circle,#mermaid-0 .node ellipse,#mermaid-0 .node polygon,#mermaid-0 .node path{fill:#1b1d20;stroke:#363739;stroke-width:1px;}#mermaid-0 .rough-node .label text,#mermaid-0 .node .label text,#mermaid-0 .image-shape .label,#mermaid-0 .icon-shape .label{text-anchor:middle;}#mermaid-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-0 .rough-node .label,#mermaid-0 .node .label,#mermaid-0 .image-shape .label,#mermaid-0 .icon-shape .label{text-align:center;}#mermaid-0 .node.clickable{cursor:pointer;}#mermaid-0 .root .anchor path{fill:#c4c4c4!important;stroke-width:0;stroke:#c4c4c4;}#mermaid-0 .arrowheadPath{fill:#f6f5f3;}#mermaid-0 .edgePath .path{stroke:#c4c4c4;stroke-width:1px;}#mermaid-0 .flowchart-link{stroke:#c4c4c4;fill:none;}#mermaid-0 .edgeLabel{background-color:#090a0c;text-align:center;}#mermaid-0 .edgeLabel p{background-color:#090a0c;}#mermaid-0 .edgeLabel rect{opacity:0.5;background-color:#090a0c;fill:#090a0c;}#mermaid-0 .labelBkg{background-color:rgba(9, 10, 12, 0.5);}#mermaid-0 .cluster rect{fill:#121315;stroke:#232325;stroke-width:1px;}#mermaid-0 .cluster text{fill:#f5f5f5;}#mermaid-0 .cluster span{color:#f5f5f5;}#mermaid-0 .node .collapsed-indicator{fill:#232325;stroke:none;opacity:0.6;}#mermaid-0 .node .collapsed-separator{stroke:#232325;stroke-width:0.75px;}#mermaid-0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:&quot;Geist&quot;,sans-serif;font-size:12px;background:#121315;border:1px solid hsl(220, 0%, 17.6470588235%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#f5f5f5;}#mermaid-0 rect.text{fill:none;stroke-width:0;}#mermaid-0 .icon-shape,#mermaid-0 .image-shape{background-color:#090a0c;text-align:center;}#mermaid-0 .icon-shape p,#mermaid-0 .image-shape p{background-color:#090a0c;padding:2px;}#mermaid-0 .icon-shape .label rect,#mermaid-0 .image-shape .label rect{opacity:0.5;background-color:#090a0c;fill:#090a0c;}#mermaid-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-0 .node .neo-node{stroke:#363739;}#mermaid-0 [data-look=&quot;neo&quot;].node rect,#mermaid-0 [data-look=&quot;neo&quot;].cluster rect,#mermaid-0 [data-look=&quot;neo&quot;].node polygon{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].swimlane.cluster rect{filter:none;}#mermaid-0 [data-look=&quot;neo&quot;].node path{stroke:url(#mermaid-0-gradient);stroke-width:1px;}#mermaid-0 [data-look=&quot;neo&quot;].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].node .neo-line path{stroke:#363739;filter:none;}#mermaid-0 [data-look=&quot;neo&quot;].node circle{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].node circle .state-start{fill:#000000;}#mermaid-0 [data-look=&quot;neo&quot;].icon-shape .icon{fill:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].icon-shape .icon-neo path{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 :root{--mermaid-font-family:&quot;Geist&quot;,sans-serif;}&lt;/style&gt;&lt;g&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointEnd&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;5&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;8&quot; markerHeight=&quot;8&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 0 L 10 5 L 0 10 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointStart&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;4.5&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;8&quot; markerHeight=&quot;8&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 5 L 10 10 L 10 0 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointEnd-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 11.5 14&quot; refX=&quot;11.5&quot; refY=&quot;7&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;10.5&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 0 L 11.5 7 L 0 14 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointStart-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 11.5 14&quot; refX=&quot;1&quot; refY=&quot;7&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11.5&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;polygon points=&quot;0,7 11.5,14 11.5,0&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/polygon&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleEnd&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;11&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleStart&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;-1&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleEnd-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refY=&quot;5&quot; refX=&quot;12.25&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;14&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleStart-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;-2&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;14&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossEnd&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 11 11&quot; refX=&quot;12&quot; refY=&quot;5.2&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 l 9,9 M 10,1 l -9,9&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossStart&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 11 11&quot; refX=&quot;-1&quot; refY=&quot;5.2&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 l 9,9 M 10,1 l -9,9&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossEnd-margin&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 15 15&quot; refX=&quot;17.7&quot; refY=&quot;7.5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;12&quot; markerHeight=&quot;12&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 L 14,14 M 1,14 L 14,1&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2.5&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossStart-margin&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 15 15&quot; refX=&quot;-3.5&quot; refY=&quot;7.5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;12&quot; markerHeight=&quot;12&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 L 14,14 M 1,14 L 14,1&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2.5;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;g class=&quot;root&quot;&gt;&lt;g class=&quot;clusters&quot;&gt;&lt;/g&gt;&lt;g class=&quot;edgePaths&quot;&gt;&lt;path d=&quot;M293,62L293,66.167C293,70.333,293,78.667,293,86.333C293,94,293,101,293,104.5L293,108&quot; id=&quot;mermaid-0-L_PR_K_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_PR_K_0&quot; data-points=&quot;W3sieCI6MjkzLCJ5Ijo2Mn0seyJ4IjoyOTMsInkiOjg3fSx7IngiOjI5MywieSI6MTEyfV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M237.519,270.597L220.932,286.01C204.346,301.424,171.173,332.251,154.586,358.331C138,384.411,138,405.745,138,425.078C138,444.411,138,461.745,138,473.911C138,486.078,138,493.078,138,496.578L138,500.078&quot; id=&quot;mermaid-0-L_K_N_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_K_N_0&quot; data-points=&quot;W3sieCI6MjM3LjUxODc3MTA2MzU2Mjk4LCJ5IjoyNzAuNTk2ODk2MDYzNTYyOTV9LHsieCI6MTM4LCJ5IjozNjMuMDc4MTI1fSx7IngiOjEzOCwieSI6NDI3LjA3ODEyNX0seyJ4IjoxMzgsInkiOjQ3OS4wNzgxMjV9LHsieCI6MTM4LCJ5Ijo1MDQuMDc4MTI1fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M348.481,270.597L365.068,286.01C381.654,301.424,414.827,332.251,431.414,353.165C448,374.078,448,385.078,448,390.578L448,396.078&quot; id=&quot;mermaid-0-L_K_B_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_K_B_0&quot; data-points=&quot;W3sieCI6MzQ4LjQ4MTIyODkzNjQzNzA1LCJ5IjoyNzAuNTk2ODk2MDYzNTYyOTV9LHsieCI6NDQ4LCJ5IjozNjMuMDc4MTI1fSx7IngiOjQ0OCwieSI6NDAwLjA3ODEyNX1d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M138,558.078L138,562.245C138,566.411,138,574.745,138,584.411C138,594.078,138,605.078,138,610.578L138,616.078&quot; id=&quot;mermaid-0-L_N_A1_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_N_A1_0&quot; data-points=&quot;W3sieCI6MTM4LCJ5Ijo1NTguMDc4MTI1fSx7IngiOjEzOCwieSI6NTgzLjA3ODEyNX0seyJ4IjoxMzgsInkiOjYyMC4wNzgxMjV9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M448,454.078L448,458.245C448,462.411,448,470.745,448,478.411C448,486.078,448,493.078,448,496.578L448,500.078&quot; id=&quot;mermaid-0-L_B_A2_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_B_A2_0&quot; data-points=&quot;W3sieCI6NDQ4LCJ5Ijo0NTQuMDc4MTI1fSx7IngiOjQ0OCwieSI6NDc5LjA3ODEyNX0seyJ4Ijo0NDgsInkiOjUwNC4wNzgxMjV9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M448,558.078L448,562.245C448,566.411,448,574.745,448,582.411C448,590.078,448,597.078,448,600.578L448,604.078&quot; id=&quot;mermaid-0-L_A2_A3_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_A2_A3_0&quot; data-points=&quot;W3sieCI6NDQ4LCJ5Ijo1NTguMDc4MTI1fSx7IngiOjQ0OCwieSI6NTgzLjA3ODEyNX0seyJ4Ijo0NDgsInkiOjYwOC4wNzgxMjV9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M138,674.078L138,680.245C138,686.411,138,698.745,138,708.411C138,718.078,138,725.078,138,728.578L138,732.078&quot; id=&quot;mermaid-0-L_A1_M1_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_A1_M1_0&quot; data-points=&quot;W3sieCI6MTM4LCJ5Ijo2NzQuMDc4MTI1fSx7IngiOjEzOCwieSI6NzExLjA3ODEyNX0seyJ4IjoxMzgsInkiOjczNi4wNzgxMjV9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M448,686.078L448,690.245C448,694.411,448,702.745,448,710.411C448,718.078,448,725.078,448,728.578L448,732.078&quot; id=&quot;mermaid-0-L_A3_M2_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_A3_M2_0&quot; data-points=&quot;W3sieCI6NDQ4LCJ5Ijo2ODYuMDc4MTI1fSx7IngiOjQ0OCwieSI6NzExLjA3ODEyNX0seyJ4Ijo0NDgsInkiOjczNi4wNzgxMjV9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M138,814.078L138,818.245C138,822.411,138,830.745,154.331,840.39C170.663,850.036,203.326,860.994,219.657,866.473L235.989,871.952&quot; id=&quot;mermaid-0-L_M1_MG_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_M1_MG_0&quot; data-points=&quot;W3sieCI6MTM4LCJ5Ijo4MTQuMDc4MTI1fSx7IngiOjEzOCwieSI6ODM5LjA3ODEyNX0seyJ4IjoyMzkuNzgxMjUsInkiOjg3My4yMjQwOTI3NDE5MzU1fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M448,814.078L448,818.245C448,822.411,448,830.745,431.669,840.39C415.337,850.036,382.674,860.994,366.343,866.473L350.011,871.952&quot; id=&quot;mermaid-0-L_M2_MG_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_M2_MG_0&quot; data-points=&quot;W3sieCI6NDQ4LCJ5Ijo4MTQuMDc4MTI1fSx7IngiOjQ0OCwieSI6ODM5LjA3ODEyNX0seyJ4IjozNDYuMjE4NzUsInkiOjg3My4yMjQwOTI3NDE5MzU1fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabels&quot;&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_PR_K_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(138, 427.078125)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_K_N_0&quot; transform=&quot;translate(-15.609375, -12)&quot;&gt;&lt;foreignObject width=&quot;31.21875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;nein&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(448, 363.078125)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_K_B_0&quot; transform=&quot;translate(-53.234375, -12)&quot;&gt;&lt;foreignObject width=&quot;106.46875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;ja / unbekannt&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_N_A1_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_B_A2_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_A2_A3_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_A1_M1_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_A3_M2_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_M1_MG_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_M2_MG_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;nodes&quot;&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-PR-0&quot; data-look=&quot;classic&quot; transform=&quot;translate(293, 35)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-74.4453125&quot; y=&quot;-27&quot; width=&quot;148.890625&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-44.4453125, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;88.890625&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Agenten-PR&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-K-1&quot; data-look=&quot;classic&quot; transform=&quot;translate(293, 219.0390625)&quot;&gt;&lt;polygon points=&quot;107.0390625,0 214.078125,-107.0390625 107.0390625,-214.078125 0,-107.0390625&quot; class=&quot;label-container&quot; transform=&quot;translate(-106.5390625, 107.0390625)&quot;&gt;&lt;/polygon&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-68.0390625, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;136.078125&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Bestehender Code&lt;br/&gt;angefasst?&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-N-3&quot; data-look=&quot;classic&quot; transform=&quot;translate(138, 531.078125)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-77.90625&quot; y=&quot;-27&quot; width=&quot;155.8125&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-47.90625, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;95.8125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Spur Neubau&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-B-5&quot; data-look=&quot;classic&quot; transform=&quot;translate(448, 427.078125)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-79.9296875&quot; y=&quot;-27&quot; width=&quot;159.859375&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-49.9296875, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;99.859375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Spur Bestand&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-A1-7&quot; data-look=&quot;classic&quot; transform=&quot;translate(138, 647.078125)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-121.734375&quot; y=&quot;-27&quot; width=&quot;243.46875&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-91.734375, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;183.46875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Build, Tests, govulncheck&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-A2-9&quot; data-look=&quot;classic&quot; transform=&quot;translate(448, 531.078125)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-121.734375&quot; y=&quot;-27&quot; width=&quot;243.46875&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-91.734375, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;183.46875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Build, Tests, govulncheck&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-A3-11&quot; data-look=&quot;classic&quot; transform=&quot;translate(448, 647.078125)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;gorelease, Helm-Diff, Lockfile-Diff&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-M1-13&quot; data-look=&quot;classic&quot; transform=&quot;translate(138, 775.078125)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Review: Schnittstelle, Datenmodell&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-M2-15&quot; data-look=&quot;classic&quot; transform=&quot;translate(448, 775.078125)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Review: ganzes Diff, zwei Augenpaare&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-MG-17&quot; data-look=&quot;classic&quot; transform=&quot;translate(293, 891.078125)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-53.21875&quot; y=&quot;-27&quot; width=&quot;106.4375&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-23.21875, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;46.4375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Merge&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;defs&gt;&lt;filter id=&quot;mermaid-0-drop-shadow&quot; height=&quot;130%&quot; width=&quot;130%&quot;&gt;&lt;feDropShadow dx=&quot;4&quot; dy=&quot;4&quot; stdDeviation=&quot;0&quot; flood-opacity=&quot;0.06&quot; flood-color=&quot;#000000&quot;&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;defs&gt;&lt;filter id=&quot;mermaid-0-drop-shadow-small&quot; height=&quot;150%&quot; width=&quot;150%&quot;&gt;&lt;feDropShadow dx=&quot;2&quot; dy=&quot;2&quot; stdDeviation=&quot;0&quot; flood-opacity=&quot;0.06&quot; flood-color=&quot;#000000&quot;&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;linearGradient id=&quot;mermaid-0-gradient&quot; gradientUnits=&quot;objectBoundingBox&quot; x1=&quot;0%&quot; y1=&quot;0%&quot; x2=&quot;100%&quot; y2=&quot;0%&quot;&gt;&lt;stop offset=&quot;0%&quot; stop-color=&quot;#363739&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;&lt;stop offset=&quot;100%&quot; stop-color=&quot;hsl(220, 0%, 17.6470588235%)&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;&lt;/linearGradient&gt;&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;Der Commit-Typ nach Conventional Commits ist ein brauchbarer Hinweis, aber kein Beleg: Den Titel schreibt der Agent. Das harte Kriterium liefert das Diff selbst. Gelöschte Zeilen bedeuten, dass bestehender Code angefasst wurde.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# .github/workflows/agent-gate.yml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;agent-gate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;pull_request&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;jobs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  spur&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    runs-on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ubuntu-latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    outputs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      lane&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;${{ steps.wahl.outputs.lane }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    steps&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;actions/checkout@v7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          fetch-depth&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;wahl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;          # Titel nie direkt in `run` interpolieren: Script Injection.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          TITEL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;${{ github.event.pull_request.title }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          BASIS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;${{ github.event.pull_request.base.sha }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          case &amp;quot;$TITEL&amp;quot; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            feat:*|&amp;quot;feat(&amp;quot;*) LANE=neubau ;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            *)               LANE=bestand ;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          esac&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          GEAENDERT=$(git diff --numstat &amp;quot;$BASIS&amp;quot;...HEAD | awk &amp;#39;$2 &amp;gt; 0&amp;#39; | wc -l)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          if [ &amp;quot;$GEAENDERT&amp;quot; -gt 0 ]; then LANE=bestand; fi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          echo &amp;quot;lane=$LANE&amp;quot; &amp;gt;&amp;gt; &amp;quot;$GITHUB_OUTPUT&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unbekannt landet in der strengen Spur. Das ist der ganze Trick: Die Voreinstellung ist streng, nicht locker.&lt;/p&gt;
&lt;h2 id=&quot;zwei-gates-die-im-go--und-kubernetes-alltag-tatsächlich-greifen&quot;&gt;Zwei Gates, die im Go- und Kubernetes-Alltag tatsächlich greifen&lt;/h2&gt;
&lt;p&gt;Für die Spur Bestand braucht es Prüfungen, die Kompatibilitätsbrüche mechanisch sichtbar machen, statt sie einem Review zu überlassen.&lt;/p&gt;
&lt;p&gt;Im Go-Modul erledigt das &lt;code&gt;gorelease&lt;/code&gt; aus &lt;a href=&quot;https://pkg.go.dev/golang.org/x/exp/cmd/gorelease&quot;&gt;golang.org/x/exp/cmd/gorelease&lt;/a&gt;. Es vergleicht die öffentliche API des ausgecheckten Stands gegen eine Basisversion und beendet sich bei inkompatiblen Unterschieden ab Major-Version 1 mit einem Exit-Code ungleich null. Damit ist der AST-Befund der Studie exakt das, was das Gate misst.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  api-vertrag&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    needs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;spur&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;needs.spur.outputs.lane == &amp;#39;bestand&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    runs-on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ubuntu-latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    steps&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;actions/checkout@v7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          fetch-depth&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;actions/setup-go@v7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          go-version-file&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;go.mod&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;go install golang.org/x/exp/cmd/gorelease@latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;gorelease -base=latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Auf der Kubernetes-Seite ist das Äquivalent der gerenderte Manifest-Diff. Nicht das Chart vergleichen, sondern das Ergebnis: Ein Agent, der einen Wert umbenennt, hinterlässt im Chart eine harmlose Zeile und im Deployment eine fehlende Umgebungsvariable.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Rendert Basis und PR-Stand und vergleicht das Ergebnis, nicht die Quelle.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;helm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; template&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; svc&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ./chart&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /tmp/neu.yaml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; worktree&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /tmp/basis&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$BASE_SHA&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;helm&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; template&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; svc&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /tmp/basis/chart&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /tmp/basis.yaml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;diff&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -u&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /tmp/basis.yaml&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /tmp/neu.yaml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;was-die-pipeline-nicht-abfangen-kann&quot;&gt;Was die Pipeline nicht abfangen kann&lt;/h2&gt;
&lt;p&gt;Statische Analyse allein ist kein Sicherheitsgate. Firouzi und Ghafari haben 1’080 LLM-erzeugte Codebeispiele gegen eine von Menschen validierte Referenz gehalten (&lt;a href=&quot;https://arxiv.org/abs/2602.05868&quot;&gt;arXiv:2602.05868&lt;/a&gt;, 05.02.2026): Nur 65 % der Semgrep- und 61 % der CodeQL-Befunde trafen die Referenz. Auf aggregierter Ebene sahen beide Werkzeuge plausibel aus, pro Beispiel wichen sie erheblich ab.&lt;/p&gt;
&lt;p&gt;Der Bedarf ist da. Peng, Wang und Zhu fanden bei 3’700 Snippets aus dem LLMSecEval-Benchmark, dass 68,8 % mindestens eine Sicherheitsanforderung verletzten, bei hartkodierten Zugangsdaten 79,1 % (&lt;a href=&quot;https://arxiv.org/abs/2607.12089&quot;&gt;arXiv:2607.12089&lt;/a&gt;). Ma et al. berichten über acht Modelle hinweg durchschnittliche Verwundbarkeitsraten über 56 % (&lt;a href=&quot;https://arxiv.org/abs/2607.23088&quot;&gt;arXiv:2607.23088&lt;/a&gt;, Poster). Die absoluten Werte sind zwischen den Arbeiten nicht vergleichbar, die Richtung ist über ein Dutzend unabhängiger Arbeiten hinweg konsistent.&lt;/p&gt;
&lt;p&gt;Was messbar wirkt, ist nachgelagerte Reparatur statt besserer Prompts: Sriram, Pradhan und Saha kombinierten Compiler-Diagnostik, CodeQL und symbolische Ausführung und senkten die Sicherheitsdefekte von CodeLlama 7B in C-Code von 49 % auf 19 % (&lt;a href=&quot;https://arxiv.org/abs/2607.21641&quot;&gt;arXiv:2607.21641&lt;/a&gt;). Ein Reparaturlauf gehört also in die Pipeline, ein Freibrief daraus nicht.&lt;/p&gt;
&lt;h2 id=&quot;planung-und-ausführung-trennen&quot;&gt;Planung und Ausführung trennen&lt;/h2&gt;
&lt;p&gt;Der Plan muss vor dem Code stehen und von einem Menschen abgenommen sein. Boris Tane beschreibt das als das am häufigsten geteilte Arbeitsmuster überhaupt: „The separation of planning and execution is the single most important thing I do”, und daraus folgend „never let Claude write code until you’ve reviewed and approved a written plan” (&lt;a href=&quot;https://boristane.com/blog/how-i-use-claude-code/&quot;&gt;boristane.com&lt;/a&gt;, Februar 2026).&lt;/p&gt;
&lt;p&gt;Das ist die Schnittstelle zwischen dem Agenten und Ihrem Team. Ein abgenommener Plan ist prüfbar, ein fertiges Diff von 2’000 Zeilen nicht mehr. Wo der Plan eine Architekturentscheidung enthält, gehört er ohnehin ins Repository, siehe &lt;a href=&quot;https://devs-group.ch/blog/architektur-entscheidungen-dokumentieren/&quot;&gt;Entscheidungen, die man in zwei Jahren noch versteht&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ein Wort zu Kontextdateien, weil hier viel Aufwand versickert: Gloaguen, Mündler, Müller, Raychev und Vechev von der ETH Zürich haben &lt;code&gt;AGENTS.md&lt;/code&gt;-Dateien systematisch evaluiert (&lt;a href=&quot;https://arxiv.org/abs/2602.11988&quot;&gt;arXiv:2602.11988&lt;/a&gt;, revidiert am 23.06.2026). Befund: Kontextdateien verbessern die Erfolgsrate generell nicht und erhöhen die Inferenzkosten um über 20 %. Anweisungen werden befolgt, Repository-Übersichten bringen nichts. Schreiben Sie also Konventionen und Fallstricke hinein, keine Verzeichnisbäume.&lt;/p&gt;
&lt;h2 id=&quot;wovon-wir-abraten&quot;&gt;Wovon wir abraten&lt;/h2&gt;
&lt;p&gt;Bauen Sie kein Merge-Gate, das nur wahr oder falsch kennt. Ein einzelner grüner Haken über allen Aufgabentypen ist entweder für den Neubau zu teuer oder für die Wartung zu billig, meistens beides.&lt;/p&gt;
&lt;p&gt;Setzen Sie keinen zweiten Agenten als alleinigen Reviewer ein. Ein Review-Agent ist nützlich, um ein Diff zu strukturieren und Kandidaten zu markieren. Er ist kein Prüfer, weil er dieselben Fehlerklassen teilt wie der Agent, den er prüft, und weil die Kette dann wieder in einer Selbstauskunft endet.&lt;/p&gt;
&lt;p&gt;Und der ehrliche Trade-off: Die lockere Spur beim Neubau lässt Fehler durch. Die 3,45 % sind besser als der menschliche Wert, aber sie sind nicht null. Wer diese Staffelung übernimmt, entscheidet sich bewusst dafür, Prüfaufwand dorthin zu verschieben, wo er statistisch mehr bringt. Für ein Team mit zwei Entwicklern und einem Prototypen lohnt sich der ganze Apparat nicht. Für ein Produkt mit externen API-Konsumenten und einem Cluster in Produktion schon.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;warum-sollen-agenten-bei-wartung-strenger-geprüft-werden-als-bei-neubau&quot;&gt;Warum sollen Agenten bei Wartung strenger geprüft werden als bei Neubau?&lt;/h3&gt;
&lt;p&gt;Weil die Daten es so zeigen. In der Vergleichsstudie von Ferdous et al. über 7’191 agentenerzeugte Pull Requests lag die Breaking-Change-Rate bei Neubau bei 3,45 %, bei Refactoring bei 6,72 % und bei Chore-Änderungen bei 9,35 %. Wartung setzt Kenntnis bestehender Verträge voraus, die im Kontextfenster oft nur teilweise vorliegen. Neubau definiert die Verträge selbst.&lt;/p&gt;
&lt;h3 id=&quot;kann-ich-den-confidence-wert-des-agenten-als-merge-kriterium-nutzen&quot;&gt;Kann ich den Confidence-Wert des Agenten als Merge-Kriterium nutzen?&lt;/h3&gt;
&lt;p&gt;Nein. Dieselbe Studie beschreibt eine „Confidence Trap”: Pull Requests mit hohem Selbstvertrauens-Wert enthalten trotzdem Breaking Changes. Der Wert ist eine Selbstauskunft des Systems, dessen Arbeit geprüft werden soll. Nutzen Sie stattdessen Kriterien, die der Agent nicht beeinflusst: Wurde bestehender Code geändert, bricht die öffentliche API, ändert sich das gerenderte Manifest.&lt;/p&gt;
&lt;h3 id=&quot;reicht-ein-security-scanner-in-der-pipeline-als-gate&quot;&gt;Reicht ein Security-Scanner in der Pipeline als Gate?&lt;/h3&gt;
&lt;p&gt;Als alleiniges Gate nicht. Firouzi und Ghafari fanden auf 1’080 validierten Beispielen, dass nur 65 % der Semgrep- und 61 % der CodeQL-Befunde der menschlich validierten Referenz entsprachen. Scanner gehören in die Pipeline, ihre Befunde sind Hinweise. Wirksamer ist ein nachgelagerter Reparaturlauf, der Compiler-Diagnostik und statische Analyse zusammenführt und das Ergebnis erneut prüft.&lt;/p&gt;
&lt;h3 id=&quot;wie-klassifiziere-ich-pull-requests-wenn-der-agent-den-titel-schreibt&quot;&gt;Wie klassifiziere ich Pull Requests, wenn der Agent den Titel schreibt?&lt;/h3&gt;
&lt;p&gt;Über das Diff, nicht über den Titel. Ein Pull Request, der Zeilen löscht, hat bestehenden Code angefasst und gehört in die strenge Spur. &lt;code&gt;git diff --numstat&lt;/code&gt; liefert das in einer Zeile. Der Commit-Typ nach Conventional Commits bleibt ein nützlicher Hinweis für Menschen, taugt aber nicht als Gate, weil ihn der Prüfling selbst setzt.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Ihre Pipeline durchgehen, nicht Ihre Strategie.&lt;/strong&gt; 30 Minuten mit einem unserer Go-Engineers: welche Gates Sie heute haben, welche Aufgabentypen bei Ihnen ungeprüft durchlaufen und was sich davon in einer Woche nachrüsten lässt. Ohne Verkaufsgespräch.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin buchen&lt;/a&gt; · &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt aufnehmen&lt;/a&gt; · Wie wir KI-Systeme und Agenten-Infrastruktur bauen, steht unter &lt;a href=&quot;https://devs-group.ch/leistungen/kuenstliche-intelligenz/&quot;&gt;Künstliche Intelligenz &amp;amp; Machine Learning&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>KI-gestützte Entwicklung</category><author>Ralph Segi</author></item><item><title>Coding-Agenten datenschutzkonform nutzen: die Lücke im Abo</title><link>https://devs-group.ch/blog/coding-agenten-datenschutzkonform-nutzen/</link><guid isPermaLink="true">https://devs-group.ch/blog/coding-agenten-datenschutzkonform-nutzen/</guid><description>Ein privates Pro-Abo auf Firmencode fällt unter Consumer-Bedingungen. Welche Tarife und Hosting-Wege Coding-Agenten datenschutzkonform machen.</description><pubDate>Mon, 31 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ein Entwickler, der mit seinem privaten Pro- oder Max-Abo an Firmencode arbeitet, fällt unter Anthropics Consumer-Bedingungen, nicht unter die kommerziellen. Dort ist die Trainingsnutzung eine Kontoeinstellung, ausdrücklich „including when you use Claude Code from these accounts”, und bei aktivierter Einstellung liegen die Daten fünf Jahre statt dreissig Tage.&lt;/p&gt;
&lt;p&gt;Das ist kein Skandal und kein verstecktes Kleingedrucktes. Anthropic dokumentiert die Unterschiede auf einer &lt;a href=&quot;https://code.claude.com/docs/en/data-usage&quot;&gt;öffentlichen Seite zur Datennutzung&lt;/a&gt;, detaillierter als die meisten Anbieter. Die Lücke entsteht in den Firmen, die den Unterschied zwischen Consumer- und Geschäftstarif nie geregelt haben. Wer Coding-Agenten datenschutzkonform nutzen will, beginnt deshalb beim Konto, nicht beim Werkzeug.&lt;/p&gt;
&lt;h2 id=&quot;warum-das-private-abo-überhaupt-auf-firmencode-landet&quot;&gt;Warum das private Abo überhaupt auf Firmencode landet&lt;/h2&gt;
&lt;p&gt;Coding-Agenten kommen über den Entwickler ins Unternehmen, nicht über die Beschaffung. Jemand testet Claude Code abends am eigenen Projekt, findet es gut, tippt am nächsten Morgen &lt;code&gt;claude&lt;/code&gt; im Kundenrepository und ist dabei immer noch mit dem privaten Konto angemeldet. Es gibt keinen Installationsdialog, der das bemerkt.&lt;/p&gt;
&lt;p&gt;Der zweite Weg ist die Spesenabrechnung. Ein Team, das noch keine Lizenz hat, vergütet zwanzig Dollar im Monat als Auslage. Damit ist das Abo bezahlt, aber vertraglich bleibt es ein Konsumentenvertrag zwischen Anthropic und einer Privatperson. Der Arbeitgeber ist darin keine Partei.&lt;/p&gt;
&lt;p&gt;Beide Wege sind technisch unauffällig. &lt;code&gt;/status&lt;/code&gt; in Claude Code zeigt die Anmeldemethode und die Organisation an, aber niemand schaut dort hin, solange nichts kaputt ist.&lt;/p&gt;
&lt;h2 id=&quot;ist-firmencode-überhaupt-ein-datenschutzthema&quot;&gt;Ist Firmencode überhaupt ein Datenschutzthema?&lt;/h2&gt;
&lt;p&gt;Firmencode ist ein Datenschutzthema, sobald Personendaten darin vorkommen, und das ist häufiger der Fall als gedacht. Test-Fixtures mit echten Namen, ein Datenbank-Dump für die Migration, ein Log-Auszug, den jemand in den Prompt kopiert: In diesen Momenten bearbeitet ein Coding-Agent Personendaten.&lt;/p&gt;
&lt;p&gt;Der EDÖB hat am 24.09.2025 im Beitrag &lt;a href=&quot;https://www.edoeb.admin.ch/de/ki-und-datenschutz&quot;&gt;KI und Datenschutz&lt;/a&gt; festgehalten, dass „das Schweizer Datenschutzgesetz (DSG) auf KI-gestützte Datenbearbeitungen direkt anwendbar ist”. Es braucht kein KI-Sondergesetz, damit Pflichten gelten. Welche Normen im Einzelnen greifen und wer für einen Verstoss haftet, steht in unserem Beitrag zur &lt;a href=&quot;https://devs-group.ch/blog/revdsg-konforme-ki-architektur/&quot;&gt;revDSG-konformen KI-Architektur&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Wo keine Personendaten im Spiel sind, bleiben zwei andere Bindungen: das Geschäftsgeheimnis des Kunden und die Vertraulichkeitsklausel im Rahmenvertrag. Ob eine bestimmte Klausel die Weitergabe an einen Inferenzanbieter deckt, ist eine Frage des Einzelfalls und gehört vor den ersten Prompt geprüft, nicht danach.&lt;/p&gt;
&lt;h2 id=&quot;was-anthropic-pro-tarif-zusagt&quot;&gt;Was Anthropic pro Tarif zusagt&lt;/h2&gt;
&lt;p&gt;Die Zusagen unterscheiden sich zwischen Consumer- und Geschäftstarifen in drei Punkten: Training, Aufbewahrung und Verhandelbarkeit. Alle Angaben stammen aus der &lt;a href=&quot;https://code.claude.com/docs/en/data-usage&quot;&gt;Datennutzungsseite&lt;/a&gt; und der &lt;a href=&quot;https://claude.com/pricing&quot;&gt;Preisseite&lt;/a&gt;, abgerufen am 20.08.2026.&lt;/p&gt;



































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tarif&lt;/th&gt;&lt;th&gt;Training auf Ihrem Code&lt;/th&gt;&lt;th&gt;Aufbewahrung bei Anthropic&lt;/th&gt;&lt;th&gt;Listenpreis (USD)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Free, Pro, Max&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;abhängig von einer Kontoeinstellung, inklusive Claude-Code-Nutzung aus diesen Konten&lt;/td&gt;&lt;td&gt;5 Jahre bei aktivierter Einstellung, sonst 30 Tage&lt;/td&gt;&lt;td&gt;Pro 17 im Jahresabo, 20 monatlich; Max ab 100&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Team&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;kein Training unter kommerziellen Bedingungen&lt;/td&gt;&lt;td&gt;30 Tage&lt;/td&gt;&lt;td&gt;20 pro Standard-Seat, 100 pro Premium-Seat, jeweils jährlich&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Enterprise&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;kein Training unter kommerziellen Bedingungen&lt;/td&gt;&lt;td&gt;30 Tage; Zero Data Retention auf Antrag&lt;/td&gt;&lt;td&gt;20 pro Seat plus Nutzung zu API-Preisen&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;API, Bedrock, Google Cloud, Microsoft Foundry&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;kein Training; das Development Partner Program ist über Bedrock und Google Cloud gar nicht verfügbar&lt;/td&gt;&lt;td&gt;30 Tage, bei Foundry „Hosted on Azure” bleiben Prompts und Completions in Azure&lt;/td&gt;&lt;td&gt;nutzungsabhängig&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Drei Details, die in Beschaffungsgesprächen regelmässig falsch wiedergegeben werden:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zero Data Retention ist nicht im Standard-Enterprise-Plan enthalten.&lt;/strong&gt; Anthropic schreibt, ZDR sei für qualifizierte Konten verfügbar und werde pro Organisation vom Account-Team nach einer Eignungsprüfung freigeschaltet. Wer ZDR braucht, verhandelt ihn.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Über &lt;code&gt;/feedback&lt;/code&gt;, &lt;code&gt;/bug&lt;/code&gt; und &lt;code&gt;/share&lt;/code&gt; geteilte Transkripte werden fünf Jahre aufbewahrt&lt;/strong&gt;, unabhängig vom Tarif. Freiwillig hochgeladene Sitzungstranskripte aus der Qualitätsumfrage bis zu sechs Monate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fehlerberichte sind nur bei Pro- und Max-Anmeldung aktiv&lt;/strong&gt;, ab Version 2.1.198 und nur bei direkter Verbindung zur Claude-API. Auch das ist eine Consumer-Eigenschaft, die im Geschäftstarif gar nicht erst auftritt.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;was-es-kostet-die-lücke-zu-schliessen&quot;&gt;Was es kostet, die Lücke zu schliessen&lt;/h2&gt;
&lt;p&gt;Der Wechsel von privaten Abos auf Team-Seats kostet ein zwölfköpfiges Team drei Dollar pro Kopf und Monat. Modellrechnung aus den Listenpreisen: zwölf Pro-Abos im Jahresabo kosten 12 × 17 = 204 USD monatlich, zwölf Team-Standard-Seats 12 × 20 = 240 USD. Delta: 36 USD im Monat, 432 USD im Jahr.&lt;/p&gt;
&lt;p&gt;Für Vielnutzer sieht die Rechnung anders und noch günstiger aus. Wer heute ein Max-Abo für 100 USD monatlich hat, kostet als Team-Premium-Seat im Jahresabo ebenfalls 100 USD. Der Wechsel ist bei diesem Nutzungsprofil preisneutral.&lt;/p&gt;
&lt;p&gt;Der ehrliche Vorbehalt: Ein Standard-Seat ist kein Ersatz für ein Max-Abo, die Nutzungskontingente unterscheiden sich. Wer heute Max spesiert, braucht einen Premium-Seat, nicht den günstigsten. Trotzdem bleibt die Grössenordnung dieselbe, und sie ist der Grund, warum diese Lücke ärgerlich ist: Sie kostet fast nichts, ausser der Entscheidung.&lt;/p&gt;
&lt;p&gt;Wenn Sie nicht wissen, mit welchen Konten Ihr Team heute arbeitet, ist das eine Stunde Arbeit, keine Woche. &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Dreissig Minuten mit einem unserer Engineers&lt;/a&gt; reichen, um daraus eine Inventarliste und eine Reihenfolge zu machen.&lt;/p&gt;
&lt;h2 id=&quot;drei-datenflüsse-die-auch-im-geschäftstarif-bleiben&quot;&gt;Drei Datenflüsse, die auch im Geschäftstarif bleiben&lt;/h2&gt;
&lt;p&gt;Ein kommerzieller Tarif regelt das Training, nicht jeden Datenfluss. Drei davon bleiben bestehen und gehören ins Bearbeitungsverzeichnis, weil sie sonst in keiner Vertragsprüfung auftauchen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lokale Transkripte im Klartext.&lt;/strong&gt; Claude Code legt Sitzungstranskripte unter &lt;code&gt;~/.claude/projects/&lt;/code&gt; ab, standardmässig 30 Tage. Die Dokumentation ist dabei unmissverständlich: „Transcripts and history are not encrypted at rest. OS file permissions are the only protection.” Liest ein Tool eine &lt;code&gt;.env&lt;/code&gt;-Datei, steht der Inhalt in der &lt;code&gt;.jsonl&lt;/code&gt;-Datei. Steuerbar über &lt;code&gt;cleanupPeriodDays&lt;/code&gt;, &lt;code&gt;CLAUDE_CODE_SKIP_PROMPT_HISTORY&lt;/code&gt; und &lt;code&gt;claude project purge&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Die WebFetch-Domainprüfung.&lt;/strong&gt; Vor jedem Abruf sendet WebFetch den angefragten Hostnamen an &lt;code&gt;api.anthropic.com&lt;/code&gt;, um ihn gegen eine Blockliste zu prüfen. Nur den Hostnamen, nicht die volle URL. Das läuft unabhängig vom Modellanbieter, also auch über Bedrock, und &lt;code&gt;CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC&lt;/code&gt; erfasst es nicht. Abschaltbar allein über &lt;code&gt;skipWebFetchPreflight&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Telemetrie und Fehlerberichte.&lt;/strong&gt; Steuerbar über &lt;code&gt;DISABLE_TELEMETRY&lt;/code&gt;, &lt;code&gt;DISABLE_ERROR_REPORTING&lt;/code&gt;, &lt;code&gt;DISABLE_FEEDBACK_COMMAND&lt;/code&gt; und &lt;code&gt;CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC&lt;/code&gt;. Bei Amazon Bedrock, Google Cloud, Microsoft Foundry und Claude Platform on AWS sind Metriken, Fehlerberichte und &lt;code&gt;/feedback&lt;/code&gt; bereits standardmässig aus. Sitzungsumfragen und die WebFetch-Prüfung laufen dort weiter.&lt;/p&gt;
&lt;h2 id=&quot;welcher-bezugsweg-für-welche-art-von-code&quot;&gt;Welcher Bezugsweg für welche Art von Code?&lt;/h2&gt;
&lt;p&gt;Der Bezugsweg richtet sich nach dem Inhalt des Repositorys, nicht nach der Grösse der Firma. Die Frage lautet also nicht „welchen Tarif kaufen wir”, sondern „was liegt in diesem Repository und was landet aus ihm im Prompt”.&lt;/p&gt;



































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Was im Repository und im Prompt landet&lt;/th&gt;&lt;th&gt;Bezugsweg&lt;/th&gt;&lt;th&gt;Was zusätzlich nötig ist&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Eigenes Tooling, Open-Source-Beiträge, keine Kundendaten&lt;/td&gt;&lt;td&gt;Team-Seat&lt;/td&gt;&lt;td&gt;nichts über die interne Richtlinie hinaus&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kundencode unter NDA, keine Personendaten&lt;/td&gt;&lt;td&gt;Team oder Enterprise&lt;/td&gt;&lt;td&gt;Vertraulichkeitsklausel des Kunden prüfen, Egress dokumentieren&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Personendaten in Fixtures, Dumps oder Logs&lt;/td&gt;&lt;td&gt;Enterprise, ZDR verhandeln&lt;/td&gt;&lt;td&gt;Auftragsbearbeitung nach Art. 9 DSG, Löschkonzept für lokale Transkripte&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Besonders schützenswerte Personendaten nach Art. 5 lit. c DSG&lt;/td&gt;&lt;td&gt;Bedrock mit kundenverwalteten KMS-Schlüsseln oder Foundry „Hosted on Azure”&lt;/td&gt;&lt;td&gt;Datenschutz-Folgenabschätzung prüfen, keine Produktionsdaten im Prompt&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Zugesicherte Datenresidenz oder Berufsgeheimnis&lt;/td&gt;&lt;td&gt;eigenes Hosting, offene Modelle&lt;/td&gt;&lt;td&gt;siehe &lt;a href=&quot;https://devs-group.ch/blog/souveraene-ki-inferenz-schweiz/&quot;&gt;souveräne KI-Inferenz in der Schweiz&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Amazon Bedrock verschlüsselt mit AES-256 und erlaubt kundenverwaltete Schlüssel über AWS KMS, Google Cloud unterstützt CMEK. Bei Microsoft Foundry und „Hosted on Azure” bleiben Prompts und Completions in Azure, nur Nutzungsmetadaten und von Sicherheitssystemen markierte Inhalte gehen an Anthropic. Welche Regionen konkret verfügbar sind, steht nicht in der Datennutzungsseite und ist beim jeweiligen Cloud-Anbieter zu prüfen.&lt;/p&gt;
&lt;h2 id=&quot;wie-sie-die-datenschutzkonforme-nutzung-technisch-erzwingen&quot;&gt;Wie Sie die datenschutzkonforme Nutzung technisch erzwingen&lt;/h2&gt;
&lt;p&gt;Die Anmeldung an einer bestimmten Organisation lässt sich erzwingen, und das ist der einzige Punkt der ganzen Liste, der ohne Disziplin auskommt. &lt;code&gt;forceLoginOrgUUID&lt;/code&gt; und &lt;code&gt;forceLoginMethod&lt;/code&gt; gehören in die Managed Settings und werden über Ihr Device Management ausgerollt: auf macOS nach &lt;code&gt;/Library/Application Support/ClaudeCode/managed-settings.json&lt;/code&gt;, auf Linux nach &lt;code&gt;/etc/claude-code/managed-settings.json&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;forceLoginMethod&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;claudeai&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;forceLoginOrgUUID&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;550e8400-e29b-41d4-a716-446655440000&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;cleanupPeriodDays&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;env&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &amp;quot;DISABLE_TELEMETRY&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &amp;quot;DISABLE_ERROR_REPORTING&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &amp;quot;DISABLE_FEEDBACK_COMMAND&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;permissions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &amp;quot;deny&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &amp;quot;Read(./.env)&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &amp;quot;Read(./.env.*)&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &amp;quot;Read(./secrets/**)&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vier Einschränkungen, die Anthropic in der &lt;a href=&quot;https://code.claude.com/docs/en/authentication&quot;&gt;Dokumentation zur Authentifizierung&lt;/a&gt; selbst benennt und die man kennen muss, bevor man den Haken setzt: &lt;code&gt;claude setup-token&lt;/code&gt; und &lt;code&gt;/install-github-app&lt;/code&gt; erzwingen nur &lt;code&gt;forceLoginMethod&lt;/code&gt;, können also ein Token in einer anderen Organisation erzeugen. Sitzungen über Cloud-Anbieter werden nicht blockiert, die schränken Sie über IAM ein. &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; und &lt;code&gt;apiKeyHelper&lt;/code&gt; werden beim Start blockiert, weil sich die Organisationszugehörigkeit dort nicht prüfen lässt. Und wenn Sie zusätzlich Server-managed Settings verteilen, müssen beide Schlüssel an beiden Orten stehen, weil die Quellen sich nicht mischen.&lt;/p&gt;
&lt;p&gt;Die zweite Hälfte gehört ins Repository, nicht aufs Gerät, damit sie im Code-Review sichtbar ist. Eine &lt;code&gt;.claude/settings.json&lt;/code&gt; mit Deny-Regeln greift für jeden, der das Projekt auscheckt:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;permissions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &amp;quot;deny&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &amp;quot;Read(./deploy/*.key)&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &amp;quot;Read(./fixtures/prod-*.sql)&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Und ein Prüfskript, das als MDM-Check oder im Onboarding läuft:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Prüft, ob die Vorgaben für Claude Code auf diesem Gerät greifen.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Exit 1, sobald eine Vorgabe fehlt.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -euo&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; pipefail&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;$(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;uname&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;  Darwin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; managed&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;/Library/Application Support/ClaudeCode/managed-settings.json&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  *)&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      managed&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;/etc/claude-code/managed-settings.json&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;esac&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;note&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;printf&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;%-26s %s\n&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;$1&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;$2&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$managed&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ]; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  org&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;jq&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -r&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;.forceLoginOrgUUID // empty&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$managed&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  [ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$org&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;note&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;forceLoginOrgUUID&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;fehlt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; fail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  days&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;jq&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -r&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;.cleanupPeriodDays // empty&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$managed&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  note&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;managed-settings.json&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;nicht vorhanden&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  fail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Klartext-Transkripte oberhalb der eigenen Aufbewahrungsfrist&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;alt&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$HOME&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/.claude/projects&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -name&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;*.jsonl&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -mtime&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; +&amp;quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;days&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;30&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; 2&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/dev/null&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; wc&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -l&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; tr&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$alt&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;note&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;alte Transkripte&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$alt&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; Dateien über der Frist&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; fail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exit&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$fail&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;openai-codex-gleicher-prüfpfad-andere-namen&quot;&gt;OpenAI Codex: gleicher Prüfpfad, andere Namen&lt;/h2&gt;
&lt;p&gt;Bei OpenAI verläuft die Prüfung entlang derselben drei Fragen, die Bezeichnungen unterscheiden sich. Der Business-Tarif kostet laut &lt;a href=&quot;https://learn.chatgpt.com/codex/pricing&quot;&gt;Codex-Preisseite&lt;/a&gt; 20 USD pro Nutzer und Monat im Jahresabo und trägt die Zusage „No training on your business data by default”. Enterprise ergänzt Kontrollen für Aufbewahrung und Datenresidenz, SCIM, External Key Management, rollenbasierte Zugriffskontrolle sowie Audit-Logs über die Compliance-API.&lt;/p&gt;
&lt;p&gt;Für Firmen, die den Datenfluss zu OpenAI ganz vermeiden wollen: Die Codex CLI unterstützt seit Release 0.148.0 Amazon Bedrock Runtime als eingebauten Provider, inklusive AWS-Profil und Region. Damit gilt für Codex derselbe Weg wie für Claude Code, nämlich Inferenz im eigenen AWS-Konto statt beim Modellanbieter.&lt;/p&gt;
&lt;p&gt;Die praktische Konsequenz ist unbequem: Wer beide Werkzeuge im Haus hat, braucht zwei Prüfungen und zwei Richtlinienzeilen. Ein einziger Absatz „KI-Tools sind erlaubt” deckt das nicht ab.&lt;/p&gt;
&lt;h2 id=&quot;was-am-montag-in-die-richtlinie-gehört&quot;&gt;Was am Montag in die Richtlinie gehört&lt;/h2&gt;
&lt;p&gt;Sechs Zeilen genügen, und sie sind in einer Stunde geschrieben. Der Reihe nach, weil die Reihenfolge den Aufwand bestimmt:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Inventar.&lt;/strong&gt; Wer arbeitet mit welchem Werkzeug unter welchem Konto? &lt;code&gt;/status&lt;/code&gt; beantwortet das pro Gerät in Sekunden.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spesenregel.&lt;/strong&gt; Private KI-Abos werden nicht mehr vergütet. Diese Zeile schliesst den zweiten Einfallsweg.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anmeldung erzwingen.&lt;/strong&gt; &lt;code&gt;forceLoginOrgUUID&lt;/code&gt; und &lt;code&gt;forceLoginMethod&lt;/code&gt; über das Device Management, mit den vier Einschränkungen oben im Hinterkopf.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Repository-Klassifikation.&lt;/strong&gt; Eine Spalte im Repository-Inventar: Enthält es Personendaten, ja oder nein? Danach richtet sich der Bezugsweg aus der Tabelle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Egress dokumentieren.&lt;/strong&gt; &lt;code&gt;api.anthropic.com&lt;/code&gt; gehört auf die Allowlist und in das Verzeichnis der Bearbeitungstätigkeiten, wegen der WebFetch-Prüfung auch dann, wenn Sie über Bedrock fahren.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feedback-Pfad regeln.&lt;/strong&gt; Entweder &lt;code&gt;DISABLE_FEEDBACK_COMMAND&lt;/code&gt; setzen oder im Team festhalten, dass &lt;code&gt;/feedback&lt;/code&gt; und &lt;code&gt;/share&lt;/code&gt; Code an einen Empfänger geben, der ihn fünf Jahre aufbewahrt.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Die Leitplanken gehören dabei ins Repository und ins Gerätemanagement, nicht in ein Wiki, aus demselben Grund, aus dem wir sie auch bei der &lt;a href=&quot;https://devs-group.ch/blog/ki-code-ohne-technische-schulden/&quot;&gt;KI-gestützten Entwicklung&lt;/a&gt; dorthin legen: Was nicht im Werkzeug steht, gilt nach drei Wochen nicht mehr.&lt;/p&gt;
&lt;h2 id=&quot;wovon-wir-abraten&quot;&gt;Wovon wir abraten&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Vom Verbot.&lt;/strong&gt; Ein Verbot von Coding-Agenten führt nicht dazu, dass niemand sie nutzt, sondern dazu, dass niemand es sagt. Das Ergebnis ist genau der Fall, den dieser Beitrag beschreibt: privates Konto, unbekannter Tarif, keine Aufsicht. Ein bezahlter Team-Seat ist die billigere Kontrolle.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Von Zero Data Retention als Reflex.&lt;/strong&gt; ZDR ist nicht im Standard-Enterprise-Plan enthalten, wird pro Organisation freigeschaltet und braucht eine Verhandlung mit dem Account-Team. Für Repositories ohne Personendaten lösen dreissig Tage Aufbewahrung plus dokumentierte Auftragsbearbeitung dasselbe Problem, ohne Beschaffungsprojekt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Von &lt;code&gt;skipWebFetchPreflight&lt;/code&gt; als Standardeinstellung.&lt;/strong&gt; Wer die Prüfung abschaltet, ruft URLs ohne Abgleich mit der Blockliste ab, und das ist bei einem Agenten, der Webinhalte in seinen Kontext zieht, kein guter Tausch. Der bessere Weg ist die Allowlist plus ein Eintrag im Verzeichnis.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Der Trade-off, den wir offen benennen:&lt;/strong&gt; Bedrock und Foundry kaufen Datenresidenz mit Betriebsaufwand. Sie verwalten Regionen, IAM-Rollen und eigene Schlüssel, Sie verlieren die Abrechnung über einen einzigen Seat-Preis, und neue Modellversionen erreichen Sie tendenziell später. Für ein Repository mit Gesundheitsdaten ist das richtig. Für das interne Admin-Tool ist es Aufwand ohne Gegenwert.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;darf-ein-entwickler-mit-privatem-claude-pro-abo-an-kundencode-arbeiten&quot;&gt;Darf ein Entwickler mit privatem Claude-Pro-Abo an Kundencode arbeiten?&lt;/h3&gt;
&lt;p&gt;Vertraglich möglich, betrieblich schwer zu verantworten. Consumer-Tarife unterliegen den Consumer-Bedingungen, die Trainingsnutzung hängt an einer persönlichen Kontoeinstellung, die der Arbeitgeber weder sieht noch steuert, und bei aktivierter Einstellung beträgt die Aufbewahrung fünf Jahre. Ob im konkreten Fall zusätzlich Datenschutz- oder Geheimhaltungspflichten verletzt werden, hängt vom Repository und vom Kundenvertrag ab.&lt;/p&gt;
&lt;h3 id=&quot;reicht-ein-team-abo-oder-brauchen-wir-enterprise&quot;&gt;Reicht ein Team-Abo, oder brauchen wir Enterprise?&lt;/h3&gt;
&lt;p&gt;Für die Trainingsfrage reicht Team: Anthropic trainiert unter kommerziellen Bedingungen nicht auf Code oder Prompts, und die Aufbewahrung liegt bei dreissig Tagen. Enterprise brauchen Sie für SSO, rollenbasierte Berechtigungen, die Compliance-API und die Managed Policy Settings für organisationsweite Konfiguration. Zero Data Retention gibt es nur auf diesem Weg, und auch dort nur nach Eignungsprüfung.&lt;/p&gt;
&lt;h3 id=&quot;wie-bekommen-wir-zero-data-retention&quot;&gt;Wie bekommen wir Zero Data Retention?&lt;/h3&gt;
&lt;p&gt;Über das Account-Team, nicht über einen Schalter im Admin-Bereich. Anthropic beschreibt ZDR als für qualifizierte Konten verfügbar und pro Organisation nach bestätigter Eignung freigeschaltet, ausdrücklich nicht als Bestandteil des Standard-Enterprise-Plans. Rechnen Sie mit einer Vorlaufzeit und klären Sie vorher, für welche Repositories Sie ihn tatsächlich benötigen.&lt;/p&gt;
&lt;h3 id=&quot;löst-amazon-bedrock-unsere-datenschutzfragen&quot;&gt;Löst Amazon Bedrock unsere Datenschutzfragen?&lt;/h3&gt;
&lt;p&gt;Bedrock löst die Residenz- und Schlüsselfrage, nicht die Bearbeitungsfrage. Verschlüsselung mit AES-256 und kundenverwaltete Schlüssel über AWS KMS sind dokumentiert, Telemetrie und Fehlerberichte sind dort standardmässig aus. Bestehen bleiben die lokalen Klartext-Transkripte, die WebFetch-Domainprüfung gegen &lt;code&gt;api.anthropic.com&lt;/code&gt; und Ihre eigenen Pflichten zu Zweckbindung, Information und Protokollierung.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Nehmen Sie Ihre Entwicklerliste und tragen Sie in eine Spalte ein, unter welchem Konto jede Person angemeldet ist.&lt;/strong&gt; Wenn dort ein privates Abo auftaucht, haben Sie das Ergebnis dieses Beitrags schon in der Hand.&lt;/p&gt;
&lt;p&gt;Dreissig Minuten mit einem Engineer über Tarifwahl, Bezugsweg und Managed Settings, ohne Verkaufsgespräch: &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin buchen&lt;/a&gt;. Lieber schriftlich? Über &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt&lt;/a&gt;. Wie wir KI-Systeme bauen und absichern, steht unter &lt;a href=&quot;https://devs-group.ch/leistungen/kuenstliche-intelligenz/&quot;&gt;Künstliche Intelligenz &amp;amp; Machine Learning&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Alle Produkt- und Vertragsangaben am 20.08.2026 an den Primärquellen von Anthropic und OpenAI geprüft. Dieser Beitrag beschreibt Produkt- und Vertragsbedingungen und leitet daraus technische Konsequenzen ab; er ist keine Rechtsberatung.&lt;/em&gt;&lt;/p&gt;</content:encoded><category>KI-gestützte Entwicklung</category><author>Ralph Segi</author></item><item><title>KI-Produktivität: Die 19 Prozent von METR sind überholt</title><link>https://devs-group.ch/blog/ki-produktivitaet-studien-2026/</link><guid isPermaLink="true">https://devs-group.ch/blog/ki-produktivitaet-studien-2026/</guid><description>Die METR-Nachfolgestudie dreht das Vorzeichen. Was die Forschung im August 2026 über KI-Produktivität belegt, und warum beide Lager falsch zitieren.</description><pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Die meistzitierte Zahl zur KI-Produktivität ist überholt. METR mass 2025 an 16 erfahrenen Open-Source-Entwicklern 19 Prozent &lt;strong&gt;mehr&lt;/strong&gt; Zeitbedarf mit KI-Werkzeugen. Die Nachfolgestudie derselben Organisation, ab August 2025 mit 57 Entwickelnden, misst 18 Prozent &lt;strong&gt;weniger&lt;/strong&gt; Zeit bei denselben Personen. Beide Intervalle sind so breit, dass gesichert davon nichts ist.&lt;/p&gt;
&lt;h2 id=&quot;warum-die-19-prozent-zahl-heute-falsch-zitiert-wird&quot;&gt;Warum die 19-Prozent-Zahl heute falsch zitiert wird&lt;/h2&gt;
&lt;p&gt;Die 19 Prozent stammen aus einer randomisierten Studie von &lt;a href=&quot;https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/&quot;&gt;METR&lt;/a&gt;, Februar bis Juni 2025: 16 erfahrene Entwickler, 246 Issues in ihren eigenen Repositories mit im Schnitt über 22’000 Sternen. Werkzeug war überwiegend Cursor Pro mit Claude 3.5 und 3.7 Sonnet.&lt;/p&gt;
&lt;p&gt;Der Befund war unbequem und wurde deshalb viel zitiert: Die Entwickler erwarteten vorher 24 Prozent Beschleunigung, glaubten nachher an 20 Prozent Beschleunigung, und waren gemessen 19 Prozent langsamer.&lt;/p&gt;
&lt;p&gt;METR hat die Untersuchung fortgesetzt. Die &lt;a href=&quot;https://metr.org/blog/2026-02-24-uplift-update/&quot;&gt;Aktualisierung vom 24. Februar 2026&lt;/a&gt; berichtet eine zweite Studie ab August 2025: 57 Entwickelnde, davon 10 aus der Originalstudie und 47 neu, 143 Repositories, über 800 Aufgaben. Alle Werte in derselben Metrik, Zeitbedarf mit KI gegenüber ohne, ein Minus bedeutet weniger Zeit:&lt;/p&gt;

























&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Gruppe&lt;/th&gt;&lt;th&gt;Punktschätzer&lt;/th&gt;&lt;th&gt;Konfidenzintervall&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Originalstudie, Feb bis Juni 2025&lt;/td&gt;&lt;td&gt;&lt;strong&gt;+19 %&lt;/strong&gt;, also mehr Zeit&lt;/td&gt;&lt;td&gt;+2 % bis +39 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Dieselben Entwickler, Zweitstudie&lt;/td&gt;&lt;td&gt;&lt;strong&gt;−18 %&lt;/strong&gt;, also weniger Zeit&lt;/td&gt;&lt;td&gt;−38 % bis +9 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Neu rekrutierte Entwickler&lt;/td&gt;&lt;td&gt;&lt;strong&gt;−4 %&lt;/strong&gt;, also weniger Zeit&lt;/td&gt;&lt;td&gt;−15 % bis +9 %&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Das Ergebnis hat sich nicht abgeschwächt, es hat das Vorzeichen gewechselt. Wichtiger ist der Unterschied in den Intervallen: Das der Originalstudie schliesst die Null aus, die beiden neuen schliessen sie ein. Belegt ist damit weder Verlangsamung noch Beschleunigung.&lt;/p&gt;
&lt;h2 id=&quot;metr-misstraut-dem-eigenen-ergebnis-und-begründet-das-sauber&quot;&gt;METR misstraut dem eigenen Ergebnis, und begründet das sauber&lt;/h2&gt;
&lt;p&gt;METR schreibt selbst, die Daten taugten nicht als Produktivitätsmass. Wörtlich zur Selektionsverzerrung: «Because of the selection effects in our experiment, our data is only very weak evidence for the size of this increase.» Und zum zentralen Schätzwert: «we believe it is likely a bad proxy for the real productivity impact.»&lt;/p&gt;
&lt;p&gt;Der Grund dafür ist die interessanteste Stelle der ganzen Debatte. METR senkte die Vergütung von 150 auf 50 Dollar pro Stunde. Damit veränderte sich, wer überhaupt mitmacht und welche Aufgaben eingereicht werden.&lt;/p&gt;
&lt;p&gt;«30% to 50% of developers told us that they were choosing not to submit some tasks because they did not want to do them without AI», heisst es im Bericht. Ein Teilnehmer im Originalton: «I avoid issues like AI can finish things in just 2 hours, but I have to spend 20 hours.»&lt;/p&gt;
&lt;p&gt;Genau dort bricht die Messbarkeit. Wer die Aufgaben aussortiert, bei denen KI am meisten hilft, misst systematisch zu tief. METR räumt ein, dass die Ergebnisse den wahren Effekt wahrscheinlich unterschätzen. Dazu kommt: Manche Teilnehmenden liessen mehrere Agenten parallel laufen, was die Zeitmessung entwertet.&lt;/p&gt;
&lt;p&gt;Wenn Sie gerade einen Business Case für KI-Werkzeuge schreiben und merken, dass Ihnen die belastbare Zahl fehlt: Das liegt nicht an Ihrer Recherche. &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Eine halbe Stunde mit jemandem, der die Primärquellen gelesen hat&lt;/a&gt;, ist an dieser Stelle billiger als eine weitere Woche Suche.&lt;/p&gt;
&lt;h2 id=&quot;die-gegenzahl-aus-dem-anderen-lager-stammt-von-2022&quot;&gt;Die Gegenzahl aus dem anderen Lager stammt von 2022&lt;/h2&gt;
&lt;p&gt;Die berühmten 55 Prozent Beschleunigung sind eine Anbieterzahl aus dem Jahr 2022. &lt;a href=&quot;https://github.blog/news-insights/research/research-quantifying-github-copilots-impact-on-developer-productivity-and-happiness/&quot;&gt;GitHub Next veröffentlichte sie am 7. September 2022&lt;/a&gt;, gemeinsam mit dem Office of the Chief Economist von Microsoft. 95 Entwickelnde, zufällig in zwei Gruppen geteilt, eine einzige Aufgabe: einen HTTP-Server in JavaScript schreiben.&lt;/p&gt;
&lt;p&gt;Die Copilot-Gruppe brauchte 1 Stunde 11 Minuten, die Kontrollgruppe 2 Stunden 41 Minuten. Das Konfidenzintervall reicht von 21 bis 89 Prozent.&lt;/p&gt;
&lt;p&gt;Drei Dinge daran sollte man kennen, bevor man die Zahl in eine Präsentation setzt. Sie stammt vom Hersteller des getesteten Werkzeugs. Sie misst eine abgeschlossene Laboraufgabe ohne bestehende Codebasis, ohne Review und ohne Betrieb. Und sie ist vier Jahre alt, aus einer Zeit vor agentischen Werkzeugen.&lt;/p&gt;
&lt;h2 id=&quot;wer-welche-zahl-erhoben-hat-und-wer-sie-bezahlt-hat&quot;&gt;Wer welche Zahl erhoben hat, und wer sie bezahlt hat&lt;/h2&gt;
&lt;p&gt;Die folgende Gegenüberstellung ordnet die sechs Zahlen, die in dieser Debatte tatsächlich zirkulieren, nach Herkunft, Finanzierung und Haltbarkeit. Stand aller Abrufe: 20. August 2026.&lt;/p&gt;






















































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Zahl&lt;/th&gt;&lt;th&gt;Wer hat erhoben&lt;/th&gt;&lt;th&gt;Wer hat bezahlt&lt;/th&gt;&lt;th&gt;Stichprobe&lt;/th&gt;&lt;th&gt;Status im August 2026&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;55 % schneller&lt;/td&gt;&lt;td&gt;GitHub Next, Microsoft&lt;/td&gt;&lt;td&gt;GitHub, also Microsoft&lt;/td&gt;&lt;td&gt;95 Personen, eine Laboraufgabe&lt;/td&gt;&lt;td&gt;Anbieterzahl von 2022, für heutige Werkzeuge nicht gültig&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;19 % langsamer&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/&quot;&gt;METR&lt;/a&gt;&lt;/td&gt;&lt;td&gt;gemeinnützig, kein Anbieter&lt;/td&gt;&lt;td&gt;16 Personen, 246 Issues&lt;/td&gt;&lt;td&gt;von der eigenen Nachfolgestudie überholt&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;18 % bzw. 4 % schneller&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://metr.org/blog/2026-02-24-uplift-update/&quot;&gt;METR&lt;/a&gt;&lt;/td&gt;&lt;td&gt;gemeinnützig, kein Anbieter&lt;/td&gt;&lt;td&gt;57 Personen, 143 Repos, 800+ Aufgaben&lt;/td&gt;&lt;td&gt;aktuell, aber Intervall schliesst null ein&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;KI wirkt als Verstärker&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://dora.dev/research/&quot;&gt;DORA&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Google Cloud&lt;/td&gt;&lt;td&gt;State of DevOps 2025&lt;/td&gt;&lt;td&gt;letzter Stand, kein 2026er Report&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3,45 % gegen 7,40 % Breaking Changes&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://arxiv.org/abs/2603.27524&quot;&gt;Ferdous et al.&lt;/a&gt;&lt;/td&gt;&lt;td&gt;akademisch, arXiv&lt;/td&gt;&lt;td&gt;7’191 Agenten-PRs, 1’402 menschliche PRs&lt;/td&gt;&lt;td&gt;aktuell&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kontextdateien ohne Wirkung, +20 % Inferenzkosten&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://arxiv.org/abs/2602.11988&quot;&gt;Gloaguen et al., ETH Zürich&lt;/a&gt;&lt;/td&gt;&lt;td&gt;akademisch, arXiv&lt;/td&gt;&lt;td&gt;SWE-bench plus reale Repositories&lt;/td&gt;&lt;td&gt;aktuell, revidiert Juni 2026&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Die Finanzierungsspalte ist keine Höflichkeit. DORA ist ein Programm von Google Cloud, und Google verkauft mit Gemini, Jules und Antigravity konkurrierende Werkzeuge. Das macht die Methodik nicht schlecht, sie geniesst zu Recht Ansehen. Aber ein Report, der Firmen hilft, KI-Budgets zu verteidigen, hat einen Absender mit Interesse an KI-Budgets.&lt;/p&gt;
&lt;h2 id=&quot;der-verstärker-befund-ist-die-belastbarste-aussage-der-forschung&quot;&gt;Der Verstärker-Befund ist die belastbarste Aussage der Forschung&lt;/h2&gt;
&lt;p&gt;Die stabilste Erkenntnis lautet, dass KI-Werkzeuge vorhandene Engineering-Reife verstärken statt sie zu ersetzen. DORA formuliert es im &lt;a href=&quot;https://dora.dev/research/&quot;&gt;State of DevOps 2025&lt;/a&gt; so: «AI acts as an amplifier, but the greatest returns come from focusing on the underlying sociotechnical systems.»&lt;/p&gt;
&lt;p&gt;Zwei akademische Arbeiten aus 2026 zeigen denselben Mechanismus von unten. Die Untersuchung &lt;a href=&quot;https://arxiv.org/abs/2603.27524&quot;&gt;«Safer Builders, Risky Maintainers»&lt;/a&gt; von Ferdous, Banik, Chowdhury und Shamim verglich 7’191 agentenerzeugte Pull Requests mit 1’402 menschlichen aus Python-Repositories und erkannte Breaking Changes über eine AST-Analyse.&lt;/p&gt;

























&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Kontext&lt;/th&gt;&lt;th&gt;Rate an Breaking Changes&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Code-Generierung, Agenten&lt;/td&gt;&lt;td&gt;3,45 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Code-Generierung, Menschen&lt;/td&gt;&lt;td&gt;7,40 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Agenten beim Refactoring&lt;/td&gt;&lt;td&gt;6,72 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Agenten bei Chore-Änderungen&lt;/td&gt;&lt;td&gt;9,35 %&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Beim Neubau brechen Agenten seltener die Kompatibilität als Menschen. Bei Wartungsarbeiten kehrt sich das um. Die Autoren beschreiben zusätzlich eine «Confidence Trap»: Auch Pull Requests mit hohem Selbstvertrauens-Score des Agenten enthalten Breaking Changes. Der Score taugt nicht als Review-Filter.&lt;/p&gt;
&lt;p&gt;Die zweite Arbeit, &lt;a href=&quot;https://arxiv.org/abs/2607.26375&quot;&gt;«(Im)Paired Programming»&lt;/a&gt; von Balepur und Kollegen, liess 54 Studierende eine Website bauen, mit einem Agenten oder mit einem Chatbot, und prüfte danach das Verständnis über Verständnisfragen und über eine Erweiterungsaufgabe ohne Agent. Befund: Agenten helfen beim Fertigwerden und schaden dem Verständnis, und ausgerechnet die bequemen Interaktionsformen, Copy-Paste-Prompts und automatisch akzeptierte Edits, korrelieren mit dem schlechtesten Verständnis. Die Einschränkung gehört dazu: 54 Studierende sind kein Engineering-Team.&lt;/p&gt;
&lt;p&gt;Warum das die Verstärkerthese stützt: In beiden Arbeiten entscheidet nicht das Werkzeug, sondern wo und wie es eingesetzt wird. Dieselbe Beobachtung aus der Praxisseite, ohne Zahlen, steht in &lt;a href=&quot;https://devs-group.ch/blog/ki-code-ohne-technische-schulden/&quot;&gt;KI schreibt den Code, wer schreibt die Architektur&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;was-die-spannweite-für-eine-kapazitätsplanung-bedeutet&quot;&gt;Was die Spannweite für eine Kapazitätsplanung bedeutet&lt;/h2&gt;
&lt;p&gt;Das Konfidenzintervall der Zweitstudie ist zu breit, um damit zu budgetieren. Rechnen wir es einmal in Schweizer Franken durch, damit die Grössenordnung sichtbar wird.&lt;/p&gt;
&lt;p&gt;Modellrechnung, keine Erhebung: ein Team von zehn Entwickelnden, 1’800 Arbeitsstunden pro Person und Jahr, also 18’000 Stunden. Als Stundensatz nehmen wir CHF 160, den Mittelwert aus dem publizierten Rechenbeispiel von &lt;a href=&quot;https://www.gryps.ch/produkte/softwareentwicklung-13/individualsoftware-kosten/&quot;&gt;gryps.ch&lt;/a&gt; für Softwareentwicklung in der Deutschschweiz (abgerufen 20. August 2026). Die Jahreskapazität entspricht damit CHF 2’880’000.&lt;/p&gt;





























&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Szenario aus dem METR-Intervall&lt;/th&gt;&lt;th&gt;Zeitbedarf&lt;/th&gt;&lt;th&gt;Stunden pro Jahr&lt;/th&gt;&lt;th&gt;Gegenwert&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Untere Intervallgrenze&lt;/td&gt;&lt;td&gt;−38 %&lt;/td&gt;&lt;td&gt;6’840 Stunden frei&lt;/td&gt;&lt;td&gt;CHF 1’094’400&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Punktschätzer&lt;/td&gt;&lt;td&gt;−18 %&lt;/td&gt;&lt;td&gt;3’240 Stunden frei&lt;/td&gt;&lt;td&gt;CHF 518’400&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Obere Intervallgrenze&lt;/td&gt;&lt;td&gt;+9 %&lt;/td&gt;&lt;td&gt;1’620 Stunden zusätzlich&lt;/td&gt;&lt;td&gt;CHF 259’200&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Zwischen den beiden Intervallgrenzen liegen CHF 1’353’600. Mit einer solchen Bandbreite plant niemand ein Budget, und das ist die ehrliche Auskunft der Forschung, nicht ihr Versagen.&lt;/p&gt;
&lt;p&gt;Die Rechnung überträgt METRs Werte bewusst grob auf eine Jahreskapazität. METR hat Issue-artige Aufgaben in reifen Open-Source-Repositories gemessen, keine vollständigen Arbeitsjahre mit Meetings, Betrieb und Incidents. Wer die Zahlen eins zu eins auf sein Team überträgt, macht denselben Fehler wie die Lager, die er kritisiert.&lt;/p&gt;
&lt;h2 id=&quot;messen-sie-stattdessen-ihre-eigene-basislinie&quot;&gt;Messen Sie stattdessen Ihre eigene Basislinie&lt;/h2&gt;
&lt;p&gt;Die brauchbarste Reaktion auf eine unklare Studienlage ist eine eigene Vorher-Messung. Zwei Kennzahlen genügen für den Anfang, und beide liegen bereits in Ihrem Repository.&lt;/p&gt;
&lt;p&gt;Erstens ein Proxy für die Change Failure Rate, aus dem Git-Log über 90 Tage:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Alle Commits der letzten 90 Tage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; log&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --since=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;90 days ago&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --no-merges&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --oneline&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; wc&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -l&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Davon Reverts und Hotfixes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; log&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --since=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;90 days ago&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --no-merges&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --oneline&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  --grep=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;^Revert&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --grep=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;^hotfix&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --grep=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;^fix!&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; wc&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -l&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zweitens die Grösse der Änderungen pro Autor, um agentenerzeugte und menschliche Pull Requests zu trennen:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gh&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; pr&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; list&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --state&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; merged&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --limit&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 200&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  --json&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; number,author,additions,deletions,mergedAt&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  --jq&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;.[] | [.author.login, .additions + .deletions] | @tsv&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Erheben Sie beides einen Monat vor dem Rollout und drei Monate danach. Diese zwei Zahlen sagen mehr über Ihr Team aus als jede Studie in diesem Beitrag. Wie Sie die Entscheidungen dahinter festhalten, damit die Messung in einem Jahr noch interpretierbar ist, steht in &lt;a href=&quot;https://devs-group.ch/blog/architektur-entscheidungen-dokumentieren/&quot;&gt;Architekturentscheidungen dokumentieren&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;was-es-im-august-2026-nicht-gibt&quot;&gt;Was es im August 2026 nicht gibt&lt;/h2&gt;
&lt;p&gt;Drei häufig erwartete Quellen existieren zum Zeitpunkt dieses Beitrags nicht, und wer sie zitiert, zitiert etwas Erfundenes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Keinen State-of-DevOps-Report 2026.&lt;/strong&gt; &lt;a href=&quot;https://dora.dev/research/&quot;&gt;dora.dev/research&lt;/a&gt; führt 2025 als jüngsten Eintrag. Neu ist nur ein Zwischenprodukt, der «ROI of AI-assisted Software Development report», zuletzt aktualisiert am 22. April 2026, samt ROI-Rechner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keine Stack Overflow Developer Survey 2026.&lt;/strong&gt; Das &lt;a href=&quot;https://survey.stackoverflow.co/&quot;&gt;Archiv&lt;/a&gt; listet 2011 bis 2025. Die 2025er Ausgabe bleibt der Stand.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keinen Technology Radar Vol. 35.&lt;/strong&gt; &lt;a href=&quot;https://www.thoughtworks.com/radar&quot;&gt;Vol. 34 vom April 2026&lt;/a&gt; ist die aktuelle Ausgabe, mit «Putting coding agents on a leash» als einem der vier Themen.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wovon-wir-abraten&quot;&gt;Wovon wir abraten&lt;/h2&gt;
&lt;p&gt;Wir raten von drei Dingen ab, und das erste betrifft die Zahlen in diesem Beitrag selbst. Erstens: einen ROI-Business-Case auf einen Punktschätzer stützen, gleich aus welchem Lager. Die belastbare Aussage der Forschung ist eine Bandbreite, kein Wert.&lt;/p&gt;
&lt;p&gt;Zweitens: den Confidence-Score eines Agenten als Review-Filter benutzen. Die Confidence Trap aus «Safer Builders, Risky Maintainers» ist genau dieser Fehler, empirisch belegt. Staffeln Sie die Review-Tiefe stattdessen nach Aufgabentyp. Neubau darf lockerer laufen, Refactoring und Wartung brauchen strenge Kontrolle.&lt;/p&gt;
&lt;p&gt;Drittens: Auto-Accept als Standardeinstellung. Nach «(Im)Paired Programming» ist es die Interaktionsform mit dem schlechtesten Verständnisergebnis.&lt;/p&gt;
&lt;p&gt;Wo unsere Empfehlung nicht passt: bei Wegwerf-Prototypen und Spikes. Wer eine Woche lang eine Machbarkeit prüft und den Code danach löscht, braucht keine gestaffelte Review-Tiefe. Der Aufwand lohnt sich ab dem Moment, in dem jemand den Code in einem Jahr noch lesen muss.&lt;/p&gt;
&lt;p&gt;Und ein Schweizer Detail, das in der internationalen Debatte untergeht: Die methodisch sauberste Arbeit zu Kontextdateien für Coding-Agenten kommt von der ETH Zürich. Gloaguen, Mündler, Müller, Raychev und Vechev &lt;a href=&quot;https://arxiv.org/abs/2602.11988&quot;&gt;zeigten im Februar 2026&lt;/a&gt;, revidiert im Juni, dass &lt;code&gt;AGENTS.md&lt;/code&gt;-Dateien die Erfolgsrate generell nicht verbessern, die Inferenzkosten aber um über 20 Prozent erhöhen. Drei der Autoren sind mit LogicStar AG in Zürich verbunden, Martin Vechev leitet an der ETH das Secure, Reliable and Intelligent Systems Lab.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;stimmt-es-dass-ki-entwickler-19-prozent-langsamer-macht&quot;&gt;Stimmt es, dass KI Entwickler 19 Prozent langsamer macht?&lt;/h3&gt;
&lt;p&gt;Das war der Befund einer METR-Studie von Februar bis Juni 2025 mit 16 erfahrenen Open-Source-Entwicklern. Die Nachfolgestudie derselben Organisation, ab August 2025 mit 57 Entwickelnden und über 800 Aufgaben, misst das Gegenteil: 18 Prozent weniger Zeitbedarf bei den wiederkehrenden Teilnehmenden. Wer die 19 Prozent heute als Beleg anführt, zitiert den überholten Stand.&lt;/p&gt;
&lt;h3 id=&quot;woher-kommt-die-zahl-55-prozent-schneller&quot;&gt;Woher kommt die Zahl «55 Prozent schneller»?&lt;/h3&gt;
&lt;p&gt;Aus einer Untersuchung von GitHub Next und dem Office of the Chief Economist von Microsoft, publiziert am 7. September 2022. 95 Entwickelnde schrieben einen HTTP-Server in JavaScript, mit oder ohne Copilot. Es ist eine Anbieterzahl aus dem Jahr 2022, gemessen an einer einzelnen Laboraufgabe ohne bestehende Codebasis, ohne Review und ohne Betrieb.&lt;/p&gt;
&lt;h3 id=&quot;welche-aussage-der-forschung-ist-am-belastbarsten&quot;&gt;Welche Aussage der Forschung ist am belastbarsten?&lt;/h3&gt;
&lt;p&gt;Der Verstärker-Befund. DORA formuliert im State of DevOps 2025, KI wirke als Verstärker und die grössten Erträge entstünden durch Arbeit an den zugrunde liegenden soziotechnischen Systemen. Zwei akademische Arbeiten aus 2026 zeigen denselben Mechanismus im Detail: Der Effekt hängt vom Aufgabentyp und von der Arbeitsweise ab, nicht vom Werkzeug.&lt;/p&gt;
&lt;h3 id=&quot;warum-ist-der-produktivitätseffekt-so-schwer-zu-messen&quot;&gt;Warum ist der Produktivitätseffekt so schwer zu messen?&lt;/h3&gt;
&lt;p&gt;Weil die Teilnehmenden die Messung beeinflussen. Als METR die Vergütung von 150 auf 50 Dollar pro Stunde senkte, gaben 30 bis 50 Prozent der Entwickelnden an, bestimmte Aufgaben nicht einzureichen, weil sie diese nicht ohne KI erledigen wollten. Wer genau die Aufgaben aussortiert, bei denen KI am meisten hilft, misst systematisch zu tief.&lt;/p&gt;
&lt;h3 id=&quot;was-misst-man-im-eigenen-team-stattdessen&quot;&gt;Was misst man im eigenen Team stattdessen?&lt;/h3&gt;
&lt;p&gt;Zwei Kennzahlen aus dem eigenen Repository, je einmal vor und drei Monate nach der Einführung: die Rate an Reverts und Hotfixes über 90 Tage als Proxy für die Change Failure Rate, und die Änderungsgrösse pro Autor, um agentenerzeugte von menschlichen Pull Requests zu trennen. Beide sind mit &lt;code&gt;git log&lt;/code&gt; und &lt;code&gt;gh pr list&lt;/code&gt; in wenigen Minuten erhoben.&lt;/p&gt;
&lt;h2 id=&quot;legen-wir-ihre-zahlen-daneben&quot;&gt;Legen wir Ihre Zahlen daneben&lt;/h2&gt;
&lt;p&gt;Bringen Sie Ihre Git-Historie und die Frage mit, die Ihr Management Ihnen gestellt hat. Wir erheben die Basislinie gemeinsam und sagen Ihnen, welche der zitierten Studien auf Ihren Fall überhaupt zutrifft und welche nicht.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin buchen&lt;/a&gt; oder &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;schreiben Sie uns&lt;/a&gt;. Womit wir Teams beim Einsatz dieser Werkzeuge begleiten, steht unter &lt;a href=&quot;https://devs-group.ch/leistungen/kuenstliche-intelligenz/&quot;&gt;Künstliche Intelligenz &amp;amp; Machine Learning&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>KI-gestützte Entwicklung</category><author>Robert Pupel</author></item><item><title>CRA-Meldepflicht ab 11.9.2026 technisch umsetzen</title><link>https://devs-group.ch/blog/cra-meldepflicht-24-stunden-technisch-umsetzen/</link><guid isPermaLink="true">https://devs-group.ch/blog/cra-meldepflicht-24-stunden-technisch-umsetzen/</guid><description>24 Stunden bis zur Erstmeldung. Was Sie an SBOM, Monitoring und Meldekette gebaut haben müssen, bevor der Cyber Resilience Act greift.</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Die CRA-Meldepflicht trifft Hersteller von Produkten mit digitalen Elementen ab dem 11. September 2026: aktiv ausgenutzte Schwachstellen binnen 24 Stunden vorläufig melden, binnen 72 Stunden vollständig, den Abschlussbericht spätestens 14 Tage nach Verfügbarkeit einer Korrekturmassnahme. Gemeldet wird nach Art. 14 Abs. 1 CRA gleichzeitig an das koordinierende CSIRT und an die ENISA, über eine einzige Einreichung.&lt;/p&gt;
&lt;h2 id=&quot;was-ab-dem-11-september-2026-konkret-gilt&quot;&gt;Was ab dem 11. September 2026 konkret gilt&lt;/h2&gt;
&lt;p&gt;Artikel 14 der &lt;a href=&quot;https://eur-lex.europa.eu/legal-content/DE/TXT/?uri=OJ%3AL_202402847&quot;&gt;Verordnung (EU) 2024/2847&lt;/a&gt; gilt ab dem 11. September 2026, die übrigen Herstellerpflichten erst ab dem 11. Dezember 2027. Die Meldepflicht kommt also fünfzehn Monate vor allem anderen, was einen Hersteller trifft. Wer auf die volle Anwendbarkeit wartet, hat die erste Frist bereits verpasst.&lt;/p&gt;
&lt;p&gt;Ein drittes Datum geht dabei regelmässig unter: Kapitel IV zu den notifizierten Stellen (Artikel 35 bis 51) gilt schon seit dem 11. Juni 2026. Es betrifft die Konformitätsbewertungsstellen, nicht Sie als Hersteller.&lt;/p&gt;
&lt;p&gt;Zwei Auslöser, zwei Fristenketten:&lt;/p&gt;























&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Auslöser&lt;/th&gt;&lt;th&gt;Frühwarnung&lt;/th&gt;&lt;th&gt;Meldung&lt;/th&gt;&lt;th&gt;Abschlussbericht&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Aktiv ausgenutzte Schwachstelle im Produkt&lt;/td&gt;&lt;td&gt;24 h ab Kenntnis&lt;/td&gt;&lt;td&gt;72 h ab Kenntnis&lt;/td&gt;&lt;td&gt;14 Tage nach Verfügbarkeit einer Korrektur- oder Risikominderungsmassnahme&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Schwerwiegender Sicherheitsvorfall&lt;/td&gt;&lt;td&gt;24 h ab Kenntnis&lt;/td&gt;&lt;td&gt;72 h ab Kenntnis&lt;/td&gt;&lt;td&gt;ein Monat nach der Vorfallmeldung&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Die Frist läuft ab Kenntnis, nicht ab Bestätigung. Wer intern erst eine Freigaberunde dreht, verbrennt die Hälfte des Budgets. Verstösse gegen Artikel 13 und 14 sind nach Artikel 64 Absatz 2 CRA mit Bussgeldern bis 15 Mio. EUR oder 2,5 % des weltweiten Jahresumsatzes bewehrt, je nachdem, was höher ist.&lt;/p&gt;
&lt;h2 id=&quot;gilt-der-cyber-resilience-act-für-schweizer-unternehmen&quot;&gt;Gilt der Cyber Resilience Act für Schweizer Unternehmen?&lt;/h2&gt;
&lt;p&gt;Ja, sobald ein Produkt mit digitalen Elementen in der EU in Verkehr gebracht wird. Der Sitz in Kreuzlingen, Zug oder Zürich ändert daran nichts. Interessant wird nur, an welches CSIRT ein Hersteller ohne Niederlassung in der Union meldet.&lt;/p&gt;
&lt;p&gt;Artikel 14 Absatz 7 CRA löst das über eine Kaskade: massgeblich ist der Mitgliedstaat, in dem der Bevollmächtigte für die meisten Produkte sitzt. Fehlt der, der Einführer. Fehlt auch der, der Händler. Bleibt das offen, entscheidet der Mitgliedstaat mit den meisten Nutzern.&lt;/p&gt;
&lt;p&gt;Das ist eine Architekturentscheidung, keine juristische Fussnote. Wer heute nicht weiss, welches nationale CSIRT zuständig ist, registriert sich am 11. September nicht mehr rechtzeitig.&lt;/p&gt;
&lt;h2 id=&quot;wohin-die-meldung-geht-und-wer-ihre-gegenstelle-ist&quot;&gt;Wohin die Meldung geht, und wer Ihre Gegenstelle ist&lt;/h2&gt;
&lt;p&gt;Die Meldung hat zwei Empfänger und wird trotzdem nur einmal abgesetzt. Artikel 14 Absatz 1 CRA verpflichtet den Hersteller, eine aktiv ausgenutzte Schwachstelle gleichzeitig dem als Koordinator benannten CSIRT und der ENISA zu melden. Für schwerwiegende Sicherheitsvorfälle sagt Absatz 3 dasselbe.&lt;/p&gt;
&lt;p&gt;Der technische Weg ist einer. Nach Artikel 14 Absatz 7 CRA läuft die Meldung über den Meldeendpunkt des CSIRT, das im Mitgliedstaat der Hauptniederlassung als Koordinator benannt ist, und ist gleichzeitig für die ENISA zugänglich. Die Kommission fasst das auf ihrer &lt;a href=&quot;https://digital-strategy.ec.europa.eu/en/policies/cra-reporting&quot;&gt;Seite zu den CRA-Meldepflichten&lt;/a&gt; so: „Manufacturers report only once through the CRA Single Reporting Platform (SRP)”.&lt;/p&gt;
&lt;p&gt;Wer zurückfragt, ist das CSIRT. Nach Artikel 14 Absatz 6 kann es einen Zwischenbericht verlangen, und es validiert vorab Ihren Zugang zur Plattform. Die ENISA baut und betreibt sie. Wer wissen will, bei wem er im Ernstfall anruft: beim CSIRT der Hauptniederlassung.&lt;/p&gt;
&lt;p&gt;Für die Umsetzung sind drei Details aus der &lt;a href=&quot;https://www.enisa.europa.eu/topics/product-security/single-reporting-platform-srp/frequently-asked-questions&quot;&gt;ENISA-FAQ zur SRP&lt;/a&gt; (Stand 3. August 2026) wichtiger als jede Rechtsfrage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Es gibt vorerst keine API.&lt;/strong&gt; Sie können den Weg bis zum Absenden automatisieren, das Absenden selbst tippt ein Mensch in ein Browserformular.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Die Registrierung läuft über EU Login&lt;/strong&gt; (&lt;code&gt;ecas.ec.europa.eu&lt;/code&gt;), die Validierung anschliessend über das zuständige CSIRT. Beides dauert und gehört vor den Ernstfall.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Die Plattform war Mitte August 2026 noch nicht live&lt;/strong&gt;, die öffentliche URL noch nicht publiziert. Betriebsbereit soll sie zum 11. September sein.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Der letzte Meter Ihrer Kette ist also manuell. Umso wichtiger, dass die neunundvierzig Meter davor es nicht sind.&lt;/p&gt;
&lt;p&gt;Zwei Behörden werden dabei regelmässig falsch einsortiert. Das BSI ist seit &lt;a href=&quot;https://www.bsi.bund.de/DE/Service-Navi/Presse/Pressemitteilungen/Presse2025/251007_CRA_BSI_marktueberwachende_Behoerde.html&quot;&gt;Oktober 2025&lt;/a&gt; notifizierende und marktüberwachende Behörde für den CRA in Deutschland. Marktüberwachung ist aber nicht Meldungsentgegennahme.&lt;/p&gt;
&lt;p&gt;Und das BACS ist im CRA-Kontext gar keine Adresse. Es ist die Adressatin der Schweizer ISG-Meldepflicht, eines eigenen Regimes mit eigener Rechtsgrundlage. Wer beides zusammenwirft, meldet an der falschen Stelle.&lt;/p&gt;
&lt;h2 id=&quot;cra-meldepflicht-und-schweizer-isg-meldepflicht-nebeneinander&quot;&gt;CRA-Meldepflicht und Schweizer ISG-Meldepflicht nebeneinander&lt;/h2&gt;
&lt;p&gt;Zwei Regime, zwei Adressaten, zwei Rechtsgrundlagen, beide mit einer 24-Stunden-Frist. Ein Schweizer Softwarehersteller, der in die EU liefert und dessen Produkte von Schweizer kritischen Infrastrukturen genutzt werden, fällt unter beide. Wir haben die Gegenüberstellung gebaut, weil wir sie nirgends gefunden haben. Jede Zeile ist am Gesetzestext belegt.&lt;/p&gt;
















































































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;CRA (EU)&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;ISG-Meldepflicht (CH)&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Rechtsgrundlage&lt;/td&gt;&lt;td&gt;VO (EU) 2024/2847, Art. 14&lt;/td&gt;&lt;td&gt;ISG (SR 128), Art. 74a bis 74h, dazu CSV (SR 128.51)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Gilt seit&lt;/td&gt;&lt;td&gt;11.09.2026&lt;/td&gt;&lt;td&gt;01.04.2025, Sanktionen ab 01.10.2025&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Wer meldet&lt;/td&gt;&lt;td&gt;Hersteller von Produkten mit digitalen Elementen&lt;/td&gt;&lt;td&gt;Betreiberinnen kritischer Infrastrukturen, darunter Herstellerinnen von Hard- oder Software, deren Produkte von kritischen Infrastrukturen genutzt werden, sofern mit Fernwartungszugang oder eingesetzt zur Steuerung und Überwachung betriebstechnischer Systeme oder für die öffentliche Sicherheit (Art. 74b Abs. 1 lit. u)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Auslöser&lt;/td&gt;&lt;td&gt;aktiv ausgenutzte Schwachstelle im Produkt oder schwerwiegender Vorfall&lt;/td&gt;&lt;td&gt;Cyberangriff auf die eigenen Informatikmittel nach vier Kriterien (Art. 74d)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Gegenstand&lt;/td&gt;&lt;td&gt;das ausgelieferte Produkt&lt;/td&gt;&lt;td&gt;der eigene Betrieb&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Adressat&lt;/td&gt;&lt;td&gt;koordinierendes CSIRT der Hauptniederlassung und ENISA gleichzeitig, eine Einreichung (Art. 14 Abs. 1 und 7)&lt;/td&gt;&lt;td&gt;BACS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kanal&lt;/td&gt;&lt;td&gt;CRA Single Reporting Platform, EU-Login-Konto, keine API&lt;/td&gt;&lt;td&gt;Meldeformular im Cyber Security Hub des BACS, alternativ E-Mail-Formular&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Erstmeldung&lt;/td&gt;&lt;td&gt;24 h ab Kenntnis&lt;/td&gt;&lt;td&gt;24 h ab Entdeckung (Art. 74e Abs. 1)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Zweite Stufe&lt;/td&gt;&lt;td&gt;72 h&lt;/td&gt;&lt;td&gt;keine&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Abschluss&lt;/td&gt;&lt;td&gt;14 Tage nach Verfügbarkeit der Korrektur, bei Vorfällen ein Monat&lt;/td&gt;&lt;td&gt;14 Tage zur Ergänzung, gewährt durch das BACS (Art. 16 Abs. 1 CSV)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Nutzer informieren&lt;/td&gt;&lt;td&gt;ja, Art. 14 Abs. 8, möglichst maschinenlesbar&lt;/td&gt;&lt;td&gt;nicht vorgesehen&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Extraterritorial&lt;/td&gt;&lt;td&gt;ja, über Inverkehrbringen in der EU&lt;/td&gt;&lt;td&gt;ja, für Angriffe mit Auswirkung in der Schweiz, auch bei Systemen im Ausland (Art. 74b Abs. 3)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sanktion&lt;/td&gt;&lt;td&gt;bis 15 Mio. EUR oder 2,5 % Weltjahresumsatz (Art. 64 Abs. 2)&lt;/td&gt;&lt;td&gt;Busse bis CHF 100’000 gegen natürliche Personen, subsidiär bis CHF 20’000 gegen den Geschäftsbetrieb (Art. 74h)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Durchsetzung&lt;/td&gt;&lt;td&gt;Marktüberwachungsbehörden der Mitgliedstaaten&lt;/td&gt;&lt;td&gt;BACS setzt Frist, erlässt dann eine Verfügung mit Strafdrohung; Verfolgung durch die Kantone (Art. 74g)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Der interessanteste Unterschied steht in der letzten Zeile. Der CRA sanktioniert das Versäumnis direkt. Das ISG sanktioniert es nicht: Nach &lt;a href=&quot;https://www.fedlex.admin.ch/eli/cc/2022/232/de&quot;&gt;Art. 74g ISG&lt;/a&gt; setzt das BACS zuerst eine Frist, erlässt dann eine Verfügung, und erst deren vorsätzliche Missachtung ist nach Art. 74h strafbar.&lt;/p&gt;
&lt;p&gt;Dieselbe indirekte Konstruktion kennen wir aus dem revDSG, wo der EDÖB ebenfalls keine direkte Sanktionskompetenz hat. Wer die ISG-Meldepflicht deshalb für zahnlos hält, übersieht Art. 74h Abs. 1: Die Busse trifft natürliche Personen, nicht die GmbH.&lt;/p&gt;
&lt;p&gt;Die Zahlen dazu kommen vom BACS selbst. Im &lt;a href=&quot;https://www.ncsc.admin.ch/dam/ncsc/de/dokumente/dokumentation/lageberichte/BACS-HJB-2025-2_DE.pdf.download.pdf/BACS-HJB-2025-2_DE.pdf&quot;&gt;Halbjahresbericht 2025/2&lt;/a&gt; (publiziert 30.03.2026) verarbeitete das Amt 145 meldepflichtige Cybervorfälle im zweiten Halbjahr 2025, verteilt auf öffentlichen Sektor (25 %), IT und Telekommunikation (18 %) sowie Finanz und Versicherung (15,7 %). Daneben 64’733 freiwillige Meldungen im Gesamtjahr.&lt;/p&gt;
&lt;h2 id=&quot;was-sie-bauen-müssen-damit-24-stunden-reichen&quot;&gt;Was Sie bauen müssen, damit 24 Stunden reichen&lt;/h2&gt;
&lt;p&gt;Vier Artefakte müssen fertig sein, bevor die Uhr läuft. Keines lässt sich im Vorfall improvisieren.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Eine SBOM pro Release, unveränderlich gespeichert.&lt;/strong&gt; &lt;a href=&quot;https://eur-lex.europa.eu/legal-content/DE/TXT/?uri=OJ%3AL_202402847&quot;&gt;Anhang I Teil II Nummer 1 CRA&lt;/a&gt; verlangt eine Software-Stückliste in einem gängigen maschinenlesbaren Format, die mindestens die Top-Level-Abhängigkeiten abdeckt. Das ist der Rechtsboden, nicht das Ziel: Wer bei transitiven Abhängigkeiten aufhört zu schauen, findet Log4Shell-Klassen nicht.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eine rückwärtsgerichtete Auskunft.&lt;/strong&gt; Die Frage im Ernstfall lautet nicht „ist die Bibliothek verwundbar”, sondern „welche ausgelieferten Versionen enthalten sie und wer betreibt die”. Das muss eine Abfrage sein, keine Rekonstruktion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ein Alarmpfad mit benannter Person.&lt;/strong&gt; Nicht „das Security-Team”, sondern ein Name und eine Stellvertretung, mit Zugriff auf das registrierte EU-Login-Konto. Am Sonntag um drei.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ein Incident-Log mit UTC-Zeitstempeln.&lt;/strong&gt; Sie müssen nicht nur fristgerecht melden, Sie müssen es belegen können.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;fünf-jahre-support-ab-dem-11-dezember-2027&quot;&gt;Fünf Jahre Support, ab dem 11. Dezember 2027&lt;/h3&gt;
&lt;p&gt;Artikel 13 Absatz 8 CRA legt den Unterstützungszeitraum auf mindestens fünf Jahre fest, kürzer nur, wenn das Produkt erwartbar kürzer im Einsatz ist. Fünf Jahre Security-Updates heissen fünf Jahre lauffähige Build-Pipeline für jeden noch unterstützten Release-Zweig. Das ist die teuerste Pflicht des ganzen CRA, und sie steht in keiner Meldefrist.&lt;/p&gt;
&lt;p&gt;Wer nicht sicher ist, ob die eigene Kette von der Detektion bis zum abgesendeten Formular innerhalb eines Arbeitstags trägt, sollte sie einmal an einer echten, bereits behobenen Schwachstelle durchspielen und dabei mitstoppen. Als Übung ist das ein Nachmittag. Was auffällt, ist selten das Werkzeug und fast immer die Übergabe zwischen zwei Personen.&lt;/p&gt;
&lt;h2 id=&quot;sbom-in-der-pipeline-ein-aufbau-der-rückwirkend-auskunft-gibt&quot;&gt;SBOM in der Pipeline: ein Aufbau, der rückwirkend Auskunft gibt&lt;/h2&gt;
&lt;p&gt;Die SBOM gehört an den Image-Digest gebunden, nicht an den Tag. Tags werden überschrieben, Digests nicht. Der folgende Workflow erzeugt beide gängigen Formate, prüft gegen CVE-Feeds und signiert das Ergebnis keyless über OIDC. Versionen vom August 2026: Syft v1.51.0, Grype v0.117.0, cosign v3.1.3.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# .github/workflows/release.yml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;release&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    tags&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;v*&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;permissions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  contents&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;read&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  packages&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;write&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  id-token&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;            # keyless signing, kein Schlüsselmaterial im Repo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;jobs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  sbom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    runs-on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ubuntu-24.04&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    env&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      IMAGE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ghcr.io/${{ github.repository }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    steps&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;actions/checkout@v7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;docker/login-action@v4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          registry&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ghcr.io&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          username&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;${{ github.actor }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          password&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Bauen, pushen, Digest festhalten&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          docker build -t &amp;quot;$IMAGE:$GITHUB_REF_NAME&amp;quot; .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          docker push &amp;quot;$IMAGE:$GITHUB_REF_NAME&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          DIGEST=$(docker buildx imagetools inspect &amp;quot;$IMAGE:$GITHUB_REF_NAME&amp;quot; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                     --format &amp;#39;{{ .Manifest.Digest }}&amp;#39;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          echo &amp;quot;REF=$IMAGE@$DIGEST&amp;quot; &amp;gt;&amp;gt; &amp;quot;$GITHUB_ENV&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Werkzeuge auf feste Versionen pinnen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          curl -sSfL https://get.anchore.io/syft  | sh -s -- -b /usr/local/bin v1.51.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          curl -sSfL https://get.anchore.io/grype | sh -s -- -b /usr/local/bin v0.117.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;sigstore/cosign-installer@v4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          cosign-release&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;v3.1.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;SBOM in beiden Formaten erzeugen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          syft registry:&amp;quot;$REF&amp;quot; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            -o cyclonedx-json=sbom.cdx.json \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            -o spdx-json=sbom.spdx.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;Gegen CVE-Feeds prüfen, Build bei Kritischem stoppen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;grype &amp;quot;sbom:sbom.cdx.json&amp;quot; --fail-on critical&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;SBOM an den Digest binden und signieren&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;cosign attest --yes --type cyclonedx --predicate sbom.cdx.json &amp;quot;$REF&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;actions/upload-artifact@v7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;sbom-${{ github.ref_name }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;sbom.*.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          retention-days&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;90&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;       # GitHubs Maximum, deshalb nur ein Puffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der &lt;code&gt;upload-artifact&lt;/code&gt;-Schritt ist die schwächste Stelle und bewusst so gelassen: Produktiv gehören die SBOMs in einen Objektspeicher mit Versionierung und Object Lock, abfragbar nach Komponente. GitHub-Artefakte sind ein Zwischenschritt, kein Archiv. Mehr dazu in unserer &lt;a href=&quot;https://devs-group.ch/leistungen/kubernetes-and-infrastruktur/&quot;&gt;Arbeit an CI/CD und Supply Chain&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;das-incident-log-das-ihre-frist-belegt&quot;&gt;Das Incident-Log, das Ihre Frist belegt&lt;/h2&gt;
&lt;p&gt;Ein Incident-Log ist kein Ticket-Verlauf, sondern ein append-only Ereignisstrom mit UTC-Zeitstempeln. NDJSON reicht, eine Zeile pro Ereignis, &lt;code&gt;ts&lt;/code&gt; immer zuerst. Entscheidend ist der maschinell festgehaltene Zeitpunkt der Kenntnisnahme, den niemand später aus einer Slack-Historie rekonstruieren muss. Dieselbe Disziplin verlangt das revDSG für Personendaten; wie ein &lt;a href=&quot;https://devs-group.ch/blog/revdsg-konforme-ki-architektur/#wie-sieht-ein-audit-log-aus-das-eine-auskunftsanfrage-%C3%BCbersteht&quot;&gt;Audit-Log aussieht, das eine Auskunftsanfrage übersteht&lt;/a&gt;, haben wir separat beschrieben.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;jsonl&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;ts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2026-09-14T07:12:41Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;event&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;aware&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;incident&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;INC-2026-0007&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;cve&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;CVE-2026-31337&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;product&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;acme-gateway&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;affected_versions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;3.4.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;3.4.1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;component&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;pkg:golang/github.com/example/parser@1.8.2&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;evidence&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;WAF-Signatur 8841, 3 Treffer aus 2 Quell-ASN&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;actively_exploited&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;detected_by&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;grype-nightly+SIEM&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;owner&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;r.segi&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;ts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2026-09-14T07:41:02Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;event&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;triaged&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;incident&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;INC-2026-0007&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;regime&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;cra&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;isg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;cra_trigger&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;actively_exploited_vulnerability&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;due_early_warning&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2026-09-15T07:12:41Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;due_notification&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2026-09-17T07:12:41Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;csirt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;NCSC-NL&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;owner&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;r.segi&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;ts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2026-09-14T09:03:55Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;event&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;reported&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;incident&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;INC-2026-0007&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;channel&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;eu-srp&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;stage&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;early_warning&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;reference&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;SRP-2026-114872&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;elapsed_h&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.85&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;submitted_by&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;r.segi&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;ts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2026-09-14T10:26:33Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;event&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;reported&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;incident&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;INC-2026-0007&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;channel&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;ch-bacs-csh&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;stage&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;erstmeldung&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;reference&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;BACS-2026-3391&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;elapsed_h&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.23&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;submitted_by&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;r.segi&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;ts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2026-09-14T11:48:07Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;event&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;users_informed&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;incident&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;INC-2026-0007&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;format&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;csaf-2.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;https://acme.example/security/ACME-SA-2026-004&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die Fristen im &lt;code&gt;triaged&lt;/code&gt;-Ereignis werden gerechnet, nicht getippt. Das ist eine Funktion, kein Kalendereintrag:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Fristen nach Art. 14 CRA, gerechnet ab Kenntnisnahme in UTC.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Deadlines&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	EarlyWarning &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // 24 h ab Kenntnis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Notification &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // 72 h ab Kenntnis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Final        &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // 14 Tage nach Verfügbarkeit der Korrekturmassnahme&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; CRADeadlines&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;awareAt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;fixAvailableAt&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Deadlines&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	awareAt &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; awareAt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Deadlines&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		EarlyWarning: awareAt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; time.Hour),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Notification: awareAt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;72&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; time.Hour),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Final:        fixAvailableAt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;UTC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AddDate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Warum der Aufwand für ein Log, das hoffentlich nie gebraucht wird: Weil im Streitfall die Beweislast bei Ihnen liegt. Wer das Prinzip vertiefen will, findet es in &lt;a href=&quot;https://devs-group.ch/blog/observability-die-man-liest/&quot;&gt;Observability, die man liest&lt;/a&gt; und in &lt;a href=&quot;https://devs-group.ch/blog/architektur-entscheidungen-dokumentieren/&quot;&gt;Architektur-Entscheidungen dokumentieren&lt;/a&gt; ausgeführt.&lt;/p&gt;
&lt;h2 id=&quot;was-sie-jetzt-nicht-tun-sollten&quot;&gt;Was Sie jetzt nicht tun sollten&lt;/h2&gt;
&lt;p&gt;Kaufen Sie kein Compliance-Tool, bevor Sie die Meldekette einmal an einer echten Schwachstelle durchgespielt haben. Bei dieser Empfehlung bekommen wir am häufigsten Widerspruch, und wir bleiben dabei.&lt;/p&gt;
&lt;p&gt;Der Markt für CRA-Plattformen ist seit Frühjahr 2026 laut, und die Produkte lösen fast alle dasselbe Problem: Sie erzeugen Dokumente. Das Problem, das Ihnen die Frist reisst, ist die Stunde zwischen „ein Alert ist aufgelaufen” und „jemand mit Zugang hat entschieden, dass das meldepflichtig ist”.&lt;/p&gt;
&lt;p&gt;Der Trade-off, ehrlich benannt: Ein Werkzeug ist in zwei Wochen eingekauft, die Probe kostet einen Nachmittag plus die Korrekturen danach. Wer im September 2026 noch gar nichts hat, fährt mit gekauftem Werkzeug plus Probe besser.&lt;/p&gt;
&lt;p&gt;Wo unsere Empfehlung nicht passt: Bei mehr als einer Handvoll Produktlinien mit unterschiedlichen Bevollmächtigten in der EU wird „welches Produkt meldet an welches CSIRT” zur Datenhaltungsfrage. Dann ist ein Werkzeug ab Tag eins richtig. Bei einem Produkt und einem CSIRT ist es Geldverbrennung.&lt;/p&gt;
&lt;p&gt;Das Zweite, was Sie nicht tun sollten: die Registrierung auf den Ernstfall verschieben. EU Login anlegen, CSIRT bestimmen, Validierung anstossen. Ein Vormittag, und die einzige Aufgabe, die sich am 11. September nicht nachholen lässt.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;ab-wann-gilt-die-cra-meldepflicht&quot;&gt;Ab wann gilt die CRA-Meldepflicht?&lt;/h3&gt;
&lt;p&gt;Ab dem 11. September 2026, über Artikel 14 der Verordnung (EU) 2024/2847. Dann laufen drei Fristen: 24 Stunden bis zur Frühwarnung, 72 Stunden bis zur vollständigen Meldung, 14 Tage nach Verfügbarkeit einer Korrekturmassnahme bis zum Abschlussbericht, bei Vorfällen ein Monat.&lt;/p&gt;
&lt;p&gt;Die übrigen Herstellerpflichten werden erst am 11. Dezember 2027 anwendbar. Kapitel IV zu den notifizierten Stellen gilt bereits seit dem 11. Juni 2026.&lt;/p&gt;
&lt;h3 id=&quot;wer-muss-nach-dem-cra-melden&quot;&gt;Wer muss nach dem CRA melden?&lt;/h3&gt;
&lt;p&gt;Der Hersteller des Produkts mit digitalen Elementen, unabhängig vom Sitz, sobald das Produkt in der EU in Verkehr gebracht wird. Meldepflichtig sind aktiv ausgenutzte Schwachstellen im Produkt und schwerwiegende Sicherheitsvorfälle, die dessen Sicherheit beeinträchtigen. Bestandsprodukte sind eingeschlossen. Zusätzlich müssen betroffene Nutzer informiert werden, nach Artikel 14 Absatz 8 möglichst in einem strukturierten, maschinell verarbeitbaren Format.&lt;/p&gt;
&lt;h3 id=&quot;was-ist-eine-sbom-und-wofür-brauche-ich-sie&quot;&gt;Was ist eine SBOM und wofür brauche ich sie?&lt;/h3&gt;
&lt;p&gt;Eine SBOM (Software Bill of Materials) ist ein maschinenlesbares Inventar aller Komponenten eines Software-Artefakts, üblicherweise im Format CycloneDX oder SPDX. Der CRA verlangt sie in Anhang I Teil II Nummer 1 mindestens für die Top-Level-Abhängigkeiten. Praktisch brauchen Sie sie, um innerhalb von Stunden zu beantworten, welche ausgelieferten Versionen eine gerade bekannt gewordene verwundbare Komponente enthalten.&lt;/p&gt;
&lt;h3 id=&quot;muss-ein-schweizer-unternehmen-doppelt-melden&quot;&gt;Muss ein Schweizer Unternehmen doppelt melden?&lt;/h3&gt;
&lt;p&gt;Möglicherweise ja, aber an verschiedene Stellen und aus verschiedenen Gründen. Der CRA adressiert Sie als Hersteller eines EU-Produkts und meint dessen Schwachstellen. Die ISG-Meldepflicht adressiert Sie als Betreiberin kritischer Infrastruktur und meint Angriffe auf Ihre eigenen Systeme. Ein Ransomware-Vorfall in Ihrem Build-System kann beides gleichzeitig auslösen.&lt;/p&gt;
&lt;h3 id=&quot;was-passiert-wenn-die-single-reporting-platform-am-11-september-nicht-läuft&quot;&gt;Was passiert, wenn die Single Reporting Platform am 11. September nicht läuft?&lt;/h3&gt;
&lt;p&gt;Die Meldepflicht entsteht aus Artikel 14, nicht aus der Verfügbarkeit der Plattform. Mitte August 2026 war die SRP noch nicht live und ihre URL noch nicht publiziert. Protokollieren Sie den Zeitpunkt der Kenntnisnahme und jeden Zustellversuch, samt Vermerk, wenn eine Einreichung technisch nicht möglich war. In dieser Lage ist ein lückenloses Log das einzige, was Sie in der Hand haben.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Wenn die Kette noch nicht steht.&lt;/strong&gt; Bis zum 11. September bleiben zwei Wochen, bis zur ersten realistischen Meldung vermutlich länger. Wenn Sie wissen wollen, ob Ihre Kette von der Detektion bis zum abgesendeten Formular trägt: 30 Minuten mit einem Engineer, der SBOM-Pipelines gebaut und in regulierten Umgebungen wie dem &lt;a href=&quot;https://devs-group.ch/projekte/formularservice-bit/&quot;&gt;Formularservice für das BIT&lt;/a&gt; gearbeitet hat. Kein Verkaufsgespräch, keine Folien.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin direkt buchen&lt;/a&gt; oder kurz über &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt&lt;/a&gt; schreiben, was Sie bauen. Wir sagen Ihnen, wo wir die Frist reissen sehen.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Alle Rechtsangaben geprüft am 19.08.2026 an EUR-Lex und Fedlex. Dieser Beitrag beschreibt die technische Umsetzung, er ist keine Rechtsberatung.&lt;/em&gt;&lt;/p&gt;</content:encoded><category>Security &amp; Compliance</category><author>Ralph Segi</author></item><item><title>revDSG-konforme KI-Architektur: was wirklich zählt</title><link>https://devs-group.ch/blog/revdsg-konforme-ki-architektur/</link><guid isPermaLink="true">https://devs-group.ch/blog/revdsg-konforme-ki-architektur/</guid><description>Die Busse bis CHF 250&apos;000 trifft die handelnde Person, nicht die Firma. Was das für die Architektur eines KI-Systems heisst, Norm für Norm.</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Unter dem revidierten Datenschutzgesetz haftet für einen Verstoss die handelnde natürliche Person mit einer Busse bis CHF 250’000, nicht das Unternehmen. Das ist der Unterschied zur DSGVO, der die meisten Architekturentscheide prägt, und er steht nicht im Pflichtenkatalog, sondern im Strafrecht.&lt;/p&gt;
&lt;p&gt;Verboten ist der Einsatz von KI damit nicht. Das revDSG verlangt vier Dinge: eine zweckgebundene Bearbeitung nach den Grundsätzen von Art. 6 DSG, Transparenz über die Beschaffung nach Art. 19, Datensicherheit nach Art. 8 in Verbindung mit der Datenschutzverordnung (DSV), und bei automatisierten Einzelentscheidungen das Recht auf Überprüfung durch eine natürliche Person nach Art. 21.&lt;/p&gt;
&lt;p&gt;Die Rechtsabteilung fragt nach Konformität. Was man dazu findet, sind Gutachten: Sie sagen, was gilt, nicht, welche technische Massnahme das erfüllt. Hier steht die zweite Hälfte.&lt;/p&gt;
&lt;h2 id=&quot;welche-vier-anforderungen-stellt-das-revdsg-an-ein-ki-system&quot;&gt;Welche vier Anforderungen stellt das revDSG an ein KI-System?&lt;/h2&gt;
&lt;p&gt;Das revDSG ist das totalrevidierte Bundesgesetz über den Datenschutz vom 25. September 2020 (SR 235.1), in Kraft seit dem 1. September 2023. Vier seiner Normen bestimmen, wie ein KI-System gebaut sein muss. Verbindlich ist der &lt;a href=&quot;https://www.fedlex.admin.ch/eli/cc/2022/491/de&quot;&gt;Gesetzestext auf Fedlex&lt;/a&gt;, keine Zusammenfassung.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Art. 6 DSG, Grundsätze.&lt;/strong&gt; Personendaten dürfen nur zu einem bestimmten, erkennbaren Zweck beschafft werden und müssen weg, sobald sie dafür nicht mehr erforderlich sind. Der Zweck muss pro Verarbeitungsschritt festhaltbar sein, nicht pro Produkt.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Art. 19 DSG, Informationspflicht.&lt;/strong&gt; Die betroffene Person erfährt Identität des Verantwortlichen, Zweck und Kategorien der Empfänger. Ein Inferenzanbieter ist ein Empfänger. Geht es ins Ausland, kommen nach Abs. 4 der Staat und die Garantien nach Art. 16 Abs. 2 dazu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Art. 8 DSG, Datensicherheit.&lt;/strong&gt; Die Mindestanforderungen stehen in der &lt;a href=&quot;https://www.fedlex.admin.ch/eli/cc/2022/568/de&quot;&gt;DSV&lt;/a&gt;. Art. 2 DSV nennt vier Ziele: Vertraulichkeit, Verfügbarkeit, Integrität, Nachvollziehbarkeit. Am vierten scheitern KI-Systeme.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Art. 21 DSG, automatisierte Einzelentscheidung.&lt;/strong&gt; Beruht ein Entscheid ausschliesslich auf automatisierter Bearbeitung und ist er mit einer Rechtsfolge verbunden oder beeinträchtigt er die betroffene Person erheblich, gilt eine Informationspflicht. Die betroffene Person kann verlangen, dass ein Mensch den Entscheid überprüft.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Dazu kommt Art. 7 DSG: Die Bearbeitung ist ab der Planung technisch so auszugestalten, dass die Vorschriften eingehalten werden. Der Artikel, der die Rechtsfrage zur Architekturfrage macht.&lt;/p&gt;
&lt;h2 id=&quot;wer-zahlt-die-busse-wenn-ein-ki-system-gegen-das-revdsg-verstösst&quot;&gt;Wer zahlt die Busse, wenn ein KI-System gegen das revDSG verstösst?&lt;/h2&gt;
&lt;p&gt;Die natürliche Person zahlt, nicht das Unternehmen. Art. 60 bis 62 DSG stellen private Personen mit Busse bis CHF 250’000 unter Strafe. Der Geschäftsbetrieb kommt nur subsidiär ins Spiel: Nach Art. 64 Abs. 2 DSG kann die Behörde ihn statt der handelnden Personen verurteilen, wenn eine Busse von höchstens CHF 50’000 in Betracht fällt.&lt;/p&gt;
&lt;p&gt;Die für ein KI-Projekt einschlägige Norm ist meist nicht Art. 60, sondern &lt;strong&gt;Art. 61 DSG, Verletzung von Sorgfaltspflichten&lt;/strong&gt;. Er trifft genau die drei Fehler, die eine Architektur macht:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bekanntgabe ins Ausland entgegen Art. 16 Abs. 1 und 2, ohne dass die Voraussetzungen nach Art. 17 erfüllt sind (lit. a)&lt;/li&gt;
&lt;li&gt;Übergabe an einen Auftragsbearbeiter entgegen Art. 9 Abs. 1 und 2 (lit. b)&lt;/li&gt;
&lt;li&gt;Mindestanforderungen an die Datensicherheit nach Art. 8 Abs. 3 nicht eingehalten (lit. c)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Der EDÖB verhängt diese Bussen nicht. Nach Art. 65 Abs. 1 DSG obliegen Verfolgung und Beurteilung den Kantonen, in der Regel den Staatsanwaltschaften. Er kann verfügen und Anzeige erstatten, wie er auf seiner &lt;a href=&quot;https://www.edoeb.admin.ch/de/strafbestimmungen&quot;&gt;Seite zu den Strafbestimmungen&lt;/a&gt; selbst festhält.&lt;/p&gt;


















































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Punkt&lt;/th&gt;&lt;th&gt;revDSG&lt;/th&gt;&lt;th&gt;DSGVO&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Sanktionsadressat&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;die handelnde natürliche Person (Art. 60 bis 62 DSG); der Geschäftsbetrieb nur subsidiär (Art. 64 Abs. 2)&lt;/td&gt;&lt;td&gt;der Verantwortliche oder Auftragsverarbeiter als Unternehmen (Art. 83)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Bussenhöhe&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;bis CHF 250’000; Unternehmensbusse bis CHF 50’000&lt;/td&gt;&lt;td&gt;bis EUR 20 Mio. oder 4 % des weltweiten Jahresumsatzes, je nachdem, was höher ist (Art. 83 Abs. 5)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Verschulden&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;nur Vorsatz; Art. 60 Abs. 1, 61 und 62 sind Antragsdelikte&lt;/td&gt;&lt;td&gt;auch Fahrlässigkeit wird sanktioniert (Art. 83 Abs. 2 lit. b)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Wer verfolgt&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;kantonale Strafverfolgungsbehörden (Art. 65 Abs. 1); der EDÖB verfügt, sanktioniert aber nicht&lt;/td&gt;&lt;td&gt;die Aufsichtsbehörde verhängt die Geldbusse selbst&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Meldung einer Sicherheitsverletzung&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;„so rasch als möglich” an den EDÖB, wenn voraussichtlich hohes Risiko (Art. 24 Abs. 1)&lt;/td&gt;&lt;td&gt;unverzüglich, möglichst binnen 72 Stunden (Art. 33 Abs. 1)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Automatisierte Einzelentscheidung&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;zulässig; Informationspflicht, auf Antrag Überprüfung durch einen Menschen (Art. 21)&lt;/td&gt;&lt;td&gt;grundsätzlich untersagt, zulässig nur in den Fällen von Art. 22 Abs. 2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Auftragsbearbeitung&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Voraussetzungen in Art. 9; Unterauftrag nur mit vorgängiger Genehmigung (Art. 9 Abs. 3)&lt;/td&gt;&lt;td&gt;detaillierter Pflichtkatalog für den Vertrag (Art. 28)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Verjährung der Strafverfolgung&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;fünf Jahre (Art. 66)&lt;/td&gt;&lt;td&gt;in der DSGVO nicht geregelt, richtet sich nach nationalem Recht&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Praktische Folge: Unter der DSGVO ist Compliance ein Bilanzrisiko und wird delegiert. Unter dem revDSG ist sie persönlich. Wer ein Agentensystem freigibt, unterschreibt mit seinem Namen.&lt;/p&gt;
&lt;h2 id=&quot;was-ändert-sich-bei-besonders-schützenswerten-personendaten&quot;&gt;Was ändert sich bei besonders schützenswerten Personendaten?&lt;/h2&gt;
&lt;p&gt;Bei besonders schützenswerten Personendaten verschärfen sich drei Pflichten. Art. 5 lit. c DSG zählt die Kategorien abschliessend auf: Gesundheit, Intimsphäre und Zugehörigkeit zu einer Rasse oder Ethnie, genetische Daten, biometrische Daten, die eine Person eindeutig identifizieren, religiöse, weltanschauliche, politische oder gewerkschaftliche Ansichten, Daten über verwaltungs- und strafrechtliche Verfolgungen sowie Daten über Massnahmen der sozialen Hilfe.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Die Einwilligung muss ausdrücklich sein&lt;/strong&gt; (Art. 6 Abs. 7 lit. a DSG). Ein Hinweis in der Nutzungsordnung genügt nicht.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Datenschutz-Folgenabschätzung&lt;/strong&gt; bei umfangreicher Bearbeitung (Art. 22 Abs. 2 lit. a DSG).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protokollierung&lt;/strong&gt;, wenn sie in grossem Umfang automatisiert bearbeitet werden oder ein Profiling mit hohem Risiko stattfindet, und präventive Massnahmen den Datenschutz nicht gewährleisten können (Art. 4 Abs. 1 DSV). Beide Bedingungen müssen zusammenkommen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bearbeitungsreglement&lt;/strong&gt; bereits dann, wenn sie in grossem Umfang bearbeitet werden oder ein Profiling mit hohem Risiko stattfindet (Art. 5 Abs. 1 DSV). Ohne die Einschränkung der Protokollierungspflicht.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Der Haken für ein Agentensystem ist die Klassifikation zur Laufzeit. Ein Freitext-Prompt aus einem HR- oder Supportkanal enthält solche Daten, ohne dass ein Datenbankfeld sie markiert. Wer sie nicht erkennt, protokolliert zu wenig. Deshalb führt das Audit-Log unten ein Feld &lt;code&gt;data_classes&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;wo-landen-personendaten-in-einem-agentensystem-tatsächlich&quot;&gt;Wo landen Personendaten in einem Agentensystem tatsächlich?&lt;/h2&gt;
&lt;p&gt;Personendaten landen an sieben Stellen, und das Modell ist die harmloseste davon. Souveränität bricht fast nie beim Inferenzanbieter, sondern an der Peripherie, weil dort niemand hinschaut.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prompt.&lt;/strong&gt; Was die Nutzerin eintippt. Der einzige Ort, an dem die meisten Konzepte hinsehen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Systemkontext.&lt;/strong&gt; Retrieval-Ergebnisse, Few-Shot-Beispiele, Stammdaten aus dem CRM. Oft mehr Personendaten als im Prompt, und niemand hat sie bewusst dorthin gegeben.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool-Aufrufe.&lt;/strong&gt; Der Agent ruft eine API mit Argumenten auf. Diese Argumente sind Personendaten und gehen an ein zweites System.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vektordatenbank.&lt;/strong&gt; Ein Vektorindex über Kundenkorrespondenz ist eine Personendatensammlung mit ungewohntem Dateiformat und braucht dieselben Löschpfade wie die Quelle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logs.&lt;/strong&gt; Ein Stacktrace enthält den Payload, ein Debug-Log den ganzen Prompt.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Telemetrie.&lt;/strong&gt; Die GenAI-Semantikkonventionen von OpenTelemetry definieren &lt;code&gt;gen_ai.input.messages&lt;/code&gt;, &lt;code&gt;gen_ai.output.messages&lt;/code&gt; und &lt;code&gt;gen_ai.system_instructions&lt;/code&gt; als Span-Attribute. Sie stehen auch nach dem Umzug in ein eigenes Repository mit Release v1.42.0 vom 12.06.2026 im Status „Development” (&lt;a href=&quot;https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/&quot;&gt;Attributregister&lt;/a&gt;) und transportieren den vollständigen Gesprächsinhalt.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitoring- und Eval-SaaS.&lt;/strong&gt; Error-Tracking, Tracing, Prompt-Evaluation. Drei Dienste, die selten in einer Vertragsprüfung auftauchen und oft im Drittstaat laufen.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;scroll-x scroll-x--diagram&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Diagramm, seitlich scrollbar&quot;&gt;&lt;svg id=&quot;mermaid-0&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot; class=&quot;flowchart&quot; style=&quot;width:2707.9375px&quot; viewBox=&quot;0 0 2707.9375 709.3096923828125&quot; role=&quot;graphics-document document&quot; aria-roledescription=&quot;flowchart-v2&quot;&gt;&lt;style&gt;#mermaid-0{font-family:&quot;Geist&quot;,sans-serif;font-size:16px;fill:#f5f5f5;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-0 .error-icon{fill:#121315;}#mermaid-0 .error-text{fill:#edecea;stroke:#edecea;}#mermaid-0 .edge-thickness-normal{stroke-width:1px;}#mermaid-0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-0 .marker{fill:#c4c4c4;stroke:#c4c4c4;}#mermaid-0 .marker.cross{stroke:#c4c4c4;}#mermaid-0 svg{font-family:&quot;Geist&quot;,sans-serif;font-size:16px;}#mermaid-0 p{margin:0;}#mermaid-0 .label{font-family:&quot;Geist&quot;,sans-serif;color:#f5f5f5;}#mermaid-0 .cluster-label text{fill:#f5f5f5;}#mermaid-0 .cluster-label span{color:#f5f5f5;}#mermaid-0 .cluster-label span p{background-color:transparent;}#mermaid-0 .label text,#mermaid-0 span{fill:#f5f5f5;color:#f5f5f5;}#mermaid-0 .node rect,#mermaid-0 .node circle,#mermaid-0 .node ellipse,#mermaid-0 .node polygon,#mermaid-0 .node path{fill:#1b1d20;stroke:#363739;stroke-width:1px;}#mermaid-0 .rough-node .label text,#mermaid-0 .node .label text,#mermaid-0 .image-shape .label,#mermaid-0 .icon-shape .label{text-anchor:middle;}#mermaid-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-0 .rough-node .label,#mermaid-0 .node .label,#mermaid-0 .image-shape .label,#mermaid-0 .icon-shape .label{text-align:center;}#mermaid-0 .node.clickable{cursor:pointer;}#mermaid-0 .root .anchor path{fill:#c4c4c4!important;stroke-width:0;stroke:#c4c4c4;}#mermaid-0 .arrowheadPath{fill:#f6f5f3;}#mermaid-0 .edgePath .path{stroke:#c4c4c4;stroke-width:1px;}#mermaid-0 .flowchart-link{stroke:#c4c4c4;fill:none;}#mermaid-0 .edgeLabel{background-color:#090a0c;text-align:center;}#mermaid-0 .edgeLabel p{background-color:#090a0c;}#mermaid-0 .edgeLabel rect{opacity:0.5;background-color:#090a0c;fill:#090a0c;}#mermaid-0 .labelBkg{background-color:rgba(9, 10, 12, 0.5);}#mermaid-0 .cluster rect{fill:#121315;stroke:#232325;stroke-width:1px;}#mermaid-0 .cluster text{fill:#f5f5f5;}#mermaid-0 .cluster span{color:#f5f5f5;}#mermaid-0 .node .collapsed-indicator{fill:#232325;stroke:none;opacity:0.6;}#mermaid-0 .node .collapsed-separator{stroke:#232325;stroke-width:0.75px;}#mermaid-0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:&quot;Geist&quot;,sans-serif;font-size:12px;background:#121315;border:1px solid hsl(220, 0%, 17.6470588235%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#f5f5f5;}#mermaid-0 rect.text{fill:none;stroke-width:0;}#mermaid-0 .icon-shape,#mermaid-0 .image-shape{background-color:#090a0c;text-align:center;}#mermaid-0 .icon-shape p,#mermaid-0 .image-shape p{background-color:#090a0c;padding:2px;}#mermaid-0 .icon-shape .label rect,#mermaid-0 .image-shape .label rect{opacity:0.5;background-color:#090a0c;fill:#090a0c;}#mermaid-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-0 .node .neo-node{stroke:#363739;}#mermaid-0 [data-look=&quot;neo&quot;].node rect,#mermaid-0 [data-look=&quot;neo&quot;].cluster rect,#mermaid-0 [data-look=&quot;neo&quot;].node polygon{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].swimlane.cluster rect{filter:none;}#mermaid-0 [data-look=&quot;neo&quot;].node path{stroke:url(#mermaid-0-gradient);stroke-width:1px;}#mermaid-0 [data-look=&quot;neo&quot;].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].node .neo-line path{stroke:#363739;filter:none;}#mermaid-0 [data-look=&quot;neo&quot;].node circle{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].node circle .state-start{fill:#000000;}#mermaid-0 [data-look=&quot;neo&quot;].icon-shape .icon{fill:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].icon-shape .icon-neo path{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 :root{--mermaid-font-family:&quot;Geist&quot;,sans-serif;}#mermaid-0 .leak&gt;*{stroke-dasharray:6,4!important;}#mermaid-0 .leak span{stroke-dasharray:6,4!important;}&lt;/style&gt;&lt;g&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointEnd&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;5&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;8&quot; markerHeight=&quot;8&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 0 L 10 5 L 0 10 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointStart&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;4.5&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;8&quot; markerHeight=&quot;8&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 5 L 10 10 L 10 0 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointEnd-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 11.5 14&quot; refX=&quot;11.5&quot; refY=&quot;7&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;10.5&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 0 L 11.5 7 L 0 14 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointStart-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 11.5 14&quot; refX=&quot;1&quot; refY=&quot;7&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11.5&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;polygon points=&quot;0,7 11.5,14 11.5,0&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/polygon&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleEnd&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;11&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleStart&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;-1&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleEnd-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refY=&quot;5&quot; refX=&quot;12.25&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;14&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleStart-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;-2&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;14&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossEnd&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 11 11&quot; refX=&quot;12&quot; refY=&quot;5.2&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 l 9,9 M 10,1 l -9,9&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossStart&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 11 11&quot; refX=&quot;-1&quot; refY=&quot;5.2&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 l 9,9 M 10,1 l -9,9&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossEnd-margin&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 15 15&quot; refX=&quot;17.7&quot; refY=&quot;7.5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;12&quot; markerHeight=&quot;12&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 L 14,14 M 1,14 L 14,1&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2.5&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossStart-margin&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 15 15&quot; refX=&quot;-3.5&quot; refY=&quot;7.5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;12&quot; markerHeight=&quot;12&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 L 14,14 M 1,14 L 14,1&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2.5;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;g class=&quot;root&quot;&gt;&lt;g class=&quot;clusters&quot;&gt;&lt;g class=&quot;cluster&quot; id=&quot;mermaid-0-US&quot; data-look=&quot;classic&quot;&gt;&lt;rect style=&quot;&quot; x=&quot;8&quot; y=&quot;313&quot; width=&quot;776.546875&quot; height=&quot;184.4264678955078&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;cluster-label&quot; transform=&quot;translate(335.6953125, 313)&quot;&gt;&lt;foreignObject width=&quot;121.15625&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Jurisdiktion USA&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;cluster&quot; id=&quot;mermaid-0-EU&quot; data-look=&quot;classic&quot;&gt;&lt;rect style=&quot;&quot; x=&quot;804.546875&quot; y=&quot;313&quot; width=&quot;330&quot; height=&quot;184.4264678955078&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;cluster-label&quot; transform=&quot;translate(914.3671875, 313)&quot;&gt;&lt;foreignObject width=&quot;110.359375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Jurisdiktion EU&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;cluster&quot; id=&quot;mermaid-0-CH&quot; data-look=&quot;classic&quot;&gt;&lt;rect style=&quot;&quot; x=&quot;1154.546875&quot; y=&quot;8&quot; width=&quot;1545.390625&quot; height=&quot;693.3097229003906&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;cluster-label&quot; transform=&quot;translate(1851.5859375, 8)&quot;&gt;&lt;foreignObject width=&quot;151.3125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Jurisdiktion Schweiz&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgePaths&quot;&gt;&lt;path d=&quot;M1862.063,135L1862.063,139.167C1862.063,143.333,1862.063,151.667,1862.063,159.333C1862.063,167,1862.063,174,1862.063,177.5L1862.063,181&quot; id=&quot;mermaid-0-L_U_APP_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_U_APP_0&quot; data-points=&quot;W3sieCI6MTg2Mi4wNjI1LCJ5IjoxMzV9LHsieCI6MTg2Mi4wNjI1LCJ5IjoxNjB9LHsieCI6MTg2Mi4wNjI1LCJ5IjoxODV9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1870.5,239L1872.427,245.167C1874.354,251.333,1878.208,263.667,1880.135,276C1882.063,288.333,1882.063,300.667,1882.063,310.333C1882.063,320,1882.063,327,1882.063,330.5L1882.063,334&quot; id=&quot;mermaid-0-L_APP_VDB_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_APP_VDB_0&quot; data-points=&quot;W3sieCI6MTg3MC41LCJ5IjoyMzl9LHsieCI6MTg4Mi4wNjI1LCJ5IjoyNzZ9LHsieCI6MTg4Mi4wNjI1LCJ5IjozMTN9LHsieCI6MTg4Mi4wNjI1LCJ5IjozMzh9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1947.563,223.657L2011.551,232.381C2075.539,241.104,2203.516,258.552,2267.504,273.443C2331.492,288.333,2331.492,300.667,2331.492,314.826C2331.492,328.985,2331.492,344.97,2331.492,352.962L2331.492,360.954&quot; id=&quot;mermaid-0-L_APP_CRM_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_APP_CRM_0&quot; data-points=&quot;W3sieCI6MTk0Ny41NjI1LCJ5IjoyMjMuNjU2Njk3Nzg4MjA3MX0seyJ4IjoyMzMxLjQ5MjE4NzUsInkiOjI3Nn0seyJ4IjoyMzMxLjQ5MjE4NzUsInkiOjMxM30seyJ4IjoyMzMxLjQ5MjE4NzUsInkiOjM2NC45NTQ0MTA1NTI5Nzg1fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1815.508,239L1804.875,245.167C1794.242,251.333,1772.977,263.667,1762.344,276C1751.711,288.333,1751.711,300.667,1643.679,319.57C1535.647,338.473,1319.583,363.946,1211.551,376.682L1103.519,389.419&quot; id=&quot;mermaid-0-L_APP_INF_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_APP_INF_0&quot; data-points=&quot;W3sieCI6MTgxNS41MDc5MzQ1NzAzMTI1LCJ5IjoyMzl9LHsieCI6MTc1MS43MTA5Mzc1LCJ5IjoyNzZ9LHsieCI6MTc1MS43MTA5Mzc1LCJ5IjozMTN9LHsieCI6MTA5OS41NDY4NzUsInkiOjM4OS44ODY4ODM2NDg2OTc1Nn1d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1099.547,391.782L1226.633,378.652C1353.719,365.521,1607.891,339.261,1734.977,319.964C1862.063,300.667,1862.063,288.333,1862.063,276.667C1862.063,265,1862.063,254,1862.063,248.5L1862.063,243&quot; id=&quot;mermaid-0-L_INF_APP_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_INF_APP_0&quot; data-points=&quot;W3sieCI6MTA5OS41NDY4NzUsInkiOjM5MS43ODE4NDk1ODA0NDA0NX0seyJ4IjoxODYyLjA2MjUsInkiOjMxM30seyJ4IjoxODYyLjA2MjUsInkiOjI3Nn0seyJ4IjoxODYyLjA2MjUsInkiOjIzOX1d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1947.563,233.071L1976.595,240.226C2005.628,247.381,2063.693,261.69,2092.725,275.012C2121.758,288.333,2121.758,300.667,2121.758,322.202C2121.758,343.738,2121.758,374.475,2121.758,405.213C2121.758,435.951,2121.758,466.689,2121.758,488.224C2121.758,509.76,2121.758,522.093,2151.276,538.415C2180.795,554.737,2239.833,575.048,2269.351,585.203L2298.87,595.359&quot; id=&quot;mermaid-0-L_APP_LOG_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_APP_LOG_0&quot; data-points=&quot;W3sieCI6MTk0Ny41NjI1LCJ5IjoyMzMuMDcwODQ2MjQ0MDk2MTV9LHsieCI6MjEyMS43NTc4MTI1LCJ5IjoyNzZ9LHsieCI6MjEyMS43NTc4MTI1LCJ5IjozMTN9LHsieCI6MjEyMS43NTc4MTI1LCJ5Ijo0MDUuMjEzMjMzOTQ3NzUzOX0seyJ4IjoyMTIxLjc1NzgxMjUsInkiOjQ5Ny40MjY0Njc4OTU1MDc4fSx7IngiOjIxMjEuNzU3ODEyNSwieSI6NTM0LjQyNjQ2Nzg5NTUwNzh9LHsieCI6MjMwMi42NTIzNDM3NSwieSI6NTk2LjY1OTk5Mzk3MTg0NDF9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1947.563,219.818L2049.966,229.182C2152.37,238.545,2357.177,257.273,2459.581,272.803C2561.984,288.333,2561.984,300.667,2561.984,315.036C2561.984,329.404,2561.984,345.809,2561.984,354.011L2561.984,362.213&quot; id=&quot;mermaid-0-L_APP_REV_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_APP_REV_0&quot; data-points=&quot;W3sieCI6MTk0Ny41NjI1LCJ5IjoyMTkuODE4MDE1NDAzNTA0ODZ9LHsieCI6MjU2MS45ODQzNzUsInkiOjI3Nn0seyJ4IjoyNTYxLjk4NDM3NSwieSI6MzEzfSx7IngiOjI1NjEuOTg0Mzc1LCJ5IjozNjYuMjEzMjMzOTQ3NzUzOX1d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M2561.984,444.213L2561.984,453.082C2561.984,461.951,2561.984,479.689,2561.984,494.724C2561.984,509.76,2561.984,522.093,2545.687,538.596C2529.39,555.1,2496.796,575.773,2480.499,586.109L2464.202,596.446&quot; id=&quot;mermaid-0-L_REV_LOG_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_REV_LOG_0&quot; data-points=&quot;W3sieCI6MjU2MS45ODQzNzUsInkiOjQ0NC4yMTMyMzM5NDc3NTM5fSx7IngiOjI1NjEuOTg0Mzc1LCJ5Ijo0OTcuNDI2NDY3ODk1NTA3OH0seyJ4IjoyNTYxLjk4NDM3NSwieSI6NTM0LjQyNjQ2Nzg5NTUwNzh9LHsieCI6MjQ2MC44MjQyMTg3NSwieSI6NTk4LjU4ODQxMDExMTQ1NDR9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1776.563,220.428L1682.596,229.69C1588.63,238.952,1400.698,257.476,1306.732,272.905C1212.766,288.333,1212.766,300.667,1049.06,320.837C885.355,341.007,557.943,369.015,394.238,383.018L230.532,397.022&quot; id=&quot;mermaid-0-L_APP_OBS_0&quot; class=&quot;edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_APP_OBS_0&quot; data-points=&quot;W3sieCI6MTc3Ni41NjI1LCJ5IjoyMjAuNDI3NTc3OTA4Nzk1NTd9LHsieCI6MTIxMi43NjU2MjUsInkiOjI3Nn0seyJ4IjoxMjEyLjc2NTYyNSwieSI6MzEzfSx7IngiOjIyNi41NDY4NzUsInkiOjM5Ny4zNjI3ODIzNzYyOTc1fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1776.563,222.925L1707.336,231.771C1638.109,240.617,1499.656,258.308,1430.43,273.321C1361.203,288.333,1361.203,300.667,1224.424,320.045C1087.645,339.424,814.087,365.848,677.307,379.06L540.528,392.272&quot; id=&quot;mermaid-0-L_APP_EVAL_0&quot; class=&quot;edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_APP_EVAL_0&quot; data-points=&quot;W3sieCI6MTc3Ni41NjI1LCJ5IjoyMjIuOTI1MjIyMjc0MjE2Mn0seyJ4IjoxMzYxLjIwMzEyNSwieSI6Mjc2fSx7IngiOjEzNjEuMjAzMTI1LCJ5IjozMTN9LHsieCI6NTM2LjU0Njg3NSwieSI6MzkyLjY1NjEyNzIyNjY2MTM0fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M1776.563,229.902L1739.867,237.585C1703.172,245.268,1629.781,260.634,1593.086,274.484C1556.391,288.333,1556.391,300.667,1422.58,320.723C1288.769,340.78,1021.147,368.56,887.336,382.45L753.525,396.34&quot; id=&quot;mermaid-0-L_APP_ERR_0&quot; class=&quot;edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_APP_ERR_0&quot; data-points=&quot;W3sieCI6MTc3Ni41NjI1LCJ5IjoyMjkuOTAxNTQ4ODQyMjAyMTJ9LHsieCI6MTU1Ni4zOTA2MjUsInkiOjI3Nn0seyJ4IjoxNTU2LjM5MDYyNSwieSI6MzEzfSx7IngiOjc0OS41NDY4NzUsInkiOjM5Ni43NTMyNDQ3MDczOTI5fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabels&quot;&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_U_APP_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_APP_VDB_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_APP_CRM_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(1751.7109375, 276)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_APP_INF_0&quot; transform=&quot;translate(-90.3515625, -12)&quot;&gt;&lt;foreignObject width=&quot;180.703125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Prompt + Systemkontext&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_INF_APP_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(2121.7578125, 405.2132339477539)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_APP_LOG_0&quot; transform=&quot;translate(-97.1953125, -12)&quot;&gt;&lt;foreignObject width=&quot;194.390625&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Vorschlag, vor der Prüfung&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_APP_REV_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(2561.984375, 534.4264678955078)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_REV_LOG_0&quot; transform=&quot;translate(-36.125, -12)&quot;&gt;&lt;foreignObject width=&quot;72.25&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Entscheid&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(1212.765625, 276)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_APP_OBS_0&quot; transform=&quot;translate(-38.21875, -12)&quot;&gt;&lt;foreignObject width=&quot;76.4375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Telemetrie&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(1361.203125, 276)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_APP_EVAL_0&quot; transform=&quot;translate(-90.21875, -12)&quot;&gt;&lt;foreignObject width=&quot;180.4375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Traces mit Prompt-Inhalt&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(1556.390625, 276)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_APP_ERR_0&quot; transform=&quot;translate(-84.96875, -12)&quot;&gt;&lt;foreignObject width=&quot;169.9375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Stacktrace mit Payload&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;nodes&quot;&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-U-0&quot; data-look=&quot;classic&quot; transform=&quot;translate(1862.0625, 84)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-51&quot; width=&quot;260&quot; height=&quot;102&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -36)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;72&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Mitarbeiterin&lt;br/&gt;Eingabe mit Personendaten&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-APP-1&quot; data-look=&quot;classic&quot; transform=&quot;translate(1862.0625, 212)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-85.5&quot; y=&quot;-27&quot; width=&quot;171&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-55.5, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;111&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Agent-Runtime&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-VDB-2&quot; data-look=&quot;classic&quot; transform=&quot;translate(1882.0625, 405.2132339477539)&quot;&gt;&lt;path d=&quot;M0,15.808823529411764 a107.5,15.808823529411764 0,0,0 215,0 a107.5,15.808823529411764 0,0,0 -215,0 l0,102.80882352941177 a107.5,15.808823529411764 0,0,0 215,0 l0,-102.80882352941177&quot; class=&quot;basic label-container outer-path&quot; style=&quot;&quot; transform=&quot;translate(-107.5, -67.21323529411765)&quot;&gt;&lt;/path&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -26)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;72&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Vektordatenbank&lt;br/&gt;Embeddings = Personendaten&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-REV-3&quot; data-look=&quot;classic&quot; transform=&quot;translate(2561.984375, 405.2132339477539)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-102.953125&quot; y=&quot;-39&quot; width=&quot;205.90625&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-72.953125, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;145.90625&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Human-in-the-Loop&lt;br/&gt;Art. 21 Abs. 2 DSG&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-LOG-4&quot; data-look=&quot;classic&quot; transform=&quot;translate(2381.73828125, 623.8680953979492)&quot;&gt;&lt;path d=&quot;M0,13.964299508911326 a79.0859375,13.964299508911326 0,0,0 158.171875,0 a79.0859375,13.964299508911326 0,0,0 -158.171875,0 l0,76.96429950891132 a79.0859375,13.964299508911326 0,0,0 158.171875,0 l0,-76.96429950891132&quot; class=&quot;basic label-container outer-path&quot; style=&quot;&quot; transform=&quot;translate(-79.0859375, -52.446449263366986)&quot;&gt;&lt;/path&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-71.5859375, -14)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;143.171875&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Audit-Log&lt;br/&gt;Art. 4 DSV, getrennt&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-CRM-5&quot; data-look=&quot;classic&quot; transform=&quot;translate(2331.4921875, 405.2132339477539)&quot;&gt;&lt;path d=&quot;M0,13.842398884239888 a77.5390625,13.842398884239888 0,0,0 155.078125,0 a77.5390625,13.842398884239888 0,0,0 -155.078125,0 l0,52.842398884239884 a77.5390625,13.842398884239888 0,0,0 155.078125,0 l0,-52.842398884239884&quot; class=&quot;basic label-container outer-path&quot; style=&quot;&quot; transform=&quot;translate(-77.5390625, -40.263598326359826)&quot;&gt;&lt;/path&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-70.0390625, -2)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;140.078125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Fachsystem / CRM&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-INF-6&quot; data-look=&quot;classic&quot; transform=&quot;translate(969.546875, 405.2132339477539)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-51&quot; width=&quot;260&quot; height=&quot;102&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -36)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;72&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Inferenz-Endpunkt&lt;br/&gt;Anhang 1 DSV: angemessen&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default leak&quot; id=&quot;mermaid-0-flowchart-OBS-7&quot; data-look=&quot;classic&quot; transform=&quot;translate(134.7734375, 405.2132339477539)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;stroke-dasharray:6 4 !important&quot; x=&quot;-91.7734375&quot; y=&quot;-27&quot; width=&quot;183.546875&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-61.7734375, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;123.546875&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Monitoring-SaaS&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default leak&quot; id=&quot;mermaid-0-flowchart-EVAL-8&quot; data-look=&quot;classic&quot; transform=&quot;translate(406.546875, 405.2132339477539)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;stroke-dasharray:6 4 !important&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Eval- und Tracing-Plattform&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default leak&quot; id=&quot;mermaid-0-flowchart-ERR-9&quot; data-look=&quot;classic&quot; transform=&quot;translate(668.046875, 405.2132339477539)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;stroke-dasharray:6 4 !important&quot; x=&quot;-81.5&quot; y=&quot;-27&quot; width=&quot;163&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-51.5, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;103&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Error-Tracking&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;defs&gt;&lt;filter id=&quot;mermaid-0-drop-shadow&quot; height=&quot;130%&quot; width=&quot;130%&quot;&gt;&lt;feDropShadow dx=&quot;4&quot; dy=&quot;4&quot; stdDeviation=&quot;0&quot; flood-opacity=&quot;0.06&quot; flood-color=&quot;#000000&quot;&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;defs&gt;&lt;filter id=&quot;mermaid-0-drop-shadow-small&quot; height=&quot;150%&quot; width=&quot;150%&quot;&gt;&lt;feDropShadow dx=&quot;2&quot; dy=&quot;2&quot; stdDeviation=&quot;0&quot; flood-opacity=&quot;0.06&quot; flood-color=&quot;#000000&quot;&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;linearGradient id=&quot;mermaid-0-gradient&quot; gradientUnits=&quot;objectBoundingBox&quot; x1=&quot;0%&quot; y1=&quot;0%&quot; x2=&quot;100%&quot; y2=&quot;0%&quot;&gt;&lt;stop offset=&quot;0%&quot; stop-color=&quot;#363739&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;&lt;stop offset=&quot;100%&quot; stop-color=&quot;hsl(220, 0%, 17.6470588235%)&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;&lt;/linearGradient&gt;&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;Die gepunkteten Kanten sind Bekanntgaben ins Ausland, die in keinem Konzept stehen. Wer seinen Datenfluss so aufzeichnet, findet meist zwei oder drei.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zeichnen Sie Ihren eigenen Fluss einmal so auf.&lt;/strong&gt; Das dauert eine Stunde und ist die billigste Datenschutz-Massnahme, die wir kennen. Wenn Sie dabei jemanden am Whiteboard wollen, der die Peripherie schon kennt: &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;eine halbe Stunde, ohne Vorbereitung&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Wie sich derselbe Datenfluss auf der Infrastrukturebene aufbauen lässt, mit Anbietervergleich und GPU-Kosten in CHF, steht in &lt;a href=&quot;https://devs-group.ch/blog/souveraene-ki-inferenz-schweiz/&quot;&gt;souveräne KI-Inferenz in der Schweiz&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;was-heisst-hosting-in-der-schweiz-technisch-und-wo-hört-es-auf&quot;&gt;Was heisst „Hosting in der Schweiz” technisch, und wo hört es auf?&lt;/h2&gt;
&lt;p&gt;„Hosting in der Schweiz” beschreibt den Speicherort, nicht die Zugriffsmöglichkeit. Beides fällt auseinander, sobald der Anbieter eine Muttergesellschaft in einem Drittstaat hat, sein Support aus einer anderen Zeitzone eskaliert oder sein Control Plane anderswo läuft. Zugriff von aussen ist eine Bekanntgabe ins Ausland nach Art. 16 DSG.&lt;/p&gt;
&lt;p&gt;Die Prüfung ist zweistufig: Steht der Empfängerstaat in Anhang 1 DSV? Falls nein, braucht es eine Garantie nach Art. 16 Abs. 2, etwa vom EDÖB anerkannte Standarddatenschutzklauseln.&lt;/p&gt;
&lt;p&gt;Für die USA gilt eine Zwischenlage, die häufig falsch wiedergegeben wird. Seit dem 15.09.2024 gelten sie als Staat mit angemessenem Datenschutz, &lt;strong&gt;aber nur für Unternehmen mit Zertifizierung nach dem Swiss-U.S. Data Privacy Framework&lt;/strong&gt; (&lt;a href=&quot;https://www.edoeb.admin.ch/de/nsb?id=102054&quot;&gt;EDÖB&lt;/a&gt;). Zertifiziert wird pro Unternehmen, nicht pro Land.&lt;/p&gt;
&lt;p&gt;Daraus folgen drei technische Konsequenzen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Egress wird erzwungen, nicht vereinbart. Eine Allowlist auf Netzwerkebene ist der einzige Nachweis, der eine Prüfung übersteht.&lt;/li&gt;
&lt;li&gt;Der Inferenz-Endpunkt gehört hinter eine eigene Abstraktion. Wer gegen ein Anbieter-SDK programmiert, kann nicht wechseln, wenn die Zertifizierung fällt.&lt;/li&gt;
&lt;li&gt;Jede ausgehende Verbindung braucht eine hinterlegte Jurisdiktion. Bei &lt;a href=&quot;https://ai-gent.ch&quot;&gt;AIgent&lt;/a&gt; ist das Startbedingung: Ein Endpunkt ohne Jurisdiktionsangabe läuft nicht an.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wie-sitzt-das-human-in-the-loop-gate-im-agent-graph&quot;&gt;Wie sitzt das Human-in-the-Loop-Gate im Agent-Graph?&lt;/h2&gt;
&lt;p&gt;Das Gate sitzt zwischen Entscheidung und Wirkung, nicht zwischen Modellantwort und Entscheidung. Art. 21 Abs. 2 DSG verlangt die Überprüfung durch eine natürliche Person, und überprüfbar ist ein Entscheid nur, solange er nicht vollzogen ist. Eine Freigabe nach dem Versand der Absage erfüllt die Norm nicht.&lt;/p&gt;
&lt;p&gt;Entscheidend ist das Verhalten bei Zeitablauf: Ein Gate, das nach einem Timeout durchlässt, ist kein Gate.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; hitl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;errors&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Decision ist der Vorschlag des Agenten, bevor er wirksam wird.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Decision&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	RunID       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	SubjectRef  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   // Pseudonym der betroffenen Person, nie der Klarname&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Action      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   // z. B. &amp;quot;antrag.ablehnen&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Rationale   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   // Begründung für die prüfende Person&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	DataClasses []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // z. B. []string{&amp;quot;bonitaet&amp;quot;, &amp;quot;beschaeftigung&amp;quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Review ist das Ergebnis der Prüfung durch eine natürliche Person.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Review&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	ReviewerID &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Approved   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;bool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Comment    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	At         &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Auditor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;	Append&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;runID&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;event&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;payload&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ReviewQueue&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;	Await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Decision&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Review&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	ErrExpired  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; errors.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;New&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;hitl: keine Freigabe innerhalb der Frist, Entscheid verworfen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	ErrRejected &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; errors.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;New&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;hitl: durch prüfende Person abgelehnt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Gate hält eine automatisierte Einzelentscheidung nach Art. 21 DSG an, bis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// eine natürliche Person sie bestätigt hat. Läuft die Frist ab, gilt die&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Entscheidung als nicht getroffen. Es gibt keinen Pfad, auf dem ein Timeout&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// zu einer stillen Freigabe führt.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Gate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Auditor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;q&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ReviewQueue&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Decision&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;wait&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Append&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, d.RunID, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;decision.proposed&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, d); err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;audit: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	waitCtx, cancel &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; context.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;WithTimeout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, wait)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	defer&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cancel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	r, err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; q.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(waitCtx, d)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;		// Der Abbruchgrund gehört ins Log, auch wenn der Kontext bereits tot ist.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		_ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Append&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(context.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;WithoutCancel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx), d.RunID, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;decision.expired&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, err.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ErrExpired&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	event &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;decision.rejected&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; r.Approved {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		event &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;decision.approved&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Append&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, d.RunID, event, r); err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;audit: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;r.Approved {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ErrRejected, r.ReviewerID)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zwei Dinge sind bewusst gesetzt. Der Vorschlag wird protokolliert, bevor jemand ihn sieht; sonst lässt sich nicht belegen, dass eine Prüfung stattfand. Und &lt;code&gt;Decision&lt;/code&gt; trägt ein Pseudonym statt eines Namens: Die prüfende Person löst die Identität über ihre eigene Berechtigung auf. Dieselbe Trennung, die wir in &lt;a href=&quot;https://devs-group.ch/blog/architektur-entscheidungen-dokumentieren/&quot;&gt;Architektur-Entscheidungen dokumentieren&lt;/a&gt; als Schnittstellenfrage behandeln, ist hier eine Datenschutzfrage.&lt;/p&gt;
&lt;h2 id=&quot;wie-sieht-ein-audit-log-aus-das-eine-auskunftsanfrage-übersteht&quot;&gt;Wie sieht ein Audit-Log aus, das eine Auskunftsanfrage übersteht?&lt;/h2&gt;
&lt;p&gt;Ein revDSG-taugliches Audit-Log beantwortet pro betroffener Person, welche Personendaten wann, von wem und wozu bearbeitet wurden. Art. 4 Abs. 4 DSV nennt die Pflichtfelder: Identität der bearbeitenden Person, Art, Datum und Uhrzeit, gegebenenfalls den Empfänger. Abs. 5 verlangt mindestens ein Jahr Aufbewahrung, &lt;strong&gt;getrennt vom System, in dem die Personendaten bearbeitet werden&lt;/strong&gt;. Wer Software in die EU liefert, braucht daneben ab September 2026 ein zweites, ähnlich gebautes Log: das &lt;a href=&quot;https://devs-group.ch/blog/cra-meldepflicht-24-stunden-technisch-umsetzen/&quot;&gt;Incident-Log für die CRA-Meldepflicht&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Eigene Datenbank, eigene Credentials, eigener Backup-Zyklus.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Art. 4 Abs. 5 DSV verlangt die Trennung vom bearbeitenden System.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; agent_audit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    id           &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;bigserial&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    occurred_at  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;timestamptz&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; DEFAULT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; now&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(),  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Art. 4 Abs. 4 DSV&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    run_id       uuid        &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    actor        &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- &amp;#39;user:4711&amp;#39;, &amp;#39;agent:triage@2.3.1&amp;#39;, &amp;#39;reviewer:rp&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    operation    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   -- die sechs Vorgänge aus Art. 4 Abs. 1 DSV&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        CHECK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (operation &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;IN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#39;speichern&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#39;veraendern&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#39;lesen&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                             &amp;#39;bekanntgeben&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#39;loeschen&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#39;vernichten&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subject_ref  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Pseudonym, auflösbar nur im Identitätsdienst&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    data_classes &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[]      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- welche Kategorien, nicht welche Inhalte&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    recipient    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,                  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- &amp;#39;llm:apertus@ch-inference&amp;#39;, &amp;#39;crm:abacus&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    jurisdiction &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)     &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- &amp;#39;CH&amp;#39;, &amp;#39;EU&amp;#39;, &amp;#39;US&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    purpose      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Art. 6 Abs. 3 DSG nachweisbar halten&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    payload_sha  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;bytea&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;       NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;   -- Hash statt Inhalt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;-- Auskunftsbegehren nach Art. 25 DSG in einer Abfrage beantwortbar machen.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; agent_audit (subject_ref, occurred_at &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; INDEX&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ON&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; agent_audit (run_id);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die Zeile, die am häufigsten fehlt, ist &lt;code&gt;payload_sha&lt;/code&gt;. Ein Audit-Log mit dem Prompt im Klartext ist eine zweite Kopie der Personendaten, die ein Jahr liegen bleiben muss. Der Trade-off: Der Hash belegt die Bearbeitung, aber niemand kann nachlesen, was drinstand.&lt;/p&gt;
&lt;p&gt;Hier stossen zwei Normen aufeinander. Art. 6 Abs. 4 DSG verlangt Vernichtung, sobald die Daten nicht mehr erforderlich sind; Art. 4 Abs. 5 DSV verlangt ein Jahr Aufbewahrung des Protokolls. Das löst sich nur mit getrennten Lebenszyklen, wie im &lt;a href=&quot;https://devs-group.ch/projekte/formularservice-bit/&quot;&gt;Formularservice für das BIT&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;wovon-wir-abraten&quot;&gt;Wovon wir abraten&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Vom Enterprise-Abo als Konformitätsnachweis.&lt;/strong&gt; Ein Enterprise-Tarif regelt, ob der Anbieter Ihre Daten zum Training verwendet. Das ist die einzige der vier Anforderungen, die er für Sie erfüllen kann. Zweckbindung, Informationspflicht, Nachvollziehbarkeit und Überprüfbarkeit nach Art. 21 entstehen in Ihrem System, nicht in seinem Vertrag.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Von Prompt-Inhalten in der allgemeinen Observability.&lt;/strong&gt; Wer &lt;code&gt;gen_ai.input.messages&lt;/code&gt; in dasselbe Trace-Backend schreibt wie seine HTTP-Spans, hat den Gesprächsinhalt in einem System, dessen Retention nach Kosten eingestellt ist. Prompts gehören ins Audit-Log, nicht in die Telemetrie.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Und der Trade-off, den wir offen benennen:&lt;/strong&gt; Selbsthostung des Modells kostet Geschwindigkeit. Sie betreiben GPU-Kapazität, hinken bei Modellfähigkeiten hinterher und verlagern Aufwand von einer Rechnung in ein Team.&lt;/p&gt;
&lt;p&gt;Ein Inferenzanbieter aus einem Staat in Anhang 1 DSV, kombiniert mit strenger Kontrolle der Peripherie, erfüllt dieselben vier Anforderungen mit weniger Betriebsaufwand. Selbsthostung ist die richtige Antwort bei besonders schützenswerten Personendaten, etwa Gesundheitsdaten, und wie das geht, steht in &lt;a href=&quot;https://devs-group.ch/blog/souveraene-ki-inferenz-schweiz/&quot;&gt;souveräne KI-Inferenz in der Schweiz&lt;/a&gt;. Für einen internen Wissensassistenten ist sie die falsche.&lt;/p&gt;
&lt;p&gt;Wie in der &lt;a href=&quot;https://devs-group.ch/blog/ki-code-ohne-technische-schulden/&quot;&gt;KI-gestützten Entwicklung&lt;/a&gt;: Die Leitplanken stehen im Repository, nicht im Kopf.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;brauche-ich-einen-auftragsbearbeitungsvertrag-für-einen-ki-anbieter&quot;&gt;Brauche ich einen Auftragsbearbeitungsvertrag für einen KI-Anbieter?&lt;/h3&gt;
&lt;p&gt;Ja, sobald er Personendaten in Ihrem Auftrag bearbeitet, und das tut jeder gehostete Inferenzdienst. Art. 9 Abs. 1 DSG erlaubt die Übertragung nur, wenn die Daten so bearbeitet werden, wie Sie sie selbst bearbeiten dürften. Regelmässig gerissen wird Abs. 3: Unteraufträge brauchen Ihre vorgängige Genehmigung. Prüfbar ist das über die versionierte Subprozessorenliste, nicht über den Vertragstext.&lt;/p&gt;
&lt;h3 id=&quot;darf-ich-personendaten-in-chatgpt-eingeben&quot;&gt;Darf ich Personendaten in ChatGPT eingeben?&lt;/h3&gt;
&lt;p&gt;Rechtlich möglich, technisch selten sauber. Nötig sind eine Bearbeitung nach den Grundsätzen von Art. 6 DSG, eine Auftragsbearbeitung nach Art. 9, die Information nach Art. 19 inklusive Empfängerstaat und, falls der Anbieter nicht Swiss-U.S.-DPF-zertifiziert ist, eine Garantie nach Art. 16.&lt;/p&gt;
&lt;p&gt;Welche Strafnorm greift, hängt davon ab, was fehlt: bei der Garantie Art. 61 lit. a, bei der Auftragsbearbeitung Art. 61 lit. b, bei der Information Art. 60 Abs. 1 lit. b.&lt;/p&gt;
&lt;h3 id=&quot;reicht-ein-enterprise-abo-für-revdsg-konformität&quot;&gt;Reicht ein Enterprise-Abo für revDSG-Konformität?&lt;/h3&gt;
&lt;p&gt;Nein. Ein Enterprise-Abo regelt die Trainingsnutzung und meist die Datenresidenz. Es erzeugt weder das Protokoll nach Art. 4 DSV noch die Überprüfbarkeit nach Art. 21 DSG, und es sagt nichts über Ihre Vektordatenbank, Ihre Logs und Ihr Monitoring.&lt;/p&gt;
&lt;h3 id=&quot;brauchen-wir-eine-datenschutz-folgenabschätzung-für-einen-ki-assistenten&quot;&gt;Brauchen wir eine Datenschutz-Folgenabschätzung für einen KI-Assistenten?&lt;/h3&gt;
&lt;p&gt;Wenn die Bearbeitung ein hohes Risiko für Persönlichkeit oder Grundrechte mit sich bringen kann, ja (Art. 22 Abs. 1 DSG). Abs. 2 nennt zwei Regelfälle: umfangreiche Bearbeitung besonders schützenswerter Personendaten und systematische Überwachung umfangreicher öffentlicher Bereiche. Bleibt trotz Massnahmen ein hohes Risiko, ist der EDÖB zu konsultieren (Art. 23).&lt;/p&gt;
&lt;h3 id=&quot;gilt-der-eu-ai-act-für-unser-schweizer-unternehmen&quot;&gt;Gilt der EU AI Act für unser Schweizer Unternehmen?&lt;/h3&gt;
&lt;p&gt;Er kann extraterritorial greifen. Art. 2 Abs. 1 lit. c der KI-Verordnung erfasst Anbieter und Betreiber aus Drittstaaten, wenn das Ergebnis des KI-Systems in der Union verwendet wird. Die Pflichten für Hochrisikosysteme nach Anhang III gelten seit der &lt;a href=&quot;https://eur-lex.europa.eu/legal-content/DE/TXT/PDF/?uri=OJ%3AL_202601744&quot;&gt;Verordnung (EU) 2026/1744&lt;/a&gt; erst ab 02.12.2027, für eingebettete Systeme nach Anhang I ab 02.08.2028.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Nehmen Sie Ihr Architekturdiagramm und zeichnen Sie die Jurisdiktionsgrenzen ein.&lt;/strong&gt; Tauchen Kanten auf, die Sie nicht erklären können, reden wir darüber.&lt;/p&gt;
&lt;p&gt;30 Minuten mit einem Engineer über Ihre Agenten-Architektur, ohne Verkaufsgespräch: &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin buchen&lt;/a&gt;. Lieber schriftlich? Über &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt&lt;/a&gt;. Was wir bauen, steht unter &lt;a href=&quot;https://devs-group.ch/leistungen/kuenstliche-intelligenz/&quot;&gt;Künstliche Intelligenz &amp;amp; Machine Learning&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Alle Gesetzesangaben geprüft am 18.08.2026 an Fedlex und beim EDÖB. Dieser Beitrag ist Architekturberatung, keine Rechtsberatung.&lt;/em&gt;&lt;/p&gt;</content:encoded><category>Künstliche Intelligenz</category><author>Robert Pupel</author></item><item><title>Kubernetes v1.37: Upgrade ohne Ausfall</title><link>https://devs-group.ch/blog/kubernetes-1-37-upgrade-ohne-ausfall/</link><guid isPermaLink="true">https://devs-group.ch/blog/kubernetes-1-37-upgrade-ohne-ausfall/</guid><description>Static Pods brechen, alte cAdvisor-Flags stoppen das kubelet, SELinuxMount ist neu aktiv. Was beim Upgrade auf Kubernetes v1.37 wirklich schiefgeht.</description><pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Kubernetes v1.37 ist am 26. August 2026 erschienen. Drei Änderungen brechen laufende Cluster beim Upgrade: Static Pods dürfen keine Secrets oder ConfigMaps mehr referenzieren, das kubelet startet nicht mehr, wenn veraltete cAdvisor-Flags gesetzt sind, und &lt;code&gt;SELinuxMount&lt;/code&gt; ist neu standardmässig aktiv. Die oft zitierte containerd-1.x-Frist dagegen wurde erneut verschoben.&lt;/p&gt;
&lt;p&gt;Die vollständigen Release Notes stehen in &lt;a href=&quot;https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.37.md&quot;&gt;&lt;code&gt;CHANGELOG-1.37.md&lt;/code&gt;&lt;/a&gt; im Repo kubernetes/kubernetes, die Feature-Übersicht im &lt;a href=&quot;https://kubernetes.io/blog/2026/07/31/kubernetes-v1-37-sneak-peek/&quot;&gt;Sneak Peek vom 31. Juli 2026&lt;/a&gt;. Wer zwei bis zwanzig produktive Cluster betreibt, braucht davon nur den Teil, der wehtut: eine Reihenfolge und ein paar Prüfbefehle. Genau das steht unten.&lt;/p&gt;
&lt;h2 id=&quot;static-pods-dürfen-keine-secrets-und-configmaps-mehr-referenzieren&quot;&gt;Static Pods dürfen keine Secrets und ConfigMaps mehr referenzieren&lt;/h2&gt;
&lt;p&gt;Kubernetes v1.37 entfernt das Feature Gate &lt;code&gt;PreventStaticPodAPIReferences&lt;/code&gt;. Static Pods, die &lt;code&gt;configMapRef&lt;/code&gt; oder &lt;code&gt;secretRef&lt;/code&gt; verwenden, starten nach dem Upgrade nicht mehr. Betroffen sind vor allem Bare-Metal-Installationen und selbstverwaltete Control Planes, nicht von kubeadm verwaltete Standardkomponenten.&lt;/p&gt;
&lt;p&gt;Das ist ein Bugfix, keine Schikane. Static Pods werden vom kubelet direkt aus &lt;code&gt;/etc/kubernetes/manifests/&lt;/code&gt; gelesen und laufen nicht über den API-Server. Dass sie trotzdem API-Objekte referenzieren konnten, war ein Fehler. Laut Release-Eintrag wurde das Gate entfernt und kann nicht mehr deaktiviert werden.&lt;/p&gt;
&lt;p&gt;Die Prüfung dauert eine Minute pro Node:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Auf jedem Control-Plane- und Worker-Node&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;grep&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -rlE&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;configMapRef|secretRef&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /etc/kubernetes/manifests/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jede Ausgabezeile ist ein Manifest, das Sie vor dem Upgrade umbauen müssen. Der Ersatz ist unspektakulär: Werte als Literal in die Pod-Spec schreiben, Dateien über &lt;code&gt;hostPath&lt;/code&gt; einhängen, oder die Komponente aus dem Static-Pod-Verzeichnis in ein echtes DaemonSet überführen.&lt;/p&gt;
&lt;h2 id=&quot;das-kubelet-startet-nicht-mehr-wenn-alte-cadvisor-flags-gesetzt-sind&quot;&gt;Das kubelet startet nicht mehr, wenn alte cAdvisor-Flags gesetzt sind&lt;/h2&gt;
&lt;p&gt;Das kubelet in v1.37 verweigert den Start, sobald eine veraltete cAdvisor-Option in seiner Konfiguration steht. Das eingebettete cAdvisor nutzt neu das schlankere Modul &lt;code&gt;github.com/google/cadvisor/lib&lt;/code&gt;, und von den alten Flags überlebt nur &lt;code&gt;--housekeeping-interval&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Diese Änderung ist in den Release Notes als Deprecation geführt, wirkt in der Praxis aber wie ein harter Breaking Change: Ein Node mit &lt;code&gt;--containerd&lt;/code&gt;, &lt;code&gt;--boot-id-file&lt;/code&gt;, &lt;code&gt;--machine-id-file&lt;/code&gt;, &lt;code&gt;--container-hints&lt;/code&gt;, &lt;code&gt;--global-housekeeping-interval&lt;/code&gt;, &lt;code&gt;--event-storage-age-limit&lt;/code&gt; oder einem der &lt;code&gt;--storage-driver-*&lt;/code&gt;-Flags kommt nach dem Neustart schlicht nicht zurück.&lt;/p&gt;
&lt;p&gt;Wichtig ist, an welchen Stellen Sie suchen. Die systemd-Unit ist nur eine davon: kubeadm legt seine Flags in &lt;code&gt;/var/lib/kubelet/kubeadm-flags.env&lt;/code&gt; ab, viele Distributionen zusätzlich in &lt;code&gt;/etc/default/kubelet&lt;/code&gt;. Wer nur &lt;code&gt;systemctl cat&lt;/code&gt; prüft, bekommt auf einem betroffenen Node ein sauberes Ergebnis.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Auf jedem Node: verbotene cAdvisor-Flags in allen drei Quellen finden&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;FLAGS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;#39;--(application-metrics-count-limit|boot-id-file|container-hints|containerd|enable-load-reader|event-storage-|global-housekeeping-interval|log-cadvisor-usage|machine-id-file|storage-driver-)&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;systemctl&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; cat&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; kubelet&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; 2&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/dev/null&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -E&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$FLAGS&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;grep&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -hE&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$FLAGS&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /var/lib/kubelet/kubeadm-flags.env&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; /etc/default/kubelet&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; 2&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/dev/null&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keine Ausgabe heisst: sauber. Zusätzlich verschwinden die Metriken &lt;code&gt;container_cpu_load_average_10s&lt;/code&gt;, &lt;code&gt;container_cpu_load_d_average_10s&lt;/code&gt; und &lt;code&gt;container_tasks_state&lt;/code&gt; aus &lt;code&gt;/metrics/cadvisor&lt;/code&gt;. Wer davon ein Grafana-Panel oder eine Alerting-Regel abhängig gemacht hat, sieht nach dem Upgrade eine stumme Lücke statt eines Fehlers. Das ist die unangenehmere Variante. Mehr dazu in unserem Beitrag über &lt;a href=&quot;https://devs-group.ch/blog/observability-die-man-liest/&quot;&gt;Observability, die man liest&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;containerd-20-unter-kubernetes-ist-der-wechsel-für-v137-pflicht&quot;&gt;containerd 2.0 unter Kubernetes: ist der Wechsel für v1.37 Pflicht?&lt;/h2&gt;
&lt;p&gt;Nein, containerd 2.0 ist auch mit Kubernetes v1.37 nicht Pflicht. Die Behauptung kursiert seit dem v1.36-Zyklus in Upgrade-Guides und stimmt nicht. Die Entfernung der veralteten kubelet-Konfigurationsflags samt CRI-Fallback wurde zweimal verschoben: in &lt;code&gt;CHANGELOG-1.36.md&lt;/code&gt; von v1.36 auf v1.37, und in &lt;code&gt;CHANGELOG-1.37.md&lt;/code&gt; erneut von v1.37 auf &lt;strong&gt;v1.38&lt;/strong&gt; (PR #139121, gemergt am 22. Mai 2026), ausdrücklich „to align with containerd v1.7 support”.&lt;/p&gt;
&lt;p&gt;Entspannen Sie sich trotzdem nicht. Laut &lt;a href=&quot;https://github.com/containerd/containerd/blob/main/RELEASES.md&quot;&gt;containerd RELEASES.md&lt;/a&gt; endet der verlängerte Support für containerd 1.7 im &lt;strong&gt;September 2026&lt;/strong&gt;, und er ist explizit auf Kubernetes 1.30 bis 1.32 auf GKE beschränkt. Für alles andere ist 1.7 bereits jetzt unbetreut.&lt;/p&gt;
&lt;p&gt;Das kubelet sagt Ihnen selbst, wann Schluss ist:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Node-Inventar: kubelet-Version, Runtime, OS-Image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kubectl&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; nodes&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; custom-columns=&amp;#39;NODE:.metadata.name,\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;KUBELET:.status.nodeInfo.kubeletVersion,\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;RUNTIME:.status.nodeInfo.containerRuntimeVersion,\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;OS:.status.nodeInfo.osImage&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# kubelet-Metriken: cgroup-Version und Support-Ende der Runtime&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kubectl&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --raw&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;/api/v1/nodes/&amp;lt;NODE&amp;gt;/proxy/metrics&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -E&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;^kubelet_(cgroup_version|cri_losing_support)&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;kubelet_cri_losing_support&lt;/code&gt; ist ein Gauge mit dem Label &lt;code&gt;version&lt;/code&gt; und meldet, in welcher Kubernetes-Version die aktuell laufende CRI-Implementierung ihren Support verliert. Alpha-Stabilität, aber genau die Zahl, die man beim Planen braucht.&lt;/p&gt;
&lt;p&gt;Was der Sprung von 1.7 auf 2.x konkret bedeutet:&lt;/p&gt;



































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Punkt&lt;/th&gt;&lt;th&gt;containerd 1.7&lt;/th&gt;&lt;th&gt;containerd 2.x&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Support&lt;/td&gt;&lt;td&gt;verlängert bis September 2026, nur für K8s 1.30 bis 1.32 auf GKE&lt;/td&gt;&lt;td&gt;2.3 als LTS bis 30.04.2028&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CRI-API&lt;/td&gt;&lt;td&gt;&lt;code&gt;v1&lt;/code&gt; und &lt;code&gt;v1alpha2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;nur &lt;code&gt;v1&lt;/code&gt;, &lt;code&gt;v1alpha2&lt;/code&gt; entfernt&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;config.toml&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Version 2&lt;/td&gt;&lt;td&gt;Version 3 empfohlen, Version 2 läuft weiter&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Docker-Schema-1-Images&lt;/td&gt;&lt;td&gt;Pull möglich, deprecated&lt;/td&gt;&lt;td&gt;in 2.0 deaktiviert, in 2.1 entfernt&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Runtime-Plugins als &lt;code&gt;*.so&lt;/code&gt;&lt;/td&gt;&lt;td&gt;unterstützt&lt;/td&gt;&lt;td&gt;in 2.1 entfernt, externe Plugins nutzen&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Wenn Sie migrieren, gehen Sie auf &lt;strong&gt;containerd 2.3&lt;/strong&gt;: LTS bis 30. April 2028. containerd 2.2 läuft schon am 6. November 2026 aus, 2.1 ist seit dem 3. Juli 2026 EOL. Die Config muss dabei nicht sofort mitwandern, Version 2 wird von containerd 2.x weiterhin gelesen.&lt;/p&gt;
&lt;p&gt;Wer nicht sicher ist, ob seine Nodes nach dem kubelet-Neustart zurückkommen, findet das in etwa einer Stunde heraus: Node-Inventar, kubelet-Unit-Diff, Static-Pod-Scan. Wenn Sie das nicht selbst durchgehen wollen, &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;schauen wir es uns gemeinsam an&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;cgroup-v1-ist-seit-v135-erledigt-nicht-erst-jetzt&quot;&gt;cgroup v1 ist seit v1.35 erledigt, nicht erst jetzt&lt;/h2&gt;
&lt;p&gt;Das kubelet startet seit Kubernetes v1.35 auf cgroup-v1-Nodes nicht mehr, weil &lt;code&gt;failCgroupV1&lt;/code&gt; dort standardmässig auf &lt;code&gt;true&lt;/code&gt; steht. Der &lt;a href=&quot;https://kubernetes.io/blog/2026/07/31/kubernetes-v1-37-sneak-peek/&quot;&gt;Sneak Peek zu v1.37&lt;/a&gt; führt das als laufende Änderung, nicht als Neuerung.&lt;/p&gt;
&lt;p&gt;Praktisch heisst das: Wer heute noch auf v1.34 sitzt, trifft cgroup v1 nicht beim Sprung auf v1.37, sondern schon beim Zwischenschritt auf v1.35. Betroffen sind ältere Node-Images und On-Prem-Bestände, typischerweise CentOS 7, RHEL 7 und Ubuntu 18.04. Die Metrik &lt;code&gt;kubelet_cgroup_version&lt;/code&gt; aus dem Block oben beantwortet das pro Node, ohne dass jemand sich einloggen muss.&lt;/p&gt;
&lt;h2 id=&quot;kube-proxy-ipvs-die-uhr-läuft-aber-langsam&quot;&gt;kube-proxy IPVS: die Uhr läuft, aber langsam&lt;/h2&gt;
&lt;p&gt;Der IPVS-Modus von kube-proxy verschwindet über vier Releases, nicht in diesem. &lt;a href=&quot;https://kubernetes.dev/resources/keps/5495&quot;&gt;KEP-5495&lt;/a&gt; legt den Pfad fest: v1.35 Warnungen, v1.37 neues Feature Gate &lt;code&gt;KubeProxyIPVS&lt;/code&gt; (standardmässig aktiv), v1.40 Gate standardmässig aus, v1.43 Code entfernt, v1.46 Gate entfernt.&lt;/p&gt;
&lt;p&gt;Die Begründung ist ehrlich und im KEP nachlesbar: „sig-network currently lacks maintainers who are familiar with the &lt;code&gt;ipvs&lt;/code&gt; backend code.” Dazu kommt, dass IPVS unter der Haube weiterhin iptables benutzt. Migrationsziel ist &lt;code&gt;nftables&lt;/code&gt;, GA seit v1.33.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kubectl&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; kube-system&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; configmap&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; kube-proxy&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  -o&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; jsonpath=&amp;#39;{.data.config\.conf}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;mode:&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ein leeres &lt;code&gt;mode:&lt;/code&gt; ist ab v1.37 ebenfalls eine Warnung wert: kube-proxy meldet neu, wenn kein Modus explizit gesetzt ist, weil der Linux-Default künftig von &lt;code&gt;iptables&lt;/code&gt; auf &lt;code&gt;nftables&lt;/code&gt; wechselt. Setzen Sie den Wert explizit, auch wenn Sie beim aktuellen Verhalten bleiben wollen.&lt;/p&gt;
&lt;h2 id=&quot;welche-kubernetes-version-noch-support-hat&quot;&gt;Welche Kubernetes-Version noch Support hat&lt;/h2&gt;
&lt;p&gt;Kubernetes pflegt die drei jüngsten Minor-Releases. Die Dokumentation nennt das „rund ein Jahr”, die letzten drei Releases liefen tatsächlich 14,0, 14,4 und 14,2 Monate. Rechnen Sie mit zwölf Monaten und freuen Sie sich über den Rest. Stand &lt;a href=&quot;https://kubernetes.io/releases/&quot;&gt;kubernetes.io/releases&lt;/a&gt; vom 18. August 2026:&lt;/p&gt;



































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Version&lt;/th&gt;&lt;th&gt;Release&lt;/th&gt;&lt;th&gt;End of Life&lt;/th&gt;&lt;th&gt;Was zu tun ist&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;v1.34&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;27.08.2025&lt;/td&gt;&lt;td&gt;&lt;strong&gt;27.10.2026&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Akut. Zwei Monate Rest, drei Minor-Sprünge bis v1.37&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;v1.35&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;17.12.2025&lt;/td&gt;&lt;td&gt;28.02.2027&lt;/td&gt;&lt;td&gt;cgroup v1 bereits scharf, IPVS-Warnungen aktiv&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;v1.36&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;22.04.2026&lt;/td&gt;&lt;td&gt;28.06.2027&lt;/td&gt;&lt;td&gt;Komfortabelste Ausgangslage, ein Sprung auf v1.37&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;v1.37&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;26.08.2026&lt;/td&gt;&lt;td&gt;ca. Oktober 2027 *&lt;/td&gt;&lt;td&gt;Neu, anfangs .0-Patchstand&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;* EOL für v1.37 ist noch nicht publiziert. Der Wert ist aus dem 14-Monats-Muster der drei Vorgänger extrapoliert und als Planungsgrösse zu behandeln, nicht als Zusage.&lt;/p&gt;
&lt;p&gt;Für Schweizer Teams auf &lt;a href=&quot;https://community.exoscale.com/product/compute/containers/how-to/lifecycle-management/&quot;&gt;Exoscale SKS&lt;/a&gt; kommt ein zweiter Takt dazu: Minor-Versionen werden dort rund 14 Monate unterstützt, Upgrades müssen sequenziell durch jede Minor-Version laufen, und der Control Plane wird zuerst gehoben, danach werden die NodePools durchgetauscht. Von v1.34 auf v1.37 sind das drei Runden, nicht eine.&lt;/p&gt;
&lt;h2 id=&quot;die-upgrade-reihenfolge-die-wir-empfehlen&quot;&gt;Die Upgrade-Reihenfolge, die wir empfehlen&lt;/h2&gt;
&lt;p&gt;Ein Upgrade ohne Ausfall folgt der offiziellen &lt;a href=&quot;https://kubernetes.io/releases/version-skew-policy/&quot;&gt;Version Skew Policy&lt;/a&gt;: Control Plane vor Nodes, keine übersprungenen Minor-Versionen beim kube-apiserver.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prüfen, bevor irgendetwas angefasst wird.&lt;/strong&gt; Static-Pod-Scan, cAdvisor-Flag-Scan, &lt;code&gt;kubelet_cgroup_version&lt;/code&gt;, &lt;code&gt;kubelet_cri_losing_support&lt;/code&gt;, kube-proxy-Modus. Alle fünf Befehle stehen oben.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;scheduling.k8s.io/v1alpha2&lt;/code&gt; aus etcd räumen.&lt;/strong&gt; v1.37 entfernt die Version vollständig. Die Kerntypen &lt;code&gt;Workload&lt;/code&gt; und &lt;code&gt;PodGroup&lt;/code&gt; sind nach &lt;code&gt;scheduling.k8s.io/v1beta1&lt;/code&gt; promoted, der Rest nach &lt;code&gt;v1alpha3&lt;/code&gt;. Bestehende Objekte müssen vor dem Update weg.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kube-apiserver hochziehen&lt;/strong&gt;, danach kube-controller-manager, kube-scheduler und cloud-controller-manager. Diese drei dürfen höchstens eine Minor-Version älter sein als der API-Server.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Einen Worker-Node exemplarisch heben.&lt;/strong&gt; kubelet und kube-proxy dürfen bis zu drei Minor-Versionen älter sein als der kube-apiserver. Sie haben also Zeit, und Sie brauchen sie: Der erste Node ist der Test.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restliche NodePools rollen&lt;/strong&gt;, mit PodDisruptionBudgets, die den Namen verdienen. Ein PDB mit &lt;code&gt;minAvailable: 1&lt;/code&gt; bei zwei Replicas blockiert kein Drain, er verzögert es nur.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ein Punkt, der gern untergeht: &lt;code&gt;SELinuxMount&lt;/code&gt; ist in v1.37 GA und standardmässig aktiv. Auf Clustern mit aktiviertem SELinux, also praktisch jedem RHEL- und OpenShift-Bestand, kann das laufende Workloads brechen. Kubernetes hat dazu am 22. April 2026 einen &lt;a href=&quot;https://kubernetes.io/blog/2026/04/22/breaking-changes-in-selinux-volume-labeling/&quot;&gt;eigenen Blogbeitrag&lt;/a&gt; publiziert, der die betroffenen Muster im v1.36-Cluster identifizierbar macht. Ohne SELinux ändert sich nichts.&lt;/p&gt;
&lt;h2 id=&quot;wann-sie-nicht-upgraden-sollten&quot;&gt;Wann Sie nicht upgraden sollten&lt;/h2&gt;
&lt;p&gt;Upgraden Sie nicht auf v1.37.0. Warten Sie auf v1.37.1 oder v1.37.2, ausser Sie haben einen konkreten Grund. Ein .0-Release ist am Erscheinungstag der am wenigsten in Produktion gelaufene Stand einer Version, und die Historie der Urgent Upgrade Notes gibt einem wenig Anlass zu Optimismus.&lt;/p&gt;
&lt;p&gt;Der Trade-off ist real und geht in beide Richtungen: Wer wartet, sammelt Distanz zu v1.34, dessen Support am 27. Oktober 2026 endet. Weil kube-apiserver keine Minor-Versionen überspringen darf, sind das drei sequenzielle Upgrades. Wer erst im Oktober anfängt, macht drei Sprünge unter Zeitdruck statt einen entspannt. Jeder Sprung ist Betriebsaufwand, und der ist der grösste Posten, wenn man &lt;a href=&quot;https://devs-group.ch/blog/was-kostet-kubernetes-in-der-schweiz/&quot;&gt;durchrechnet, was Kubernetes in der Schweiz wirklich kostet&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unsere Linie: Wer auf v1.36 sitzt, hat bis Juni 2027 Ruhe und kann auf .2 warten. Wer auf v1.34 sitzt, fängt diese Woche an, und zwar mit v1.35, nicht mit v1.37. Und wer mitten im Quartalsabschluss steckt oder ein Release-Freeze fährt, verschiebt das Ganze bewusst und schriftlich, statt es zu vergessen.&lt;/p&gt;
&lt;p&gt;Packen Sie ausserdem nicht alles in dasselbe Wartungsfenster. &lt;a href=&quot;https://kubernetes.io/blog/2026/01/29/ingress-nginx-statement/&quot;&gt;Ingress NGINX wurde im März 2026 retired&lt;/a&gt;, ohne weitere Security-Patches, laut interner Datadog-Recherche mit rund der Hälfte aller Cloud-Native-Umgebungen im Rücken. Der Wechsel auf die Gateway API ist ein eigenes Projekt mit eigenem Risiko, kein Nebenschauplatz eines Minor-Upgrades.&lt;/p&gt;
&lt;p&gt;Ein Cluster ist ohnehin kein Selbstzweck. Bevor Sie drei Upgrade-Runden planen, lohnt die Frage, &lt;a href=&quot;https://devs-group.ch/blog/kubernetes-ist-kein-ziel/&quot;&gt;ob ein Cluster überhaupt die richtige Antwort ist&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;wie-funktioniert-ein-kubernetes-cluster-upgrade-ohne-ausfall&quot;&gt;Wie funktioniert ein Kubernetes-Cluster-Upgrade ohne Ausfall?&lt;/h3&gt;
&lt;p&gt;Ein ausfallfreies Upgrade hebt zuerst den Control Plane, dann die Nodes. Der kube-apiserver kommt zuerst, danach controller-manager und scheduler, zuletzt kubelet und kube-proxy. Workloads bleiben verfügbar, wenn jede Anwendung mindestens zwei Replicas, ein sinnvolles PodDisruptionBudget und funktionierende Readiness-Probes hat. Nodes werden einzeln gedraint, nicht parallel.&lt;/p&gt;
&lt;h3 id=&quot;welche-kubernetes-version-wird-noch-unterstützt&quot;&gt;Welche Kubernetes-Version wird noch unterstützt?&lt;/h3&gt;
&lt;p&gt;Unterstützt sind v1.35, v1.36 und v1.37, sobald v1.37 veröffentlicht ist. v1.34 erreicht am 27. Oktober 2026 sein End of Life. Kubernetes pflegt grundsätzlich die drei jüngsten Minor-Releases, was rund ein Jahr Patch-Support pro Version ergibt. Managed-Anbieter weichen ab: Exoscale SKS gibt rund 14 Monate.&lt;/p&gt;
&lt;h3 id=&quot;wie-prüfe-ich-welchen-kube-proxy-modus-mein-cluster-nutzt&quot;&gt;Wie prüfe ich, welchen kube-proxy-Modus mein Cluster nutzt?&lt;/h3&gt;
&lt;p&gt;Der Befehl &lt;code&gt;kubectl -n kube-system get configmap kube-proxy -o jsonpath=&amp;#39;{.data.config\.conf}&amp;#39; | grep &amp;#39;mode:&amp;#39;&lt;/code&gt; liest den Modus aus der ConfigMap. Ein leerer Wert bedeutet Default, aktuell &lt;code&gt;iptables&lt;/code&gt; auf Linux. Steht dort &lt;code&gt;ipvs&lt;/code&gt;, planen Sie die Migration auf &lt;code&gt;nftables&lt;/code&gt; ein: ab v1.40 ist IPVS standardmässig deaktiviert, ab v1.43 entfernt.&lt;/p&gt;
&lt;h3 id=&quot;muss-ich-für-kubernetes-v137-auf-containerd-2x-wechseln&quot;&gt;Muss ich für Kubernetes v1.37 auf containerd 2.x wechseln?&lt;/h3&gt;
&lt;p&gt;Nein, nicht zwingend. Die Entfernung des kubelet-CRI-Fallbacks wurde auf v1.38 verschoben. Der verlängerte Support für containerd 1.7 endet aber im September 2026 und deckt nur Kubernetes 1.30 bis 1.32 auf GKE ab. Praktisch heisst das: Planen Sie den Wechsel auf containerd 2.3 jetzt, aber nicht im selben Wartungsfenster wie das v1.37-Upgrade.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Gut zwei Monate bis zum End of Life von v1.34.&lt;/strong&gt; Bis v1.37 sind das drei sequenzielle Sprünge, und jeder braucht sein eigenes Wartungsfenster. Wir gehen den Pfad einmal mit Ihnen durch: welche Version zuerst, was pro Sprung bricht, wie lange das realistisch dauert. Am Ende haben Sie eine Reihenfolge, keine Präsentation.&lt;/p&gt;
&lt;p&gt;Schreiben Sie uns über &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt&lt;/a&gt;, welche Version bei Ihnen läuft und wie viele Cluster dranhängen, dann bereiten wir den Pfad vor. Oder setzen Sie gleich &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;einen Termin&lt;/a&gt;. Was wir sonst an Clustern bauen und betreiben, steht unter &lt;a href=&quot;https://devs-group.ch/leistungen/kubernetes-and-infrastruktur/&quot;&gt;Kubernetes und Infrastruktur&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Cloud &amp; Infrastruktur</category><author>Ralph Segi</author></item><item><title>Was kostet Kubernetes in der Schweiz wirklich?</title><link>https://devs-group.ch/blog/was-kostet-kubernetes-in-der-schweiz/</link><guid isPermaLink="true">https://devs-group.ch/blog/was-kostet-kubernetes-in-der-schweiz/</guid><description>Anbietervergleich in CHF, eine durchgerechnete Modellrechnung und der Posten, den alle unterschätzen: der Betrieb kostet mehr als die Infrastruktur.</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ein produktiver Kubernetes-Cluster mit drei Worker-Nodes zu je 4 vCPU und 16 GB RAM, 500 GB Storage und einer Control Plane mit SLA kostet bei Schweizer Anbietern zwischen CHF 158 und CHF 779 pro Monat. Das ist die kleinere Hälfte der Rechnung. Der Betrieb kostet ab CHF 1’730 monatlich, gerechnet mit vier Stunden pro Woche zum tiefsten Schweizer Stundensatz.&lt;/p&gt;
&lt;p&gt;Beide Zahlen sind eine Modellrechnung. Jeder Eingangswert stammt aus einer öffentlichen Preisliste, abgerufen am 19. August 2026. Zum Einordnen haben wir dasselbe Szenario bei Azure in Switzerland North und bei AWS in Europe (Zurich) durchgerechnet. Die Herleitung steht weiter unten, Posten für Posten.&lt;/p&gt;
&lt;h2 id=&quot;warum-die-suche-nach-kubernetes-preisen-in-der-schweiz-ins-leere-läuft&quot;&gt;Warum die Suche nach Kubernetes-Preisen in der Schweiz ins Leere läuft&lt;/h2&gt;
&lt;p&gt;Wer nach Kubernetes-Kosten sucht, findet Rechner von AWS, Azure und Google in USD und EUR. Für Schweizer Anbieter existiert keine einzige durchgerechnete Gegenüberstellung in CHF. Das ist der Grund für diesen Beitrag.&lt;/p&gt;
&lt;p&gt;Stattdessen kursieren zwei Zahlen, die beide aus Suchzusammenfassungen stammen und nicht aus geprüften Preislisten: „Managed Kubernetes ab CHF 100 pro Monat” und „CHF 150 bis 400 pro Monat”. Wir haben beide nachgeschlagen. Beide sind falsch, und zwar in unterschiedliche Richtungen.&lt;/p&gt;
&lt;p&gt;Der günstigste publizierte Einstieg liegt deutlich tiefer. Bei &lt;a href=&quot;https://www.infomaniak.com/de/hosting/public-cloud/kubernetes&quot;&gt;Infomaniak&lt;/a&gt; ist die Shared Control Plane kostenlos, drei Worker-Nodes mit 2 vCPU und 4 GB RAM kosten CHF 0.01043 pro Stunde und Node, also rund CHF 23 pro Monat zusammen. Mit einem Load Balancer landet ein minimaler Cluster bei etwa CHF 33.&lt;/p&gt;
&lt;p&gt;Und ein Cluster in produktiver Grösse liegt deutlich höher als CHF 400. Bei &lt;a href=&quot;https://doc.flow.swiss/platform/pricing/kubernetes&quot;&gt;Flow Swiss&lt;/a&gt; kostet allein ein einzelner Worker-Node mit 4 vCPU und 16 GB RAM CHF 197 pro Monat. Drei davon sind Pflicht.&lt;/p&gt;
&lt;h2 id=&quot;die-vier-kostenblöcke-aus-denen-sich-die-rechnung-zusammensetzt&quot;&gt;Die vier Kostenblöcke, aus denen sich die Rechnung zusammensetzt&lt;/h2&gt;
&lt;p&gt;Eine Kubernetes-Rechnung besteht aus Control Plane, Worker-Nodes, Storage samt Traffic und Betrieb. Die ersten drei stehen auf der Preisliste. Der vierte steht nirgends und ist der grösste.&lt;/p&gt;
&lt;p&gt;Vorweg, weil es die zweithäufigste Suchanfrage in diesem Umfeld ist: Kubernetes ist Open Source unter &lt;a href=&quot;https://github.com/kubernetes/kubernetes/blob/master/LICENSE&quot;&gt;Apache-2.0-Lizenz&lt;/a&gt; und damit lizenzkostenfrei. Der Betrieb ist es nicht. Sie zahlen keine Lizenz, Sie zahlen Maschinen und Personen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Control Plane.&lt;/strong&gt; Der Preis für die verwaltete Steuerebene. Exoscale und Infomaniak geben sie in der Basisvariante gratis ab, dann allerdings ohne SLA. Bei Flow Swiss kostet sie pro Cluster CHF 73 im Monat, unabhängig von der Clustergrösse.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Worker-Nodes.&lt;/strong&gt; Der grösste Posten auf der Rechnung. Hier liegen zwischen den Schweizer Anbietern Faktoren, keine Prozente.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Storage und Traffic.&lt;/strong&gt; Block Storage wird pro GiB und Stunde verrechnet. Beim Egress unterscheiden sich die Modelle stark: Infomaniak gibt Bandbreite grundsätzlich gratis ab, Flow Swiss inkludiert 20 TB pro Organisation und Monat, Exoscale gewährt pro Instanz 1.42 GiB pro Stunde und verrechnet danach CHF 0.02 pro GiB.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Betrieb.&lt;/strong&gt; Upgrades, Zertifikate, Netzwerk-Policies, Alarme um drei Uhr morgens. Dieser Block taucht auf keiner Preisliste auf, weil ihn kein Anbieter verkauft.&lt;/p&gt;
&lt;p&gt;Genau hier verrutschen Budgets. Ein Managed-Kubernetes-Angebot von Infomaniak oder Exoscale übernimmt die Control Plane, die etcd-Backups und die Node-Bereitstellung. Alles oberhalb der Kubernetes-API bleibt bei Ihnen: Ingress, Zertifikatsrotation, RBAC, Backups der Applikationsdaten, Alerting, und die Frage, wer den Upgrade-Pfad plant.&lt;/p&gt;
&lt;h2 id=&quot;was-managed-kubernetes-kostet-der-anbietervergleich-schweiz&quot;&gt;Was Managed Kubernetes kostet: der Anbietervergleich Schweiz&lt;/h2&gt;
&lt;p&gt;Von sieben Schweizer Anbietern führen vier eine öffentliche Preisliste und drei nicht. Alle Werte in der folgenden Tabelle stammen aus den verlinkten Preislisten, abgerufen am 19. August 2026, exklusive Mehrwertsteuer.&lt;/p&gt;































































































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Anbieter&lt;/th&gt;&lt;th&gt;Control Plane&lt;/th&gt;&lt;th&gt;Worker 4 vCPU / 16 GB&lt;/th&gt;&lt;th&gt;Block Storage&lt;/th&gt;&lt;th&gt;Egress&lt;/th&gt;&lt;th&gt;Datenstandort&lt;/th&gt;&lt;th&gt;SLA&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.exoscale.com/pricing/&quot;&gt;Exoscale SKS&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Starter gratis, Pro CHF 0.054995/h&lt;/td&gt;&lt;td&gt;CHF 0.18667/h&lt;/td&gt;&lt;td&gt;CHF 0.00014 pro GiB/h&lt;/td&gt;&lt;td&gt;1.42 GiB/h pro Instanz frei, dann CHF 0.02/GiB&lt;/td&gt;&lt;td&gt;Zonen ch-gva-2, ch-dk-2&lt;/td&gt;&lt;td&gt;99.95 % (Pro)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.infomaniak.com/de/hosting/public-cloud/kubernetes&quot;&gt;Infomaniak&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Shared gratis, Dediziert 4 ab CHF 0.04/h&lt;/td&gt;&lt;td&gt;CHF 0.03429/h&lt;/td&gt;&lt;td&gt;CHF 0.00012 pro GiB/h&lt;/td&gt;&lt;td&gt;inklusive&lt;/td&gt;&lt;td&gt;eigene RZ in der Schweiz&lt;/td&gt;&lt;td&gt;99.9 % (dediziert)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://doc.flow.swiss/platform/pricing/kubernetes&quot;&gt;Flow Swiss&lt;/a&gt;&lt;/td&gt;&lt;td&gt;CHF 73/Monat pro Cluster&lt;/td&gt;&lt;td&gt;CHF 197/Monat (k1.4x16)&lt;/td&gt;&lt;td&gt;CHF 0.22 pro GB/Monat&lt;/td&gt;&lt;td&gt;20 TB pro Organisation inklusive&lt;/td&gt;&lt;td&gt;ZRH1 Zürich, ALP1 Luzern&lt;/td&gt;&lt;td&gt;99.9 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.cloudscale.ch/de/preise&quot;&gt;cloudscale.ch&lt;/a&gt;&lt;/td&gt;&lt;td&gt;kein eigenes Managed Kubernetes&lt;/td&gt;&lt;td&gt;CHF 4.40 pro 24 h (Flex-16-4)&lt;/td&gt;&lt;td&gt;publiziert&lt;/td&gt;&lt;td&gt;100 GB pro 24 h inklusive&lt;/td&gt;&lt;td&gt;Schweiz&lt;/td&gt;&lt;td&gt;99.99 %&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://products.vshn.ch/openshift/pricing.html&quot;&gt;VSHN / APPUiO&lt;/a&gt;&lt;/td&gt;&lt;td&gt;im Servicepreis enthalten&lt;/td&gt;&lt;td&gt;ab CHF 4’900/Monat für den ganzen Cluster&lt;/td&gt;&lt;td&gt;Infrastruktur des Kunden&lt;/td&gt;&lt;td&gt;Infrastruktur des Kunden&lt;/td&gt;&lt;td&gt;frei wählbar&lt;/td&gt;&lt;td&gt;bis 99.99 % 24/7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.metanet.ch/de/solutions/managed-kubernetes&quot;&gt;Metanet&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;keine öffentliche Preisliste&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;keine öffentliche Preisliste&lt;/td&gt;&lt;td&gt;keine öffentliche Preisliste&lt;/td&gt;&lt;td&gt;keine öffentliche Preisliste&lt;/td&gt;&lt;td&gt;Schweiz, ISO 27001&lt;/td&gt;&lt;td&gt;Enterprise-SLA auf Anfrage&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.swisscom.ch/de/business/enterprise/angebot/cloud/cloudnative/container-services.html&quot;&gt;Swisscom&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;keine öffentliche Preisliste&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;keine öffentliche Preisliste&lt;/td&gt;&lt;td&gt;keine öffentliche Preisliste&lt;/td&gt;&lt;td&gt;keine öffentliche Preisliste&lt;/td&gt;&lt;td&gt;Schweiz&lt;/td&gt;&lt;td&gt;nicht publiziert&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://azure.microsoft.com/de-de/pricing/details/kubernetes-service/&quot;&gt;Azure AKS&lt;/a&gt;, Switzerland North&lt;/td&gt;&lt;td&gt;Free-Tier gratis, Standard CHF 0.082/h&lt;/td&gt;&lt;td&gt;CHF 0.2075/h (D4s v5)&lt;/td&gt;&lt;td&gt;CHF 72.68/Monat (P20, 512 GiB)&lt;/td&gt;&lt;td&gt;100 GB/Monat gratis, dann CHF 0.0656/GB&lt;/td&gt;&lt;td&gt;Switzerland North&lt;/td&gt;&lt;td&gt;Free ohne SLA, Standard mit hinterlegtem Uptime-SLA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://aws.amazon.com/eks/pricing/&quot;&gt;AWS EKS&lt;/a&gt;, Europe (Zurich)&lt;/td&gt;&lt;td&gt;USD 0.10/h pro Cluster&lt;/td&gt;&lt;td&gt;USD 0.253/h (m6i.xlarge)&lt;/td&gt;&lt;td&gt;USD 0.1142 pro GB/Monat (gp3)&lt;/td&gt;&lt;td&gt;USD 0.09/GB bis 10 TB&lt;/td&gt;&lt;td&gt;eu-central-2&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://aws.amazon.com/eks/sla/&quot;&gt;99.95 %&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Drei Anmerkungen dazu. Erstens rechnet Flow Swiss Monatspreise mit 730 Stunden, Exoscale mit 720; wir vereinheitlichen unten auf 730. Zweitens publiziert AWS für die Zürcher Region ausschliesslich USD, Azure liefert über die Retail-Prices-API echte CHF-Preise für Switzerland North. Wir rechnen nichts um, weil wir keinen belegbaren Stichtagskurs haben.&lt;/p&gt;
&lt;p&gt;Drittens gehört Exoscale seit 2017 zu &lt;a href=&quot;https://newsroom.a1.com/news-a1-digital-erwirbt-schweizer-cloud-anbieter-exoscale?id=65425&amp;amp;menueid=13799&amp;amp;l=deutsch&quot;&gt;A1 Digital&lt;/a&gt;, einer Tochter der Telekom Austria Group. Die Daten liegen in der Schweiz, die Eigentümerschaft nicht. Für revDSG-Fragen zählt beides.&lt;/p&gt;
&lt;h2 id=&quot;die-modellrechnung-derselbe-cluster-bei-fünf-anbietern&quot;&gt;Die Modellrechnung: derselbe Cluster bei fünf Anbietern&lt;/h2&gt;
&lt;p&gt;Dasselbe Referenzszenario kostet zwischen CHF 158.10 bei Infomaniak und CHF 779.00 bei Flow Swiss. Das Szenario: drei Worker-Nodes zu je 4 vCPU und 16 GB RAM, 500 GB persistenter Storage, eine Control Plane mit SLA, ein Load Balancer, Egress unter 1 TB, gerechnet mit 730 Stunden.&lt;/p&gt;





















































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Anbieter&lt;/th&gt;&lt;th&gt;3 Worker-Nodes&lt;/th&gt;&lt;th&gt;Control Plane&lt;/th&gt;&lt;th&gt;Storage&lt;/th&gt;&lt;th&gt;Load Balancer&lt;/th&gt;&lt;th&gt;Total pro Monat&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Infomaniak&lt;/td&gt;&lt;td&gt;CHF 75.10&lt;/td&gt;&lt;td&gt;CHF 29.20&lt;/td&gt;&lt;td&gt;CHF 43.80&lt;/td&gt;&lt;td&gt;CHF 10.00&lt;/td&gt;&lt;td&gt;&lt;strong&gt;CHF 158.10&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Exoscale&lt;/td&gt;&lt;td&gt;CHF 408.81&lt;/td&gt;&lt;td&gt;CHF 40.15&lt;/td&gt;&lt;td&gt;CHF 66.43&lt;/td&gt;&lt;td&gt;CHF 25.35&lt;/td&gt;&lt;td&gt;&lt;strong&gt;CHF 540.74&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Azure AKS, Switzerland North&lt;/td&gt;&lt;td&gt;CHF 454.42&lt;/td&gt;&lt;td&gt;CHF 59.86&lt;/td&gt;&lt;td&gt;CHF 72.68&lt;/td&gt;&lt;td&gt;CHF 14.78&lt;/td&gt;&lt;td&gt;&lt;strong&gt;CHF 601.74&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Flow Swiss&lt;/td&gt;&lt;td&gt;CHF 591.00&lt;/td&gt;&lt;td&gt;CHF 73.00&lt;/td&gt;&lt;td&gt;CHF 110.00&lt;/td&gt;&lt;td&gt;CHF 5.00&lt;/td&gt;&lt;td&gt;&lt;strong&gt;CHF 779.00&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AWS EKS, Europe (Zurich)&lt;/td&gt;&lt;td&gt;USD 554.07&lt;/td&gt;&lt;td&gt;USD 73.00&lt;/td&gt;&lt;td&gt;USD 57.10&lt;/td&gt;&lt;td&gt;USD 21.68&lt;/td&gt;&lt;td&gt;&lt;strong&gt;USD 705.85&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Modellrechnung, keine Offerte. Preise exklusive MwSt., abgerufen am 19. August 2026 aus den oben verlinkten Preislisten. Die Storage-Zeile enthält bei Exoscale zusätzlich die Node-Disks (3 × 50 GiB), die dort separat verrechnet werden; bei Infomaniak sind 50 GB pro Node im Flavor enthalten, bei Azure entspricht sie einer Premium-SSD P20 mit 512 GiB. Der Egress liegt bei allen fünf im Freikontingent oder ist gratis.&lt;/p&gt;
&lt;p&gt;Preis ist nicht Leistung. Infomaniak fährt Shared vCPUs im OpenStack-Verbund und positioniert sich &lt;a href=&quot;https://www.infomaniak.com/de/hosting/public-cloud/tarife&quot;&gt;ausdrücklich über den Preis&lt;/a&gt;. Flow Swiss liefert dedizierte Ressourcen, ein 99.9-Prozent-SLA und zwei Schweizer Regionen. Was die Tabelle nicht abbildet: Support-Qualität, Reaktionszeit bei Incidents, Reifegrad der API, wie schnell eine neue Kubernetes-Minor-Version verfügbar ist.&lt;/p&gt;
&lt;h2 id=&quot;was-kostet-kubernetes-bei-azure-und-aws-in-der-schweiz&quot;&gt;Was kostet Kubernetes bei Azure und AWS in der Schweiz?&lt;/h2&gt;
&lt;p&gt;Azure AKS in Switzerland North kostet im selben Szenario CHF 601.74 pro Monat, AWS EKS in Europe (Zurich) USD 705.85. Beide liegen damit im Feld der Schweizer Anbieter, nicht darüber. Das widerlegt die verbreitete Annahme, ein Hyperscaler sei automatisch die teure Variante.&lt;/p&gt;
&lt;p&gt;Azure ist günstiger als Flow Swiss und teurer als Exoscale. Infomaniak unterbietet Azure um fast den Faktor vier. Die Preisspanne innerhalb der Schweiz ist also grösser als der Abstand zwischen Schweiz und Hyperscaler.&lt;/p&gt;
&lt;p&gt;Zwei Unterschiede, die auf keiner Preisliste stehen. Erstens den Egress: Azure gibt 100 GB pro Monat gratis und verlangt danach CHF 0.0656 pro GB, AWS USD 0.09 pro GB bis 10 TB. Bei Infomaniak ist Bandbreite gratis, bei Flow Swiss sind 20 TB inklusive. Wer 2 TB (2’000 GB) pro Monat ausliefert, zahlt bei Azure CHF 124.64 zusätzlich und bei Infomaniak nichts.&lt;/p&gt;
&lt;p&gt;Zweitens die Rechtslage. Microsoft und AWS betreiben Schweizer Regionen, unterstehen als US-Konzerne aber dem &lt;a href=&quot;https://www.justice.gov/criminal/cloud-act-resources&quot;&gt;CLOUD Act&lt;/a&gt;. Für revDSG-Prüfungen mit erhöhtem Schutzbedarf ist das der Punkt, an dem die Preisfrage endet und die Architekturfrage beginnt.&lt;/p&gt;
&lt;h2 id=&quot;was-der-betrieb-kostet-schweizer-stundensätze-als-rechengrösse&quot;&gt;Was der Betrieb kostet: Schweizer Stundensätze als Rechengrösse&lt;/h2&gt;
&lt;p&gt;Der Betrieb kostet ein Vielfaches der Infrastruktur. &lt;a href=&quot;https://www.gryps.ch/produkte/softwareentwicklung-13/individualsoftware-kosten/&quot;&gt;gryps.ch&lt;/a&gt; nennt für Softwareentwicklung in der Deutschschweiz CHF 100 bis 150 pro Stunde für Junior-Profile und CHF 140 bis 180 für Senior-Profile, mit CHF 160 als Mittelwert im publizierten Beispiel (abgerufen 19.08.2026). Cluster-Betrieb ist Senior-Arbeit.&lt;/p&gt;





























&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Betriebsaufwand&lt;/th&gt;&lt;th&gt;CHF 100/h&lt;/th&gt;&lt;th&gt;CHF 140/h&lt;/th&gt;&lt;th&gt;CHF 180/h&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;4 h pro Woche (17.3 h/Monat)&lt;/td&gt;&lt;td&gt;CHF 1’730&lt;/td&gt;&lt;td&gt;CHF 2’430&lt;/td&gt;&lt;td&gt;CHF 3’120&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;10 h pro Woche (43.3 h/Monat)&lt;/td&gt;&lt;td&gt;CHF 4’330&lt;/td&gt;&lt;td&gt;CHF 6’070&lt;/td&gt;&lt;td&gt;CHF 7’800&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;20 h pro Woche (86.7 h/Monat)&lt;/td&gt;&lt;td&gt;CHF 8’670&lt;/td&gt;&lt;td&gt;CHF 12’130&lt;/td&gt;&lt;td&gt;CHF 15’600&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Die Zeile, auf die es ankommt: Selbst die vorsichtigste Annahme, vier Stunden pro Woche zum tiefsten publizierten Satz, ergibt CHF 1’730 pro Monat. Das ist mehr als die teuerste Infrastrukturrechnung im Vergleich oben.&lt;/p&gt;
&lt;p&gt;Vier Stunden pro Woche sind für einen produktiven Cluster knapp bemessen. Kubernetes gibt pro Jahr drei Minor-Versionen frei, jede mit Deprecations. Wie viel Vorbereitung ein einzelnes Upgrade kostet, haben wir am Beispiel &lt;a href=&quot;https://devs-group.ch/blog/kubernetes-1-37-upgrade-ohne-ausfall/&quot;&gt;1.37 durchgespielt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Rechnen Sie Ihren eigenen Fall einmal komplett durch, Infrastruktur plus Personentage. Wir machen das in einem Termin mit Ihnen, mit Ihren Node-Grössen und Ihrer Preisliste, und Sie behalten die Tabelle. &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;30 Minuten mit einem Engineer, der Schweizer Cluster betreibt&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;managed-selbst-betrieben-oder-betreiben-lassen&quot;&gt;Managed, selbst betrieben oder betreiben lassen&lt;/h2&gt;
&lt;p&gt;Es gibt drei Betriebsmodelle, und sie unterscheiden sich weniger im Preis als darin, wer nachts aufsteht. Die folgende Matrix ordnet sie entlang der Kriterien, die in Budgetdiskussionen tatsächlich auftauchen.&lt;/p&gt;





















































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Kriterium&lt;/th&gt;&lt;th&gt;Managed beim Anbieter&lt;/th&gt;&lt;th&gt;Selbst betrieben auf IaaS&lt;/th&gt;&lt;th&gt;Betreiben lassen&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Infrastruktur pro Monat&lt;/td&gt;&lt;td&gt;CHF 158 bis 779&lt;/td&gt;&lt;td&gt;CHF 132 pro Node und 30 Tage bei cloudscale.ch&lt;/td&gt;&lt;td&gt;wie Managed oder IaaS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Betriebsaufwand intern&lt;/td&gt;&lt;td&gt;4 bis 10 h pro Woche&lt;/td&gt;&lt;td&gt;10 bis 20 h pro Woche&lt;/td&gt;&lt;td&gt;nahe null&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Zusatzkosten Betrieb&lt;/td&gt;&lt;td&gt;CHF 1’730 bis 6’070&lt;/td&gt;&lt;td&gt;CHF 4’330 bis 12’130&lt;/td&gt;&lt;td&gt;ab CHF 4’900 bei VSHN&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Control Plane&lt;/td&gt;&lt;td&gt;Anbieter&lt;/td&gt;&lt;td&gt;Sie&lt;/td&gt;&lt;td&gt;Partner&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Anbieterbindung&lt;/td&gt;&lt;td&gt;hoch&lt;/td&gt;&lt;td&gt;tief&lt;/td&gt;&lt;td&gt;tief&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Datenstandort steuerbar&lt;/td&gt;&lt;td&gt;nur Anbieter-Zonen&lt;/td&gt;&lt;td&gt;vollständig&lt;/td&gt;&lt;td&gt;vollständig&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Passt, wenn&lt;/td&gt;&lt;td&gt;ein Team, klare Workloads&lt;/td&gt;&lt;td&gt;Compliance verlangt eigene Hoheit&lt;/td&gt;&lt;td&gt;Plattform ist kritisch, Team ist klein&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Der Preis für „betreiben lassen” ist öffentlich: &lt;a href=&quot;https://products.vshn.ch/openshift/pricing.html&quot;&gt;VSHN publiziert&lt;/a&gt; für Managed OpenShift auf Cloud-Provider-Infrastruktur CHF 4’900 pro Monat als Baseline, CHF 7’500 mit 99.9 Prozent rund um die Uhr und CHF 10’100 bei 99.99 Prozent (abgerufen 19.08.2026). Der Stundensatz für Zusatzarbeiten liegt bei CHF 250.&lt;/p&gt;
&lt;p&gt;Hier liegt die Lücke im Schweizer Markt. Exoscale, Infomaniak, Flow Swiss, cloudscale.ch, Metanet und Swisscom verkaufen Infrastruktur. VSHN verkauft eine eigene Plattform. Niemand verkauft „wir bauen und betreiben Ihre Plattform auf Ihrer Infrastruktur, mit Ihren Tools”. Genau das ist unsere Position, und deshalb steht sie hier in der Matrix und nicht in einem Werbekasten.&lt;/p&gt;
&lt;h2 id=&quot;wo-die-über-provisionierung-sitzt-die-niemand-sieht&quot;&gt;Wo die Über-Provisionierung sitzt, die niemand sieht&lt;/h2&gt;
&lt;p&gt;Die Infrastrukturrechnung entsteht an einer Stelle, die im Code steht, nicht im Portal. Kubernetes plant Pods nach &lt;code&gt;requests&lt;/code&gt;, nicht nach tatsächlicher Last. Wer grosszügig requestet, bezahlt Nodes für Kapazität, die nie genutzt wird.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;resources&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  requests&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    cpu&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    memory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;4Gi&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  limits&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    cpu&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    memory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;4Gi&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vier solche Pods belegen 8 vCPU und binden damit CPU-seitig zwei der Worker-Nodes aus unserem Referenzszenario. Bei Flow Swiss sind das CHF 394 pro Monat, bei Infomaniak CHF 50.06. Ob die Pods 5 Prozent oder 95 Prozent davon brauchen, sieht man auf der Rechnung nicht.&lt;/p&gt;
&lt;p&gt;Der Abgleich zwischen angefordert und verbraucht dauert zwei Befehle:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kubectl&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; pods&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -A&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; custom-columns=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;NS:.metadata.namespace,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;POD:.metadata.name,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;CPU_REQ:.spec.containers[*].resources.requests.cpu,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MEM_REQ:.spec.containers[*].resources.requests.memory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kubectl&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; top&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; pods&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -A&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; --containers&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wo die zweite Ausgabe dauerhaft weit unter der ersten liegt, zahlen Sie für Luft. Das ist der einzige Hebel in diesem Beitrag, der ohne Anbieterwechsel wirkt.&lt;/p&gt;
&lt;h2 id=&quot;wann-sich-der-cluster-nicht-rechnet&quot;&gt;Wann sich der Cluster nicht rechnet&lt;/h2&gt;
&lt;p&gt;Unter etwa fünf Diensten und einem Team rechnet sich Kubernetes in der Schweiz nicht. Bei CHF 158 Infrastruktur und CHF 2’430 Betrieb pro Monat zahlen Sie rund 94 Prozent der Rechnung für Betriebswissen, das eine einzelne gut dimensionierte VM mit Docker Compose, &lt;code&gt;systemd&lt;/code&gt; und einem sauberen Deploy-Skript nicht braucht.&lt;/p&gt;
&lt;p&gt;Wir raten in diesen Fällen ab, auch wenn wir Kubernetes bauen und betreiben. Die ehrliche Frage steht in &lt;a href=&quot;https://devs-group.ch/blog/kubernetes-ist-kein-ziel/&quot;&gt;Kubernetes ist kein Ziel&lt;/a&gt;: Was passiert, wenn dieser Dienst um drei Uhr morgens ausfällt, und wer schaut hin? Lautet die Antwort „ein Alarm, ein Runbook, ein Neustart”, braucht es keinen Orchestrator.&lt;/p&gt;
&lt;p&gt;Der Cluster rechnet sich, sobald mehrere Teams unabhängig deployen, Lastspitzen unvorhersehbar sind oder Compliance reproduzierbare, deklarative Infrastruktur mit Audit-Trail verlangt. Für &lt;a href=&quot;https://devs-group.ch/projekte/onocoy/&quot;&gt;onocoy&lt;/a&gt; und &lt;a href=&quot;https://devs-group.ch/projekte/relai/&quot;&gt;Relai&lt;/a&gt; trifft genau das zu. Für eine Anwendung mit einer Datenbank und bekanntem Traffic trifft es nicht zu.&lt;/p&gt;
&lt;h2 id=&quot;was-sich-über-zwölf-monate-an-der-rechnung-ändert&quot;&gt;Was sich über zwölf Monate an der Rechnung ändert&lt;/h2&gt;
&lt;p&gt;Über zwölf Monate bewegen sich vor allem die Worker-Nodes, und zwar in beide Richtungen. Right-Sizing der Requests holt typischerweise am meisten heraus, weil es direkt die Anzahl Nodes senkt.&lt;/p&gt;
&lt;p&gt;Cluster Autoscaling hilft nur bei schwankender Last. Bei konstanter Grundlast verschiebt es die Rechnung nicht, es verkompliziert sie. Infomaniak und Exoscale unterstützen Node-Pools mit Minimum und Maximum; wer beide gleich setzt, hat Autoscaling nur nominell.&lt;/p&gt;
&lt;p&gt;Was in der Schweiz fehlt: Reservierungen. Weder Exoscale noch Infomaniak noch Flow Swiss publizieren Rabatte für Laufzeitbindung, wie sie AWS mit Savings Plans anbietet. Wer plant, mit einer Vorauszahlung 30 Prozent zu sparen, plant mit einem Instrument, das es hier nicht gibt.&lt;/p&gt;
&lt;p&gt;Die Betriebsseite bewegt sich in die andere Richtung. Im ersten Jahr ist der Aufwand am höchsten, weil Ingress, Secrets-Handling, Backup-Strategie und CI-Anbindung erst entstehen. Danach sinkt er auf ein Grundrauschen aus Upgrades und Incidents, und genau dieses Grundrauschen ist die Zahl, mit der Sie planen sollten, nicht der Aufbauaufwand.&lt;/p&gt;
&lt;p&gt;Der Posten, der diese Rechnung am schnellsten sprengt, steht hier nicht drin: GPUs. Eine einzige Inferenz-Karte kostet mehr als der gesamte Cluster oben. Was souveräne KI-Inferenz auf Schweizer Infrastruktur kostet und ab welchem Anfragevolumen sich Eigenbetrieb gegenüber einer API rechnet, steht in &lt;a href=&quot;https://devs-group.ch/blog/souveraene-ki-inferenz-schweiz/&quot;&gt;souveräne KI-Inferenz in der Schweiz&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;was-kostet-ein-managed-kubernetes-cluster-in-der-schweiz-pro-monat&quot;&gt;Was kostet ein Managed-Kubernetes-Cluster in der Schweiz pro Monat?&lt;/h3&gt;
&lt;p&gt;Ein Cluster mit drei Worker-Nodes zu je 4 vCPU und 16 GB RAM, 500 GB Storage und Control Plane mit SLA kostet zwischen CHF 158 und CHF 779 pro Monat, je nach Anbieter. Das Minimum für einen sehr kleinen Cluster liegt bei Infomaniak bei rund CHF 33. Alle Werte aus publizierten Preislisten, abgerufen am 19. August 2026, exklusive MwSt.&lt;/p&gt;
&lt;h3 id=&quot;ist-kubernetes-nicht-kostenlos&quot;&gt;Ist Kubernetes nicht kostenlos?&lt;/h3&gt;
&lt;p&gt;Kubernetes ist Open Source unter Apache-2.0-Lizenz, es fallen keine Lizenzkosten an. Kosten entstehen durch Maschinen und Menschen: Control Plane, Worker-Nodes, Storage und Traffic ergeben CHF 158 bis 779 pro Monat für einen Cluster in produktiver Grösse, dazu kommt der Betriebsaufwand ab CHF 1’730 monatlich. Der lizenzfreie Teil ist der kleinste Teil der Rechnung.&lt;/p&gt;
&lt;h3 id=&quot;was-kostet-kubernetes-bei-azure-und-aws-in-der-schweiz-1&quot;&gt;Was kostet Kubernetes bei Azure und AWS in der Schweiz?&lt;/h3&gt;
&lt;p&gt;Azure AKS in der Region Switzerland North kostet im Referenzszenario CHF 601.74 pro Monat, AWS EKS in Europe (Zurich) USD 705.85. Beide liegen im Feld der Schweizer Anbieter: teurer als Exoscale mit CHF 540.74, günstiger als Flow Swiss mit CHF 779.00. AWS publiziert für Zürich ausschliesslich USD-Preise, Azure liefert echte CHF-Preise (Stand 19.08.2026).&lt;/p&gt;
&lt;h3 id=&quot;brauche-ich-als-kmu-überhaupt-kubernetes-oder-reicht-docker-compose&quot;&gt;Brauche ich als KMU überhaupt Kubernetes, oder reicht Docker Compose?&lt;/h3&gt;
&lt;p&gt;Docker Compose auf einer VM reicht, solange eine Anwendung, eine Datenbank und ein Team im Spiel sind und der Traffic bekannt ist. Kubernetes lohnt sich ab mehreren unabhängig deployenden Teams, unvorhersehbaren Lastspitzen oder Compliance-Anforderungen an deklarative Infrastruktur. Die Betriebskosten von CHF 1’730 aufwärts pro Monat entscheiden diese Frage häufiger als die Infrastrukturkosten.&lt;/p&gt;
&lt;h3 id=&quot;bleiben-meine-daten-bei-einem-schweizer-kubernetes-anbieter-in-der-schweiz&quot;&gt;Bleiben meine Daten bei einem Schweizer Kubernetes-Anbieter in der Schweiz?&lt;/h3&gt;
&lt;p&gt;Das hängt vom Anbieter und von der gewählten Zone ab. Infomaniak betreibt eigene Rechenzentren in der Schweiz, Flow Swiss die Regionen ZRH1 und ALP1. Exoscale bietet die Schweizer Zonen ch-gva-2 und ch-dk-2 an, gehört aber seit 2017 zur Telekom Austria Group. Für revDSG-Prüfungen ist neben dem Standort auch die Eigentümerschaft relevant.&lt;/p&gt;
&lt;h2 id=&quot;rechnen-wir-ihren-cluster-durch&quot;&gt;Rechnen wir Ihren Cluster durch&lt;/h2&gt;
&lt;p&gt;Bringen Sie Ihre Node-Grössen, Ihre Storage-Klasse und eine ehrliche Schätzung der internen Stunden mit. Wir legen die aktuellen Preislisten daneben und rechnen beide Seiten der Rechnung, Infrastruktur und Betrieb, in einem Termin durch.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin buchen&lt;/a&gt; oder &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;schreiben Sie uns&lt;/a&gt;, wenn Ihnen eine Frage per Mail lieber ist. Was wir dabei bauen und betreiben, steht unter &lt;a href=&quot;https://devs-group.ch/leistungen/kubernetes-and-infrastruktur/&quot;&gt;Kubernetes und Infrastruktur&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Cloud &amp; Infrastruktur</category><author>Ralph Segi</author></item><item><title>Souveräne KI-Inferenz in der Schweiz: die Architektur</title><link>https://devs-group.ch/blog/souveraene-ki-inferenz-schweiz/</link><guid isPermaLink="true">https://devs-group.ch/blog/souveraene-ki-inferenz-schweiz/</guid><description>Anbietervergleich in CHF, GPU-Scheduling mit DRA und die Stellen, an denen Souveränität tatsächlich bricht. Meist ist es nicht das Modell.</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Souveräne KI-Inferenz ist eine Eigenschaft des gesamten Datenflusses, nicht des Modells. Ein in Zürich gehostetes Apertus-Modell ist nicht souverän, wenn die Traces bei einem US-Monitoring-Dienst landen, die Vektordatenbank in Irland liegt oder der Support aus einem Drittstaat in die Logs schaut. Souverän ist eine Architektur erst, wenn Prompt, Kontext, Gewichte, Logs und Metadaten dieselbe Jurisdiktion nie verlassen.&lt;/p&gt;
&lt;p&gt;Über digitale Souveränität ist viel geschrieben worden. ipt etwa führt eine Seite mit dem Title-Tag „Souveräne KI Plattformen auf Kubernetes” und hat das Thema mit dem ETH AI Center bespielt. Was fehlt, ist die Ebene darunter: welche Anbieter es gibt, was sie kosten, wie der Betrieb aussieht.&lt;/p&gt;
&lt;p&gt;Wir rechnen das am Schweizer Markt durch, weil dort Preise und Rechtslage öffentlich prüfbar sind. Die Architektur darunter ist dieselbe, ob die souveräne Cloud in Zürich, Frankfurt oder Paris steht.&lt;/p&gt;
&lt;h2 id=&quot;was-souveräne-ki-inferenz-technisch-bedeutet&quot;&gt;Was souveräne KI-Inferenz technisch bedeutet&lt;/h2&gt;
&lt;p&gt;Souveränität lässt sich an fünf Artefakten prüfen, die bei jeder Inferenz-Anfrage entstehen. Modellgewichte, Prompt, abgerufener Kontext, generierte Antwort und die Telemetrie darüber. Jedes hat einen physischen Speicherort und einen rechtlichen Zugriffsberechtigten, und die beiden sind nicht dasselbe.&lt;/p&gt;
&lt;p&gt;Das Schweizer Recht macht daraus eine konkrete Prüfung. Art. 16 revDSG erlaubt die Bekanntgabe von Personendaten ins Ausland nur, wenn der Bundesrat den Zielstaat als angemessen eingestuft hat.&lt;/p&gt;
&lt;p&gt;Die Liste steht in Anhang 1 der Datenschutzverordnung (SR 235.11). Die USA stehen &lt;a href=&quot;https://www.edoeb.admin.ch/de/bekanntgabe-von-personendaten-ins-ausland&quot;&gt;seit dem 15. September 2024 darauf&lt;/a&gt;, aber nur für Organisationen, die unter dem Swiss-US Data Privacy Framework zertifiziert sind.&lt;/p&gt;
&lt;p&gt;Der zweite Prüfpfad läuft über den Anbieter selbst. &lt;a href=&quot;https://www.law.cornell.edu/uscode/text/18/2713&quot;&gt;18 U.S.C. § 2713&lt;/a&gt;, eingeführt mit dem CLOUD Act, verpflichtet US-Anbieter zur Herausgabe gespeicherter Daten „regardless of whether such communication, record, or other information is located within or outside of the United States”.&lt;/p&gt;
&lt;p&gt;Ein Rechenzentrum in Zürich ändert daran nichts, wenn die betreibende Gesellschaft US-Konzernrecht untersteht. Welche Architekturentscheidungen daraus folgen, steht in &lt;a href=&quot;https://devs-group.ch/blog/revdsg-konforme-ki-architektur/&quot;&gt;revDSG-konforme KI-Architektur&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;welche-schweizer-cloud-anbieter-souveräne-ki-inferenz-anbieten&quot;&gt;Welche Schweizer Cloud-Anbieter souveräne KI-Inferenz anbieten&lt;/h2&gt;
&lt;p&gt;Vier Anbieter kommen für produktive GPU-Inferenz in der Schweiz realistisch infrage, dazu der Eigenbetrieb. Nur einer davon publiziert vollständige Preise.&lt;/p&gt;





















































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Anbieter&lt;/th&gt;&lt;th&gt;GPU-Typen&lt;/th&gt;&lt;th&gt;Abrechnungsmodell&lt;/th&gt;&lt;th&gt;Datenstandort&lt;/th&gt;&lt;th&gt;Kubernetes-Zugang&lt;/th&gt;&lt;th&gt;Öffentliche Preise&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Exoscale&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;RTX Pro 6000 (96 GB), A40, A5000, A30, V100, 3080ti; B300 auf Anfrage&lt;/td&gt;&lt;td&gt;Instanz pro Stunde, Dedicated Inference pro Sekunde&lt;/td&gt;&lt;td&gt;je nach GPU-Typ CH-DK-2 (Schweiz), DE-FRA-1, AT-VIE-2, HR-ZAG-1&lt;/td&gt;&lt;td&gt;ja, SKS&lt;/td&gt;&lt;td&gt;&lt;strong&gt;ja&lt;/strong&gt;, vollständig in CHF&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Infomaniak&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;B300, H200, H100, A100, L40S, L4, A2, T4&lt;/td&gt;&lt;td&gt;GPU-Instanz pro Stunde, AI Services pro Token&lt;/td&gt;&lt;td&gt;Genf und Zürich&lt;/td&gt;&lt;td&gt;ja, Kubernetes-Dienst&lt;/td&gt;&lt;td&gt;&lt;strong&gt;teilweise&lt;/strong&gt;: Token-Preise publiziert, Instanzpreise nur im Konfigurator&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Swisscom Swiss AI Platform&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;NVIDIA SuperPOD&lt;/td&gt;&lt;td&gt;GPU as a Service, dazu Inference-Endpunkte pro Token&lt;/td&gt;&lt;td&gt;Schweiz&lt;/td&gt;&lt;td&gt;nicht dokumentiert&lt;/td&gt;&lt;td&gt;&lt;strong&gt;nein&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Phoenix Technologies&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;H100, H200&lt;/td&gt;&lt;td&gt;nicht publiziert&lt;/td&gt;&lt;td&gt;Schweiz&lt;/td&gt;&lt;td&gt;nicht dokumentiert&lt;/td&gt;&lt;td&gt;&lt;strong&gt;nein&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Eigenbetrieb, Colocation&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;frei wählbar&lt;/td&gt;&lt;td&gt;CapEx plus Housing&lt;/td&gt;&lt;td&gt;frei wählbar&lt;/td&gt;&lt;td&gt;ja, selbst gebaut&lt;/td&gt;&lt;td&gt;entfällt&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Ein Detail, das bei der Souveränitätsprüfung zählt: Exoscales RTX-Pro-6000-Instanzen laufen in DE-FRA-1, HR-ZAG-1 und CH-DK-2, die 3080ti-Instanzen ausschliesslich in AT-VIE-2. Ein Schweizer Anbieter garantiert also nicht automatisch eine Schweizer Zone (abgerufen 19.08.2026).&lt;/p&gt;
&lt;h2 id=&quot;apertus-15-was-das-schweizer-modell-heute-kann&quot;&gt;Apertus 1.5: was das Schweizer Modell heute kann&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.apertus-ai.org/articles/2026-07-apertus-1-5/&quot;&gt;Apertus 1.5&lt;/a&gt; erschien am 24. Juli 2026 und ist gegenüber der Fassung vom September 2025 ein anderes Modell. Das Kontextfenster liegt bei 262’144 Tokens, eine Vervierfachung. Die Modelle nehmen neu Bilder entgegen, Audio ist als experimentell gekennzeichnet. Lizenz: Apache 2.0.&lt;/p&gt;
&lt;p&gt;Für den Betrieb zählt die Tool-Integration mehr als die Multimodalität. Die &lt;a href=&quot;https://huggingface.co/swiss-ai/Apertus-v1.5-70B&quot;&gt;Modellkarte für Apertus-v1.5-70B&lt;/a&gt; dokumentiert einen eigenen Tool-Call-Parser und einen optionalen Thinking-Modus, beides direkt in vLLM ansteuerbar. Damit ist Apertus für Agenten-Architekturen brauchbar, nicht nur für Chat.&lt;/p&gt;
&lt;p&gt;Entwickelt haben es EPFL, ETH Zürich und das CSCS auf dem Alps-Supercomputer in Lugano. Wer nicht selbst betreiben will: Infomaniak führt &lt;code&gt;swiss-ai/Apertus-v1.5-70B&lt;/code&gt; als API-Modell, aktuell als Beta.&lt;/p&gt;
&lt;h2 id=&quot;apertus-selbst-betreiben-hugging-face-ollama-oder-apertus-mini&quot;&gt;Apertus selbst betreiben: Hugging Face, Ollama oder Apertus Mini&lt;/h2&gt;
&lt;p&gt;Für den Eigenbetrieb gibt es drei Wege mit sehr unterschiedlichem Produktionsreifegrad.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hugging Face plus vLLM&lt;/strong&gt; ist der produktive Pfad. &lt;code&gt;swiss-ai/Apertus-v1.5-70B&lt;/code&gt; und die 8B-Variante liegen dort unter Apache 2.0 und laden ohne Konvertierungsschritt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ollama ist der schnellste Weg zum Prompt und der langsamste zur Produktion.&lt;/strong&gt; Es gibt keinen offiziellen Apertus-Build von swiss-ai; die verbreiteten GGUF-Pakete stammen von Community-Packagern und führen die Fassung &lt;code&gt;2509&lt;/code&gt;, also Apertus 1.0. Wer 1.5 lokal will, quantisiert selbst. Für einen Laptop-Test ist das in Ordnung, für einen Dienst mit Parallellast nicht.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apertus Mini löst oft das eigentliche Problem.&lt;/strong&gt; Die &lt;a href=&quot;https://huggingface.co/collections/swiss-ai/apertus-mini&quot;&gt;offizielle Collection&lt;/a&gt; enthält Distillate der Reihe v1.1 in 0.5B, 1.5B und 4B, dazu Quantisierungen für MLX und vLLM. Für Klassifikation, Extraktion und Routing reicht ein 4B-Modell meist, und es verschiebt die GPU-Kosten um eine Grössenordnung.&lt;/p&gt;
&lt;h2 id=&quot;was-inferenz-auf-eigener-infrastruktur-kostet&quot;&gt;Was Inferenz auf eigener Infrastruktur kostet&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Modellrechnung&lt;/strong&gt;, hergeleitet aus publizierten Preislisten, abgerufen am 19. August 2026. Sie gilt für Apertus-v1.5-70B und vergleicht zwei Bezugswege beim selben Souveränitätsniveau.&lt;/p&gt;
&lt;p&gt;Die &lt;a href=&quot;https://huggingface.co/swiss-ai/Apertus-v1.5-70B&quot;&gt;Modellkarte&lt;/a&gt; nennt als Referenzkonfiguration &lt;code&gt;--tensor-parallel-size 4&lt;/code&gt; bei vollen 262’144 Tokens Kontext. Bei 72 Milliarden Parametern in BF16 sind das 144 GB reine Gewichte, dazu der KV-Cache. Vier Karten mit je 96 GB sind damit das Minimum, keine Grosszügigkeit.&lt;/p&gt;
&lt;p&gt;Eigenbetrieb, Exoscale Dedicated Inference auf RTX Pro 6000, &lt;a href=&quot;https://www.exoscale.com/pricing/&quot;&gt;publizierte Preisliste&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CHF 2.15277778 pro GPU und Stunde, sekundengenau abgerechnet&lt;/li&gt;
&lt;li&gt;4 GPUs im Dauerbetrieb: 4 × 2.15277778 × 720 h = &lt;strong&gt;CHF 6’200 pro Monat&lt;/strong&gt; (720 Stunden, wie Exoscale selbst auf Monatspreise umrechnet)&lt;/li&gt;
&lt;li&gt;Modellspeicher 134 GiB (144 GB Gewichte) zu CHF 0.0000275 pro GiB-Stunde: CHF 2.65 pro Monat&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;API-Bezug, Infomaniak AI Services, &lt;a href=&quot;https://www.infomaniak.com/en/hosting/ai-services/prices&quot;&gt;publizierte Preisliste&lt;/a&gt;: CHF 0.70 pro Million Input-Tokens, CHF 2.50 pro Million Output-Tokens für dasselbe Modell.&lt;/p&gt;
&lt;p&gt;Angenommenes Anfrageprofil: 3’000 Tokens Input (Systemprompt plus RAG-Kontext), 500 Tokens Output. Das ergibt CHF 0.00335 pro Anfrage oder CHF 0.96 pro Million gemischter Tokens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Der Kipppunkt liegt bei rund 1.85 Millionen Anfragen pro Monat&lt;/strong&gt;, also etwa 62’000 pro Tag. Darunter ist die API günstiger. Das entspricht 6.5 Milliarden Tokens im Monat oder rund 2’500 Tokens pro Sekunde im Dauerdurchsatz.&lt;/p&gt;
&lt;p&gt;Bei 2’500 Tokens pro Sekunde laufen die vier Karten allerdings rund um die Uhr am Anschlag, und kein Betrieb fährt so. Wer Reserve für Lastspitzen und eine zweite Zone für Ausfälle einplant, verdoppelt die GPU-Kosten und damit den Kipppunkt: realistisch drei bis vier Millionen Anfragen pro Monat.&lt;/p&gt;
&lt;p&gt;Umgekehrt hilft die Sekundenabrechnung: Wer nur zu Bürozeiten Last hat und auf null skaliert, zahlt bei 220 Stunden im Monat CHF 1’894 statt CHF 6’200, und der Kipppunkt fällt auf rund 566’000 Anfragen. Die geforderte Spitzenlast bleibt dieselbe.&lt;/p&gt;
&lt;p&gt;Nicht enthalten: der Cluster darunter (Exoscale SKS Pro CHF 0.054995 pro Stunde, rund CHF 40 im Monat, im Detail in &lt;a href=&quot;https://devs-group.ch/blog/was-kostet-kubernetes-in-der-schweiz/&quot;&gt;was Kubernetes in der Schweiz wirklich kostet&lt;/a&gt;) und Ihre Zeit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rechnen Sie den Kipppunkt für Ihr Profil nach.&lt;/strong&gt; Er verschiebt sich stark durch Prompt-Caching, ein kleineres Modell oder einen anderen Input-Output-Schnitt. Wenn Sie Ihr Anfrageprofil kennen, &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;rechnen wir das gemeinsam durch&lt;/a&gt;, mit Ihren Zahlen statt unseren Annahmen.&lt;/p&gt;
&lt;h2 id=&quot;gpu-scheduling-auf-kubernetes-dra-statt-device-plugins&quot;&gt;GPU-Scheduling auf Kubernetes: DRA statt Device Plugins&lt;/h2&gt;
&lt;p&gt;Dynamic Resource Allocation ersetzt die Zählweise „gib mir eine GPU” durch eine Anforderung an Eigenschaften. Der Kern von DRA ist &lt;a href=&quot;https://kubernetes.io/blog/2025/09/01/kubernetes-v1-34-dra-updates/&quot;&gt;seit Kubernetes v1.34 GA&lt;/a&gt;, die API-Gruppe ist &lt;code&gt;resource.k8s.io/v1&lt;/code&gt;; die &lt;a href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/&quot;&gt;Konzeptseite der Doku&lt;/a&gt; führt DRA inzwischen als &lt;code&gt;Kubernetes v1.35 [stable]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Das alte Device Plugin kannte nur &lt;code&gt;nvidia.com/gpu: 4&lt;/code&gt;. Welche vier Karten der Scheduler nimmt, war ihm egal. Bei einem 70B-Modell mit Tensor-Parallelismus ist das kein Detail: Vier Karten mit 24 GB sind nicht dasselbe wie vier mit 96 GB, und der Pod stirbt erst beim Laden der Gewichte.&lt;/p&gt;
&lt;p&gt;Mit DRA formulieren Sie die Anforderung als CEL-Ausdruck gegen die Attribute, die der Treiber publiziert:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Vier GPUs mit je mindestens 80 GiB, exklusiv für einen vLLM-Pod.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Setzt den DRA-Treiber für NVIDIA-GPUs voraus (DeviceClass gpu.nvidia.com).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;resource.k8s.io/v1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ResourceClaimTemplate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;apertus-70b-gpus&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  namespace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;inference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  spec&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    devices&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      requests&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;gpu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;          exactly&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;            deviceClassName&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;gpu.nvidia.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;            allocationMode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ExactCount&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;            count&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;            selectors&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;cel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;                  expression&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                    device.capacity[&amp;#39;gpu.nvidia.com&amp;#39;].memory.isGreaterThan(quantity(&amp;#39;80Gi&amp;#39;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Pod referenziert das Template, statt eine Zahl zu fordern:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  resourceClaims&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;gpu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      resourceClaimTemplateName&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;apertus-70b-gpus&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  containers&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;vllm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      image&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;vllm/vllm-openai:v0.27.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      resources&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;        claims&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;          - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;gpu&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Unterschied in der Praxis: Ein falsch dimensionierter Node fällt beim Scheduling durch, nicht nach acht Minuten Modell-Download. Der &lt;a href=&quot;https://dra-driver-nvidia-gpu.sigs.k8s.io/docs/reference/resourceslice-attributes/&quot;&gt;DRA-Treiber für NVIDIA-GPUs&lt;/a&gt; publiziert dafür unter anderem &lt;code&gt;productName&lt;/code&gt;, &lt;code&gt;architecture&lt;/code&gt; und &lt;code&gt;cudaComputeCapability&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;inference-serving-was-zwischen-modell-und-anwendung-gehört&quot;&gt;Inference-Serving: was zwischen Modell und Anwendung gehört&lt;/h2&gt;
&lt;p&gt;vLLM ist der Modellserver, nicht die Plattform. Es macht Continuous Batching, PagedAttention und einen OpenAI-kompatiblen Endpunkt. Was es nicht macht: entscheiden, welche von acht Replicas eine Anfrage bekommt.&lt;/p&gt;
&lt;p&gt;Ein Deployment-Ausschnitt für Apertus. Tool-Parser und Chat-Template stammen aus der Modellkarte; das Kontextfenster ist halbiert, weil der KV-Cache sonst den GPU-Speicher füllt:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;containers&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;vllm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    image&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;vllm/vllm-openai:v0.27.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    args&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;--model=swiss-ai/Apertus-v1.5-70B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;--served-model-name=apertus-70b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;--tensor-parallel-size=4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;--max-model-len=131072&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;--gpu-memory-utilization=0.90&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;--chat-template-content-format=string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;--enable-auto-tool-choice&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;--tool-call-parser=apertus&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    ports&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;containerPort&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    readinessProbe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;      httpGet&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/health&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das Routing gehört eine Ebene höher. Die &lt;a href=&quot;https://github.com/kubernetes-sigs/gateway-api-inference-extension&quot;&gt;Gateway API Inference Extension&lt;/a&gt; (v1.6.0 vom 17.08.2026) bringt den &lt;code&gt;InferencePool&lt;/code&gt; und einen Endpoint Picker, der Warteschlangentiefe und KV-Cache-Auslastung auswertet. Ein Round-Robin-Loadbalancer trifft dagegen ein Replica, dessen Cache den Präfix nicht hat, und zahlt den Prefill zweimal.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;inference.networking.k8s.io/v1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;InferencePool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;apertus-70b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  selector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    matchLabels&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;apertus-70b&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  targetPorts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  endpointPickerRef&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;apertus-70b-epp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    port&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;9002&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    failureMode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;FailOpen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;llm-d (v0.9.0 vom 17.08.2026) kombiniert beides zu disaggregiertem Serving, also Prefill und Decode auf getrennten Pods. Für die meisten Installationen dieser Grösse ist das eine Nummer zu gross.&lt;/p&gt;
&lt;h2 id=&quot;wo-souveränität-real-bricht&quot;&gt;Wo Souveränität real bricht&lt;/h2&gt;
&lt;p&gt;Das Modell ist selten das Problem. Die Bruchstellen sitzen in der Peripherie, die niemand als KI-Komponente wahrnimmt und deshalb niemand prüft.&lt;/p&gt;
&lt;div class=&quot;scroll-x scroll-x--diagram&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Diagramm, seitlich scrollbar&quot;&gt;&lt;svg id=&quot;mermaid-0&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot; class=&quot;flowchart&quot; style=&quot;width:1198.203125px&quot; viewBox=&quot;0 0 1198.203125 835&quot; role=&quot;graphics-document document&quot; aria-roledescription=&quot;flowchart-v2&quot;&gt;&lt;style&gt;#mermaid-0{font-family:&quot;Geist&quot;,sans-serif;font-size:16px;fill:#f5f5f5;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-0 .error-icon{fill:#121315;}#mermaid-0 .error-text{fill:#edecea;stroke:#edecea;}#mermaid-0 .edge-thickness-normal{stroke-width:1px;}#mermaid-0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-0 .marker{fill:#c4c4c4;stroke:#c4c4c4;}#mermaid-0 .marker.cross{stroke:#c4c4c4;}#mermaid-0 svg{font-family:&quot;Geist&quot;,sans-serif;font-size:16px;}#mermaid-0 p{margin:0;}#mermaid-0 .label{font-family:&quot;Geist&quot;,sans-serif;color:#f5f5f5;}#mermaid-0 .cluster-label text{fill:#f5f5f5;}#mermaid-0 .cluster-label span{color:#f5f5f5;}#mermaid-0 .cluster-label span p{background-color:transparent;}#mermaid-0 .label text,#mermaid-0 span{fill:#f5f5f5;color:#f5f5f5;}#mermaid-0 .node rect,#mermaid-0 .node circle,#mermaid-0 .node ellipse,#mermaid-0 .node polygon,#mermaid-0 .node path{fill:#1b1d20;stroke:#363739;stroke-width:1px;}#mermaid-0 .rough-node .label text,#mermaid-0 .node .label text,#mermaid-0 .image-shape .label,#mermaid-0 .icon-shape .label{text-anchor:middle;}#mermaid-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-0 .rough-node .label,#mermaid-0 .node .label,#mermaid-0 .image-shape .label,#mermaid-0 .icon-shape .label{text-align:center;}#mermaid-0 .node.clickable{cursor:pointer;}#mermaid-0 .root .anchor path{fill:#c4c4c4!important;stroke-width:0;stroke:#c4c4c4;}#mermaid-0 .arrowheadPath{fill:#f6f5f3;}#mermaid-0 .edgePath .path{stroke:#c4c4c4;stroke-width:1px;}#mermaid-0 .flowchart-link{stroke:#c4c4c4;fill:none;}#mermaid-0 .edgeLabel{background-color:#090a0c;text-align:center;}#mermaid-0 .edgeLabel p{background-color:#090a0c;}#mermaid-0 .edgeLabel rect{opacity:0.5;background-color:#090a0c;fill:#090a0c;}#mermaid-0 .labelBkg{background-color:rgba(9, 10, 12, 0.5);}#mermaid-0 .cluster rect{fill:#121315;stroke:#232325;stroke-width:1px;}#mermaid-0 .cluster text{fill:#f5f5f5;}#mermaid-0 .cluster span{color:#f5f5f5;}#mermaid-0 .node .collapsed-indicator{fill:#232325;stroke:none;opacity:0.6;}#mermaid-0 .node .collapsed-separator{stroke:#232325;stroke-width:0.75px;}#mermaid-0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:&quot;Geist&quot;,sans-serif;font-size:12px;background:#121315;border:1px solid hsl(220, 0%, 17.6470588235%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#f5f5f5;}#mermaid-0 rect.text{fill:none;stroke-width:0;}#mermaid-0 .icon-shape,#mermaid-0 .image-shape{background-color:#090a0c;text-align:center;}#mermaid-0 .icon-shape p,#mermaid-0 .image-shape p{background-color:#090a0c;padding:2px;}#mermaid-0 .icon-shape .label rect,#mermaid-0 .image-shape .label rect{opacity:0.5;background-color:#090a0c;fill:#090a0c;}#mermaid-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-0 .node .neo-node{stroke:#363739;}#mermaid-0 [data-look=&quot;neo&quot;].node rect,#mermaid-0 [data-look=&quot;neo&quot;].cluster rect,#mermaid-0 [data-look=&quot;neo&quot;].node polygon{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].swimlane.cluster rect{filter:none;}#mermaid-0 [data-look=&quot;neo&quot;].node path{stroke:url(#mermaid-0-gradient);stroke-width:1px;}#mermaid-0 [data-look=&quot;neo&quot;].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].node .neo-line path{stroke:#363739;filter:none;}#mermaid-0 [data-look=&quot;neo&quot;].node circle{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].node circle .state-start{fill:#000000;}#mermaid-0 [data-look=&quot;neo&quot;].icon-shape .icon{fill:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 [data-look=&quot;neo&quot;].icon-shape .icon-neo path{stroke:url(#mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#mermaid-0 :root{--mermaid-font-family:&quot;Geist&quot;,sans-serif;}&lt;/style&gt;&lt;g&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointEnd&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;5&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;8&quot; markerHeight=&quot;8&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 0 L 10 5 L 0 10 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointStart&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;4.5&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;8&quot; markerHeight=&quot;8&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 5 L 10 10 L 10 0 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointEnd-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 11.5 14&quot; refX=&quot;11.5&quot; refY=&quot;7&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;10.5&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 0 0 L 11.5 7 L 0 14 z&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-pointStart-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 11.5 14&quot; refX=&quot;1&quot; refY=&quot;7&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11.5&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;polygon points=&quot;0,7 11.5,14 11.5,0&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/polygon&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleEnd&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;11&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleStart&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;-1&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:1;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleEnd-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refY=&quot;5&quot; refX=&quot;12.25&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;14&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-circleStart-margin&quot; class=&quot;marker flowchart-v2&quot; viewBox=&quot;0 0 10 10&quot; refX=&quot;-2&quot; refY=&quot;5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;14&quot; markerHeight=&quot;14&quot; orient=&quot;auto&quot;&gt;&lt;circle cx=&quot;5&quot; cy=&quot;5&quot; r=&quot;5&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:0;stroke-dasharray:1, 0&quot;&gt;&lt;/circle&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossEnd&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 11 11&quot; refX=&quot;12&quot; refY=&quot;5.2&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 l 9,9 M 10,1 l -9,9&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossStart&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 11 11&quot; refX=&quot;-1&quot; refY=&quot;5.2&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;11&quot; markerHeight=&quot;11&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 l 9,9 M 10,1 l -9,9&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossEnd-margin&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 15 15&quot; refX=&quot;17.7&quot; refY=&quot;7.5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;12&quot; markerHeight=&quot;12&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 L 14,14 M 1,14 L 14,1&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2.5&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;marker id=&quot;mermaid-0_flowchart-v2-crossStart-margin&quot; class=&quot;marker cross flowchart-v2&quot; viewBox=&quot;0 0 15 15&quot; refX=&quot;-3.5&quot; refY=&quot;7.5&quot; markerUnits=&quot;userSpaceOnUse&quot; markerWidth=&quot;12&quot; markerHeight=&quot;12&quot; orient=&quot;auto&quot;&gt;&lt;path d=&quot;M 1,1 L 14,14 M 1,14 L 14,1&quot; class=&quot;arrowMarkerPath&quot; style=&quot;stroke-width:2.5;stroke-dasharray:1, 0&quot;&gt;&lt;/path&gt;&lt;/marker&gt;&lt;g class=&quot;root&quot;&gt;&lt;g class=&quot;clusters&quot;&gt;&lt;g class=&quot;cluster&quot; id=&quot;mermaid-0-US&quot; data-look=&quot;classic&quot;&gt;&lt;rect style=&quot;&quot; x=&quot;8&quot; y=&quot;112&quot; width=&quot;330&quot; height=&quot;715&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;cluster-label&quot; transform=&quot;translate(67.46875, 112)&quot;&gt;&lt;foreignObject width=&quot;211.0625&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Jurisdiktion USA, CLOUD Act&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;cluster&quot; id=&quot;mermaid-0-EU&quot; data-look=&quot;classic&quot;&gt;&lt;rect style=&quot;&quot; x=&quot;358&quot; y=&quot;522&quot; width=&quot;330&quot; height=&quot;128&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;cluster-label&quot; transform=&quot;translate(467.8203125, 522)&quot;&gt;&lt;foreignObject width=&quot;110.359375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Jurisdiktion EU&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;cluster&quot; id=&quot;mermaid-0-CH&quot; data-look=&quot;classic&quot;&gt;&lt;rect style=&quot;&quot; x=&quot;708&quot; y=&quot;241&quot; width=&quot;482.203125&quot; height=&quot;409&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;cluster-label&quot; transform=&quot;translate(873.4453125, 241)&quot;&gt;&lt;foreignObject width=&quot;151.3125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Jurisdiktion Schweiz&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgePaths&quot;&gt;&lt;path d=&quot;M173,62L173,66.167C173,70.333,173,78.667,173,87C173,95.333,173,103.667,173,111.333C173,119,173,126,173,129.5L173,133&quot; id=&quot;mermaid-0-L_CLIENT_CDN_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_CLIENT_CDN_0&quot; data-points=&quot;W3sieCI6MTczLCJ5Ijo2Mn0seyJ4IjoxNzMsInkiOjg3fSx7IngiOjE3MywieSI6MTEyfSx7IngiOjE3MywieSI6MTM3fV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M173,191L173,195.167C173,199.333,173,207.667,173,216C173,224.333,173,232.667,280.782,244.318C388.563,255.969,604.126,270.939,711.908,278.423L819.689,285.908&quot; id=&quot;mermaid-0-L_CDN_GW_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_CDN_GW_0&quot; data-points=&quot;W3sieCI6MTczLCJ5IjoxOTF9LHsieCI6MTczLCJ5IjoyMTZ9LHsieCI6MTczLCJ5IjoyNDF9LHsieCI6ODIzLjY3OTY4NzUsInkiOjI4Ni4xODQ4NjM2OTE4NDg2NX1d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M921.82,320L921.82,324.167C921.82,328.333,921.82,336.667,921.82,344.333C921.82,352,921.82,359,921.82,362.5L921.82,366&quot; id=&quot;mermaid-0-L_GW_V_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_GW_V_0&quot; data-points=&quot;W3sieCI6OTIxLjgyMDMxMjUsInkiOjMyMH0seyJ4Ijo5MjEuODIwMzEyNSwieSI6MzQ1fSx7IngiOjkyMS44MjAzMTI1LCJ5IjozNzB9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M974.872,448L983.261,454.167C991.649,460.333,1008.426,472.667,1016.815,485C1025.203,497.333,1025.203,509.667,1025.203,519.333C1025.203,529,1025.203,536,1025.203,539.5L1025.203,543&quot; id=&quot;mermaid-0-L_V_OBJ_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_V_OBJ_0&quot; data-points=&quot;W3sieCI6OTc0Ljg3MjAxODkxNDQ3MzYsInkiOjQ0OH0seyJ4IjoxMDI1LjIwMzEyNSwieSI6NDg1fSx7IngiOjEwMjUuMjAzMTI1LCJ5Ijo1MjJ9LHsieCI6MTAyNS4yMDMxMjUsInkiOjU0N31d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M921.82,448L921.82,454.167C921.82,460.333,921.82,472.667,921.82,485C921.82,497.333,921.82,509.667,877.675,522.917C833.53,536.168,745.24,550.336,701.095,557.421L656.949,564.505&quot; id=&quot;mermaid-0-L_V_VDB_0&quot; class=&quot;edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_V_VDB_0&quot; data-points=&quot;W3sieCI6OTIxLjgyMDMxMjUsInkiOjQ0OH0seyJ4Ijo5MjEuODIwMzEyNSwieSI6NDg1fSx7IngiOjkyMS44MjAzMTI1LCJ5Ijo1MjJ9LHsieCI6NjUzLCJ5Ijo1NjUuMTM4NDc0Nzk4NzIyOH1d&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M845.564,448L833.507,454.167C821.449,460.333,797.334,472.667,785.276,485C773.219,497.333,773.219,509.667,695.512,524.119C617.805,538.571,462.391,555.143,384.684,563.429L306.977,571.714&quot; id=&quot;mermaid-0-L_V_MON_0&quot; class=&quot;edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_V_MON_0&quot; data-points=&quot;W3sieCI6ODQ1LjU2NDI0NzUzMjg5NDgsInkiOjQ0OH0seyJ4Ijo3NzMuMjE4NzUsInkiOjQ4NX0seyJ4Ijo3NzMuMjE4NzUsInkiOjUyMn0seyJ4IjozMDMsInkiOjU3Mi4xMzgzODcwNDYzODkzfV0=&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M173,625L173,629.167C173,633.333,173,641.667,173,652C173,662.333,173,674.667,173,686.333C173,698,173,709,173,714.5L173,720&quot; id=&quot;mermaid-0-L_MON_SUP_0&quot; class=&quot;edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link&quot; style=&quot;&quot; data-edge=&quot;true&quot; data-et=&quot;edge&quot; data-id=&quot;L_MON_SUP_0&quot; data-points=&quot;W3sieCI6MTczLCJ5Ijo2MjV9LHsieCI6MTczLCJ5Ijo2NTB9LHsieCI6MTczLCJ5Ijo2ODd9LHsieCI6MTczLCJ5Ijo3MjR9XQ==&quot; data-look=&quot;classic&quot; marker-end=&quot;url(#mermaid-0_flowchart-v2-pointEnd)&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabels&quot;&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_CLIENT_CDN_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_CDN_GW_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_GW_V_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_V_OBJ_0&quot; transform=&quot;translate(0, 0)&quot;&gt;&lt;foreignObject width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(921.8203125, 485)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_V_VDB_0&quot; transform=&quot;translate(-83.3828125, -12)&quot;&gt;&lt;foreignObject width=&quot;166.765625&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Kontext-Abruf, Klartext&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(773.21875, 485)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_V_MON_0&quot; transform=&quot;translate(-45.21875, -12)&quot;&gt;&lt;foreignObject width=&quot;90.4375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Traces, Logs&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;edgeLabel&quot; transform=&quot;translate(173, 687)&quot;&gt;&lt;g class=&quot;label&quot; data-id=&quot;L_MON_SUP_0&quot; transform=&quot;translate(-29.0078125, -12)&quot;&gt;&lt;foreignObject width=&quot;58.015625&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; class=&quot;labelBkg&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;edgeLabel&quot;&gt;&lt;p&gt;Einsicht&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;nodes&quot;&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-GW-0&quot; data-look=&quot;classic&quot; transform=&quot;translate(921.8203125, 293)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-98.140625&quot; y=&quot;-27&quot; width=&quot;196.28125&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-68.140625, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;136.28125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Inference Gateway&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-V-1&quot; data-look=&quot;classic&quot; transform=&quot;translate(921.8203125, 409)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;vLLM-Pods, Apertus 1.5 70B&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-OBJ-2&quot; data-look=&quot;classic&quot; transform=&quot;translate(1025.203125, 586)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Objektspeicher, Modellgewichte&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-VDB-3&quot; data-look=&quot;classic&quot; transform=&quot;translate(523, 586)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Vektordatenbank, Managed SaaS&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-CDN-4&quot; data-look=&quot;classic&quot; transform=&quot;translate(173, 164)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-81.765625&quot; y=&quot;-27&quot; width=&quot;163.53125&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-51.765625, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;103.53125&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;CDN und WAF&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-MON-5&quot; data-look=&quot;classic&quot; transform=&quot;translate(173, 586)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Monitoring-SaaS, Traces mit Prompt-Inhalt&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-SUP-6&quot; data-look=&quot;classic&quot; transform=&quot;translate(173, 763)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-130&quot; y=&quot;-39&quot; width=&quot;260&quot; height=&quot;78&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-100, -24)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;200&quot; height=&quot;48&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table;white-space:break-spaces;line-height:1.5;max-width:200px;text-align:center;width:200px&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Support-Zugriff aus Drittstaat&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;g class=&quot;node default&quot; id=&quot;mermaid-0-flowchart-CLIENT-7&quot; data-look=&quot;classic&quot; transform=&quot;translate(173, 35)&quot;&gt;&lt;rect class=&quot;basic label-container&quot; style=&quot;&quot; x=&quot;-51.3671875&quot; y=&quot;-27&quot; width=&quot;102.734375&quot; height=&quot;54&quot;&gt;&lt;/rect&gt;&lt;g class=&quot;label&quot; style=&quot;&quot; transform=&quot;translate(-21.3671875, -12)&quot;&gt;&lt;rect&gt;&lt;/rect&gt;&lt;foreignObject width=&quot;42.734375&quot; height=&quot;24&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot; style=&quot;display:table-cell;white-space:nowrap;line-height:1.5;max-width:200px;text-align:center&quot;&gt;&lt;span class=&quot;nodeLabel&quot;&gt;&lt;p&gt;Client&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;defs&gt;&lt;filter id=&quot;mermaid-0-drop-shadow&quot; height=&quot;130%&quot; width=&quot;130%&quot;&gt;&lt;feDropShadow dx=&quot;4&quot; dy=&quot;4&quot; stdDeviation=&quot;0&quot; flood-opacity=&quot;0.06&quot; flood-color=&quot;#000000&quot;&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;defs&gt;&lt;filter id=&quot;mermaid-0-drop-shadow-small&quot; height=&quot;150%&quot; width=&quot;150%&quot;&gt;&lt;feDropShadow dx=&quot;2&quot; dy=&quot;2&quot; stdDeviation=&quot;0&quot; flood-opacity=&quot;0.06&quot; flood-color=&quot;#000000&quot;&gt;&lt;/feDropShadow&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;linearGradient id=&quot;mermaid-0-gradient&quot; gradientUnits=&quot;objectBoundingBox&quot; x1=&quot;0%&quot; y1=&quot;0%&quot; x2=&quot;100%&quot; y2=&quot;0%&quot;&gt;&lt;stop offset=&quot;0%&quot; stop-color=&quot;#363739&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;&lt;stop offset=&quot;100%&quot; stop-color=&quot;hsl(220, 0%, 17.6470588235%)&quot; stop-opacity=&quot;1&quot;&gt;&lt;/stop&gt;&lt;/linearGradient&gt;&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Monitoring-SaaS ist die häufigste Bruchstelle.&lt;/strong&gt; Ein OpenTelemetry-Trace um einen LLM-Aufruf transportiert Attribute wie &lt;code&gt;gen_ai.input.messages&lt;/code&gt; und &lt;code&gt;gen_ai.output.messages&lt;/code&gt;, also den vollständigen Gesprächsinhalt. Wer den Collector auf einen US-Anbieter zeigen lässt, exportiert damit den Prompt, nicht nur Latenzen. Das ist kein Konfigurationsfehler, sondern das Default-Verhalten gängiger Instrumentierungen. Welche datenschutzrechtlichen Folgen daran hängen, steht in &lt;a href=&quot;https://devs-group.ch/blog/revdsg-konforme-ki-architektur/&quot;&gt;revDSG-konforme KI-Architektur&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Die Vektordatenbank speichert den Klartext gleich mit.&lt;/strong&gt; Jede RAG-Implementierung legt den Quelltext-Chunk als Payload neben den Vektor, sonst kann sie ihn nicht in den Prompt setzen. Eine Managed-Vektordatenbank mit Region Irland ist damit eine Kopie Ihres Dokumentenbestands ausserhalb der Schweiz.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Der Support-Zugriff steht im Vertrag, nicht im Architekturdiagramm.&lt;/strong&gt; Ob ein Anbieter Second-Level-Support aus einem Drittstaat leistet und ob dieses Team Leseberechtigung auf Produktivsysteme hat, ist eine Frage an den Einkauf. Sie wird selten gestellt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Das CDN sieht jede Anfrage, bevor sie den Origin erreicht.&lt;/strong&gt; Wer einen US-CDN vor den Inference-Endpunkt setzt, hat den Prompt im Klartext bei einem Anbieter unter CLOUD-Act-Zugriff.&lt;/p&gt;
&lt;p&gt;Dazu die leiseren: der Embedding-Dienst, oft ein anderer Anbieter als der LLM-Dienst, und der Objektspeicher für Modellgewichte, dessen Bucket-Region niemand mehr prüft. Wer diese Punkte auditiert, hat mehr für die Souveränität getan als mit der Wahl des Modells. Dieselbe Disziplin brauchte die verteilte Plattform, die wir für &lt;a href=&quot;https://devs-group.ch/projekte/onocoy/&quot;&gt;onocoy&lt;/a&gt; gebaut haben.&lt;/p&gt;
&lt;h2 id=&quot;wann-souveräne-inferenz-die-falsche-antwort-ist&quot;&gt;Wann souveräne Inferenz die falsche Antwort ist&lt;/h2&gt;
&lt;p&gt;Für die Mehrheit der Anwendungsfälle, die wir sehen, ist eigener GPU-Betrieb die teurere und langsamere Lösung. Unterhalb von etwa einer Million Anfragen pro Monat zahlen Sie für Souveränität einen Aufschlag, ohne technischen Gegenwert.&lt;/p&gt;
&lt;p&gt;Ein API-Anbieter mit sauberem Auftragsbearbeitungsvertrag, dokumentiertem Datenstandort und einer Zusicherung zum Modelltraining deckt die revDSG-Anforderungen für Geschäftsdaten in aller Regel ab. Infomaniak etwa verarbeitet in Genf und Zürich. Das ist in Tagen produktiv, nicht in Wochen.&lt;/p&gt;
&lt;p&gt;Eigenbetrieb lohnt sich, wenn eines davon zutrifft: Das Volumen liegt dauerhaft über dem Kipppunkt. Die Daten fallen unter ein Berufsgeheimnis nach Art. 321 StGB. Oder Sie brauchen eine gepinnte Modellversion, weil eine Validierung daran hängt.&lt;/p&gt;
&lt;p&gt;Wovon wir abraten: von der Zwischenlösung mit eigenem Cluster, aber Monitoring, Vektordatenbank und CDN beim US-Anbieter. Das kostet den vollen Betriebsaufwand und liefert die Souveränität trotzdem nicht.&lt;/p&gt;
&lt;h2 id=&quot;die-entscheidungsmatrix&quot;&gt;Die Entscheidungsmatrix&lt;/h2&gt;















































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Kriterium&lt;/th&gt;&lt;th&gt;API-Bezug&lt;/th&gt;&lt;th&gt;Dedizierte GPU in der Schweiz&lt;/th&gt;&lt;th&gt;On-prem oder Colocation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Anfragevolumen&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;bis rund 1 Mio. pro Monat&lt;/td&gt;&lt;td&gt;ab rund 3 Mio. pro Monat, planbar&lt;/td&gt;&lt;td&gt;dauerhaft hoch, über 3 Jahre gerechnet&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Datenklasse&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Geschäftsdaten ohne besondere Kategorien&lt;/td&gt;&lt;td&gt;besonders schützenswerte Personendaten (Art. 5 lit. c revDSG)&lt;/td&gt;&lt;td&gt;Berufsgeheimnis (Art. 321 StGB), Daten mit Ausfuhrverbot&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Modellkontrolle&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Anbieter bestimmt Version und Deprecation&lt;/td&gt;&lt;td&gt;Sie pinnen Version und Quantisierung&lt;/td&gt;&lt;td&gt;zusätzlich Treiber und Kernel&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Latenzsteuerung&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;keine, Batching liegt beim Anbieter&lt;/td&gt;&lt;td&gt;Batchgrösse, KV-Cache, Präfix-Routing&lt;/td&gt;&lt;td&gt;zusätzlich der Netzwerkpfad&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Betriebsaufwand&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;API-Schlüssel und Rechnung&lt;/td&gt;&lt;td&gt;Cluster, DRA-Treiber, vLLM, Gateway, Kapazitätsplanung&lt;/td&gt;&lt;td&gt;zusätzlich Hardware-Lifecycle&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Zeit bis produktiv&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Stunden&lt;/td&gt;&lt;td&gt;Tage bis Wochen&lt;/td&gt;&lt;td&gt;Monate&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Die Zeilen sind nicht gleich gewichtet. Fast immer entscheidet die zweite: Welche Datenklasse fliesst durch den Prompt. Der Rest ist danach eine Kostenfrage.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;welche-schweizer-alternativen-zu-chatgpt-gibt-es&quot;&gt;Welche Schweizer Alternativen zu ChatGPT gibt es?&lt;/h3&gt;
&lt;p&gt;Apertus ist das offene Schweizer Sprachmodell von EPFL, ETH Zürich und CSCS, in Version 1.5 seit dem 24. Juli 2026 verfügbar. Beziehen lässt es sich über Infomaniak AI Services, die Swisscom Swiss AI Platform, Phoenix Technologies oder von Hugging Face zum Eigenbetrieb. Daneben betreiben Schweizer Anbieter Endpunkte für offene Modelle von Mistral, Qwen und Google.&lt;/p&gt;
&lt;h3 id=&quot;was-kostet-ein-selbst-gehostetes-llm-im-vergleich-zur-api&quot;&gt;Was kostet ein selbst gehostetes LLM im Vergleich zur API?&lt;/h3&gt;
&lt;p&gt;Nach unserer Modellrechnung vom 19. August 2026 kosten vier RTX Pro 6000 bei Exoscale im Dauerbetrieb CHF 6’200 pro Monat. Dieselbe Last über die Infomaniak-API kostet bei 3’000 Input- und 500 Output-Tokens CHF 0.00335 pro Anfrage. Der rechnerische Kipppunkt liegt bei 1.85 Millionen Anfragen im Monat, mit Reserve für Spitzen und Ausfälle eher bei drei bis vier Millionen.&lt;/p&gt;
&lt;h3 id=&quot;welche-hardware-brauche-ich-für-ein-eigenes-llm&quot;&gt;Welche Hardware brauche ich für ein eigenes LLM?&lt;/h3&gt;
&lt;p&gt;Für Apertus-v1.5-70B nennt die Modellkarte vier GPUs bei vollem Kontextfenster: 72 Milliarden Parameter in BF16 sind 144 GB reine Gewichte, dazu kommt der KV-Cache. Das 8B-Modell läuft auf einer Karte mit 48 GB komfortabel. Quantisierung senkt den Bedarf, kostet aber Qualität und muss für den konkreten Anwendungsfall gemessen werden.&lt;/p&gt;
&lt;h3 id=&quot;schützt-schweizer-hosting-vor-dem-us-cloud-act&quot;&gt;Schützt Schweizer Hosting vor dem US CLOUD Act?&lt;/h3&gt;
&lt;p&gt;Nur, wenn der Betreiber nicht US-Recht untersteht. 18 U.S.C. § 2713 verpflichtet US-Anbieter zur Herausgabe von Daten unabhängig vom Speicherort. Entscheidend ist also die Gesellschaftsstruktur des Anbieters, nicht die Adresse des Rechenzentrums. Ein Rechenzentrum in Zürich, betrieben von einer Schweizer Tochter eines US-Konzerns, fällt weiterhin unter den Zugriff.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Inferenz-Architektur besprechen.&lt;/strong&gt; 30 Minuten mit einem unserer Engineers über Ihren konkreten Fall: welches Modell, welches Volumen, wo die Daten liegen und wo die Peripherie die Jurisdiktion verlässt. Kein Verkaufsgespräch, keine Vorbereitung nötig.&lt;/p&gt;
&lt;p&gt;Einen &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin gibt es hier&lt;/a&gt;. Wer lieber erst schreibt, erreicht uns über &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt&lt;/a&gt;. Woran wir arbeiten, steht unter &lt;a href=&quot;https://devs-group.ch/leistungen/kuenstliche-intelligenz/&quot;&gt;Künstlicher Intelligenz&lt;/a&gt; und &lt;a href=&quot;https://devs-group.ch/leistungen/kubernetes-and-infrastruktur/&quot;&gt;Kubernetes und Infrastruktur&lt;/a&gt;.&lt;/p&gt;</content:encoded><category>Künstliche Intelligenz</category><author>Robert Pupel</author></item><item><title>MCP-Server in Go produktiv betreiben</title><link>https://devs-group.ch/blog/mcp-server-in-go-produktiv-betreiben/</link><guid isPermaLink="true">https://devs-group.ch/blog/mcp-server-in-go-produktiv-betreiben/</guid><description>Was die MCP-Spezifikation vom Juli 2026 ändert: Stateless Core, OAuth statt geteiltem Token, und die Tool-Design-Fehler, die wir am häufigsten sehen.</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ein MCP-Server nach der Spezifikation vom 28. Juli 2026 hält keinen Sitzungszustand. Die Revision entfernt den &lt;code&gt;initialize&lt;/code&gt;-Handshake und den &lt;code&gt;Mcp-Session-Id&lt;/code&gt;-Header: Jede Anfrage trägt Protokollversion und Client-Identität selbst, in &lt;code&gt;_meta&lt;/code&gt;. Für einen produktiven Server in Go heisst das drei Dinge: Round-Robin hinter einem gewöhnlichen Load Balancer, Zustand in server-vergebenen Handles, Identität in einem OAuth-Token pro Aufruf.&lt;/p&gt;
&lt;p&gt;Primärquelle ist die &lt;a href=&quot;https://modelcontextprotocol.io/specification/2026-07-28/changelog&quot;&gt;Änderungsliste der Revision 2026-07-28&lt;/a&gt;. Alle Codebeispiele unten sind gegen das offizielle &lt;a href=&quot;https://github.com/modelcontextprotocol/go-sdk/releases&quot;&gt;Go-SDK v1.7.0&lt;/a&gt; übersetzt, das am selben Tag stabil erschienen ist.&lt;/p&gt;
&lt;h2 id=&quot;was-die-spezifikation-vom-28-juli-2026-ändert&quot;&gt;Was die Spezifikation vom 28. Juli 2026 ändert&lt;/h2&gt;
&lt;p&gt;Die Revision 2026-07-28 macht MCP von einem bidirektionalen, zustandsbehafteten Protokoll zu einem Request/Response-Protokoll. Neun Punkte führt die Änderungsliste als „Major changes”, und sechs davon zwingen zu Arbeit an einem bestehenden Server.&lt;/p&gt;








































&lt;div class=&quot;scroll-x scroll-x--table&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabelle, seitlich scrollbar&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Vorher (2025-11-25)&lt;/th&gt;&lt;th&gt;Nachher (2026-07-28)&lt;/th&gt;&lt;th&gt;Was Sie anpassen müssen&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;initialize&lt;/code&gt;-Handshake, &lt;code&gt;Mcp-Session-Id&lt;/code&gt;-Header&lt;/td&gt;&lt;td&gt;Jede Anfrage selbstbeschreibend über &lt;code&gt;_meta&lt;/code&gt;; neu Pflicht-RPC &lt;code&gt;server/discover&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Sticky Sessions am Load Balancer abschalten, prozesslokalen Sitzungsspeicher entfernen&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Server-initiierte Requests (&lt;code&gt;roots/list&lt;/code&gt;, &lt;code&gt;sampling/createMessage&lt;/code&gt;, &lt;code&gt;elicitation/create&lt;/code&gt;) über gehaltenen Stream&lt;/td&gt;&lt;td&gt;Multi Round-Trip Requests: Server antwortet mit &lt;code&gt;resultType: &amp;quot;input_required&amp;quot;&lt;/code&gt;, Client wiederholt mit &lt;code&gt;inputResponses&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Zwischenzustand in &lt;code&gt;requestState&lt;/code&gt; kodieren statt im Prozess halten&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Routing durch Inspektion des JSON-Bodys&lt;/td&gt;&lt;td&gt;Pflicht-Header &lt;code&gt;Mcp-Method&lt;/code&gt; auf jedem Streamable-HTTP-POST, &lt;code&gt;Mcp-Name&lt;/code&gt; zusätzlich bei &lt;code&gt;tools/call&lt;/code&gt;, &lt;code&gt;resources/read&lt;/code&gt; und &lt;code&gt;prompts/get&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Gateway-Regeln auf Header umstellen, sonst &lt;code&gt;HeaderMismatchError&lt;/code&gt; (&lt;code&gt;-32020&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Listenergebnisse ohne Cache-Hinweis&lt;/td&gt;&lt;td&gt;&lt;code&gt;ttlMs&lt;/code&gt; und &lt;code&gt;cacheScope&lt;/code&gt; sind auf &lt;code&gt;tools/list&lt;/code&gt;, &lt;code&gt;prompts/list&lt;/code&gt;, &lt;code&gt;resources/list&lt;/code&gt;, &lt;code&gt;resources/read&lt;/code&gt; und &lt;code&gt;resources/templates/list&lt;/code&gt; Pflichtfelder&lt;/td&gt;&lt;td&gt;Werte bewusst setzen; bei nutzerabhängigen Toollisten &lt;code&gt;cacheScope: &amp;quot;private&amp;quot;&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Roots, Sampling und Logging aktiv&lt;/td&gt;&lt;td&gt;Alle drei deprecated (SEP-2577), weiterhin funktionsfähig&lt;/td&gt;&lt;td&gt;Nach &lt;code&gt;stderr&lt;/code&gt; oder über OpenTelemetry loggen, Sampling durch direkten Aufruf der Provider-API ersetzen&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Dynamic Client Registration (RFC 7591) als Standardweg&lt;/td&gt;&lt;td&gt;Deprecated zugunsten von Client ID Metadata Documents&lt;/td&gt;&lt;td&gt;CIMD unterstützen, DCR nur noch als Rückfallebene betreiben&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Für die Planung zählt der Governance-Teil: Die Spezifikation hat erstmals eine &lt;a href=&quot;https://modelcontextprotocol.io/community/feature-lifecycle&quot;&gt;Feature-Lifecycle- und Deprecation-Policy&lt;/a&gt; mit einem Mindestfenster von zwölf Monaten. Wer Roots, Sampling oder Logging im Einsatz hat, muss nicht diese Woche umbauen. Wer neu baut, fasst sie gar nicht erst an.&lt;/p&gt;
&lt;p&gt;Ein verbreitetes Missverständnis betrifft Tasks: Sie sind nicht in den Kern gewandert, sondern aus dem experimentellen Kern heraus in die Erweiterung &lt;code&gt;io.modelcontextprotocol/tasks&lt;/code&gt;. MCP Apps (&lt;code&gt;io.modelcontextprotocol/ui&lt;/code&gt;) und Enterprise-Managed Authorization stehen ebenfalls ausserhalb des Kerns, waren dort aber nie: Beide sind von Beginn weg Erweiterungen. Erweiterungen sind opt-in und werden über das Feld &lt;code&gt;extensions&lt;/code&gt; ausgehandelt.&lt;/p&gt;
&lt;h2 id=&quot;warum-ein-mcp-server-in-go-gebaut-wird&quot;&gt;Warum ein MCP-Server in Go gebaut wird&lt;/h2&gt;
&lt;p&gt;Go ist die Sprache, in der die Agenten-Infrastruktur ohnehin schon geschrieben ist: Kubernetes-Controller, Inference-Gateways, agentgateway, kagent. Warum wir kritische Backends generell in Go bauen, steht in einem &lt;a href=&quot;https://devs-group.ch/blog/warum-go-fuer-kritische-backends/&quot;&gt;eigenen Beitrag über Go für langlebige Systeme&lt;/a&gt;, und der Rest dieses Texts wiederholt das nicht.&lt;/p&gt;
&lt;p&gt;Ein Punkt kommt für MCP neu dazu. Ein Tool-Server ist ein kurzlebiger Prozess, der oft neu startet, in vielen Instanzen läuft und gelegentlich pro Mandant separat deployt wird. Ein statisches Binary in einem &lt;code&gt;FROM scratch&lt;/code&gt;-Image ist dafür eine andere Ausgangslage als ein Interpreter mit Paketbaum.&lt;/p&gt;
&lt;p&gt;Das Go-SDK verlangt in seiner &lt;code&gt;go.mod&lt;/code&gt; mindestens Go 1.25.0. Als Unterbau empfiehlt sich Go 1.26 mit dem Patch-Stand 1.26.6 vom &lt;a href=&quot;https://go.dev/doc/devel/release&quot;&gt;13. August 2026&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;zustandslos-heisst-dass-der-zustand-einen-namen-bekommt&quot;&gt;Zustandslos heisst, dass der Zustand einen Namen bekommt&lt;/h2&gt;
&lt;p&gt;Ein produktiver MCP-Server hält keinen Sitzungszustand im Prozess. Zustand gehört in einen externen Speicher und wird über ein server-vergebenes Handle adressiert, das als gewöhnliches Tool-Argument hin und zurück läuft. So beschreibt es SEP-2567.&lt;/p&gt;
&lt;p&gt;Der Gewinn: Der zweite Aufruf darf auf einer anderen Instanz landen, ein Deployment mitten in einer Agenten-Sitzung zerstört nichts, und der Load Balancer braucht keine Klebrigkeit. Im Go-SDK ist das ein Feld, &lt;code&gt;StreamableHTTPOptions.Stateless&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Die vier Beispiele in diesem Beitrag sind vollständige Programme: kopieren, &lt;code&gt;go get github.com/modelcontextprotocol/go-sdk@v1.7.0&lt;/code&gt;, &lt;code&gt;go run .&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Vollständiges Programm. go get github.com/modelcontextprotocol/go-sdk@v1.7.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;encoding/json&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sync&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;github.com/modelcontextprotocol/go-sdk/mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Store ist der externe Zustandsspeicher. Produktiv: Redis, Valkey, Postgres.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Nur nicht der Prozess, denn der nächste Aufruf landet auf einer anderen Instanz.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Store&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;	Put&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;handle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ttl&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;	Get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;handle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// memStore ist die Wegwerf-Variante, damit dieses Beispiel ohne Redis läuft.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; memStore&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{ m &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sync&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;memStore&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Put&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; time&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	b, err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; json.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Marshal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(v)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	s.m.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Store&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(h, b)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;memStore&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;v&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	b, ok &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s.m.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Load&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(h)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ok {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Handle &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%q&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; unbekannt oder abgelaufen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, h)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; json.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Unmarshal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(b.([]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), v)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; exportState&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	UserID &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;   `json:&amp;quot;user_id&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Zeilen []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;zeilen&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; startIn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Mandant &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;mandant&amp;quot; jsonschema:&amp;quot;Mandantenkürzel, drei Grossbuchstaben&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; startOut&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Handle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;handle&amp;quot; jsonschema:&amp;quot;Undurchsichtiges Handle, unverändert an export_seite zurückgeben&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Gesamt &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    `json:&amp;quot;gesamt&amp;quot; jsonschema:&amp;quot;Anzahl Zeilen im Export&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; seiteIn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Handle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;handle&amp;quot; jsonschema:&amp;quot;Handle aus export_starten&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; addExport&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Server&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;store&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Store&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AddTool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(s, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Name:        &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;export_starten&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Description: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Startet einen Buchungsexport und liefert ein Handle. Ruft selbst keine Daten ab.&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; startIn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;startOut&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		zeilen &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;B-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;B-2&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;B-3&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		handle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Sprintf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;exp_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, in.Mandant, time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Now&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;UnixNano&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		st &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; exportState&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{UserID: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;userID&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(req), Zeilen: zeilen}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; store.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Put&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, handle, st, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;time.Minute); err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;startOut&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{}, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Handle konnte nicht abgelegt werden: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;startOut&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Handle: handle, Gesamt: &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(zeilen)}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AddTool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(s, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Name:        &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;export_seite&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Description: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Liefert die Zeilen eines mit export_starten begonnenen Exports.&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; seiteIn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; st &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;exportState&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; store.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, in.Handle, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;st); err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;, bitte export_starten erneut aufrufen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;		// Das Handle gehört dem Aufrufer, oder es wird nicht bedient.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; st.UserID &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; userID&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(req) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Handle &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%q&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; gehört zu einer anderen Identität&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, in.Handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		b, _ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; json.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Marshal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(st.Zeilen)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Content: []&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TextContent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Text: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(b)}}}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// userID liefert die Identität aus dem Bearer Token, siehe Abschnitt Authentifizierung.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; userID&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; req.Extra &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; req.Extra.TokenInfo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; req.Extra.TokenInfo.UserID&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	store &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;memStore&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{} &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// eine Instanz, ausserhalb des Request-Pfads&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	handler &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewStreamableHTTPHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Server&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		s &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewServer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Implementation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;erp-bridge&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Version: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;1.4.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;		addExport&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(s, store)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;StreamableHTTPOptions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;		// Kein Mcp-Session-Id, keine gehaltene Verbindung, kein Prozessgedächtnis.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Stateless:    &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		JSONResponse: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Fatal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Server&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Addr:              &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;:8080&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Handler:           handler,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		ReadHeaderTimeout: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; time.Second,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das Handle bekommt eine TTL und einen Eigentümer. Ohne TTL wächst der Speicher unbegrenzt, ohne die Eigentümerprüfung in &lt;code&gt;export_seite&lt;/code&gt; kann ein zweiter Nutzer ein fremdes Handle einlösen. Beides sind zwei Zeilen, und beide fehlen in den meisten Beispielprojekten.&lt;/p&gt;
&lt;h2 id=&quot;authentifizierung-wie-ein-tool-aufruf-an-eine-benutzeridentität-gebunden-wird&quot;&gt;Authentifizierung: wie ein Tool-Aufruf an eine Benutzeridentität gebunden wird&lt;/h2&gt;
&lt;p&gt;Ein Tool-Aufruf wird über ein OAuth-2.1-Access-Token an eine Identität gebunden, dessen &lt;code&gt;aud&lt;/code&gt;-Claim die kanonische URI genau dieses MCP-Servers enthält. Die Spezifikation ist hier ungewöhnlich deutlich: MCP-Server müssen prüfen, dass ein Token für sie als Zielgruppe ausgestellt wurde, und sie dürfen keine anderen Tokens akzeptieren oder weiterreichen.&lt;/p&gt;
&lt;p&gt;Das ist der Abschnitt, den die Beispielprojekte auslassen. Ein Prototyp läuft mit einem geteilten Bearer-Token in einer Umgebungsvariable, und alle Tool-Aufrufe erreichen die Datenbank unter demselben Dienstkonto. Im Log ist dann nicht mehr feststellbar, welcher Mensch was ausgelöst hat.&lt;/p&gt;
&lt;p&gt;Dazu kommt eine Pflicht, die nicht neu ist, aber regelmässig fehlt: Der Server muss OAuth 2.0 Protected Resource Metadata nach &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc9728&quot;&gt;RFC 9728&lt;/a&gt; ausliefern, sonst findet kein Client den zuständigen Authorization Server. Das steht so schon in der Revision 2025-06-18.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Vollständiges Programm. go get github.com/modelcontextprotocol/go-sdk@v1.7.0 github.com/golang-jwt/jwt/v5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;slices&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;strings&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;github.com/golang-jwt/jwt/v5&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;github.com/modelcontextprotocol/go-sdk/auth&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;github.com/modelcontextprotocol/go-sdk/mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;github.com/modelcontextprotocol/go-sdk/oauthex&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;	// canonicalURI ist der Resource Indicator nach RFC 8707. Genau dieser Wert&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;	// muss in der aud-Claim stehen, sonst war das Token für einen anderen Dienst.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;	canonicalURI&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;https://mcp.example.ch/mcp&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;	issuer&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;       =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;https://login.example.ch/realms/erp&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// claims ergänzt die Standard-Claims um scope, wie es Keycloak und Entra ID liefern.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; claims&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Scope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;scope&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;	jwt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;RegisteredClaims&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; verifyToken&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;parser&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;jwt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Parser&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;keyFunc&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; jwt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Keyfunc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;auth&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TokenVerifier&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;raw&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;auth&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TokenInfo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;claims&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; _, err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; parser.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ParseWithClaims&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(raw, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c, keyFunc); err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%v&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, auth.ErrInvalidToken, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c.Issuer &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; issuer {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: unerwarteter Aussteller &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%q&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, auth.ErrInvalidToken, c.Issuer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;slices.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Contains&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(c.Audience, canonicalURI) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: Token nicht für &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; ausgestellt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, auth.ErrInvalidToken, canonicalURI)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c.Subject &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: kein sub-Claim, keine Identität&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, auth.ErrInvalidToken)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;auth&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TokenInfo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			UserID:     c.Subject,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			Scopes:     strings.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Fields&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(c.Scope),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			Expiration: c.ExpiresAt.Time,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; buchungIn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Konto   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;konto&amp;quot; jsonschema:&amp;quot;Kontonummer nach Schweizer KMU-Kontenrahmen&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Rappen  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    `json:&amp;quot;betrag_rappen&amp;quot; jsonschema:&amp;quot;Betrag in Rappen, ganzzahlig&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	IdemKey &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;idempotenz_schluessel&amp;quot; jsonschema:&amp;quot;Vom Aufrufer erzeugte UUID. Derselbe Schlüssel bucht nie zweimal.&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; buchen&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; buchungIn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	tok &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; req.Extra.TokenInfo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tok &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Aufruf ohne Identität&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;slices.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Contains&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tok.Scopes, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;buchhaltung:schreiben&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Scope buchhaltung:schreiben fehlt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;	// Ab hier läuft jede Abfrage unter tok.UserID, nicht unter einem Dienstkonto.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Printf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;buchung user=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; konto=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; rappen=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; idem=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, tok.UserID, in.Konto, in.Rappen, in.IdemKey)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Content: []&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TextContent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Text: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;gebucht&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}}}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	server &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewServer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Implementation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;erp-bridge&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Version: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;1.4.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AddTool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(server, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Name:        &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;buchung_erfassen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Description: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Erfasst eine Buchung. Schreibend. Derselbe Idempotenz-Schlüssel erzeugt nie eine zweite Buchung.&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Annotations: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ToolAnnotations&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{IdempotentHint: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}, buchen)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mcpHandler &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewStreamableHTTPHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Server&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; server },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;StreamableHTTPOptions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Stateless: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; keyFunc &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;jwt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Keyfunc&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; // aus dem JWKS des Ausstellers, gecached&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	requireToken &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; auth.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;RequireBearerToken&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;		verifyToken&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(jwt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewParser&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(jwt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;WithValidMethods&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;([]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})), keyFunc),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;auth&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;RequireBearerTokenOptions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			Scopes:              []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;buchhaltung:lesen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			ResourceMetadataURL: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;https://mcp.example.ch/.well-known/oauth-protected-resource&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mux &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; http.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewServeMux&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mux.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Handle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;/mcp&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;requireToken&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(mcpHandler))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;	// RFC 9728. Die Spezifikation macht dieses Dokument zur Pflicht: ohne es&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;	// findet kein Client den zuständigen Authorization Server.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mux.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Handle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;/.well-known/oauth-protected-resource&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, auth.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ProtectedResourceMetadataHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;oauthex&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ProtectedResourceMetadata&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			Resource:             canonicalURI,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			AuthorizationServers: []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{issuer},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			ScopesSupported:      []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;buchhaltung:lesen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;buchhaltung:schreiben&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Fatal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(http.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;:8080&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, mux))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der entscheidende Punkt liegt in einer einzigen Zeile: &lt;code&gt;tok.UserID&lt;/code&gt; stammt aus dem &lt;code&gt;sub&lt;/code&gt;-Claim und steht ab da jedem Tool-Handler zur Verfügung. Der Agent erbt damit exakt die Rechte des angemeldeten Menschen, nicht die eines Dienstkontos.&lt;/p&gt;
&lt;p&gt;In der Schweiz ist das nicht bloss guter Stil. Artikel 4 der &lt;a href=&quot;https://www.fedlex.admin.ch/eli/cc/2022/568/de&quot;&gt;Datenschutzverordnung (DSV, SR 235.11)&lt;/a&gt;, der Ausführungsverordnung zum revDSG, verpflichtet private Verantwortliche zur Protokollierung, sobald sie besonders schützenswerte Personendaten in grossem Umfang automatisiert bearbeiten und die präventiven Massnahmen den Datenschutz nicht gewährleisten können. Absatz 4 sagt, was drinstehen muss: Aufschluss über „die Identität der Person, die die Bearbeitung vorgenommen hat, die Art, das Datum und die Uhrzeit der Bearbeitung”.&lt;/p&gt;
&lt;p&gt;Absatz 5 setzt die Aufbewahrung auf mindestens ein Jahr, getrennt vom bearbeitenden System. Ein geteiltes Dienstkonto erfüllt das technisch nicht. Was das revDSG darüber hinaus von einem Agentensystem verlangt, Norm für Norm, steht in &lt;a href=&quot;https://devs-group.ch/blog/revdsg-konforme-ki-architektur/&quot;&gt;revDSG-konforme KI-Architektur&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Genau hier bleiben die meisten Prototypen stehen, und meistens erst dann, wenn das Sicherheitsreview kommt. Wenn Sie an dieser Stelle stehen: Wir schauen uns Ihre Kette vom Identity Provider bis zum Tool-Handler einmal gemeinsam an und sagen, wo sie reisst. &lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin buchen&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;tool-design-die-fehler-die-wir-am-häufigsten-sehen&quot;&gt;Tool-Design: die Fehler, die wir am häufigsten sehen&lt;/h2&gt;
&lt;p&gt;Die drei häufigsten Fehler im Tool-Design sind zu viele Werkzeuge, unscharfe Beschreibungen und fehlende Idempotenz. Alle drei zeigen sich erst im Betrieb, als falsch gewählte Werkzeuge und doppelte Buchungen.&lt;/p&gt;
&lt;p&gt;Eine Beschreibung ist der einzige Kontext, den das Modell bei der Auswahl hat. Sie gehört mit Abgrenzung geschrieben: was das Werkzeug tut, was es nicht tut, und welches andere Werkzeug für den Nachbarfall zuständig ist.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Vollständiges Programm, spricht Streamable HTTP auf :8080.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;github.com/modelcontextprotocol/go-sdk/mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; sucheIn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	KundenNr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;kunden_nr&amp;quot; jsonschema:&amp;quot;Kundennummer im Format K-00000, exakt wie in Abacus hinterlegt&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Jahr     &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    `json:&amp;quot;jahr&amp;quot; jsonschema:&amp;quot;Geschäftsjahr, vierstellig, zwischen 2015 und 2030&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; sucheOut&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Treffer  []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `json:&amp;quot;treffer&amp;quot; jsonschema:&amp;quot;Rechnungsnummern, absteigend nach Datum&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Gesamt   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      `json:&amp;quot;gesamt&amp;quot; jsonschema:&amp;quot;Anzahl Treffer insgesamt, auch wenn die Liste begrenzt ist&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	Begrenzt &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;     `json:&amp;quot;begrenzt&amp;quot; jsonschema:&amp;quot;true, wenn auf 50 Einträge gekürzt wurde&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; suchen&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; sucheIn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sucheOut&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; in.Jahr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2015&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; in.Jahr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2030&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;		// Fehlertext als Anweisung, nicht als Statuscode. Das Modell liest ihn.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sucheOut&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{}, fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;			&amp;quot;Jahr &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; liegt ausserhalb des gepflegten Bereichs 2015 bis 2030, bitte mit einem Jahr in diesem Bereich erneut aufrufen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, in.Jahr)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;sucheOut&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Treffer: []&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;RE-2026-0184&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, Gesamt: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	server &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewServer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Implementation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;erp-bridge&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Version: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;1.4.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AddTool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(server, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;rechnungen_suchen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Description: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Sucht Debitorenrechnungen eines Kunden in einem Geschäftsjahr. &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;			&amp;quot;Liefert höchstens 50 Rechnungsnummern und ändert nichts. &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;			&amp;quot;Nicht verwenden, um eine bekannte Rechnungsnummer zu laden, dafür ist rechnung_lesen da.&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Annotations: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ToolAnnotations&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{ReadOnlyHint: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Title: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Rechnungen suchen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}, suchen)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	handler &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewStreamableHTTPHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Server&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; server },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;StreamableHTTPOptions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Stateless: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Fatal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(http.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;:8080&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, handler))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Aufrufen lässt sich das mit &lt;code&gt;curl&lt;/code&gt;. Ein Streamable-HTTP-POST braucht seit 2026-07-28 drei Header und zwei Pflichtfelder in &lt;code&gt;_meta&lt;/code&gt;, sonst antwortet der Server mit &lt;code&gt;-32020&lt;/code&gt; oder &lt;code&gt;-32602&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -sN&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; -X&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; POST&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; http://localhost:8080/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  -H&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  -H&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;Accept: application/json, text/event-stream&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  -H&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;Mcp-Protocol-Version: 2026-07-28&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  -H&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;Mcp-Method: tools/call&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  -H&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;Mcp-Name: rechnungen_suchen&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  -d&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;#39;{&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;id&amp;quot;:1,&amp;quot;method&amp;quot;:&amp;quot;tools/call&amp;quot;,&amp;quot;params&amp;quot;:{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &amp;quot;name&amp;quot;:&amp;quot;rechnungen_suchen&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &amp;quot;arguments&amp;quot;:{&amp;quot;kunden_nr&amp;quot;:&amp;quot;K-00042&amp;quot;,&amp;quot;jahr&amp;quot;:1999},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &amp;quot;_meta&amp;quot;:{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &amp;quot;io.modelcontextprotocol/protocolVersion&amp;quot;:&amp;quot;2026-07-28&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &amp;quot;io.modelcontextprotocol/clientCapabilities&amp;quot;:{},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &amp;quot;io.modelcontextprotocol/clientInfo&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;curl&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;1&amp;quot;}}}}&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# event: message&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# data: {&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;id&amp;quot;:1,&amp;quot;result&amp;quot;:{&amp;quot;content&amp;quot;:[{&amp;quot;type&amp;quot;:&amp;quot;text&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#   &amp;quot;text&amp;quot;:&amp;quot;Jahr 1999 liegt ausserhalb des gepflegten Bereichs 2015 bis 2030,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#           bitte mit einem Jahr in diesem Bereich erneut aufrufen&amp;quot;}],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#   &amp;quot;isError&amp;quot;:true,&amp;quot;resultType&amp;quot;:&amp;quot;complete&amp;quot;}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Fehlerfall kommt als &lt;code&gt;isError: true&lt;/code&gt; mit lesbarem Text zurück, nicht als JSON-RPC-Fehler. Das ist Absicht: Ein Modell kann einen Satz lesen und den Aufruf korrigieren, einen Statuscode kann es nur raten.&lt;/p&gt;
&lt;p&gt;Ein Detail, das beim Nachbauen auffällt: Das Go-SDK setzt auf &lt;code&gt;tools/list&lt;/code&gt; standardmässig &lt;code&gt;cacheScope: &amp;quot;public&amp;quot;&lt;/code&gt;. Wer eine nutzerabhängige Werkzeugliste ausliefert, muss &lt;code&gt;private&lt;/code&gt; selbst setzen, sonst darf ein Gateway die Liste des einen Nutzers dem nächsten zeigen.&lt;/p&gt;
&lt;p&gt;Für schreibende Werkzeuge gilt dieselbe Logik wie für eine Zahlungs-API: Der Aufrufer schickt einen selbst erzeugten Schlüssel mit, der Server reserviert ihn vor der Verarbeitung, und eine Wiederholung liefert dieselbe Antwort ohne zweite Wirkung. Wie wir das bauen, steht in unserem Beitrag über &lt;a href=&quot;https://devs-group.ch/blog/idempotenz-in-zahlungs-apis/&quot;&gt;Idempotenz in Zahlungs-APIs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bei Agenten ist die Wiederholung häufiger als bei Menschen, weil ein Modell nach einem Timeout einfach nochmals aufruft.&lt;/p&gt;
&lt;p&gt;Zur Menge: Zwanzig scharf geschnittene Werkzeuge schlagen sechzig überlappende. Und &lt;code&gt;tools/list&lt;/code&gt; soll seit dieser Revision deterministisch sortiert sein, was die Prompt-Cache-Trefferquote der Clients verbessert.&lt;/p&gt;
&lt;h2 id=&quot;betrieb-timeouts-rate-limits-und-was-in-die-logs-gehört&quot;&gt;Betrieb: Timeouts, Rate Limits und was in die Logs gehört&lt;/h2&gt;
&lt;p&gt;Ein fehlgeschlagener Tool-Aufruf ist rekonstruierbar, wenn eine einzige Logzeile Werkzeugname, Identität, Protokollversion, Dauer und Korrelations-ID enthält. Die Revision 2026-07-28 dokumentiert dafür erstmals die OpenTelemetry-Konventionen für &lt;code&gt;_meta&lt;/code&gt;: &lt;code&gt;traceparent&lt;/code&gt;, &lt;code&gt;tracestate&lt;/code&gt; und &lt;code&gt;baggage&lt;/code&gt; reisen im Protokoll mit.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Vollständiges Programm. Jeder Tool-Aufruf erzeugt genau eine JSON-Logzeile.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log/slog&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;os&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;github.com/modelcontextprotocol/go-sdk/mcp&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// logToolCalls schreibt pro Tool-Aufruf eine Zeile, aus der sich ein&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Fehlschlag ohne Rückfrage rekonstruieren lässt.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; logToolCalls&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;logger&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;slog&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Logger&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Middleware&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;	return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MethodHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MethodHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;method&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Result&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			call, ok &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; req.(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			if&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ok &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; method &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &amp;quot;tools/call&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;				return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; next&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, method, req)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			start &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Now&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			res, err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; next&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, method, req)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			attrs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;				slog.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;tool&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, call.Params.Name),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;				slog.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;protocol_version&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, call.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ProtocolVersion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;				slog.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;dauer&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, time.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Since&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(start)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;			// traceparent reist nach der Spezifikation 2026-07-28 in _meta mit.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tp, ok &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; call.Params.Meta[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;traceparent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;); ok {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;				attrs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; append&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(attrs, slog.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;traceparent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, tp))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; extra &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; call.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;GetExtra&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(); extra &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; extra.TokenInfo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;				attrs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; append&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(attrs, slog.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;user_id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, extra.TokenInfo.UserID))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;				logger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;tool_call fehlgeschlagen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;append&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(attrs, slog.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;fehler&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, err.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()))&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;				logger.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;tool_call&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, attrs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;			}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;			return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; res, err&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	logger &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slog.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;New&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(slog.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewJSONHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(os.Stderr, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	server &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewServer&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Implementation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Name: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;erp-bridge&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, Version: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;1.4.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	server.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AddReceivingMiddleware&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;logToolCalls&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(logger))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;AddTool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(server, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Tool&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Name:        &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;ping&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Description: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Antwortet mit pong. Dient nur der Prüfung der Logkette.&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;		Annotations: &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ToolAnnotations&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{ReadOnlyHint: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	}, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; struct&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{}) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CallToolResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Content: []&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;TextContent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Text: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;pong&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}}}, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	handler &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mcp.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NewStreamableHTTPHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Server&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; server },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;		&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;StreamableHTTPOptions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{Stateless: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	log.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Fatal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(http.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;:8080&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, handler))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zwei Betriebsgrössen setzen Sie besser explizit, bevor der erste Vorfall sie für Sie setzt. Erstens ein Timeout pro Werkzeug, nicht pro Server: Eine Volltextsuche darf zehn Sekunden brauchen, ein Kontostand nicht.&lt;/p&gt;
&lt;p&gt;Zweitens ein Rate Limit pro Identität statt pro IP. Hinter einer IP sitzt ein ganzes Unternehmen, hinter einer Identität ein Agent, der im Fehlerfall in einer Schleife läuft. Was auf die Dashboards gehört und was nicht, steht in &lt;a href=&quot;https://devs-group.ch/blog/observability-die-man-liest/&quot;&gt;Drei Dashboards statt dreissig&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;ist-ein-pod-die-richtige-einheit-für-einen-agenten&quot;&gt;Ist ein Pod die richtige Einheit für einen Agenten?&lt;/h2&gt;
&lt;p&gt;Ein Pod pro Agent ist die naheliegende, aber nicht offensichtlich richtige Antwort. Lin Sun von Solo.io hat die Frage am 14. Juli 2026 im CNCF-Blog unter genau diesem Titel gestellt: &lt;a href=&quot;https://www.cncf.io/blog/2026/07/14/is-a-pod-the-right-deployment-unit-for-an-ai-agent/&quot;&gt;Is a Pod the right deployment unit for an AI agent?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ein eigener Pod bringt Prozessisolation und über den ServiceAccount eine Kubernetes-Identität, kostet aber Grundlast: Ein Agent ist Sekunden aktiv und danach lange leer.&lt;/p&gt;
&lt;p&gt;Für einen MCP-Server, der reine Tool-Ausführung macht, ist das eine gute Nachricht: Er ist ein gewöhnlicher zustandsloser Dienst und braucht diese Diskussion nicht. Sie wird erst relevant, sobald der Server fremden Code ausführt. Dann ist der Pod die falsche Grenze, und es braucht eine echte Sandbox.&lt;/p&gt;
&lt;h2 id=&quot;wovon-wir-abraten&quot;&gt;Wovon wir abraten&lt;/h2&gt;
&lt;p&gt;Bauen Sie keinen MCP-Server, wenn eine gewöhnliche HTTP-API reicht. MCP löst ein Entdeckungsproblem, kein Integrationsproblem: Es beschreibt Werkzeuge so, dass ein Modell sie zur Laufzeit findet und auswählt, ohne dass jemand die Integration vorher fest verdrahtet. Wenn Ihre Anwendung genau weiss, welchen Endpunkt sie aufrufen will, ist ein &lt;code&gt;POST /rechnungen/suchen&lt;/code&gt; billiger und einfacher zu betreiben.&lt;/p&gt;
&lt;p&gt;Der Trade-off ist real. MCP kostet einen Authorization Server, ein RFC-9728-Dokument, gepflegte Tool-Beschreibungen und ein Protokoll in Bewegung. Dafür bekommen Sie Werkzeuge, die jeder MCP-fähige Client entdecken kann, ohne dass Sie für ihn etwas bauen.&lt;/p&gt;
&lt;p&gt;Unsere Linie: Ein MCP-Server lohnt sich, wenn mehr als ein Client dieselben Werkzeuge braucht, oder wenn die Auswahl der Werkzeuge selbst Teil der Aufgabe ist. Für die AI-Agenten-Plattform AIgent trifft das zu.&lt;/p&gt;
&lt;p&gt;Für eine einzelne interne Automatisierung mit drei bekannten Aufrufen trifft es nicht zu. Das sagen wir auch dann, wenn ein Projekt anders budgetiert war.&lt;/p&gt;
&lt;p&gt;Und: Fangen Sie nicht mit der Deprecation-Migration an, solange die Authentifizierung fehlt. Roots, Sampling und Logging haben zwölf Monate. Ein Server ohne Identitätsbindung hat keine Frist, sondern ein Problem.&lt;/p&gt;
&lt;h2 id=&quot;häufige-fragen&quot;&gt;Häufige Fragen&lt;/h2&gt;
&lt;h3 id=&quot;was-ist-das-model-context-protocol&quot;&gt;Was ist das Model Context Protocol?&lt;/h3&gt;
&lt;p&gt;Das Model Context Protocol ist ein offenes Protokoll, über das KI-Anwendungen Werkzeuge, Ressourcen und Prompts eines Servers zur Laufzeit entdecken und aufrufen. Es setzt auf JSON-RPC auf und kennt zwei Transporte: STDIO für lokale Prozesse und Streamable HTTP für Netzwerkdienste. Seit der Revision 2026-07-28 ist der Protokollkern zustandslos, jede Anfrage beschreibt sich selbst.&lt;/p&gt;
&lt;h3 id=&quot;wie-baue-ich-einen-mcp-server-in-go&quot;&gt;Wie baue ich einen MCP-Server in Go?&lt;/h3&gt;
&lt;p&gt;Mit dem offiziellen &lt;code&gt;github.com/modelcontextprotocol/go-sdk&lt;/code&gt;, aktuell v1.7.0. Ein Server entsteht mit &lt;code&gt;mcp.NewServer&lt;/code&gt;, Werkzeuge werden über die generische Funktion &lt;code&gt;mcp.AddTool&lt;/code&gt; registriert, die Ein- und Ausgabeschema per Reflection aus Ihren Go-Typen ableitet. Für den Netzwerkbetrieb kommt &lt;code&gt;mcp.NewStreamableHTTPHandler&lt;/code&gt; dazu, für lokale Prozesse &lt;code&gt;server.Run&lt;/code&gt; mit &lt;code&gt;mcp.StdioTransport&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;wie-authentifiziere-ich-tool-aufrufe-eines-ki-agenten&quot;&gt;Wie authentifiziere ich Tool-Aufrufe eines KI-Agenten?&lt;/h3&gt;
&lt;p&gt;Über OAuth 2.1 mit dem MCP-Server als Resource Server. Der Client holt ein Access Token, dessen &lt;code&gt;aud&lt;/code&gt;-Claim die kanonische URI des Servers nennt, und schickt es in jedem HTTP-Request als Bearer Token. Der Server prüft Signatur, Aussteller und Zielgruppe und übersetzt den &lt;code&gt;sub&lt;/code&gt;-Claim in eine Identität, unter der die Tool-Handler arbeiten. Ein geteiltes statisches Token erfüllt das nicht.&lt;/p&gt;
&lt;h3 id=&quot;muss-ich-meinen-bestehenden-mcp-server-jetzt-migrieren&quot;&gt;Muss ich meinen bestehenden MCP-Server jetzt migrieren?&lt;/h3&gt;
&lt;p&gt;Nicht sofort, aber die Richtung ist klar. Roots, Sampling, Logging, der HTTP+SSE-Transport und Dynamic Client Registration sind deprecated und laufen mindestens zwölf Monate weiter. Die zustandslose Umstellung ist dagegen kein Deprecation-Thema, sondern eine Protokolländerung: Sitzungen und &lt;code&gt;Mcp-Session-Id&lt;/code&gt; sind in 2026-07-28 entfernt. Wer neu baut, baut zustandslos.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Über Ihre Agenten-Infrastruktur reden.&lt;/strong&gt; 30 Minuten mit einem unserer Go-Engineers: welche Werkzeuge Sie überhaupt exponieren wollen, wie die Identität vom Login bis zum Tool-Handler durchgereicht wird, und ob MCP für Ihren Fall die richtige Antwort ist. Ohne Verkaufsgespräch, ohne Vorbereitung auf Ihrer Seite.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://calendar.app.google/KojcyhwDrSDqM9oQ7&quot;&gt;Termin buchen&lt;/a&gt; · &lt;a href=&quot;https://devs-group.ch/kontakt/&quot;&gt;Kontakt aufnehmen&lt;/a&gt; · Mehr zu &lt;a href=&quot;https://devs-group.ch/leistungen/kuenstliche-intelligenz/&quot;&gt;KI- und Agenten-Systemen&lt;/a&gt; und &lt;a href=&quot;https://devs-group.ch/leistungen/backend-and-frontend/&quot;&gt;Backend-Entwicklung&lt;/a&gt;&lt;/p&gt;</content:encoded><category>Architektur</category><author>Ralph Segi</author></item><item><title>Warum wir kritische Backends in Go bauen</title><link>https://devs-group.ch/blog/warum-go-fuer-kritische-backends/</link><guid isPermaLink="true">https://devs-group.ch/blog/warum-go-fuer-kritische-backends/</guid><description>Nicht wegen der Benchmarks. Wegen dem, was ein Team nach drei Jahren noch versteht.</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Wenn wir gefragt werden, warum ein Backend in Go und nicht in Node, Java oder Rust entstehen soll, kommt die Antwort selten von den Benchmarks. Go ist schnell, ja. Aber schnell sind viele. Der Grund ist ein anderer: Go zwingt zu einer Einfachheit, die man drei Jahre später noch lesen kann.&lt;/p&gt;
&lt;h2 id=&quot;die-sprache-hat-wenig-meinung--und-genau-das-ist-die-meinung&quot;&gt;Die Sprache hat wenig Meinung – und genau das ist die Meinung&lt;/h2&gt;
&lt;p&gt;Go hat keine Vererbung, keine Exceptions, keine Generics-Akrobatik, keine drei Wege, eine Schleife zu schreiben. Was auf den ersten Blick wie ein Mangel wirkt, ist im Betrieb ein Geschenk: Code, den ein Junior schreibt, sieht fast so aus wie Code, den ein Senior schreibt. Reviews drehen sich um Fachlichkeit, nicht um Stil.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ein Backend, das man nicht mehr lesen kann, ist kein Backend mehr. Es ist eine Hypothek.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Für Systeme, die zehn Jahre laufen sollen – und das ist bei Behörden, Banken und Infrastruktur die Regel –, wiegt Lesbarkeit schwerer als jede Feature-Liste.&lt;/p&gt;
&lt;h2 id=&quot;fehler-sind-werte-keine-überraschungen&quot;&gt;Fehler sind Werte, keine Überraschungen&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;if err != nil&lt;/code&gt; wird gern belächelt. Wir mögen es. Jeder Fehler ist ein sichtbarer Pfad im Code, den man behandelt oder bewusst weiterreicht. Es gibt keinen Stack, der irgendwo drei Ebenen höher aufschlägt und die Anfrage still verschluckt.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;order, err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; repo.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;FindOrder&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, id)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;find order &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;%w&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, id, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die Fehlerkette, die daraus entsteht, ist im Log lesbar wie ein Satz: &lt;code&gt;handle payment: find order 4711: connection refused&lt;/code&gt;. Das ist Observability, für die man kein Tool kaufen muss.&lt;/p&gt;
&lt;h2 id=&quot;ein-binary-ein-container-kein-rätsel&quot;&gt;Ein Binary, ein Container, kein Rätsel&lt;/h2&gt;
&lt;p&gt;Go kompiliert zu einem statischen Binary. Das Deployment ist ein &lt;code&gt;FROM scratch&lt;/code&gt;-Container mit einer Datei darin – kein Runtime-Image, kein Paket-Manager, kaum Angriffsfläche. Für Kubernetes-Umgebungen heisst das: kleine Images, schnelle Starts, wenig CVE-Rauschen. Dasselbe Muster tragen wir auch in neue Protokolle, etwa wenn wir &lt;a href=&quot;https://devs-group.ch/blog/mcp-server-in-go-produktiv-betreiben/&quot;&gt;MCP-Server in Go produktiv betreiben&lt;/a&gt;. Was wir als &lt;a href=&quot;https://devs-group.ch/leistungen/golang-entwicklung/&quot;&gt;Golang-Entwickler aus der Schweiz&lt;/a&gt; konkret anbieten, steht auf der Leistungsseite.&lt;/p&gt;
&lt;h2 id=&quot;nebenläufigkeit-die-man-erklären-kann&quot;&gt;Nebenläufigkeit, die man erklären kann&lt;/h2&gt;
&lt;p&gt;Goroutines und Channels sind kein Zauber, aber sie erlauben es, nebenläufige Abläufe so zu schreiben, wie man sie am Whiteboard zeichnet: ein Worker-Pool, eine Pipeline, ein Fan-out. Wer das Modell einmal verstanden hat, liest fremden Code ohne Angst.&lt;/p&gt;
&lt;h2 id=&quot;wann-wir-nicht-zu-go-greifen&quot;&gt;Wann wir &lt;em&gt;nicht&lt;/em&gt; zu Go greifen&lt;/h2&gt;
&lt;p&gt;Ehrlichkeit gehört dazu: Für datenlastige Explorationen und ML-Pipelines bleibt Python die richtige Wahl. Für Frontends selbstverständlich TypeScript. Und wo ein Team bereits tief in einem Ökosystem steckt und gut damit fährt, ist ein Sprachwechsel selten die wichtigste Entscheidung.&lt;/p&gt;
&lt;p&gt;Aber wo ein System die kritische Infrastruktur eines Unternehmens ist – Zahlungen, Identität, Verwaltung –, ist Go für uns die Sprache, die den geringsten Preis für Klarheit verlangt.&lt;/p&gt;</content:encoded><category>Architektur</category><author>Ralph Segi</author></item><item><title>KI schreibt den Code. Wer schreibt die Architektur?</title><link>https://devs-group.ch/blog/ki-code-ohne-technische-schulden/</link><guid isPermaLink="true">https://devs-group.ch/blog/ki-code-ohne-technische-schulden/</guid><description>Wie wir KI-gestützte Entwicklung so einsetzen, dass am Ende weniger Code entsteht, nicht mehr.</description><pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Die Code-Menge, die ein Team pro Woche produzieren kann, hat sich mit KI-Assistenten vervielfacht. Die Menge an Code, die ein Team pro Woche &lt;em&gt;verstehen&lt;/em&gt; kann, nicht. Genau in dieser Lücke entstehen die technischen Schulden der nächsten Jahre.&lt;/p&gt;
&lt;h2 id=&quot;das-problem-ist-nicht-die-ki-es-ist-die-fehlende-bremse&quot;&gt;Das Problem ist nicht die KI. Es ist die fehlende Bremse.&lt;/h2&gt;
&lt;p&gt;Ein Assistent, dem man sagt „bau mir das”, baut es. Er fragt nicht, ob es das dritte Repository-Pattern im selben Service ist, ob die neue Abhängigkeit nötig ist oder ob die Funktion, die er gerade schreibt, schon existiert. Das ist keine Kritik an den Werkzeugen. Es ist eine Beschreibung ihrer Aufgabe. Die Bremse muss von aussen kommen.&lt;/p&gt;
&lt;h2 id=&quot;drei-regeln-die-bei-uns-gelten&quot;&gt;Drei Regeln, die bei uns gelten&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1. Architektur zuerst, dann Prompt.&lt;/strong&gt; Bevor ein Feature an einen Assistenten geht, ist geklärt, in welches Modul es gehört, welche Schnittstelle es benutzt und was es &lt;em&gt;nicht&lt;/em&gt; anfassen darf. Diese Leitplanken stehen im Repository, nicht im Kopf.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Jede Änderung wird von einem Menschen gelesen – ganz.&lt;/strong&gt; Nicht überflogen. Ein Review, das nur die Diff-Statistik prüft, ist kein Review. Wenn ein Diff zu gross ist, um gelesen zu werden, war der Prompt zu gross.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Löschen zählt als Fortschritt.&lt;/strong&gt; Wir messen nicht, wie viel Code entsteht, sondern wie viel Komplexität pro gelöstem Problem übrig bleibt. Ein Assistent ist hervorragend darin, Duplikate zu finden und zusammenzuführen – wenn man ihn danach fragt.&lt;/p&gt;
&lt;h2 id=&quot;was-sich-dadurch-verändert&quot;&gt;Was sich dadurch verändert&lt;/h2&gt;
&lt;p&gt;Die Rolle des Entwicklers verschiebt sich vom Schreiben zum Entscheiden. Das ist anspruchsvoller, nicht einfacher: Man muss wissen, wie ein System aussehen soll, bevor man es beschreiben kann. Wer das kann, bekommt mit KI einen Hebel, den es so noch nie gab. Wer es nicht kann, bekommt sehr schnell sehr viel Code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Menschliche Intelligenz steuert die künstliche – nicht als Slogan, sondern als Arbeitsteilung.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;ein-beispiel-aus-dem-alltag&quot;&gt;Ein Beispiel aus dem Alltag&lt;/h2&gt;
&lt;p&gt;Ein Kunde brauchte einen Import für ein neues Datenformat. Der erste KI-Vorschlag: ein neuer Parser, ein neues Datenmodell, 600 Zeilen. Nach zehn Minuten Architektur-Gespräch: ein Adapter von 80 Zeilen, der das bestehende Modell füttert. Beide Varianten hätten funktioniert. Nur eine davon versteht in einem Jahr noch jemand.&lt;/p&gt;</content:encoded><category>KI-gestützte Entwicklung</category><author>Robert Pupel</author></item><item><title>Kubernetes ist kein Ziel</title><link>https://devs-group.ch/blog/kubernetes-ist-kein-ziel/</link><guid isPermaLink="true">https://devs-group.ch/blog/kubernetes-ist-kein-ziel/</guid><description>Wann sich ein Cluster lohnt, wann eine einzelne VM die bessere Architektur ist – und woran man den Unterschied erkennt.</description><pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Kubernetes ist ein hervorragendes Werkzeug. Es ist auch das am häufigsten missverstandene. Wir sehen regelmässig Cluster, die drei Container betreiben, von zwei Personen gewartet werden und mehr kosten als die Anwendung, die darauf läuft.&lt;/p&gt;
&lt;h2 id=&quot;die-ehrliche-frage-vor-jedem-cluster&quot;&gt;Die ehrliche Frage vor jedem Cluster&lt;/h2&gt;
&lt;p&gt;Nicht „können wir Kubernetes?”, sondern: &lt;strong&gt;Was passiert, wenn dieser Dienst um 3 Uhr morgens ausfällt – und wer schaut hin?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Wenn die Antwort „ein Alarm, ein Runbook, ein Neustart” ist, braucht es keinen Orchestrator. Wenn die Antwort „zwölf Dienste müssen in der richtigen Reihenfolge wieder hochkommen, mit Rolling Updates und Zero Downtime” ist, dann schon.&lt;/p&gt;
&lt;h2 id=&quot;wann-sich-kubernetes-lohnt&quot;&gt;Wann sich Kubernetes lohnt&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Mehrere Teams deployen unabhängig voneinander in dieselbe Umgebung.&lt;/li&gt;
&lt;li&gt;Lastspitzen sind unvorhersehbar und Skalierung muss automatisch passieren.&lt;/li&gt;
&lt;li&gt;Compliance verlangt reproduzierbare, deklarative Infrastruktur mit Audit-Trail.&lt;/li&gt;
&lt;li&gt;Es gibt Menschen, die den Cluster &lt;em&gt;betreiben&lt;/em&gt; – nicht nur benutzen.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wann-nicht&quot;&gt;Wann nicht&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Eine Anwendung, eine Datenbank, ein Team.&lt;/li&gt;
&lt;li&gt;Der Traffic ist bekannt und passt auf eine gut dimensionierte Maschine.&lt;/li&gt;
&lt;li&gt;Niemand im Team hat Zeit, sich um Upgrades, Netzwerk-Policies und Zertifikate zu kümmern.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In diesen Fällen ist eine VM mit &lt;code&gt;systemd&lt;/code&gt;, einem Reverse Proxy und einem sauberen Deploy-Skript nicht rückständig. Sie ist die richtige Grösse. Wer die Entscheidung mit Zahlen unterlegen will: Wir haben &lt;a href=&quot;https://devs-group.ch/blog/was-kostet-kubernetes-in-der-schweiz/&quot;&gt;durchgerechnet, was ein Cluster bei Schweizer Anbietern kostet&lt;/a&gt;, inklusive des Betriebsaufwands, der auf keiner Preisliste steht. Die Zahlen machen die Entscheidung nicht schwieriger, sondern leichter: Sie zwingen dazu, das Ziel zu benennen, bevor man das Werkzeug wählt.&lt;/p&gt;
&lt;h2 id=&quot;was-wir-stattdessen-zuerst-bauen&quot;&gt;Was wir stattdessen zuerst bauen&lt;/h2&gt;
&lt;p&gt;Egal ob Cluster oder VM – drei Dinge kommen immer zuerst:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Ein Deployment, das jeder auslösen kann.&lt;/strong&gt; Ein Befehl, ein Ergebnis, kein Wissen im Kopf einer Person.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability, die man liest.&lt;/strong&gt; Wenige Metriken, klare Alarme, Logs mit Kontext.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ein Rollback, das schneller ist als die Analyse.&lt;/strong&gt; Zurückrollen, dann verstehen.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Wer diese drei hat, kann jederzeit von der VM in den Cluster wachsen. Wer sie nicht hat, hat mit Kubernetes nur ein grösseres Problem.&lt;/p&gt;</content:encoded><category>Cloud &amp; Infrastruktur</category><author>Ralph Segi</author></item><item><title>Entscheidungen, die man in zwei Jahren noch versteht</title><link>https://devs-group.ch/blog/architektur-entscheidungen-dokumentieren/</link><guid isPermaLink="true">https://devs-group.ch/blog/architektur-entscheidungen-dokumentieren/</guid><description>Architecture Decision Records sind das günstigste Werkzeug gegen Systeme, die niemand mehr erklären kann.</description><pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Jedes System, das älter als ein Jahr ist, hat Stellen, an denen ein neues Teammitglied fragt: „Warum ist das so?” Und die ehrliche Antwort lautet zu oft: „Das weiss nur noch jemand, der nicht mehr da ist.” Die Abhilfe kostet fast nichts: Architektur-Entscheidungen dokumentieren, in dem Moment, in dem sie fallen, mit dem Kontext, der sie erzwungen hat. Nicht als Prosa für die Nachwelt, sondern als kurze, datierte Notiz mit drei Feldern: Was wurde entschieden, welche Alternativen standen zur Wahl, was gab den Ausschlag.&lt;/p&gt;
&lt;h2 id=&quot;ein-adr-ist-eine-seite-nicht-ein-dokument&quot;&gt;Ein ADR ist eine Seite, nicht ein Dokument&lt;/h2&gt;
&lt;p&gt;Ein Architecture Decision Record hält fest, &lt;em&gt;was&lt;/em&gt; entschieden wurde, &lt;em&gt;warum&lt;/em&gt;, und &lt;em&gt;was man dafür in Kauf nimmt&lt;/em&gt;. Er hat vier Abschnitte und passt auf einen Bildschirm:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kontext&lt;/strong&gt; – Was war die Situation? Welche Zwänge gab es?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entscheidung&lt;/strong&gt; – Was tun wir?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alternativen&lt;/strong&gt; – Was haben wir verworfen, und warum?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Konsequenzen&lt;/strong&gt; – Was wird dadurch einfacher, was schwieriger?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Er liegt im Repository, neben dem Code, den er erklärt. Nicht im Wiki, nicht in einem Ticket, nicht in einer Slack-Nachricht.&lt;/p&gt;
&lt;h2 id=&quot;warum-das-mehr-bringt-als-jede-doku&quot;&gt;Warum das mehr bringt als jede Doku&lt;/h2&gt;
&lt;p&gt;Dokumentation beschreibt, wie ein System &lt;em&gt;ist&lt;/em&gt;. Sie veraltet in dem Moment, in dem sich das System ändert. Ein ADR beschreibt, warum es so &lt;em&gt;wurde&lt;/em&gt;. Das veraltet nie – selbst wenn die Entscheidung später revidiert wird, bleibt der Record wahr. Man ergänzt einen neuen, der auf den alten verweist.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ein System ohne Entscheidungsgeschichte ist wie ein Vertrag ohne Datum. Man kann ihn lesen, aber nicht einordnen.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;wie-wir-es-im-alltag-halten&quot;&gt;Wie wir es im Alltag halten&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Jede Entscheidung, die schwer rückgängig zu machen ist, bekommt einen ADR. Datenbankwahl, Modulschnitt, Auth-Modell – ja. Farbe des Buttons – nein.&lt;/li&gt;
&lt;li&gt;Der ADR entsteht &lt;em&gt;vor&lt;/em&gt; der Umsetzung und wird im selben Pull Request reviewt.&lt;/li&gt;
&lt;li&gt;Nummeriert, chronologisch, nie gelöscht. Überholt wird ein Record durch einen neuen, nicht durch Editieren.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Der Aufwand: zwanzig Minuten pro Entscheidung. Der Ertrag: ein Team, das auch nach dem dritten Wechsel noch weiss, warum das System aussieht, wie es aussieht.&lt;/p&gt;</content:encoded><category>Architektur</category><author>Robert Pupel</author></item><item><title>Idempotenz: das unscheinbarste Feature einer Zahlungs-API</title><link>https://devs-group.ch/blog/idempotenz-in-zahlungs-apis/</link><guid isPermaLink="true">https://devs-group.ch/blog/idempotenz-in-zahlungs-apis/</guid><description>Netzwerke sind unzuverlässig, Clients wiederholen Anfragen. Warum ein Idempotency-Key kein Detail ist, sondern die Grundlage.</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Eine Anfrage geht raus, die Antwort kommt nicht zurück. Timeout. Der Client versucht es noch einmal. Hat die Zahlung jetzt einmal stattgefunden – oder zweimal? Wenn eine API diese Frage nicht eindeutig beantworten kann, ist sie für Geld nicht geeignet. Das gilt für alle Zahlungs-APIs, unabhängig von Anbieter und Protokoll.&lt;/p&gt;
&lt;h2 id=&quot;das-prinzip&quot;&gt;Das Prinzip&lt;/h2&gt;
&lt;p&gt;Ein Endpoint ist idempotent, wenn dieselbe Anfrage – beliebig oft wiederholt – denselben Effekt hat wie einmal. Für &lt;code&gt;GET&lt;/code&gt; ist das selbstverständlich. Für &lt;code&gt;POST /payments&lt;/code&gt; muss man es bauen.&lt;/p&gt;
&lt;p&gt;Der Client schickt mit jeder schreibenden Anfrage einen selbst erzeugten Schlüssel:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;http&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;POST&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; /v1/payments&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;Idempotency-Key&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; 8f1c2a4e-3b7d-4c9e-a1f0-5d6e7f8a9b0c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Server merkt sich unter diesem Schlüssel das Ergebnis der ersten Verarbeitung. Jede Wiederholung mit demselben Schlüssel bekommt dieselbe Antwort – ohne die Zahlung erneut auszuführen.&lt;/p&gt;
&lt;h2 id=&quot;was-oft-übersehen-wird&quot;&gt;Was oft übersehen wird&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Der Schlüssel muss zur Anfrage passen.&lt;/strong&gt; Derselbe Schlüssel mit einem anderen Body ist ein Fehler, keine Wiederholung. Wir prüfen einen Hash des Bodys und antworten mit &lt;code&gt;422&lt;/code&gt;, wenn er abweicht.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nebenläufige Wiederholungen.&lt;/strong&gt; Zwei identische Anfragen treffen im selben Moment ein. Der Schlüssel muss &lt;em&gt;vor&lt;/em&gt; der Verarbeitung reserviert werden – ein &lt;code&gt;INSERT ... ON CONFLICT DO NOTHING&lt;/code&gt; in derselben Transaktion – sonst arbeiten beide.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ablauf.&lt;/strong&gt; Schlüssel leben nicht ewig. 24 Stunden sind ein guter Standard; danach ist eine Wiederholung eine neue Anfrage.&lt;/p&gt;
&lt;h2 id=&quot;ein-ausschnitt-in-go&quot;&gt;Ein Ausschnitt in Go&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;go&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Service&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;CreatePayment&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; PaymentRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Payment&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s.idem.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, key, req.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Hash&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Payment&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; s.payments.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Create&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ctx, req)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die gesamte Logik – reservieren, ausführen, Ergebnis ablegen, bei Wiederholung zurückgeben – lebt in einem Paket, das jeder schreibende Endpoint benutzt. Kein Endpoint entscheidet selbst, ob er idempotent ist.&lt;/p&gt;
&lt;h2 id=&quot;warum-das-die-grundlage-ist&quot;&gt;Warum das die Grundlage ist&lt;/h2&gt;
&lt;p&gt;Retries sind kein Fehlerfall, sie sind der Normalfall: mobile Netze, Load Balancer, Timeouts, Queues mit At-least-once-Zustellung. Eine API, die Wiederholungen nicht als Wiederholungen erkennt, verlagert das Problem in die Buchhaltung des Kunden. Dort ist es teurer.&lt;/p&gt;</content:encoded><category>Backend</category><author>Ralph Segi</author></item><item><title>Drei Dashboards statt dreissig</title><link>https://devs-group.ch/blog/observability-die-man-liest/</link><guid isPermaLink="true">https://devs-group.ch/blog/observability-die-man-liest/</guid><description>Observability scheitert selten am Werkzeug. Sie scheitert daran, dass niemand mehr hinschaut.</description><pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Fast jede Umgebung, die wir übernehmen, hat Grafana. Und fast jede hat Dashboards, die seit Monaten niemand geöffnet hat. Das Problem ist nicht zu wenig Beobachtung – es ist zu viel davon, ohne Frage dahinter. Observability, die man liest, beginnt deshalb nicht beim Werkzeug, sondern bei der Frage, welche drei Aussagen über das System jederzeit beantwortbar sein müssen: Läuft es, wird es langsamer, und wo klemmt es gerade. Alles, was diese drei Fragen nicht beantwortet, ist Dekoration, so hübsch das Panel auch aussieht.&lt;/p&gt;
&lt;h2 id=&quot;jedes-dashboard-beantwortet-genau-eine-frage&quot;&gt;Jedes Dashboard beantwortet genau eine Frage&lt;/h2&gt;
&lt;p&gt;Bevor ein Panel entsteht, muss klar sein, welche Entscheidung es unterstützt. „Ist der Dienst gesund?” ist eine Frage. „CPU-Auslastung aller Pods” ist keine – es ist eine Zahl.&lt;/p&gt;
&lt;p&gt;Wir kommen fast immer mit drei Ansichten aus:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Geht es dem Nutzer gut?&lt;/strong&gt; Fehlerrate, Latenz an der Kante, erfolgreiche Kernaktionen pro Minute.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Geht es dem System gut?&lt;/strong&gt; Sättigung der knappen Ressourcen: Verbindungen, Queue-Länge, Speicher.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Was hat sich zuletzt geändert?&lt;/strong&gt; Deployments, Konfigurationsänderungen, Feature-Flags – als Marker in der Zeitachse.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Alles Weitere ist Diagnose. Diagnose gehört in Ad-hoc-Abfragen, nicht auf ein Dashboard.&lt;/p&gt;
&lt;h2 id=&quot;alarme-die-man-ernst-nehmen-kann&quot;&gt;Alarme, die man ernst nehmen kann&lt;/h2&gt;
&lt;p&gt;Ein Alarm, der wöchentlich fehlfeuert, wird stummgeschaltet. Dann ist er kein Alarm mehr. Unsere Regel: Jeder Alarm hat einen Namen, eine Schwelle, die aus dem Nutzerversprechen abgeleitet ist, und ein Runbook. Fehlt eines davon, wird er gelöscht, nicht ergänzt.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ein Alarm ist eine Bitte um menschliche Aufmerksamkeit. Man verschickt sie sparsam.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;logs-mit-kontext-nicht-mit-volumen&quot;&gt;Logs mit Kontext, nicht mit Volumen&lt;/h2&gt;
&lt;p&gt;Strukturiert, mit Request-ID, mit dem &lt;em&gt;Warum&lt;/em&gt; – nicht dem &lt;em&gt;Was&lt;/em&gt;. &lt;code&gt;payment declined: limit exceeded, limit=500 amount=620&lt;/code&gt; sagt alles. &lt;code&gt;error in handler&lt;/code&gt; sagt nichts, und es steht trotzdem in jedem zweiten Log, das wir sehen.&lt;/p&gt;
&lt;h2 id=&quot;was-am-ende-bleibt&quot;&gt;Was am Ende bleibt&lt;/h2&gt;
&lt;p&gt;Weniger Panels, weniger Alarme, weniger Logzeilen – und ein Team, das bei einem Vorfall in dreissig Sekunden weiss, wo es hinschauen muss. Das ist Observability. Der Rest ist Speicherplatz.&lt;/p&gt;</content:encoded><category>Cloud &amp; Infrastruktur</category><author>Ralph Segi</author></item></channel></rss>