8 Min. Lesezeit

Approval-Timeouts verhindern, dass alte Genehmigungen neue Aktionen ausführen

Approval-Timeouts verhindern, dass alte Genehmigungen für Deployments, Löschungen und SSH-Befehle noch ausgeführt werden, nachdem sich Ziele oder Bedingungen geändert haben. Erfahre, wie du sie bindest, ablaufen lässt und erneut prüfst.

Approval-Timeouts verhindern, dass alte Genehmigungen neue Aktionen ausführen

Eine Genehmigung ist die Erlaubnis für eine bestimmte geplante Aktion zu einem bestimmten Zeitpunkt. Sie ist kein Gutschein, den ein Agent einlösen kann, sobald es gerade passt.

Das klingt offensichtlich, bis ein Agent ein Produktions-Deployment, eine Löschung oder einen SSH-Befehl in die Warteschlange stellt, während ein Mensch beschäftigt ist. Der Reviewer sieht eine nachvollziehbare Anfrage und genehmigt sie. Dann verändert sich die Welt. Ein neuerer Build gewinnt die Warteschlange. Die Zielgruppe ändert sich. Jemand zeigt einen Umgebungsalias auf ein anderes Ziel. Ein Vorfall verändert die Sicherheitsbedingungen. Wenn die alte Genehmigung trotzdem noch ausgelöst werden kann, macht das System aus einer Entscheidung über den Zustand von gestern eine Berechtigung für den Zustand von heute.

Approval-Timeouts lösen nur einen Teil dieses Problems, aber genau diesen Teil lassen Teams oft offen. Setze für Aktionen, deren Bedeutung sich ändern kann, eine kurze, harte Ablaufzeit. Verknüpfe die Genehmigung anschließend mit der exakt geplanten Aktion und prüfe die veränderlichen Bedingungen vor der Ausführung erneut. Beides ist nötig. Jede Kontrolle für sich lässt eine Lücke.

Jede Genehmigung hat ein Zeitbudget

Jede Genehmigung verliert Zeit, während sie auf ihre Ausführung wartet. Je stärker sich das Ziel verändern kann, desto kleiner sollte dieses Budget sein.

Eine Anfrage zum Neustart eines kurzlebigen Preview-Workers kann eine halbe Stunde lang sinnvoll bleiben. Eine Anfrage, ein Release in die Produktion zu bringen, kann innerhalb weniger Minuten veralten, wenn ein anderes Release, ein Rollback oder ein laufender Vorfall den nächsten richtigen Schritt verändern kann. Ein Befehl zum Löschen eines benannten Backup-Snapshots sollte schnell ablaufen, wenn gerade aktiv an der Aufbewahrung der Snapshots gearbeitet wird. Ein SSH-Befehl gegen einen veränderlichen Host-Alias verdient das kürzeste Zeitfenster von allen.

Der falsche Standard ist eine große Zahl, nur weil sie niemanden stört. Acht Stunden wirken entgegenkommend. In der Praxis können sich Genehmigungen so über die Mittagspause, die Nacht oder eine Schichtübergabe hinweg ansammeln. Ein Reviewer genehmigt um 10:02 Uhr ein Deployment, vergisst es und stellt um 16:40 Uhr fest, dass ein viel späterer Zustand der Warteschlange seinen Klick verwendet hat. Die Genehmigungsoberfläche wirkte sorgfältig. Der Ausführungspfad war es nicht.

Lege das Zeitfenster fest, indem du eine engere Frage stellst: Wie lange kann diese exakt geplante Aktion noch eine zutreffende Beschreibung dessen sein, was passieren wird?

Für die meisten Teams ist folgende Ausgangsregel sinnvoll:

  • Produktions-Deployment oder Rollback: 5 bis 15 Minuten.
  • Destruktive Löschung: 2 bis 10 Minuten, abhängig davon, ob die Objektmenge feststeht.
  • SSH-Befehl mit Schreibwirkung: 2 bis 5 Minuten.
  • Schreibgeschützte SSH-Prüfung: keine Genehmigung pro Aktion oder ein längeres Fenster, falls die Umgebung weiterhin eine verlangt.
  • Routinemäßige Änderungen außerhalb der Produktion mit einem festgelegten Build: 15 bis 30 Minuten.

Das sind Betriebsstandards und keine universellen Konstanten. Eine Ablaufzeit von fünf Minuten ist zu lang, wenn eine Automatisierung das Ziel alle paar Sekunden verändern kann. Sie ist zu kurz, wenn ein On-Call-Reviewer zuerst Belege zusammentragen muss. Die richtige Reaktion besteht nicht darin, die Frist stillschweigend immer weiter zu verlängern. Gib dem Reviewer den nötigen Kontext und mach es leicht, die Anfrage aus dem aktuellen Zustand neu zu erzeugen.

GitHub Actions unterscheidet hier an einer wichtigen Stelle: Ein Deployment-Job kann auf eine erforderliche Prüfung warten. Ein ausstehender Job, der genehmigt wird, kann anschließend fortfahren und Zugriff auf seine Umgebungsgeheimnisse erhalten. GitHub dokumentiert außerdem, dass ein nicht genehmigter Job nach 30 Tagen fehlschlagen kann. Das verhindert, dass Warteschlangen ewig bestehen bleiben. 30 Tage sind jedoch kein sinnvolles Zeitfenster für die Aktualität einer Genehmigung über ein sich veränderndes Deployment. Der eigene Kontrollpunkt sollte das Alter der Genehmigung als Teil der Autorisierung behandeln und nicht als bloße Warteschlangenpflege.

Die Entscheidung an die Aktion und nicht an ein Label binden

Eine Genehmigung muss konkrete Aktionsdaten abdecken. «Produktions-Deployment genehmigen» ist ein Label. Es sagt dem Reviewer fast nichts über das Objekt, das ausgeführt wird.

Bei einem Deployment sollte die Entscheidung an den unveränderlichen Artefakt-Digest oder die Commit-ID, das Ziel, den vorhandenen Migrationsplan, die Konfigurationsrevision und die Release-Aktion gebunden sein. Bei einer Löschung sollte sie an eine unveränderliche Objektliste oder einen Snapshot des Abfrageergebnisses sowie an den Löschmodus gebunden sein. Bei SSH gehören die geprüfte Host-Identität, der Benutzer, die Befehlsschablone, die aufgelösten Argumente, das Arbeitsverzeichnis, falls relevant, und eine begrenzte Beschreibung der Eingabedateien in die Bindung.

Diese Unterscheidung wird am häufigsten verwischt:

  • Genehmigung einer Absicht bedeutet, dass der Reviewer einem groben Ziel zustimmt, etwa «veraltete Previews entfernen».
  • Genehmigung einer Aktion bedeutet, dass der Reviewer zustimmt, dass dieser Executor diese Objekt-IDs mit diesem Befehl vor dieser Frist löscht.

Eine Absichtsgenehmigung hat im Change-Management ihren Platz. Sie kann eine Ausführungsgenehmigung nicht ersetzen, wenn ein Agent auf einem aktiven System handeln kann. Wenn du eine Absicht genehmigst und den Agenten die Ziele erst später auflösen lässt, überträgst du den wichtigsten Teil der Entscheidung an den Agenten.

OWASP beschreibt diesen Punkt in einem anderen Bereich im Transaction Authorization Cheat Sheet. Dort heißt es, dass die Person, die eine Transaktion autorisiert, wichtige Transaktionsdaten erkennen und bestätigen muss. Außerdem wird davor gewarnt, Daten nach der Autorisierung zu ändern, weil dadurch ein Time-of-Check-to-Time-of-Use-Fehler entsteht. Das Beispiel stammt aus dem Finanzbereich, die Regel lässt sich aber direkt übertragen: Genehmigungsdaten müssen vor Änderungen geschützt werden, und eine Datenänderung sollte die bestehende Autorisierung ungültig machen.

Ein Digest gibt dem Executor etwas Präzises zum Vergleichen. Hash nicht einfach eine vage Zusammenfassung in natürlicher Sprache und erkläre die Sache damit für erledigt. Normalisiere die Felder, die die Wirkung steuern, serialisiere sie deterministisch und hashe anschließend diese kanonische Form.

{
  "request_id": "appr_01JX...",
  "action_type": "deploy",
  "action_digest": "sha256:8b1d...",
  "summary": {
    "artifact": "registry.example/app@sha256:4fa2...",
    "environment": "production",
    "operation": "promote",
    "config_revision": "7c0e...",
    "migration": "none"
  },
  "issued_at": "2026-07-22T14:03:00Z",
  "expires_at": "2026-07-22T14:13:00Z",
  "status": "pending"
}

Die summary ist für den Menschen. Der action_digest ist für den Executor. Behalte beides. Menschen müssen nützliche Fakten sehen, Dienste brauchen einen exakten Gleichheitsvergleich. Wenn der Agent auch nur ein gebundenes Feld ändert, muss er eine neue Anfrage stellen und eine neue Entscheidung einholen.

Ablauf und Ungültigkeit lösen unterschiedliche Fehler

Eine Frist verhindert, dass alte Genehmigungen liegen bleiben. Eine Ungültigerklärung entfernt eine Genehmigung, sobald sich relevante Fakten ändern. Du brauchst beides, denn auf einen Timer zu warten ist nachlässig, wenn das System bereits weiß, dass die Anfrage nicht mehr zur Wirklichkeit passt.

Erkläre eine ausstehende Genehmigung für ungültig, wenn sich der Aktions-Digest ändert. Diese Regel ist nicht verhandelbar. Ungültig werden sollte sie auch, wenn sich eine für die Bedeutung relevante Abhängigkeit ändert: die vorgesehene Umgebungsrevision eines Deployments, die ausgewählte Löschmenge, ein Hostschlüssel, der Inhaber einer Release-Sperre oder der Status eines erforderlichen Change-Tickets.

Erkläre nicht jedes unabhängige Ereignis zum Ungültigkeitsgrund. Wenn jede Logzeile, jeder unabhängige Commit oder jede harmlose Metrikänderung eine Genehmigung beendet, lernen Reviewer, dass Anfragen unzuverlässig sind. Dann genehmigen sie, ohne hinzusehen. Die Regel sollte Fakten verfolgen, die entweder die gewünschte Wirkung oder die Sicherheitsvoraussetzungen verändern.

Verwende drei Zustände statt zwei:

  1. pending bedeutet, dass die exakte Anfrage noch vor ihrer Frist genehmigt werden kann.
  2. approved bedeutet, dass ein Reviewer sie genehmigt hat, der Executor sie aber noch nicht verbraucht hat.
  3. consumed bedeutet, dass die Ausführung die Genehmigung genau einmal beansprucht hat.

Ergänze die Endzustände expired, invalidated, rejected und failed. Eine abgelehnte Anfrage darf nicht wieder zu pending werden, nur weil ein Agent einen Netzwerkaufruf wiederholt hat. Eine fehlgeschlagene Ausführung darf dieselbe Genehmigung nicht stillschweigend wiederverwenden, sofern du nicht beweisen kannst, dass die Aktion nie begonnen hat und sich kein relevanter Zustand geändert hat. In den meisten Aktionssystemen ist es sicherer und leichter zu erklären, den Agenten erneut fragen zu lassen.

Der Executor sollte diese Prüfungen in einer Transaktion oder einer atomaren Compare-and-Set-Operation durchführen:

if now \u003e= expires_at: reject as expired
if status != approved: reject as unavailable
if stored_digest != supplied_digest: reject as changed
if live_preconditions fail: reject as stale
atomically change status from approved to consumed
execute the action

Markiere die Genehmigung nicht erst nach Beginn der Aktion als verbraucht. Zwei Worker können gleichzeitig zugreifen, beide approved sehen und beide ausführen. Verbrauche sie zuerst mit einer atomaren Zustandsänderung und protokolliere anschließend, dass die Ausführung begonnen hat. Wenn der Prozess nach dem Verbrauch beendet wird, bleibt das Ergebnis unbekannt, bis der Executor feststellen kann, ob das Ziel erreicht wurde. Das ist unbequem. Doppelte destruktive Arbeit ist schlimmer.

Deployment-Genehmigungen müssen dem Artefakt folgen

Eine Deployment-Anfrage wird veraltet, wenn sich ihr Artefakt, ihr Ziel, ihr Release-Plan oder ihre Position in der Warteschlange ändert. Branch-Namen und bewegliche Tags reichen nicht aus.

Die Deployment-Anfrage sollte ein unveränderliches Artefakt nennen. Das kann ein Image-Digest, ein signierter Hash eines Release-Bundles oder ein unveränderlicher Build-Eintrag sein. Sie sollte dem Reviewer außerdem mitteilen, ob der Executor Datenbankmigrationen ausführt, die Feature-Konfiguration ändert, Instanzen neu startet oder ein vorheriges Deployment ersetzt. Diese Details beeinflussen die Genehmigung. Sie hinter einer allgemeinen «Deploy»-Schaltfläche zu verbergen, lädt zum unkritischen Bestätigen ein.

Ein solider Vertrag für eine Deployment-Genehmigung umfasst:

  • Die unveränderliche Build-ID und die Quellrevision.
  • Die genaue Zielumgebung sowie die Identität des Kontos oder Clusters.
  • Die Release-Aktion, etwa Promote, Rollback oder Redeploy.
  • Die Konfigurations- und Migrationsrevisionen, die angewendet werden.
  • Ein Konkurrenz-Token oder eine Deployment-Generation.

Das Konkurrenz-Token ist wichtig, wenn eine spätere Änderung eine frühere Anfrage ersetzt. Angenommen, Build A wartet auf eine Genehmigung. Build B wird fertig, besteht die Prüfungen und ist nun das Release, das du ausliefern möchtest. Wenn die Anfrage für Build A gültig bleibt, kann ein Reviewer versehentlich den alten Build freigeben. Sobald Build B in dieselbe Release-Spur gelangt, muss die ausstehende Genehmigung für Build A ungültig werden. Verlass dich in einer vollen Warteschlange nicht darauf, dass Reviewer Zeitstempel bemerken.

Die Deployment-Dokumentation von GitHub trennt den Schutz der Umgebung von der Workflow-Konkurrenz. Die Konkurrenzsteuerung kann ausstehende Arbeit in einer Gruppe abbrechen, während die Umgebungsfreigabe entscheidet, ob ein Job fortfahren darf. Diese Trennung ist nützlich: Eine Warteschlangenregel kann entscheiden, welcher Lauf aktuell ist, während ein Genehmigungskontrollpunkt entscheidet, ob genau dieser aktuelle Lauf ausgeführt werden darf. Wer beides unvorsichtig verbindet, erzeugt den klassischen Fehler, bei dem die richtige Person den falschen Lauf genehmigt.

Der Executor muss vor dem Deployment erneut prüfen. Ein praktischer Vorab-Check kann bestätigen, dass das angeforderte Artefakt noch existiert, die Umgebung weiterhin auf die erwartete Zielidentität zeigt, kein neueres Release die Spur blockiert und der Migrationsplan noch zum genehmigten Digest passt. Wenn eine Prüfung fehlschlägt, markiere die Anfrage als ungültig und zeige dem Reviewer eine neue Anfrage. Ersetze Build A niemals stillschweigend durch Build B, nur weil A genehmigt wurde. Das ist eine andere Aktion.

Vermeide ein beliebtes, aber schwaches Muster: einen Pull Request zu genehmigen und diese Genehmigung als Produktionsfreigabe zu behandeln. Code-Review beantwortet die Frage, ob eine geplante Änderung in die Codebasis gehört. Es beantwortet nicht, ob dieser Build jetzt, nach dem aktuellen Vorfall, mit den aktuellen Migrationen und dem aktuellen Zielzustand in der Produktion laufen sollte. Halte diese Entscheidungen getrennt.

Löschanfragen brauchen eine eingefrorene Objektmenge

HTTP-Zugangsdaten schützen
HTTP-Bearer-, Basic- und benutzerdefinierte Header-Zugangsdaten bleiben im lokalen Tresor von Sallyport verschlüsselt.

Löschgenehmigungen werden gefährlich, wenn die Anfrage eine Abfrage statt der aufgelösten Objekte enthält. «Backups löschen, die älter als 30 Tage sind» kann jede Minute eine andere Menge beschreiben.

Löse die Abfrage beim Erstellen der Anfrage in Objekt-IDs auf und speichere einen Snapshot-Marker. Die Genehmigungsansicht sollte die Anzahl, einige repräsentative IDs, die Grundlage für die Aufbewahrung und den genauen Löschmodus anzeigen. Der Executor sollte diese eingefrorene Menge verwenden und die allgemeine Abfrage nach der Genehmigung nicht erneut ausführen.

Wenn die Menge zu groß ist, um sie vollständig anzuzeigen, gib dem Reviewer eine stabile Manifest-ID und eine kurze Aufschlüsselung. Reduziere die Anfrage nicht auf «8.421 Elemente löschen», ohne die Grenzen zu zeigen. Eine Anzahl verrät dem Reviewer nicht, ob die falsche Mandantenumgebung, aktuelle Backups oder ein unerwartetes Präfix in der Liste enthalten sind.

Betrachte diese Anfrage:

{
  "action_type": "delete_objects",
  "scope": "archive/preview/",
  "selection": {
    "manifest_digest": "sha256:19e7...",
    "object_count": 184,
    "newest_object_at": "2026-06-19T03:11:00Z",
    "oldest_object_at": "2025-11-02T18:24:00Z"
  },
  "mode": "permanent",
  "expires_at": "2026-07-22T14:08:00Z"
}

Prüfe bei der Ausführung, dass das Manifest noch existiert und jede Objekt-ID weiterhin auf die erwartete Version verweist. Wenn das Speichersystem Versionierung unterstützt, binde die Löschung an Versionen und nicht an Namen. Namen können wiederverwendet werden. Ein neues Objekt, das nach der Genehmigung am selben Pfad geschrieben wird, darf nicht das Todesurteil des alten Objekts erben.

Eine kurze Frist ist besonders wichtig, wenn die Anfrage auf dem Alter oder einem aktuellen Inventar beruht. Je länger sie wartet, desto wahrscheinlicher verändern ein neu berechtigtes Objekt, ein wiederhergestelltes Element oder ein neu klassifizierter Datensatz die gewünschte Menge. Wenn das System die Menge nicht einfrieren kann, sollte eine einzelne Genehmigung keine umfassende Löschabfrage autorisieren dürfen. Fordere stattdessen eine engere, aktuelle Anfrage an.

Soft Delete und endgültige Löschung brauchen unterschiedliche Abfragen und unterschiedliche Ablaufzeiten. Soft Delete kann umkehrbar sein. Verwende die Umkehrbarkeit aber nicht als Entschuldigung für ungenaue Genehmigungen. Die Wiederherstellung ist oft langsam, unvollständig oder hängt von Berechtigungen ab, die die Person, die die Löschung beantragt, nicht kontrolliert.

SSH-Genehmigungen veralten schneller als gedacht

SSH reagiert besonders empfindlich auf veralteten Kontext, weil sich Namen, Sitzungen, Umgebungsvariablen und Arbeitsverzeichnisse unter demselben Befehlstext verändern können.

systemctl restart api wirkt konkret, bis du fragst, welche Maschine den Befehl erhält, worauf api dort zeigt, welches Deployment aktuell aktiv ist und ob ein späterer Vorfall den Grund für einen Neustart verändert hat. rm -rf /srv/tmp/job-123 kann auf einem Host sicher und auf einem anderen katastrophal sein, wenn sich ein Alias, ein Mount oder eine Shell-Erweiterung ändert.

Genehmige bei einer SSH-Aktion eine strukturierte Befehlsanfrage und kein Terminalprotokoll. Die Anfrage sollte die geprüfte Identität des Hosts, den Zielbenutzer, eine feste Befehlsschablone, vollständig aufgelöste erlaubte Argumente, das deklarierte Arbeitsverzeichnis und gegebenenfalls den erwarteten Eingabe-Digest enthalten. Wenn der Agent eine Shell braucht, beschränke den Shell-Befehl auf eine ausdrücklich angegebene Nutzlast, statt eine offene interaktive Sitzung zu autorisieren.

Eine sinnvolle Genehmigungskarte könnte so aussehen:

Host: prod-api-03, host key SHA256:K4f...
User: deploy
Command: /usr/local/bin/release-health --release 2026.07.22.4 --repair-cache
Directory: /srv/api
Effect: writes cache state, may restart one service
Expires: 14:08 UTC

Das beweist noch nicht, dass der Befehl sicher ist. Es sind jedoch genug Informationen vorhanden, damit ein Mensch erkennt, was er autorisiert. Der Executor verbindet sich anschließend erneut, prüft die Host-Identität noch einmal, bestätigt den Befehls-Digest und führt den Befehl vor Ablauf der Frist aus.

Eine Genehmigung für einen Befehl auf prod-api darf niemals die Ausführung autorisieren, nachdem DNS, Inventar oder eine Bastion-Zuordnung dieses Label auf einen anderen Host auflösen. Binde die Aktion, sofern der Verbindungsaufbau das zulässt, an die kryptografische Identität des Hosts. Wenn während des Wartens auf die Genehmigung eine legitime Hostschlüsselrotation stattfindet, erkläre die Anfrage für ungültig. Das kann während einer Wartung störend sein. Es ist besser, als einen Befehl für eine Maschine zu genehmigen und ihn an eine andere zu schicken.

Schreibgeschützte Befehle verdienen eine eigene Kategorie. Teams verlangen oft für jeden SSH-Aufruf eine Genehmigung, weil sie eine Kontrolle haben und sie überall anwenden. Das führt zu Genehmigungsmüdigkeit. Reviewer klicken dann Befehle durch, die sie nicht verstehen. Trenne harmlose Prüfungen von Aktionen, die schreiben, neu starten, Zugriffe ändern oder vertrauliche Ausgaben offenlegen. Verwende eine Genehmigung pro Aufruf, wenn die Wirkung des Befehls das rechtfertigt, und halte die Abfrage so kompakt, dass sie gelesen werden kann.

Die Genehmigungsansicht muss Änderungen sichtbar machen

Genehmigungen bis zur Ausführung schützen
Sallyport führt genehmigte HTTP- und SSH-Aktionen aus, ohne dem Agenten wiederverwendbare Zugangsdaten zu geben.

Ein präziser Backend-Vertrag ist nutzlos, wenn der Reviewer nur einen vom Agenten formulierten Satz sieht. Die Ansicht muss die Felder zeigen, die die Antwort verändern könnten.

Beginne mit der Wirkung: diesen Digest in dieser Umgebung deployen, dieses feste Manifest endgültig löschen oder diesen Befehl auf diesem geprüften Host ausführen. Platziere die Frist so, dass sie vor der Genehmigung auffällt, und zeige die Zeit in einer eindeutigen Zeitzone an. Ein Countdown ist nur eine Hilfe. Der serverseitige Zeitstempel des Executors entscheidet über die Gültigkeit.

Wenn sich eine Anfrage ändert, ersetze den alten Inhalt nicht einfach an derselben Stelle und lass die Genehmigungsschaltfläche aktiv. Markiere die Anfrage als ungültig. Erstelle eine neue Anfrage mit einer sichtbaren Erklärung wie «Artefakt geändert» oder «Zielinventar geändert». Ein Reviewer, der die frühere Version genehmigt hat, muss eine neue Entscheidung treffen. Genau darum geht der zusätzliche Klick.

NIST SP 800-63B-4 beschreibt Authentifizierungsabsicht als eine Handlung des Benutzers, die bestätigt, dass ein Anspruchsteller sich authentifizieren oder erneut authentifizieren will. Für Aktionsgenehmigungen braucht es dieselbe Disziplin, allerdings enger gefasst. Ein Fingertipp oder Bestätigungsklick sollte die Absicht für die angezeigte Aktion ausdrücken und nicht die allgemeine Bereitschaft, einen Agenten weitermachen zu lassen.

Vermeide Abfragen, die Zeitdruck in eine Falle verwandeln. Ein zweiminütiges Fenster für eine komplexe Löschung zwingt einen Reviewer zwischen blinder Genehmigung und Ablauf zu wählen. Die Anfrage sollte prüfbereit sein, bevor sie den Reviewer erreicht. Verwende eine kurze Ausführungsfrist, nachdem der Reviewer ausreichend Kontext erhalten hat, und keine überhastete Entscheidungsfrist, die sorgfältiges Lesen bestraft.

Ein Kommentarfeld kann helfen, wenn der Reviewer begründen muss, warum eine ungewöhnliche Aktion vertretbar ist. Mache einen Kommentar bei gewöhnlichen Vorgängen nicht verpflichtend. Pflichttexte erzeugen Floskeln, die niemand liest. Verlange einen Kommentar bei Überschreibungen, außergewöhnlichen Verlängerungen oder Aktionen, die einen festgelegten Wirkungsbereich überschreiten.

Der Executor ist für die Durchsetzung zuständig

Das System, das die Berechtigung zur Aktion besitzt, muss Ablauf, Bindung und einmalige Nutzung durchsetzen. Eine Workflow-Oberfläche, ein Chatbot oder ein Agent-Framework kann eine Genehmigung anfordern. Es darf aber nicht das letzte Urteil fällen, wenn eine andere Komponente den Kontrollpunkt umgehen kann.

Deshalb ist ein Aktions-Gateway eine sinnvolle Grenze. Der Agent stellt einen HTTP-Aufruf oder einen SSH-Befehl in Aussicht. Das Gateway prüft, ob eine aktuelle Genehmigung vorhanden ist, fügt gegebenenfalls die Zugangsdaten ein, führt die Aktion aus und gibt das Ergebnis zurück. Der Agent braucht nie wiederverwendbare Zugangsdaten, mit denen er den Genehmigungspfad später umgehen könnte.

Sallyport folgt diesem Modell für HTTP-APIs und SSH: Der Agent verbindet sich über seinen MCP-Shim, während die Zugangsdaten im verschlüsselten Tresor der App bleiben. Die App führt die Aktion aus, statt Geheimnisse an den Agenten zu übergeben. Die Schlüssel pro Aufruf sind ein natürlicher Ort, um bei Aktionen mit schnell wechselndem Kontext eine neue Bestätigung zu verlangen. Timeout und Aktionsbindung müssen im Anfragepfad trotzdem ausdrücklich umgesetzt werden. Eine Bestätigung ohne diese Prüfungen kann in dasselbe Problem veralten.

Halte den Genehmigungsstatus in unmittelbarer Nähe zum Executor oder mache ihn für den Executor kryptografisch prüfbar. Ein signiertes Genehmigungs-Token kann funktionieren, wenn es Anfrage-ID, Aktions-Digest, Ausstellungszeit, Ablaufzeit, Reviewer-Identität und Nonce enthält. Der Executor muss trotzdem den Widerruf prüfen und die Nonce einmalig verbrauchen. Ein signiertes Token, das nach der Ungültigerklärung einer Anfrage gültig bleibt, ist einfach eine gut signierte veraltete Genehmigung.

Behandle Uhren sorgfältig. Verwende für Ablaufentscheidungen eine vertrauenswürdige Dienstuhr, speichere Zeitstempel in UTC und lehne Genehmigungen am oder nach dem Ablaufzeitpunkt ab. Die lokale Uhr des Agenten und der Countdown im Browser dienen nur der Anzeige. Sie sind keine Autorisierungsdaten.

Logs sollten erklären, warum eine Ausführung stattfand oder ausblieb

Agenten keine Geheimnisse übergeben
Agenten senden Anfragen über sp mcp. Sallyport fügt die Zugangsdaten ein und gibt nur die Ergebnisse zurück.

Wenn eine Genehmigung abläuft, brauchen Teams einen Eintrag, der mehr sagt als «abgelehnt». Sie müssen wissen, ob ein Reviewer nicht geantwortet hat, sich die Anfrage nach der Genehmigung geändert hat, der Executor eine fehlgeschlagene Voraussetzung gefunden hat oder ein anderer Worker die Genehmigung bereits verbraucht hatte.

Schreibe eine unveränderliche Ereignisspur, die Vorschlag, angezeigte Zusammenfassung, Genehmigungsentscheidung, Ungültigerklärung oder Ablauf, Vorabprüfungen, Ausführungsversuch und Ergebnis miteinander verbindet. Speichere den Aktions-Digest in jedem Ereignis. Wenn die Anfrage neu erzeugt wurde, protokolliere die ID der Ersatzanfrage, ohne den Eindruck zu erwecken, dass die frühere Genehmigung übernommen wurde.

Eine nützliche Ereignisstruktur sieht so aus:

{
  "event": "approval.invalidated",
  "request_id": "appr_01JX...",
  "action_digest": "sha256:8b1d...",
  "reason": "release_lane_superseded",
  "replaced_by": "appr_01JY...",
  "recorded_at": "2026-07-22T14:06:22Z"
}

Protokolliere auch Versuche, abgelaufene Genehmigungen zu verbrauchen. Sie zeigen Agenten, die blind wiederholen, Worker mit falschen Uhren und UI-Pfade, die ihre Anzeige nicht aktualisiert haben. Außerdem kann ein Incident-Reviewer so zwischen einer abgelaufenen Anfrage und einer Aktion unterscheiden, die tatsächlich die Produktion erreicht hat.

Das Sitzungsjournal und das Aktivitätsjournal von Sallyport werden aus einem verschlüsselten, hashverketteten Audit-Log erzeugt. Der Befehl sp audit verify prüft diese Kette offline über dem Chiffretext. Eine solche Spur ist nur dann nützlich, wenn die Ereignisbegriffe ehrlich sind. Protokolliere Ablauf, Ungültigerklärung und fehlgeschlagene Vorabprüfungen und nicht nur erfolgreiche Aufrufe, die das Dashboard sauber aussehen lassen.

Verwechsle Prüfbarkeit nicht mit Vermeidung. Ein perfekter Nachweis darüber, dass eine alte Genehmigung gegen einen neuen Zustand ausgeführt wurde, ist ein Beleg für einen Fehler. Die Vermeidungsprüfung muss laufen, bevor der Executor die Anfrage sendet oder den SSH-Kanal öffnet.

Mach es einfach, abgelaufene Anfragen zu ersetzen

Kurze Zeitfenster funktionieren nur, wenn eine neue Anfrage leichter ist, als über eine alte zu diskutieren. Wenn die Neuerstellung das erneute Eingeben einer Ticketnummer, das manuelle Erstellen eines Befehls und die Abstimmung mit drei Personen erfordert, werden Teams dich dazu drängen, jedes Timeout so weit zu verlängern, bis es bedeutungslos ist.

Der Agent sollte die Anfrage aus dem aktuellen Zustand erneut einreichen können, muss die neuen Fakten aber klar anzeigen. Wenn sich nur die Ablaufzeit geändert hat und alle gebundenen Felder identisch bleiben, kann eine neue Anfrage dieselbe lesbare Zusammenfassung verwenden, aber eine neue ID und Frist erhalten. Wenn sich ein Aktionsfeld oder eine aktuelle Voraussetzung geändert hat, muss die Änderung genannt werden. Zwinge den Reviewer nicht, undurchsichtige Hashes zu vergleichen.

Behandle eine Verlängerung der Ablaufzeit als Ausnahme. Wenn du sie anbietest, muss der Executor alle Vorabprüfungen erneut ausführen und der Reviewer die aktuelle Zusammenfassung wieder sehen. Ein «30 Minuten verlängern»-Button, der das alte Token erneuert, ist ein Umgehen der Genehmigung mit besserer Typografie.

Beginne mit vier Messwerten: Wie oft laufen Genehmigungen ab? Wie oft werden genehmigte Aktionen vor der Ausführung ungültig? Wie lange warten Anfragen? Und bei welchen Aktionstypen gibt es wiederholte Versuche? Die Ergebnisse zeigen, ob die Frist zu kurz, die Warteschlange zu langsam ist oder der Agent Anfragen erstellt, bevor seine Eingaben stabil sind.

Eine veraltete Genehmigung sollte leise und eindeutig scheitern: Der Executor lehnt sie ab, das Log nennt den Grund und der Agent fordert eine aktuelle Entscheidung an, falls die Arbeit weiterhin sinnvoll ist. Diese kleine Ablehnung sorgt dafür, dass die menschliche Kontrolle an der Aktion bleibt, die tatsächlich ausgeführt wird.

FAQ

Was ist ein Approval-Timeout?

Ein Approval-Timeout ist eine feste Frist. Nach ihrem Ablauf kann eine nicht verbrauchte Genehmigung eine Aktion nicht mehr autorisieren. So wird verhindert, dass jemand eine Anfrage genehmigt, sich entfernt und die alte Entscheidung erst ausgeführt wird, nachdem sich Ziel, Befehl oder Rahmenbedingungen geändert haben.

Wie lange sollte eine Deployment-Genehmigung gültig sein?

Eine Deployment-Genehmigung sollte normalerweise nach Minuten und nicht nach Stunden ablaufen. Wähle ein kürzeres Zeitfenster, wenn ein Release schnell durch ein anderes ersetzt werden kann oder ein Vorfall aktiv ist. Ein etwas längeres Fenster ist nur sinnvoll, wenn Build und Ziel unverändert feststehen und bei der Ausführung erneut geprüft werden.

Verhindert der Ablauf einer Genehmigung allein veraltete Aktionen?

Nein. Eine kurze Ablaufzeit begrenzt lediglich, wie lange eine Entscheidung unbeaufsichtigt liegen bleiben kann. Sie beweist nicht, dass die Aktion noch dieselbe Bedeutung hat. Verknüpfe die Genehmigung mit einem unveränderlichen Aktions-Digest und prüfe die aktuellen Voraussetzungen unmittelbar vor der Ausführung erneut.

Was sollte eine Löschgenehmigung enthalten?

Die Genehmigung muss das konkrete Objekt oder die konkrete Auswahl, ihre Version oder ihren Snapshot-Marker, die beabsichtigte Wirkung und die Ablaufzeit nennen. Wenn eine Löschanfrage nur sagt «alte Logs entfernen», ist sie für eine sichere Genehmigung nicht konkret genug.

Sollten SSH-Befehlsfreigaben ablaufen?

Verwende eine kurze Ablaufzeit, eine feste Befehlsschablone, eine eindeutige Host-Identität und eine frische Verbindungs- oder Host-Prüfung, bevor der Befehl ausgeführt wird. Eine Genehmigung für einen Befehl auf einem Host darf nicht zu einer Erlaubnis für denselben Text auf dem Host werden, der später unter einem Alias erreichbar ist.

Sind Approval-Timeouts dasselbe wie Idempotenz?

Ein Timeout behandelt Veralterung. Idempotenz behandelt doppelte Ausführung. Ein Deployment kann von beiden Problemen betroffen sein. Verwende deshalb eine Genehmigungsfrist und zusätzlich einen Idempotenzschlüssel für die Ausführung oder einen Release-Eintrag, der einen zweiten Lauf unschädlich macht oder ablehnt.

Was passiert, wenn eine Genehmigung abläuft?

Lass die Genehmigung ablaufen und erstelle eine neue Anfrage aus den aktuellen Aktionsdaten. Biete keinen allgemeinen «Verlängern»-Button an. Er würde Reviewer daran gewöhnen, eine Entscheidung zu erneuern, ohne zu prüfen, was sich geändert hat.

Ist ein Approval-Timeout dasselbe wie ein Warte-Timer?

Nein. Wartezeiten und Ablaufzeitfenster lösen gegensätzliche Probleme. Ein Warte-Timer verzögert die Berechtigung zur Ausführung. Eine Ablaufzeit begrenzt, wie lange eine Genehmigung gültig bleibt, nachdem ein Reviewer entschieden hat.

Wo sollte der Ablauf einer Genehmigung durchgesetzt werden?

Die Ablaufprüfung gehört an das Aktions-Gateway oder in den Executor. Dort kann das System den genehmigten Digest mit der Anfrage vergleichen, die es gerade ausführen soll. Eine Chat-Oberfläche darf die Frist anzeigen, aber nicht die letzte Autorität sein.

Was sollte ein Audit-Log für eine abgelaufene Genehmigung protokollieren?

Der Audit-Eintrag sollte den Aktions-Digest, die lesbare Zusammenfassung, die Identität des Reviewers, den Entscheidungszeitpunkt, den Ablaufzeitpunkt, den Ausführungszeitpunkt, die Live-Prüfungen und das Ergebnis enthalten. Protokolliere auch abgelaufene und ungültig gewordene Versuche. Sie erklären, warum eine Aktion nicht ausgeführt wurde.

Sallyport

Sallyport führt API-Aufrufe und SSH-Befehle für Ihren KI-Agenten aus. Die Schlüssel bleiben in einem lokalen Tresor auf Ihrem Mac; Sie geben jeden Lauf frei, und jede Aktion landet in einem versiegelten Journal.

© 2026 Sallyport · Open Source unter Apache-2.0 · Oleg Sotnikov