Repository navigation
Description
Summary
cbm_service_pattern_match() in internal/cbm/service_patterns.c classifies a
call as an HTTP client call (HTTP_CALLS edge) only when the resolved
qualified name contains a substring from a hardcoded allowlist
(http_libraries[], service_patterns.c ~L30-70): axios, node-fetch,
undici, ofetch, requests, httpx, etc.
The native/global Fetch API (fetch(url, opts) used with no import
statement, as in any browser or modern Node runtime) is not in this list.
Since it has no import, its resolved QN never contains any library
substring, so cbm_service_pattern_match() returns CBM_SVC_NONE and no
HTTP_CALLS edge is ever emitted — even when the call's first argument is a
literal path that byte-matches a real backend Route node.
Repro
Vue frontend (frontend/src/api.js):
export async function drawLottery(drawId) {
const res = await fetch('/lottery/draw', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${auth.token}` },
body: JSON.stringify({ draw_id: drawId }),
})
...
}FastAPI backend (backend/app/draw.py):
@router.post("/lottery/draw")
def draw(body: DrawRequest, ...):
...trace_path(function_name="drawLottery", mode="cross_service")→ no link found.MATCH (a)-[r]->(b:Route {qualified_name:'__route__POST__/lottery/draw'})→ 3 inbound edges, all backend-side (CALLSfrom the module,CALLSfrom a test,HANDLESfrom the handler itself). Zero edges from the frontend caller.- Project-wide: 8 of 9 frontend API functions in
api.jscall barefetch()directly and get zeroHTTP_CALLSedges.cross-repo-intelligence/trace_path(mode=cross_service)can never link them to their backend routes.
Secondary oddity (found while investigating, not fully root-caused)
Two functions (requestOtp, verifyOtp) that call a local wrapper
(postJson(path, body) → itself calls bare fetch) do get an HTTP_CALLS
edge, despite postJson not resolving to anything in http_libraries[],
route_reg_libraries[], or matching method_suffixes[]/route_reg_suffixes[]
(checked all three tables). Whatever mechanism creates these edges also emits
a duplicate Route node with method ANY (__route__ANY__/auth/otp)
alongside the real FastAPI-registered one (__route__POST__/auth/otp), and
the edge lands on the ANY node — which has no HANDLES edge from the real
handler. So even the "working" case points at an orphan node, not the real
route.
Suggested fix
Add the bare Fetch API as a recognized "library" for HTTP classification —
e.g., treat an unresolved/global fetch identifier (no import binding) as an
implicit HTTP client call when its first argument is a URL/path-shaped string
literal, the same way emit_http_async_edge already gates on
first_string_arg[0] == '/' || strstr(url, "://"). This is likely a common
false-negative for any modern frontend codebase that doesn't wrap fetch in
axios/ofetch/etc.
Environment
- codebase-memory-mcp 0.8.1 (linux-amd64-portable)
- Reproduced on a Vue 3 + FastAPI monorepo,
index_repository(mode=full)
Activity
DeusData commentedon Jul 5, 2026
Thanks for the clear native fetch repro. Triage: parsing/cross-repo HTTP edge bug, tracked under #592. Native global fetch needs a careful fixture because unqualified calls can be shadowed by local functions; the fix should prove literal/global fetch emits HTTP_CALLS while a local fetch helper does not over-match.
fix(pipeline): classify native fetch() as HTTP_CALLS, not local shadows
fix(swift): unify incompatible-overload fallback across resolver paths