183 lines
18 KiB
Markdown
183 lines
18 KiB
Markdown
# 플레이 감사 사용과 DB 적용
|
|
|
|
플레이 감사는 각 프로필의 `/play-audit`에서 읽는다. Gateway 관리자 조치 원장과
|
|
다른 기능이다. 현재 전달은 [전체 설계](design/play-audit.md)의 부분 구현이며
|
|
구현·검증 source는 [inventory](design/play-audit-implementation.md)에 기록한다.
|
|
이번 전달 대상은 sam.hided.net의 전체 프로필이다. 코드와 migration을 main에 push하고,
|
|
운영자는 각 프로필에 직접 DB 보존 업데이트를 적용한다. 이 문서의 검증 결과는 실제
|
|
운영 DB에 이미 적용되었다는 뜻이 아니다.
|
|
|
|
## 지금 사용할 수 있는 기능
|
|
|
|
| 화면 | 사용할 수 있는 정보 | 읽을 때 주의할 점 |
|
|
| -------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
| 국가 | 월말 금·쌀·기술력, 세율·실제 정산, 유저/NPC/부대장 NPC별 자원·숙련 집계, 월/6개월 그래프 | 보유량은 마지막 월말, 수입/지급액은 기간 합. 부분 기간/미수집은 0과 다름 |
|
|
| 장수 | 이름 부분 검색·장수 번호 정렬, 모든 국가·재야의 현재/월말 장수, 자원·능력·숙련·병력·훈련·사기·장비·특기·위치, 독립 로그 상세 | 현재 예약은 현재 조회에서만 제공. 과거 월말은 그달 모든 명령의 이력이 아님 |
|
|
| 도시 | 현재/월말 소유·내정 상태와 국가별 주둔 장수 상세 연결 | 월말 주둔은 그달 모든 방문자가 아님. 지도 기반 탐색은 미완성 |
|
|
| 외교 | 국가쌍·기간별 문서 제안/승인/철회/파기, 즉시 합의와 월간·명령 관계 전이, 생성/소멸 관계 | 문서 내용과 실제 관계는 별개. 최초 관측 이전 사건은 복원하지 않음 |
|
|
| NPC 결정 | 장수별 개인·수뇌 판단, 절차 시도/차단, 관측한 RNG 결과와 선택·실제 실행·대체 시도 | 새 실행부터 수집하며 후보 내부 조건 전체는 미완성 |
|
|
| 정책 | NPC 국가 값·국가/장수 우선순위·국방 설정의 기준 버전과 변경 전후, 당시 주체 | 수뇌용 공개 화면은 아직 없음. NPC 결정에서 저장된 당시 버전을 직접 조회 가능 |
|
|
|
|
목록/그래프와 선택 상세를 분리해 읽는다. 표는 기본50건이며 더 보기를 명시적으로
|
|
누른다. 현재 상태는 수동으로 조회하며 백그라운드 polling은 하지 않는다. 필터·월·선택
|
|
대상은 URL에 남으므로 같은 권한으로 직접 열기/새로고침할 수 있다.
|
|
장수 이름은 선택 시점의 이름으로 부분 검색하며 영문 대소문자를 구분한다. 검색어는
|
|
64자까지이고 `%`·`_`도 문자 그대로 찾는다. 장수 번호 정렬은 오름차순/내림차순을 제공한다.
|
|
|
|
정책 버전과 외교 사건 상세의 **요청 처리 조회**는 연결된 요청의 현재 상태와 처리 시도
|
|
횟수, 접수·처리 시각/tick, 결과·오류 기록 존재 여부를 보여준다. 조회 시각 기준 정보이며
|
|
시도별 전체 이력이나 실제 변경 횟수는 아니다. 요청이 없거나 참조 순번이 맞지 않으면
|
|
그 사유를 표시한다. 버튼을 누를 때만 한 건을 조회하고 원문 요청/오류 내용은 제공하지 않는다.
|
|
|
|
## 화면 탐색
|
|
|
|
상위 메뉴에서 국가·장수·도시·외교·정책을 선택하고, 아래 메뉴에서 세부 조회를 선택한다.
|
|
국가는 추이/수집 시작/최종 표본, 장수는 전체/유저/NPC/부대장 NPC,
|
|
도시는 현재/월말/수집 시작/최종 표본, 정책은 NPC 정책/국가·장수 우선순위/국방 설정으로 나뉜다.
|
|
외교는 문서·관계 이력을 제공한다. 메뉴 선택은 즉시 이동하며 국가·기간 등 조회 조건은
|
|
조회 버튼으로 적용한다. 기존 query URL과 직접 접근·새로고침·뒤로가기를 지원한다.
|
|
화면을 전환하면 이전 상세 선택은 해제하고 선택한 화면에 필요한 자료만 읽는다.
|
|
|
|
## 진입과 권한
|
|
|
|
1. Gateway의 사용자 관리에서 대상 관리자에게 정확한 프로필 scope를 부여한다.
|
|
예: `admin.playAudit.read:che:default`, `admin.playAudit.read:hwe:default`.
|
|
일반 `admin` 역할이나 게임 수뇌 직책만으로 이 권한을 대신하지 않는다.
|
|
2. Gateway 관리자 서버 목록에서 해당 프로필의 **플레이 감사** 진입을 사용한다.
|
|
기존 게임 session 발급을 재사용하며 장수가 없어도 접근할 수 있다.
|
|
3. 같은 origin의 `/che/play-audit`, `/hwe/play-audit`로 이동한다. 직접 URL은 해당
|
|
프로필의 유효한 session이 필요하다. token을 URL에 넣지 않는다.
|
|
4. 외교/정책은 대상 국가·기간을 적용하고 사건을 눌러 상세를 읽는다. 멸망국은
|
|
해당 월의 국가 목록에서 선택한다. 상세 실패는 목록을 유지한 채 다시 시도한다.
|
|
|
|
권한 취소, 다른 프로필 token, 게임 입장 제재는 backend에서 다시 검사한다.
|
|
공통 계정 조사용 `admin.playAudit.accounts` scope는 준비되어 있으나 계정 조사 기능은
|
|
아직 제공하지 않는다. 이 scope만으로 프로필 조회가 허용되지 않는다.
|
|
|
|
## DB migration과 적용 순서
|
|
|
|
정식 game migration에 감사 테이블과 인덱스가 포함되어 있다. `prisma db push`나
|
|
수동 CREATE TABLE로 대신 적용하지 않는다. 현재 game chain은58개이며 다음 감사
|
|
migration들을 포함한다. 기존 기록을 삭제하거나 지난달 상세를 역산하지 않는다.
|
|
|
|
| migration | 준비되는 저장소/제약 |
|
|
| ----------------------------------------------------- | --------------------------------------------------------------------- |
|
|
| `20260916010000_add_play_audit_month` | 월 표본과 국가·도시·장수 projection 4개 테이블 |
|
|
| `20260916020000_add_log_entry_server_id` | 새 장수 로그의 불변 기수 identity |
|
|
| `20260916030000_add_play_audit_policy` | 국가별 불변 정책 revision |
|
|
| `20260916031000_add_play_audit_policy_schema_version` | 정책 payload 버전 |
|
|
| `20260916040000_add_play_audit_initial` | 기수당 INITIAL 표본 1개 제약 |
|
|
| `20260916050000_add_play_audit_diplomacy` | 방향·국가쌍·실행 순서 기반 외교 사건과 불변 원문 보호 |
|
|
| `20260916060000_widen_play_audit_ticks` | 월 표본/정책 tick을 BIGINT로 확장하여 약60개월 이후 INTEGER 초과 방지 |
|
|
| `20260916070000_add_play_audit_decision` | NPC/자동턴 결정 요약과 순서별 상세 chunk, bounded 정리용 FK/index |
|
|
| `20260916080000_index_play_audit_decision_month` | 기존 장수 인덱스를 월 조건 포함 인덱스로 교체하여 기수 전체 조회 방지 |
|
|
|
|
운영은 [릴리스 절차](release-operations.md)의 **DB 보존 버전 업데이트**로 해당 고정
|
|
commit을 적용한다. 이 기능을 켜기 위해 시나리오를 초기화할 필요는 없다. 수동 환경의
|
|
동등한 migration 명령은 infra의 `pnpm --filter @sammo-ts/infra prisma:migrate:deploy:game`이며,
|
|
올바른 profile DB/schema를 환경 또는 기존 secret 경로로 전달해야 한다. credential을
|
|
CLI/보고서에 출력하지 않는다. Gateway schema에는 이번 구현 때문에 새 테이블을 요구하지 않는다.
|
|
`release-manifest.json`의 gameSchemaHead도 위 마지막 migration을 가리킨다. 여러 프로필은
|
|
Gateway의 DB 보존 일괄 업데이트로 같은 고정 commit을 순차 적용할 수 있다. 각 프로필은
|
|
자기 schema에 migration을 적용해야 하며 한 프로필의 성공을 전체 적용 성공으로 보지 않는다.
|
|
Gateway의 새 진입/권한 catalog도 사용하려면 같은 commit의 Gateway 구성요소를 업데이트한다.
|
|
|
|
적용 전 기존 backup/운영 보호 절차를 따르고, migration 후 API/engine/frontend를 같은
|
|
버전으로 전환한다. 엔진은 clock 복구 후 INITIAL·정책·관계·보유 문서의 기준을 수집한다.
|
|
문서 원문은 200건씩 읽어 hash만 사건에 남긴다. 감사 전용 오류는 savepoint만 되돌리고
|
|
게임 준비를 계속한다. 누락된 감사 묶음은 버리며 게임 상태와 누락 표시를 저장한다.
|
|
이전 구간의 자동 재구성이나 완전한 이력 연결을 보장하지 않는다. 기존 migration을 되돌리거나 수정하지 않는다. tick 확장 migration은 기존 감사 행의
|
|
값과 hash를 보존하지만 열 형식 변경의 테이블 잠금/재작성 비용이 있다. 첫 감사 도입에서는
|
|
앞 migration이 만든 빈 테이블에 적용되며, 시험판 감사 기록이 이미 많다면 기존 업데이트
|
|
유지보수 구간에서 적용 시간을 확인한다. API의 tick은 정밀도 손실을 막기 위해 문자열로 반환한다. 월별 결정 인덱스 교체도 기존 결정 기록이 많으면 인덱스 생성 시간과 잠금을 업데이트 구간에 고려한다.
|
|
|
|
확인은 프로필 감사 진입 → 현재 장수/도시 → 초기 표본 → 정책/외교 기준 → 다음 정상
|
|
월 경계 후 월말 표본 순서로 한다. 조기 수집 구간의 정산 coverage가 부분일 수 있으므로
|
|
화면의 0/null/미수집·부분 표시에 따라 해석한다. 감사 migration을 적용했다고 과거 NPC
|
|
결정이나 자원 이동이 자동으로 채워지는 것은 아니다.
|
|
|
|
## NPC 결정 시점과 실제 시나리오 검증
|
|
|
|
NPC 결정은 해당 장수의 개인·수뇌 AI 실행을 관측하고 게임 상태 flush와 함께 저장한다.
|
|
월말 표본을 기다리지 않는다. 월 경계와 장수별 턴 시각은 다르므로 새 월에 해당 장수의
|
|
턴이 아직 오지 않았다면 이전 월 기록이 최신이다. 현재 장수에서 **NPC 결정 기록 조회**를
|
|
열면 가장 최근 기록 월을 표시한다. 명시적으로 선택한 과거 월과 **이전 월/다음 월**은
|
|
그 월만 조회하고, **최근 결정 조회**는 다시 최신 기록 월을 찾는다. 빈 목록은 선택 월에
|
|
행이 없다는 뜻이며, 수집 장애 여부는 감사 화면의 이력 누락 표시와 함께 확인한다.
|
|
일반 장수의 개인 판단과 수뇌 직책 NPC의 수뇌 판단을 구분하며 AI를 실행하지 않은
|
|
수동 명령에는 AI 결정 기록을 만들지 않는다.
|
|
|
|
재현 도구는 `tools/integration-tests/scripts/play-audit-npc-lifecycle.ts`다. 격리된 개발
|
|
DB/Redis와 새 `_npc_audit_lifecycle` suffix schema를 준비하고 정식 migration을 적용한다.
|
|
`DATABASE_URL`은 환경에서 전달하며 command line이나 artifact에 출력하지 않는다.
|
|
기존 world가 있으면 기본 실행을 거부한다. 완료한 전용 fixture는 같은 명령에 `--verify`를
|
|
붙여 게임을 변경하지 않고 저장 결과만 다시 검증할 수 있다. 초기화나 기존 시즌 삭제
|
|
도구로 사용하지 않는다.
|
|
|
|
```sh
|
|
pnpm --filter @sammo-ts/infra prisma:migrate:deploy:game
|
|
pnpm exec tsx tools/integration-tests/scripts/play-audit-npc-lifecycle.ts
|
|
pnpm exec playwright test --config tools/frontend-legacy-parity/play-audit-npc.playwright.config.mjs
|
|
```
|
|
|
|
시나리오 2601을 180년부터 실제 production handler·fenced DB flush로 실행하며,
|
|
183년 이후 공백지 점령 완료와 n/m NPC 개인·수뇌 결정/chunk를 검증한다. 시간만 manual
|
|
clock으로 가속하고 결정·도시 소유를 직접 생성하지 않는다. `maxGenerals:20`의 작은
|
|
flush batch로 감사의 시간 제한을 보존한다. 브라우저는 같은 DB의 실제 API를 사용하며
|
|
결정 응답을 mock하지 않는다. 기본 port는 frontend15301/API15302이며 각각
|
|
`NPC_AUDIT_FRONTEND_PORT`, `NPC_AUDIT_API_PORT`로 격리한다. API 실행에는 개발용
|
|
`REDIS_URL`, `GAME_TOKEN_SECRET`, `GAME_IMAGE_UPLOAD_SECRET_FILE`도 필요하다.
|
|
결과 JSON은 `test-results/npc-audit-lifecycle/`, 화면·geometry는
|
|
`test-results/npc-audit-browser/`에 보존한다. 세션 token은 artifact에 남기지 않는다.
|
|
|
|
## 보존과 미완성 범위
|
|
|
|
- 현재 기수 자료만 제공한다. RESET이 새 serverId를 활성화하면 이전 기수 조회를
|
|
즉시 차단하고 이전 감사 자료를200행 단위로 정리한다. 기존 연감/계정 원장은 별도다.
|
|
- 통일 시 FINAL 표본은 정규 월말과 구분한다. **CANCELLED가 runtime을 중단한 프로필은
|
|
현재 감사 API도 사용할 수 없다.** 취소 후 다음 초기화까지 읽는 수명주기는 후속 작업이다.
|
|
- NPC/유저 자동턴의 개인·수뇌 절차, 정책 차단, RNG utility 결과와 최종 실행 결과는
|
|
migration 이후 새 실행부터 저장한다. 후보 내부 조건 전체는 아직 없으며 `PROCEDURES`
|
|
coverage로 구분한다. 실행 단계 수집이 추가된 기록은 인자·조건·대기·문맥 검사와 대체 명령도 순서대로 표시하며 이전 기록과 구분한다. 장수 상세의 **NPC 결정 기록 조회**에서 선택 월의 목록과 순서별 상세를 읽는다. 과거 결정은 역산하지 않는다.
|
|
- 결정은 당시 확보된 정책 참조를 보존하며 **당시 정책 참조**에서 해당 불변 버전을 바로 조회한다. 새 결정의 시작 항목에서 **당시 합성 정책**을 펼치면 개인/수뇌 우선순위·허용 여부와 국가 정책 수치·부대 편성을 확인한다. 이전 기록은 미수집으로 표시한다. 실행 직전 자원 지급 상한·개별 후보 조건·별도 자동화 권한 판정은 이 정책 표와 구분한다. Gateway 관리 daemon은 프로필의 buildCommitSha를 새 실행에 기록한다. 수동 daemon은 실행 산출물의 전체 SHA를 TURN_BUILD_COMMIT_SHA로 전달할 수 있다. 미지정/잘못된 SHA의 실행과 기존 null 기록은 현재 버전으로 메우지 않는다.
|
|
- 계정/IP HMAC 조사, 상세 자원 이동, 예약 변경/실행 연결, 실패·rollback 조사와 알려진
|
|
버그 사례 조회는 미완성이다. 자동 탐지·자동 제재 기능도 제공하지 않는다.
|
|
- 일부 국가 생성/소멸 사건은 actor/request가 null이다. 원인을 현재 주체로 추정하지 않는다.
|
|
- 자원·능력별 정렬·지도 탐색·모든 전투 지표/연결과 전체 COST gate는 남아 있다.
|
|
- 격리 PostgreSQL/Redis 및 mock API를 쓰는 실제 Chromium 검증은 운영 HTTPS 검증과 다르다.
|
|
|
|
후속 NPC/행위/계정 저장소의 필드·순서·보존·인덱스 요구는 설계의 R5/조사 A~F와 비용
|
|
표를 유지한다. 미구현 저장소를 현재 수집 중이라고 표시하지 않는다. 다음 작업은 해당
|
|
writer와 rollback·정리 경계를 함께 추가하는 정식 migration으로 이어가야 한다.
|
|
|
|
## 정책 이력 연결과 재시작
|
|
|
|
신규 NPC 국가와 이민족 국가의 `addNation`은 정책 기준 원장과 국가 meta의
|
|
`_playAuditPolicy` head를 함께 만든다. 후속 군주·장수 수 갱신은 world에 저장된
|
|
최신 meta를 사용해야 한다. 생성 전에 만든 객체를 다시 저장하면 head가 유실되어
|
|
다음 배포 재시작에서 기준 원장의 같은 ID를 다른 시점으로 기록하려다 충돌한다.
|
|
|
|
데몬 startup은 현재 기수의 누락된 head만 정책 원장의 마지막 revision으로 복원한다.
|
|
기존 원장과 hash는 수정하지 않는다. 현재 정책이 원장과 다르면 `OBSERVED_GAP`을
|
|
다음 revision으로 남기고, 복원 meta와 새 기록은 기존 lease/fencing transaction에서
|
|
함께 저장한다. 이력이 없는 국가는 일반 BASELINE을 만들며 다른 기수 이력은 사용하지 않는다.
|
|
실제 replay payload 충돌 검사는 계속 적용한다.
|
|
|
|
`/healthz`는 clock reconciliation뿐 아니라 해당 profile의 만료되지 않은
|
|
`clock_ready=true` 데몬 lease까지 확인한다. 게임 clock·lease 초기화 실패는 503이지만
|
|
감사만 실패한 경우 게임 준비 완료를 허용한다. 감사 누락은 `playAuditGap`과 감사 화면,
|
|
`[play-audit]` 운영 로그로 구분한다. PREOPEN과 PAUSED도
|
|
데몬 초기화가 완료되면 준비 완료이며, 턴 진행 여부와 준비 상태는 별개다.
|
|
|
|
## 감사 장애 시 게임 지속 (2026-09-26)
|
|
|
|
현재 정책은 [실패·내구성 계약](./design/play-audit.md#_6-1-공통-식별자와-내구성)을 따른다.
|
|
정책·외교·NPC 결정·월말/최종 표본과 startup 수집이 대상이다. 같은 flush의 감사 묶음은
|
|
하나라도 실패하면 모두 취소하지만, 연감·통일 처리·게임 상태·입력 처리 원장은 그대로
|
|
검증하고 저장한다. API 외교 문서/관계도 감사만 취소하고 문서·알림을 정상 처리한다.
|
|
|
|
누락 표시는 기수별 sticky 상태이며 이후 성공해도 지우지 않는다. 감사 writer가 복구되면
|
|
다음 수집부터 다시 기록한다. 배포로 로직이 바뀐 과거 구간을 수정하거나 hash를 맞추지 않는다.
|
|
missing table/SQL 오류/충돌/수집 형식 오류를 게임 오류로 승격하지 않지만, DB 연결 단절이나
|
|
필수 core 행 저장 실패처럼 game commit 자체를 보장할 수 없는 상황은 기존 보호 동작을 유지한다.
|