Skip to content

bug(analytics): the frontend call scanner reads JSDoc examples as live calls — 3 of 4 'Potential Bugs' are documentation #17668

Closed

Description

@mrveiss

Child of #12745. That issue's primary cause — the backend scan returning 0 routes and flooding the panel with 2400 findings — is evidently addressed: the panel now reports 4. This is a second, independent cause that survives it, and it is now the dominant one by proportion.

The finding

On the live panel, "Missing Endpoints (4) — Potential Bugs":

# reported reality verdict
1 GET /api/export @ useFileDownload.ts:11 inside the /** … */ opening at line 6, closing at 17 — a Usage: example false
2 GET /api/export @ useFileDownload.ts:16 same block, Or inline: example false
3 GET /api/users @ apiErrorHandler.ts:222 inside the JSDoc ```typescript fence opening at 212 false
4 POST /api/themes @ ThemeManagerView.vue:35 real call, await apiClient.post('/api/themes', form), and no backend route matches true

3 of 4 false, on a panel labelled "Potential Bugs".

Mechanism

api_endpoint_scanner.py:1030-1032, per line:

# Skip comments
stripped = line.strip()
if stripped.startswith("//") or stripped.startswith("/*"):
    continue

The filter knows two spellings of "this line is a comment" and the class has at least three:

  1. Block-comment continuation — * const response = await ApiClient.get('/api/export') strips to * const …, which starts with neither // nor /*. This is where JSDoc examples live, and it is all three false positives above.
  2. Block interior without a leading * — any line inside /* … */ that does not begin with a star.
  3. Trailing comment — doThing() // await apiClient.get('/api/legacy') does not start with //, so the commented-out call is scanned as live.

A per-line prefix test cannot answer "is this position inside a comment"; that needs block state carried across lines.

Why this is worse than an empty panel

An empty panel gets investigated. A panel that is 75% false on its own label gets acted on — the three false findings cost investigation time, and the one real finding is discounted along with them. POST /api/themes is a theme upload that can only 404, and it is currently indistinguishable from noise.

Proposed fix

Blank comments out of the content before scanning, preserving line and column structure so reported positions stay correct — comment characters become spaces rather than being deleted. It needs string-literal awareness, or 'https://…' would be read as a line comment and truncate the rest of a genuine call.

Acceptance criteria

  • A call appearing only inside a /* … */ block, including a * continuation line, is not reported
  • A call after a // on a line whose code precedes it is not reported
  • A URL containing // inside a string literal does not truncate scanning of that line
  • POST /api/themes at ThemeManagerView.vue:35 is still reported — the fix must not silence the true positive
  • Tests cover all four forms, mutation-proved: reverting the comment handling fails a named test
  • The three known-false findings above are gone from the panel, verified against the live instance

Related

Activity

  1. mrveiss commented on Sep 28, 2026

    @mrveiss
    OwnerAuthor

    Closure evidence, verified against merged main

    This issue auto-closed on #17670's merge with no evidence posted. A merge is not a closure, so each criterion is checked against merged code.

    criterion evidence in origin/main
    a call inside /* … */, including a * continuation line, is not reported comment_blanking.py carries _consume_until / _consume_line_comment / _HTML_OPEN / _matching_brace (11 references); block state is carried across lines rather than tested per-line
    a call after a // following code is not reported same mechanism — the line-comment consumer runs from the marker to the newline regardless of what precedes it
    a URL containing // inside a string does not truncate scanning _consume_string copies literals verbatim; asserted by test_a_url_containing_a_double_slash_does_not_start_a_comment
    POST /api/themes at ThemeManagerView.vue:35 is still reported frontend_call_scanner_comments_test.py::test_the_one_real_finding_is_named_and_kept asserts after.get(35) == "/api/themes" through _scan_file
    tests cover all four forms, mutation-proved 18 tests in comment_blanking_test.py + 3 in frontend_call_scanner_comments_test.py; mutations recorded in the PR body (identity → 6 fail, delete-not-blank → 5, no string awareness → 1, no block state → 4, code-blanked-too → 2)
    scanner ratchet api_endpoint_scanner.py pinned at 1444, down from 1445 — the helper went to its own module rather than growing the scanner

    One criterion I cannot tick, and it should not be ticked by someone else without doing it:

    the three known-false findings are gone from the panel, verified against the live instance

    I verified the scanner no longer reports them — before/after finding sets through _scan_file, which is the mechanism behind the panel. I did not re-open the panel on the live deployment and confirm the rendered output. Those are different claims: the second also depends on cache state and on the panel's own query path, neither of which this PR touched.

    What the work found beyond the stated scope

    The panel was wrong in both directions. Running the real scanner to settle the fourth finding surfaced DELETE /api/themes/${id} at ThemeManagerView.vue:49 — a second genuine call, on the same missing route, that the panel never reported. So the surface was over-reporting documentation and under-reporting real calls simultaneously. "Make the findings precise" is therefore not the whole remedy; the same panel is also missing things, and that half is not addressed here.

    Three defects were found inside the fix itself, each one level further in, and all by review rather than by a tool: a verification using a private regex instead of the scanner's own patterns; a test that reimplemented the scan loop and so would have passed with production blanking removed; and _matching_brace counting raw braces, so a } inside a comment or string ended an interpolation early and leaked its contents. Recorded because a change whose subject is detectors that see less than they claim cannot quietly contain three of them.

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

    backendbugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions