Files
startover/docs/BUG-REPORT-2026-03-08.md
Johngreen de531bfe11 Protect admin pages, add store/subsidy actions
Enforce authentication/authorization for admin pages and add several management actions and UI improvements.

Key changes:
- Added auth checks and redirects on admin pages (contracts, stores, subsidies, vendors) to restrict access to SUPER_ADMIN/OPS_MANAGER.
- Hooked server actions to authenticated user IDs (release escrow, review/publish stores, review subsidies/vendors, open disputes, create subsidy cases, create match requests, submit/delete store drafts).
- Implemented store publish flow including policy version resolution and StoreActionButtons update to show approve/reject/publish based on reviewStatus.
- Added filtering UIs and query handling: admin lists (stores/subsidies/vendors) now support status filters; public stores list uses a new client StoreFilters component to build search params.
- New client-side improvements: invite form triggers router.refresh() after success; register page accepts/validates optional phone and persists it; store creation now uses createStoreDraftService and shows error banner on failure.
- Matching and subsidies pages now support contextual forms to create match requests and subsidy cases when a storeId is provided.
- Various UX tweaks: disabled inspection button, dispute form, list link styling, and revalidation calls after server actions.
- Added docs/BUG-REPORT-2026-03-08.md.

These changes centralize auth, connect actions to real user IDs, and improve admin and store workflows and filtering.
2026-03-08 23:15:21 +09:00

9.7 KiB

Startover DB 상호작용 전수조사 버그 리포트

조사일: 2026-03-08 조사 범위: DB와 상호작용하는 모든 페이지 (총 15개 페이지, 5개 API 라우트, 4개 서비스) 조사 방법: 코드 정적 분석 (모든 CRUD 경로 추적) 빌드 검증: pnpm turbo build 전체 통과 (7/7 tasks, 0 type errors)


수정 현황

심각도 발견 수정 완료 미수정
CRITICAL 6건 6건 0건
HIGH 9건 8건 1건
MEDIUM 8건 6건 2건
합계 23건 20건 3건

수정 완료 목록 (20건)

  • BUG-001~006: 하드코딩 사용자 ID → auth() 세션 사용 (CRITICAL x6)
  • BUG-007: /stores/new 서비스 레이어 우회 → createStoreDraftService 호출 (HIGH)
  • BUG-008: 매장 DRAFT→SUBMITTED 제출/삭제 + admin APPROVED→PUBLISHED 공개 버튼 (HIGH)
  • BUG-010: /stores 필터 동작 연결 (HIGH)
  • BUG-011: /contracts 분쟁 접수 버튼 → openDisputeService 연결 (HIGH)
  • BUG-012: /matching 매칭 요청 생성 폼 + matchRequest.create 구현 (HIGH)
  • BUG-013: /subsidies 지원금 케이스 생성 폼 + createSubsidyCaseService 연결 (HIGH)
  • BUG-014: admin 3개 페이지 필터 → searchParams + Link 연동 (HIGH)
  • BUG-015: 초대 후 목록 갱신 (router.refresh()) (HIGH)
  • BUG-017: 회원가입 전화번호 필드 추가 (MEDIUM)
  • BUG-018: /stores/new 에러 핸들링 추가 (MEDIUM)
  • BUG-019~022: 관리자 4개 페이지 인증 검증 추가 (MEDIUM x4)

미수정 (추가 작업 필요, 3건)

  • BUG-009: 매장 수정 폼 (DRAFT 상태 수정 기능)
  • BUG-016: 에스크로 RELEASE_REVIEW → RELEASED 전환 관리자 액션
  • BUG-023: /stores/new form validation 빈 문자열 검증 (도메인 서비스에서 부분 처리됨)

CRITICAL (즉시 수정 필요) - 전부 수정 완료

BUG-001: /stores/new - 하드코딩된 사용자 ID

  • 파일: apps/web/src/app/stores/new/page.tsx
  • 수정: TEMP_OWNER_USER_ID = BigInt(1)auth() 세션에서 session.user.dbId 사용

BUG-002: /vendors actions - 하드코딩된 사용자 ID

  • 파일: apps/web/src/app/vendors/actions.ts
  • 수정: ownerUserId: '1'session.user.dbId

BUG-003: /admin/stores - 하드코딩된 actorUserId

  • 파일: apps/web/src/app/admin/stores/page.tsx
  • 수정: actorUserId = '1'session.user.dbId

BUG-004: /admin/vendors - 하드코딩된 actorUserId

  • 파일: apps/web/src/app/admin/vendors/page.tsx
  • 수정: 4개 server action 모두 auth() 세션 사용

BUG-005: /admin/contracts - 하드코딩된 actorUserId

  • 파일: apps/web/src/app/admin/contracts/page.tsx
  • 수정: releaseEscrowService(prisma, contractPublicId, '1')session.user.dbId

BUG-006: /admin/subsidies - 하드코딩된 actorUserId

  • 파일: apps/web/src/app/admin/subsidies/page.tsx
  • 수정: 승인/반려 모두 session.user.dbId 사용

HIGH (빠른 수정 필요)

BUG-007: /stores/new - Server Action이 서비스 레이어를 우회

  • 파일: apps/web/src/app/stores/new/page.tsx
  • 수정: 직접 prisma.store.createcreateStoreDraftService 호출
  • 효과: 도메인 검증, AuditLog, OutboxEvent 정상 동작

BUG-008: 매장 등록 → 공개 플로우 단절

  • 수정 내용:
    • /stores/[id]: DRAFT 상태에서 "검토 제출" 버튼 (→SUBMITTED) + "삭제" 버튼 추가
    • /admin/stores: APPROVED 상태에서 "공개" 버튼 추가 (publishStoreService 연결)
    • StoreActionButtons: 상태별 버튼 분기 (SUBMITTED: 승인/반려, APPROVED: 공개)

BUG-009: /stores/[id] - 수정 기능 부재 ⚠️ 미수정

  • 파일: apps/web/src/app/stores/[id]/page.tsx
  • 현재 상태: 삭제는 가능 (DRAFT 상태), 수정 폼은 미구현
  • 남은 작업: 매장 정보 수정 폼 페이지 추가

BUG-010: /stores - 필터가 동작하지 않음

  • 파일: apps/web/src/app/stores/page.tsx
  • 수정: searchParams 기반 Prisma where 조건 연동 (region/industry/status 필터)

BUG-011: /contracts - "분쟁 접수" 버튼 미동작

  • 파일: apps/web/src/app/contracts/page.tsx
  • 수정: handleOpenDispute server action → openDisputeService 연결
  • 참고: "검수 요청" 버튼은 "준비 중" 상태로 비활성화

BUG-012: /matching - 매칭 요청 생성 기능 없음

  • 파일: apps/web/src/app/matching/page.tsx
  • 수정: handleCreateMatchRequest server action + 매칭 요청 폼 구현
    • storeId searchParams 처리, 매장 정보 조회
    • matchType(인수/철거/인테리어) 선택 + 메시지 입력
    • matchRequest.create + auditLog.create 트랜잭션

BUG-013: /subsidies - 지원금 케이스 생성 UI 없음

  • 파일: apps/web/src/app/subsidies/page.tsx
  • 수정: handleCreateSubsidyCase server action + 신청 폼 구현
    • storeId searchParams로 매장 연결
    • createSubsidyCaseService 호출
    • 체크리스트 진행률 프로그레스바 표시

BUG-014: 관리자 페이지 필터 버튼 미동작

  • 수정:
    • /admin/stores: FILTER_LABELS + searchParams + StoreReviewStatus 타입 캐스트
    • /admin/vendors: FILTER_BUTTONS + VendorCertificationStatus 타입 캐스트
    • /admin/subsidies: FILTER_BUTTONS + SubsidyCaseStatus 타입 캐스트

BUG-015: /admin/settings/invite - 초대 후 목록 갱신 안 됨

  • 파일: apps/web/src/app/admin/settings/invite/invite-form.tsx
  • 수정: 성공 시 router.refresh() 추가

MEDIUM (개선 필요)

BUG-016: /admin/contracts - releaseAction이 RELEASE_REVIEW까지만 처리 ⚠️ 미수정

  • 파일: apps/web/src/services/contract-service.ts:150-154
  • 증상: releaseEscrowServiceRELEASE_REVIEW로만 변경. RELEASED 전환 후속 처리 없음
  • 남은 작업: RELEASE_REVIEW → RELEASED 전환 관리자 액션 추가

BUG-017: /auth/register - 전화번호 필드 누락

  • 파일: apps/web/src/app/auth/register/page.tsx, actions.ts
  • 수정: phone 입력 필드 추가, zod 스키마에 phone 정규식 검증 추가

BUG-018: /stores/new - 에러 핸들링 부재

  • 파일: apps/web/src/app/stores/new/page.tsx
  • 수정: useActionState + ErrorBanner로 에러 표시

BUG-019~022: 관리자 페이지 인증 검증 없음

  • /admin/stores, /admin/vendors, /admin/contracts, /admin/subsidies
  • 수정: auth() + SUPER_ADMIN/OPS_MANAGER role 체크, 미인증 시 /403 redirect

BUG-023: /stores/new - form validation 불완전 ⚠️ 미수정

  • 현재 상태: createStoreDraftService 도메인 레이어에서 부분 검증
  • 남은 작업: 서버 측 빈 문자열 추가 검증

변경된 파일 목록 (15개 파일, +637 / -202 lines)

파일 변경 내용
apps/web/src/app/admin/contracts/page.tsx auth 가드, session.user.dbId
apps/web/src/app/admin/settings/invite/invite-form.tsx router.refresh()
apps/web/src/app/admin/stores/StoreActionButtons.tsx 상태별 버튼 분기 (publish 추가)
apps/web/src/app/admin/stores/page.tsx auth 가드, publish, 필터, enum 캐스트
apps/web/src/app/admin/subsidies/page.tsx auth 가드, 필터, enum 캐스트
apps/web/src/app/admin/vendors/page.tsx auth 가드, 필터, enum 캐스트
apps/web/src/app/auth/register/actions.ts phone zod 스키마 + DB 저장
apps/web/src/app/auth/register/page.tsx phone 입력 필드
apps/web/src/app/contracts/page.tsx 분쟁 접수 server action
apps/web/src/app/matching/page.tsx 매칭 요청 생성 폼 + server action
apps/web/src/app/stores/[id]/page.tsx 검토 제출 + 삭제 server action
apps/web/src/app/stores/new/page.tsx 서비스 레이어, auth, 에러 핸들링
apps/web/src/app/stores/page.tsx searchParams 필터 연동
apps/web/src/app/subsidies/page.tsx 지원금 신청 폼 + server action
apps/web/src/app/vendors/actions.ts session.user.dbId

페이지별 DB 상호작용 현황 (수정 후)

사용자 페이지

페이지 CREATE READ UPDATE DELETE 상태
/stores - O - - 필터 동작
/stores/new O - - - 서비스 레이어, auth
/stores/[id] - O O O 제출/삭제 (수정 미구현)
/vendors O O - - auth 세션 사용
/contracts - O O - 분쟁 접수 연결
/subsidies O O - - 신청 폼 구현
/matching O O - - 요청 생성 구현
/auth/register O O - - phone 추가
/auth/complete-profile O O O - 정상
/auth/invite/[token] O O O - 정상

관리자 페이지

페이지 CREATE READ UPDATE DELETE 상태
/admin/stores - O O - auth, 필터, publish
/admin/vendors - O O - auth, 필터
/admin/contracts - O O - auth
/admin/subsidies - O O - auth, 필터
/admin/settings/invite O O - - 목록 갱신

API 라우트

엔드포인트 동작 상태
POST /api/v1/stores CREATE 정상
POST /api/v1/stores/[id]/submit UPDATE 정상
POST /api/auth/complete-profile UPDATE 정상
POST /api/auth/invite/create CREATE 정상
POST /api/auth/invite/accept CREATE 정상