# Hosted viewer

> Serve the Hansard app to other devices on a trusted network, with a password and read-only access.

`hansard web` serves the app in a browser. By default it answers only on this
machine. You can serve it to other devices on a network you trust, such as a
home network or a VPN. Hosting is a CLI feature.

- CLI: `hansard web --host`

Anyone who signs in to a hosted viewer can read the whole archive: every
conversation, memory, and attachment preview. Hansard has one password per
viewer and no per-user, per-repository, or per-conversation permissions.

## How the default viewer is protected

```sh
hansard web
```

Without `--host`, the viewer listens on `127.0.0.1:7824`, which other devices
cannot reach. Hansard opens the browser with a random token, which the browser
exchanges for a sign-in cookie. Viewing, searching, and importing need no
network service.

Browsers send that cookie with requests from any page on `127.0.0.1`, including
pages that other local servers serve. The viewer therefore refuses every
request that changes data when the browser reports that it came from a page
other than the viewer's own. Command-line clients send no such report and are
not affected.

To start the viewer without opening a browser, or on another port:

```sh
hansard web --no-open --port 7825
```

## Confirm answers and approvals in a browser

Agents on this computer run as your user account, so they can read the sign-in
token. Some actions must come from you, never from an agent:

- Answering an agent's question or approving its tool call.
- Approving a hosted assistant or a paired device, or changing what it reaches.
- Accepting a team's rules, admitting or revoking a team device, and accepting
  a relay change.
- Confirming your Personal Sync devices.
- Sending words as you, such as a note, a composer message, or terminal keys.

In the Mac app, the window itself shows that the action is yours, so no prompt
appears.

In a browser, the first of these actions opens **Confirm it's you**, and
`hansard web` prints a code in the terminal where it runs:

```text
Hansard: a browser tab asks to answer as you. Type ABCD-EFGH in that tab within 5 minutes.
If you did not just answer or approve something in a browser, ignore this code.
```

Type the code in the tab and select **Confirm**, and Hansard finishes the
action. A code works once, only in the tab that asked for it, for 5 minutes.
After five wrong codes, select **New code** to print another.

The tab stays confirmed for up to 12 hours. Reloading the tab or restarting
`hansard web` ends it, and the next action asks for a new code.

Hansard offers codes only when you start `hansard web` in your own terminal.
If an agent started the viewer, or its output does not reach a terminal, answer
in the Mac app or start `hansard web` yourself.

The matching commands, such as `hansard peers answer`,
`hansard team accept <name>`, `hansard team devices <name> --admit`,
`hansard remote host pair`, `hansard device pair`, and
`hansard personal-sync devices --confirm`, work the same way. They run only in
your own interactive terminal, never in an agent's shell.

## Serve the viewer on your network

> **Do not expose the viewer to the public internet:** The viewer speaks plain HTTP and has no TLS. Keep it on a trusted network or
> a VPN, or put it behind a reverse proxy that adds TLS and access control.

1. Choose a long, unique password and start the viewer with it in the
   environment:

   ```sh
   HANSARD_WEB_PASSWORD='replace-with-a-long-random-password' \
     hansard web --host 0.0.0.0 --read-only --no-open
   ```

   In Windows PowerShell, set the environment variable on its own line:

   ```powershell
   $env:HANSARD_WEB_PASSWORD = 'replace-with-a-long-random-password'
   hansard web --host 0.0.0.0 --read-only --no-open
   ```

   Every address other than loopback requires a password, and the viewer
   refuses to start without one. `--host` with no value listens on all
   interfaces. `--password` also works, but your shell history keeps it.

2. Limit who can connect. Allow only the devices you intend at the firewall,
   VPN, or reverse proxy. Terminate TLS before traffic leaves the machine.

3. On the other device, open the served address and sign in with the password.

The sign-in cookie lasts up to 30 days, but password sign-ins live in the
viewer's memory. Signing out, or restarting the viewer, ends them. Restart the
viewer to sign everyone out after you change the password.

## What remote visitors can do

- Read and search everything in the archive the viewer can access.
- Nothing that changes data. Hansard refuses changes from any address other
  than this machine, with or without `--read-only`.

`--read-only` also blocks changes that arrive from this machine. Use it when a
reverse proxy on the same machine forwards remote traffic, because Hansard sees
that traffic as local.

Account names and emails from plan usage tracking appear only to browsers on
this machine. Read-only mode does not narrow what visitors can read, and it
cannot stop a browser, proxy, or screenshot from keeping a copy.

Hansard compresses conversations and Stats with gzip for browsers on other
devices. Traffic from a reverse proxy on this machine looks local and arrives
uncompressed, so turn on compression in the proxy if its clients need it.

## Keep the viewer running

The viewer stops when the terminal that started it closes. To keep it running
after that, add `--keep-alive`:

```sh
HANSARD_WEB_PASSWORD='replace-with-a-long-random-password' \
  hansard web --host 0.0.0.0 --read-only --no-open --keep-alive
```

In PowerShell, set `$env:HANSARD_WEB_PASSWORD` as above, then run
`hansard web --host 0.0.0.0 --read-only --no-open --keep-alive`.

The Mac app starts its own private viewer on this machine and does not use
these settings.

## Checklist

- Bind to the narrowest address and firewall rule that works.
- Keep the Hansard password on even when a proxy also asks for sign-in.
- Use TLS on any path that leaves the machine.
- Run shared viewers with `--read-only`.
- Treat proxy logs, browser caches, and screenshots as copies of the archive.
