Prompt hasil diskusi dengan Claude Code CLI yang dipakai untuk membangun workspace awal Privyx. Teks ini merupakan arsip rancangan awal; implementasi project berkembang setelahnya.
Build Privyx, a Python 3.12 privacy proxy for LLM APIs. It sits between a client and OpenAI or Anthropic, replaces secrets and personal data in the request with placeholders, and puts the original values back into the reply. The client only changes its base URL.
The first version is a library plus a CLI. The privacy engine must not import FastAPI or a provider SDK.
Pipeline, all behind small protocols: detect, decide, pseudonymize, save the mapping, forward, restore. A request and its reply share one session.
- Detector `regex` ships patterns for email, phone, credit card (Luhn), IPv4, SSN, and secrets: vendor API keys, JWTs, PEM private keys, Bearer tokens, URL passwords, and values assigned to names like password or api_key. `yaml` uses only the patterns the user lists. A `(?P<value>)` group masks just that group. `terms` is a case-insensitive word list per entity.
- Policy `default` masks every finding. `strict` masks only the entity types listed in `allowed`.
- Operator `pseudonym` writes `<PRIVYX_EMAIL_1>`. The same value keeps the same number inside a session. `hash` uses a short SHA-256 id. `redact` writes `[REDACTED]` and cannot be restored. An HMAC anchor secret makes pseudonym ids stable across sessions. An empty secret means no anchor.
- Vaults: `memory`, `sqlite`, `redis`, one protocol. The vault stores the original value.
Proxy, two modes. `transparent` mirrors the client path on the upstream origin and relays the client's API key. `gateway` posts every served path to one configured URL and sends only Privyx's key. Mask `/v1/chat/completions`, `/v1/messages`, and `/v1/responses`, including text, tool results, and tool-call arguments. Leave `model` and sampling settings alone. Forward any other path unchanged. If masking fails, do not forward the request.
Streaming must survive a placeholder split across SSE chunks. Hold back a partial token and release it only when it is complete or the stream ends. Restored stream text must equal a batch restore of the same text. Cover OpenAI Chat Completions and Anthropic Messages.
Session: header `x-privyx-session` wins. Otherwise `ephemeral` (one session per request, the default), `client` (one session per API key), or `conversation` (API key plus the first user message). `privyx run` defaults to `conversation` and creates an anchor secret on first use.
CLI: `privyx proxy`, `privyx run claude|codex|openai|aider` (free local port, stop the proxy when the tool exits), `privyx detect`, `privyx mask` / `unmask` for text and JSON without a proxy, `privyx config`, `privyx doctor`. Config is YAML, then `PRIVYX_*` environment variables, then flags. Unknown settings fail at startup.
Plugins load from local paths and register a detector, policy, operator, vault, or provider by subclass. A plugin cannot replace a built-in name.
Tests: unit tests for detection and restore, plus Hypothesis tests that any chunk split restores the same text as batch. `ruff` and strict `mypy`. Package with hatchling as `privyx`, extra `sqlite`, `redis`, and `dev`.
Do not add authentication, image scanning, or a Gemini schema. Bind the proxy to 127.0.0.1.