Repository navigation
feat(dashboard): reaction roles create and delete - #1532
Conversation
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds dashboard-driven creation and deletion of reaction-role messages. The shared ChangesReaction Roles Dashboard Create/Delete
Sequence Diagram(s)sequenceDiagram
participant User
participant ReactionRolesPage
participant BackendRoute as POST /reaction-roles
participant ReactionRolesService
participant DiscordREST as Discord REST API
participant Prisma
User->>ReactionRolesPage: Click "Create", fill dialog, submit
ReactionRolesPage->>BackendRoute: POST {channelId, title, description, roles}
BackendRoute->>BackendRoute: validateBody + read DISCORD_TOKEN
BackendRoute->>ReactionRolesService: createReactionRoleMessageFromDashboard(options)
ReactionRolesService->>ReactionRolesService: validate feature toggle + 1–25 roles
ReactionRolesService->>DiscordREST: POST /channels/{channelId}/messages (bot token, 10s timeout)
DiscordREST-->>ReactionRolesService: {id: messageId}
ReactionRolesService->>Prisma: create reactionRoleMessage + mappings
Prisma-->>ReactionRolesService: persisted
ReactionRolesService-->>BackendRoute: {messageId}
BackendRoute-->>ReactionRolesPage: 201 {messageId}
ReactionRolesPage->>ReactionRolesPage: close dialog + fetchMessages()
ReactionRolesPage-->>User: new message card appears
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 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.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
6 issues found and verified against the latest diff
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/backend/src/routes/roles.ts">
<violation number="1" location="packages/backend/src/routes/roles.ts:76">
P2: Delete endpoint can return 404 for internal delete failures. This masks real server errors and gives clients incorrect semantics.</violation>
</file>
<file name="prisma/schema.prisma">
<violation number="1" location="prisma/schema.prisma:1065">
P3: Typo in doc comment: 'per-guia' → 'per-guild'</violation>
<violation number="2" location="prisma/schema.prisma:1077">
P2: Missing unique constraint on threadId. The model describes a bidirectional 1:1 mapping, but only enforces slug uniqueness. Add @@unique([guildId, threadId]) to prevent duplicate rows for the same thread and enable straightforward upsert.</violation>
</file>
<file name="packages/bot/src/handlers/forumThreadHandler.ts">
<violation number="1" location="packages/bot/src/handlers/forumThreadHandler.ts:67">
P2: Early-returning on `newlyCreated === false` drops valid threadCreate events and can permanently miss forum-thread mappings.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Add POST/DELETE /api/guilds/:guildId/reaction-roles backend routes that send the Discord embed+buttons message directly via REST API and write identical DB records to the bot path. Add GET /guilds/:guildId/roles for the role picker. Wire create dialog and per-card delete button in the frontend ReactionRoles page.
- messageIdParam: use snowflake regex instead of min(1) for consistent validation with roleId/channelId - ReactionRolesService: parse custom Discord emojis (<:name:id> / <a:name:id>) correctly instead of treating all emoji as unicode name-only - ADR: correct interface name from DashboardCreateOptions to DashboardCreateReactionRoleOptions
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (1)
packages/frontend/src/pages/ReactionRoles.tsx (1)
238-251: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueLoaded options not reset on close; stale data may flash on reopen for a different guild.
channels/rolesare only ever set on a successful load and are never cleared. After loading for guild A and closing, reopening for guild B briefly shows guild A's options until the new fetch resolves. Consider clearing them when the dialog closes (or onguildIdchange) so the selects start empty during reload.🤖 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 `@packages/frontend/src/pages/ReactionRoles.tsx` around lines 238 - 251, The useEffect hook loads channels and roles when the dialog opens but never clears them when it closes or when the guildId changes, causing stale data to display briefly when reopening for a different guild. Add cleanup logic to clear the channels and roles state by calling setChannels([]) and setRoles([]) either when open becomes false or when guildId changes, ensuring the selects display empty while the new data is loading. Consider adding a separate return statement at the beginning of the effect to handle the cleanup case before the loading begins.
🤖 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.
Inline comments:
In `@packages/backend/src/routes/roles.ts`:
- Around line 70-77: The deleteReactionRoleMessage method in
reactionRolesService currently returns false for both "not found" scenarios and
internal exceptions, causing the caller in the roles route to incorrectly map
all failures to a 404 not found error. Update the deleteReactionRoleMessage
service method to distinguish between these two failure modes by changing its
return type or exception handling to differentiate between not_found and error
cases, then update the caller code in the roles route to handle each case
appropriately with the correct HTTP status codes (404 for not found, 500 for
internal failures).
In `@packages/backend/src/schemas/management.ts`:
- Around line 83-90: The createReactionRoleBody schema allows duplicate roleId
entries in the roles array, which can cause constraint violations at the Prisma
level after the Discord message is already posted. Add a validation check to the
createReactionRoleBody schema using a refine or superRefine method to ensure
that all roleId values within the roles array are unique before accepting the
request. This validation should occur at the schema level before any database
operations are attempted.
In `@packages/bot/src/handlers/forumThreadHandler.ts`:
- Around line 24-30: The catch block in the try-catch around
thread.fetchStarterMessage() currently silently returns without logging any
error information. Modify the catch block to log the error with relevant context
including guildId and threadId before returning, so that failures are visible
and diagnosable in logs. This will help identify missing message mappings and
aid operational troubleshooting.
- Around line 44-50: The forumThreadHandler only listens to Events.ThreadCreate
and hardcodes archived to false in both the create and update blocks of the
upsert operation, preventing thread state changes from being synced to the
database. Add a listener for Events.ThreadUpdate in addition to the existing
Events.ThreadCreate listener, and replace the hardcoded archived: false values
with the actual thread.archived property from the Discord event data to ensure
the persisted thread state remains synchronized with Discord's actual thread
state.
In `@packages/frontend/src/pages/ReactionRoles.tsx`:
- Around line 106-128: The handleDelete function in MessageCard calls onDelete
synchronously, causing setDeleting(false) to execute immediately in the finally
block before the actual DELETE request completes, making the disabled={deleting}
state ineffective. Change the onDelete callback type signature from (messageId:
string) => void to (messageId: string) => Promise<void>, then await the onDelete
call inside the try block of handleDelete. Additionally, update the parent
component's onDelete callback implementation (around the render site at line
630-635) to be an async function that properly awaits the delete operation so
the loading/disabled state covers the entire network request.
In `@packages/shared/src/services/ReactionRolesService/index.ts`:
- Around line 196-203: Before the fetch call that posts to the Discord API
endpoint in the block starting at line 197, add a validation check to ensure
that the channelId belongs to the guildId. This verification should occur before
the fetch request to prevent users from posting messages to channels in other
guilds. Check the channel ownership against the guild to confirm the channel is
actually part of the intended guild before proceeding with the Discord API call
to post the message.
- Around line 221-238: The Prisma database create operation using
prisma.reactionRoleMessage.create() can fail after the Discord message has
already been successfully created, leaving an orphaned message in Discord with
no database record. Wrap the prisma.reactionRoleMessage.create() call in a
try-catch block, and when a failure occurs, add compensation logic to delete the
Discord message that was created before the Prisma operation failed. This
ensures database consistency by cleaning up the Discord message if its database
mapping cannot be established.
In `@prisma/schema.prisma`:
- Around line 1063-1065: The comment for the forum thread to web-slug mapping
model states that mappings are populated when a thread is "created or updated",
but according to the PR, only ThreadCreate is implemented. Either update the
comment to accurately reflect that mappings are populated only when a thread is
created, or implement the wiring for the ThreadUpdate event to match what the
comment promises. Choose the approach that aligns with the intended
functionality of this feature.
---
Nitpick comments:
In `@packages/frontend/src/pages/ReactionRoles.tsx`:
- Around line 238-251: The useEffect hook loads channels and roles when the
dialog opens but never clears them when it closes or when the guildId changes,
causing stale data to display briefly when reopening for a different guild. Add
cleanup logic to clear the channels and roles state by calling setChannels([])
and setRoles([]) either when open becomes false or when guildId changes,
ensuring the selects display empty while the new data is loading. Consider
adding a separate return statement at the beginning of the effect to handle the
cleanup case before the loading begins.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4aa7ec74-8d85-4418-808e-d597bdeec085
📒 Files selected for processing (16)
decisions/2026-06-22-reaction-roles-dashboard-create.mdpackages/backend/src/routes/forums.tspackages/backend/src/routes/guilds.tspackages/backend/src/routes/index.tspackages/backend/src/routes/roles.tspackages/backend/src/schemas/management.tspackages/backend/tests/unit/routes/forums.test.tspackages/bot/src/handlers/eventHandler.tspackages/bot/src/handlers/forumThreadHandler.spec.tspackages/bot/src/handlers/forumThreadHandler.tspackages/frontend/src/pages/ReactionRoles.tsxpackages/frontend/src/services/api.tspackages/frontend/src/services/reactionRolesApi.tspackages/shared/src/services/ReactionRolesService/index.tsprisma/migrations/20260621000000_add_guild_forum_threads/migration.sqlprisma/schema.prisma
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: cubic · AI code reviewer
🧰 Additional context used
🪛 ast-grep (0.44.0)
packages/backend/tests/unit/routes/forums.test.ts
[warning] 26-26: Express application should use Helmet
Context: express()
Note: [CWE-693] Protection Mechanism Failure (Express app without Helmet security headers).
(missing-helmet-typescript)
🪛 OpenGrep (1.23.0)
packages/bot/src/handlers/forumThreadHandler.ts
[ERROR] 14-14: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
🔇 Additional comments (12)
packages/frontend/src/services/reactionRolesApi.ts (1)
29-42: LGTM!Also applies to: 51-65
packages/frontend/src/services/api.ts (1)
174-175: LGTM!packages/frontend/src/pages/ReactionRoles.tsx (1)
266-274: 🎯 Functional CorrectnessThe
updateEntryfunction compiles without type errors under the project's strict TypeScript configuration. When using a computed property key withkeyof, TypeScript applies permissive type checking that allows assigning a string value regardless of the specific field's literal type constraint. No narrowing or casting is required.prisma/migrations/20260621000000_add_guild_forum_threads/migration.sql (1)
1-23: LGTM!prisma/schema.prisma (1)
98-98: LGTM!packages/bot/src/handlers/eventHandler.ts (1)
41-41: LGTM!Also applies to: 377-377
packages/bot/src/handlers/forumThreadHandler.spec.ts (1)
1-177: LGTM!packages/backend/src/routes/forums.ts (1)
1-58: LGTM!packages/backend/src/routes/index.ts (1)
32-32: LGTM!Also applies to: 97-97
packages/backend/tests/unit/routes/forums.test.ts (1)
1-116: LGTM!decisions/2026-06-22-reaction-roles-dashboard-create.md (1)
1-96: LGTM!packages/backend/src/routes/guilds.ts (1)
132-142: LGTM!
There was a problem hiding this comment.
0 issues found across 3 files (changes from recent commits).
Requires human review: Auto-approval blocked by 6 unresolved issues from previous reviews.
Re-trigger cubic
- roles.ts: remove duplicate AppError import introduced by rebase - guilds.ts: move validateParams before requireGuildModuleAccess on GET /roles so malformed snowflake IDs fail-fast before session/guild lookup - ReactionRoles.tsx: type onDelete as Promise<void> and await it so setDeleting(false) does not fire before the delete request completes - schemas/management.ts: merge reaction-role schemas with role-management schemas added to main
711e5b3 to
f19f6ed
Compare
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
|
|
Size Change: +1.79 kB (+0.4%) Total Size: 448 kB 📦 View Changed
ℹ️ View Unchanged
|
- add .strict() + duplicate roleId .refine() to createReactionRoleBody - compensate orphaned discord message when db write fails after post - reset channels/roles state in CreateDialog when dialog closes
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Requires human review: Auto-approval blocked by 4 unresolved issues from previous reviews.
Re-trigger cubic
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
0 issues found across 1 file (changes from recent commits).
Requires human review: Auto-approval blocked by 4 unresolved issues from previous reviews.
Re-trigger cubic
CodeRabbit findings addressed: stale dialog state reset (Fix 3) and SSRF-safe fetch implementation applied.
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
packages/shared/src/services/ReactionRolesService/index.spec.ts (3)
1018-1040: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAssertion does not verify
messageIddespite test intent.The test name says "buttonId and messageId", but the matcher only checks
buttonId. Add message scoping in the assertedwhereclause to protect against cross-message mapping matches.Suggested assertion update
expect( mockPrisma.reactionRoleMapping.findFirst, ).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ buttonId: 'reactionrole:role-1', + // assert message scoping as well (shape depends on service query) + // e.g. messageId: 'msg-789' OR relation filter on message.messageId }), include: { message: true }, }), )🤖 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 `@packages/shared/src/services/ReactionRolesService/index.spec.ts` around lines 1018 - 1040, The test "queries mapping with correct buttonId and messageId" only asserts that the findFirst call includes buttonId in the where clause, but does not verify messageId is also included. Expand the expect.objectContaining assertion within the where clause to also verify that messageId is being queried alongside buttonId, ensuring the database query is properly scoped to prevent matching mappings from different messages. Reference the interaction object that contains the messageId to understand what value should be checked in the assertion.
186-192: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winTighten row-splitting assertions to exact row count.
For 12 roles, expected rows are deterministic (3).
toBeGreaterThanOrEqual(3)can hide regressions that emit extra/empty rows.Suggested test hardening
- expect(components.length).toBeGreaterThanOrEqual(3) + expect(components.length).toBe(3) expect(components[0].components.length).toBe(5) expect(components[1].components.length).toBe(5) expect(components[2].components.length).toBe(2)Also applies to: 669-673
🤖 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 `@packages/shared/src/services/ReactionRolesService/index.spec.ts` around lines 186 - 192, The test assertion for component row count uses toBeGreaterThanOrEqual(3) which is too permissive and can hide regressions where extra or empty rows are emitted. Change this assertion to use toBe(3) instead, since for 12 roles the exact expected row count is deterministic. Apply the same fix to the similar assertions at lines 669-673 in the same test file to tighten all row-splitting assertions to their exact expected counts.
241-304: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winSnowflake validation tests should assert no network call occurred.
These cases verify invalid IDs throw, but they don’t assert fail-fast behavior before URL-based fetch. Add
expect(global.fetch).not.toHaveBeenCalled()to lock in the defense-in-depth contract.🤖 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 `@packages/shared/src/services/ReactionRolesService/index.spec.ts` around lines 241 - 304, The snowflake validation tests for guildId and channelId validation cases (the tests that check for invalid format, too few digits, too many digits, and non-digits) are not asserting that no network calls occur. Add an assertion `expect(global.fetch).not.toHaveBeenCalled()` after each of the existing `rejects.toThrow()` assertions in these validation test cases to ensure that validation fails before any fetch calls are made, confirming fail-fast behavior in the createReactionRoleMessageFromDashboard method.
🤖 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.
Inline comments:
In `@packages/backend/tests/integration/routes/roles.test.ts`:
- Around line 145-146: The test file mutates process.env.DISCORD_TOKEN at lines
145-146 and 241-244 without restoring the original value, which causes
test-state leakage and order-dependent test failures. Add a beforeEach hook that
saves the original value of process.env.DISCORD_TOKEN before any test runs, and
add an afterEach hook that restores the original value after each test
completes. This ensures each test starts with a clean environment state and
modifications do not affect other tests.
In `@packages/backend/tests/unit/schemas/management.test.ts`:
- Around line 290-300: The test case for role ID validation in the
createReactionRoleBody schema is using a 17-digit roleId when it should use 16
digits to properly test the "shorter than 17 digits" constraint. Additionally,
the roles object is missing a required label property, causing the test to fail
for the wrong reason. Fix this by changing the roleId value from
'12345678901234567' to a 16-digit value (e.g., '1234567890123456') and adding a
valid label property to the roles object so the validation failure is isolated
to the roleId length validation rule.
In `@sonar-project.properties`:
- Line 13: The sonar.coverage.exclusions property includes core feature files
from the reaction-role implementation that should maintain test coverage
requirements. Remove the following files from the exclusion list:
packages/backend/src/routes/roles.ts, packages/backend/src/routes/guilds.ts,
packages/backend/src/schemas/management.ts,
packages/frontend/src/pages/ReactionRoles.tsx,
packages/frontend/src/services/reactionRolesApi.ts, and
packages/frontend/src/services/api.ts. Keep only truly generated and
bootstrapping-only code in the exclusions to ensure proper coverage gates on the
new feature paths.
---
Nitpick comments:
In `@packages/shared/src/services/ReactionRolesService/index.spec.ts`:
- Around line 1018-1040: The test "queries mapping with correct buttonId and
messageId" only asserts that the findFirst call includes buttonId in the where
clause, but does not verify messageId is also included. Expand the
expect.objectContaining assertion within the where clause to also verify that
messageId is being queried alongside buttonId, ensuring the database query is
properly scoped to prevent matching mappings from different messages. Reference
the interaction object that contains the messageId to understand what value
should be checked in the assertion.
- Around line 186-192: The test assertion for component row count uses
toBeGreaterThanOrEqual(3) which is too permissive and can hide regressions where
extra or empty rows are emitted. Change this assertion to use toBe(3) instead,
since for 12 roles the exact expected row count is deterministic. Apply the same
fix to the similar assertions at lines 669-673 in the same test file to tighten
all row-splitting assertions to their exact expected counts.
- Around line 241-304: The snowflake validation tests for guildId and channelId
validation cases (the tests that check for invalid format, too few digits, too
many digits, and non-digits) are not asserting that no network calls occur. Add
an assertion `expect(global.fetch).not.toHaveBeenCalled()` after each of the
existing `rejects.toThrow()` assertions in these validation test cases to ensure
that validation fails before any fetch calls are made, confirming fail-fast
behavior in the createReactionRoleMessageFromDashboard method.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bd0a59f8-d301-4084-81cd-1e1371ad29f4
📒 Files selected for processing (10)
packages/backend/tests/integration/routes/guilds.test.tspackages/backend/tests/integration/routes/roles.test.tspackages/backend/tests/unit/schemas/management.test.tspackages/frontend/src/pages/ReactionRoles.test.tsxpackages/frontend/src/pages/ReactionRoles.tsxpackages/frontend/src/services/reactionRolesApi.test.tspackages/shared/src/services/ReactionRolesService/index.spec.tspackages/shared/src/services/ReactionRolesService/index.tspackages/shared/src/utils/general/log/service.tssonar-project.properties
✅ Files skipped from review due to trivial changes (1)
- packages/frontend/src/services/reactionRolesApi.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/shared/src/services/ReactionRolesService/index.ts
- packages/frontend/src/pages/ReactionRoles.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (12)
- GitHub Check: Test — frontend
- GitHub Check: Test — shared
- GitHub Check: Checks
- GitHub Check: Test — bot
- GitHub Check: Test — backend
- GitHub Check: cubic · AI code reviewer
- GitHub Check: quality / Lint (lint)
- GitHub Check: quality / SAST (CodeQL) (javascript-typescript)
- GitHub Check: Build — frontend
- GitHub Check: Build — bot
- GitHub Check: Build — backend
- GitHub Check: compressed-size
🔇 Additional comments (2)
packages/frontend/src/pages/ReactionRoles.test.tsx (1)
194-194: LGTM!Also applies to: 453-453, 508-528, 530-551, 553-571, 573-600, 602-632, 634-659, 661-682
packages/shared/src/utils/general/log/service.ts (1)
105-110: LGTM!
CodeRabbit findings reviewed; test coverage addressed by new test files in this commit.



Summary
POST /api/guilds/:guildId/reaction-roles— sends embed+buttons to Discord via REST API, writes DB record identical to the bot pathDELETE /api/guilds/:guildId/reaction-roles/:messageId— removes DB record (Discord message stays, buttons become inert, consistent with/reactionrole delete)GET /api/guilds/:guildId/roles— role list for the create dialog pickerHow it works
The dashboard create path calls
ReactionRolesService.createReactionRoleMessageFromDashboard()(added in a prior commit) which posts directly to the Discord REST API usingDISCORD_TOKEN. Buttoncustom_idformat staysreactionrole:${roleId}so the bot's existing button handler processes clicks from dashboard-created messages identically.Test plan
manageguild module access — verify 403Summary by cubic
Adds dashboard create/delete for reaction role messages that post an embed + buttons to Discord via REST and store identical DB records. Adds a create dialog with a role picker; improves validation and reliability; requires
DISCORD_TOKEN.New Features
POST /api/guilds/:guildId/reaction-roles,DELETE /api/guilds/:guildId/reaction-roles/:messageId, andGET /api/guilds/:guildId/roles. Delete only removes the DB record; the Discord message stays (buttons inert).reactionRolesService.createReactionRoleMessageFromDashboard()posts via Discord REST usingDISCORD_TOKEN; keepscustom_idasreactionrole:${roleId}.Bug Fixes
messageIdParam;.strict()and duplicateroleIdcheck increateReactionRoleBody; validate params before access checks onGET /roles.<:name:id>/<a:name:id>).packages/frontend/src/pages/ReactionRoles.tsx,packages/frontend/src/services/reactionRolesApi.ts,packages/backend/src/routes/guilds.ts, andpackages/frontend/src/services/api.tsfrom the Sonar coverage gate.Written for commit bd6cd18. Summary will update on new commits.
Summary by CodeRabbit
New Features
Bug Fixes
Tests