.claude/skills/verify-auth/SKILL.md
Verifies server-side authentication/authorization pattern compliance — req.user.userId extraction (no body userId), @RequirePermissions decorator, @AuditLog decorator, JwtAuthGuard coverage. Run after adding/modifying controller endpoints.
npx skillsauth add junnv93/equipment_management_system verify-authInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
백엔드 컨트롤러가 인증/인가 규칙을 올바르게 준수하는지 검증합니다:
req.user.userId로 사용자 식별, Body에서 userId 수신 금지@RequirePermissions() 데코레이터 적용| File | Purpose |
|---|---|
| apps/backend/src/modules/auth/guards/permissions.guard.ts | Permission Guard |
| apps/backend/src/modules/auth/decorators/permissions.decorator.ts | @RequirePermissions() |
| apps/backend/src/common/decorators/audit-log.decorator.ts | AuditLog 데코레이터 |
| apps/backend/src/types/auth.ts | SSOT: JwtUser, AuthenticatedRequest 타입 |
| apps/backend/src/database/utils/uuid-constants.ts | SYSTEM_USER_UUID |
| apps/backend/src/common/utils/enforce-site-access.ts | 크로스 사이트 접근 제어 |
| packages/shared-constants/src/permissions.ts | Permission enum |
상태 변경 DTO에 approverId/userId 필드가 정의되어 있지 않은지 확인합니다. PASS: DTO에 approverId/userId 없음. FAIL: Zod schema에 정의되어 있으면 위반.
상세: references/auth-checks.md Step 1
approve/reject 메서드에서 @Request() req: AuthenticatedRequest를 통해 userId를 추출하는지 확인.
PASS: 모든 approve/reject에 req 파라미터 존재. FAIL: 누락 메서드.
상세: references/auth-checks.md Step 2
POST/PATCH/DELETE 엔드포인트에 Permission Guard가 적용되어 있는지 확인합니다. PASS: 모든 변경 엔드포인트에 데코레이터 존재. FAIL: 누락.
상세: references/auth-checks.md Step 3
상태 변경 엔드포인트에 감사 로그가 기록되는지 확인합니다. PASS: 상태 변경 메서드에 @AuditLog 존재. FAIL: 누락.
상세: references/auth-checks.md Step 4
| Step | 검증 대상 | |---|---| | 5 | JwtUser 필드 접근 패턴 (레거시 user.id/user.role 사용 금지) | | 6 | Permission import 소스 (shared-constants에서만) | | 7 | @SkipAudit() 올바른 사용 (POST/PATCH/DELETE에 사용 금지) | | 8 | SYSTEM_USER_UUID 사용 (비-UUID 문자열 하드코딩 금지) | | 9 | AuthenticatedRequest 옵셔널 파라미터 탐지 | | 10 | enforceSiteAccess() 뮤테이션 엔드포인트 적용 |
상세: references/auth-checks.md Step 5~10
| # | 검사 | 상태 | 상세 |
| --- | --------------------------- | --------- | ------------------------------- |
| 1 | Body userId 금지 | PASS/FAIL | 위반 DTO 목록 |
| 2 | req.user.userId 추출 | PASS/FAIL | 누락 메서드 목록 |
| 3 | @RequirePermissions | PASS/FAIL | 누락 엔드포인트 목록 |
| 4 | @AuditLog | PASS/FAIL | 누락 메서드 목록 |
| 5 | JwtUser 필드 접근 | PASS/FAIL | 레거시 필드 사용 위치 |
| 6 | Permission import | PASS/FAIL | 잘못된 import 위치 |
| 7 | @SkipAudit() 오용 | PASS/FAIL | POST/PATCH/DELETE에 사용된 위치 |
| 8 | SYSTEM_USER_UUID 사용 | PASS/FAIL | UUID 컬럼에 비-UUID 하드코딩 |
| 9 | AuthenticatedRequest 옵셔널 | PASS/FAIL | req?: 또는 req!. 사용 위치 |
| 10 | enforceSiteAccess 적용 | PASS/FAIL | 누락 mutation 컨트롤러 |
| 11 | 라우트 선언 순서 | PASS/FAIL | 정적 sub-path 가 /:param 뒤에 선언된 위치 |
동일 prefix 아래에 정적 sub-path (/reorder, /upload-csv, /bulk, /search, /counts)와
파라미터 path (/:sectionId, /:id)가 공존할 때, 정적 경로가 파라미터 경로보다 먼저 선언되어야 한다.
NestJS Express 어댑터는 데코레이터 선언 순서대로 라우트를 등록하므로, 역순이면 "reorder" 같은
리터럴이 ParseUUIDPipe 에 UUID 로 파싱되어 즉시 400 Bad Request 를 반환한다.
탐지 방법:
# 컨트롤러 파일에서 같은 prefix 의 정적/파라미터 라우트 쌍 탐지
grep -n "@(Get|Post|Patch|Delete|Put)(" apps/backend/src/modules/**/*.controller.ts \
| grep -E "/:.*/" \
| # 같은 prefix 의 정적 경로가 파라미터 경로 뒤(더 큰 라인 번호)에 나오면 WARN
PASS: 정적 라우트가 파라미터 라우트 앞에 선언되어 있음.
FAIL: @Patch(':uuid/result-sections/:sectionId') 뒤에 @Patch(':uuid/result-sections/reorder') 가 선언됨.
배경: 2026-04-12 harness evaluator 1차 FAIL 사유. feedback_nest_route_order.md 영구화.
다음은 위반이 아닙니다:
@Public() 정상@Public() 정상src/common/metrics/) — Prometheus 스크래핑용 @Public() + @Get() 정상@RequirePermissions 필수 아님SseJwtAuthGuard 별도 가드 사용 정상@SkipPermissions() PATCH — 본인 설정만 변경하므로 정상POST/DELETE me/signature — @SkipPermissions() + @AuditLog + req.user.userId 추출, 본인 서명만 변경하므로 정상POST sync — @InternalServiceOnly() 가드 전용 엔드포인트. JWT 인증 불필요, @RequirePermissions 불필요. @AuditLog 적용됨 (행위자는 Anonymous User/시스템으로 기록 — 의도된 설계)testing
Verifies Zod validation pattern compliance — ZodValidationPipe usage (no class-validator), versionedSchema inclusion in state-change DTOs, controller pipe application, query DTO consistency. Run after adding/modifying DTOs or controller endpoints.
testing
Verifies cross-feature workflow E2E test coverage against critical-workflows.md checklist. Checks WF-01~WF-35 coverage, step completeness, role correctness, side-effect verification, and status transition assertions. Run after adding workflow tests or before PR.
testing
SSOT(Single Source of Truth) 임포트 소스를 검증합니다. 타입/enum/상수가 올바른 패키지에서 임포트되는지 확인. 타입/enum 추가/수정 후 사용.
development
Verifies SQL safety — LIKE wildcard escaping, N+1 query pattern detection, COUNT(DISTINCT) for fan-out JOINs, RBAC INNER JOIN enforcement. Run after adding/modifying search or list API endpoints.