Skip to main content

Module scan

Module scan 

Source
Expand description

Static scanning — the first of the three evidence sources behind keel init and keel doctor (dx-spec §2). No code runs: we read the project’s source and find where effects enter.

Two scanners, one merged result:

  • python shells an ast-walker out to python3 - for precise Python parsing (imports of known effect libraries, URL/DSN string literals).
  • js parses JS/TS/JSX in-process with oxc (no Node toolchain needed) for fetch/undici/node:http usage, provider-SDK imports, effect-lib call sites, and URL literals.

Both label every finding with file:line, so the generated keel.toml can cite where each target was found and trust stays inspectable.

Modules§

js
The JS/TS static scan — a real parse on oxc.
python
The Python static scan: an ast-walker executed out-of-process via python3 -.

Structs§

CallSite
One effect call site with enclosing-function attribution — an internal detail of the JS/TS pass (js), which uses it to verify its real scope-chain tracking (dotted paths like Class.method) independently of the coarser top-level-only FunctionFacts attribution keel flows suggest consumes. Not exposed on ScanResult. Field order is the sort order (file, then line).
DepAverseFile
One file the scan judged dependency-averse: stdlib-only imports plus a risk/gate/guard/auth/valid/safety/kill name or docstring signal, or an explicit # keel: exclude marker. Markers win in both directions: an exclude marker forces this classification regardless of imports, and an include marker defeats the heuristic even where it would otherwise match. keel doctor/keel init (a later program task) use this to honestly exclude hosts seen only in such files from proposed policy. Field order is the sort order (by file).
FunctionFacts
Per-function effect attribution — the evidence behind keel flows suggest.
LangFindings
One language scanner’s raw findings before host-gating.
OrchestrationSighting
One hand-rolled orchestration construct sighted in a file the language passes never parse — shell scripts, Makefiles, CI workflows. Coarse by design: a substring line match, not a parse, so it is a lead to inspect, never a verdict. kind is a closed set: “lockfile-mutex” | “guard-file” | “pid-check”. Field order is sort order.
ScanResult
The merged output of both scanners.
Sighting
One place a target was seen: a project-relative path and 1-based line.
SimplificationSighting
One hand-rolled resilience pattern sighted inside a function that also reaches a Keel-relevant target — a simplification lead: once the target is wrapped, the pattern becomes redundant. kind is a closed set: “hand-rolled-retry” | “hand-rolled-poll” | “silent-swallow”. line anchors the construct to delete (the loop / the except line), not the sleep call inside it. Python-only as of this build (JS pattern parity is a spec’d follow-on program).
SubprocessSighting
One externally-launched process the scan saw — traffic inside it is outside Keel’s visibility regardless of policy. Field order is the sort order (file, then line).
TargetEvidence
A target and everywhere the static scan saw it, deduplicated and ordered.

Enums§

TargetClass
What kind of target a sighting resolves to. Governs the policy block keel init writes (an llm:* target gets the LLM pack; a host gets the outbound pack).
TransportClass
How a sighted host’s traffic is dispatched, best-known across sightings. Ordering is meaningful: Tracked < UntrackedKnown < Unknown, so merging (min) always keeps the most favorable class seen for a host across every file/language that sighted it. This is what keel doctor (a later program task) uses to say honestly what Keel can and cannot see: a host is Tracked if some sighting reached it through a registry-adapted library, UntrackedKnown if the best reach was a known-but-unadapted transport (http.client, or urllib without urllib.request; Python’s urllib.request itself is adapted), and Unknown if no transport evidence was found near any sighting at all.

Functions§

scan
Scan project with both scanners and merge. Host targets are only emitted when the language pass also saw an HTTP client in use (a bare URL in a non-networked file is not evidence of an outbound call), keeping the output honest.