diff --git a/background/auto-run-controller.js b/background/auto-run-controller.js index c5ff064..c534c75 100644 --- a/background/auto-run-controller.js +++ b/background/auto-run-controller.js @@ -74,6 +74,31 @@ }); const DONE_NODE_STATUSES = new Set(['completed', 'manual_completed', 'skipped']); + function buildFreshAttemptIdentityResetPatch() { + return { + currentPhoneActivation: null, + phoneNumber: '', + accountIdentifierType: null, + accountIdentifier: '', + signupPhoneNumber: '', + signupPhoneActivation: null, + signupPhoneCompletedActivation: null, + signupPhoneVerificationRequestedAt: null, + signupPhoneVerificationPurpose: '', + currentPhoneVerificationCode: '', + currentPhoneVerificationCountdownEndsAt: 0, + currentPhoneVerificationCountdownWindowIndex: 0, + currentPhoneVerificationCountdownWindowTotal: 0, + email: null, + registrationEmailState: { ...EMPTY_REGISTRATION_EMAIL_STATE }, + step8VerificationTargetEmail: '', + lastEmailTimestamp: null, + lastSignupCode: '', + lastLoginCode: '', + bindEmailSubmitted: false, + }; + } + function isPhoneSignupFlow(state = {}) { const resolvedSignupMethod = String(state?.resolvedSignupMethod || '').trim().toLowerCase(); if (resolvedSignupMethod === 'phone' || resolvedSignupMethod === 'email') { @@ -703,6 +728,7 @@ attemptRun, sessionId, }), + ...buildFreshAttemptIdentityResetPatch(), currentNodeId: '', nodeStatuses: buildFreshAttemptNodeStatuses(prevState), autoRunRoundSummaries: serializeAutoRunRoundSummaries(totalRuns, roundSummaries), diff --git a/tests/auto-run-fresh-attempt-reset.test.js b/tests/auto-run-fresh-attempt-reset.test.js index ad5bc95..6c999d5 100644 --- a/tests/auto-run-fresh-attempt-reset.test.js +++ b/tests/auto-run-fresh-attempt-reset.test.js @@ -149,6 +149,23 @@ let currentState = { inbucketMailbox: '', cloudflareDomain: '', cloudflareDomains: [], + email: 'stale-round@example.com', + registrationEmailState: { + current: 'stale-round@example.com', + previous: 'older-round@example.com', + source: 'generated:duck', + updatedAt: 123456789, + }, + step8VerificationTargetEmail: 'bound-round@example.com', + lastEmailTimestamp: 987654321, + lastSignupCode: '111111', + lastLoginCode: '222222', + bindEmailSubmitted: true, + currentPhoneActivation: { + activationId: 'runtime-activation', + phoneNumber: '+661111111', + }, + phoneNumber: '+661111111', reusablePhoneActivation: { activationId: '123456', phoneNumber: '66959916439', @@ -280,6 +297,52 @@ async function runAutoSequenceFromStep() { throw new Error('fresh auto-run attempt reused stale runtime tab context'); } + if (runCalls === 2) { + if (state.email !== null) { + throw new Error('fresh round must not reuse prior registration email'); + } + if (JSON.stringify(state.registrationEmailState) !== JSON.stringify({ + current: '', + previous: '', + source: '', + updatedAt: 0, + })) { + throw new Error('fresh round must clear registration email history'); + } + if (state.step8VerificationTargetEmail !== '') { + throw new Error('fresh round must clear bound-email target'); + } + if (state.lastEmailTimestamp !== null) { + throw new Error('fresh round must clear email timestamp'); + } + if (state.lastSignupCode !== '') { + throw new Error('fresh round must clear signup code cache'); + } + if (state.lastLoginCode !== '') { + throw new Error('fresh round must clear login code cache'); + } + if (state.bindEmailSubmitted !== false) { + throw new Error('fresh round must clear bind-email marker'); + } + if (state.currentPhoneActivation !== null) { + throw new Error('fresh round must clear runtime phone activation'); + } + if (state.phoneNumber !== '') { + throw new Error('fresh round must clear runtime phone number'); + } + } + + currentState = { + ...currentState, + email: 'fresh-round-' + runCalls + '@example.com', + registrationEmailState: { + current: 'fresh-round-' + runCalls + '@example.com', + previous: 'fresh-round-' + runCalls + '@example.com', + source: 'generated:duck', + updatedAt: 22334455 + runCalls, + }, + }; + currentState = { ...currentState, stepStatuses: {