.claude/skills/verify-hardcoding/SKILL.md
SSOT 소스가 존재하는 값의 하드코딩을 탐지합니다. API 경로, queryKeys, 환경변수, 캐시 키, 토큰 TTL, 페이지 옵션 등. 기능 구현 후 사용.
npx skillsauth add junnv93/equipment_management_system verify-hardcodingInstall 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.
SSOT 소스(중앙 상수, 유틸리티, 팩토리)가 존재하는 값이 하드코딩되어 있는지 탐지합니다:
API_ENDPOINTS 대신 문자열 직접 사용queryKeys 팩토리 대신 배열 직접 생성API_BASE_URL 대신 process.env 직접 접근Promise<unknown> 안티패턴shared-constants 대신 매직 넘버getTableColumns() 대신 필드 목록 하드코딩ease-[cubic-bezier(...)] 대신 CSS 변수/TRANSITION_PRESETS.limit(20) 대신 SSOT 상수임포트 소스 검증은
/verify-ssot에서 수행합니다.
| File | Purpose |
|---|---|
| apps/frontend/lib/api/query-config.ts | queryKeys 팩토리 |
| apps/frontend/lib/config/api-config.ts | SSOT API_BASE_URL |
| apps/frontend/lib/config/pagination.ts | PAGE_SIZE_OPTIONS, DEFAULT_PAGE_SIZE |
| apps/frontend/lib/errors/equipment-errors.ts | ErrorCode ↔ EquipmentErrorCode 매핑 |
| apps/backend/src/common/cache/cache-key-prefixes.ts | CACHE_KEY_PREFIXES SSOT |
| apps/backend/src/modules/equipment/utils/request-data-codec.ts | requestData 코덱 |
| packages/shared-constants/src/auth-token.ts | 토큰 TTL SSOT |
| packages/shared-constants/src/business-rules.ts | 비즈니스 규칙 상수 SSOT |
| packages/shared-constants/src/pagination.ts | 페이지네이션 상수 SSOT |
| packages/schemas/src/validation/messages.ts | VM SSOT |
| apps/frontend/lib/api/utils/response-transformers.ts | unwrapResponseData SSOT |
| apps/backend/src/common/base/versioned-base.service.ts | VERSION_CONFLICT_MESSAGE SSOT |
| packages/shared-constants/src/form-catalog.ts | FORM_CATALOG SSOT (양식 번호, 이름, 보존기간) |
| apps/frontend/lib/utils/file-url.ts | fetchStorageFileUrl — FILES.SERVE + arraybuffer 분기 |
| apps/frontend/components/shared/StorageImage.tsx | StorageImage — queryKeys.storageFiles SSOT 사용 |
| packages/shared-constants/src/api-endpoints.ts | FILES.SERVE SSOT (/api/files) |
각 Step의 bash 명령어, 코드 예시: references/step-details.md 참조
PASS: API 클라이언트에서 API_ENDPOINTS 외 경로 0개. FAIL: 문자열 직접 사용.
PASS: 모든 queryKey가 queryKeys 팩토리 사용. FAIL: queryKey: ['equipment', 'detail'] 하드코딩.
PASS: public 서비스 메서드에 Promise<unknown> 0개. FAIL: 타입 명시 필요.
PASS: api-config.ts/tests/e2e 제외 process.env.NEXT_PUBLIC_API_URL 0개.
PASS: auth 파일에 15m, 7d, 계산식 하드코딩 0개. SSOT: packages/shared-constants/src/auth-token.ts.
PASS: SSOT 파일 외 직접 선언 0개.
PASS: 서비스/헬퍼에서 하드코딩 캐시 키 프리픽스 0개.
PASS: SSOT 파일 외 직접 선언 0개. 매직넘버 직접 사용 0개.
PASS: ErrorCode 주요 값이 mapBackendErrorCode에 매핑됨.
PASS: getTableColumns() 기반. FAIL: 하드코딩 필드 배열.
PASS: equipment-approval.service.ts에 JSON.parse/stringify 직접 호출 0개.
PASS: DTO에 하드코딩 한국어 메시지 0개. E2E에 이메일 리터럴 0개.
PASS: 교정 임계값(30, 7) 매직넘버 0개. SSOT: CALIBRATION_THRESHOLDS.*.
PASS: createVersionConflictException() 헬퍼 사용. 인라인 ConflictException 0개.
PASS: ease-[cubic-bezier(...)] 0개. ease-[var(--ease-*)] 또는 TRANSITION_PRESETS 사용.
PASS: .limit(숫자) 0개 (.limit(1) 제외). SSOT 상수 사용.
PASS: 3개 API 클라이언트 모두 unwrapResponseData 사용. return response.data 직접 반환 0개.
PASS: 양식 번호(UL-QP-18-XX, UL-QP-19-XX)가 FORM_CATALOG 상수로 참조. FAIL: 문자열 직접 사용.
탐지 명령어:
rg "\.xlsx|\.docx" apps/frontend/lib/api/ --type ts -n | grep -v "node_modules\|\.d\.ts" | grep -v "import\|require\|Content-Type"
PASS: 파일 확장자(.xlsx, .docx)가 서버 Content-Disposition 또는 FORM_CATALOG 기반으로 결정됨. FAIL: 프론트엔드에서 확장자 배열(XLSX_FORMS = [...] 등) 하드코딩하여 서버 반환 형식과 불일치 발생 가능.
| # | 검사 | 상태 | 상세 |
| --- | ----------------------------- | --------- | -------------------------------------- |
| 1 | 하드코딩 API 경로 | PASS/FAIL | 하드코딩 위치 목록 |
| 2 | queryKeys 팩토리 | PASS/FAIL | 하드코딩 queryKey 위치 |
| 3 | Promise<unknown> 반환 타입 | PASS/FAIL | unknown 반환 위치 |
| 4 | 환경변수 직접 참조 | PASS/FAIL | 직접 참조 위치 |
| 4b | E2E Backend URL SSOT | PASS/FAIL | 직접 env 참조 파일 |
| 5 | 토큰 TTL 하드코딩 | PASS/FAIL | 하드코딩 위치 |
| 6 | SITE_VALUES 로컬 재정의 | PASS/FAIL | 로컬 선언 위치 |
| 7 | PAGE_SIZE_OPTIONS 로컬 재정의 | PASS/FAIL | 직접 선언 위치 |
| 8 | CACHE_KEY_PREFIXES SSOT | PASS/FAIL | 하드코딩 캐시 키 위치 |
| 9 | APPROVAL_KPI 임계값 | PASS/FAIL | 하드코딩 임계값 위치 |
| 10 | ErrorCode↔프론트엔드 매핑 | PASS/FAIL | 누락된 매핑 목록 |
| 11 | DTO→Entity 동적 매핑 | PASS/FAIL | 하드코딩 필드 목록 위치 |
| 12 | requestData 코덱 | PASS/FAIL | 직접 JSON.parse 위치 |
| 13 | DTO 검증 메시지 VM SSOT | PASS/FAIL | 하드코딩 한국어 메시지 위치 |
| 13b | Test User Email SSOT | PASS/FAIL | 하드코딩 이메일 위치 |
| 14 | CALIBRATION_THRESHOLDS | PASS/FAIL | 매직넘버 위치 |
| 15 | VERSION_CONFLICT 일관성 | PASS/FAIL | SSOT 불일치 서비스 |
| 16 | CSS easing 하드코딩 | PASS/FAIL | ease-[cubic-bezier] 위치 |
| 17 | 페이지네이션 매직넘버 | PASS/FAIL | .limit(숫자) 위치 |
| 18 | unwrapResponseData SSOT | PASS/FAIL | 인라인 래핑 해제 위치 |
| 19 | FORM_CATALOG 양식 번호 SSOT | PASS/FAIL | 하드코딩 양식 번호 위치 |
| 20 | 파일 확장자/MIME 타입 SSOT | PASS/FAIL | 하드코딩 확장자 배열 위치 |
SITE_OPTIONS 등 레이블+값 쌍은 로컬 정의 허용shared-test-data.ts의 BACKEND URL — E2E 테스트용 URL SSOTPromise<unknown> private 헬퍼 — 클래스 내부 전용은 면제primitives.ts의 JSDoc 주석 — easing SSOT 정의 문서 면제.limit(1) 단일 레코드 조회 — 페이지네이션이 아닌 단건 조회 면제audit.service.ts formatLogMessage() 및 reports.service.ts 보고서 행 생성에서 AuditLogUserRole 특수값('system', 'unknown')에 대한 '시스템', '알 수 없음' 한국어 레이블 직접 사용은 허용. 백엔드 텍스트 생성 전용이며 브라우저 i18n 시스템을 경유할 수 없음. USER_ROLE_LABELS가 커버하지 않는 특수값이므로 인라인 처리가 정상 설계.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.