Skip to content

layer7-kr/2026codegate-layer7-booth

Repository files navigation

2026codegate-layer7-booth

CODEGATE 행사 부스에서 운영하는 체험형 웹 방탈출 게임입니다. 플레이어는 제한 시간 안에 보안 콘셉트의 스테이지를 클리어하고, 점수는 공개 스코어보드에 기록됩니다.

현재 상태

  • 운영 제한 시간: 5분
  • 현재 총 스테이지: 5개
  • 랭킹 기준: 클리어 스테이지 수, 점수, 마지막 클리어 시점의 남은 시간 순
  • 닉네임 정책: 중복 닉네임 사용 불가
  • 게임 종료 시 제출 순위가 2~7위면 굿즈 추첨이 자동으로 진행됩니다.
  • stage4는 OpenAI API를 사용하는 프롬프트 인젝션 스테이지입니다.
  • stage5는 게이트 제어 웹사이트의 관리자 로그인을 SQL injection으로 우회하는 스테이지입니다.

스테이지 구성

Stage 이름 핵심 동작
1 ACCESS LOCK 락픽 UI를 조작해 첫 격벽을 엽니다.
2 REMOTE TERMINAL 터미널/소스 화면을 보고 게이트를 엽니다.
3 CCTV COOKIE 개발자도구로 cctv_enabled 쿠키 값을 바꿔 CCTV 문을 엽니다. 60초 후 힌트 버튼이 표시됩니다.
4 AI GUARD AI 경비원과 대화해 프롬프트 인젝션으로 키패드 코드를 얻습니다. 대화는 10회 제한입니다.
5 SQL INJECTION 출구 게이트 앞 컴퓨터에서 게이트 제어 사이트를 열고 관리자 로그인을 SQLi로 우회합니다. 열린 게이트를 통과하면 탈출합니다.

점수 규칙

  • 스테이지당 점수 범위: 1,000점 ~ 2,000점
  • 스테이지 시작 후 1초마다 10점씩 감점됩니다.
  • 스테이지별 점수는 1,000점 아래로 내려가지 않습니다.
  • 총점은 클리어한 스테이지 점수의 합입니다.
  • 랭킹 정렬 순서:
    1. 클리어 스테이지 수가 많은 기록
    2. 총점이 높은 기록
    3. 마지막 클리어 시점의 남은 시간이 많은 기록
    4. 먼저 제출된 기록

닉네임 정책

  • 닉네임은 1~16자입니다.
  • 앞뒤 공백과 연속 공백은 정리됩니다.
  • 제어 문자는 사용할 수 없습니다.
  • 대소문자만 다른 닉네임도 같은 닉네임으로 취급합니다.
  • 이미 등록된 닉네임은 게임 시작 전에 차단됩니다.
  • 동시에 제출되는 경우를 대비해 서버 제출 시점에도 중복 닉네임을 409 duplicate_nickname으로 차단합니다.
  • 기존 점수 파일에 중복 닉네임이 있으면 서버 로드 시 최고 기록 하나만 남깁니다.

굿즈 추첨

  • 점수 제출 시점 순위가 2~7위인 플레이어만 추첨 대상입니다.
  • 종료 화면에서 순위·점수·남은 시간 정보를 유지한 채 굿즈 추첨 패널이 함께 표시됩니다.
  • 참가자가 뽑기 시작 버튼을 누르면 추첨 애니메이션과 당첨 상품이 표시됩니다.
  • 최초 재고는 간식 100개, 키링 50개, 클리커 50개입니다.
  • 재고가 있는 상품 중 하나를 같은 확률로 무작위 추첨하며 재고가 없는 상품은 추첨에서 제외됩니다.
  • 추첨 결과와 남은 재고는 점수 파일에 함께 저장되므로 서버를 재시작해도 유지됩니다.
  • 관리자 화면에서 남은 재고와 기록별 당첨 상품을 확인하고 재고만 초기화할 수 있습니다.
  • 점수 기록을 삭제해도 이미 지급된 상품 재고는 복구되지 않습니다.

실행

Docker 운영

docker compose up -d --build

접속 주소:

http://localhost:8080/

운영 화면:

http://localhost:8080/scoreboard
http://localhost:8080/admin

상태 확인:

curl http://localhost:8080/api/health

중지:

docker compose down

점수 기록까지 초기화해야 할 때만 볼륨을 함께 삭제합니다.

docker compose down -v

로컬 개발

npm install
npm run dev

개발 서버:

http://localhost:5173/

프로덕션 빌드:

npm run build

빌드 결과 미리보기:

npm run preview

환경 변수

Docker Compose는 프로젝트 루트의 .env를 읽습니다.

SCORE_ADMIN_TOKEN=change-this-admin-token
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4.1-mini
STAGE_FOUR_PASSWORD=7391
STAGE_FOUR_MAX_GUARD_REQUESTS=10
변수 기본값 설명
SCORE_ADMIN_TOKEN codegate-admin /admin 관리자 인증 토큰
OPENAI_API_KEY 없음 stage4 AI 경비원 호출에 필요
OPENAI_MODEL gpt-4.1-mini stage4에서 사용할 OpenAI 모델
STAGE_FOUR_PASSWORD 7391 stage4 키패드 정답
STAGE_FOUR_MAX_GUARD_REQUESTS 10 stage4 AI 대화 횟수 제한

OPENAI_API_KEY가 없으면 stage4의 일반 AI 대화는 사용할 수 없습니다. 다만 공식 기록 맥락, 수정 없는 원문 요청, 무결성 보존 이유를 모두 갖춘 요청은 서버에서 처리됩니다.

API

공개 API

GET  /api/health
GET  /api/scores?limit=10
GET  /api/scores/nickname?nickname=PLAYER
POST /api/scores
POST /api/stage4/guard
POST /api/stage4/verify
POST /api/stage5/login

점수 제출 예시:

{
  "nickname": "PLAYER",
  "clearedStages": 4,
  "remainingTimeMs": 42123,
  "score": 6730
}

중복 닉네임이면 POST /api/scores409를 반환합니다.

관리자 API

관리자 API는 Authorization: Bearer <SCORE_ADMIN_TOKEN> 헤더가 필요합니다.

GET    /api/admin/scores?limit=500
DELETE /api/admin/scores
DELETE /api/admin/scores/:id
POST   /api/admin/prizes/reset

디버그 모드

시작 화면 닉네임 입력란에 debug를 입력하면 스테이지 선택 화면으로 들어갑니다. 현재 선택 가능한 디버그 항목은 1~6입니다. 6을 선택하면 실제 점수 제출과 재고 차감 없이 2위 종료 결과와 굿즈 추첨 화면을 바로 확인할 수 있습니다.

디버그 런은 스코어보드에 기록되지 않습니다.

파일 구조

src/
├─ config/
│  └─ gameConfig.ts
├─ constants/
│  ├─ stageLayout.ts
│  └─ world.ts
├─ objects/
│  └─ createPlayerTexture.ts
├─ pages/
│  ├─ adminPage.ts
│  └─ scoreboardPage.ts
├─ scenes/
│  └─ DungeonScene.ts
├─ services/
│  ├─ scoreboard.ts
│  ├─ scoring.ts
│  └─ stageFour.ts
├─ ui/
│  ├─ createAiGuardDialog.ts
│  ├─ createBofTerminalScreen.ts
│  ├─ createGameFlowScreen.ts
│  ├─ createGameHud.ts
│  ├─ createLockpickScreen.ts
│  └─ createStageFourKeypad.ts
├─ world/
│  ├─ createAiGuardStage.ts
│  ├─ createBofStage.ts
│  ├─ createCctvStage.ts
│  ├─ createDungeonBackground.ts
│  ├─ createDungeonPlatforms.ts
│  └─ createStageTransport.ts
├─ main.ts
└─ style.css

server/
└─ scoreServer.mjs

운영 메모

  • 점수와 굿즈 재고 데이터는 Docker 볼륨 score-data/data/scores.json에 저장됩니다.
  • 웹 컨테이너는 Nginx로 정적 파일을 제공하고 /api/* 요청을 score API 컨테이너로 프록시합니다.
  • stage4의 AI 응답 비용은 실제 대화 요청 수에 비례합니다. 서버를 켜둔 것만으로는 OpenAI 비용이 발생하지 않습니다.
  • 관리자 토큰과 OpenAI API 키는 저장소에 커밋하지 않습니다.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages