Skip to main content
Jenks Guo

Docs / explanation

Security and privacy

What the public and admin interfaces can do, how SSO, agent service tokens, the audit log and GitHub access protect them, 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, and the AI agents he gives a token to. /api/admin/*, /mcp/admin, jenks admin … and the console can validate, write and delete content files, upload and delete media files, and promote dev to main. That is real power, so there are three layers.

Sign-in for people: SSO

The console is at https://admin.jenksguo.xyz/admin (and https://admin.dev.jenksguo.xyz/admin for the dev site). Cloudflare Access stands in front of those hosts: nobody reaches the console until they sign in with an allowed Google account. /admin on every other address redirects there.

The Worker does not simply trust Cloudflare's headers. On every admin request it checks the signed Access token itself — the signature against the Access team's public keys, the application's audience tag, the issuer and the expiry — and the email must be on the admin list.

Service tokens for agents

An AI agent never uses Jenks's sign-in. Jenks creates a service token for each agent in the console (Access → New agent token):

  • Named — "Claude Code on MacBook", so the audit log says which agent did what.
  • Scoped — content (content, translations and site copy), media (the media library), publish (write straight to production and promote dev → main). Every token can read. Without publish, an agent saves to dev and Jenks promotes the change.
  • Expiring — 30 to 365 days (90 by default).
  • Revocable — one click, effective on the next request.
  • Tied to SSO — only a person signed in through Access can create, list or revoke tokens; an agent token cannot make another token. A token also stops working if the person who made it is no longer an admin.
  • Stored as a hash — the token is shown once, when it is created; the database keeps only its SHA-256 hash.

Agents send the token as Authorization: Bearer jgx_agt_… to /api/admin/* or /mcp/admin on https://jenksguo.pages.dev (Access would stop a program on the admin host). Browsers do not send such a header on their own, so a malicious page cannot borrow it.

The audit log

Every admin write — and every refused attempt — is recorded: who (an email or agent:<name>), which tool, which files, branch, host, and the result or error. Token creation and revocation are logged too. File contents are never logged. Jenks reads the log in the console (Access); an agent can read only its own entries (admin_audit_log). Git history remains the record of what changed in the content itself.

The break-glass admin token

The original admin token still works, for emergencies, but it cannot create agent tokens. It lives in the macOS Keychain as agent-env:JENKSGUO_ADMIN_TOKEN and as an encrypted Worker secret, and is compared in constant time. Rotate it if it may have leaked: store a new value in the Keychain and the Worker secret, and the old one stops working at once. For local development only (wrangler dev on localhost) the console can sign in with it: the token is exchanged once for an HttpOnly session cookie.

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.

Media files

Images, videos and PDFs uploaded through the admin interfaces are stored in a Cloudflare R2 bucket and served from /media/…. They are public by address from the moment they are uploaded, so only material meant for every visitor belongs there.

  • The file type is detected from the bytes, not the name, and only web image, video and PDF formats are accepted (25 MB each).
  • SVG images are refused if they contain scripts or event handlers, and every SVG is served inside a content-security sandbox, so even a crafted SVG opened directly cannot run code on this site.
  • Unlike content, media is not in git: deletion is permanent. Deletes are refused while published content still uses the file.

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 records every change — what changed, when, and why (the commit message; the commit trailer names the agent),
  • 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 is off until the visitor taps the mic, and it switches itself off after ten turns or when it hears no real conversation. Voice input uses the browser's own speech recognition where available; otherwise audio is sent to OpenRouter for transcription. Spoken replies are generated by Cloudflare Workers AI (Deepgram Aura-2, English) or OpenRouter (other languages), with the device's speech synthesis as a fallback. No recordings or generated audio are stored.
  • 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.

.md