Commit Graph

9 Commits

Author SHA1 Message Date
joungmin
c7bd3c4c09 feat(cache): #336 SCAN/UNLINK + disabled 자동 복구 + 에러 메트릭
- CacheService.flush: redis.keys() 블로킹 → SCAN cursor + UNLINK 논블로킹.
  UNLINK 미지원 환경은 DEL로 폴백. 500 batch 단위.
- 30초 주기 @Scheduled checkHealth: Redis ping → disabled 자동 토글.
  startup 시 disabled=true여도 Redis 재기동되면 자동 복구.
- recordError 헬퍼: AtomicLong errorCount + volatile lastError.
  로그 throttle (n==1 || n%100==0만 WARN, 나머지 DEBUG).
- CacheStats record + GET /api/admin/cache/stats (admin only).
- 설계서: docs/design/336-cache-scan-recovery/README.md (Approved).

Refs: #336
2026-06-15 15:07:22 +09:00
joungmin
437e709a8d feat: P5-1 작은 후속 묶음 (#319+#325+#344)
#325 (#291 후속):
- VideoSseController.bulkExtract: Math.random() → ThreadLocalRandom 통일
  (bulkTranscript와 일관)
- VideoSseController.rebuildVectors: 즉시 complete(total=0) 대신 명시적
  'not_implemented' SSE 이벤트로 운영자 가시성 확보 + timeout 600s → 60s
- YouTubeService.getTranscript JavaDoc: mode 인자가 youtube-transcript-api
  폴백에서만 사용된다는 점, 브라우저 추출은 mode 무관 명시

#319 (#301 후속):
- RestaurantDetail: buildSearchQuery 헬퍼 추출 (외부 지도 검색 URL 조합)
  '한국' 단독 region 더미 케이스 가드 포함
- BottomSheet SNAP_POINTS/VELOCITY_THRESHOLD 정책 fn-doc 신규
  (docs/design/279-frontend-restaurant-detail/fn-bottomsheet-snap.md)

#344 (#283 후속):
- globals.css에 --z-bottom-sheet=50, --z-filter-sheet=60, --z-modal=70 토큰
- LoginMenu: zIndex 99999 매직 넘버 → var(--z-modal)

Refs: #319 #325 #344
2026-06-15 14:40:45 +09:00
joungmin
7fa623d22d docs: CHANGELOG v0.1.15+v0.1.16 기록 + #322 설계서 Approved 2026-06-15 13:07:08 +09:00
joungmin
d2e78b0363 feat(verify): #322 LLM 검증으로 잘못된/프랜차이즈 식당 자동 숨김
DB 마이그레이션 (운영 ATP에 사전 실행 완료):
- restaurants.hidden NUMBER(1) DEFAULT 0 NOT NULL
- restaurants.hidden_reason VARCHAR2(120)
- restaurants.verified_at TIMESTAMP
- idx_restaurants_hidden 인덱스

코드:
- Restaurant 도메인에 hidden/hiddenReason/verifiedAt 필드 추가
- RestaurantMapper.xml resultMap 갱신 + findAll에 hidden=0 조건 (includeHidden=true 시 제외)
- RestaurantMapper에 updateVerification/clearHidden/findUnverified/countUnverified 추가
- RestaurantService.findAll() includeHidden 오버로드 + 검증 헬퍼 메서드
- RestaurantVerifyService 신규 (verify, verifyAsync, verifyAll, buildPrompt, parseVerifyResponse)
  - LLM 응답이 JSON 아닐 때 안전 기본값(valid=true) → hidden 유지
  - 백필은 식당당 200ms sleep으로 LLM rate 보호
- PipelineService.processExtract 끝에 verifyAsync(restId) 호출 (신규 등록 자동 검증)
- AdminRestaurantController 신규 — requireAdmin 필수:
  - GET  /api/admin/restaurants/verify/pending
  - POST /api/admin/restaurants/verify/all?batchSize=10
  - POST /api/admin/restaurants/{id}/verify
  - PATCH /api/admin/restaurants/{id}/hidden {hidden, reason}

프롬프트:
- 식당명, 주소, 지역, cuisine, foods를 OCI GenAI로 보내 valid/is_franchise/reason 판정
- 보수적 가이드 (모호하면 valid=true)

설계서: docs/design/322-restaurant-llm-verify/README.md (Approved 대기)

Refs: #322
2026-06-15 13:04:23 +09:00
joungmin
2d41f22b83 fix(infra): #316 backend resource request 재산정 + RollingUpdate 25%/25% 복귀
노드 다운사이징(2×1OCPU/6GB) 이후 backend CPU request 500m이 노드 한도
의 절반을 차지해 rollingUpdate 데드락 발생. 임시 패치(maxSurge=0/
maxUnavailable=1) 상태를 합리화하여 25%/25% 기본 정책으로 복귀.

변경:
- cpu 500m/1 → 300m/800m
- mem 768Mi/1536Mi → 512Mi/1024Mi
- strategy 25%/25% 명시 (기본값 복귀)

근거: 실측 idle CPU 0.7%, RSS ~305 MB. peak 30-40% 추정 안에서 안전.
검증: 적용 후 노드 잔여 330m → 다음 배포 시 두 Pod 공존 가능 (무중단).
다운타임: 이번 1회 ~25초 (구 500m Pod 점유 해제), 다음 배포부터 0초.

설계서: docs/design/316-backend-resource-rightsize/README.md (Approved).

Refs: #316
2026-06-15 12:07:47 +09:00
joungmin
4638f605aa fix(security): [Developer] #267 AdminUserController GET 4종에 requireAdmin() 추가
CRITICAL: listUsers, userFavorites, userReviews, userMemos 4개 GET이 인증만 요구하고 admin 검사가 없어, 일반 사용자 토큰으로 전체 사용자 목록 및 타인 활동 조회 가능했음. 각 메서드 첫 줄에 AuthUtil.requireAdmin() 호출 추가 → non-admin은 403.

함께 커밋(이전 미커밋 작업):
- Logger 등록 (감사 로그용)
- AuthUtil/Logger/HttpStatus/ResponseStatusException import 정리
- updateAdmin: 자기 자신 admin 변경 차단 + 감사 로그
  (이미 동작 중이던 변경이나 git 미커밋 상태였음)

문서:
- 설계서 §3 인수조건에 권한 강제 항목 추가, 상태 Draft → Approved
- CHANGELOG.md 2026-06-15 핫픽스 항목 추가

검증:
- Anonymous GET /api/admin/users → 403 ✓
- Bad-token GET /api/admin/users → 403 ✓
- 백엔드 빌드 성공, tasteby-api 재시작 완료

Refs: #267
2026-06-15 11:17:48 +09:00
joungmin
80b553ec19 docs: 현행화 17개 설계서 Approved + 후속 이슈 백로그 등록
Reviewer 결과 17 PASS / 1 REJECT (#267 admin 권한 critical).
- 17개 설계서를 Draft → Approved로 갱신
- #267(backend-user)은 critical 결함으로 06-Reviewer 유지
- 후속 17개 개선 이슈(#289~#305) 자동 등록 — 결함 124건 백로그 반영
  (critical 3 / major 46 / minor 75)
- docs/README.md에 18개 설계서 인덱스 추가
- CHANGELOG.md 2026-06-15 섹션 추가

Refs: #266 #268-#283 (현행화 완료) #267 (대기) #289-#305 (백로그)
2026-06-15 11:08:18 +09:00
joungmin
e97a36a8d9 docs/design: tasteby 18개 기능 현행화 설계서 추가
- 백엔드 12개: auth/user/restaurant/video/extract-pipeline/search/review-memo/channel/stats/daemon/cache/health
- 프론트 6개: map/restaurant-detail/filter/review-memo/admin/login
- 12개 섹션 전 항목 채움 (목적/범위/인수조건/제약/아키텍처/데이터모델/함수명세표/흐름/엣지/테스트/리스크/미해결)
- 추적성 헤더에 구현 파일 경로 명시, 테스트는 TBD (현재 없음)
- 코드 변경 없음 — 기존 구현의 설계 문서화

Refs: #266 #267 #268 #269 #270 #271 #272 #273 #274 #275 #276 #277 #278 #279 #280 #281 #282 #283
2026-06-15 10:48:50 +09:00
joungmin
c78f928a2d ch-bootstrap: persona pipeline + Design-First + 안전-최대 권한
- Redmine 8단계 페르소나 파이프라인 (.claude/agents, workflows)
- Design-First docs 골격 (docs/design, docs/adr, docs/pipeline)
- 안전-최대 권한 정책 (.claude/settings.json)
- Tasteby 고유 규칙 보존 (CLAUDE.md 병합)
- scripts/enqueue.sh: Redmine 큐 투입

Refs: tasteby bootstrap
2026-06-15 10:20:50 +09:00