Skip to content

Rules engine + shipped ruleset, at parity with python #72

Description

@rahlk

Is your feature request related to a problem? Please describe.

TypeScript has no entrypoint detection. grep -rniE "entry_?point" src/ returns one hit, and it is a bundler comment in src/dataflow/pool.ts. The fields were de-advertised in #60 precisely because nothing populated them; this issue is the work that earns them back.

Without it the analyzer emits a call graph with no distinguished roots, so a consumer cannot ask what is reachable from outside the application — the first question any taint or attack-surface query asks.

codeanalyzer-python shipped this as its #27: a codeanalyzer/entrypoints/ package (5 files), 73 source references, PyEntrypoint/PyEntrypointReport, is_entrypoint and entrypoint_frameworks on two Neo4j labels, and --entrypoint-rules.

Design: docs/design/specs/entrypoint-detection.md.

Describe the solution you'd like

Per the spec's decomposition; each becomes its own PR, filed just-in-time.

  • TSEntrypoint/TSEntrypointReport schema, Neo4j is_entrypoint/entrypoint_frameworks, and the level-free L1 post-pass skeleton emitting an empty report
  • Stage-0 framework gate over TSImportTSDependency, populating frameworks_detected
  • Rules file format, loader, --entrypoint-rules, and the decorator matcher (ships NestJS + Angular)
  • Base-class matcher over resolved extends_ids/implements_ids, with dispatch: and via:
  • Call-site, file-convention and manifest matchers — the TypeScript-specific ones

Describe alternatives you've considered

Not stated in the original issue.

Additional context

Scope boundary

This issue is a rules ENGINE plus a shipped ruleset, not a pair of framework finders. Its previous title ("entrypoint finders (Express/Angular routes)") named two frameworks and no engine; built that way it would produce hardcoded detectors with no rules file, no confidence grading, no coverage report and no user extensibility, then need rewriting to reach parity.

The other half of #60 is already done and is NOT in scope. Top-level invocation roots are in the call graph: module-scope calls are attributed to the MODULE (src/semantic_analysis/callGraph.ts:161, python #131 parity). Verified — a module-scope boot() now yields can://…/app.ts -> can://…/app.ts/boot with prov: ["tsc"].

Not in scope: taint or reachability queries over the entrypoints (those are frontend SDK concerns).

Caveats and known risks

Python's engine cannot be ported as-is. It has two matchers, decorators and base classes, which cover its ecosystem. TypeScript needs three more with no python analog:

framework declared how matcher
NestJS, Angular decorators python has it
Express, Koa, Fastify app.get('/p', h) — a call call-site
Next.js, Remix, SvelteKit app/**/route.ts, +server.ts file convention
AWS Lambda exported handler export name
CLI tools, packages bin/main in package.json manifest

The rules format must be designed for those from the start, not copied from python's rules.yml.

  • Under-approximation is the designed failure mode and is invisible without the report. Ship TSEntrypointReport in the same change as detection, never after — a framework the ruleset misses looks identical to a project with no entrypoints.
  • False positives are worse than misses. A locally defined Controller decorator in a non-NestJS project must not register. The stage-0 gate is what prevents that, so it is not an optimisation.
  • The call-site matcher is the weakest link; it should ship at confidence: heuristic. Express handlers registered through a variable (const r = express.Router()) or a helper will be missed, and that belongs in the report's unresolved counts.
  • Two decisions are open in the spec: whether a file-convention entrypoint may hang off a module (python has no module-level entrypoints, so this diverges from the shared vocabulary and should go to the siblings first), and how call-site matching stays level-free — the spec recommends a syntactic L1 match at heuristic rather than gating Express to -a >= 2, which would break "identical at every -a".
  • File-convention rules are framework-version-sensitive — Next.js moved pages/api to app/**/route.ts across a major. Rules must express both without a code change or the ruleset rots.

Definition of done

  • A NestJS or Angular project gets correct, gated, reported entrypoints — not "some entrypoints were found"
  • SCHEMA_VERSION unmoved; the change is provably additive (existing fields and relationships unchanged)
  • Detection never aborts an analysis: rule loading is a hard error before analysis starts, detection itself is best-effort
  • Entrypoints are identical at every -a, and a test asserts it
  • A project that does NOT use a framework registers zero of its entrypoints (the gate is tested, not assumed)
  • TSEntrypointReport is populated in the same release as the detection it reports on
  • Validated against real projects, not only fixtures — python's ruleset was tuned that way, and "it found entrypoints on vscode" is not validation

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions