lc asked in #feedback (message 1558300896142696549) for magpie's masking to cover more of what identifies a person or a machine. Under Settings > Privacy > Mask personal data, each kind now has its own Off/On (settings.redactKinds, redact.Options.Kinds). What each one masks: - US SSNs: dashed numbers, except ones never issued (000, 666 and 9xx areas) and well-known examples. Undashed ones only next to "SSN" or "social security". - Passport numbers, next to passport, Reisepass, 护照 or パスポート. - IBANs: compact or in groups of four, with the country's length and the mod-97 check. - Birthdays: a date only next to birthday, DOB, born, 生日 and the like. A date on its own stays. - MAC addresses, but not documentation examples or all-decimal groups. - Serial numbers, next to S/N, serial or 序列号. - The user name in /Users/x, /home/x and C:\Users\x. The name is masked and the path is kept. - User and host in a shell prompt or an ssh/scp/rsync target (user@host goes out as two placeholders, not as an email address), and on hostname/user lines whose value ends the line. Code such as `hostname = socket.gethostname()` is left alone. - Public IPv4 and IPv6 addresses. Private, loopback, link-local, CGNAT, documentation, multicast and well-known resolver addresses stay, and so do version numbers. - Cloud bucket names in s3://, gs://, oss://, cos://, abfss:// and storage URLs. The object path is kept. The last four are off by default. Agents send their working folder, the prompt and log lines in nearly every request, and the model then has to copy the placeholder exactly inside a path or URL. The first six are rare and sensitive, so they are on. Each placeholder is restored in replies, in streamed text and in tool-call JSON. Context rules run only in a window around their words (rule.matches), so masking with the defaults on 400KB of app.js takes 136ms (112ms before; 222ms with every kind on). Tests, run at this head: - gofmt -l is clean. go vet passes on darwin, GOOS=linux and GOOS=windows (-tags nogui) for internal/redact, gateway, gui and settings. - go test -tags nogui ./... under a temp HOME with pinned caches passed everywhere except internal/proc's TestNoCommandBypassesProc. That failure came from2da8fbe4, andb934d64afixed it on main. After the rebase, the changed packages and internal/proc were run again and passed. New tests: - internal/redact TestMoreKinds, TestMoreKindsLeaveAlone (versions, timestamps, hashes, UUIDs, model ids, code, ordinary dates, URLs in code), TestCategoryDefaults, TestMoreKindsKnown, TestMoreKindsJSON. - internal/gateway TestRedactedKinds. - internal/gui TestRedactKindsAreRedacts. - I broke the IBAN checksum by hand and TestMoreKindsLeaveAlone went red. - GUI tests pass in Chromium and WebKit: - the new redact-kinds.test.cjs (en, zh, zh-TW, ja and de, at 1100 and 640 px); - i18n-keys, gui-de, gui-ja, gui-zh-tw, redact-rule-row, privacy-hides-accounts, privacy-usage-stats, settings-groups, settings-sections and mobile-web; - 29 more files that open the Privacy page (252 tests). privacy-usage-stats now scrolls with the wheel to reach Count me as a user, which the new rows push below its 760px window. WebKit doesn't let a script scroll Settings. - Real gateway check: a `magpie serve` built from this tree, under a sandbox HOME, on 127.0.0.1:3492, with a fake OpenAI upstream on 3491. An Anthropic /v1/messages request went to the upstream with each kind as a placeholder. Turning SSNs off and home folders on changed what was sent the same way. The streamed reply came back with every value restored.
Subsystem design references
These pages describe current responsibilities, runtime paths, state, and contracts. Start with the subsystem relevant to your task, then follow its source links to verify the implementation you change.
| Subsystem | Reference |
|---|---|
| Built-in subscriptions moving to plugins | Provider and plugin ownership |
| Plugins that run on the gateway's requests and replies | Gateway middleware |
| Claude subscription turns across Claude Code runs | Claude subscription bridge |
| How the gateway picks a provider, key or account, and falls back | Gateway routing and fallback |
| Gateway Session Aggregation | Gateway Session Aggregation |
| Connecting an agent's config to the gateway, drift, disconnect, WSL twins | Agent wiring |
| Providers, keys, subscription accounts, refresh and allowance | Providers and accounts |
| Instructions, MCP servers, skills and RTK written into agents | Library |
Tray, panel, window, magpie web and the page's JSON API |
GUI app shell |
A subsystem can span several packages or repositories. Its reference describes the behavior those parts provide together; it does not need to list every function.
Maintain a reference
Update the owning reference in the same PR when a change alters a documented responsibility, interface, state transition, runtime path, compatibility rule, or failure behavior. An internal refactor that preserves these contracts does not require a prose change.
Keep each fact in one reference and link to it from agent instructions or other pages. Link to source files and named symbols rather than copying implementation details that change frequently. Explain field meanings and constraints that signatures alone do not express.
For a new reference, include the responsibilities and boundaries, source of truth, main runtime paths, state transitions, important constraints, and existing verification commands. Include failure and compatibility behavior where relevant. Document current behavior separately from proposed changes; the proposal belongs in its issue or PR.
Describe a PR's semantic changes
For each affected subsystem, explain the observable change with its trigger and before/after behavior. Include changes to interfaces, state, compatibility, and failure behavior when relevant. Link the affected reference, implementation, and verification evidence. State when a refactor preserves the documented behavior.
For example, a change to plugin adoption should explain which migration state and account condition trigger it, which implementation handles requests before and after adoption, and which test exercises that transition.
This is an author-provided explanation that a reviewer verifies against the diff and surrounding code. It is not an automatically proven compatibility verdict.
Review a change
- Identify the affected subsystem and the actual runtime path, including plugin or built-in ownership.
- Compare the claimed before/after behavior with the base and head implementation. Trace relevant callers and state transitions beyond the changed lines.
- Check that changed contracts appear in the owning reference and that source links still resolve.
- Check that the cited tests or runtime evidence exercise the claimed behavior. Report checks that were not run.
A documentation update alone does not prove the implementation. Existing tests and runtime evidence remain necessary for behavior changes.