偿还 lewan 工程债:模块拆分、默认角色降级与短链收口
将 kuaishou-cloud 大入口拆为 prepare/rebind/probe/refresh 等模块;默认角色仅作诊断;补充兑换状态单测;短链明确只读兼容历史链接。
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import {
|
||||
TASK_STATUS,
|
||||
canRedeemKuaishouCloudClaimStatus,
|
||||
canTaskTransition,
|
||||
normalizeTaskStatus,
|
||||
} from '../../domain/task-status.js'
|
||||
import {
|
||||
assertBoundUidMatchesExpected,
|
||||
assertClaimExpectedUidReady,
|
||||
isClaimUidMatched,
|
||||
} from './claim-identity.js'
|
||||
|
||||
/**
|
||||
* 一键兑换前置:waiting_binding + UID 匹配 → 可升到 role_confirmed → redeeming
|
||||
*/
|
||||
function canPromoteWaitingBindingToRedeem(options: {
|
||||
status: unknown
|
||||
expectedUid: string
|
||||
boundUid: string
|
||||
}) {
|
||||
const status = normalizeTaskStatus(options.status)
|
||||
if (!canRedeemKuaishouCloudClaimStatus(status)) {
|
||||
return { ok: false, reason: 'status_not_redeemable' as const }
|
||||
}
|
||||
if (!options.expectedUid) {
|
||||
return { ok: false, reason: 'uid_missing' as const }
|
||||
}
|
||||
if (!isClaimUidMatched(options.expectedUid, options.boundUid)) {
|
||||
return { ok: false, reason: 'uid_mismatch' as const }
|
||||
}
|
||||
if (status === TASK_STATUS.WAITING_BINDING) {
|
||||
if (!canTaskTransition(TASK_STATUS.WAITING_BINDING, TASK_STATUS.ROLE_CONFIRMED)) {
|
||||
return { ok: false, reason: 'cannot_promote' as const }
|
||||
}
|
||||
}
|
||||
if (!canTaskTransition(TASK_STATUS.ROLE_CONFIRMED, TASK_STATUS.REDEEMING)) {
|
||||
return { ok: false, reason: 'cannot_redeem' as const }
|
||||
}
|
||||
return { ok: true as const, reason: 'ok' as const }
|
||||
}
|
||||
|
||||
test('waiting_binding + uid 匹配可一键兑换', () => {
|
||||
const result = canPromoteWaitingBindingToRedeem({
|
||||
status: TASK_STATUS.WAITING_BINDING,
|
||||
expectedUid: '10001',
|
||||
boundUid: '10001',
|
||||
})
|
||||
assert.deepEqual(result, { ok: true, reason: 'ok' })
|
||||
})
|
||||
|
||||
test('waiting_binding + uid 不一致不可兑换', () => {
|
||||
const result = canPromoteWaitingBindingToRedeem({
|
||||
status: TASK_STATUS.WAITING_BINDING,
|
||||
expectedUid: '10001',
|
||||
boundUid: '99999',
|
||||
})
|
||||
assert.equal(result.ok, false)
|
||||
assert.equal(result.reason, 'uid_mismatch')
|
||||
})
|
||||
|
||||
test('link_generated 状态不可直接 redeem', () => {
|
||||
const result = canPromoteWaitingBindingToRedeem({
|
||||
status: TASK_STATUS.LINK_GENERATED,
|
||||
expectedUid: '10001',
|
||||
boundUid: '10001',
|
||||
})
|
||||
assert.equal(result.ok, false)
|
||||
assert.equal(result.reason, 'status_not_redeemable')
|
||||
})
|
||||
|
||||
test('assertBoundUidMatchesExpected 在不匹配时抛错', () => {
|
||||
assert.throws(
|
||||
() =>
|
||||
assertBoundUidMatchesExpected(
|
||||
{
|
||||
context_json: JSON.stringify({
|
||||
claimIdentity: { expectedUid: '10001' },
|
||||
}),
|
||||
},
|
||||
{
|
||||
binding: { roleId: '999', roleName: 'x', vnPhone: '1' },
|
||||
role: { rid: '999', name: 'x' },
|
||||
},
|
||||
),
|
||||
/不一致/,
|
||||
)
|
||||
})
|
||||
|
||||
test('assertClaimExpectedUidReady 要求 claimIdentity', () => {
|
||||
assert.throws(
|
||||
() => assertClaimExpectedUidReady({ context_json: '{}' }),
|
||||
/填写游戏 UID/,
|
||||
)
|
||||
})
|
||||
@@ -36,7 +36,8 @@ export async function syncKuaishouCloudRoleInfo(task: TaskRow) {
|
||||
source: 'claim_page_polling',
|
||||
actor: { source: 'system' },
|
||||
recordEvent: false,
|
||||
forceProbe: flow.role.isDefaultRole === true,
|
||||
// 轮询阶段始终允许探测绑链,默认角色仅作诊断
|
||||
forceProbe: true,
|
||||
})
|
||||
return result.task || task
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user