# Beacons — passive observers for AI activity

Three lightweight collectors that turn ordinary system signals into
**signed, append-only governance receipts**. They are the optional,
opt-in second stage of the AIGovOps Beacon journey:

> **Manual mode** (the [checklist wizard](../checklist/README.md)) →
> **Beacon-augmented mode** (this folder) →
> **Full Studio** (the React UI in `studio/`).

A receipt is the atomic unit of evidence. See
[`docs/RECEIPT_SCHEMA.md`](../docs/RECEIPT_SCHEMA.md) for the wire format.

---

## The three beacons

| Beacon | What it observes | What it does **not** see |
|---|---|---|
| `model_beacon.py` | Egress TCP connections to known AI API hosts (via `psutil.net_connections()`), resolved to PID and process name. | Request bodies. Response bodies. URL paths. |
| `prompt_beacon.py` | Reverse-proxy / SIEM **log lines** that already contain model name, route, and token counts. Privacy-by-default; never opens TLS. | Prompt text. Response text. PII. |
| `artifact_beacon.py` | File-system artifacts with provenance markers (C2PA, "Generated by…" headers, `.ai`/`.assistant` frontmatter). | File contents (only a 1 MiB head hash is recorded). |

All three share `_common.py` for keypair management, RFC 8785 JCS
canonicalization, Ed25519 signing, and NDJSON receipt append.

## Privacy posture

- **No payloads ever leave the host.** Beacons store only metadata
  (host, route, model name, token counts, file hashes).
- The `prompt_beacon` has a `--tls-proxy` stub that explicitly refuses
  to enable TLS-MITM mode and prints the privacy default. If you want
  prompt observability, you operate your own proxy and feed its logs
  into `--log-dir`.
- Keys live in `~/.beacon/keys/ed25519.key` with `0600` perms.
- Receipts live in `~/.beacon/receipts/YYYY-MM-DD.ndjson`.
- The same NDJSON is what the **Studio** home demo ingests, so a beacon
  receipt and a manual-checklist receipt are byte-identical apart from
  the `event_type` and `evidence_meta`.

## Quick start

```bash
pip install psutil pyyaml cryptography

# One-shot scans — handy for testing
python beacons/model_beacon.py --once
python beacons/artifact_beacon.py --path .

# Continuous mode (use systemd in production)
python beacons/prompt_beacon.py --log-dir /var/log/proxy
```

## Systemd deployment (Linux)

```
sudo cp systemd/beacon-*.service /etc/systemd/system/
sudo useradd -r -m -d /home/beacon beacon
sudo install -d -o beacon -g beacon /var/lib/beacon
sudo systemctl daemon-reload
sudo systemctl enable --now beacon-model.service beacon-prompt.service beacon-artifact.service
```

Logs go to `journalctl -u beacon-model`. Receipts go to
`/home/beacon/.beacon/receipts/`.

## From beacon to bundle

The Studio "Publish bundle" action concatenates today's NDJSON, the
manifest, and the signing chain into a single sealed bundle. The
beacons do nothing magical here — they just keep the NDJSON stream
fed with evidence whether or not a human is at the keyboard.
---

## Contact & community

**Tagline:** YES-Ship AI · YES-Steady AI · YES-Recover AI

- Bob Rapp — [bob.rapp@aigovops.community](mailto:bob.rapp@aigovops.community)
- Ken Johnston — [ken.johnston@aigovops.community](mailto:ken.johnston@aigovops.community)
- Foundation — [aigovopsfoundation.org](https://www.aigovopsfoundation.org/)

*Verifiable AI governance — Apache-2.0, no SaaS lock-in.*
