Skip to content

feat: carry resolved identity into request_completed logs - #267

Merged
Zingzy merged 3 commits into
mainfrom
feat/request-attribution
Jul 22, 2026
Merged

feat: carry resolved identity into request_completed logs#267
Zingzy merged 3 commits into
mainfrom
feat/request-attribution

Conversation

@Zingzy

@Zingzy Zingzy commented Jul 22, 2026

Copy link
Copy Markdown
Member

Stacked on #266 (which stacks on #265).

What

The auth dependency stashes the resolved identity (user_id, auth_method, and for API keys key_id/key_prefix, for app tokens app_id) on request.state; the request logging middleware merges it into the request_completed event.

Why

request_completed currently carries no identity at all. The auth dependency binds structlog contextvars, but BaseHTTPMiddleware runs the downstream handler in a child task, so those bindings never propagate back to the middleware's dispatch context where request_completed is emitted. Service events get identity, the request log does not. request.state rides the shared ASGI scope, so it crosses that boundary.

Performance and security

No extra queries or allocations beyond a small dict on authenticated requests. Fields match exactly what service-layer logs already carry; nothing new is exposed. Anonymous requests and requests rejected before auth runs (rate-limited 429s) are unchanged.

Unit tests cover both the authenticated and anonymous shapes of the event.

Auth stashes user_id, auth_method, key_id, key_prefix, and app_id on
request.state; the logging middleware merges it into request_completed.
Contextvars bound in the handler task don't propagate back to the
middleware dispatch context, so the main request log had no identity.
Copilot AI review requested due to automatic review settings July 22, 2026 13:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Zingzy, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 33 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4a0574a1-4ffe-49c1-8822-69b5a0f20426

📥 Commits

Reviewing files that changed from the base of the PR and between 91dc0b2 and 72c65d8.

📒 Files selected for processing (3)
  • dependencies/auth.py
  • middleware/logging.py
  • tests/unit/middleware/test_logging.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/request-attribution

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Zingzy Zingzy left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mergeable, nothing blocking, and the mechanism is right.

  • The task-boundary claim checks out: BaseHTTPMiddleware runs downstream in a child task, contextvars copied at spawn never propagate back, and request.state rides the shared ASGI scope. request.state.tenant from the tenant middleware is the existing precedent, and the getattr(..., None) read matches how the redirect routes consume that one.
  • The **auth_ctx merge cannot collide with the explicit kwargs of request_completed, and the keys come from a fixed internal set, never from anything user-controlled.
  • key_prefix/key_id in request_completed survive redaction via the #265 safe list, same coupling as #266.
  • The comments here are the kind worth having: they state a constraint the code cannot show (why request.state instead of contextvars). Keep them.

Middleware and auth test files pass at this head (118).

# Conflicts:
#	tests/unit/middleware/test_logging.py
Base automatically changed from feat/api-key-hygiene to main July 22, 2026 15:06
@Zingzy
Zingzy merged commit bc871e8 into main Jul 22, 2026
12 checks passed
@Zingzy
Zingzy deleted the feat/request-attribution branch July 22, 2026 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✔️ Done

Development

Successfully merging this pull request may close these issues.

2 participants