# LazyToken — Security Whitepaper

**Audience:** CISOs, security architects, DPO/privacy, and procurement.
**Purpose:** a single, customer-facing document that explains how LazyToken is
built so a security team can approve it — the trust model, what we never collect,
the enforced payload allowlist, the Context Firewall (DLP), air-gapped operation,
supply-chain posture, and ready answers to a security questionnaire.

Companion documents (attach to a DPA): [`DATA-FLOW.md`](./DATA-FLOW.md),
[`NOT-COLLECTED.md`](./NOT-COLLECTED.md), [`DPA-TEMPLATE.md`](./DPA-TEMPLATE.md),
[`SECURITY.md`](./SECURITY.md), and the wire protocol [`CONTRACT.md`](./CONTRACT.md).

> We do not claim LazyToken is "unbreakable" or "100% secure." We claim it is
> built on specific, auditable principles — described below — and that the parts
> that reduce your risk are enforced in code, not just in policy.

---

## 1. The one-sentence narrative

> LazyToken is likely the only software in your stack that is architected so that
> **even if we wanted to, we could not reach your data.** The risk already
> exists: your coding agents send terminal output to a model provider. LazyToken
> is the filter that *reduces and blocks* what leaves — not a new pipe out.

---

## 2. Trust model — the five pillars

### 2.1 Code transparency
The filtering engine that runs on developer workstations is a fork of an
Apache-2.0 open-source project — auditable line by line. The proprietary layer
(reporting, policy, server, dashboard) is available to Enterprise customers for
**source review under NDA**, or via **source escrow**.

### 2.2 "We don't have the data" architecture
The server is **self-hosted in your environment**. The vendor has no tenant, no
copy, and no access. The agent transmits to *your* server only, and only
**numbers and a tool name** — never code, arguments, paths, output, environment
variables, or secrets. This is enforced in code (§4) and, in air-gapped mode, the
server makes **zero** outbound calls.

### 2.3 Minimal privilege
The agent runs as an ordinary user — **no root/admin** for normal operation. It
**does not listen on any port**; it only initiates outbound connections to the
single configured server. Policy is applied **only if cryptographically signed**,
so a compromised server cannot push a malicious configuration. Credentials live
in the **OS keychain**, not in files.

### 2.4 Supply chain
Release binaries are designed to ship **signed** (EV code signing on Windows,
Apple notarization on macOS, GPG on Linux), each with a **CycloneDX SBOM** and
published checksums. CI builds are isolated with provenance where possible.
**Agent updates are distributed only from your internal server** (Ed25519-signed)
— never pulled from the open internet. Upstream syncs pass code review + SAST
before adoption, not a blind merge.

> **Honest status:** installer code-signing/notarization is a release step that
> must be enabled before a regulated rollout (the packaging scripts exist; the
> signing keys/pipeline are an operational task). See the Admin Guide's
> prerequisites.

### 2.5 Process
A published vulnerability-disclosure policy (`security.txt` + a dedicated address
+ a 48-hour response SLA), an annual external penetration test (report under
NDA), SAST on every CI run (Semgrep) plus dependency scanning, and SOC 2 Type I
on the roadmap ahead of serious US-market entry.

---

## 3. What we never collect

Every item below is excluded **by design and enforced in code**. The agent never
transmits:

- Source code — no files, snippets, or diffs.
- Command **arguments** — only the *first word* of a command (`git`, `cat`,
  `npm`); the rest is dropped before it can leave.
- File paths / filenames / directory names.
- Command or terminal **output**.
- **Environment variables** — none, ever.
- **Secrets / credentials / tokens** — and when the Context Firewall detects one,
  it is redacted locally; only the *rule type* (e.g. `aws-key`) is reported.
- Prompts or model responses (LazyToken is not in the prompt path for reporting).
- Keystrokes, screen contents, clipboard.
- Git remote URLs, commit messages, branch names, repository contents.
- IP-based geolocation or device fingerprinting beyond a hashed hostname.

The complete, itemized list is in [`NOT-COLLECTED.md`](./NOT-COLLECTED.md).

**The entire dataset that *is* collected:** numeric token counters, a tool name
(first word), a coarse category, which AI agent was used, a timestamp, filter
timing, and an optional salted project hash. That's it.

---

## 4. The payload allowlist (enforced, not promised)

The privacy rule is enforced on **both** sides of the wire, and the enforcement
**blocks merges**:

- **Agent (Rust):** `agent/tests/payload_allowlist.rs` serializes every payload
  type and asserts no field outside the approved schema can be emitted (plus a
  compile-time-exhaustive match on struct fields). This test is a merge gate.
- **Server (TypeScript):** every ingest body is validated with a Zod `.strict()`
  schema. Unknown keys are **rejected** with `400 INVALID_PAYLOAD` — never
  silently stripped, so a leak is caught in testing rather than quietly passed.

The approved keys per metric record are exactly:
`ts, tool, category, ai_agent, tokens_raw, tokens_filtered, duration_ms,
project_hash`. For security events: `ts, type, tool`. Additional guarantees:
`tool` must match `^[A-Za-z0-9._-]+$` and is capped at 32 chars — no spaces means
**no argument can ride along**. Full schema: [`CONTRACT.md`](./CONTRACT.md) §2.

---

## 5. Context Firewall (DLP) — reducing what reaches the model

Because the agent sits between the terminal and the model, it is positioned to do
more than compress — it can **control what leaves the organization**:

- **Secret redaction.** Every command output is scanned **locally, before it
  enters the model's context**, for API keys, tokens, passwords, connection
  strings, private keys, and high-entropy strings (pattern + entropy detection in
  the style of well-known secret scanners). Matches are replaced with
  `[REDACTED:<type>]`. The original value is **never written to disk and never
  transmitted anywhere**.
- **Command guardrails.** Org policy can block output of sensitive commands/paths
  from reaching the model at all (e.g. `cat` on `**/.env*`) — the model receives
  a short block notice instead.
- **PII masking** (optional, policy-controlled) for emails, IDs, and card numbers
  in output.
- **Event reporting.** The dashboard shows how many secrets were blocked, by team,
  over time — storing **only `{type, tool, timestamp, device}`**, never the value.

This is the security-budget conversation: token savings justify the price; the
Context Firewall makes the purchase a control, not just a cost saver.

---

## 6. Air-gapped operation

LazyToken supports a fully air-gapped deployment (`deploy/AIR-GAPPED.md`):

- Images are carried in as a tar; the license is a **signed file** — there is no
  license server to phone home.
- A Kubernetes **NetworkPolicy** (`networkPolicy.enabled=true`) technically
  restricts server pods to DNS + in-cluster PostgreSQL. You can verify zero egress
  with a simple in-pod `wget` test.
- The **only** optional egress paths are OIDC SSO (your IdP), SMTP, and Slack for
  report delivery — all **off by default** and only to endpoints you configure
  (add them under `networkPolicy.extraEgress` if you turn them on).
- Encryption: TLS 1.3 in transit; at rest, the database is under **your** control.

---

## 7. Anonymization — the employee-monitoring concern

Measuring "how much each developer saved" can be perceived as workforce
surveillance (especially sensitive in the EU / with works councils). LazyToken
ships a built-in **anonymized mode**: the dashboard shows **teams** and
**"Dev #N"** rather than individuals. The choice is the customer's, set at policy
level and recorded in the audit log. Positioning: *managerial visibility without
personal surveillance.*

---

## 8. Security questionnaire — ready answers

Copy-paste answers for procurement/security questionnaires:

| Question | Answer |
|---|---|
| Where is our data stored? | With you only. Self-hosted server; we have no tenant and no access. |
| What does the agent collect? | Numeric counters + a tool name (first word only). Full schema in the data-flow appendix. |
| Is source code / command output sent to a third party? | No. Blocked at the schema level + an automated test. The Context Firewall further reduces what reaches the model provider. |
| Encryption in transit / at rest? | TLS 1.3 in transit; at rest is under your control (the DB is yours). |
| Authentication & authorization? | SSO (OIDC/SAML), RBAC, MFA via your IdP. |
| Audit logging? | Every admin action and policy change; append-only. |
| Agent privileges on the workstation? | Ordinary user, no root, no network listener. |
| Software updates? | Signed, distributed from your internal server only; you control the pace. |
| SBOM / third-party components? | CycloneDX SBOM attached to each release. |
| Penetration testing? | Annual, external; report under NDA. |
| Vulnerability reporting? | `security.txt`; response within 48 hours. |
| Business continuity if the vendor closes? | Source escrow for Enterprise; the system keeps running independently in your environment. |
| GDPR / employee privacy? | No PII by default; built-in anonymized mode; DPA available. |
| Internet dependency? | None. Air-gapped fully supported. |

---

## 9. What we will not overstate (sales discipline)

- Not "unhackable" / "100% secure" — instead: "built to principles X, audited by
  Y."
- We do **not** claim certifications we don't yet hold (SOC 2, ISO 27001). Where
  applicable we say "in progress / on the roadmap."
- We do not promise a security SLA we can't meet — a 48-hour response we honor
  beats a 4-hour one we miss.

---

## 10. Appendices

- [`DATA-FLOW.md`](./DATA-FLOW.md) — end-to-end diagram + plain-language flow.
- [`NOT-COLLECTED.md`](./NOT-COLLECTED.md) — the explicit exclusion list.
- [`DPA-TEMPLATE.md`](./DPA-TEMPLATE.md) — data-processing agreement template.
- [`SECURITY.md`](./SECURITY.md) — disclosure policy and hardening notes.
- [`CONTRACT.md`](./CONTRACT.md) — the agent↔server wire protocol (source of
  truth for the allowlist).
