audit fixes: checked types + curated lint; install-mcp drift guard; strict policy keys; transport credential guard#77
Merged
Conversation
…trict policy keys; transport credential guard
Three fixes from the 2026-07-14 module-by-module audit.
1. Annotations become a CHECKED contract. [tool.ruff.lint] curated select
(I/B/UP/C4/SIM/RET/PLE on top of the defaults) + a lenient [tool.mypy]
baseline, both in CI. Burn-down: 114 ruff findings (96 auto), 17 mypy
errors - several real: pump()'s src annotation claimed TextIO but receives
an Iterator from HttpTransport; answer_retrieve indexed the drop store
with a possibly-None handle; text_diff reused a loop variable across int/
int|None types; an invalid 'type: ignore' comment in _emit_audit was
silently not suppressing anything.
2. install-mcp drift guard. A re-wrap used to rebuild the entry purely from
the stashed original, silently reverting hand-edits to the WRAPPED entry
(reverted codegraph's node@22 env.PATH pin in production, 2026-07-13).
wrap() now carries live non-terse-owned keys forward (command/args still
rebuilt; url/headers never resurrected), do_install reports what it
preserved, and the CLI prints it with the uninstall caveat. USAGE updated.
3. Hardening pair.
- load_policy rejects unknown keys at every level ('_'-prefixed
annotations exempt - the policy_gen convention). Immediately caught a
latent specimen: a multiproxy test's policy file used 'rules' (schema
says 'policies') and the old loader silently ignored it.
- HttpTransport refuses credential-bearing headers (authorization/token/
key/secret/cookie) over cleartext http to a non-loopback host - parity
with fluency.openai_answerer's TLS guard. Loopback gateways unaffected.
476 tests pass (+5), ruff clean, mypy clean, live policy file verified
against the strict loader.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three fixes from the 2026-07-14 module-by-module audit, approved as a batch.
1. Annotations → checked contract
[tool.ruff.lint]curated select (I,B,UP,C4,SIM,RET,PLEon top of defaults) — the repo previously ran ruff's minimal defaults with no config at all.[tool.mypy]lenient baseline (ratchet later), added to the CI lint job;mypyin dev deps.zip(..., strict=)chosen per real semantics at each site). 17 mypy errors, several genuinely load-bearing:pump()claimedsrc: TextIObut receives anIterator[str]fromHttpTransport→ nowIterable[str](the actual contract);answer_retrievecould index the drop store with a non-strhandle from a malformed call → explicit miss;# type: ignorecomment in_emit_audit(trailing prose broke the syntax) was suppressing nothing → replaced with real narrowing.2. install-mcp drift guard
A re-wrap rebuilt the entry purely from the stashed original, silently reverting hand-edits to the wrapped entry — this reverted codegraph's node@22
env.PATHpin in production on 07-13.wrap()now carries live non-terse-owned keys forward (command/argsalways rebuilt;url/headersnever resurrected from a drifted entry),do_installreports the preserved keys, the CLI prints them with the uninstall caveat, USAGE updated. Regression test reproduces the codegraph scenario exactly.3. Hardening pair
load_policyrejects unknown keys at every level (_-prefixed annotations exempt — thepolicy_genconvention). It immediately caught a latent specimen in our own tree: a multiproxy test's policy file used"rules"(schema says"policies") and the old loader swallowed it.HttpTransportrefuses credential-bearing headers over cleartext http to a remote host — parity withfluency.openai_answerer's existing TLS guard. Loopback gateways and https unaffected.Verification
ruffclean at the new bar,mypyclean.