User Management Audit — Nougat DevPay (v5.0 Phase 0)
기준: HEAD 0b141a5a 이후. 기능 구분: IMPLEMENTED / PARTIAL / MOCK / MISSING.
1. 사용자 관리
| 기능 | 현재 구현 | 문제 | 재사용 여부 | 개선안 |
|---|---|---|---|---|
| User DB | users(id,email,password_hash,salt,role,seller_id,created_at) — mig 010 | profile/status/display_name 없음, 비활성화 불가 | 유지 | mig 011로 status,display_name,updated_at 추가 |
| Login | Workers POST /auth/login — HMAC토큰(24h) | Axum은 JWT(HS256,iss/aud/exp) — 형식·시크릿 불일치 | 유지 | 공통 토큰 계약 통일(서명 형식 동일화) |
| Signup | MISSING — users INSERT만 수동 | 일반 회원가입 없음 | 신규 | POST /auth/signup |
| User Role | users.role buyer|seller|admin | role 문자열만, membership 개념 없음 | 유지 | seller_membership 테이블로 확장 |
| Seller | users.seller_id 단일 연결 | seller_nougat 하드코딩 fallback 8곳 | 유지 | 온보딩으로 실생성, fallback 제거 |
| Authorization | verify_token + seller_id 스코핑 | 일부 seller_id 없는 테이블, role 체크 미검증 경로 | 유지 | who()로 (sub,role,seller) 통일 |
| Session/Logout | stateless 토큰, 만료만 | 로그아웃·폐기 없음 | 신규 | token revoke 또는 client clear + 짧은 exp |
| Password Hash | sha256(pw+salt) | PoC급 — PBKDF2/Argon2id 요구 | 변경 | WebCrypto PBKDF2(네이티브)로 승급 |
| Profile | MISSING | 조회/수정 없음 | 신규 | GET/PATCH /me |
| Deactivate/Delete | MISSING | 탈퇴 없음 | 신규 | POST /me/deactivate |
| Admin User Mgmt | MISSING | 사용자 목록/상태 없음 | 신규 | /admin/users |
| 계정 상태 | MISSING | status 컬럼 없음 | 신규 | status=active/inactive/banned |
2. 판매자 도메인
| 항목 | 현재 구현 | 개선안 |
|---|---|---|
| User↔Seller | users.seller_id 1:1 | seller_memberships(user_id,seller_id,role)로 N:M 확장 가능 구조 |
| Seller 생성 | MISSING — seed만 | POST /seller/onboarding (atomic seller+membership+settings+verification) |
| SellerSettings | seed로 초기화 | 온보딩에서 기본값으로 생성 |
| Verification | seed로 초기화 | 온보딩에서 NOT_REGISTERED로 생성 |
| 다중 판매자 | seller_id 컬럼만 | membership으로 여러 seller 소유 가능 |
3. Seed / Bootstrap
| 항목 | 현재 구현 | 문제 | 개선안 |
|---|---|---|---|
| Axum seed() | db.rs open()에서 NOUGAT_SEED!=0이면 자동 실행 | 서버 시작과 seed 결합 | 명시적 seed 경로로 분리 |
| FE createSeed() | fe/stores/db.ts init 시 항상 호출 | API mode에서도 mock 초기 상태 — 서버 권위 위반 | apiMode면 createSeed 생략 |
| seller_nougat | seed + 8곳 fallback | 고정 판매자 의존 | 명시적 seller 해결 + fallback 제거 |
| seeds/ dir | 없음 | 환경별 seed 분리 없음 | seeds/ |
| seed-data.ps1 | 없음 | 명시적 seed CLI 없음 | 신규 -Environment/-Profile/-DryRun |
| bootstrap-admin.ps1 | 없음 | prod 최초 admin 없음 | 신규, 중복 거부 |
| prod demo seed | 차단(NOUGAT_SEED) | 이미 구현됨 | 유지 |
4. 인증 통합 분석 (문제 A)
- Axum: JWT HS256 — iss=nougat-devpay, aud=nougat-api, exp. prod=NOUGAT_JWT_SECRET/X-Admin-Key
- Workers: 커스텀 HMAC 토큰 — payload.hmac_sha256(NOUGAT_AUTH_SECRET), 24h exp
- 불일치: 형식·시크릿·검증 로직이 완전히 다름. Workers login은 NOUGAT_AUTH_SECRET, prod auth()는 NOUGAT_API_SECRET 공유 secret fallback
개선안: Workers를 표준 JWT 형식으로 통일(HS256 header.payload.signature, iss/aud/exp) — Axum verify_jwt와 동일 계약. WebCrypto HMAC으로 서명. 비밀번호는 PBKDF2(cloudflare crypto.subtle 네이티브 — WASM CPU 한도 우회)로 승급.
5. 우선 구현 순서
- Phase 2: JWT 통일 + PBKDF2 + seller_nougat fallback 제거(→401/403)
- Phase 3: signup, /me(조회/수정/비밀번호변경/비활성화), admin/users
- Phase 8: seller onboarding (atomic)
- Phase 5+9: FE apiMode createSeed 제거 + 사용자 상태 격리
- Phase 4+6+7: seed 분리 + seed-data.ps1 + bootstrap-admin.ps1