- BossRoom 세션명을 매 입장마다 고유하게 생성 (슬롯명_타임스탬프)
- SlotSessionName 필드 추가로 슬롯 리셋 시 원래 슬롯명 사용
- DeleteRoomBySlotSessionName 추가 (dedicated server ResetRoom 대응)
- CompleteRaid/FailRaid/cleanup에서 슬롯 리셋 로직 수정
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CRITICAL:
- graceful shutdown 레이스 수정 — Listen을 goroutine으로 이동
- Register 레이스 컨디션 — sentinel error + MySQL duplicate key 처리
HIGH:
- 멱등성 키에 method+path 포함 — 엔드포인트 간 캐시 충돌 방지
- 입장 토큰 생성 실패 시 방/슬롯 롤백 추가
MEDIUM:
- RequestEntry 슬롯 없음 시 503 반환
- chain ExportWallet/GetWalletInfo/GrantReward 에러 처리 개선
- resolveUsername 에러 타입 구분 (duplicate key vs 기타)
- 공지사항 길이 검증 byte→rune (한국어 256자 허용)
- Level 검증 범위 MaxLevel(50)로 통일
- admin 자기 강등 방지
- CORS ExposeHeaders 추가
- MySQL DSN loc=Local→loc=UTC
- hashGameExeFromZip 100MB 초과 절단 감지
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HTTP 핸들러에서 동기 재시도(3회 + sleep 1s/2s)를 제거하고
1회만 시도 후 실패 시 즉시 RewardFailure DB에 저장.
기존 RewardWorker가 백그라운드에서 재시도 처리.
변경 전: 최악 ~18초 블로킹 (데디서버 15초 타임아웃 초과)
변경 후: RPC 1회 × 플레이어 수 ≈ 2-3초
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- RequestEntry에서 MaxPlayers를 len(usernames)로 설정 (기존 고정 3 → 동적)
- ValidateEntryToken 응답에 expectedPlayers 필드 추가
- 데디 서버가 파티 크기만큼 접속 시 레이드 시작 가능
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HIGH (3건):
- 런처 파일 업로드 시 PE 헤더 검증 + 500MB 크기 제한 추가
- 체인 노드 URL 파싱 시 scheme/host 유효성 검증
- Dockerfile 비루트 사용자(app:1000) 실행
MEDIUM (7건):
- SSAFY username 충돌 시 랜덤 suffix로 최대 3회 재시도
- 내부 API username 검증 validID(256자) → validUsername(3~50자) 분리
- 동시 업로드 경합 방지 sync.Mutex 추가
- 프로덕션 환경변수 검증 강화 (DB_PASSWORD, OPERATOR_KEY_HEX, INTERNAL_API_KEY)
- Redis 에러 시 멱등성 요청 통과 → 503 거부로 변경
- CORS AllowOrigins 환경변수화 (CORS_ALLOW_ORIGINS)
- Refresh 엔드포인트 rate limiting 추가 (IP당 5 req/min)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
타임아웃 대신 Redis entry token 존재 여부로 판단:
- pending token이 Redis에 남아있음 → 정상 로딩 중, 방 보존
- pending token이 없음 (만료/소비) → abandoned 확정, 즉시 정리
정상 로딩 중인 파티원의 방을 보호하면서도
강제 종료 유저의 즉각적 복구 가능.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
로딩 화면에서 강제 종료하면 BossRoom이 waiting 상태로 남아
재입장이 영구 차단되는 문제 수정.
- waiting 상태 2분 초과 BossRoom 자동 정리 (15초 주기)
- RequestEntry 시 해당 유저의 stale waiting room 선제 정리
- 연결된 RoomSlot도 idle로 리셋
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- reward_worker에 txCheck 기반 이중 지급 방지 추가 (LastTxID 저장 후 재시도 전 확인)
- RewardFailure 모델에 LastTxID 필드 추가
- grantWithRetry가 txID를 반환하도록 변경
- 10회 재시도 초과 시 CRITICAL 로그에 상세 정보 포함
- 경험치 실패도 hasRewardFailure에 반영하여 reward_failed 상태 전이
- 에러 응답에 requestId 필드 포함 (관측성 개선)
- /api/auth/refresh를 authLimiter에서 분리 (NAT 환경 한도 초과 방지)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
actions/checkout, actions/setup-go, appleboy/ssh-action을
직접 실행 방식으로 대체. Gitea runner github.com clone 차단 문제 해결.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CompleteRaid/FailRaid에서 슬롯 리셋 전 BossRoom hard-delete 추가.
기존에는 BossRoom.SessionName uniqueIndex 충돌로 한 번 사용된 슬롯의
재사용이 불가능했음 (10개 중 점점 사용 가능 슬롯 감소).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
resolveUsername()에서 user_wallets 레코드가 없는 유저(레거시/마이그레이션 누락)에 대해
CreateWallet을 자동 호출하여 지갑을 즉시 생성. unique constraint 충돌 시 재조회로
동시성 안전 처리.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CHAIN_NODE_URLS 환경변수(쉼표 구분)로 복수 노드 지정 가능.
Client.Call()이 네트워크/HTTP 오류 시 다음 노드로 자동 전환.
RPC 레벨 오류(트랜잭션 실패 등)는 즉시 반환 (페일오버 미적용).
기존 CHAIN_NODE_URL 단일 설정은 하위 호환 유지.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- test job: go vet + go build + go test (coverage.out 아티팩트 업로드)
- docker job: main 머지 시 GHCR 이미지 빌드/푸시 (tolchain 의존성 처리)
- deploy job: SSH로 docker compose pull api && up
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fiber 앱 설정, 미들웨어, rate limiter를 server 패키지로 추출.
main.go는 DB 연결, DI, 서버 시작, graceful shutdown만 담당.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- middleware(Auth, Idempotency)를 클로저 팩토리 패턴으로 DI 전환
- database.DB/RDB 전역 변수 제거, ConnectMySQL/Redis 값 반환으로 변경
- download API X-API-Version 헤더 + 하위 호환성 규칙 문서화
- SaveGameData PlayTimeDelta 원자적 UPDATE (race condition 해소)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 보상 지급 실패 시 즉시 재시도(3회 backoff) + DB 기록 + 백그라운드 워커 재시도
- WaitForTx 폴링으로 블록체인 TX 확정 대기, SendTxAndWait 편의 메서드
- chain 트랜잭션 코드 중복 제거 (userTx/operatorTx 헬퍼, 50% 감소)
- AppError 기반 에러 응답 포맷 통일 (8개 코드, 전 핸들러 마이그레이션)
- TX 에러 분류 + 한국어 사용자 메시지 매핑 (11가지 패턴)
- player 서비스 테스트 20개 + chain WaitForTx 테스트 10개 추가
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- BossRoom 삭제 시 Unscoped() hard delete로 변경하여 unique index 충돌 방지
- GetProfile에서 프로필 없으면 기본값으로 자동 생성
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
클라이언트가 MMO 서버 경유로 보스 레이드 입장하도록 변경하면서
불필요해진 public /api/bossraid/ 라우트와 핸들러 제거.
입장은 MMO 서버 → internal API 경로만 사용.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
데디서버가 reset-room 호출 시 슬롯만 idle로 변경하고 BossRoom 레코드는
남아있어서 다음 입장 시 unique 제약 위반(Duplicate entry) 발생.
ResetRoom에서 해당 sessionName의 BossRoom 레코드도 함께 삭제.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fiber는 라우트를 등록 순서대로 매칭하므로, /api/internal이 /api 그룹
뒤에 있으면 apiLimiter가 먼저 적용됨. 순서를 변경하여 Rate Limit 우회.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
데디케이트 서버 10개 인스턴스의 하트비트가 apiLimiter(IP당 60req/min)에
걸려 429 에러 발생. Internal API를 별도 그룹으로 분리하여 Rate Limit 제외.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- RequestEntry() 시 CheckStaleSlots() 호출하여 좀비 슬롯 자동 정리
- 블록체인 보상 실패 시 BossRoom 상태를 reward_failed로 업데이트
- UpdateRoomStatus() 레포지토리 메서드 추가
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- swaggo/swag 기반 전체 API 엔드포인트 Swagger 어노테이션 (59개)
- /swagger/ 경로에 Swagger UI 제공
- 보스레이드 데디서버 관리 (등록, 하트비트, 슬롯 리셋)
- 플레이어 레벨/경험치 시스템 및 스탯 성장
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- lint-and-build 단계에 go test ./... 추가
- deploy 단계 git clone에 set +x / --quiet / 2>/dev/null 적용
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 체인 nonce 경쟁 조건 수정 (operatorMu + per-user mutex)
- 등록/SSAFY 원자적 트랜잭션 (wallet+profile 롤백 보장)
- IdempotencyRequired 미들웨어 (SETNX 원자적 클레임)
- 런치 티켓 API (JWT URL 노출 방지)
- HttpOnly 쿠키 refresh token
- SSAFY OAuth state 파라미터 (CSRF 방지)
- Refresh 시 DB 조회로 최신 role 사용
- 공지사항/유저목록 페이지네이션
- BodyLimit 미들웨어 (1MB, upload 제외)
- 입력 검증 강화 (닉네임, 게임데이터, 공지 길이)
- 에러 메시지 내부 정보 노출 방지
- io.LimitReader (RPC 10MB, SSAFY 1MB)
- RequestID 비출력 문자 제거
- 단위 테스트 (auth 11, announcement 9, bossraid 16)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- /health + /ready 엔드포인트 추가 (DB/Redis 상태 확인)
- RequestID 미들웨어 + 구조화 JSON 로깅
- 체인 트랜잭션 per-user rate limit (20 req/min)
- DB 커넥션 풀 설정 (MaxOpen 25, MaxIdle 10, MaxLifetime 5m)
- Graceful Shutdown 시 Redis/MySQL 연결 정리
- Dockerfile HEALTHCHECK 추가
- CI에 go vet + 빌드 검증 단계 추가 (deploy 전 실행)
- 보스 레이드 클라이언트 입장 API (JWT 인증)
- Player 프로필 모듈 추가
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 입력 검증 강화 (로그인/체인 핸들러 전체)
- boss raid 비관적 잠금으로 동시성 문제 해결
- SSAFY 사용자명 sanitize + 트랜잭션 처리
- constant-time API 키 비교, 보안 헤더, graceful shutdown
- 안전하지 않은 기본값 경고 추가
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
보안:
- RPC 응답 HTTP 상태코드 검증 (chain/client)
- SSAFY OAuth 에러 응답 내부 로깅으로 변경 (제3자 상세 노출 제거)
- resolveUsername에서 username 노출 제거
- LIKE 쿼리 특수문자 이스케이프 (bossraid/repository)
- 파일명 경로 순회 방지 + 길이 제한 (download/handler)
- ServerAuth 실패 로깅 추가
안정성:
- AutoMigrate 에러 시 서버 종료
- GetLatest() 에러 시 nil 반환 (초기화 안 된 포인터 방지)
- 멱등성 캐시 저장 시 새 context 사용
- SSAFY HTTP 클라이언트 타임아웃 10s
- io.ReadAll/rand.Read 에러 처리
- Login에서 DB 에러/Not Found 구분
검증 강화:
- 중복 플레이어 검증 (bossraid/service)
- username 길이 제한 50자 (auth/handler, bossraid/handler)
- 역할 변경 시 세션 무효화
- 지갑 복호화 실패 로깅
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MMO 서버/데디케이트 서버 연동을 위한 내부 API 엔드포인트 구현:
- POST /api/internal/bossraid/entry — 파티 입장 요청 (방 생성)
- POST /api/internal/bossraid/start — 세션 시작 보고
- POST /api/internal/bossraid/complete — 클리어 보고 + TOL Chain 보상 지급
- POST /api/internal/bossraid/fail — 실패 보고
- GET /api/internal/bossraid/room — 방 조회
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>