# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands ```bash go run . # 로컬 실행 go build -o server . # 빌드 docker build -t a301-server . # Docker 빌드 ``` ## Tech Stack - **Go** + **Fiber v2** (StreamRequestBody: true — 대용량 업로드용, Body Limit 4GB) - **GORM** + **MySQL** (AutoMigrate 사용) - **Redis** — JWT 세션 저장(`session:{userID}`, `refresh:{userID}`) + 멱등성 캐시 - **JWT** — `golang-jwt/jwt v5`, Access + Refresh 토큰 로테이션 ## Project Purpose "One of the plans" 게임 플랫폼 백엔드. 인증 / 공지사항 / 게임 파일 업로드·서빙 / 블록체인(TOL Chain) 연동 담당. ## Project Structure ``` internal/ ├── auth/ # User 모델, JWT 발급·검증, 세션 관리(Redis) ├── announcement/ # Announcement CRUD ├── download/ # Info 조회, 파일 업로드(스트리밍), 파일 서빙 └── chain/ # 블록체인 지갑·거래·마켓·인벤토리 (5파일: handler, service, repository, model, client) pkg/ ├── config/ # 환경변수 → Config 구조체 ├── database/ # ConnectMySQL(), ConnectRedis() └── middleware/ # Auth, AdminOnly, ServerAuth, Idempotency routes/routes.go # 모든 라우트 등록 ``` ## Key Patterns - **계층 구조**: `Handler → Service → Repository`. 각 도메인 폴더에 4~5파일. - **파일 업로드**: `Fiber StreamRequestBody: true` + `io.Copy`로 raw body를 직접 디스크에 스트리밍. 메모리에 파일 올리지 않음. - **SHA256 자동 추출**: 게임 zip 업로드 시 zip 내 `A301.exe`를 스트리밍으로 읽어 해시 계산. - **CORS**: `AllowMethods`에 `PATCH` 포함 필수 (유저 권한 변경 엔드포인트). `AllowOrigins`: `https://a301.tolelom.xyz`. - **초기 admin 계정**: 서버 시작 시 `EnsureAdmin()`으로 존재 확인 후 없으면 생성. - **DI 패턴**: `main.go`에서 생성자 함수로 Repo → Service → Handler 주입. - **콜백 연결**: `authSvc.SetWalletCreator()` — 회원가입 시 자동 지갑 생성. `chainSvc.SetUserResolver()` — username → userID 변환. ## Middleware - **Auth**: `Authorization: Bearer ` 검증 + Redis 세션 확인. `c.Locals("userID", "username", "role")` 설정. - **AdminOnly**: `role == "admin"` 확인, 아니면 403. - **ServerAuth**: `X-API-Key` 헤더 검증. 게임 서버 → API 서버 내부 통신용. - **Idempotency**: `Idempotency-Key` 헤더로 중복 요청 방지. Redis 캐시 TTL 10분. 블록체인 트랜잭션 이중 지출 방지용. ## JWT 토큰 로테이션 - **Access Token**: `JWT_SECRET`으로 서명, 기본 24시간 만료, Redis `session:{userID}`에 저장. - **Refresh Token**: `REFRESH_SECRET`으로 서명, 7일 만료, Redis `refresh:{userID}`에 저장. - **Refresh 시**: 이전 토큰 무효화 + 새 Access/Refresh 쌍 발급 (로테이션). - **Logout**: Redis에서 session + refresh 키 모두 삭제. ## Rate Limiting - Auth 엔드포인트: IP당 10 req/min - 일반 API: IP당 60 req/min ## 블록체인 연동 (internal/chain/) TOL Chain 노드와 JSON-RPC 2.0 통신. - **UserWallet 모델**: ed25519 키페어 생성, 개인키는 AES-256-GCM 암호화 후 DB 저장. - **client.go**: Chain 노드 RPC 호출 (10초 타임아웃). - **service.go**: 지갑 생성/암호화, 트랜잭션 서명, 마켓/인벤토리 로직. - **내부 API**: 게임 서버가 username 기반으로 보상 지급 (`/api/internal/chain/*`). ## Routes **인증**: `POST /api/auth/{register,login,refresh,logout,verify}` (register/login/refresh는 rate limit) **유저 관리 (admin)**: `GET /api/users/`, `PATCH /api/users/:id/role`, `DELETE /api/users/:id` **공지사항**: `GET /api/announcements/`, `POST|PUT|DELETE /api/announcements/:id` (CUD는 admin) **다운로드**: `GET /api/download/{info,file,launcher}`, `POST /api/download/upload/{game,launcher}` (upload는 admin) **체인 조회 (JWT)**: `GET /api/chain/{wallet,balance,assets,asset/:id,inventory,market,market/:id}` **체인 트랜잭션 (JWT + Idempotency)**: `POST /api/chain/{transfer,asset/transfer,market/list,market/buy,market/cancel,inventory/equip,inventory/unequip}` **체인 관리자 (JWT + Admin + Idempotency)**: `POST /api/chain/admin/{mint,reward,template}` **내부 API (X-API-Key + Idempotency)**: `POST /api/internal/chain/{reward,mint}`, `GET /api/internal/chain/{balance,assets,inventory}` (username 쿼리 파라미터) ## Environment Variables ``` APP_PORT=8080 DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME REDIS_ADDR, REDIS_PASSWORD JWT_SECRET, REFRESH_SECRET, JWT_EXPIRY_HOURS(기본24) ADMIN_USERNAME, ADMIN_PASSWORD BASE_URL=https://a301.api.tolelom.xyz GAME_DIR=/data/game CHAIN_NODE_URL=http://localhost:8545 CHAIN_ID=tolchain-dev OPERATOR_KEY_HEX # 오퍼레이터 개인키 (블록체인 트랜잭션 서명용) WALLET_ENCRYPTION_KEY # 64자 hex = 32바이트 AES-256 키 (지갑 암호화) INTERNAL_API_KEY # 게임 서버 인증용 API 키 ``` ## File Storage 게임 파일은 `GAME_DIR`(`/data/game`)에 저장: - `/data/game/game.zip` — 게임 본체 - `/data/game/launcher.exe` — 런처 Docker 볼륨 `game_data:/data/game` 마운트로 컨테이너 재시작 후에도 유지.