docs← Back to article

Markdown for LLMs

Offline and restricted-network operation

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# Offline and restricted-network operation

## Goal

Run installs, asks, and replays on a host with no (or allow-listed)
network access, using a bundle prepared in advance on a connected machine.

## Scope

Component `law` CLI, tool `0.1.1`. Scenario: a closed host where package
registries and release servers are unreachable; all artifacts arrive by
removable media or a one-way drop. Names, paths, and sizes below are
synthetic created-examples.

## Applies to

| Branch | Coverage in this article |
|---|---|
| MCP + `law serve` | the offline bundle procedure feeds both servers; serve worlds travel as world directories (or bundles restored to directories), MCP slices as pinned profiles |

## Prerequisites

- A connected staging machine with the same pinned `law` version as the
  target (check with `law version --json` on both).
- The full dependency closure of the project (`law.toml` + `law.lock`)
  resolved on the staging machine.
- Write-once transfer media (created-example: `/mnt/drop/`).

## Steps

1. On the staging machine, resolve and freeze the world:
   `law install --project <dir>` (connected), then
   `law test` over the `law.lock` world to confirm the closure is green.
2. Build the portable bundle (real command):
   `law pack --project <dir> --out /mnt/drop/world-2026-10-03.arxo`
   (real flags: `--contents full|source`, `--deps closure|pins`,
   `--codec zstd|deflate`, `--zstd-level 1..19`, `--timings`,
   `--no-tests`, `--json`). Prefer `--deps closure` so the bundle is
   self-sufficient; the container carries packages with their
   operations' inputs, identical files stored once.
3. Sign the bundle if your policy requires it (real):
   `law sign /mnt/drop/world-2026-10-03.arxo --key <keyfile>
   --role publisher`.
4. Transfer the `.arxo` file (and, for first provisioning, the `law`
   release archive + `.sha256`) to the closed host.
5. On the closed host, verify before use (real):
   `law inspect world-2026-10-03.arxo --verify --trust <key> --files`.
   Then either `law unpack world-2026-10-03.arxo --out <dir>` or execute
   straight from the container (`law ask <file.arxo> …`,
   `law test <file.arxo> …` — real, no unpacking needed).
6. For project-form installs on the closed host, use the one offline
   flag that exists (real): `law install --offline`. Confirm no other
   package command is in your runbook (see Limits below).
7. Serve locally as usual (real):
   `law serve --world <dir> --journal <dir> --host 127.0.0.1 --port 8480`
   (real defaults: host `127.0.0.1`, port `8480`).

## Expected result

- `law inspect --verify` exits `0` with `integrity` and `signature`
  lines matching the release record.
- `law test <file.arxo>` and `law ask <file.arxo> …` exit `0` with no
  network access on the host.
- `GET /healthz` and `GET /readyz` (real endpoints; readyz returns `200`
  after all workers warm up) answer on the local port.

## Result check

- Disconnect the staging check: run the full ask/replay set with the
  network interface down (or in a network namespace without a route) and
  confirm exit `0` and unchanged `resultHash` values.
- Egress verification (operator-policy-example): capture traffic during
  the run (`tcpdump`/firewall counters — created-example tooling, not
  tool behavior) and confirm zero non-loopback connections; any egress
  is a finding, not background noise.

## Failures and diagnostics

- `law add` / `law update` attempted offline: these subcommands have no
  `--offline` flag (implementation limit, stated in `law --help`): they
  must read registry descriptors to build the closure. Prepare the
  closure on the connected machine instead.
- `law install --offline` failing on a missing descriptor: the bundle or
  project cache is incomplete; re-run connected `law install` on staging
  and re-pack with `--deps closure`.
- `no signature from a --trust or trustedKeys key`: the trust set is
  non-empty but no signature matches it. Check both sides against
  the independent operator trust record before touching either:
  unsigned bundle, different publisher, wrong trust set, or wrong
  release are all possible — a missing key file in transit is only
  one of them. Never bend the trusted keys to fit the artifact you
  received; resolve which side is wrong first (see
  [Install and trust artifacts](/operate/install-trust-artifacts/)).
- Stale calendars/resources: the release artifact embeds `resources`
  (real `law pack` content); a bundle built last quarter answers with
  last quarter's resources. Re-pack when the normative inputs change.

## Support boundaries

- Supported (tool behavior): `--offline` on `install` only; container
  execution without unpacking; hash/signature verification of bundles.
- Implementation limit: dependency resolution (`add`, `update`) always
  needs registry descriptors; there is no offline closure solver.
- Reference setting: media paths, ports, and capture tooling here are
  created-examples. "Isolated" in this article means only "no
  non-loopback traffic observed during the check" — it says nothing
  about side channels, media hygiene, or host hardening.

## Next step

Record the bundle filename, its hashes, and the trusted key ids in the
change log; for version moves, continue with
[Upgrades and compatibility](/operate/upgrades-compatibility/).