marketplace

airlock

Shows an untrusted model only files you choose.

needs

pairs with

Lets the Author try an experimental tool on a slice of their record they choose, without letting it near anything else they own. It reads only the files they select, and whatever it sends back arrives as untrusted material.

Module ID

github:benmowinckel/alexandria#factory/systems/airlock

What it does

Airlock gives one experimental tool a bounded Alexandria projection plus an untrusted return path. It has three surfaces:

  • context/ contains only files deliberately selected by the owner.
  • inbox/ accepts file writes; a tool on the Author's team keeps its team work under inbox/team/.
  • airlock-capture GitHub issues accept tools that can create issues but not files.

Every return enters the normal capture folder as trust: untrusted, except team work under inbox/team/, which goes to files/vault/team/<tool>/ for the executive (the team module), marked the same way. It has no automatic authority to change files, invoke tools, or become canon. A wholly public Library projection may refresh automatically. Any other projection requires the Author's approval of the room's plan: Library pages they approved for another audience (members, invite, a group) then follow the bytes they approve for that audience, and every other file is pinned to its exact bytes, so the room stays frozen as a unit until changed private bytes are reapproved.

The structural boundary

The wall is a separate GitHub account, not a repository label. Some tools request account-wide GitHub access. A private repo inside the Author's normal account would therefore expose every repo that account can reach.

The dedicated Airlock account holds one private repo per untrusted tool, each named for that tool, and belongs to no GitHub organizations. It receives no Apple login, sovereign-repo credential, private Git history, or unrelated repository. The signed controller checks the credential identity, expected app-named remote, organization list, repository visibility, and complete accessible-repository list before every fetch, push, or issue import (the session-start drain checks once per run, before its first): every repository that account can reach must be one of the Author's own declared Airlocks. A remote created under the older <tool>-airlock spelling is the same Airlock and still passes.

Each tool gets its own room, and the grant is what keeps it there. Scope every tool's access to its own repo. A repo-scoped grant reaches nothing else in the account even though neighbours exist. An account-wide grant does reach them, so a tool that demands one signs in as the Airlock account itself, reads every room, and is told to write only to its own, which keeps clear what came from whom as long as it does. Never make it a further account, since GitHub allows each person one free personal account and one machine account, and a third can put the main one at risk. The honest cost of the shared account is that the wall between rooms is the grant, and for a tool signed in as the Airlock account only an instruction, while the wall between the Airlock account and everything the Author owns stays structural.

On the computer each room has its own name (airlock for the first, airlock-<name> for each after it), state, approval and repository, and every session start imports them all. A new room never replaces another, and never shares another's checkout or repository; one room that cannot be read is reported and never stops the others importing. To retire a tool, import its final return, revoke its grant, then delete or rebuild that repo. The others are untouched.

The selected projection is the content. The private Git repo is only a replaceable transport and write buffer. App identity names the disposable repo for legibility and provenance; the separate account remains the structural wall.

Human use

The Author opens the trusted model on their computer and types Airlock this new tool: <name or URL>, or pastes in the request from the untrusted-tool door on https://alexandria.place/loop. That is approval to prepare the local projection and the one app-named repo, in a room of the tool's own that leaves every existing room as it is. The trusted model then hands the Author one ready-to-send message for the new tool with the real repository address filled in, and once the tool has written a labelled test note, imports it and checks it reached the record. Any private selection is shown with its exact content hash and separately approved before export. GitHub requires the human to create/sign into the separate account and approve or revoke third-party access; the trusted agent handles the files, checks, and commands around those unavoidable human steps.

The signed controller is airlock.py, fetched through the verifier as scripts/airlock.py; exact commands and consent boundaries are in system/.optional § airlock.

Operation

The controller accepts only explicit regular text files under files/, and requires the Author's approval of the room's plan whenever any selected file is not already public Library material. It rejects path traversal, symlinks, binary or oversized files, unapproved private-byte changes, changed exported context, changed protected paths, rewritten history, the wrong GitHub identity, a generic or wrong app repo, organization membership, and access to any second repository.

At import it fast-forwards file returns, verifies the exported projection byte-for-byte, wraps both return channels as untrusted captures (team work as untrusted team notes), and closes an issue only after its local capture exists and, while the Author's backup is on, only once that capture is in the backup. It may then regenerate the selected context from local ground truth, but only while the Author's approval still covers it (beyond public pages, an approval the Author recorded themselves outside the sandbox with permission.sh grant <room>): every Library page at bytes approved for its audience, and every other file at its approved bytes. Changed private bytes never auto-refresh, and nothing the model writes widens what leaves.

The honest limit is content: an experimental tool can return malicious instructions. Airlock makes those words untrusted data; the trusted local model must still review rather than obey them.

OFF

status shows the account, current occupant, repo, hashes, issue label, and import counts. off disables that room's local refresh and import. Revoking the current app removes its GitHub access, except for a tool signed in as the Airlock account itself, which is also signed out, with any app, token or key it added to the account and anything it left on any room (a collaborator, deploy key or webhook) removed, and the account's password changed if it ever held it; deleting or rebuilding the disposable repo clears its returned history before the account is reused. The sovereign source remains untouched.

Product boundary

This is a personal module that reaches outward, so it waits for its own yes: never part of Foundation, default setup, or onboarding. Visibility in the marketplace does not activate it.