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.
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
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 insrc/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_entrypointandentrypoint_frameworkson 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/TSEntrypointReportschema, Neo4jis_entrypoint/entrypoint_frameworks, and the level-free L1 post-pass skeleton emitting an empty reportTSImport∪TSDependency, populatingframeworks_detected--entrypoint-rules, and the decorator matcher (ships NestJS + Angular)extends_ids/implements_ids, withdispatch:andvia: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-scopeboot()now yieldscan://…/app.ts -> can://…/app.ts/bootwithprov: ["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:
app.get('/p', h)— a callapp/**/route.ts,+server.tshandlerbin/mainin package.jsonThe rules format must be designed for those from the start, not copied from python's
rules.yml.TSEntrypointReportin the same change as detection, never after — a framework the ruleset misses looks identical to a project with no entrypoints.Controllerdecorator in a non-NestJS project must not register. The stage-0 gate is what prevents that, so it is not an optimisation.confidence: heuristic. Express handlers registered through a variable (const r = express.Router()) or a helper will be missed, and that belongs in the report'sunresolvedcounts.heuristicrather than gating Express to-a >= 2, which would break "identical at every-a".pages/apitoapp/**/route.tsacross a major. Rules must express both without a code change or the ruleset rots.Definition of done
SCHEMA_VERSIONunmoved; the change is provably additive (existing fields and relationships unchanged)-a, and a test asserts itTSEntrypointReportis populated in the same release as the detection it reports on