# Pilot workspace backup and restore

This tool backs up an existing **stopped, single-workspace Pilot service** on Node 24. It preserves the SQLite records and the key needed to decrypt provider credentials. It does not back up desktop-only workspaces, external files, TLS certificates, operating-system configuration or remote model services. No application migration is performed.

The backup is a directory containing exactly `agentworks.sqlite`, `pilot.env` and `manifest.json`. These files form one recovery bundle: keep them together. This is not an arbitrary ZIP importer. To move a zipped bundle, unpack it yourself into a protected directory, then verify that directory. Do not pass the public website/source release ZIP to this tool.

## Protect the recovery material

**The bundle contains a plaintext master key. Anyone who can read the bundle can decrypt its stored provider credentials.** Store and transport it using operator-controlled encryption and restricted access. Never place a bundle in the public website, repository, release archive or downloads directory. Directory/file modes restrict access on POSIX. On Windows, modes do not set NTFS ACLs: create the parent directory in an account-restricted location and verify its Security permissions before backing up. The tool requires trusted local parent directories; it does not defend against an administrator or attacker concurrently changing those directories.

Hashes detect accidental alteration and incomplete copies. They are not signatures or proof of publisher authenticity: a person with the bundle can rewrite its manifest and data. Keep an independently protected hash/record of accepted backups if authenticity is required. SQLite integrity, vault decryption and the internal audit chain are also checked; this is not an externally anchored audit guarantee.

## Create and verify

Stop the Pilot service normally and ensure no other process writes its data. The tool exclusively acquires the same `server.lock` used by the service, and refuses an existing lock. After a crash, inspect the PID and confirm that the owning process is stopped before handling a stale lock; the tool never removes somebody else's lock. Do not run an alternate database writer that bypasses this convention.

From the application/Pilot distribution directory, with Node 24 installed:

```powershell
node scripts/pilot-backup.mjs backup --data .pilot-data --output C:\PrivateBackups\agentswat-2026-11-01
node scripts/pilot-backup.mjs verify --bundle C:\PrivateBackups\agentswat-2026-11-01
```

The output directory must not exist and its parent must exist. Paths are examples; choose your own protected location. On macOS/Linux use native paths, for example `/private/agentswat-backups/2026-11-01`. Those platforms have not been executed in the current evidence.

By default the master key comes from `<data>/pilot.env`. If your deployment obtains its key from a separate environment file, pass `--env <that-file>`. The file must contain the actual canonical 32-byte base64 `PILOT_MASTER_KEY` matching this workspace. Process environment alone is not used as a key source. No key or bearer token is printed. The original environment file is never changed.

The tool checks the source database/key/audit chain, uses SQLite `VACUUM INTO` to capture committed WAL content into a standalone database, writes file sizes and SHA-256 hashes, and verifies the completed bundle. An existing destination is never overwritten. Only files created by the current operation are removed after failure. Leave the service stopped until backup succeeds or fails and releases its lock. A process crash can leave a partial directory or lock: inspect it manually, verify any completed bundle, and choose a new output directory for a retry. Do not treat the mere presence of a directory as a successful backup.

## Restore into a new data directory

```powershell
node scripts/pilot-backup.mjs restore --bundle C:\PrivateBackups\agentswat-2026-11-01 --data C:\AgentSWATData\restored
$env:PILOT_DATA_DIR = 'C:\AgentSWATData\restored'
node --env-file=C:\AgentSWATData\restored\pilot.env dist/pilot.cjs
```

Use the same compatible Pilot application version for the initial drill. **The destination must not already exist, even if empty, and must be outside the input recovery bundle.** Restoring to the bundle itself or any descendant is rejected before verification or mutation, preserving the source backup. Restore never merges or replaces current user data. Keep the old workspace intact until the restored service is verified. Parent directories must already exist. Links/junctions in recovery paths are rejected; relocate the bundle to a real protected directory when necessary.

Restored `pilot.env` contains only the matching key plus `127.0.0.1:4319` defaults. Existing bearer-token hashes, member roles, workflow revisions, jobs and audit records remain in SQLite. Bootstrap tokens and stale server locks are excluded. The backup format rejects arbitrary additional environment variables. Explicitly reconfigure TLS/proxy/listener settings and external file paths after local validation, and review inherited process environment before starting Node (environment variables can override `--env-file`). Never expose a restored listener publicly without the normal Pilot TLS controls.

Check `/health`, connect using an existing unexpired member token, inspect workflows/jobs and verify the audit export. If all administrator tokens expired, use the existing documented offline `pilot-recover.mjs` procedure after stopping the restored service; that procedure rotates an administrator token and records an audit event. The backup tool does not rotate identities or silently reactivate members.

Restart/recovery behavior for interrupted jobs remains the existing Pilot behavior; review outstanding approvals and job state before new live calls. No recovery drill should make paid model calls until an authorized operator has inspected it.

## Executed evidence and limits

`node scripts/test-pilot-recovery.mjs` (from `app`) compiles isolated fixtures with esbuild, creates synthetic data, preserves committed WAL records and encrypted secrets, restores into a fresh directory, and starts the actual compiled Pilot service to verify authenticated state/audit. It checks active-lock refusal, destination protection, checksum damage, malformed SQLite, wrong key, audit tampering, partial/extra files, path traversal, environment injection and directory links. Fixture material is synthetic and retained in the test's reported temporary directory for inspection; no real credentials or provider calls are used.

Current author evidence is Windows, Node 24.16.0, one host and small synthetic data. This is a clean-data-directory restoration, not a second-machine or regional disaster recovery drill. macOS/Linux execution, large-data timing, power-loss/fsync durability, malicious concurrent filesystem writers, encrypted backup storage, automated retention, off-site copies and operator training remain unverified. Maximum supported database file size is 2 GiB; configuration and manifest are limited to 64 KiB. No RPO, RTO, availability or enterprise certification is asserted.
