# Havre Silo reference client

This is the technical-pilot client for Silo.havre.cloud. It seals private files on
your device, sends only ciphertext to Havre, and decrypts downloads locally. The
server does not receive your private key.

This bundle includes the command-line reference client and a small desktop
companion. The companion is a transparent Python/Tk shell around the same
trusted client; it does not duplicate encryption or key storage and is not a
signed native installer. Silo checkout is still closed while pricing, account
email, recovery, renewal, and restore evidence are completed. Do not use it for
personal files until Havre invites you to a pilot.

## Install

Use Python 3.11 or newer in the extracted bundle. The bundle includes launchers that create
an isolated `.venv` beside the client and install only the two cryptographic dependency families.

Windows PowerShell:

```text
Set-ExecutionPolicy -Scope Process Bypass
.\run-silo.ps1 --selftest
.\run-silo-desktop.ps1 --selftest
```

macOS or Linux:

```text
./run-silo.sh --selftest
./run-silo-desktop.sh --selftest
```

If you prefer to manage the environment yourself, the equivalent commands are:

```text
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe havre_remote.py --selftest
```

macOS or Linux:

```text
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python havre_remote.py --selftest
```

To open the desktop companion after the smoke test:

```text
.\run-silo-desktop.ps1
./run-silo-desktop.sh
```

The companion needs the Python Tk support shipped with most Windows and macOS
Python distributions. Some Linux distributions package it separately. If Tk
is unavailable, the reference CLI remains the supported fallback.

The smoke test creates temporary local state and verifies the encryption round trip.
It does not contact Havre.

Repository maintainer drill:

```text
python box/backend/silo_pilot_drill.py --output docs/evidence/silo-technical-pilot-receipt.json
```

This runs the canonical local mock suites and records named technical scenarios with source
hashes. It does not contact the live service, open checkout, or count as customer-pilot evidence.

## First Silo pilot flow

1. Create and verify your Havre account in the browser. The Silo account path
   requires email verification and a recovery-capable account before sync.
2. Log in with the client after Havre enables your pilot:

   ```text
   python havre_remote.py login you@example.com
   ```

3. Check the package and server-side gates:

   ```text
   python havre_remote.py silo-catalog
   python havre_remote.py silo-status
   python havre_remote.py silo-device register --name "This computer"
   python havre_remote.py silo-doctor --root ./My-Silo --json
   ```

   Alternatively, from the authenticated Silo browser console choose **Link a new device**.
   Copy the one-time command to the new computer and run it there:

   ```text
   python havre_remote.py silo-device setup --code <one-time-code> --name "This computer" --root ./My-Silo
   ```

   The setup code expires after ten minutes, is single-use, and lets the client generate
   its own key, store its device token locally, and start the first encrypted push and pull
   without putting a private key or bearer token in the browser. Use `silo-device enroll` when
   you need enrollment without starting a sync.

4. For a private scanned book, identify it before uploading the bytes:

   ```text
   python havre_remote.py silo-book-push ./My-Silo Scans/book.pdf
   ```

   The client scans the local EPUB package, bounded PDF/file text, and filename for ISBN
   evidence before it computes an opaque tenant-local identity. EPUB title and author
   metadata can fill the command automatically; use `--title`, `--author`, or `--isbn`
   when the scan cannot identify the edition. Multiple or conflicting ISBNs fail closed
   before any upload. Silo then preflights the edition and uploads encrypted bytes only
   for a new approved edition. An exact duplicate or an uncertain identity stops before
   ciphertext upload. The same resumable path binds a successful upload to the book edition.

5. After the doctor is green, sync a selected folder:

   ```text
   python havre_remote.py silo-sync ./My-Silo
   python havre_remote.py silo-watch ./My-Silo --interval-seconds 30
   python havre_remote.py silo-move ./My-Silo Documents/old-name.pdf Documents/new-name.pdf
   python havre_remote.py silo-move-dir ./My-Silo Documents/OldFolder Archive/OldFolder
   ```

    To add another computer, install the bundle there and redeem a one-time browser link
   with `silo-device setup --code <one-time-code> --name "Second computer" --root ./My-Silo`,
   or run `silo-device register --name "Second computer"` after signing in. From an already trusted device, run
   `silo-device grant --id <target-device-id>`, then run `silo-sync ./My-Silo` on the new
   device. The new device receives its own key and only the existing device can authorize
   access to the private objects already stored. To grant only one collection, use
   `silo-device grant --id <target-device-id> --collection "Private scans"`; omitting
   `--collection` grants every existing private object. Future uploads include all active
   devices, so this is an initial-access scope rather than a permanent recipient policy.
   A successful sync saves a bounded receipt
   visible in the Silo account console; it contains counters and status, not filenames,
   hashes, keys, or tokens.

   The folder command checks every current file identity before committing one atomic
   remote prefix move. It refuses unsynced local files, stale edits, overlapping folders,
   and an existing local destination. A retry does not upload or re-encrypt the files.

   To discover account-backed collections from a trusted device and select one without
   copying its opaque root prefix:

   ```text
   python havre_remote.py silo-collections
   python havre_remote.py silo-sync ./My-Silo --collection "Private scans"
   python havre_remote.py silo-watch ./My-Silo --collection <collection-id>
   ```

   Collection metadata is read with the device credential only. The client resolves the
   name or id to the server-owned stable root, mounts that collection at the top of
   `./My-Silo`, and uses the same cursor, bootstrap, deletion guard, and local-space-saving
   rules as `--include-prefix`. Local state keeps the full remote_path separately so moves,
   deletion guards, and another device remain authoritative. It does not put private keys,
   bearer tokens, ciphertext, or content identities in the selector response.

   To keep the folder current after closing the companion, install a user-level background
   sync task. It uses systemd user services on Linux, a LaunchAgent on macOS, or a least-
   privilege Task Scheduler task on Windows:

   ```text
   python havre_remote.py silo-service install ./My-Silo --interval-seconds 30
   python havre_remote.py silo-service status
   python havre_remote.py silo-service uninstall
   ```

   The operating-system definition contains the server URL, local folder, and retry settings
   only. The bearer token, device token, private key, and recovery material remain in the
   private local Silo state directory. The service does not bypass account, device, or checkout
   gates. Use `silo-service status` to inspect the task without creating a new key.

   To save local space, retain only selected remote folders on this device:

   ```text
   python havre_remote.py silo-sync ./My-Silo --include-prefix Documents --include-prefix Photos/2026
   python havre_remote.py silo-watch ./My-Silo --include-prefix Documents --include-prefix Photos/2026
   ```

   The selection is saved with that local sync root. A later `silo-pull` or `silo-watch`
   reuses it until you pass new prefixes or `--include-all`. Unselected changes still
   advance the tenant-wide cursor without downloading bytes. When you add a prefix, the
   client bootstraps its current metadata and then resumes the ordered feed, so selection
   expansion does not lose files. Narrowing removes only unchanged tracked local copies;
   edited copies are preserved with a visible suffix and remote files are never deleted.

   A tracked local deletion is propagated as a recoverable Silo tombstone only
   after the client confirms there is no newer remote change for that path. The
   foreground watcher retries temporary sync failures with bounded exponential
   backoff; the default is five attempts starting at 15 seconds, and it stops
   visibly after the retry budget is exhausted. Use `silo-move` for an unchanged
   tracked file rename so Silo preserves its file identity and ciphertext instead
   of uploading a second version. An unrecognized local rename remains a safe
   delete plus a new upload. The desktop companion exposes the same setup check,
   device registration, one-shot sync, and foreground watcher as buttons. It also
   opens the canonical recovery-create or recovery-import command in a separate
   terminal. Enter the recovery password only there; the companion never receives
   it. The companion can now install or remove the user-level background sync task for the
   selected folder. The companion remains a thin interface around the canonical client and
   never receives a password or private key.

The client stores its local identity and session under `HAVRE_HOME` or
`~/.havre`. Keep that directory private. A recovery bundle is password-wrapped
locally; Havre does not receive the recovery password or private key.

## Bundle contents

- `havre_remote.py`: HTTPS client, local key handling, device commands, doctor, and sync.
- `silo_book_scanner.py`: bounded local EPUB/PDF/filename ISBN and metadata scan used before
  private book preflight; it never sends plaintext book bytes.
- `silo_service.py`: user-level Linux, macOS, and Windows background sync definitions.
- `envelope.py`: client-side sealed-object encryption and integrity checks.
- `sealed_object.py`: the pure-standard-library sealed-object contract validator.
- `requirements.txt`: the two cryptographic runtime dependencies.
- `silo_desktop.py`: a thin Tk desktop companion that delegates every operation
  to `havre_remote.py`.
- `run-silo.ps1`: Windows PowerShell launcher.
- `run-silo.sh`: macOS/Linux launcher.
- `run-silo-desktop.ps1`: Windows PowerShell desktop launcher.
- `run-silo-desktop.sh`: macOS/Linux desktop launcher.
- `SHA256SUMS`: checksums for the downloaded files.
