#61 — Bug: GetCurrentUserIdQuery missing from the internal-only endpoint exclusion list #61
Labels
No labels
priority/could
priority/must
priority/should
priority/wont
status/blocked
status/claimed
status/done-migrated
type/bug
type/feature
type/infra
type/tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/todo#61
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Feature
#61— Bug:GetCurrentUserIdQuerymissing from the internal-only endpoint exclusion listRequested by: Backend Engineer, spotted during
#57's audit of internal-plumbing request types,2026-07-21
Priority: Could
Blocked by: none
Problem
EndpointRouteBuilderExtensions.MapRequestsauto-maps every publicIRequesttype to aPOSTendpoint unless explicitly excluded. Five internal-only session/plumbing commands are correctly
excluded:
SetCurrentUserIdCommand,DestroyCurrentSessionCommand,RevokeAllSessionsForCurrentUserCommand,GetSessionsRevokedBeforeUtcQuery,SendEmailVerificationCommand.GetCurrentUserIdQuery— a sibling in the exact sameCqsTodo.Features.Usernamespace, alsopublic, also only ever dispatched as a constructor-injecteddependency from inside other handlers (confirmed during
#57's audit: no direct caller anywhereoutside handler bodies) — is the one that was never added, and is currently live at
POST /api/GetCurrentUserIdQuery.Severity is low: the handler only returns the caller's own session-derived
UserId?(nullifunauthenticated), so there's no cross-user data exposure or IDOR — unlike the
#59review'sGetSessionsRevokedBeforeUtcQueryfinding, which did leak other users' data. Still the same categoryof bug (an internal-only type missing from the exclusion list becomes an unintended live endpoint with
no compile error or test failure to flag it), so it's worth closing for consistency and because the
next thing added near it could be worse.
Scope
GetCurrentUserIdQueryto the exclusion list inCqsTodo.WebApi/EndpointRouteBuilderExtensions.cs.MapRequestsTests.MapRequests_excludes_internal_only_session_types_from_real_assembly(added in
#59's review) to also assert this type produces no route.Out of scope
instead of a hardcoded list) — already logged as accepted debt from the
#59review(
docs/SECURITY_NOTES.md), not re-litigated here.Agents involved
same audit
#57/#59did)Resolution — Closed, not a bug (2026-07-21)
This story's premise was factually wrong. The fix was implemented, tested (new regression test
green, full solution green), and committed — then
/code-review's cross-file tracer angle checkedthe frontend for callers and found one:
ReactUi/src/App.tsx:23callscallApi('GetCurrentUserIdQuery', {})over real HTTP inside auseEffecton every app mount, todetermine login status. It's also a live path in the checked-in generated OpenAPI schema
(
ReactUi/src/api/generated/openapi-schema.d.ts).The "confirmed during
#57's audit: no direct caller anywhere outside handler bodies" claim aboveonly checked C# call sites (constructor-injected handler dependencies), not the frontend's HTTP
callers — the exact blind spot that made the five sibling types (all actually internal) look like
a pattern this type also fit. It doesn't:
GetCurrentUserIdQueryis the load-bearing "am I loggedin" check for the entire app, not internal plumbing, despite being marked
IInternalRequest(thatmarker was added in
#57for a different purpose — scoping metrics — and was never meant to imply"has no external caller"; conflating the two is the root confusion here).
Impact avoided: the fix was reverted before push. Had it shipped,
POST /api/GetCurrentUserIdQuerywould have 404'd, and every user's login-status check on every pageload would have failed — likely presenting as an app-wide stuck "Loading…" screen. Neither test
suite would have caught it: the new backend test only asserted the route's absence (that was the
regression, framed as the fix), and
ReactUi/src/api/api.test.tsmocksfetchdirectly rather thanexercising the real
MapRequestspipeline end-to-end.No further action required.
GetCurrentUserIdQuerystays off the exclusion list and continuesto be served at
POST /api/GetCurrentUserIdQuery, matching current (correct) behavior. Closingwithout code changes.
See the backend-engineer and security-agent team memory for the reusable lesson (verify "no
caller" claims against frontend/generated-schema call sites too, not just C# grep, before trusting
an audit's exclusion-list recommendation).