fix: 특수 유저 커맨드의 Ref 호환 경계를 보강한다
수뇌 국가 설정과 NPC 정책을 actor-bound ENGINE mutation으로 옮기고, 추방·등용·점령·멸망·아이템 폐기의 특수 분기를 Ref와 맞춘다. 요청 ID를 사용자·프로필별로 격리하고 토너먼트 손상 projection을 fail-closed하며 실제 DB 및 Ref 차등 회귀를 보강한다.
This commit is contained in:
@@ -97,6 +97,7 @@ const buildContext = (options: {
|
||||
metaDevelCost?: number;
|
||||
auctionTargets?: string[];
|
||||
clockTick?: number;
|
||||
requestId?: string;
|
||||
}) => {
|
||||
const auth = options.auth === undefined ? buildAuth() : options.auth;
|
||||
const general = options.general === undefined ? buildGeneral() : options.general;
|
||||
@@ -202,6 +203,7 @@ const buildContext = (options: {
|
||||
battleSim: {} as GameApiContext['battleSim'],
|
||||
profile: { id: 'che', scenario: 'default', name: 'che:default' },
|
||||
auth,
|
||||
...(options.requestId ? { requestId: options.requestId } : {}),
|
||||
uploadDir: 'uploads',
|
||||
uploadPath: '/uploads',
|
||||
uploadPublicUrl: null,
|
||||
@@ -247,13 +249,15 @@ describe('vote router actor and permission boundaries', () => {
|
||||
|
||||
it('uses only the general owned by the authenticated user for voting and reward dispatch', async () => {
|
||||
const owned = buildGeneral({ id: 7, userId: 'user-1', name: '유비' });
|
||||
const fixture = buildContext({ general: owned, clockTick: 100 });
|
||||
const fixture = buildContext({ general: owned, clockTick: 100, requestId: 'http-vote-submit' });
|
||||
|
||||
await expect(
|
||||
appRouter.createCaller(fixture.context).vote.submitVote({ voteId: 1, selection: [0] })
|
||||
).resolves.toEqual({ ok: true, wonLottery: false });
|
||||
expect(fixture.requestCommand).toHaveBeenCalledWith({
|
||||
type: 'voteReward',
|
||||
requestId: 'http-vote-submit:vote.submitVote:engine:0:voteReward',
|
||||
userId: 'user-1',
|
||||
voteId: 1,
|
||||
generalId: 7,
|
||||
selection: [0],
|
||||
|
||||
Reference in New Issue
Block a user