"Give the brain a window into the vault, not a key. It can look at everything and change nothing."
Two locks on the same door
Pippa needs to see the portfolio to answer questions about it, but it must never touch it. Keep enforces that with two independent locks. First, the host adapter is read-only: it exposes exactly three capabilities — status, read, and search — and no write path at all. Pippa cannot mutate holdings, cash, seeds, watchlists, or simulation runs, because there is literally no adapter method that would let it. Second, the internal Sidekick API is loopback-only: /api/internal/sidekick/* answers only to requests originating from 127.0.0.1, so nothing off-machine can reach it even if it somehow found the URL.
Why 'no write method exists' beats 'writes are checked'
There are two ways to prevent the brain from writing: check permissions on every write, or simply don't build a write path. Keep chose the second, and it's meaningfully stronger. A permission check can be misconfigured, bypassed by a new code path, or forgotten on the next endpoint someone adds. But a capability that doesn't exist can't be misconfigured — there's no method to call, no flag to get wrong. The read-only adapter isn't "writes are denied"; it's "writes are unrepresentable." Least privilege at its cleanest is not a guard on a dangerous power, but the absence of the power entirely.
Why loopback-only is the second, independent lock
Read-only handles "what can Pippa do to the data." Loopback-only handles "who can even reach this door." The internal Sidekick endpoints trust a scheme that only makes sense on the local machine, and the server is configured so that trust is only granted for genuinely-local requests (forwarded_allow_ips=127.0.0.1 makes the proxy header trustworthy). Even a perfectly read-only API shouldn't be reachable from arbitrary network locations, and even a loopback-only API shouldn't be able to write. The two locks defend different threats, so you keep both — belt and suspenders, on purpose.