feat(platform): alert + gate admin impersonation start via Discord - #13299
feat(platform): alert + gate admin impersonation start via Discord#13299ntindle wants to merge 9 commits into
Conversation
Why: Admin impersonation was only recorded in a backend log line. We want a real-time audit alert when an admin starts impersonating a user, and we would rather block impersonation than allow it with no audit trail. What: Adds an admin-only endpoint that posts a Discord alert to the platform alerts channel when impersonation starts, and gates the dashboard "start impersonation" action on it. How: The admin dashboard awaits the generated POST /api/admin/impersonation/notify before swapping identity; a non-2xx response blocks the swap. The backend sends via the existing discord_send_alert helper with a bounded timeout. If no Discord bot token is configured the alert is skipped and impersonation is allowed (keeps non-Discord / self-hosted deployments working); if a token is set but delivery is not confirmed -- including the non-raising "channel not found" case -- it returns 502 so the swap is blocked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds an admin-protected POST endpoint that emits a Discord audit alert when impersonation starts; when Discord is configured, delivery failures block impersonation. Registers the router, updates OpenAPI, gates frontend impersonation on the notification (with re-entry protection), and adds backend and frontend tests. ChangesImpersonation Audit Alerts
Sequence DiagramsequenceDiagram
participant AdminClient
participant FrontendHook
participant NotifyEndpoint
participant EmailResolver
participant DiscordGateway
AdminClient->>FrontendHook: startImpersonating(target_user_id)
FrontendHook->>NotifyEndpoint: POST /api/admin/impersonation/notify
NotifyEndpoint->>NotifyEndpoint: log impersonation request
alt Discord token configured
NotifyEndpoint->>EmailResolver: resolve admin & target emails (best-effort)
EmailResolver-->>NotifyEndpoint: emails or null
NotifyEndpoint->>DiscordGateway: send alert (timeout)
DiscordGateway-->>NotifyEndpoint: delivery status
alt success ("Message sent")
NotifyEndpoint-->>FrontendHook: 200 alerted=true
FrontendHook->>AdminClient: set impersonation state + reload
else delivery failed
NotifyEndpoint-->>FrontendHook: 502 (blocked)
FrontendHook-->>AdminClient: show destructive toast, abort
end
else No token
NotifyEndpoint-->>FrontendHook: 200 alerted=false
FrontendHook->>AdminClient: set impersonation state + reload
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
autogpt_platform/frontend/src/app/api/openapi.json (1)
849-849: 💤 Low valueDuplicate
"admin"tag in the tags array.The tags array
["v2", "admin", "admin", "impersonation"]contains"admin"twice. This is cosmetic but indicates the backend route has redundant tag declarations. Consider removing the duplicate in the route decorator for cleaner OpenAPI output.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/frontend/src/app/api/openapi.json` at line 849, The OpenAPI tags array contains a duplicate "admin" entry (["v2", "admin", "admin", "impersonation"]); remove the redundant "admin" value so the tags array is ["v2", "admin", "impersonation"]. Locate the OpenAPI definition producing that array (the tags field with values "v2","admin","admin","impersonation") and update the route decorator or generator that emits these tags to avoid emitting "admin" twice.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@autogpt_platform/frontend/src/app/api/openapi.json`:
- Line 849: The OpenAPI tags array contains a duplicate "admin" entry (["v2",
"admin", "admin", "impersonation"]); remove the redundant "admin" value so the
tags array is ["v2", "admin", "impersonation"]. Locate the OpenAPI definition
producing that array (the tags field with values
"v2","admin","admin","impersonation") and update the route decorator or
generator that emits these tags to avoid emitting "admin" twice.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6c143b48-7eb7-4b86-a31d-4abf76fc470b
📒 Files selected for processing (5)
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.pyautogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.tsautogpt_platform/frontend/src/app/api/openapi.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
- GitHub Check: integration_test
- GitHub Check: lint
- GitHub Check: check API types
- GitHub Check: Cursor Bugbot
- GitHub Check: lint
- GitHub Check: test (3.12)
- GitHub Check: lint
- GitHub Check: test (3.11)
- GitHub Check: type-check (3.11)
- GitHub Check: type-check (3.13)
- GitHub Check: type-check (3.12)
- GitHub Check: test (3.13)
- GitHub Check: end-to-end tests
- GitHub Check: types
- GitHub Check: Analyze (typescript)
- GitHub Check: Analyze (python)
- GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (14)
autogpt_platform/backend/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development
autogpt_platform/backend/**/*.py: Usepoetry run ...command for executing Python package dependencies
Use top-level imports only — avoid local/inner imports except for lazy imports of heavy optional dependencies likeopenpyxl
Use absolute imports withfrom backend.module import ...for cross-package imports; single-dot relative imports are acceptable for sibling modules within the same package; avoid double-dot relative imports
Do not use duck typing — avoidhasattr/getattr/isinstancefor type dispatch; use typed interfaces/unions/protocols instead
Use Pydantic models over dataclass/namedtuple/dict for structured data
Do not use linter suppressors — no# type: ignore,# noqa,# pyright: ignore; fix the type/code instead
Prefer list comprehensions over manual loop-and-append patterns
Use early return with guard clauses first to avoid deep nesting
Use%sfor deferred interpolation indebuglog statements for efficiency; use f-strings elsewhere for readability (e.g.,logger.debug("Processing %s items", count)vslogger.info(f"Processing {count} items"))
Sanitize error paths by usingos.path.basename()in error messages to avoid leaking directory structure
Be aware of TOCTOU (Time-Of-Check-Time-Of-Use) issues — avoid check-then-act patterns for file access and credit charging
Usetransaction=Truefor Redis pipelines to ensure atomicity on multi-step operations
Usemax(0, value)guards for computed values that should never be negative
Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract helpers, models, or a sub-module into a new file)
Keep functions under ~40 lines; extract named helpers when a function grows longer
...
Files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
autogpt_platform/backend/backend/api/features/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Update routes in '/backend/backend/api/features/' and add/update Pydantic models in the same directory for API development
Files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.py
autogpt_platform/{backend,autogpt_libs}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
autogpt_platform/backend/**/api/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/AGENTS.md)
autogpt_platform/backend/**/api/**/*.py: UseSecurity()instead ofDepends()for authentication dependencies to get proper OpenAPI security specification
Follow SSE (Server-Sent Events) protocol: usedata:lines for frontend-parsed events (must match Zod schema) and: commentlines for heartbeats/status
Files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
autogpt_platform/backend/**/*_test.py
📄 CodeRabbit inference engine (autogpt_platform/backend/AGENTS.md)
autogpt_platform/backend/**/*_test.py: Use pytest with snapshot testing for API responses
Colocate test files with source files using*_test.pynaming convention
Mock at boundaries — mock where the symbol is used, not where it's defined; after refactoring, update mock targets to match new module paths
UseAsyncMockfromunittest.mockfor async functions in tests
When writing tests, use Test-Driven Development (TDD): write failing tests marked with@pytest.mark.xfailbefore implementation, then remove the marker once the implementation is complete
When creating snapshots in tests, usepoetry run pytest path/to/test.py --snapshot-update; always review snapshot changes withgit diffbefore committing
Files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.py
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Use Node.js 21+ with pnpm package manager for frontend development
Always run 'pnpm format' for formatting and linting code in frontend developmentFormat frontend code using
pnpm format
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Fully capitalize acronyms in symbols, e.g.graphID,useBackendAPI
No linter suppressors (//@ts-ignore``,// eslint-disable) — fix the actual issue
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
autogpt_platform/frontend/**/*.{tsx,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{tsx,ts}: Use function declarations for components and handlers (not arrow functions) in React components
Only use arrow functions for small inline lambdas (map, filter, etc.) in React components
Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Use Tailwind CSS utilities only for styling in frontend components
Use design system components from 'src/components/' (atoms, molecules, organisms) in frontend development
Never use 'src/components/legacy/' in frontend code
Only use Phosphor Icons (@phosphor-icons/react) for icons in frontend components
Use generated API hooks from '@/app/api/__generated__/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/'
Use React Query for server state (via generated hooks) in frontend development
Default to client components ('use client') in Next.js; only use server components for SEO or extreme TTFB needs
Use '' component for rendering errors in frontend UI; use toast notifications for mutation errors; use 'Sentry.captureException()' for manual exceptions
Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
autogpt_platform/frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{ts,tsx}: No barrel files or 'index.ts' re-exports in frontend code
Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development
autogpt_platform/frontend/**/*.{ts,tsx}: Use function declarations (not arrow functions) for components/handlers
Noanytypes unless the value genuinely can be anything
Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
autogpt_platform/frontend/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
autogpt_platform/frontend/src/**/*.{ts,tsx}: Use generated API hooks from@/app/api/__generated__/endpoints/following the patternuse{Method}{Version}{OperationName}, and regenerate withpnpm generate:api
Separate render logic from business logic using component.tsx + useComponent.ts + helpers.ts pattern, colocate state when possible and avoid creating large components, use sub-components in local/componentsfolder
Use function declarations for components and handlers, use arrow functions only for callbacks
Do not useuseCallbackoruseMemounless asked to optimise a given function
autogpt_platform/frontend/src/**/*.{ts,tsx}: Keep files under ~200 lines; extract sub-components or hooks into their own files when a file grows beyond this
Use generated API hooks from@/app/api/__generated__/endpoints/with patternuse{Method}{Version}{OperationName}
Always import the-Icon-suffixed alias from@phosphor-icons/react(e.g.TrashIcon,PlusIcon,SquareIcon) — bare exports are deprecated
Do not useuseCallbackoruseMemounless asked to optimize a given function
Never usesrc/components/__legacy__/*— use design system components fromsrc/components/
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
autogpt_platform/frontend/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
No barrel files or
index.tsre-exports in the frontend
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
autogpt_platform/frontend/src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Do not type hook returns, let Typescript infer as much as possible
autogpt_platform/frontend/src/**/*.ts: Extract component logic into custom hooks grouped by concern, not by component, with each hook in its own.tsfile
Do not type hook returns; let TypeScript infer as much as possible
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
autogpt_platform/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never type with
any, if no types available useunknown
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
autogpt_platform/frontend/src/**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Structure components as
ComponentName/ComponentName.tsx+useComponentName.ts+helpers.ts
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
autogpt_platform/frontend/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Avoid index and barrel files
Files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
🧠 Learnings (34)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12566
File: autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts:968-974
Timestamp: 2026-03-26T00:32:06.673Z
Learning: In Significant-Gravitas/AutoGPT, the admin-facing methods in `autogpt_platform/frontend/src/lib/autogpt-server-api/client.ts` (e.g., `addUserCredits`, `getUsersHistory`, `getUserRateLimit`, `resetUserRateLimit`) intentionally follow the legacy `BackendAPI` pattern with manually defined types in `autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts`. Migrating these admin endpoints to the generated OpenAPI hooks (`@/app/api/__generated__/endpoints/`) is a planned separate effort covering all admin endpoints together, not done piecemeal per PR. Do not flag individual admin type additions in `types.ts` as blocking issues.
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12536
File: autogpt_platform/frontend/src/app/api/openapi.json:5732-5752
Timestamp: 2026-03-24T21:27:22.326Z
Learning: Repo: Significant-Gravitas/AutoGPT — Preference: Do not add explicit 403/404 entries to FastAPI route decorators for admin endpoints just to influence OpenAPI. Keep openapi.json autogenerated and use route docstrings to document admin-only (403) and not-found (404) behavior; rely on tests for enforcement. File context: autogpt_platform/backend/backend/api/features/admin/store_admin_routes.py. PR `#12536`.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12796
File: autogpt_platform/backend/backend/api/features/chat/routes.py:504-527
Timestamp: 2026-04-16T12:33:44.990Z
Learning: In `autogpt_platform/backend/backend/api/features/chat/routes.py`, `get_session` (PR `#12796`, commit 3771bfad9c1) closes the TOCTOU race between the initial `stream_registry.get_active_session()` pre-check and `get_chat_messages_paginated()` with a post-check re-verification: after the DB fetch, if `is_initial_load and active_session is not None`, it calls `get_active_session` a second time; if `post_active is None` (stream completed during the window), it resets `from_start=True`, `forward_paginated=True`, and re-fetches messages from sequence 0. Do NOT flag the double `get_active_session` call pattern as redundant — it is the intentional TOCTOU mitigation for pagination direction selection.
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12284
File: autogpt_platform/frontend/src/app/api/openapi.json:11897-11900
Timestamp: 2026-03-04T23:58:18.476Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12284`
Backend/frontend OpenAPI codegen convention: In backend/api/features/store/model.py, the StoreSubmission and StoreSubmissionAdminView models define submitted_at: datetime | None, changes_summary: str | None, and instructions: str | None with no default. This is intentional to produce “required but nullable” fields in OpenAPI (properties appear in required[] and use anyOf [type, null]). This matches Prisma’s submittedAt DateTime? and changesSummary String?. Do not flag this as a required/nullable mismatch.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 0
File: :0-0
Timestamp: 2026-05-12T09:59:51.200Z
Learning: In `autogpt_platform/frontend/src/app/(platform)/copilot/useSendMessage.ts`, the pending-first-send stall watchdog logic was intentionally kept inline (not extracted to a separate `usePendingFirstSendWatchdog` hook) to comply with the AGENTS.md rule of keeping out-of-scope changes under 20% in a bug-fix PR. The file was already ~190 lines before this PR; the watchdog adds ~40 lines. A follow-up PR is planned to extract the watchdog into a dedicated hook. Do not flag the watchdog's inline placement in `useSendMessage.ts` as a refactor opportunity in the current PR context.
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12536
File: autogpt_platform/frontend/src/app/api/openapi.json:5770-5790
Timestamp: 2026-03-24T21:25:15.983Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12536`
File: autogpt_platform/frontend/src/app/api/openapi.json
Learning: The OpenAPI spec file is auto-generated; per established convention, endpoints generally declare only 200/201, 401, and 422 responses. Do not suggest adding explicit 403/404 response entries for single operations unless planning a repo-wide spec update. Prefer clarifying such behaviors in endpoint descriptions/docstrings instead of altering response maps.
Learnt from: Swiftyos
Repo: Significant-Gravitas/AutoGPT PR: 12347
File: autogpt_platform/backend/backend/data/invited_user.py:193-193
Timestamp: 2026-03-10T11:22:18.867Z
Learning: In Significant-Gravitas/AutoGPT, the admin data-layer functions in `autogpt_platform/backend/backend/data/invited_user.py` (`list_invited_users`, `create_invited_user`, `revoke_invited_user`, `retry_invited_user_tally`, `bulk_create_invited_users_from_file`) intentionally omit an acting-user/admin ID parameter. Authorization for these functions is enforced entirely at the FastAPI router layer via `Security(requires_admin_user)` in `user_admin_routes.py`. Do not flag the absence of a user_id/actor_id parameter in these functions as a missing data-access guardrail violation.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12773
File: autogpt_platform/backend/backend/copilot/pending_messages.py:52-64
Timestamp: 2026-04-14T14:36:25.545Z
Learning: In `autogpt_platform/backend/backend/copilot` (PR `#12773`, commit d7bced0c6): when draining pending messages into `session.messages`, each message's text is sanitized via `strip_user_context_tags` before persistence to prevent user-controlled `<user_context>` injection from bypassing the trusted server-side context prefix. Additionally, if `upsert_chat_session` fails after draining, the drained `PendingMessage` objects are requeued back to Redis to avoid silent message loss. Do NOT flag the drain-then-requeue pattern as redundant — it is the intentional failure-resilience strategy for the pending buffer.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12919
File: autogpt_platform/backend/backend/data/notifications_test.py:296-338
Timestamp: 2026-04-25T05:02:54.108Z
Learning: In `autogpt_platform/backend/backend/data/notifications.py`, `create_or_add_to_user_notification_batch` uses a Prisma `upsert` on the `(userId, type)` unique constraint. Because Prisma's `upsert` is internally find→INSERT/UPDATE (not a true SQL `ON CONFLICT`), two concurrent callers on an empty row can both miss the SELECT and both attempt INSERT, causing a `UniqueViolationError`. The helper retries once on `UniqueViolationError`; on retry the row exists, so the loser takes the UPDATE path deterministically. Do NOT flag the retry-on-`UniqueViolationError` pattern as unnecessary — it is the intentional TOCTOU mitigation for the non-atomic Prisma upsert. Covered by `test_upsert_retries_on_unique_violation` (monkeypatch) and `test_upsert_concurrent_invocations_no_unique_violation` (live-DB gather), added in PR `#12919` commit 7fcc50a.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 0
File: :0-0
Timestamp: 2026-04-28T03:31:29.696Z
Learning: In Significant-Gravitas/AutoGPT PR `#12933` (`fix/stripe-checkout-link-auth-loop`), the initial approach of pinning `payment_method_types=["card"]` in `top_up_intent` and `create_subscription_checkout` (in `autogpt_platform/backend/backend/data/credit.py`) was reverted in commit `584b43a71` as it patched a symptom. The true root cause was in `update_subscription_tier()` in `v1.py`: a `current_tier_price_id is not None` guard was gating admin-granted DB-tier flips and short-circuiting them when the BUSINESS tier was pruned from the price-id LaunchDarkly flag. Do NOT flag `payment_method_types` absence in these checkout helpers as a Stripe Link bypass issue; the fix lives in the subscription tier update guard logic.
📚 Learning: 2026-03-10T11:22:18.867Z
Learnt from: Swiftyos
Repo: Significant-Gravitas/AutoGPT PR: 12347
File: autogpt_platform/backend/backend/data/invited_user.py:193-193
Timestamp: 2026-03-10T11:22:18.867Z
Learning: In Significant-Gravitas/AutoGPT, the admin data-layer functions in `autogpt_platform/backend/backend/data/invited_user.py` (`list_invited_users`, `create_invited_user`, `revoke_invited_user`, `retry_invited_user_tally`, `bulk_create_invited_users_from_file`) intentionally omit an acting-user/admin ID parameter. Authorization for these functions is enforced entirely at the FastAPI router layer via `Security(requires_admin_user)` in `user_admin_routes.py`. Do not flag the absence of a user_id/actor_id parameter in these functions as a missing data-access guardrail violation.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.py
📚 Learning: 2026-03-24T21:27:19.455Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12536
File: autogpt_platform/frontend/src/app/api/openapi.json:5732-5752
Timestamp: 2026-03-24T21:27:19.455Z
Learning: For FastAPI admin endpoints, avoid adding explicit 403/404 status-code entries in the route decorator (e.g., for the OpenAPI schema) solely to shape OpenAPI output. Keep openapi.json generation automatic, and instead document admin-only (403) and not-found (404) behavior via route docstrings. Enforce the actual behavior with automated tests rather than relying on decorator OpenAPI overrides.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/api/features/**/*.py : Update routes in '/backend/backend/api/features/' and add/update Pydantic models in the same directory for API development
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-03-05T15:42:08.207Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12297
File: .claude/skills/backend-check/SKILL.md:14-16
Timestamp: 2026-03-05T15:42:08.207Z
Learning: In Python files under autogpt_platform/backend (recursively), rely on poetry run format to perform formatting (Black + isort) and linting (ruff). Do not run poetry run lint as a separate step after poetry run format, since format already includes linting checks.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-03-16T16:35:40.236Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/api/features/workflow_import.py:54-63
Timestamp: 2026-03-16T16:35:40.236Z
Learning: Avoid using the word 'competitor' in public-facing identifiers and text. Use neutral naming for API paths, model names, function names, and UI text. Examples: rename 'CompetitorFormat' to 'SourcePlatform', 'convert_competitor_workflow' to 'convert_workflow', '/competitor-workflow' to '/workflow'. Apply this guideline to files under autogpt_platform/backend and autogpt_platform/frontend.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-03-31T15:37:38.626Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/backend/backend/copilot/tools/agent_generator/fixer.py:37-47
Timestamp: 2026-03-31T15:37:38.626Z
Learning: When validating/constructing Anthropic API model IDs in Significant-Gravitas/AutoGPT, allow the hyphen-separated Claude Opus 4.6 model ID `claude-opus-4-6` (it corresponds to `LlmModel.CLAUDE_4_6_OPUS` in `autogpt_platform/backend/backend/blocks/llm.py`). Do NOT require the dot-separated form in Anthropic contexts. Only OpenRouter routing variants should use the dot separator (e.g., `anthropic/claude-opus-4.6`); `claude-opus-4-6` should be treated as correct when passed to Anthropic, and flagged only if it’s used in the OpenRouter path where the dot form is expected.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-04-15T02:43:36.890Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12780
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-15T02:43:36.890Z
Learning: When reviewing Python exception handlers, do not flag `isinstance(e, X)` checks as dead/unreachable if the caught exception `X` is a subclass of the exception type being handled. For example, if `X` (e.g., `VirusScanError`) inherits from `ValueError` (directly or via an intermediate class) and it can be raised within an `except ValueError:` block, then `isinstance(e, X)` inside that handler is reachable and should not be treated as dead code.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-05-23T05:29:43.085Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13200
File: autogpt_platform/backend/backend/executor/scheduler.py:590-593
Timestamp: 2026-05-23T05:29:43.085Z
Learning: When reviewing Python code that uses Pydantic discriminated/tagged unions (e.g., `Annotated[Union[...], Field(discriminator="kind")]`), recognize that using `isinstance(x, SomeVariantInfo)` to narrow the union is an intentional and correct runtime guard and should also enable static type narrowing in tools like Pyright. Do not recommend replacing such `isinstance`-based narrowing with `cast(...)` when the check already proves the variant at runtime.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-04-22T11:46:04.431Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/config.py:0-0
Timestamp: 2026-04-22T11:46:04.431Z
Learning: Do not flag the Claude Sonnet 4.6 model ID as incorrect when it uses the project’s established hyphenated convention: `anthropic/claude-sonnet-4-6`. This hyphen form is the intentional, production convention and should be treated as valid (including in files like llm.py, blocks tests, reasoning.py, `_is_anthropic_model` tests, and config defaults). Note that OpenRouter also accepts the dot variant `anthropic/claude-sonnet-4.6`, so either form may be tolerated, but `anthropic/claude-sonnet-4-6` should be considered the standard to match project usage.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-04-22T11:46:12.892Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/baseline/service.py:322-332
Timestamp: 2026-04-22T11:46:12.892Z
Learning: In this codebase (Significant-Gravitas/AutoGPT), OpenRouter-routed Anthropic model IDs should use the hyphen-separated convention (e.g., `anthropic/claude-sonnet-4-6`, `anthropic/claude-opus-4-6`). Although OpenRouter may accept both hyphen and dot variants, treat the hyphen-separated form as the intended, correct codebase-wide convention and do not flag it as an error. Only flag the dot-separated variant (e.g., `anthropic/claude-sonnet-4.6`) as incorrect when reviewing/validating model ID strings for OpenRouter-routed Anthropic models.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-05-07T18:48:14.242Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13040
File: autogpt_platform/backend/backend/blocks/llm.py:0-0
Timestamp: 2026-05-07T18:48:14.242Z
Learning: In this repository, isort may split imports from the same module into separate blocks when some imports are aliased (e.g., `from module import X as Y`) and others are not. Preserve the two-block layout when it results from isort (such as keeping `from openai.types.chat import ChatCompletion as OpenAIChatCompletion` separate from non-aliased imports from `openai.types.chat`). Do not treat that split as a style issue during review; merging them into a single block can fail CI with `Imports are incorrectly sorted and/or formatted`.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-05-26T14:24:34.866Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13217
File: autogpt_platform/backend/backend/api/features/search/service.py:137-137
Timestamp: 2026-05-26T14:24:34.866Z
Learning: In the Significant-Gravitas/AutoGPT backend, treat `user_id` (an opaque UUID used only for correlation/tracing) as non-PII. Do not flag direct logging of `user_id` in `logger.warning`/`logger.info` statements as a PII exposure issue, as the established convention is to log `user_id` for tracing while reserving PII for fields like email or display name.
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.pyautogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.pyautogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-03-26T00:32:06.673Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12566
File: autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts:968-974
Timestamp: 2026-03-26T00:32:06.673Z
Learning: In Significant-Gravitas/AutoGPT, the admin-facing methods in `autogpt_platform/frontend/src/lib/autogpt-server-api/client.ts` (e.g., `addUserCredits`, `getUsersHistory`, `getUserRateLimit`, `resetUserRateLimit`) intentionally follow the legacy `BackendAPI` pattern with manually defined types in `autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts`. Migrating these admin endpoints to the generated OpenAPI hooks (`@/app/api/__generated__/endpoints/`) is a planned separate effort covering all admin endpoints together, not done piecemeal per PR. Do not flag individual admin type additions in `types.ts` as blocking issues.
Applied to files:
autogpt_platform/frontend/src/app/api/openapi.jsonautogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-03-24T21:25:15.983Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12536
File: autogpt_platform/frontend/src/app/api/openapi.json:5770-5790
Timestamp: 2026-03-24T21:25:15.983Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12536`
File: autogpt_platform/frontend/src/app/api/openapi.json
Learning: The OpenAPI spec file is auto-generated; per established convention, endpoints generally declare only 200/201, 401, and 422 responses. Do not suggest adding explicit 403/404 response entries for single operations unless planning a repo-wide spec update. Prefer clarifying such behaviors in endpoint descriptions/docstrings instead of altering response maps.
Applied to files:
autogpt_platform/frontend/src/app/api/openapi.json
📚 Learning: 2026-03-07T07:43:09.871Z
Learnt from: kcze
Repo: Significant-Gravitas/AutoGPT PR: 12328
File: autogpt_platform/frontend/src/app/api/openapi.json:1116-1118
Timestamp: 2026-03-07T07:43:09.871Z
Learning: For autogpt_platform/frontend/src/app/api/openapi.json, preserve the existing behavior: HTTPBearerJWT is declared at the router level with Depends(auth.get_user_id) returning None for unauthenticated users; treat as optional auth. Do not change per-operation security descriptions unless you plan a repo-wide OpenAPI update. If you change this file, prefer clarifying operation descriptions rather than altering security requirements.
Applied to files:
autogpt_platform/frontend/src/app/api/openapi.json
📚 Learning: 2026-03-01T07:58:56.207Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/api/openapi.json:10030-10037
Timestamp: 2026-03-01T07:58:56.207Z
Learning: When a backend field represents sensitive data, use a secret type (e.g., Pydantic SecretStr with length constraints) so OpenAPI marks it as a password/writeOnly field. Apply this pattern to similar sensitive request fields across API schemas so generated TypeScript clients and docs treat them as secrets and do not mishandle sensitivity. Review all openapi.jsons where sensitive inputs are defined and replace plain strings with SecretStr-like semantics with appropriate minLength constraints.
Applied to files:
autogpt_platform/frontend/src/app/api/openapi.json
📚 Learning: 2026-04-14T06:39:49.111Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12773
File: autogpt_platform/frontend/src/app/api/openapi.json:12803-12806
Timestamp: 2026-04-14T06:39:49.111Z
Learning: In OpenAPI specs, ensure the schema/message length caps for the StreamChatRequest.message and QueuePendingMessageRequest.message fields are set to the intended values: StreamChatRequest.message maxLength must be 64000 and QueuePendingMessageRequest.message maxLength must be 32000. Keep QueuePendingMessageRequest.message consistent with PendingMessage.content, and ensure the pending (queue) ceiling never exceeds the stream ceiling because both ultimately feed the same LLM context window. Update any legacy smaller limits (e.g., 4000/16000) to these newer ceilings.
Applied to files:
autogpt_platform/frontend/src/app/api/openapi.json
📚 Learning: 2026-04-08T17:28:23.439Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/AGENTS.md:0-0
Timestamp: 2026-04-08T17:28:23.439Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Mock at boundaries — mock where the symbol is **used**, not where it's **defined**; after refactoring, update mock targets to match new module paths
Applied to files:
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.py
📚 Learning: 2026-03-24T21:27:22.326Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12536
File: autogpt_platform/frontend/src/app/api/openapi.json:5732-5752
Timestamp: 2026-03-24T21:27:22.326Z
Learning: Repo: Significant-Gravitas/AutoGPT — Preference: Do not add explicit 403/404 entries to FastAPI route decorators for admin endpoints just to influence OpenAPI. Keep openapi.json autogenerated and use route docstrings to document admin-only (403) and not-found (404) behavior; rely on tests for enforcement. File context: autogpt_platform/backend/backend/api/features/admin/store_admin_routes.py. PR `#12536`.
Applied to files:
autogpt_platform/backend/backend/api/rest_api.py
📚 Learning: 2026-03-23T06:36:25.447Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/frontend/src/app/(platform)/library/components/LibraryImportWorkflowDialog/useLibraryImportWorkflowDialog.ts:0-0
Timestamp: 2026-03-23T06:36:25.447Z
Learning: In Significant-Gravitas/AutoGPT PR `#12440`, the `LibraryImportWorkflowDialog` (previously `LibraryImportCompetitorDialog`) and its associated generated API hook (`usePostV2ImportACompetitorWorkflowN8nMakeComZapier` / `usePostV2ImportAWorkflowFromAnotherToolN8nMakeComZapier`) were removed in a subsequent refactor. Workflow import from external platforms (n8n, Make.com, Zapier) now uses a server action `fetchWorkflowFromUrl` instead of direct API calls or generated orval hooks. Do not expect or flag missing generated hook usage for workflow import in `autogpt_platform/frontend/src/app/(platform)/library/components/LibraryImportWorkflowDialog/`.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-04-30T03:25:37.624Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/frontend/AGENTS.md:0-0
Timestamp: 2026-04-30T03:25:37.624Z
Learning: Applies to autogpt_platform/frontend/src/**/*.{ts,tsx} : Use generated API hooks from `@/app/api/__generated__/endpoints/` with pattern `use{Method}{Version}{OperationName}`
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/frontend/**/*.{tsx,ts} : Use generated API hooks from '`@/app/api/__generated__/endpoints/`' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/*'
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-04-08T17:27:45.740Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-08T17:27:45.740Z
Learning: Applies to autogpt_platform/frontend/src/**/*.{ts,tsx} : Use generated API hooks from `@/app/api/__generated__/endpoints/` following the pattern `use{Method}{Version}{OperationName}`, and regenerate with `pnpm generate:api`
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/frontend/**/*.{tsx,ts} : Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-04-30T14:10:26.644Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12960
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunAgent/components/AgentDetailsCard/__tests__/helpers.test.ts:3-3
Timestamp: 2026-04-30T14:10:26.644Z
Learning: In `autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunAgent/components/AgentDetailsCard/__tests__/helpers.test.ts`, the import path change from `./helpers` to `../helpers` was purely a file relocation into a `__tests__/` subdirectory — the helper module's contract did not change. `buildInputSchema({})` correctly returns `null` (empty properties check), `extractDefaults` correctly falls back to `examples[0]`, and `isFormValid(schema, formData)` has the correct argument order. Do not flag these assertions as mismatched after the path adjustment.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/frontend/**/*.{ts,tsx} : Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-05-12T09:59:51.200Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 0
File: :0-0
Timestamp: 2026-05-12T09:59:51.200Z
Learning: In `autogpt_platform/frontend/src/app/(platform)/copilot/useSendMessage.ts`, the pending-first-send stall watchdog logic was intentionally kept inline (not extracted to a separate `usePendingFirstSendWatchdog` hook) to comply with the AGENTS.md rule of keeping out-of-scope changes under 20% in a bug-fix PR. The file was already ~190 lines before this PR; the watchdog adds ~40 lines. A follow-up PR is planned to extract the watchdog into a dedicated hook. Do not flag the watchdog's inline placement in `useSendMessage.ts` as a refactor opportunity in the current PR context.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-04-30T13:34:34.273Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12958
File: autogpt_platform/frontend/src/app/(platform)/admin/spending/helpers.ts:24-41
Timestamp: 2026-04-30T13:34:34.273Z
Learning: In `autogpt_platform/frontend/src/app/(platform)/admin/spending/helpers.ts`, the credit transactions CSV export (`buildCreditTransactionsCsv`) intentionally omits `admin_user_id` from `CREDIT_CSV_HEADERS` and the row body. Plumbing that field through `UserTransaction` and regenerating `openapi.json` was considered disproportionate to the value — `admin_email` already encodes the audit identity. Do not flag the absence of `admin_user_id` in the CSV export as a missing audit field.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-04-01T18:54:16.035Z
Learnt from: Bentlybro
Repo: Significant-Gravitas/AutoGPT PR: 12633
File: autogpt_platform/frontend/src/app/(platform)/library/components/AgentFilterMenu/AgentFilterMenu.tsx:3-10
Timestamp: 2026-04-01T18:54:16.035Z
Learning: In the frontend, the legacy Select component at `@/components/__legacy__/ui/select` is an intentional, codebase-wide visual-consistency pattern. During code reviews, do not flag or block PRs merely for continuing to use this legacy Select. If a migration to the newer design-system Select is desired, bundle it into a single dedicated cleanup/migration PR that updates all Select usages together (e.g., avoid piecemeal replacements).
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-04-07T09:24:16.582Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12686
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/__tests__/PainPointsStep.test.tsx:1-19
Timestamp: 2026-04-07T09:24:16.582Z
Learning: In Significant-Gravitas/AutoGPT’s `autogpt_platform/frontend` (Vite + `vitejs/plugin-react` with the automatic JSX transform), do not flag usages of React types/components (e.g., `React.ReactNode`) in `.ts`/`.tsx` files as missing `React` imports. Since the React namespace is made available by the project’s TS/Vite setup, an explicit `import React from 'react'` or `import type { ReactNode } ...` is not required; only treat it as missing if typechecking (e.g., `pnpm types`) would actually fail.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-04-02T05:43:49.128Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12640
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/WelcomeStep.tsx:13-13
Timestamp: 2026-04-02T05:43:49.128Z
Learning: Do not flag `import { Question } from "phosphor-icons/react"` as an invalid import. `Question` is a valid named export from `phosphor-icons/react` (as reflected in the package’s generated `.d.ts` files and re-exports via `dist/index.d.ts`), so it should be treated as a supported named export during code reviews.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
📚 Learning: 2026-05-07T14:17:04.630Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13031
File: autogpt_platform/frontend/src/app/(platform)/admin/block-cost-estimates/components/useBlockCostEstimates.ts:31-72
Timestamp: 2026-05-07T14:17:04.630Z
Learning: In Significant-Gravitas/AutoGPT `autogpt_platform/frontend`, admin pages (under `src/app/(platform)/admin/`, including subfolders like `spending/`, `platform-costs/`, `block-cost-estimates/`) intentionally use manual server-state handling (manual fetch + toast + local/loading/error state) instead of React Query. When reviewing code in this admin area, do not flag manual fetch/state as a violation of any React Query guideline. If React Query adoption is ever required, do it in a single dedicated PR that covers all admin pages together (avoid piecemeal conversions).
Applied to files:
autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts
🔇 Additional comments (8)
autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes.py (1)
1-132: LGTM!autogpt_platform/backend/backend/api/features/admin/impersonation_admin_routes_test.py (1)
1-128: LGTM!autogpt_platform/backend/backend/api/rest_api.py (1)
23-23: LGTM!Also applies to: 361-365
autogpt_platform/frontend/src/app/api/openapi.json (2)
13760-13773: LGTM!
852-852:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
operationIdcontains a space, breaking code generation.The operationId
"postV2Notify impersonation start"has a space. OpenAPI codegen uses this to generate hook/function names, so the generated hook won't match the expectedusePostV2NotifyImpersonationStartpattern the frontend depends on.Since this file is auto-generated, fix the backend route by adding an explicit
operation_idparameter:`@router.post`( "/impersonation/notify", operation_id="postV2NotifyImpersonationStart", # <-- add this ... )Then regenerate with
pnpm generate:api.⛔ Skipped due to learnings
Learnt from: ntindle Repo: Significant-Gravitas/AutoGPT PR: 12536 File: autogpt_platform/frontend/src/app/api/openapi.json:5770-5790 Timestamp: 2026-03-24T21:25:15.983Z Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12536` File: autogpt_platform/frontend/src/app/api/openapi.json Learning: The OpenAPI spec file is auto-generated; per established convention, endpoints generally declare only 200/201, 401, and 422 responses. Do not suggest adding explicit 403/404 response entries for single operations unless planning a repo-wide spec update. Prefer clarifying such behaviors in endpoint descriptions/docstrings instead of altering response maps.Learnt from: Abhi1992002 Repo: Significant-Gravitas/AutoGPT PR: 12226 File: autogpt_platform/frontend/src/app/api/openapi.json:6542-6583 Timestamp: 2026-02-27T10:51:26.956Z Learning: In this repo, frontend/src/app/api/openapi.json is autogenerated from FastAPI; do not hand-edit it. To change the spec, update the backend route annotations (response_model/responses) or Pydantic models.Learnt from: Abhi1992002 Repo: Significant-Gravitas/AutoGPT PR: 13217 File: autogpt_platform/frontend/src/app/api/openapi.json:0-0 Timestamp: 2026-05-26T14:24:11.320Z Learning: In Significant-Gravitas/AutoGPT frontend OpenAPI generation, Orval sanitizes spaces and parentheses in `operationId` values into valid generated React Query hook names. Do not claim such operation IDs will necessarily break generation solely due to spaces/parentheses; instead, flag them as generating verbose or undesirable hook names when appropriate.Learnt from: Pwuts Repo: Significant-Gravitas/AutoGPT PR: 12284 File: autogpt_platform/frontend/src/app/api/openapi.json:5593-5593 Timestamp: 2026-03-04T23:57:59.510Z Learning: In Significant-Gravitas/AutoGPT backend (FastAPI), openapi.json is autogenerated: descriptions come from route docstrings and schemas from response_model/type annotations. To prevent drift when models are renamed (e.g., AdminView variants), avoid embedding specific schema class names in route docstrings; instead describe behavior, or keep names synced via backend edits—never hand-edit frontend/src/app/api/openapi.json.Learnt from: majdyz Repo: Significant-Gravitas/AutoGPT PR: 12566 File: autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts:968-974 Timestamp: 2026-03-26T00:32:06.673Z Learning: In Significant-Gravitas/AutoGPT, the admin-facing methods in `autogpt_platform/frontend/src/lib/autogpt-server-api/client.ts` (e.g., `addUserCredits`, `getUsersHistory`, `getUserRateLimit`, `resetUserRateLimit`) intentionally follow the legacy `BackendAPI` pattern with manually defined types in `autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts`. Migrating these admin endpoints to the generated OpenAPI hooks (`@/app/api/__generated__/endpoints/`) is a planned separate effort covering all admin endpoints together, not done piecemeal per PR. Do not flag individual admin type additions in `types.ts` as blocking issues.Learnt from: kcze Repo: Significant-Gravitas/AutoGPT PR: 12328 File: autogpt_platform/frontend/src/app/api/openapi.json:1116-1118 Timestamp: 2026-03-07T07:43:15.754Z Learning: In Significant-Gravitas/AutoGPT, v2 chat endpoints often declare HTTPBearerJWT at the router level while using Depends(auth.get_user_id) that returns None for unauthenticated users; effective behavior is optional auth. Keep this convention unless doing a repo-wide OpenAPI update; prefer clarifying descriptions over per-operation security changes.Learnt from: ntindle Repo: Significant-Gravitas/AutoGPT PR: 12536 File: autogpt_platform/frontend/src/app/api/openapi.json:5732-5752 Timestamp: 2026-03-24T21:27:22.326Z Learning: Repo: Significant-Gravitas/AutoGPT — Preference: Do not add explicit 403/404 entries to FastAPI route decorators for admin endpoints just to influence OpenAPI. Keep openapi.json autogenerated and use route docstrings to document admin-only (403) and not-found (404) behavior; rely on tests for enforcement. File context: autogpt_platform/backend/backend/api/features/admin/store_admin_routes.py. PR `#12536`.Learnt from: Pwuts Repo: Significant-Gravitas/AutoGPT PR: 12284 File: autogpt_platform/frontend/src/app/api/openapi.json:11897-11900 Timestamp: 2026-03-04T23:58:18.476Z Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12284` Backend/frontend OpenAPI codegen convention: In backend/api/features/store/model.py, the StoreSubmission and StoreSubmissionAdminView models define submitted_at: datetime | None, changes_summary: str | None, and instructions: str | None with no default. This is intentional to produce “required but nullable” fields in OpenAPI (properties appear in required[] and use anyOf [type, null]). This matches Prisma’s submittedAt DateTime? and changesSummary String?. Do not flag this as a required/nullable mismatch.Learnt from: majdyz Repo: Significant-Gravitas/AutoGPT PR: 13031 File: autogpt_platform/backend/backend/api/rest_api.py:361-365 Timestamp: 2026-05-07T14:17:47.431Z Learning: In the Significant-Gravitas/AutoGPT repository, the frontend API generated client directory `autogpt_platform/frontend/src/app/api/__generated__/` is gitignored. It is rebuilt locally by running `pnpm generate:api` from the committed `autogpt_platform/frontend/src/app/api/openapi.json`. Do NOT flag the absence of `__generated__/` as a missing code generation step — the committed `openapi.json` is the source of truth, and the generated files will be absent in a fresh checkout until `pnpm generate:api` is run.Learnt from: majdyz Repo: Significant-Gravitas/AutoGPT PR: 12213 File: autogpt_platform/frontend/src/app/api/openapi.json:9983-9995 Timestamp: 2026-02-27T15:59:00.370Z Learning: Repo: Significant-Gravitas/AutoGPT PR: 12213 — Backend/frontend OpenAPI codegen Learning: For MCP schema models, required OpenAPI fields must have no defaults in Pydantic. Specifically, MCPToolInfo.input_schema must be required (no Field(default_factory=dict)) so openapi.json emits it in "required", ensuring generated TS types treat input_schema as non-optional.autogpt_platform/frontend/src/app/(platform)/admin/components/useAdminImpersonation.ts (3)
6-6: LGTM!
26-27: LGTM!
32-55: LGTM!Also applies to: 70-70
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev #13299 +/- ##
========================================
Coverage 74.71% 74.72%
========================================
Files 2537 2539 +2
Lines 192315 192466 +151
Branches 18925 18998 +73
========================================
+ Hits 143697 143823 +126
- Misses 44493 44513 +20
- Partials 4125 4130 +5
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
…tion Integration tests (Vitest + RTL + MSW) for the impersonation start flow: - a 502 audit alert blocks the swap and surfaces a destructive toast - a delivered alert proceeds with the swap (state set + reload) - an empty user id is rejected without calling the API Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Added frontend integration coverage for the impersonation gate (Vitest + RTL + MSW), in
Verified: |
Addresses two Cursor Bugbot findings on the now-async impersonation start: - Re-entry guard: startImpersonating returns Promise<void>, uses a ref guard so rapid double-clicks can't fire duplicate audit alerts, and exposes isStarting so the Start button disables while in flight. - The panel now awaits startImpersonating and no longer clears the user-ID input up front, so a blocked/failed audit alert (502) keeps the entered ID for retry instead of wiping it. Adds a test covering the re-entry guard (only one audit alert for a double start). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Addressed both Cursor Bugbot findings on
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 642da4d. Configure here.
Cursor Bugbot finding: the notify handler derived the actor from get_user_id, which honors the X-Act-As-User-Id header. A lingering impersonation cookie (a prior session or another tab) could make the Discord alert and log name the impersonated user instead of the real acting admin — undermining the audit. Derive the actor from requires_admin_user (the JWT) instead, which ignores the impersonation header. Adds a regression test asserting the recorded actor is the JWT admin even when an X-Act-As-User-Id header is present on the request. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Addressed the third Cursor Bugbot finding ("Notify audit uses impersonated id") in 1ce5dec: The notify handler now derives the actor from Added a regression test asserting the recorded actor is the JWT admin even when an |
Backend (impersonation_admin_routes_test.py): - bounded timeout on a slow Discord send blocks the swap (502) - missing target_user_id fails validation (422) - email-lookup failure degrades to "unknown" but still delivers (200) - admin email is read from the JWT; only the target hits the DB Frontend (AdminImpersonationPanel.test.tsx, new): - Start disabled until a user id is entered - non-UUID input shows an inline error and does not swap - a blocked alert (502) keeps the entered id and toasts (regression guard) - a delivered alert starts impersonation (reload) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: ntindle <8845353+ntindle@users.noreply.github.com>
Resolved the merge conflicts in
|
|
Conflicts have been resolved! 🎉 A maintainer will review the pull request shortly. |
🔍 PR Overlap DetectionThis check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early. 🟢 Low Risk — File Overlap OnlyThese PRs touch the same files but different sections (click to expand)
Summary: 0 conflict(s), 0 medium risk, 4 low risk (out of 4 PRs with file overlap) Auto-generated on push. Ignores: |
|
This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request. |
|
@copilot upadate from dev (to fix the merge conflicts via regening the openapi.json) and also fix the linting and types check from teh ci |
Co-authored-by: ntindle <8845353+ntindle@users.noreply.github.com>
Done in |
|
Conflicts have been resolved! 🎉 A maintainer will review the pull request shortly. |
…rmatting The committed openapi.json was in expanded json.dump(indent=2) style and had never been run through prettier, so the "check API types" CI step (export-api-schema -> prettier -> git diff --exit-code) always reported a diff and failed. Regenerated via `poetry run export-api-schema` + `pnpm prettier --write`; the result is semantically byte-identical to the previous spec (same 220 paths / 360 schemas / canonical content), only the formatting/line-wrapping changes. Output is idempotent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XG5a6wZoCmWsKVjUCGgr6b
|
/review |
There was a problem hiding this comment.
📋 Automated Review — PR #13299
PR #13299 — feat(platform): alert + gate admin impersonation start via Discord
Author: ntindle | Files: 8
🎯 Verdict: APPROVE
PR Description Quality
✅ Has Why + What + How — the PR explains the audit-trail motivation ("rather block impersonation than let it happen with no audit trail"), the mechanism (notify endpoint gates the dashboard swap), and the fail-open no-token behavior. Two manual e2e checklist items remain unchecked, but QA exercised both live below.
What This PR Does
When an admin starts impersonating a user from the dashboard, the frontend now calls a new POST /api/admin/impersonation/notify endpoint that fires a real-time Discord alert before the identity swap happens. If Discord delivery fails, the swap is blocked (502 + toast); if no bot token is configured, it passes through so self-hosted deploys keep working. A server-side logger.info audit line is written on every start, and the acting admin is correctly derived from the JWT rather than the (spoofable) X-Act-As-User-Id header.
Specialist Findings
🛡️ Security requires_admin_user applied and double-enforced) and actor-from-JWT is a genuinely good choice with regression coverage. Two flags: the audit "gate" is UI-level only (below), and target_user_id is an unconstrained str (impersonation_admin_routes.py:53) interpolated into logs and Discord markdown → log/mention injection.
🟠 Server-side enforcement gap; unvalidated target_user_id.
🏗️ Architecture _DISCORD_SENT_STATUS = "Message sent" (impersonation_admin_routes.py:39) copied from bot_blocks.py:294 — an upstream wording change would silently block all dashboard impersonation.
🟠 Duplicated success sentinel across a module boundary.
⚡ Performance ✅ — Admin-only, human-click frequency, no scale concern. Each notify pays for a full Discord gateway login + guild sync (~1–3s, bounded to 10s) on the synchronous click path (impersonation_admin_routes.py:117); a webhook POST would cut this to ~100–300ms. awaited, so it never stalls the event loop. Acceptable as-is.
🧪 Testing :83) and retry-after-a-blocked-502 (useAdminImpersonation.ts:78) are unasserted.
📖 Quality ✅ — Grade A-. Well-named constants, excellent docstrings explaining the JWT-vs-header rationale. Minor: requires_admin_user wired both at router and handler level (harmless redundancy), test-call duplication.
📦 Product stopImpersonating emits no alert (unbounded "acting as" window in the record), and up to 10s of silent "Starting…".
📬 Discussion ✅ — All three Cursor Bugbot findings (double-start race, input-cleared-early, audit-uses-impersonated-id) were fixed in follow-up commits with matching tests. GitHub CI fully green on head c2e4aee, branch conflict-free. Process notes: 2 unchecked manual e2e items and Bentlybro's review is DISMISSED (no active human approval).
🔎 QA ✅ — Exercised live end-to-end. All 9 scenarios Actual = Expected: 401/403/422 auth+validation, 200 alerted:false with no token, 502 block on invalid token (0.24s, LoginFailure caught gracefully), audit line naming the real admin while a spoofed X-Act-As-User-Id header was ignored, and both UI paths (blocked-with-retained-UUID, allow-into-active-impersonation).
🟠 Should Fix
- Audit gate is client-side only; document or enforce server-side (
impersonation_admin_routes.py:82,useAdminImpersonation.ts:55) — The notify call gates only the dashboard swap. Real impersonation is driven by theX-Act-As-User-Idheader honored byget_user_id; any admin/tooling setting it directly impersonates with no alert and no log, undermining the stated guarantee. Either move the alert to the layer that honors the header, or explicitly document this as a dashboard-path-only audit and file a follow-up. (Flagged by: security, architect, product — 3 specialists) - Duplicated
"Message sent"success sentinel (impersonation_admin_routes.py:39) — Delivery success is inferred by string-equality against a literal copied frombot_blocks.py:294; if that wording drifts, every send reads as undelivered and all dashboard impersonation is blocked, and the test hard-codes the same string so it wouldn't catch it. Export a shared constant and import it in both places. (Flagged by: architect — 1) - Validate
target_user_idon the backend (impersonation_admin_routes.py:53) — Accepted as unconstrainedstr; frontend UUID regex is bypassed by direct API calls. Raw value flows into alogger.infoline (newline → log forgery) and Discord markdown (backticks/@here→ mention injection). Type it as a PydanticUUIDand/or strip control chars. (Flagged by: security — 1) - Add tests for the audit-log guarantee and retry-after-failure — The audit line written on every start (
impersonation_admin_routes.py:83) — the one behavior that survives with Discord disabled — has nocaplogassertion, and no test verifies thestartingRefre-entry guard resets after a 502 so a retry re-fires (useAdminImpersonation.ts:78). A stuck-true guard would permanently block impersonation and pass every existing test. (Flagged by: testing — 1)
🟡 Nice to Have
- Prefer a Discord webhook over full gateway login (
impersonation_admin_routes.py:117) — cuts click-to-swap latency from ~1–3s to ~100–300ms on the interactive path. (performance) - Audit
stopImpersonatingtoo (useAdminImpersonation.ts:89) — a non-gating stop alert/log would bound the "acting as" window in the record. (product) - Reconsider exporting both admin + target emails to Discord (
impersonation_admin_routes.py:118) — PII into a third-party chat system's retention; confirm against data-handling policy or send IDs only. (security)
🔵 Nits
- Duplicate
admintag in OpenAPI (impersonation_admin_routes.py:47+rest_api.py:365) — yields["v2","admin","admin","impersonation"]; drop one. (architect) operationIdcontains a space —"postV2Notify impersonation start"; give it a clean summary so codegen stays stable. (architect, quality)- Redundant
requires_admin_userat router + handler level (impersonation_admin_routes.py:57) — drop the router-level dependency or note the belt-and-suspenders. (quality) "(see plan)"in module docstring (impersonation_admin_routes.py:4) — points at an ephemeral doc; drop the parenthetical. (architect)- Weak actor-regression assertion (
impersonation_admin_routes_test.py:157) — only asserts the spoofed id is absent; also positively assert the real admin id is present. (testing)
QA Screenshots
| Screenshot | Description |
|---|---|
![]() |
Impersonation panel loaded ✅ |
![]() |
Before Start, UUID entered ✅ |
![]() |
502 block: destructive toast, UUID retained, no swap ✅ |
![]() |
Allow path: " |
Human Review Needed
YES — This changes the admin authorization/impersonation trust boundary (who can act as whom and how that is audited); a maintainer should confirm the UI-only-gate tradeoff is acceptable and provide a fresh approval, since Bentlybro's prior review was dismissed.
Risk Assessment
Merge risk: LOW | Rollback: EASY — additive, admin-only, no schema/migration changes; the no-token escape hatch keeps self-hosted deploys unaffected.
CI Status
GitHub CI: ✅ All required checks green on head c2e4aee (per discussion specialist: test/type-check 3.11–3.13, lint ×3, integration + e2e, CodeQL, codecov patch 98.77%).
Local harness: lint (frontend + backend), typecheck, and build all passed; pnpm test:unit (frontend) failed in the sandbox. Since GitHub CI ran the same suite green on this SHA, the local failure is environment skew, not a code defect — reported as a warning only.
UI Testing — Variant Results
✅ local: Live testing confirms the impersonation audit gate works end-to-end: 200 allow with no token, 502 block on failed Discord delivery, 403/401/422 auth+validation, JWT-based audit actor, and both UI paths behaving correctly.
✅ hosted: Live-tested admin impersonation Discord gate: 401/403/422 auth checks, no-token→allow, bad-token→502 block, JWT-based audit actor, and both UI flows (blocked toast + active banner) all behave exactly as designed.
|
This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request. |





Why / What / How
Why: Admin impersonation (
X-Act-As-User-Id) is currently only recorded in a backendlogger.infoline. We want a real-time audit alert when an admin starts impersonating someone, and we'd rather block impersonation than let it happen with no audit trail.What: Adds an admin-only endpoint that posts a Discord alert to the platform alerts channel when impersonation begins, and gates the dashboard "start impersonation" action on that alert succeeding.
How:
POST /api/admin/impersonation/notify(via the generated Orval client) before swapping identity. The Orval mutator throws on non-2xx, so a failed/blocked alert aborts the swap.sessionStorage, not yet set).discord_send_alerthelper to thePLATFORMchannel, with a bounded (~10s) timeout so a slow Discord gateway login can't hold the request open.discord_bot_tokenis configured, the alert is skipped and the swap is allowed (keeps non-Discord / self-hosted deployments working). If a token is set but delivery isn't confirmed — including the non-raising"Channel not found"case, wherediscord_send_alertreturns a status string rather than raising — the endpoint returns 502 so the swap is blocked. Delivery is considered successful only when the block returns its"Message sent"sentinel.logger.infoaudit line is written on every start regardless of token, so a trail exists even without Discord.Changes 🏗️
backend/api/features/admin/impersonation_admin_routes.py— admin-onlyPOST /api/admin/impersonation/notify(requires_admin_user); gates on Discord delivery.impersonation_admin_routes_test.py— covers: delivered→allow, no-token→allow (alert skipped), channel-not-found→502, send-raises→502, non-admin→403.backend/api/rest_api.py— register the new router under/api.frontend/.../admin/components/useAdminImpersonation.ts—startImpersonatingnow awaits the generatedusePostV2NotifyImpersonationStartmutation before swapping, and blocks + toasts on failure.frontend/src/app/api/openapi.json— regenerated to include the new endpoint.Checklist 📋
For code changes:
poetry run pytest .../impersonation_admin_routes_test.py— passing (5 cases)poetry run format/poetry run lint(ruff + black + isort + pyright) cleanpnpm format/pnpm lint/pnpm typescleanusePostV2NotifyImpersonationStarthookFor configuration changes:
.env.defaultis updated or already compatible (reuses existingdiscord_bot_token+platform_alert_discord_channel; no new config)docker-compose.ymlalready compatibleNote
High Risk
Changes admin impersonation gating and audit behavior; misconfigured Discord can block all dashboard impersonation when a token is set.
Overview
Admin impersonation from the dashboard now requires a successful audit notify before identity swap. A new admin-only
POST /api/admin/impersonation/notifyposts a Discord platform alert (admin + target IDs/emails), always logs server-side, and blocks with 502 when a bot token is set but delivery is not confirmed ("Message sent"only, with a ~10s timeout). No token → alert skipped, swap allowed (alerted: false). The audit actor is taken from the JWT admin, not impersonation headers.The admin UI
useAdminImpersonationawaits the generated notify mutation before writing impersonation state (so requests stay as the real admin), shows a destructive toast on failure, addsisStarting/ re-entry guard, and the panel keeps the entered UUID on blocked alerts. OpenAPI and backend/frontend tests cover delivery, skip, 502, timeout, and auth edge cases.Reviewed by Cursor Bugbot for commit c2e4aee. Bugbot is set up for automated code reviews on this repo. Configure here.