fix(rbac): return the documented { error: { code, message } } shape from forbiddenByRole - #355
Conversation
forbiddenByRole emitted { error: 'forbidden', message } — a string `error`,
which the documented API contract forbids ("직접 { error: 'string' } 패턴 사용
금지"). The browser api-client reads data.error?.code and data.error?.message,
so for the string shape BOTH are undefined: the RBAC denial's code and its
Korean role-explanation message are silently dropped and the user sees only the
generic "API request failed: 403" fallback.
Return { error: { code: 'FORBIDDEN', message } } (built inline to keep this
DB-free module importable in the vitest server env — the codebase's other
inline sites do the same). Update rbac.test.ts, which pinned the wrong shape
(body.error === 'forbidden', top-level body.message), to assert
body.error.code === 'FORBIDDEN' and the nested body.error.message.
Scope: this fixes the shared RBAC denial helper (the common path, pinned by
tests). The same { error: 'string' } pattern remains at ~40 other route sites
(e.g. orgs/[orgSlug]/members/[memberUserId]/route.ts) and is a follow-up sweep.
Verification: pnpm --filter @argos/web exec vitest run src/lib/server/rbac.test.ts
→ 35 passed; tsc --noEmit → clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH
|
Warning Review limit reached
Next review available in: 21 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthrough루트 및 웹 패키지 의존성을 업데이트하고, RBAC 역할 거부 응답을 문자열 오류에서 코드와 메시지를 포함하는 객체 구조로 변경했습니다. 관련 테스트도 새 응답 형식에 맞게 갱신했습니다. Changes의존성 업데이트
RBAC 오류 응답 계약
Estimated code review effort: 2 (Simple) | ~15 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
CI status: the red checks are pre-existing base issues, not this diffThis PR is a 2-line TypeScript error-shape fix (
Flagging once rather than re-reacting to each re-run. If any of these produces a new, non-empty finding that actually points at Generated by Claude Code |
…highs) Clears the org Security Scan / npm-audit findings that are cleanly fixable: Runtime (packages/web + overrides): - next-auth 5.0.0-beta.30 -> 5.0.0-beta.32 and @auth/core -> 0.41.3 (clears the two CRITICAL Auth.js advisories GHSA-8fpg-xm3f-6cx3 and GHSA-7rqj-j65f-68wh, plus GHSA-xmf8-cvqr-rfgj high and GHSA-x445-f3h2-j279) - next 15 -> ^15.5.22 (clears CVE-2026-64641/64649/64645 high + 64648/64647/ 64646/64644/64643 moderate) - sharp -> ^0.35.0 (GHSA-f88m-g3jw-g9cj high), postcss -> ^8.5.18 (GHSA-r28c-9q8g-f849 high) Dev/build overrides refreshed/added: - hono 4.12.25 -> 4.12.27 (the two prior overrides pinned vulnerable versions) - js-yaml 4.2.0 -> 4.3.0 (GHSA-52cp-r559-cp3m), fast-uri -> ^3.1.4 (GHSA-v2hh-gcrm-f6hx + GHSA-4c8g-83qw-93j6) - brace-expansion per-major (@1 ^1.1.16, @2 ^2.0.2, @5 ^5.0.8): a blanket ^5.0.8 breaks minimatch@3.1.5 (v1 callable export; "expand is not a function" -> lint crash), so each major is patched to its own line. This clears the ReDoS (GHSA-3jxr-9vmj-r5cp). Verified: pnpm --filter @argos/web typecheck (0), test (230 passed / 13 skipped), lint (0). pnpm audit: all critical/high runtime advisories cleared. Known residuals (not cleanly fixable here, dev-only, flagged on the PR): - brace-expansion OOM (GHSA-mh99-v99m-4gvg) is patched only >=5.0.8, but reaches via @eslint/eslintrc -> minimatch@3.1.5 which requires brace-expansion 1.x's export; clearing it needs an eslint-toolchain upgrade. - @hono/node-server path-traversal (GHSA-frvp-7c67-39w9) needs the breaking v1->v2 major. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH
|
Added a second, thematically-separate commit to this branch ( What it clears (org Security Scan /
Verified: Known residuals (dev-only, flagged not silently dropped):
Generated by Claude Code |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
package.json (1)
25-25: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win
@auth/core오버라이드의 상한을 제한하세요.
>=0.41.3은 향후 호환성이 검증되지 않은 버전까지 허용합니다. 인증 의존성은 검증된 패치/마이너 범위로 고정하거나 상한을 추가해, lockfile 재생성 시 예기치 않은 동작 변경을 방지하는 편이 안전합니다.🤖 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 `@package.json` at line 25, Update the `@auth/core` dependency constraint in package.json to retain the minimum supported version while adding a tested upper bound, or pin it to the verified patch/minor range, so lockfile regeneration cannot select unvalidated future releases.
🤖 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 `@package.json`:
- Line 25: Update the `@auth/core` dependency constraint in package.json to retain
the minimum supported version while adding a tested upper bound, or pin it to
the verified patch/minor range, so lockfile regeneration cannot select
unvalidated future releases.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b37000f1-e354-4823-a3f6-aa5a1a64f83d
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
package.jsonpackages/web/package.jsonpackages/web/src/lib/server/rbac.test.tspackages/web/src/lib/server/rbac.ts
Address review feedback: the `>=0.41.3` override was open-ended, letting a lockfile regeneration pick unvalidated future @auth/core releases. Pin to ^0.41.3 (allows 0.41.x patches, resolves to 0.41.3, compatible with the pinned next-auth 5.0.0-beta.32) so an auth dependency cannot drift unvalidated. Verified: pnpm --filter @argos/web typecheck (0); @auth/core resolves 0.41.3; critical/high runtime advisories remain cleared. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH
|
Addressed the review + triaged the failing CI (drive-to-green on the security commit): Review nitpick — done ( Failing security gates — the documented residual, not a regression:
Net effect of this commit: the two CRITICAL Auth.js advisories + all runtime HIGHs (next-auth, next, sharp, postcss, @auth/core) are cleared and verified (typecheck + 230 tests + lint green). The remaining red is confined to dev-only, toolchain-coupled residuals that predate this PR. Note (ONE SOURCE): CodeRabbit flags #344 / #356 / #353 as overlapping dependency/RBAC PRs — this branch and those should be de-duplicated so only one dependency-bump lands. Generated by Claude Code |
…-pr-audit-governance-1hdcp5 # Conflicts: # package.json # pnpm-lock.yaml
Problem
packages/web/src/lib/server/rbac.tsforbiddenByRole()emitted:erroris a string, which the documented API contract explicitly forbids (CLAUDE.md: "모든 API 에러 응답은{ error: { code, message } }", "직접{ error: 'string' }패턴 사용 금지"). The browserapi-clientreadsdata.error?.codeanddata.error?.message, so for the string shape both areundefined— the RBAC denial'scodeand its Korean role-explanationmessageare silently dropped and the user sees only the generic"API request failed: 403 Forbidden"fallback instead of why they were denied and what role is required.Fix
Return the documented nested shape:
Built inline (not via the
jsonErrorhelper) on purpose:error-helper.tsbegins withimport 'server-only', and pulling it intorbac.tsdrags that throwing module intorbac.test.ts's import graph (the vitest config has noserver-onlystub). The codebase's other inline error sites do the same, and the contract is about the response shape, which this satisfies.rbac.test.tshad pinned the wrong shape (body.error === 'forbidden', top-levelbody.message); updated to assertbody.error.code === 'FORBIDDEN'and the nestedbody.error.message.Scope
This fixes the shared RBAC denial helper — the common, test-pinned path. The same
{ error: 'string' }pattern remains at ~40 other route sites (e.g.orgs/[orgSlug]/members/[memberUserId]/route.ts:52,119) and is a follow-up sweep, intentionally out of scope here to keep this change small, test-backed, and low-risk.Verification
(CI builds
@argos/sharedbefore typecheck/test; done locally too.)🤖 Generated with Claude Code
https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH
Generated by Claude Code
Summary by CodeRabbit
버그 수정
업데이트