CONTRACT HUB / CURRENT
게임 연결 계약을 한곳에.
게임은 자기 화면과 데이터를 소유하고, KOISCORE는 플레이어 셸·로그인·공용 젬을 담당합니다. 출시할 때 필요한 API와 브릿지 계약을 구현 순서대로 정리했습니다.CONTRACT MAP
어떤 문서를 봐야 하나요?
신규 게임은 네 계약을 모두 적용합니다. 기존 라이브 게임은 Portal Bridge v1을 유지한 채 Identity와 Runtime 계약부터 점진적으로 전환합니다.
Portal Bridge v1
iframe 준비, 초기화, 음소거, 게임 설명과 identity 갱신 메시지 계약입니다.
koiscore.portal.v1IDENTITYGame Identity v2
게임별 playerId와 Ed25519 단기 assertion으로 로그인 사용자를 식별합니다.
koiscore.game-identity.v2CANVASRuntime Policy v2
Pixi·WASM·WebGL 게임의 프레임, 캔버스, 호스트와 출시 단계 정책입니다.
koiscore.game-runtime.v2RELEASEIntegration v1
게임 등록, 광고 소유권, 공용 젬과 게임 전용 데이터 경계를 정의합니다.
koiscore.game-integration.v1IMPLEMENTATION ORDER
연동 순서
고정 gameId와 런타임 URL, 장르, 언어, 화면 비율을 draft로 등록합니다.
game:ready 이후 portal:init을 받고 origin·source·gameId를 검증합니다.
identity.playerId로 게임 데이터를 분리하고 assertion을 서버에서 검증합니다.
프레임 크기, 무스크롤, 결제 멱등성, 플레이타임 조건을 확인합니다.
PORTAL BRIDGE / V1
포털과 게임 iframe
전송 방식은 window.postMessage입니다. 게임은 리스너를 먼저 등록하고 game:ready를 보냅니다. 포털은 현재 locale, 음소거, 셸 설정과 게임별 identity를 portal:init으로 응답합니다.
| 방향 | TYPE | 역할 |
|---|---|---|
| 게임 → 포털 | game:ready | 메시지 수신 준비 완료 |
| 포털 → 게임 | portal:init | locale, shell, audio, identity 전체 동기화 |
| 포털 → 게임 | portal:audio | 실행 중 마스터 음소거 변경 |
| 게임 → 포털 | game:identity-refresh | 만료 전 새 identity assertion 요청 |
| 게임 → 포털 | game:how-to | 현지화된 게임 방법과 규칙 전달 |
| 게임 → 포털 | game:wallet | 교환 후 공용 젬 잔액 갱신 요청 |
window.addEventListener('message', (event) => {
if (event.source !== window.parent) return;
if (event.origin !== 'https://koiscore.com') return;
const message = event.data;
if (message?.protocol !== 'koiscore.portal.v1') return;
if (message?.gameId !== 'your-game-id') return;
if (message.type === 'portal:init') {
applyLocale(message.locale);
setMuted(message.audio?.muted === true);
setIdentity(message.identity);
}
});
window.parent.postMessage({
protocol: 'koiscore.portal.v1',
type: 'game:ready',
gameId: 'your-game-id'
}, 'https://koiscore.com');postMessage('*')로 사용자 identity를 보내지 마세요. 승인된 포털 origin, 부모 window, protocol과 gameId를 모두 확인해야 합니다.LOGIN IDENTITY / V2
로그인은 공용, 데이터는 게임별
KOISCORE가 로그인 세션과 계정 연결을 관리합니다. 게임은 전역 profileId가 아니라 게임마다 다른 identity.playerId를 세이브·점수·인벤토리의 사용자 키로 사용합니다.
{
"schemaVersion": "koiscore.game-identity.v2",
"gameId": "your-game-id",
"authenticated": true,
"playerId": "ply_...",
"displayName": "Koi Player",
"locale": "ko",
"provider": "google",
"assertion": {
"format": "jwt",
"token": "header.payload.signature",
"expiresAt": "2026-08-04T00:01:00.000Z"
}
}게임 서버 필수 검증
GET /api/platform/identity/jwks의 Ed25519 공개키로 JWT 서명을 검증합니다.iss=https://koiscore.com,aud=gameId,game_id=gameId를 확인합니다.- 검증된
sub만 데이터 키로 사용하고 body의 playerId는 신뢰하지 않습니다. - assertion은 최대 300초만 허용하고 만료되면
game:identity-refresh를 요청합니다.
RUNTIME / V2
게임 프레임과 캔버스 정책
| 항목 | 필수 정책 |
|---|---|
| Renderer | pixi-canvas, wasm-canvas, unity-webgl 중 등록 |
| Size | iframe 실제 너비·높이를 사용하고 ResizeObserver로 갱신 |
| Mobile | html, body, root 100%, 내부 문서 스크롤 금지 |
| Shell | 타이틀, 광고, 공용 젬 UI는 KOISCORE 호스트가 소유 |
| Launch | URL에 세션 token을 넣지 않고 승인된 호스트 진입만 허용 |
| Migration | sandbox → shadow → canary → v2-live, rollback 산출물 유지 |
INTEGRATION / V1
등록·광고·젬 경계
- 게임 화면, 세이브, 점수, 게임 전용 재화와 인벤토리는 개별 게임이 소유합니다.
- 로그인 세션, 게임별 identity 발급, 공용 젬 원장과 결제 영수증은 KOISCORE가 소유합니다.
- 웹 광고는 포털, Apps in Toss 광고는 미니앱 채널이 담당하며 게임에서 중복 요청하지 않습니다.
- 젬 구매는 서버 상품 카탈로그와 영수증을 사용하고 게임 지급 API는 멱등 처리합니다.
PUBLIC SOURCES
원본 계약 참조
자동화 도구와 CI는 공개 계약 카탈로그에서 현재 Schema URL을 조회할 수 있습니다. 사람이 읽는 브릿지 상세본은 아래 레퍼런스를 사용합니다.