feat: 계정 Web Push 전달 기반과 사건 판정을 추가한다

게임 상태 변경과 같은 트랜잭션에 내구성 outbox를 기록하고 Gateway가 계정 설정과 기기 구독으로 fan-out하도록 한다. 전역 기본값은 비활성으로 유지하며 migration과 회귀 테스트를 함께 추가한다.
This commit is contained in:
2026-08-23 13:16:07 +00:00
parent f858806295
commit 7bc3213b03
34 changed files with 1964 additions and 9 deletions
+1
View File
@@ -29,3 +29,4 @@ export * from './legacyArchive/ArchivedGeneralSnapshot.js';
export * from './gateway/profileStatus.js';
export * from './game/accessPenalty.js';
export * from './http/trpcTransport.js';
export * from './webPush/types.js';
+46
View File
@@ -0,0 +1,46 @@
export const WEB_PUSH_EVENT_TYPES = [
'TROOP_ANNIHILATED',
'PRIVATE_MESSAGE_RECEIVED',
'AUTONOMOUS_ACTION_ENDED',
'RESERVED_TURNS_ENDED',
'PROFILE_PREOPENED',
'PROFILE_OPEN_SCHEDULED',
'PROFILE_OPENED',
'NATION_DESTROYED',
'TARGET_DATE_REACHED',
] as const;
export type WebPushEventType = (typeof WEB_PUSH_EVENT_TYPES)[number];
export const WEB_PUSH_TARGETED_EVENT_TYPES = [
'TROOP_ANNIHILATED',
'PRIVATE_MESSAGE_RECEIVED',
'AUTONOMOUS_ACTION_ENDED',
'RESERVED_TURNS_ENDED',
'NATION_DESTROYED',
] as const satisfies readonly WebPushEventType[];
export type WebPushTargetedEventType = (typeof WEB_PUSH_TARGETED_EVENT_TYPES)[number];
export interface WebPushEventEnvelopeV1 {
version: 1;
eventId: string;
eventType: WebPushEventType;
profileName: string;
userIds: string[];
year?: number;
month?: number;
occurredAt: string;
}
export interface WebPushClientSubscription {
endpoint: string;
expirationTime: number | null;
keys: {
p256dh: string;
auth: string;
};
}
export const isWebPushEventType = (value: unknown): value is WebPushEventType =>
typeof value === 'string' && (WEB_PUSH_EVENT_TYPES as readonly string[]).includes(value);