# Security and privacy

> What the public and admin interfaces can and cannot do, how the admin token and GitHub access are protected, and what happens to visitor data.

## Two kinds of access

**Public** — anyone, no credentials. The REST API (`/api/v1/*`), the public MCP server (`/mcp`), the
CLI's public commands and the static files are **read-only**. They expose only the published corpus,
which is public by design. `ask_jenks` and the website chat call a language model, so they are
rate-limited per IP address to stop abuse.

**Admin** — Jenks only. `/api/admin/*`, `/mcp/admin`, `jenks admin …` and the console at `/admin`
require Jenks's personal admin token in an `Authorization: Bearer` header. With it, a caller can
validate, write and delete content files and promote `dev` to `main`. That is real power, so the
token is treated like a password.

## The admin token

- It lives in the macOS Keychain as `agent-env:JENKSGUO_ADMIN_TOKEN` and is loaded into a shell only
  when needed. It is never written into content, commits, config files that get shared, or chats.
- The Worker stores it as an encrypted secret and compares it in constant time.
- The `/admin` console never stores the token. Signing in posts it once to `/api/admin/login`, which
  sets an `HttpOnly`, `Secure`, `SameSite=Strict` session cookie (12 hours, or 14 days with
  "remember"). Page scripts cannot read that cookie, and cookie-authenticated writes must also send
  an `x-jenks-admin` header, which a cross-site form cannot set.
- **Rotate it** if it may have leaked: generate a new token, store it in the Keychain, update the
  Worker secret, and the old one stops working immediately — along with every console session,
  because sessions are signed with a key derived from the token.

## What the admin API can touch

Writes are limited to an allowlist of content paths — the corpus entries, lenses, skills, core
documents, the translation glossary and these docs. It cannot change code, workflows, secrets or
anything outside `content/`. Every write is validated against the content schema first.

## GitHub access

Admin writes become commits through the GitHub API using a fine-grained personal access token scoped
to the single repository, with only the permissions publishing needs. It is stored as an encrypted
Worker secret. Because every change is a commit:

- **git history is the audit log** — who changed what, when, and why (the commit message),
- **undo is always possible** — any earlier version of any file can be restored.

Risky changes can be staged on the `dev` branch and checked on `https://dev.jenksguo.xyz` before
anything reaches the live site.

## Visitor privacy

- No advertising trackers and no marketing cookies.
- The chat transcript is kept only in the visitor's browser (`sessionStorage`) and cleared when the
  tab closes. The site does not store chat transcripts.
- Chat messages are sent through the Cloudflare Worker to **OpenRouter**, which routes them to a
  third-party language model. Visitors are asked not to share sensitive personal information.
- Voice input uses the browser's own speech recognition where available; otherwise audio is sent to
  OpenRouter for transcription. Spoken replies use the device's speech synthesis.
- Cloudflare keeps standard request logs for security and rate limiting.

## Content privacy

Everything under `content/` is public. Jenks's résumés contained phone numbers, a home address and
referee contacts; none of those are in the corpus, and they must never be added. Facts about other
people are limited to what is needed to describe Jenks's roles.

## Reporting a problem

Email jenksguo@gmail.com with details. Please do not test the admin interface without permission.
