From the coverage-doctrine discussion (.github-private#1, epic #1): HTML/templates were mis-tiered as assets — they are extraction surfaces. A page that submits a form to /cart/checkout or fetches an API is a behavior-bearing actor; blast radius should reach it.
Design
- Nodes:
page:<path> (NodeKind.PAGE) for HTML files and server-rendered templates.
- Impact edges (blast-traversed):
SUBMITS_TO (form action=), FETCHES (fetch/XHR/axios URLs in inline or referenced scripts) — target = the route/handler node, joined via route-registration literals.
- Reference edges (NOT blast-traversed):
REFERENCES for page→stylesheet/script-src — nodes are cheap, edge kind gates traversal, so inventory edges cannot corrupt impact answers. (This also generalizes: CSS/Fluent can be reference nodes without ever carrying impact semantics.)
- Extractor home:
cocoa.system (parse HTML/templates for URLs; join to route registrations) — same pattern as the RPC stitcher.
The join constraint (honesty note)
Route literals live in handler-registration call sites (mux.HandleFunc("/cart", …), @app.route("/cart"), app.post("/cart", …)):
- Java:
argument_expr literals available → DERIVED-STATIC joins.
- Python/TS: callable
code available → regex extraction (SQL-extractor pattern) → DERIVED-STATIC.
- Go: no
code field and no argument literals in analysis.json → joins start as INFERRED, or wait on a codeanalyzer-go literal-capture enhancement (file there when this is picked up).
Blast semantics
Reverse traversal gains one hop: handler → pages that submit/fetch to it. Demo upgrade: "which PAGES break if hipstershop.Money.units changes" — user-visible impact.
Priority: post-launch feature; after codeanalyzer-go#5 / codeanalyzer-dotnet#1.
From the coverage-doctrine discussion (.github-private#1, epic #1): HTML/templates were mis-tiered as assets — they are extraction surfaces. A page that submits a form to
/cart/checkoutor fetches an API is a behavior-bearing actor; blast radius should reach it.Design
page:<path>(NodeKind.PAGE) for HTML files and server-rendered templates.SUBMITS_TO(formaction=),FETCHES(fetch/XHR/axios URLs in inline or referenced scripts) — target = the route/handler node, joined via route-registration literals.REFERENCESfor page→stylesheet/script-src — nodes are cheap, edge kind gates traversal, so inventory edges cannot corrupt impact answers. (This also generalizes: CSS/Fluent can be reference nodes without ever carrying impact semantics.)cocoa.system(parse HTML/templates for URLs; join to route registrations) — same pattern as the RPC stitcher.The join constraint (honesty note)
Route literals live in handler-registration call sites (
mux.HandleFunc("/cart", …),@app.route("/cart"),app.post("/cart", …)):argument_exprliterals available → DERIVED-STATIC joins.codeavailable → regex extraction (SQL-extractor pattern) → DERIVED-STATIC.codefield and no argument literals in analysis.json → joins start asINFERRED, or wait on a codeanalyzer-go literal-capture enhancement (file there when this is picked up).Blast semantics
Reverse traversal gains one hop: handler → pages that submit/fetch to it. Demo upgrade: "which PAGES break if hipstershop.Money.units changes" — user-visible impact.
Priority: post-launch feature; after codeanalyzer-go#5 / codeanalyzer-dotnet#1.