Metadata-Version: 2.5
Name: harbor-glovebox
Version: 0.1.0
Summary: Run a Harbor trial in a hypervisor-isolated, egress-filtered glovebox microVM
Project-URL: Homepage, https://github.com/AlexanderMattTurner/agent-glovebox
Project-URL: Source, https://github.com/AlexanderMattTurner/agent-glovebox
Author: AlexanderMattTurner
License-Expression: Apache-2.0
Keywords: ai-control,evals,harbor,microvm,sandbox,terminal-bench
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Requires-Python: >=3.12
Requires-Dist: glovebox-driver>=0.6.0
Requires-Dist: harbor<0.24,>=0.23
Description-Content-Type: text/markdown

# harbor-glovebox

Run a [Harbor](https://github.com/harbor-framework/harbor) trial inside a glovebox microVM instead of a shared-kernel container. Each trial boots one hardware-isolated VM behind glovebox's outgoing-traffic filter, and the filter's records land beside the trial's other artifacts.

## Status

The `harbor-trial` live check drives one trial's environment calls on a real microVM in CI, then runs `harbor run` with Harbor's oracle agent over a one-task dataset through this environment. No run over a published dataset with a model-backed agent has used it yet.

## Use

Install the released package:

```bash
pip install harbor-glovebox
```

To run the unreleased code on `main` instead, install all three packages from the repository at one revision. That needs `git` on the machine. Set `R` to the same tag or full commit for all three, since two people who install `main` on different days get different code. `--upgrade --force-reinstall` replaces a released `glovebox-driver` or `glovebox-hosts` that already satisfies the version pins:

```bash
R=git+https://github.com/AlexanderMattTurner/agent-glovebox.git@<tag-or-full-commit>
pip install --upgrade --force-reinstall \
  "glovebox-hosts @ $R#subdirectory=glovebox-hosts" \
  "glovebox-driver @ $R#subdirectory=glovebox-driver" \
  "harbor-glovebox @ $R#subdirectory=harbor-glovebox"
```

Then run a trial:

```bash
harbor run --dataset <dataset> --agent claude-code \
  --env harbor_glovebox.environment:GloveboxEnvironment
```

The host needs what any glovebox launch needs. `glovebox sandbox preflight` checks it, and each trial runs that check before it builds anything.

## Users

A command runs as the `user` Harbor names, else the task's `[agent].user` or `[verifier].user`. With neither named, it runs as glovebox's de-privileged account, never as the image's own `USER`. Before that account's first command, it takes over the image's working directory and what the image's `USER` owned in its home. A task that names the image's own account keeps those files as they are. Every command inherits the image's `ENV`, as `docker exec` would carry it. Harbor names root itself for its own setup steps, such as installing the agent. Every command, root's included, sends its traffic through the in-VM filter and then the host filter outside the VM.

## What it refuses, and why

- **`network_mode = "public"`.** glovebox has no unfiltered mode. Use `allowlist` and list every host the task needs. Put the agent's model endpoint in Harbor's `extra_allowed_hosts`.
- **Wildcard and IP allowlist entries.** The filter matches hostnames only. Harbor rejects such a task before it starts.
- **A bare top-level name as an allowlist entry**, such as `com`. A public suffix with a dot, such as `github.io`, is accepted, but it reaches that one host alone. An ordinary entry also reaches one label below it, so `example.com` admits `api.example.com`. Under a public suffix that label is a stranger's name.
- **A download larger than 1 GiB.** The guest's archive arrives in the host's memory whole, so the transfer fails rather than grow without bound.
- **A task image that already ships `/logs`, `/tests`, `/solution` or `/harbor`.** The guest's root is read-only, so each of Harbor's fixed trees is a link onto the guest's writable `/tmp` disk, and the image build refuses to replace a tree the image carries.
- **Multi-container tasks** (a `docker-compose.yaml` in the task's environment directory). <!-- # allow-dangling-path: a file in a Harbor task's own directory, not in this repo -->

`storage_mb` is ignored, as Harbor's own Docker environment ignores it.
