Skip to main content
Glama

AIRLOCK

Nichts erreicht die Produktion, ohne die Schleuse zu passieren.

Eine Change-Control-Konsole für irreversible Produktionsarbeit. Jede gefährliche Änderung — eine Schema-Migration, eine Massendatenkorrektur, ein Löschantrag (Recht auf Vergessenwerden), eine Erstattung, eine Gewährung von Produktionszugriff, vierzigtausend E-Mails — wird in englischer Sprache beauftragt, zuerst gegen eine Schattenkopie des echten Systems ausgeführt, in einer Sandbox bewiesen und erst danach mit den dazugehörigen Belegen einem Menschen zur Genehmigung vorgelegt.

Entwickelt auf TrueForge für den Agent Harness Hackathon, 24.-30. August 2026.


Die Idee in einer Regel

TrueFoundrys Schlusssatz auf der Hackathon-Seite ist „Bauen Sie den Agenten, dem Sie root anvertrauen". AIRLOCK ist die wörtliche Antwort: ein Agent, der sich so verhält, als hätte er kein Root bekommen, und das jedes Mal beweist, bevor er um etwas bittet.

Jedes andere Genehmigungs-Gate ist "der Agent sagt, dass es X tun – klick Ja". Das verlangt von einem Menschen, einem Plan zu vertrauen. AIRLOCKs Gate kann erst gekringhen werden, wenn der Agent ein Zertifikat erstellt hat, und es gibt zwei Arten:

Das Undo-Zertifikat – für umkehrbare Änderungen. The Agent wendet die change on a Schattenbranch an, Rollback, and then die tables a third time per the checksum, and proves it the data is the Ausgangszustand zurückgekehrt. Er hat es already did, and regretted, and hier sind die matching Checksummen. Jetzt darf er fragen.

The Scope-Zertifikat – für wirklich irreversible Änderungen. You cannot prove a deletion is rückgängig, so belegt the Agent the opposite: exactly what for all Systeme destroyed, and nothing else – plus an explicit exclusion list, what he deliberately mit the system? He cannot promise that you are backkam. He can promise that he knows exactly what "das" is.

certificate.status !== "PROVEN"  →  the approval gate is never offered.

Nicht ausgegraut. Keine Warnung. Nie gelehdet.

Das ist ein Typ, kein if

Das Approve-Steuerelement erwartet einen ApprovalGrant. ApprovalGrant trägt ein modulprivates Symbol, das nur openGate() erzeugen kann, sodass es keinen Wert gibt, den could ein Entwickler, to exposure an approval for an unbewiesene Änderung–not by accident, not even deliberately, without itself to change the gate.

// packages/contract/src/gate.ts
const GATE_WITNESS: unique symbol = Symbol('airlock.gate.witness');

export interface ApprovalGrant {
  readonly [GATE_WITNESS]: true;   // unforgeable outside this module
  readonly irreversible: boolean;
  readonly seals_required: number;
  readonly final: boolean;
  // …
}

Sechs Versuche, wildcard zu fälschen, sind in gate.typetest.ts as Compile-Fehler asserted. If someone the type weak, the expected errors disappear, tsc reports an unused @ts-expect-error, and the build fails.

Die same Regel also server-side. A Freigotte the HTTP API, without browser, will be identically refused:

$ curl -XPOST localhost:3000/api/dossiers/dos_currency_fix/decision -d '{"decision":"approved"}'
{"error":"CERTIFICATE_FAILED","message":"Verification ran and failed. This change cannot be approved from this dossier."}
403

$ # …and a dossier that lies, claiming match:true with checksums that differ:
{"error":"CHECKSUM_MISMATCH","message":"The data did not return to its starting state after rollback."}
403

AIRLOCK never trusts the matching match flag of the Verifizier terminated. It recomputes pre === post_rollback themselves, so an Engine-Bug or a forged payload cannot open the door.

Try it out, install nothing yourself. The landing page carries a live gate: it builds a real Change Dossier from a set of controls and passes it to the real openGate(). Every combination is a genuine evaluation. Find you can find one, which open a door that it does not.


Related MCP server: mcp-nixreview

Starten

git clone https://github.com/Rohit-ATS/Airlock && cd Airlock
npm install
npm run build --workspace @airlock/contract
npm run dev --workspace @airlock/console

Route

Beschreibung

/

The Vordereingang – the argument, with two live demos in it

/console

The Operator console: DOING / WAITING / DID

/control

The Kontrollraum: Haltung, Refusals, Ledger integrity

Die Konsole initialisiert sich auf contracts/examples/ beim first start from itself, so you land on a live approval queue with eleven real changes: two ready for der Freigabe, six for six different reasons sealed, and three decided Records in a Hash-Kette versiegelt – without database, no API key, no sign-up.

These eleven are console fixtures. They exercise the certificate card, the queue, the policy engine and the ledger. no schema belegs for each database, and the unentschiedenen false when scheduling on the current time, because a certificate has a fresh window and an forever abgelaufenes Demo beweist nothing. AIRLOCK_NO_SEED=1 Starts of their empty.

Um rather than the Agent as the fixtures to drive, he says at a TrueForge-Server aus:

npx @truefoundry/trueforge@latest              # http://localhost:8790
NEXT_PUBLIC_TRUEFORGE_BASE_URL=http://localhost:8790 npm run dev --workspace @airlock/console

On Windows use Docker. TrueForge 0.1.4 does not start natively on Windows (Only URLs with underscore in: file, data, and node are supported… Found protocol 'c:'), and its local sandbox fallback is only macOS/Linux. See docs/TRUEFORGE-NOTES.md.

What is it in / Subjects

Der Agent has exactly one Zugang

AIRLOCK is a MCP-Server delivered (packages/mcp). Eoin Gelingen is makeggesimp, einsätze "least privilege" structural, not just an expectation:

{ "name": "airlock",
  "command": "npx", "args": ["-y", "@airlock/mcp"],
  "enable_tools": ["@all"],
  "require_approval_for_tools": ["airlock_request_approval"] }

The Agent can read the Policy, open a change, attach a proof and ask to human. That is all verbs he has. There is no workzeug, that applies a change to the production, and the one workzeug, that brings a change forward, is backpressed by the harness, until a person responds.

Production connectors are @read-only mounted in parallel, and because TrueForge-Subagents inherit the MCP scope onto the Root-Agent, change applies to every subagent automatically: kein Principal runs; can the production without a person. That is in the .github/workflows/...? Nein: scripts/check-agents.mjs in CI asserted, damit kann es nicht driften.

Sieben Klassen von Änderungen

The test is not "is it a database write" but "if it goes wrong, can you take it back?" Fourzchschentausend underway emails is so irreversible as to fall a column, and considerably than worth to apologize.

Änderungsklasse

Zertifikat

Genehmiger

Obergrenze

Schema-Migration

UNDO

1

Datenungsoperation

UNDO

1

5.000.000 Datensätze

Löschung / Erasure

SCOPE

2

1.000 Personen

Zugriffsgewährung

SCOPE

2

jede Gewährung muss abliefe

Geldbewegung

SCOPE

2

£25,000

Massenkommunikation

SCOPE

2

50.000 persons, Ruhezeiten erzwungen

Infrastrukturänderung

his kit

2

Freitag- bis Montag-Change-Freeze

Policy: die zweite Frage

Das Zertifikat beantwortet yes "What, ersetzung of thischange itself?"; The Politics can answer another: "this change is not sparting at all, let alone for all, and "The Durchschnitt can do that does not be answered, because it is not property of the change, but property of the organisation.

Beide same evaluation of openGate—so a change, the a 1:1 thoroughly unwoven and getting not permitted, for the second reason is "sie gilt and is stated precise. The details in docs/POLICY.md, generated from the policy, so that the two cannot disagree.

Four rules are currently in: mentioned:

  • Ein Beweis ist eine unverzeilage Ware. Damit a fresh window printed a certificate a system that does not exist. Ten minutes for a score, thirty for a migration.

  • Produktionsdrift. Before the gate opens, AIRLOCK re-validates the checksums of the production against the state from which proof is derived. If he even says someone gave further migration, the change is sealed — even wenn der Drift-Checker selbst, alles ist normal, gesagt. A threat claim is believed to be true; a safety claim is recalculated.

  • Ein Quorum counts people, not clicks. Signatures are stored per identity, so same signer signs twice is one person – and the person who requested the change can never be there.

  • Kein Dauerhafter Produktionszugriff. Each grant must have a "expires" field, so the default status of the system is that no one has the keys.

Das Ledger is tamper-evident

A change-control system whose audit log can be edited is a change-control theatre show. Every decided change is closed with hash of the previous one, so editing any historical record destroys every link that follows it:

$ npm run verify:ledger
  ok  #000  dos_orders_index         a41f9c02be7d8e5f31c4…
  FAIL #001  dos_gdpr_batch          9e02cc71a4bb0d3f2871…
         fault      : content-modified
FAIL — the chain breaks at record 1. Every record after that point is no longer trustworthy.

This does not change the ledger (nicht unabsifrierbar) – anyone who can reconstruct the file can reconstruct the whole chain. What makes it possible is a "tampering visible" for anyone with a older copy of a single hash, and the property that counts because your auditor is not the person who has been handled.

Individual receipts from a decouple and independent verify, with no console: GET /api/dossiers/{id}/receiptnode scripts/verify-ledger.mjs receipt.json.

The landing page lets it in your browser. If you rewrite a record, you will see the chain break.

The three-zone console

The Savile Row rubric asks for an interface showing what the agent is doing, what it is waiting for, and what it has done – and asks before the irreversible step. These are therefore the three zones, exactly named:

  • DOING – the live Run: Subagent-Lanes in parallel, each with its own model and running costs, the Sandbox-Log streams underneath, tool calls resolved in life.

  • WAITING – the approval queue: each change against the people or in the queue, on what urgent it, how much of the signatures it still need, and how long it has been waiting.

  • DID – the immutable change ledger: who asked, who approved, which certificate, defined checksum and the receipt, which seals it.

The control room

/control is the other audience. Not "shall I take this one?" but "what is this system holding, what has it rejected, and can I still trust that record of what it did?"

The headline trend is how many this is the gate refused not approved – an "empty" queue is not proof of security; a greeting of stopped change with reasons is the one. It also re-verifies the ledger in the browser, rather than trusting a server that says, says that it is "MyEverything ok".

The Harness Panel

A persistent panel lists all 22 TrueForge capabilities. Each lamp is "dark", until a real harness event props it vesteckt, then lights up with a timestamp and a link to the step at that time.

A lamp cannot be lit from application code. The only writer is detectors.ts, fed by a [passthrough] observer around the real TrueForge event stream in observedServer.ts. Events are observed and passed on unchanged – never synthesized, never reordered, never dropped. A run that does not exercise a capability ends below 22, and that lies correct.

Bar "Hat dynaqua pelitions legit" happen nothing, "hiding what was not happened would make the count meaningless; showing it makes the lit that one believe worth. The remaining rows stay "dark" intentional. On the landing side, every lamp is dark because no run took place there.

See docs/CAPABILITIES.md – generated from registry, so what it says and what the panel can do, can't drift apart.

The certificate card

Verdict banner, magnitude, effective policy and its objections, signatures, Forward- and Rollbackall behaviours side by side, all who are women affected with real recordfulness, Lock-Profile and the warning of the table rewriting, the checksum triple, the drift test, the blast radius of the entire codebase, the exclusion list, costs per model, the receipt, and the decision.

Of the checksum triple, the argument makes "visible": row 1 and 3 are brackets; row 2 solely smoke is because it should differ; and a match (unsecured) is exactly what it character with the hash is diffently marked, not a red X.

Notfallzugriff

Per Policy geschützt, standardmäßig deaktiviert, und es öffnet das Tor nichtBreakGlassOverride trägt ein anderes privates Symbol als ApprovalGrant, und keine Funktion akzeptiert beide. Was es tut, ist festzuhalten, dass ein namentlich genannter Mensch eine versiegelte Tür umgangen hat, mit einem schriftlichen Grund von mindestens 40 Zeichen, dauerhaft, in derselben Hash-Kette wie alles andere.

Das Argument dafür: Menschen tun das ohnehin. In jeder Organisation gibt es einen Moment, in dem der sichere Pfad nicht verfügbar ist und jemand stattdessen eine psql-Sitzung öffnet. Eine Control Plane, die das Gegenteil behauptet, verhindert das Override nicht — sie sorgt nur dafür, dass es keine Aufzeichnung davon gibt. Zwei Schalter sind erforderlich, um es zu aktivieren, und ERASURE, MONEY_MOVEMENT und COMMS_BLAST verbieten es ausdrücklich.


Architektur

contracts/dossier.schema.json     the Change Dossier — the one contract everything shares
packages/contract/                types, the gate, policy, receipts, capabilities, detectors
  src/gate.ts                     the invariant, as an unforgeable type
  src/policy.ts                   quorum, ceilings, freshness, freezes, no standing access
  src/receipt.ts                  the tamper-evident hash chain, isomorphic
  src/detectors.ts                the ONLY thing that can light a lamp
  src/capabilities.ts             the 22, each with its load-bearing use and its evidence
packages/mcp/                     AIRLOCK as an MCP server — the agent's one doorway
apps/console/                     Next.js 15, React 19, Tailwind v4
  app/page.tsx                    the landing page
  app/console/                    the three-zone operator console
  app/control/                    the control room
  src/server/observedServer.ts    the passthrough tap on the real TrueForge stream
agents/                           four agent specs: least privilege, model routing
skills/                           seven skill packs, one per domain the agent must not improvise

Die Konsole ist das SDK. TrueForgeUI akzeptiert eine benutzerdefinierte Layout-Komponente, die innerhalb ihres eigenen Provider-Stacks gerendert wird, und AIRLOCK wird daher als layout={AirlockConsole} übergeben — Transkript, Composer, Thread-Liste, Karten für Tool-Freigaben, Karten für Benutzerabfragen und der MCP-OAuth-Bildschirm sind allesamt eigene Komponenten von @truefoundry/trueforge-ui, die ein neues Theme erhalten haben. Es ist keine Nachahmung, die daneben hergestellt wurde.


Ehrliche Anmerkungen

Drei Dinge im ursprünglichen Plan stellten sich als von API abhängig heraus, die es nicht gibt, und sind deshalb anders gebaut statt vorgetäuscht. Ausführliche Details in docs/TRUEFORGE-NOTES.md §4.

  1. Subagenten sind dynamisch, nicht deklariert. TrueForge erzeugt sie zur Laufzeit über create_sub_agent; die Spezifikation hat keinen Block pro Subagent. Deshalb ist „vier benannte Subagenten, jeweils mit eigenem Tool-Scope“ nicht implementierbar.

  2. Tool-Scoping pro Subagent existiert nicht. Die Dokumentation ist eindeutig: „Subagenten haben Zugriff auf dieselben MCP-Tools und dieselbe Sandbox-Umgebung wie der Root-Agent.“ AIRLOCK setzt stattdessen das Prinzip der geringsten Rechte an der Agentengrenze durch — Produktions-Konnektoren werden @read-only gemountet, und der einzige Vorwärtspfad ist ein Tool auf unserem eigenen MCP-Server, das der Harness hält. Weil Subagenten diesen Scope erben, kann kein Prinzipal während eines Laufs die Produktion ohne einen Menschen berühren. Das ist eine stärkere Aussage als eine kleinere Toolbox — und sie ist real.

  3. Modell-Routing pro Subagent existiert ebenfalls nicht. Routing gibt es real an der Agentengrenze — siehe airlock-scout, airlock-privacy und airlock-treasury — und das pro Lane angezeigte Modell sowie die Kosten werden aus echten thread.created.agentInfo.model- und turn.done.state.metrics.total_cost_in_usd-Werten gelesen.

Drei Fähigkeitsdetektoren hängen von Signalen ab, die wir aus den Unterlagen nicht bestätigen konnten — der Tool-Name des Code-Modus, die Markierung für die Auslagerung großer Ergebnisse und die Frage, ob ein Kompaketierungsereignis emittiert wird. Sie sind als unverifiziert geführt. Wenn ein echter Lauf sie nicht belegt, bleiben diese Lampen dunkel und der Nenner sinkt. Ein ehrliches 19/19 schlägt ein aufgeblähtes 22/22, das ein Prüfer durch das Anklicken einer Lampe widerlegt.

Zwei gefundene Upstream-Bugs

  • @truefoundry/trueforge-ui@0.2.4 hat einen Abhängigkeitskonflikt: @assistant-ui/core benötigt als Peer-Abhängigkeit zustand@^5, während die OpenUI-Renderer zustand@^4 anziehen, was npm hoisted. Der Build schlägt mit 'useShallow' is not exported from 'zustand/shallow' fehl. Umgangen wurde das mit einem overrides-Block in der package.json im Root.

  • Deren styles.css enthält ein vollständiges Tailwind-Utility-Set in @layer tfy-agent-ui-utilities. Nach tailwindcss importiert, registeriert sich diese Ebene später, sodass sich das einfache .hidden des SDK gegen dein .xl\:flex durchsetzt, unabhängig von der Media Query — was stillschweigend jede responsive Variante der Host-App zerbricht. Behoben mit einer expliziten @layer-Reihenfolge-Deklaration in globals.css.


Tests

npm test        # 92 tests, 11 fixtures, 4 agent specs

Vier Suites, und jede sichert eine Grundeigenschaft zu, statt eine Implementierbarkeit zu testen:

Suite

Was sie festhält

gate.test.mjs

Kein nicht-PROVEN-Zertifikat öffnet das Tor, bei jeder Kombination aus Klasse, Status und Betrachter

policy.test.mjs

Quoren zählt Personen; Einfrierungen werden nach der Londoner Wanduhrzeit ausgewertet; ein Sicherheitsnachweis wird neu berechnet; Break-Glass kann niemals eine Genehmigung werden

receipt.test.mjs

Diese Operation wird erkannt – das Bearbeiten, Umordnen oder Löschen schwerer TLS; pro versiegelten Datensatz, genau dort, wo es geschah, und an der genauen Stelle im Record

harness.test.mjs

Nur ein echtes Harness-Ereignis lässt eine Lampe aufleuchten — Rauschen, wiederholte Konnektoren und Prosa, die ein Grafikelement nur erwähnt, lässt nichts aufleuchten

mcp/server.test.mjs

Genau ein Tool ist destruktiv, und genau das wird für die Genehmigung zurückgehalten;

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Pauses AI agent execution and routes approval requests to humans via Slack or email, with cryptographically signed proof of the human's decision.
    197
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A safety gate for agent-proposed NixOS configuration changes, grading security-relevant option deltas, attesting closures for vulnerabilities, and requiring human approval with a tamper-evident audit ledger.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A human-in-the-loop governance interlock for AI agents. Agents propose changes, a human countersigns the exact plan, and then it executes stage by stage with precondition checks, verification, and auditing.
    Apache 2.0

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Rohit-ATS/Airlock'

If you have feedback or need assistance with the MCP directory API, please join our Discord server