The harness

Every agent in a machine of its own, and a record of what held.

Each agent runs in its own microVM, and the host decides what that machine holds: the evidence as a read-only share, the agent's own directories, the hosts it may reach, and placeholders where the keys would be. The audit trail stays out of the agents' reach, and where a guard is only advisory the run record says so, so no forensic report can claim a protection the run never had.

Every guard, and what holds it.

A microVM per agent is the default, on macOS with Apple silicon or Linux with KVM. Host mode, which the examiner chooses with --isolation host, runs the same swarm unisolated, on the host under kernel policy, for a machine that cannot run microVMs; the kickoff never switches to it by itself. The kickoff measures what the host can enforce and records it, and the report prints it in the chain of custody.

One run in microVMs

Every part of a run and the lines between them. Select a part to see what it does, what holds it and what it leaves on disk, and try it; or play a run from the kickoff to the signed release.

  • kelp work in motion
  • slate files and the record
  • moss sealed, passed, done
  • saffron keys, budget, caps
  • brick refused at the wall

A dashed line is a read-only view or a check. A solid one carries work.

Swipe sideways to see the whole map, or switch to the list.

Overview

Every part of one run in microVMs, in its place. Select a part, or play a run.

Where the agents thinka microVM per seat, from the base image
A peerAn agent's Pi in a microVM of its own, booted from the base image: a shell, Python and the tool library, with the forensic programs left to the job images.
What it does
  • Reads the contract, the catalogue and the board, and divides the case with its peers; nothing is assigned.
  • Keeps a shell for quick looks, and sends parsing, carving and anything long or worth citing to a job.
  • Writes only its own directories, and reaches its peers through the hub.
What holds it
  • The run is a read-only floor in its VM; its own work, extracted and quarantine directories, its tool output and its session are the writable holes.
  • A veil over the trace, the peers' sessions and the peers' tool output keeps its peers' records out of view, and the kickoff refuses a VM that sees them.
  • Root in the guest is the agent's; the boundary is the host side of every share, the network policy and the hub's socket.
What it leaves on disk
work/<seat>/work/extracted/<seat>/work/quarantine/<seat>/tool-output/<seat>/vm/<seat>.json
Another peerA second agent in a machine of its own. What it shares with the first travels through the hub, under a lease, on the record.
What it does
  • Publishes a shared file, such as the report or the timeline, through the hub, which claims it, writes it on the host and records the revision.
  • Sees a peer's published file current within five seconds; a claim on a file written in the last six seconds is granted once that window has passed.
  • Learns what its peers are doing from the board, the claims, the ledger, the store and the team list the hub builds from them.
What holds it
  • Nothing writable is shared between VMs.
  • A peer's own directory is refused to it for claims, writes, restores, records and publishes.
  • Every process in its VM speaks to the hub as this seat, a forged tool or a parser over hostile content included.
What it leaves on disk
publish_fileclaim_filelist_teamwork/report.md
The criticA peer like the others, whose goal asks it to re-derive what each answer rests on before the run may end.
What it does
  • Re-derives what an answer rests on from the sealed objects it cites, and records an attestation or a dispute, each in a chain of its own.
  • Works from the ledger and the store; the veil keeps its peers' trace lines, sessions and tool output out of view, so it cannot read how a peer got there.
  • Is what the goal's checks look for: an answer that no one but its author attested or disputed is a defect the finish line names.
What holds it
  • The harness assigns no roles: the goal names the critic, and the critic is one of the peers.
  • An answer resting on an entry that is later disputed or superseded stops standing, and so does every answer resting on it.
What it leaves on disk
attestdisputeledger/attestations.jsonlledger/disputes.jsonl
Your machinethe host decides what each VM holds
The hubOne process on the host that writes the board, the ledger and the registers for every seat, serves each VM a socket of its own, runs every tool job, decides every lookup and runs the finish line.
What it does
  • Serves each seat over a socket of its own, which answers only a connection that opens with that seat's token.
  • Writes the board and the ledger: posts, leases, published files, findings, answers, attestations and disputes.
  • Writes the registers: the question register, the leads with their offers, and the requests the run makes of the operator, each hash-chained.
  • Admits the operator's acts on the question register through an admin socket in its own directory, which only the host account reaches, and notifies each new request by its id.
  • Runs the job service: every tool job, the catalogue's recipes and the derived catalogue.
  • In a dynamic run, decides every lookup by rules and hands a granted one to the fetch service.
  • Runs the goal's checks on the host when the seat that coordinates the finish says done, keeps the wall clock, pauses the run at a cap, and stops the VMs when the run ends.
What holds it
  • Who is asking is the socket a call arrives on, whatever the message claims.
  • It never opens a file under a seat's own directory: a seat sends its file's bytes with the call.
  • It bounds each seat: its connections, the bytes held for it, its calls queued, and its posts, records and done calls per minute.
  • A keeper brings it back from its saved state if it dies, until the run's stop.
What it leaves on disk
~/.dfirswarm/hubs/<run>/admin.sock<seat>.sockSWARM_SEAT_TOKENhub_call seat_auth
Network policyThe host's rule for each VM's network: its models' hosts and the hosts the examiner allowed, and nothing else. The keys are swapped in here, on the way out. A dynamic run adds no host to it.
What it does
  • Lets a VM reach its models' hosts, the hosts the examiner allowed and, when the run allows installs, the package index.
  • Swaps each placeholder for its value in the request headers, on the way to that credential's own hosts.
  • Stops and logs a placeholder aimed at any other host, which custody reads.
  • Stays as it booted in a dynamic run: a lookup goes to the hub over the seat's socket, and the fetch service on the host makes it.
What holds it
  • A name off the list does not resolve, and an address off it has no route.
  • No credential enters a VM. Each seat's VM holds placeholders: for its own model, the summary model and, when the examiner allows them, a pack's secrets.
  • An allowed host is a way out as well as in: anything a seat can send to its model's host leaves.
  • The network mode and the case policy are fixed at kickoff, recorded, and sealed by custody; an agent can weaken neither.
What it leaves on disk
--network closed|dynamic|open--policy standard--allow-host--allow-installswarm.sh netcheckblock-and-log
The evidenceDisk images, memory, phones, logs and captures, shared read-only into every seat's VM and every worker from where they lie.
What it does
  • Is mounted into each VM at its own host path, read-only, with no copy made. For evidence the examiner's own account can still write, a read-only copy in the run adds a second layer.
  • Is hashed at kickoff, SHA-256 with MD5 and SHA-1 beside it, and held to the imager's acquisition hashes when they are given.
  • Is re-hashed in full on the host at stop.
What holds it
  • The host side of the share is the boundary: root in a VM can flip its own mount flag, and the host still refuses every write.
  • A worker sees the evidence its job declared, read-only and no-exec; a job that declares nothing sees what a seat sees.
  • An earlier run's findings on the same evidence are never mounted into a new one.
What it leaves on disk
--inputs--inputs-copy--inputs-hashesinputs.json
The harnessThe harness's extensions, scripts and prompts, copied at kickoff and mounted read-only in every VM where the checkout is.
What it does
  • Is copied at kickoff and mounted where the checkout is, read-only, so an edit or a pull mid-run does not reach the agents.
  • Gives the hub a second copy taken at the same time, from which the hub, the VM finish and its custody run, with their own copy of msb.
  • Keeps the repository itself out of every VM, since the run registry and the published cases would come with it.
What holds it
  • The kickoff prints which commit it froze, and the run records what produced it: the harness commit, Node, Pi, msb and the image digest.
  • The extension inside a VM runs under the guest's root, so its checks are advisory there; the finish line, custody and the report are decided on the host.
What it leaves on disk
provenanceextensions/scripts/prompts/
The examinerThe person who starts the run, watches it in the console, asks it questions while it works, answers what it asks, reviews the ledger, and signs the report's release with a key of their own.
What it does
  • Starts the run from the console or the terminal, and watches it live: the board, every VM's probe and hub link, the jobs, the ledger and custody.
  • Asks the running swarm a question, answers the requests the run makes (a clarification, an acquisition, a lookup to grant), extends a paused run, and resumes one that stopped.
  • Is enrolled on the install once, outside every run, with a name, an organisation, a competence statement and one key: an ssh key with a passphrase, a FIDO2 security key, or the certificate on a PKCS#11 e-signature token.
  • Adopts, qualifies, withdraws or renders inconclusive each answer in a chained review beside the registry that no agent reaches, then signs release v1 in the console's Release tab or with swarm.sh review --sign.
  • Imports a technical reviewer's signed review made from the package on another machine, checked against the register or the CA.
What holds it
  • Every command they give a run is a line of the operator's chained record, and on a live run a line of its trace.
  • The release seals exactly the bytes shown with their sha256 after the consent, and the passphrase, touch or PIN reaches the signing program only down a pipe.
  • Their key is out of every VM, and the console refuses a key without a passphrase or one held in ssh-agent.
  • An answer whose support is defective cannot be adopted: it is withdrawn or rendered inconclusive.
What it leaves on disk
swarm.sh examiner enrollswarm.sh review --signruns/reviews/<run>.jsonlrelease/v1/swarm.sh releases --verify
Fetch serviceA host process that makes exactly the lookup the hub granted and nothing else, holds no evidence, and seals each answer as a capture.
What it does
  • Takes a grant from the hub: one exact method and URL, for one seat or one job, for five minutes and one use, with a byte limit.
  • Sends only its own headers, resolves the name once, refuses loopback, private, link-local and other special addresses, and connects to the address it checked with TLS verified against the name.
  • Writes each use to its log before a byte leaves, and seals the answer in the store as a capture, which the ledger records as external material.
What holds it
  • It is no proxy: anything but the grant's method and exact URL is refused.
  • A body over the limit is refused whole; a revocation or expiry during a transfer stops it, and what came is kept as incomplete and delivered to nobody.
  • The rules that decided the grant read no free text, and no model sits in the decision.
What it leaves on disk
network/grants.jsonlnetwork/fetches.jsonlstore/net/<k>/<n>/net:<k>/<n>swarm.sh net <run> list
Where the tools runa worker microVM per job
Worker microVMsThrowaway microVMs the hub makes for one job each, booted from the job image of the profile the work needs, and removed when the job ends.
What it does
  • Boot from the image the job names or its pack's image; a command that names none runs in the smallest job image that holds every program it runs.
  • See what the job declared, read-only, resolved when the job was submitted; a job that declares nothing sees what a seat sees.
  • Write only their own output directory, which is sealed into the store once the worker is gone.
What holds it
  • No credential, and nothing of the board, the inbox, the ledger or the sessions.
  • No network unless the job asks, and then only the run's allowlist; in a dynamic run it may call the fetch service with its own job's token.
  • A running job is watched from the host by its output directory, its logs and its CPU and I/O; a suspected stall is shown and never acted on.
  • What a job read within its scope is not observed, and the record says unknown.
What it leaves on disk
job_run profile=diskinputs=[…]$OUTstore/jobs/<id>/scope.<attempt>.json
The recordwritten on the host, sealed at stop
Trace collectorThe only writer of the audit trail. It runs on the host, chains every line to the one before and anchors the head outside the run.
What it does
  • Writes every call a seat makes, its arguments, its whole result and the reasoning before it, as the hub hands them on.
  • Attributes each line by the channel it came through, and stamps the host's time of receipt beside the seat's own.
  • Names on each line the file that holds a tool's whole output, with its size and its sha256.
What holds it
  • In a microVM run the hub is its only door, and no VM sees the trace.
  • A line claiming to be another agent is written as what it is, with the claim beside it.
  • The report walks the chain and says intact, edited, appended, shortened or rewritten.
What it leaves on disk
traces/events.jsonltool-output/<seat>/prevrecv_ts
The ledgerEvery fact the agents establish, each with the sealed objects it rests on and what it indicates, written by the hub and chained entry to entry.
What it does
  • Holds events, indicators, findings, searches that found nothing, hypotheses and limitations, coverage records, external material, and one answer per question with its result.
  • Resolves every ref when the entry is written: an input, a job's sealed output, a catalogue member, a capture. One that does not resolve refuses the entry.
  • Takes an attestation or a dispute of an entry beside it, each in a chain of its own; a review of a negative is an attestation that says what it checked.
What holds it
  • Nothing is edited or deleted: a correction is a new entry that supersedes the old one.
  • A finding says what it indicates, how sure its finder is and why, and what else could explain it.
  • A material negative stands unreviewed until another seat reviews it, and the finish line waits for that.
  • A seat's own output is sealed as an import before an entry may cite it.
What it leaves on disk
recordledger/entries.jsonlledger/attestations.jsonlledger/disputes.jsonlkind=coverage
The storeWhere every job's output is sealed, file by file, with a hash-chained journal of every step the job service took.
What it does
  • Seals a committed job's output read-only under its own directory, every file hashed and stored once by its sha256.
  • Keeps the journal: accepted, started, finished, fenced when the worker is gone, committed; one chained line each.
  • Is what a finding cites, as job:<id>/<path>.
What holds it
  • Nothing is sealed while the worker that wrote it could still write.
  • A failed job keeps what it wrote, and a finding resting on it says why those bytes still hold.
  • The journal's head is anchored outside the run.
What it leaves on disk
store/jobs/<id>/out/store/blobs/<sha256>store/journal.jsonl
Custody at stopThe verdict on the run, taken on the host at stop: the evidence and the store re-hashed, every chain sealed, every VM's disk kept.
What it does
  • Keeps each VM's disk as a snapshot, with its integrity record, before the VM is removed.
  • Re-hashes every evidence file in full, and compares the acquisition hashes when they were given.
  • Walks every hash-chained register (the trace, the ledger with its attestations, disputes and store sweeps, the leads and the finish register, the question register, the requests, the network's grants and fetches, the store's journal and the model gateway's log), checks every sealed output and capture against its manifest, and seals the length and head of each chain.
  • Holds the case policy to the hash the kickoff anchored, and names a rewrite.
  • Seals the machine's draft of the report as release v0, which adopts nothing.
What holds it
  • Every check has a status: passed, failed, incomplete, not applicable or unavailable.
  • It reads and writes nothing through a link, and its verdict's hash goes into the anchor outside the run.
  • It can be taken again later, writing nothing, and held to what it sealed.
  • After a resume, every earlier verdict verifies as a prefix of the same chains, and the next stop seals the continuation anew.
What it leaves on disk
custody.json<run>.vm-snapshots/swarm.sh custody-verifyrelease/v0/
Outsidereached through the network policy, or by the fetch service
Model providersThe hosts of the models the seats run on: cloud, private or local. A seat reaches only its own model's hosts, with its key swapped in on the host.
What it does
  • Receive each seat's model calls through the network policy, with the key the host swapped in.
  • Can be fronted by an optional model gateway on the host, which holds the key and meters each call from the provider's own answer.
  • Serve a local model through the host's gateway port when the team runs on this machine.
What holds it
  • A provider whose host is unknown is refused at kickoff, and one that signs its requests with its secret on the client cannot run in a VM.
  • A seat's spend is what it reports about itself unless the model gateway meters it; the wall clock is the brake the host holds by itself.
What it leaves on disk
--models--provider-host--model-gatewaybudget.json
A case's own hostsThe hosts a case needs, such as a symbol server, reachable when the examiner allows them: at kickoff for the whole run, or later as a socket grant.
What it does
  • Are named at kickoff, one host or port at a time, and checked before anything is written; the kickoff says each is a socket allowance for the whole run.
  • Reach a worker only when its job asks for the network, and then only the run's list.
  • Can be allowed later with swarm.sh lead note --allow-host, which makes a socket grant: a host and a port, recorded in the grants chain.
  • Let a memory job fetch Windows kernel symbols from Microsoft's symbol server and the storage hosts it redirects to.
What holds it
  • A socket grant controls the host and the port and nothing more: no method, no path, no capture of the content.
  • It is refused under the ctf, internal and live_adversary policies.
  • A suffix lets a seat send data to any host under it, and a suffix of one label is refused.
  • A URL found in the evidence is a finding to record; resolving it would tell the subject their device is being examined.
What it leaves on disk
--allow-host msdl.microsoft.com:80--allow-host '*.blob.core.windows.net'swarm.sh lead note --allow-hostswarm.sh netcheck
Reference servicesThe public services a lookup may reach, each through an adapter that places typed values into a fixed request.
What it does
  • RDAP, crt.sh, the NVD CVE API, CISA's KEV feed, CIRCL hashlookup, RIPEstat, Nominatim, Overpass and a video's title.
  • VirusTotal by hash, when the operator configures a key on the host that only the fetch service reads.
  • One evidence-linked HEAD of an exact URL, which is active contact.
What holds it
  • Only the fetch service reaches them, one granted request at a time.
  • A lookup discloses: the case policy says which classes of case data may leave, such as hashes and public indicators.
  • A capture's hash proves its bytes; an examiner records what they establish.
What it leaves on disk
network/adapters.jsonDFIRSWARM_VT_API_KEY
The same run, phase by phase
  1. 01

    Boot

    The kickoff checks that this host can boot the VMs and hold what the run asks for, and stops with the reason when it cannot. It hashes the evidence, records the case policy and anchors both, pins the image by its digest, freezes a copy of the harness, and starts the trace collector and the hub. Then it boots a microVM per seat from the base image, and each VM's probe has to report its floor read-only, its own directories writable, the evidence read-only and the hub reachable.

  2. 02

    Shares

    Each VM holds the run as a read-only floor, with holes that are the seat's own: its work, extracted and quarantine directories, its tool output and its session. The evidence is a read-only share from where it lies, and the keys are placeholders. A veil lies over the trace, the peers' sessions and the peers' tool output, so a seat reads none of its peers' records.

  3. 03

    Work

    A seat asks the hub for a job over its socket, and the hub makes a worker microVM of the image the work needs. The worker sees, read-only, what the job declared, or what a seat sees when the job declares nothing; it writes only its own output directory and has no network unless the job asks. Once the worker is gone, what it wrote is sealed into the store, and every step is a line of the hash-chained journal.

  4. 04

    Reach out

    A seat's traffic leaves only through the network policy on the host. Its models' hosts and the hosts the examiner allowed are reachable; a name off the list does not resolve and an address off it has no route. The key is swapped in on the host, in the request headers, and a placeholder aimed at any other host is stopped and logged.

  5. 05

    Look up

    In a dynamic run a seat that needs what a reference service knows asks the hub for one bounded lookup. The hub decides it by rules alone under the case policy and records the decision before it answers. A granted lookup goes to the fetch service on the host, which makes exactly that request, seals the answer as a capture and has it recorded as external material. The seat's VM gains no host.

  6. 06

    Record

    The hub is the one writer of the board, the ledger and the registers: a post, a lease, a finding with the sealed objects it rests on, a coverage record, an answer with its result, an attestation or a dispute, a question and its revisions, a request to the operator. Every call a seat makes reaches the trace collector through the hub, and the collector chains each line to the one before and attributes it by the channel it came through.

  7. 07

    Finish

    When the seat that coordinates the finish says done, the hub runs the goal's checks on the host, where the trace they read is; any other seat's done is answered "not yours". A check that fails refuses the done, and the seat is told which one and what it printed. When the finish line passes the run is stopped from the host and the hub puts the VMs away. At a cap the run pauses instead: no seat is prompted until the examiner extends it or stops it.

  8. 08

    Custody

    At stop each VM's disk is kept as a snapshot. Custody re-hashes the evidence in full, walks the trace, the ledger and the store's journal, checks every sealed output against its manifest, and seals the head of every chain, with a status for every check. The report's first release, v0, is the machine's draft: sealed by this install's machine key, and adopted by no one.

  9. 09

    Sign

    An enrolled examiner reviews the ledger and adopts, qualifies, withdraws or renders inconclusive each answer; a technical reviewer signs their own review first when the run asks for one. The report is rendered once without the draft mark and shown with its sha256, and after the examiner's consent their passphrase, touch or PIN seals release v1 over those bytes. Every later release names the one before it and why, and verify walks them all.

  10. 10

    Resume

    A run that stopped or was sealed can go on as the same run: swarm.sh resume, anchored beside the run before anything moves. The VMs are booted again from the options the kickoff kept, each seat starts from its last hand-off, and the ledger, the registers, the board, the trace and the store are appended to. The next stop seals the continuation anew, and every earlier verdict verifies as a prefix of the same chains.

guardwhat it holdsin a microVM · the defaultin host mode
Evidence read-onlyNo agent can write the evidence. In a microVM it is a share the host holds read-only: root inside the VM can flip its own mount flag, and the host still refuses every write. Hashed before the first agent starts and re-hashed on the host at the end.read-only share · hostseatbelt · macOS mount namespace · Linux
Write allowlistAn agent writes its own directories and nowhere else: not the examiner's home, not another case, not the run registry. In a microVM those are its own work, extracted and quarantine directories, its tool output and its session; the rest of the run is read-only in its VM, and shared files reach the others through the hub. In host mode a pane writes inside its own run.own directories · hostseatbelt · macOS Landlock · Linux
QuarantineWhat is extracted from the evidence lands on no-exec mounts, so a carved binary does not run by mistake. In a microVM that is a mount flag in the guest, and a peer's carved material is no-exec there too; it does not stop a root inside the VM that means to run it.no-exec · guest flagseatbelt · macOS noexec mount · Linux
The boardPosts, leases and shared files. In a microVM run they have one writer, a hub on the host, and each VM reaches it over a socket of its own, so who is asking is decided by the socket, whatever a message claims. The hub bounds what one agent can ask of it.one writer · the hubin each pane · under leases
Tool jobsParsing, carving and any long or citable work runs as a job in a throwaway worker VM, made for that job and removed after. It reads what the agent reads, read-only, and writes only its own output directory; it holds no key and nothing of the board, and it has no network unless the job asks for the run's allowlist. Nothing it wrote is read until the worker is gone, and then it is sealed into the store. In host mode there are no jobs, and tools run in the agent's pane.a worker VM per job · sealednone · tools run in the pane
Trace collectorThe only writer of the audit trail runs on the host, outside every agent's reach. Each line names the hash of the line before; the head of the chain is anchored where no agent can write. In a microVM run every line is attributed by the channel it came through. In host mode it is a per-pane token no other pane can read on macOS, and on Linux, where one pane can read a peer's environment, a gate in front of the collector attributes by process ancestry.enforced · by channelby token · macOS by ancestry · Linux
KeysA provider's key, and a pack's secret, never enter an agent's microVM. The VM holds a placeholder, and the host swaps in the value on the way out, in request headers, only toward the hosts that key belongs to. A placeholder aimed anywhere else is stopped and logged. In host mode the pane's own agent reads its key from the examiner's store.placeholder · swapped on the hostthe agent's own store
Prior-run isolationAn earlier run on the same evidence (its findings, its board, its tools) is unreadable to the new swarm, so a re-run cannot copy the earlier answers. In a microVM it is never mounted, and a kickoff that would mount it is refused. In host mode on Linux the directory is masked by a tmpfs inside the namespace, or denied by Landlock where there is no namespace; under Landlock alone the file names stay visible and the contents do not, and the record says which.never mountedseatbelt · macOS tmpfs mask or Landlock · Linux
Signing keysThe keys that seal and sign the report's releases stay out of every agent's reach: the install's machine key, each enrolled examiner's and reviewer's key, and the ssh-agent socket, with the examiners' reviews beside them. In a microVM none of them is mounted. In host mode the kernel guard denies them to every pane; a host run whose panes could still reach one is refused unless the examiner accepts the exposure, and the record says which it was, for the release to bind. Signing the reportnever mountedseatbelt · macOS kernel guard · Linux
Terminal control socketThe multiplexer the agents run in has an unauthenticated control socket; an agent that reached it could start a process outside every rule above. It stays on the host, where no microVM reaches it. In host mode it is denied to the panes: on macOS by the profile, on Linux by a mask inside the mount namespace. Landlock alone cannot mask a socket, and on such a host the record says unenforced rather than claiming a seal.outside every VMseatbelt · macOS namespace mask · Linux
Egress allowlistOnly the model providers and the hosts the examiner allows. In a microVM the host's network policy denies everything else: a name off the list does not resolve and an address off it has no route, and that refusal leaves no log. In host mode every refused connection is counted and printed. Installing from an index, when allowed, is inventoried package by package. In a dynamic run no VM gains a host: each lookup is decided by rules and fetched on the host. The networkdeny by default · hostproxy · advisory · macOS network namespace · Linux
One microVM per agent in the console: the image and its digest, the network and the placeholders every VM gets, and each VM's life from creation to being put away
Every VM in one view: the image the agents booted and its digest, the network each VM may reach, the placeholders where the keys would be, and each VM's life from creation to being put away, with the checks its probe held and the disk kept.

In a microVM the boundary is the host side of every share and of the network. The guest's kernel is the agent's: root inside the VM can flip its own mount flags and unmount its own directories, and the host still refuses every write to the evidence and the run. What runs inside the VM, the harness's own extension included, is the agent's to change, so the finish line, custody and the report are all decided on the host. Some limits stay, and the repository lists them: an allowed host is a way out as well as in, the host's microVM runtime holds the run's keys while the VMs live, and the spend in a VM run is what each agent reports, with the wall clock as the brake the host holds by itself.

In host mode, "advisory" is not a euphemism. On macOS the egress guard is a proxy the agents are pointed at through their environment, and an environment belongs to the process that has it. On Linux the same guard is a network namespace with no route out except through the proxy, which is a kernel boundary. Every Linux cell was measured in two tiers, a host with user namespaces and a container without them, and the run record carries which one a run had.

Evidence handling

Hashed on the way in, held read-only throughout, checked on the way out.

In a microVM run the evidence is shared read-only into every agent's VM from where it lies, and the host refuses every write through that share, whatever the guest does. For evidence the examiner's own account can still write, a read-only copy in the run adds a second layer. Every file's hash is recorded before the first agent starts, with MD5 and SHA-1 beside SHA-256, and held to the acquisition hashes the imager recorded when you give them: a mismatch stops the kickoff. At the end the host re-hashes every file, and the verdict, content and metadata separately, is anchored outside the run and printed in the custody section; a check that runs out of time names the files it did not re-read.

In host mode the inputs are copied into the run with a pristine copy beside it, the kernel refuses writes in every pane, and a write that lands by another route is restored from the pristine copy and announced on the board.

Work over the evidence that parses it, takes long or produces something to cite runs as a job in a throwaway worker VM of the image that holds its programs. What a job writes is sealed into the store, read-only and hashed file by file, the same bytes kept once, and every step of every job is a line of a hash-chained journal anchored outside the run: who asked, the image, the scope it could read, the network, and what was sealed. A finding cites a job's output as job:<id>/<path>, and custody re-hashes every sealed file against its manifest. A job that failed keeps what it wrote, and a finding resting on it is told so. A job starts in the run's directory, read-only in its worker, so a program that writes its log where it stands is pointed at the job's own output; a job that failed on a write outside it says so, with the path and where it may write.

The catalogue of the evidence has one author, the job service, working from recipes the packs ship. The kickoff gives every input a coverage row: catalogued, in part, or not, and why. The recipes then run as jobs while the agents work, each result a new generation and each change a numbered revision, announced on the board. What the jobs produce, an archive or a decrypted volume, is offered to the recipes in turn, in the lowest lane, so a container an agent opens in the middle of a case is catalogued for the whole team. In host mode the catalogue is built before the agents start.

The evidence read-only and no-exec in every agent's microVM, hashed, and intact at the end
One tool job in the console: what it ran, its outcome, where its output was sealed, and the worker VM, its image and its network
One job as the store keeps it: the command, the outcome, the sealed output and when it was committed, and the worker that ran it, a VM of the disk image with no network.
inputs.jsonEvery evidence file with its size, hash, mode and link count, and how it is held on this host.
history/<sha256>/Every earlier version of every working file, by hash. Nothing an agent wrote is ever lost to a later write.
store/journal.jsonlEvery step of every tool job, chained line to line: accepted, started, finished, fenced when the worker is gone, committed.
catalog/revisions/<n>/Each change to the catalogue as a new numbered revision. Nothing is renamed or replaced.

The audit trail cannot be edited by what it records.

Every tool call, its arguments, its result and the reasoning before it. Every intervention with its reason. Every refusal.

The raw event trace, filtered by lane and tool, one tool job expanded to its call and result
one writer

A collector process on the host holds the only writable handle. In a microVM run the agents reach it only through the hub; in host mode, over a socket in a directory they cannot write. Either way it cannot be unlinked or replaced.

a chain and an anchor

Each line names the sha256 of the line before it. The head of the chain is written outside the run, so a file that is rewritten, extended or shortened no longer matches what the record remembers.

attribution by channel

Who wrote a line is decided by where it came from: in a microVM run, the agent's own socket to the hub; in host mode, a per-pane secret the collector holds. A line claiming to be another agent is written as what it is, with the claim beside it; an attempt on the record is itself a finding.

verified, and named

The report walks the chain and says intact, edited, appended, shortened or rewritten, and how many lines could not be attributed to an agent.

The examiner is on the record too. Each command that starts, stops, extends, resumes, reaps, speaks into, asks, reviews, signs, packages, exports, holds, releases, purges or verifies a run is a line in a chained operator log, with the OS user and the host, and so is every signing act in the console; on a live run, starting, stopping, reaping, speaking into it, reviewing, exporting, holding and releasing are on its trace as well. The report says which evidence files no command on the trace named, and until an examiner adopts an answer it says that answer is the agents' conclusion. How the report is signed is below.

the ledger

Chained entry to entry, like the trace. An entry is an event, an indicator, a finding, a search that found nothing (with what was searched and whether the search completed), a hypothesis with its status, a limitation (what could not be examined, and why), a coverage record behind a negative, material from outside the evidence with its provenance, or an answer with its result. It can say which question it answers, which entries it supports, contradicts or derives from, which clock a time came from and how precise it is, whether it was observed or inferred, whether it holds sensitive material, and which inputs or sealed job outputs it rests on. A second author is an attestation beside the entry. Nothing is rewritten.

the custody verdict

Every check has a status: passed, failed, incomplete, not applicable or unavailable, with what it covered. The verdict seals the length and head of every hash-chained register the run keeps: the trace, the ledger with its attestations, disputes and store sweeps, the leads and the finish register, the question register, the requests, the network's grants and fetches, the store's journal and the model gateway's log. A release binds each of them. The verdict holds the case policy to its hash, compares the evidence with the imager's acquisition hashes, matches the operator's log to the trace, and verifies each job's logs and each catalogue generation against their seals. It can be signed with an ssh key and timestamped by an RFC 3161 authority, with a reference clock's offset beside it, and custody-verify checks a finished run again while writing nothing.

the hand-over

A package made with --redact takes out what a sensitive entry says and the files it cites, lists each change with the hashes before and after, and every chain in it still verifies. The package carries every register custody sealed, and verify re-hashes it, re-walks each register against the verdict's seal and walks every release of the report it carries. A package can be signed with the examiner's ssh key. In the console a sensitive entry stays blurred until it is clicked.

A change to the finish rules, measured firstswarm.sh replay <run> reads a finished run's registers again under any harness version's finish rules, with no model call and nothing written in the run, and prints codes, ids and counts rather than what the records say. --compare sets two versions side by side and names every difference. Synthetic histories, each held to what the design decided, keep readiness, the answers check and the finish gate in agreement on every question, and every custody verdict verifying as a prefix. Replay measures the decisions on a history already written; whether a rule changes what the agents do takes paired runs.
Questions and answers

What the run is asked, who asked it, and what an answer may say.

A real case starts without its answers, and some of them the evidence cannot give. Questions raise further questions as the work goes on, and the people watching think of new ones. The run keeps one register of all of them: the goal's numbered questions, the ones agents open from the evidence, and the ones people add while the swarm works. Each is a Q-n in a hash-chained file the hub writes, with who asked it, every revision of its words and how it was answered. The finish line holds every material question in scope to an answer, and a negative answer has to say where it looked and hold against every output the run already has.

In the Community editionThe question register with its premises, analyst questions, the negative bar, the stop policy, resume and replay are part of the AGPL harness, like the rest of the record. Editions
From a question to what the report may sayquestions/questions.jsonl, beside the leads, one writer.
  1. who asks
    • goalNumbered in the goal and seeded at kickoff: Q-3 is the ledger's question:3.
    • agentOpened from the evidence, with the entry that raised it.
    • analystA person, while it runs: an examiner, an analyst, a reviewer or an observer, claimed or signed.
  2. the register
    Q-7 · rev 2

    One question, and its history

    Every revision word for word, who asked it and how, its objective, and whether the finish line waits for it.

    in scopeproposed · triageexcluded
  3. the seats

    Leads

    Offered to one seat at a time, for a minute. The first lead under a person's question states the proposition and its negation, and plans its routes: a source and a method each.

    A question found on the way goes back to the register as a new Q-n.
  4. before a negative stands

    The negative bar

    • a coverage record: the objects, the time range, the method
    • whether the event would have left a trace there
    • complete or partial, counted by the hub
    • a sweep of every output the run holds for what a hit would contain
    • the planned routes nobody examined
    • a claim of absence waits while its source is parsed whole
    • a review by another seat
    negative (unreviewed)quick negative
  5. the answer

    Its result

    • established
    • partial
    • bounded negative
    • not determinable
    • out of scope
    • premise not supported

    A bounded negative reads "No evidence that X was found in" its objects and time range.

When a question is unclear
  1. An agent asksa clarification, C-4; the question waits
  2. A request to youR-12, sent to your targets by its id
  3. You replyclarify-reply Q-7 C-4 "…"
  4. The seat wakeswith the reply posted to it
How a question moves through a run. Anyone may ask; the register keeps who did and how; the seats work it as leads; a negative passes the bar before it stands; the answer carries its result. Ids and revisions are examples.
who asked it

An agent's question names the entry that raised it. A person's names their role, their OS account, the host and the channel, whether they are enrolled, and whether the act was claimed with --as or signed with --sign by their enrolled key: ssh, FIDO2 or PKCS#11, like a release. With nobody named, the act is the OS account's, marked as not enrolled. Who asked a question, who found its answer and who adopted it stay three separate records.

who decides the scope

An examiner's or the operator's question is in scope by their authority, and may add an objective. An analyst's is in scope inside an objective and proposed otherwise; a reviewer's and an observer's are proposed. A proposed question waits in a triage queue for the operator or an examiner to admit or exclude it. Inside an objective or under a question in scope, an agent's question is in scope, and an agent never changes a person's question or the goal's.

a proposition to test

The first lead under a person's question states the proposition and its negation. Its answer names the evidence against it, or says why there is none, and "the premise is not supported" is an answer. A question can say what it presumes, presumes: in the goal or --presumes when you ask it, and that premise is tested before the question is answered. A review of an established answer to it tests "the question's premise is not supported" as a rival, or the answer is recorded as a best candidate; a partial answer that never tested it is warned. A clue that fits the question's frame is a candidate to test against that rival. A question worded as its own conclusion, "confirm that" or "prove", is flagged for the critic and worked all the same. Who asked, and how urgently, carries no evidential weight.

asked while it runs

swarm.sh question <run> add, or the console's Questions tab, commits the question to the chain first and acknowledges it after. Then it is posted from analyst:<you>, ranked first in every agent's header, and offered to the seat you suggested for its first minute, or to the idle seat best suited to it. A hint says where to look; a hint that says what to find is recorded as an open hypothesis in your name.

the finish line waits for it

An answer names the revision of the question it answers. An amendment makes the standing answer stale until it is recorded again, and a question admitted a minute before done is held like the goal's own. One admitted after the sentinel is kept as a follow-up, which a resume takes up. While the coordinator assembles the finish, another seat revises an answer only with material: why it changes a conclusion.

a withdrawal keeps the evidence

Withdrawing a question needs a reason. The leads that served only that question close, a lead holding a finding goes to triage, and nothing in the ledger is touched. A withdrawn goal question is no longer required by the finish line; the goal keeps it, and the register says who withdrew it and why.

what the case takes as given

Whose device it is, who the subject is: what the case brief states as given is a premise, P-n, on the same chain as the questions. Only you designate one, in the goal's front matter premises: or with swarm.sh question <run> premise add, and the kickoff warns about a brief with none. A premise an agent proposes is tested until you admit it. When one answer assumes a premise and another contradicts it, both wait until the record reconciles them, and neither is forced.

an answer's parts

An answer lists the parts of the question it answers, each established on the entries it rests on or open with what bounds it: an evidence request, a route or a limitation. A partial answer names what is open. Only a part the question asks can be open, and a premise never is. A part that nothing in scope can settle, such as what came before the retained logs, can be held at the limit of the evidence instead: it keeps the answer partial, and the report tells the gaps more work could close from the ones the evidence cannot. The report shows each answer's parts, and beside a partial label it says when every asked part is established; the metrics count those answers. A reviewer can name a part the answer left out, and it is warned of until the answer is recorded again with it.

the finish, prepared

The coordinator drafts the report and prepares the finish before its done: everything late against the report is listed whole, and it answers the list in one call, each item folded in or not material with why. A review of the report names the sections it covered and carries over to the next version while they are unchanged, so only what changed is asked again.

What "not found" means here

A search that found nothing says where it looked, and another seat checks it.

An answer carries its result: established, partial, a bounded negative, not determinable, out of scope, or a premise not supported. Established, partial and a premise not supported rest on a standing finding, since a search that found nothing cannot show a premise false. A quick "looked, not found" is how an examination goes wrong without anyone noticing, so a negative answer has to pass a bar on the host before the run may finish. A positive answer is held too: it is taken down only with evidence against it, and it keeps a high confidence only when a review weighed an alternative.

a coverage record

Every material negative cites one. It says what was searched: the proposition, the objects and the time range, the method and its settings, what was covered, skipped or failed, and what is still open. It also states the detection opportunity: whether the event would have left a trace in those sources at all, yes, no or unknown, with why.

counted by the hub

The hub compares every object the record names with the inputs the jobs behind it were actually given, and marks the coverage complete, or partial with what was missed. A job over everything covers each object and is said to. Whether an object was the right one to search stays the examiner's judgement.

swept across the store

The record names the strings a hit would contain were the answer in the evidence. The hub searches every output the run already holds for them: each job's output and logs, the evidence added later, the captures and the agents' kept tool output, byte for byte, in UTF-8 and UTF-16LE, with no parser. A hit in an object the record does not name holds the negative until that object is examined and the record names it, or the answer is revised. A sweep cut short names what it did not search. A kept output and the import it was sealed as are one object. A hit that only repeats the run's own words (its registers, a seat's summary, or a search over objects the record already names) is an echo: it is shown, and it holds nothing. When the sweep's rules change, the sweeps recorded under the older ones are read again when the run next starts or resumes.

routes, and quick negatives

A lead under a question plans its routes. At a negative close the hub lists the planned routes no job examined, and a material negative is refused when no route was planned. A negative closed within two minutes, after one job over one object, is flagged as a quick negative in the leads and the report, and in every header until a peer attests it.

reviewed by another seat

A material negative stands as "negative (unreviewed)" until a seat that recorded neither the answer nor its coverage reviews it: did it challenge the detection assumptions, reproduce a decisive check, try a materially different route, each done or not, with what was done or why not. The review is offered to one seat and held for it while it works. It opens with the question as asked and the sources the answer leads back to, then the sweep and its hits, and links the answer rather than quoting it; a seat of another model family is asked first where the team has one. The finish line refuses while one is unreviewed.

a complete set

A question that asks for every file, all connections or a complete list is marked so, by its words or by whoever asked it. Its established or partial answer rests on a coverage record of five areas, allocated, deleted, unallocated, slack and secondary, each searched, skipped or not applicable, or the finish line holds it.

taken down only on evidence

A revision that takes an established or partial answer down to not determinable or a negative names the entries or objects that undermine it. Without them the revision is refused, and the doubt becomes a dispute on the answer and, if it holds, a lower strength or confidence. The report shows a downgraded answer's earlier form, its disputes and the evidence that took it down.

high only when earned

A review that holds an answer established names an alternative explanation it weighed, why the evidence rules it out and the entries that show it; one that names none is recorded as a best candidate. The run records high confidence only on an established answer reviewed that way. Any other high is recorded as medium, and the report and the metrics show the confidence its author stated beside it.

the value, in the bytes

An established review of an established answer names the strongest rival reading and a test that separates it. It locates each literal value in the sealed bytes, and the hub reads the bytes at that offset and checks that the value is one the answer or its chain states; a derived value names the job that derived it. A review with no rival test that counts, a locator that does not verify or a derivation that does not resolve is recorded as a best candidate and told how to fix it; one that locates and derives nothing is warned. A locator proves the value is there, not that it is the answer: the review stays a best candidate until a coverage record for the question says the other areas of the source it was read from, deleted entries, unallocated space and slack, were searched too, so a rival value in slack is looked for before the one in the live file stands.

a source, parsed whole

A pack's recipe says whether it inventories a source or parses all of it into something searchable. The hub offers each broad extraction that applies as a lead of its own, one per source; the mobile pack parses a whole iOS or Android file-system acquisition at the kickoff. Every step is a receipt on the store's journal: planned, attempted, produced, partial, failed or declined.

a negative waits for it

A negative that claims absence, or complete coverage of a source, waits while that source's broad extraction is planned or running, and whatever it yields releases it, a failure or a decline included. Any other negative on a source not yet parsed whole is warned, and its reviewer sees each source's state first.

warned as it decides

The answers check's warnings reach a seat at the moment it decides: the reply to an answer, a review offer, an attest, a lead's close, and the finish status. An answer that leaves out what the record ties to its question is warned, entry by entry, with each tie. A warning never holds the run.

How the report words itA bounded negative is rendered as "No evidence that X was found in" its objects and time range, with its coverage and its reviewer, or a note that it has none. "X did not happen" is taken only for an existence question, over coverage the hub found complete, whose detection opportunity says the event would have left a trace. The report states a negative's conclusion from the coverage record's proposition and scope, and the answers check names an answer worded past its bar.
When a question cannot be settledA review of an answer says whether it holds it established or a best candidate, part by part, and a best candidate is never counted as answered. The operator or an examiner can accept a question's limits as they stand, bounded or not determinable, for its current revision, once no lead under it is open and its negative is reviewed. Any acceptance makes the run's outcome examination limited, and the report says so.
best candidateexamination limited
Caps, pauses and continuing

A cap pauses the run for you. A run that ended can go on, as the same run.

At the spend cap, the token cap or the wall clock, every agent is steered once to post a checkpoint, and two minutes later the run pauses. No model call goes out, every seat stays where it is, and you are notified. The pause does not rest on the agents' cooperation: the hub prompts no seat, the model gateway refuses the call when the run has one, and the watchdog enforces the pause from outside the panes. The run does not go on by itself. The same pause holds when the model provider refuses every seat, and when you hold the run yourself.

the stop policy

--stop cap-pause is the default. cap-stop is for a run nobody watches: two minutes after the steer the harness writes the stop itself. operator, which --until-solved also means, runs until you stop it, with every cap advisory. A metered team given no token cap gets one by default, as a second brake sized to stop a runaway.

extend, or stop

swarm.sh extend <run> adds minutes, tokens or dollars. When the caps then leave room, the pause lifts, the wall clock starts again where it stopped, and every seat is woken once, where it was. swarm.sh stop ends the run with the outcome stopped, which is never read as completed. Time spent paused does not count against the clock.

your own pause

swarm.sh pause <run> holds a going run under any stop policy: each seat finishes its step and goes idle, no model call goes out and the clock stands. swarm.sh unpause <run>, or Unpause in the console, lifts a pause whose cause is gone and wakes every seat. A pause at a cap lifts only when the caps leave room, which is what extend is for.

the provider's limit

When the model provider refuses every seat, as a subscription's usage limit does, the run pauses itself under every stop policy, once every live seat is limited: told to wait half an hour or more, or refused again after a retry. One seat's error never pauses it. The harness tries again at the time the provider named, or every thirty minutes, and tells you once per spell. The wait holds every VM, so the notice says you can stop the run to free the machine and resume it once the limit lifts.

when nothing yields

When no new finding, question disposition or coverage record has appeared across twenty committed jobs or thirty minutes, the watchdog proposes a stop to you, as a request with its own id. The proposal stops nothing, and it is never an agent's vote. Another comes only after a further window with nothing new.

how the run ended

Completed, examination limited, paused, stopped, abandoned, or verification unavailable, read from the run's files. The summary, the report and the console say which. A run that ends on limitations, deferrals or accepted questions is examination limited.

The same run continues.

swarm.sh resume <run> --question "…", or Continue this run in the console, continues a run that stopped or was sealed: the same sandbox, the same ledger, registers, board, trace and store, appended to and never rewritten. Each seat starts from its last hand-off note or compaction summary, whole. The questions you give are asked as analyst questions, and the follow-ups asked after the sentinel become the continuation's work. The team restarts with the options it was started with, which the kickoff kept outside the run.

the budget first

The wall clock counts on from the stop, the caps grow by what you give, and a resume that would still be over a cap is refused before anything moves. A running run is extended; a purged one cannot be resumed.

anchored before it moves

The resume is your act, on the trace and the operator's record, and anchored beside the run with each chain's length and head before anything is moved. What marked the end is moved whole into the run's history.

the seals stay valid

The next stop seals the continuation anew: a new custody verdict and a new draft release. Every earlier verdict verifies as a prefix of the same chains, and custody-verify prints each one.

a signed release stays as signed

A signed v1 is left untouched and valid for what it bound. The continuation's answers are adopted through a later release, and the case policy the kickoff recorded is kept, with each field the new options would have changed named.

Signing the report

The machine seals the draft at the stop. The examiner who read the report signs its release.

A report leaves a run as a series of releases, each a directory of the run that nothing writes over. The first is the machine's sealed draft. The next is an enrolled examiner's adoption, signed with their own key over the exact bytes they were shown, after a technical reviewer has signed their own review when the run asks for one. Each later release names the one before it and why it was made, and verify walks them all.

In the Community editionEnrolment, the three kinds of key, signing from the console or the command line, two-stage review and verification are part of the AGPL harness, free like the rest of the record. Editions
From the stop to a verified releaseEach release is its own directory: release/v0/, release/v1/ and on.
  1. the machine · at the stop
    v0 · sealed

    The draft

    The report is rendered with the DRAFT mark and sealed with the install's machine key, together with custody's verdict and the head of every chain. It adopts nothing.

    machine key
    swarm.sh stop <id>
  2. the technical reviewer · optional
    signed by the reviewer

    A second person

    A reviewer enrolled in a role of their own reads the run, here or from its package, and signs their record of what they checked and the outcome.

    sshFIDO2PKCS#11
    review --technical-review
  3. the examiner
    sha256 shown

    Read, then consent

    Each answer is adopted, qualified, withdrawn or rendered inconclusive. The final bytes are shown once with their sha256, and the examiner confirms having read them. The prepared release is used once and lapses after fifteen minutes.

    review --adopt · review --sign
  4. the examiner
    v1 · signed

    The release

    The passphrase, the touch or the PIN seals exactly the bytes that were shown, with each disposition, every technical review and custody.

    sshFIDO2PKCS#11
    release/v1/
  5. the examiner · later
    vN · amended

    An amendment

    A correction is a new release that names the one before it by its sha256 and says why it was made.

    review --sign --amend-reason
  6. whoever receives it
    verified

    Verify

    Each release in order: ssh and FIDO2 signatures against the allowed-signers register, an e-signature against the issuer's CA chain, and v0 as "machine seal, self-checked".

    releases --verify · verify
The release lifecycle. The machine's key seals v0 and nothing else. The examiner's and the reviewer's keys are their own, enrolled on the install, and every signature records which kind of key made it.
ssh keyA key with a passphrase

The default: an ed25519 key made at enrolment, its passphrase typed twice, or an encrypted key file you give. Enrolment prints the line for the organisation's allowed-signers register, and verify holds the signature to it.

FIDO2 security keyA touch for every signature

An ed25519-sk key made on the authenticator plugged into this computer. Every signature needs a touch, and its PIN as well when it was enrolled verify-required. The key-handle file alone signs nothing.

PKCS#11 e-signature tokenA certificate and its PIN

The X.509 certificate on the token is read without the PIN and shown by its CN alone. The platform signs with the certificate on the token (CAdES-BES) and verifies it against the issuer's CA chain.

machine keyThe install's seal

Made once per install, with no passphrase, so a stop can seal the draft unattended. It seals v0 and is checked only as the machine's seal. swarm.sh machine rotate retires it and makes the next one.

The Release tab with release v1 prepared: the sha256 of the bytes shown, the gate's counts, the technical reviewer's signed review, the key, and the report in a frame
The Release tab on a test run: release v1 prepared once, the sha256 of the exact bytes shown in the frame below, the gate's counts, the reviewer's signed review and the examiner's key. The people are the hardware tests' fictional examiner and reviewer.
The dialog that signs release v1: the bytes and the key it signs with, where the secret goes, and an empty passphrase field
After the box is ticked, the dialog names the bytes and the key, says where the passphrase goes and what five wrong ones do, and signs nothing until it is typed. The key's path is masked here.
From the console

The Release tab of a stopped run lists the enrolled examiners whose keys it can use, shows the prepared report in a frame with no scripts beside the sha256 of exactly the bytes the browser holds, and waits for the box "I have read the report and the answers I adopt" before a dialog asks for the passphrase, a touch of the key or the PIN. The Examiners page enrols a person, and the Technical review tab is the reviewer's.

The console signs only with its token and only on loopback. It leaves out a key without a passphrase or held in ssh-agent, signs nothing while a host-mode run is live on the install, and after five wrong secrets locks that person out of console signing for fifteen minutes, on the operator's record.

On the command line

swarm.sh review <id> --sign prepares the release and prints what will be signed: the sha256 of the report and the release, the counts of adopted and withdrawn answers, the technical reviews and the key. It asks for the confirmation, then for the passphrase or the PIN with echo off, or says when to touch the key. A wrong secret leaves the prepared release for another try, three at the terminal.

Either way the secret reaches ssh-keygen or OpenSSL only down a pipe. It is never in an argument, the environment, a file, a job record or a log.

two stages, two keys

The technical reviewer's signed record comes first, and the examiner's release binds it. A reviewer with the examiner's id, name or key is refused; the organisation's register is what ties each key to a person. A reviewer on another machine signs from the package, and the examiner imports that file, checked against the register or the CA. --require-technical-review at kickoff makes the release wait for a signed review, and a release without one says "No technical review".

out of the agents' reach

No agent's VM mounts the machine key, an examiner's or reviewer's key, the ssh-agent socket, an earlier run's sandbox or the examiners' reviews. In host mode the kernel guard denies them to every pane, and a host run whose panes could reach a key is refused unless the examiner accepts the exposure. The release binds what the run's agents could reach.

what verify says

releases --verify, and verify for a package, walk every release: its place in the chain, its signature, whether it was signed from the console or the command line with the consent confirmed, the technical reviews it binds, and the bytes it binds. Exit 0 when every adoption's key is one the register allows or the CA verifies; 3 when there was nothing to check the signer against; 4 when something does not hold.

The hardware tests in the repository sign end to end with a FIDO2 security key and a PKCS#11 e-signature token, run on macOS with a YubiKey 5 and a SafeNet eToken 5110. A release's signature can also be timestamped by an RFC 3161 authority, later when the lab is offline. Signing, in the usage guide →

The case contract

What may come in, what may leave, and what the run asked of whom.

A case is examined under a contract fixed at kickoff. The case policy says what may leave the run and reach outside it, whether more evidence may arrive while it goes on, and what material from outside the original evidence may be used for. The kickoff refuses a policy that contradicts itself, anchors it beside the run and writes it into the contract the agents read. Custody seals it by its hash and names a rewrite, a release binds it, and a resume keeps it. An agent can weaken none of it.

presetwhat it permitsmore evidence during the run
standard
the default
Hashes and public indicators, sent to approved passive reference services. Contact with anything the evidence names, such as a URL's HEAD, is the operator's decision.The operator decides each ask.
live_adversaryThe same lookups, and nothing the evidence names is ever contacted. No socket grant.The operator decides each ask.
internalNothing leaves the run, and nothing is captured from outside it.The operator decides each ask.
ctfA published case: no search engine and no write-up site, only reference or evidence-linked lookups, and every value sent must be found in the evidence the request cites. No socket grant.None: the collection is closed.

The goal's metadata or the kickoff's flags change one field at a time: --lookups, --contact, --disclosure, --more-evidence no|ask|yes, --material-use, --legal, --provider-retention. The legal text is the operator's own, such as the jurisdiction, the warrant's scope or "GDPR or similar laws", and is recorded as given.

what the run asks of you

A lead that needs you, evidence the run does not have, a clarification, a network item, a stop proposed when nothing yields: each is a request with its own id, R-n. The record that makes it is committed first, the request is derived from it and written once to a chain custody seals, and a crash in between loses nothing. It moves from pending to notified, acknowledged, and then answered, declined or withdrawn.

told by its id

The hub hands each new request to your targets: a desktop notification, an ntfy topic, a mail address or a command of yours. The notification carries the request's id and kind and the lead's or question's id. What was asked stays in the run, since it may be case content and a notification leaves the host. swarm.sh requests <run> list and the console's Requests tab show everything open.

asking for evidence

An agent asks for evidence the run does not have on the lead that needs it: the source, where it is, what it would establish, how urgent it is. The acquisition moves from requested to authorised or declined, then collecting, received, and validated or unavailable. Under more_evidence: no the hub answers at once "no additional input under this case policy", a constraint of the case that says nothing about whether the source or the fact exists. An answer that a missing source leaves not determinable names its ask, R-n, or says why none would settle it, and the answers check warns when it does neither.

evidence that arrives later

swarm.sh evidence <run> add PATH --for R-n copies it outside the run, holds each copy to its source's hash and to the acquisition hash you give, and seals it in the store as a new inventory revision. It answers the acquisition, reopens the leads under its questions, makes the answers recorded before it stale, and lifts an acceptance made before it; with the catalogue on, each file is detected and catalogued. Its files are searched at once for what every standing coverage record looked for, and each hit goes to the questions it bears on. Every negative, not-determinable and partial answer whose coverage predates it goes stale too, whatever it was added for, until another seat reviews an examination of it against the new evidence that says how the evidence bears on the answer (it supports it, contradicts it, adds a part, is irrelevant or is inconclusive), or you accept the question after the addition. Citing the new evidence alone clears nothing. Each agent's VM reads the run read-only and live, so the addition is readable there at once, and through jobs.

material, with its provenance

A statement, a policy document or a question's attachment is supplied with swarm.sh material <run> add and sealed the same way, recorded with who supplied it, when, from where and its hash. What the policy permits it for is part of the record, a record citing material the policy says may not be cited is refused, and every answer resting on material from outside the original evidence is named as such by the answers check, the report and the release.

where the evidence ends

The report's "Evidence gaps and acquisition requests" is generated from the records: every acquisition with its stage and outcome, and each gap told apart as never collected, unavailable, inaccessible, unexamined or inconclusive, with its questions, what it bounds and what would close it. A declined or unavailable acquisition bounds the questions it bore on; it is listed as a gap and never turned into a negative answer.

The network

A lookup is decided by rules and made on the host.

Some questions need what a reference service knows: a domain's registration, a certificate log, a CVE, a hash's reputation, a place. The network mode says how that is decided. closed is the default: the models' hosts, the package index when installs are allowed, and the hosts you allow. open is every public host. In a dynamic run no agent's VM gains a host: an agent asks for one bounded lookup, the hub decides it by rules alone under the case policy and records the decision before it answers, and a fetch service on the host makes exactly that request and nothing else.

A lookup disclosesA hash sent to a reputation service, a coordinate sent to a geocoder or a domain sent to a registry tells a third party what the case is interested in. The case policy says which classes of case data may leave: hashes, public indicators, coordinates, internal names, personal data, file uploads.
The rules, in the order the hub applies them
  1. who asksdecided by the channel the request came on
  2. its shapea strict schema, an adapter's typed values, an open lead the asker holds
  3. the case policywhich lookups, which contact, which data may leave; a request no adapter covers is uncertain, and left to the operator
  4. hard denialssearch engines, write-up and paste sites, social platforms, proxies, logins, uploads
  5. what would leavecredentials and the run's sensitive values, as sent and decoded
  6. the evidence linkwhat leaves must be found in the evidence the request cites, where the policy asks
  7. enforceabilitywhat is asked must be something the harness can hold it to
  8. quotascounted again under the lock that issues the grant

The first step that refuses decides, with reasons a machine can read. The same request gets the same answer. No model sits in the decision, and the purpose a request states is stored and shown and read by no rule, so no words in a request or a response can change a decision. A refusal closes that avenue and leaves the lead open.

the adapter catalogue

A list of what may be asked: RDAP for domains, addresses and AS numbers, crt.sh, the NVD CVE API, CISA's KEV feed, CIRCL hashlookup, RIPEstat, Nominatim, Overpass, a video's title, VirusTotal by hash when you configure a key on the host, and one evidence-linked HEAD of an exact URL, which is active contact. An agent gives typed values, and the adapter places each one; none can become a host or a path.

a grant is a capability

One exact method and URL, for one seat or one job, for five minutes and one use, with a byte limit, recorded in a hash-chained file with every request and decision. A refusal you may override opens one item per host and lead, and swarm.sh net <run> grant runs the same rules with those reasons waived and recorded. A login, an upload, a credential or a sensitive value stays refused whoever asks.

the fetch service

A host process with no evidence. It sends only its own headers, so no provider key, seat token or cookie leaves with a request. It resolves the name once, refuses loopback, private, link-local and other special addresses, connects to the address it checked with TLS verified against the name, and is no proxy. Each use is written to its log before a byte leaves.

a capture is external material

The answer is sealed in the store as a capture, with the request, the headers sent, the address and the TLS identity, and the harness records it on the ledger as external material. A capture's hash proves its bytes. An examiner records what they establish, and every answer resting on a capture is named as such by the answers check, the report and the release.

a socket, said plainly

Where a job's own client needs a connection, a socket grant allows a host and a port, with no control of the method or the path and no capture of the content. It is the operator's alone, needs a policy that permits it, and is refused under ctf, internal and live_adversary. The kickoff's --allow-host is such an allowance for the whole run, and says so.

seen and answered by you

swarm.sh net <run> list and the console's Network tab show the policy, what waits on you, every grant with its time left, every request with its reasons, every capture and what the fetch service refused. You grant, deny or revoke with a reason, and each act lands on the trace and the operator's record and is posted to whoever asked.

What it does not coverA host run has no hub and no fetch service, so a dynamic network needs a microVM run. A model provider's own browsing tool is outside this mediation, and a run that must exclude it needs a model without one. A worker already running keeps the network it booted with, so a revocation reaches the next one. The evidence link is a literal match, bounded in size, and a value an agent converted is cited from the job output that holds it as sent. Categories cannot guarantee a published case's integrity alone, which is why ctf also requires every value sent to be in the evidence.
We publish the escape

When a guard is only advisory, the report says so. When an agent walked around one, we published the whole account.

On one published run, in host mode on macOS, an agent refused repeatedly by the egress guard unset the proxy variables in its environment and installed the library it needed. The kernel-enforced guards held throughout. The advisory one did not, and could not have, which is what advisory means. The custody section of that run's report prints Egress enforcement: ADVISORY beside the package that came through, and the full account (every attempt, the command, why it worked, what to do about it) sits in the repository beside the run, with the runs where a guard was only advisory in the case ledger.

In a microVM the same guard is the host's network policy for that VM: a name off the list does not resolve and an address off it has no route, and there is no variable to unset.

A harness that hides its own limits cannot be put in front of a court. The record reports what was achieved rather than what was asked for.

The escape, end to end, in the repository →
The trace row of the escape, expanded in the console
Chain of custody, as that run's report printed it
Inputsintact at the end, every file checked Write guardenforced (seatbelt) Terminal socketdenied to the panes Trace integrityintact, every line chained Egress enforcementADVISORY (proxy environment only) Egress refusedthe hosts, and how many times Installed during the runname, version, sha256 of its own manifest

Isolation, by edition.

The same harness under each, with the record carrying how a run was held.

Community · todayA microVM per agent

Each agent in its own microVM on your own machine, on macOS with Apple silicon or Linux with KVM: the evidence a read-only share, its own directories writable, its network an allowlist the host enforces, its keys placeholders. The agents boot a small base image, the forensic programs are in a job image per profile, and tool work runs in a throwaway worker VM per job. Every image is built from the packs in the repository.

Community · todayHost mode, unisolated

Chosen with --isolation host, for a machine that cannot run microVMs: kernel policy on the host, with seatbelt profiles per pane on macOS, and on Linux Landlock inside a user namespace with a network namespace for egress. The record says the run was held this way and which guards the host could enforce.

Pro · by contactPrebuilt images, a verified toolset

Private, digest-pinned images for every pack, built and checked for you, holding a toolset whose tools we have checked and ship. The same microVM per agent, on your own machine.

Enterprise · by contactA dedicated host per case

Each case on a host of its own in your lab, with nothing of any other case on it, and its agents each in a microVM there; air-gapped where the evidence demands it, with the case file as the only thing that leaves.

Evidence is hostile input

The files were written by the subject of the investigation. They are material to examine, and the harness treats them that way.

A note, a filename, a chat message inside the evidence cannot give an agent a task or a permission. A URL in a chat log is a finding to record; resolving it would tell the subject their device is being examined. The contract says it; each microVM reaches only the hosts the run allows, a worker VM that parses the evidence has no key and no network unless its job asks for the run's allowlist, extracted material lands on no-exec mounts, and the trace shows every time it was tested. No-exec keeps a carved file from executing, and an interpreter can still read it, so a command or a job that runs or evaluates code recovered from the evidence, from an extraction or from a job's output is flagged on the trace and in the report's job record. In a dynamic run, a HEAD of a URL the evidence names is active contact: the operator's decision under the standard policy, refused outright under live_adversary and internal, and granted by the rules under ctf only where the value sent is in the evidence.

Everything on this page is in the source, with the tests that fail without it: the guards, the collector, the verification, the custody section, and a suite that boots real microVMs on every pull request.

Read the harness on GitHub →