Skip to content

fix(github-bot): use numeric user ID in prompt authorId#577

Merged
ColeMurray merged 3 commits intomainfrom
fix/github-bot-author-id-format
Apr 29, 2026
Merged

fix(github-bot): use numeric user ID in prompt authorId#577
ColeMurray merged 3 commits intomainfrom
fix/github-bot-author-id-format

Conversation

@ColeMurray
Copy link
Copy Markdown
Owner

@ColeMurray ColeMurray commented Apr 29, 2026

Summary

  • Changes authorId in all 4 github-bot handlers from github:${sender.login} to github:${sender.id}, using the stable numeric GitHub user ID instead of the mutable login name.
  • This is Step 1 of the git attribution fix plan. The D1 user_identities table is keyed by provider_user_id (numeric), so this change enables the router-level identity enrichment in Step 2 to resolve user identity via UserStore.getIdentity(provider, providerUserId) for all three bot types without additional query methods.

Affected handlers

Handler Trigger
handleReviewRequested Review assignment on a PR
handlePullRequestOpened Auto-review when a PR is opened
handleIssueComment Issue or PR conversation comment
handleReviewComment PR review comment

Backward compatibility

Existing participants created with the old github:${login} format will not be found by getByUserId("github:${id}"), so a new participant will be created on the next prompt. This is expected — the enrichment in Step 2/3 will create it with correct identity data.

Test plan

  • All 39 handler tests pass with updated assertions (github:alicegithub:1001, etc.)
  • Verify no regressions in CI (lint, typecheck, full test suite)

Summary by CodeRabbit

  • Bug Fixes

    • Improved error messaging when archiving sessions fails—users now receive toast notifications instead of silent failures.
  • Tests

    • Added coverage for archive failures on mobile devices.
  • Refactor

    • Updated author identification mechanism in GitHub integrations.
    • Simplified callback signatures for dialog components.
  • Documentation

    • Added clarifying comments to session management code.

Follow-up to #570. Show a toast when archiving fails instead of silently
logging to console. Add a failure-path test, clarify the split cache
responsibility with a comment, and narrow the dialog onConfirm type.
Switch authorId from `github:${sender.login}` to `github:${sender.id}`
in all four handler functions. This aligns with D1 user_identities which
are keyed by provider_user_id (numeric), enabling the router-level
identity enrichment in the next step of the attribution fix. Numeric IDs
are also stable — logins can be renamed.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

📝 Walkthrough

Walkthrough

The PR changes GitHub webhook handlers to use numeric sender id instead of username for identity purposes, updates error reporting in session archival from console logging to toast notifications, narrows the ArchiveSessionDialog callback type signature to sync-only, and adds test coverage for mobile archive failure scenarios with documentation comments.

Changes

Cohort / File(s) Summary
GitHub Bot Identity Provider
packages/github-bot/src/handlers.ts, packages/github-bot/test/handlers.test.ts
Switched all four webhook handlers to derive authorId from numeric sender.id (e.g., github:1001) instead of sender.login (e.g., github:alice). Updated corresponding test expectations to validate numeric ID format.
Archive Session Error Handling
packages/web/src/components/archive-session-dialog.tsx, packages/web/src/lib/archive-session.ts
Narrowed onConfirm callback type from `() => void
Session Management & Testing
packages/web/src/components/session-sidebar.tsx, packages/web/src/components/session-sidebar.test.tsx
Added inline documentation comments explaining archive cache invalidation and pagination handling. Added mobile-specific test case verifying session persistence when archive request fails with HTTP 500.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • open-inspect

Poem

🐰 Numeric IDs now guide the way,
Console logs fade, toasts here to stay,
Types grow tighter, stricter and keen,
Mobile tests catch what's in between,
The handlers hop with renewed ID pride! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: converting authorId in github-bot handlers from login-based to numeric ID format, which is the primary focus across the file modifications.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/github-bot-author-id-format

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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

@github-actions
Copy link
Copy Markdown

Terraform Validation Results

Step Status
Format
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

Copy link
Copy Markdown
Contributor

@open-inspect open-inspect Bot left a comment

Choose a reason for hiding this comment

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

Summary

PR Title and number: fix(github-bot): use numeric user ID in prompt authorId (#577)
Author: @ColeMurray
Files changed: 6 files, +58 / -12

This updates the github-bot handlers to use the stable numeric GitHub user ID in authorId, and includes a small web follow-up to surface archive failures to users. I reviewed the changed files and did not find any correctness, security, performance, or maintainability issues that should block merging.

Critical Issues

None.

Suggestions

None.

Nitpicks

None.

Positive Feedback

  • The authorId change is applied consistently across all four github-bot entry points, and the handler assertions were updated to match.
  • The archive-session follow-up improves user-facing behavior by replacing silent console logging with an error toast.
  • The added failure-path sidebar test covers the key regression risk for the web change.

Questions

None.

Verdict

Approve

Verified locally:

  • npm test -w @open-inspect/github-bot: all 100 tests passed
  • npm test -w @open-inspect/web -- session-sidebar: all 6 tests passed

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/web/src/lib/archive-session.ts (1)

44-46: Preserve diagnostics in catch path.

Line 44 swallows the thrown error entirely. Keep the toast, but also capture/log the exception so production failures remain debuggable.

Suggested patch
-  } catch {
+  } catch (error) {
+    console.error("Failed to archive session", error);
     toast.error("Failed to archive session");
     return false;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/web/src/lib/archive-session.ts` around lines 44 - 46, The catch
block in archiveSession currently swallows exceptions; update the catch to
accept the error (e.g., catch (err)) and log or report it before returning false
— for example call console.error("Failed to archive session", err) and, if a
telemetry helper (Sentry.captureException or appLogger) exists in this module,
forward the error there as well — keep the existing toast.error call and then
return false.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/web/src/components/archive-session-dialog.tsx`:
- Line 17: The onConfirm prop on ArchiveSessionDialog is currently typed as ()
=> void but callers pass async functions; update its type to () => Promise<void>
(or () => void | Promise<void> if you prefer to allow sync handlers) in the
component props/interface (the onConfirm declaration) and then ensure the local
confirmation handler that invokes onConfirm (e.g., the component's
confirm/handleConfirm function) awaits the call (make it async) so the async
contract is respected.

---

Nitpick comments:
In `@packages/web/src/lib/archive-session.ts`:
- Around line 44-46: The catch block in archiveSession currently swallows
exceptions; update the catch to accept the error (e.g., catch (err)) and log or
report it before returning false — for example call console.error("Failed to
archive session", err) and, if a telemetry helper (Sentry.captureException or
appLogger) exists in this module, forward the error there as well — keep the
existing toast.error call and then return false.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 86a19bfd-9009-4f1e-837b-09cc95b6b0dd

📥 Commits

Reviewing files that changed from the base of the PR and between 891abe3 and 45f4fde.

📒 Files selected for processing (6)
  • packages/github-bot/src/handlers.ts
  • packages/github-bot/test/handlers.test.ts
  • packages/web/src/components/archive-session-dialog.tsx
  • packages/web/src/components/session-sidebar.test.tsx
  • packages/web/src/components/session-sidebar.tsx
  • packages/web/src/lib/archive-session.ts

Comment thread packages/web/src/components/archive-session-dialog.tsx
@github-actions
Copy link
Copy Markdown

Terraform Validation Results

Step Status
Format
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@ColeMurray ColeMurray merged commit bfbcc3f into main Apr 29, 2026
18 checks passed
@ColeMurray ColeMurray deleted the fix/github-bot-author-id-format branch April 29, 2026 05:41
ColeMurray added a commit that referenced this pull request Apr 29, 2026
## Summary

Fixes git commit and PR attribution for bot-originated sessions (GitHub,
Slack, Linear). This is Steps 2-4 of the attribution fix plan (Step 1
was #577).

**Problem**: Bot sessions created owner participants with `user_id:
"anonymous"` (unfindable by later prompts), and resolved D1 identity was
discarded — never forwarded to the DO. Commits showed incorrect author
identity and PRs always opened as `open-inspect[bot]`.

**Solution**: Enrich participants with linked GitHub identity at two
points:

- **Session creation** (owner): `deriveUserId()` constructs canonical
userId matching prompt `authorId` format. `resolveGitHubEnrichment()`
looks up linked GitHub identity from D1 (display name, email, OAuth
tokens) and forwards to DO init.
- **Prompt time** (non-owner): `parseAuthorId()` extracts provider info
from bot authorIds, resolves linked GitHub identity, and forwards
enrichment fields through `EnqueuePromptRequest` to the DO for COALESCE
update.

**Key design decisions**:
- Email resolution: actual GitHub identity email preferred, noreply
format as fallback
- D1 queries parallelized where independent (`getUserById` +
`getEncryptedTokens`)
- Best-effort enrichment (try/catch) — D1 failures degrade gracefully to
existing behavior
- No DO changes needed — existing init/COALESCE/token refresh
infrastructure handles enriched data
- Web client path unaffected — `parseAuthorId` returns null for plain
user IDs, `deriveUserId` passes through explicit `userId`

### Files changed

| File | Change |
|---|---|
| `router.ts` | `deriveUserId()`, `parseAuthorId()`,
`resolveGitHubEnrichment()`, session creation + prompt time enrichment |
| `user-scm-tokens.ts` | `getEncryptedTokens()` — returns raw D1
ciphertext without decrypting |
| `message.service.ts` | Expand `EnqueuePromptRequest` with identity +
token fields |
| `message-queue.ts` | Use `EnqueuePromptRequest` type, COALESCE update
for non-owner participants |
| `router.identity.test.ts` | 16 tests for `parseAuthorId` and
`deriveUserId` |
| `user-scm-tokens.test.ts` | 2 tests for `getEncryptedTokens` |
| `message-queue.test.ts` | 4 tests for `enqueuePromptFromApi`
enrichment path |

## Test plan

- [x] `parseAuthorId` — 7 cases (github/slack/linear parse, web client
null, anonymous null, unknown prefix null, empty null)
- [x] `deriveUserId` — 9 cases (explicit userId, each bot with/without
identity fields, unknown source, empty input)
- [x] `getEncryptedTokens` — round-trip returns ciphertext not
plaintext, null for unknown user
- [x] `enqueuePromptFromApi` — COALESCE runs with enrichment fields,
skipped without them, `authorDisplayName` used for new participant name,
fallback to `authorId`
- [x] Typecheck passes (only pre-existing `CacheStore` errors)
- [x] 1019 control-plane unit tests pass (10 pre-existing failures in
`models.test.ts`)
- [x] 93 github-bot tests pass (7 pre-existing failures in
`webhook.test.ts`)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* GitHub identity enrichment during session creation; bot-origin prompts
are optionally enriched with author display/email/login and SCM
token/identity fields.
  * Canonical user ID derivation for bot authors.
* Prompt requests now carry enrichment fields; participant creation
prefers provided display name and will coalesce SCM identity/token data
when present.

* **Tests**
* Added tests for identity parsing, canonical user ID derivation,
encrypted token retrieval, and message-queue participant coalescing
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
MartinRoberts-Fountain pushed a commit to MartinRoberts-Fountain/background-agents that referenced this pull request Apr 29, 2026
## Summary

- Changes `authorId` in all 4 github-bot handlers from
`github:${sender.login}` to `github:${sender.id}`, using the stable
numeric GitHub user ID instead of the mutable login name.
- This is **Step 1** of the [git attribution fix
plan](docs/internal/2026-04-27-git-attribution-fix-plan.md). The D1
`user_identities` table is keyed by `provider_user_id` (numeric), so
this change enables the router-level identity enrichment in Step 2 to
resolve user identity via `UserStore.getIdentity(provider,
providerUserId)` for all three bot types without additional query
methods.

### Affected handlers
| Handler | Trigger |
|---|---|
| `handleReviewRequested` | Review assignment on a PR |
| `handlePullRequestOpened` | Auto-review when a PR is opened |
| `handleIssueComment` | Issue or PR conversation comment |
| `handleReviewComment` | PR review comment |

### Backward compatibility
Existing participants created with the old `github:${login}` format will
not be found by `getByUserId("github:${id}")`, so a new participant will
be created on the next prompt. This is expected — the enrichment in Step
2/3 will create it with correct identity data.

## Test plan
- [x] All 39 handler tests pass with updated assertions (`github:alice`
→ `github:1001`, etc.)
- [ ] Verify no regressions in CI (lint, typecheck, full test suite)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved error messaging when archiving sessions fails—users now
receive toast notifications instead of silent failures.

* **Tests**
  * Added coverage for archive failures on mobile devices.

* **Refactor**
  * Updated author identification mechanism in GitHub integrations.
  * Simplified callback signatures for dialog components.

* **Documentation**
  * Added clarifying comments to session management code.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
MartinRoberts-Fountain pushed a commit to MartinRoberts-Fountain/background-agents that referenced this pull request Apr 29, 2026
…eMurray#579)

## Summary

Fixes git commit and PR attribution for bot-originated sessions (GitHub,
Slack, Linear). This is Steps 2-4 of the attribution fix plan (Step 1
was ColeMurray#577).

**Problem**: Bot sessions created owner participants with `user_id:
"anonymous"` (unfindable by later prompts), and resolved D1 identity was
discarded — never forwarded to the DO. Commits showed incorrect author
identity and PRs always opened as `open-inspect[bot]`.

**Solution**: Enrich participants with linked GitHub identity at two
points:

- **Session creation** (owner): `deriveUserId()` constructs canonical
userId matching prompt `authorId` format. `resolveGitHubEnrichment()`
looks up linked GitHub identity from D1 (display name, email, OAuth
tokens) and forwards to DO init.
- **Prompt time** (non-owner): `parseAuthorId()` extracts provider info
from bot authorIds, resolves linked GitHub identity, and forwards
enrichment fields through `EnqueuePromptRequest` to the DO for COALESCE
update.

**Key design decisions**:
- Email resolution: actual GitHub identity email preferred, noreply
format as fallback
- D1 queries parallelized where independent (`getUserById` +
`getEncryptedTokens`)
- Best-effort enrichment (try/catch) — D1 failures degrade gracefully to
existing behavior
- No DO changes needed — existing init/COALESCE/token refresh
infrastructure handles enriched data
- Web client path unaffected — `parseAuthorId` returns null for plain
user IDs, `deriveUserId` passes through explicit `userId`

### Files changed

| File | Change |
|---|---|
| `router.ts` | `deriveUserId()`, `parseAuthorId()`,
`resolveGitHubEnrichment()`, session creation + prompt time enrichment |
| `user-scm-tokens.ts` | `getEncryptedTokens()` — returns raw D1
ciphertext without decrypting |
| `message.service.ts` | Expand `EnqueuePromptRequest` with identity +
token fields |
| `message-queue.ts` | Use `EnqueuePromptRequest` type, COALESCE update
for non-owner participants |
| `router.identity.test.ts` | 16 tests for `parseAuthorId` and
`deriveUserId` |
| `user-scm-tokens.test.ts` | 2 tests for `getEncryptedTokens` |
| `message-queue.test.ts` | 4 tests for `enqueuePromptFromApi`
enrichment path |

## Test plan

- [x] `parseAuthorId` — 7 cases (github/slack/linear parse, web client
null, anonymous null, unknown prefix null, empty null)
- [x] `deriveUserId` — 9 cases (explicit userId, each bot with/without
identity fields, unknown source, empty input)
- [x] `getEncryptedTokens` — round-trip returns ciphertext not
plaintext, null for unknown user
- [x] `enqueuePromptFromApi` — COALESCE runs with enrichment fields,
skipped without them, `authorDisplayName` used for new participant name,
fallback to `authorId`
- [x] Typecheck passes (only pre-existing `CacheStore` errors)
- [x] 1019 control-plane unit tests pass (10 pre-existing failures in
`models.test.ts`)
- [x] 93 github-bot tests pass (7 pre-existing failures in
`webhook.test.ts`)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* GitHub identity enrichment during session creation; bot-origin prompts
are optionally enriched with author display/email/login and SCM
token/identity fields.
  * Canonical user ID derivation for bot authors.
* Prompt requests now carry enrichment fields; participant creation
prefers provided display name and will coalesce SCM identity/token data
when present.

* **Tests**
* Added tests for identity parsing, canonical user ID derivation,
encrypted token retrieval, and message-queue participant coalescing
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant