Skip to content

feat: give project plugins each module's functions with their span and entry point - #118

Merged
SizzleUnrlsd merged 2 commits into
mainfrom
feat/project-functions
Sep 24, 2026
Merged

SizzleUnrlsd merged 2 commits into
mainfrom
feat/project-functions

Conversation

@SizzleUnrlsd

Copy link
Copy Markdown
Contributor

Closes #116. Replaces #117, which GitHub closed when its base branch release/0.4.0 was deleted on merging #115; same two commits, now against main (released as 0.4.0).

Why

Needed by the enterprise exposure-prioritization plugin (CoreTrace-Entreprise/coretrace-python-analyzer-plugins#4). A project plugin could not place a finding in the call graph: findings carry bare function names (get, not Admin.get), the context's call graphs are rebuilt from call sites without definitions (no spans), and nothing said which functions are entry points. The engine now provides those facts; the ranking policy stays in the plugin.

What

  • ModuleFunction(name, span, entry_point) in coretrace_python.interprocedural: the call graph's name, the span, the entry point's label (http, argv, ...) or None.
  • function_entry_point(...) extracted from parameter_sources (decorator or base matching an EntryPoint model, or a registration elsewhere); parameter_sources now calls it, behaviour unchanged.
  • EntryPointAnalysis (taint.entry_points) applies it to every function of the module, with the factory instances and registered routes the taint engine uses. It reads the project summaries, so it joins the analyses ProjectSummariesUpdated invalidates.
  • CachedModule.functions holds the records (cache format 5 → 6); ProjectContext.functions(module) serves them, falling back to the module's manager like call_graph() does.

Tests

tests/test_project.py: names, spans and labels of a Flask module (<module>, index = http, helper, Admin.get); a Django view registered in urls.py is http, an unregistered function is not; the route of an app built by create_app() in another module is http; a module served from the cache gives the same records. The two cache codec tests build CachedModule from records (the heap one only checks summaries, so it passes none).

932 passed; ruff and mypy clean. Plugin guide documents ctx.functions(module) (and fixes ctx.modules() → ctx.modules, a property). Changelog entry under a new Unreleased above 0.4.0.

Every function as the call graph names it, with its span and the label
of the entry point it is: a Flask route, a Django view registered in
another module, a route of an app made by a factory in another module,
and the same answer from a module served from the cache. The cache codec
tests build CachedModule from the new function records.
…d entry point

A finding names its function by its bare name and the project context's
call graphs carry no definitions, so a project plugin could not place a
finding in the call graph, nor tell a route from a helper.

ModuleFunction(name, span, entry_point) records each function as the call
graph names it. EntryPointAnalysis decides the entry point with the taint
engine's own rule, extracted from parameter_sources as
function_entry_point, and is invalidated with the project summaries it
reads. The records are cached with the module (format 6) and served by
ProjectContext.functions(module).

Closes #116
@SizzleUnrlsd SizzleUnrlsd self-assigned this Sep 24, 2026
@SizzleUnrlsd
SizzleUnrlsd merged commit 3b98ce7 into main Sep 24, 2026
15 checks passed
@SizzleUnrlsd
SizzleUnrlsd deleted the feat/project-functions branch September 24, 2026 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plugin API: give project plugins each module's functions with their span and entry point

1 participant