refactor kiro flow to web signin authorization
This commit is contained in:
@@ -83,6 +83,13 @@ test('kiro desktop authorize runner uses a shared 3-minute page-load timeout bud
|
||||
assert.match(source, /finalizeDesktopAuthorizeCallback/);
|
||||
});
|
||||
|
||||
test('kiro desktop authorization is gated by completed Kiro Web sign-in', () => {
|
||||
const source = fs.readFileSync('background/kiro/desktop-authorize-runner.js', 'utf8');
|
||||
assert.match(source, /runtimeState\.register\?\.status/);
|
||||
assert.match(source, /runtimeState\.webAuth\?\.status/);
|
||||
assert.match(source, /Kiro Web 登录态尚未建立/);
|
||||
});
|
||||
|
||||
test('executeKiroCompleteDesktopAuthorize finishes from callback page without waiting for tracker replay', async () => {
|
||||
const api = loadDesktopAuthorizeRunnerApi();
|
||||
let currentState = createDesktopAuthorizeState();
|
||||
|
||||
@@ -10,52 +10,18 @@ function loadRegisterRunnerApi() {
|
||||
return globalScope.MultiPageBackgroundKiroRegisterRunner;
|
||||
}
|
||||
|
||||
test('kiro register runner module exposes a factory and device login bootstrap helper', () => {
|
||||
test('kiro register runner module exposes a factory and Kiro official sign-in entry', () => {
|
||||
const api = loadRegisterRunnerApi();
|
||||
assert.equal(typeof api?.createKiroRegisterRunner, 'function');
|
||||
assert.equal(typeof api?.startBuilderIdDeviceLogin, 'function');
|
||||
assert.equal(api?.KIRO_SIGNIN_URL, 'https://app.kiro.dev/signin');
|
||||
});
|
||||
|
||||
test('startBuilderIdDeviceLogin registers Builder ID client and returns login bootstrap payload', async () => {
|
||||
const api = loadRegisterRunnerApi();
|
||||
const requests = [];
|
||||
const result = await api.startBuilderIdDeviceLogin('us-east-1', async (url, options = {}) => {
|
||||
requests.push({ url, options });
|
||||
if (url.endsWith('/client/register')) {
|
||||
return {
|
||||
ok: true,
|
||||
text: async () => JSON.stringify({
|
||||
clientId: 'client-001',
|
||||
clientSecret: 'secret-001',
|
||||
}),
|
||||
};
|
||||
}
|
||||
if (url.endsWith('/device_authorization')) {
|
||||
return {
|
||||
ok: true,
|
||||
text: async () => JSON.stringify({
|
||||
deviceCode: 'device-code-001',
|
||||
userCode: 'ABCD-1234',
|
||||
verificationUri: 'https://view.awsapps.com/start',
|
||||
verificationUriComplete: 'https://view.awsapps.com/start?user_code=ABCD-1234',
|
||||
interval: 7,
|
||||
expiresIn: 600,
|
||||
}),
|
||||
};
|
||||
}
|
||||
throw new Error(`Unexpected request: ${url}`);
|
||||
});
|
||||
|
||||
assert.equal(requests.length, 2);
|
||||
assert.equal(requests[0].url, 'https://oidc.us-east-1.amazonaws.com/client/register');
|
||||
assert.equal(requests[1].url, 'https://oidc.us-east-1.amazonaws.com/device_authorization');
|
||||
assert.equal(result.clientId, 'client-001');
|
||||
assert.equal(result.clientSecret, 'secret-001');
|
||||
assert.equal(result.deviceCode, 'device-code-001');
|
||||
assert.equal(result.userCode, 'ABCD-1234');
|
||||
assert.equal(result.verificationUriComplete, 'https://view.awsapps.com/start?user_code=ABCD-1234');
|
||||
assert.equal(result.interval, 7);
|
||||
assert.equal(result.region, 'us-east-1');
|
||||
test('kiro register runner removed the old AWS device authorization bootstrap', () => {
|
||||
const source = fs.readFileSync('background/kiro/register-runner.js', 'utf8');
|
||||
assert.doesNotMatch(source, /startBuilderIdDeviceLogin/);
|
||||
assert.doesNotMatch(source, /device_authorization/);
|
||||
assert.doesNotMatch(source, /verificationUriComplete/);
|
||||
assert.match(source, /https:\/\/app\.kiro\.dev\/signin/);
|
||||
});
|
||||
|
||||
test('kiro register runner uses a shared 3-minute page-load timeout budget', () => {
|
||||
@@ -66,3 +32,10 @@ test('kiro register runner uses a shared 3-minute page-load timeout budget', ()
|
||||
assert.match(source, /timeoutBudget\.getRemainingMs\(1000\)/);
|
||||
assert.match(source, /onRetryableError: buildKiroRetryRecovery\(tabId, \{\s*\.\.\.options,\s*timeoutBudget,/);
|
||||
});
|
||||
|
||||
test('kiro register consent step treats Kiro Web signed-in page as completion', () => {
|
||||
const source = fs.readFileSync('background/kiro/register-runner.js', 'utf8');
|
||||
assert.match(source, /targetStates: \['authorization_page', 'kiro_web_signed_in'\]/);
|
||||
assert.match(source, /landingResult\?\.state !== 'kiro_web_signed_in'/);
|
||||
assert.doesNotMatch(source, /landingResult\?\.state !== 'success_page'/);
|
||||
});
|
||||
|
||||
@@ -32,10 +32,14 @@ test('kiro state module exposes canonical nested kiroRuntime view', () => {
|
||||
register: {
|
||||
email: 'aws-user@example.com',
|
||||
fullName: 'Ada Lovelace',
|
||||
userCode: 'ABCD-1234',
|
||||
loginUrl: 'https://device.example.com/complete',
|
||||
loginUrl: 'https://app.kiro.dev/signin',
|
||||
status: 'waiting_name',
|
||||
},
|
||||
webAuth: {
|
||||
status: 'signin_started',
|
||||
hasAccessToken: false,
|
||||
hasSessionToken: false,
|
||||
},
|
||||
desktopAuth: {
|
||||
clientId: 'client-001',
|
||||
clientSecret: 'secret-001',
|
||||
@@ -54,7 +58,8 @@ test('kiro state module exposes canonical nested kiroRuntime view', () => {
|
||||
assert.equal(view.kiroRuntime.session.currentStage, 'desktop-authorize');
|
||||
assert.equal(view.kiroRuntime.session.registerTabId, 88);
|
||||
assert.equal(view.kiroRuntime.register.email, 'aws-user@example.com');
|
||||
assert.equal(view.kiroRuntime.register.userCode, 'ABCD-1234');
|
||||
assert.equal(view.kiroRuntime.register.loginUrl, 'https://app.kiro.dev/signin');
|
||||
assert.equal(view.kiroRuntime.webAuth.status, 'signin_started');
|
||||
assert.equal(view.kiroRuntime.desktopAuth.clientId, 'client-001');
|
||||
assert.equal(view.kiroRuntime.desktopAuth.refreshToken, 'refresh-001');
|
||||
assert.equal(view.kiroRuntime.upload.status, 'ready_to_upload');
|
||||
|
||||
@@ -146,6 +146,9 @@ const captured = [];
|
||||
const PLUS_PAYMENT_METHOD_PAYPAL = 'paypal';
|
||||
const PLUS_PAYMENT_METHOD_GOPAY = 'gopay';
|
||||
const PLUS_PAYMENT_METHOD_GPC_HELPER = 'gpc-helper';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
||||
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
|
||||
const self = {
|
||||
MultiPageStepDefinitions: {
|
||||
getSteps(options) {
|
||||
@@ -160,8 +163,10 @@ const self = {
|
||||
};
|
||||
${extractFunction('isPlusModeState')}
|
||||
${extractFunction('normalizePlusPaymentMethod')}
|
||||
${extractFunction('normalizePlusAccountAccessStrategy')}
|
||||
${extractFunction('normalizeSignupMethod')}
|
||||
${extractFunction('getSignupMethodForStepDefinitions')}
|
||||
${extractFunction('buildResolvedStepDefinitionState')}
|
||||
${extractFunction('getStepDefinitionsForState')}
|
||||
return {
|
||||
getCaptured: () => captured.slice(),
|
||||
@@ -180,6 +185,7 @@ return {
|
||||
activeFlowId: 'openai',
|
||||
plusModeEnabled: true,
|
||||
plusPaymentMethod: 'gopay',
|
||||
plusAccountAccessStrategy: 'oauth',
|
||||
signupMethod: 'phone',
|
||||
phoneSignupReloginAfterBindEmailEnabled: false,
|
||||
}]);
|
||||
|
||||
@@ -77,3 +77,16 @@ test('kiro register content does not misclassify the normal name page as a proxy
|
||||
|
||||
assert.equal(fatal, null);
|
||||
});
|
||||
|
||||
test('kiro register content treats Kiro web success callback as signed in', () => {
|
||||
const harness = createHarness({
|
||||
href: 'https://app.kiro.dev/signin?auth_status=success&redirect_from=KiroIDE',
|
||||
hostname: 'app.kiro.dev',
|
||||
title: 'Kiro',
|
||||
bodyText: 'Signed in',
|
||||
});
|
||||
|
||||
const detected = harness.detectKiroRegisterPageState();
|
||||
|
||||
assert.equal(detected.state, 'kiro_web_signed_in');
|
||||
});
|
||||
|
||||
@@ -195,6 +195,9 @@ test('collectSettingsPayload omits custom password and local sync settings in co
|
||||
const api = new Function('normalizeIcloudTargetMailboxType', 'normalizeIcloudForwardMailProvider', `
|
||||
let latestState = { contributionMode: true };
|
||||
const window = {};
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
||||
const DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY = PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH;
|
||||
let cloudflareDomainEditMode = false;
|
||||
let cloudflareTempEmailDomainEditMode = false;
|
||||
const selectCfDomain = { value: 'example.com' };
|
||||
@@ -297,6 +300,7 @@ function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) ||
|
||||
function normalizeAutoDelayMinutes(value) { return Number(value) || 30; }
|
||||
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
||||
function normalizeVerificationResendCount(value, fallback) { return Number.isFinite(Number(value)) ? Number(value) : fallback; }
|
||||
function normalizePlusAccountAccessStrategy(value = '') { return String(value || '').trim().toLowerCase() === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION ? PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION : PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH; }
|
||||
function normalizePhoneSmsProvider(value = '') { return String(value || '').trim().toLowerCase() === '5sim' ? '5sim' : 'hero-sms'; }
|
||||
function getSelectedPhoneSmsProvider() { return normalizePhoneSmsProvider(selectPhoneSmsProvider?.value || latestState?.phoneSmsProvider); }
|
||||
function normalizeFiveSimCountryId(value, fallback = DEFAULT_FIVE_SIM_COUNTRY_ID) { return String(value || '').trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '') || fallback; }
|
||||
|
||||
@@ -43,7 +43,7 @@ test('sidepanel html exposes flow selector and kiro source fields', () => {
|
||||
'id="row-kiro-rs-key"',
|
||||
'id="btn-test-kiro-rs"',
|
||||
'id="row-kiro-rs-test-status"',
|
||||
'id="row-kiro-device-code"',
|
||||
'id="row-kiro-web-status"',
|
||||
'id="row-kiro-login-url"',
|
||||
'id="row-kiro-upload-status"',
|
||||
].forEach((snippet) => {
|
||||
@@ -73,12 +73,14 @@ const window = {
|
||||
let latestState = { activeFlowId: 'openai' };
|
||||
let currentPlusModeEnabled = false;
|
||||
let currentPlusPaymentMethod = 'paypal';
|
||||
let currentPlusAccountAccessStrategy = 'oauth';
|
||||
let currentSignupMethod = 'email';
|
||||
let currentPhoneSignupReloginAfterBindEmailEnabled = false;
|
||||
let currentStepDefinitionFlowId = 'openai';
|
||||
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
|
||||
const DEFAULT_SIGNUP_METHOD = 'email';
|
||||
const DEFAULT_PLUS_PAYMENT_METHOD = 'paypal';
|
||||
const DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY = 'oauth';
|
||||
let stepDefinitions = [{ id: 6, key: 'openai' }];
|
||||
let STEP_IDS = [6];
|
||||
let STEP_DEFAULT_STATUSES = { 6: 'pending' };
|
||||
@@ -86,6 +88,9 @@ let SKIPPABLE_STEPS = new Set([6]);
|
||||
function renderStepsList() {
|
||||
calls.push({ type: 'render', stepIds: [...STEP_IDS] });
|
||||
}
|
||||
function normalizePlusAccountAccessStrategy(value = '') {
|
||||
return String(value || DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY).trim().toLowerCase() || DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY;
|
||||
}
|
||||
${bundle}
|
||||
return {
|
||||
calls,
|
||||
@@ -110,6 +115,7 @@ return {
|
||||
activeFlowId: 'kiro',
|
||||
plusModeEnabled: false,
|
||||
plusPaymentMethod: 'paypal',
|
||||
plusAccountAccessStrategy: 'oauth',
|
||||
signupMethod: 'email',
|
||||
phoneSignupReloginAfterBindEmailEnabled: false,
|
||||
},
|
||||
|
||||
@@ -86,6 +86,9 @@ test('collectSettingsPayload persists icloud target mailbox settings', () => {
|
||||
const api = new Function(`
|
||||
let latestState = { contributionMode: false };
|
||||
const window = {};
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
||||
const DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY = PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH;
|
||||
let cloudflareDomainEditMode = false;
|
||||
let cloudflareTempEmailDomainEditMode = false;
|
||||
const selectCfDomain = { value: '' };
|
||||
@@ -220,6 +223,7 @@ function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) ||
|
||||
function normalizeAutoDelayMinutes(value) { return Number(value) || 30; }
|
||||
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
||||
function normalizeVerificationResendCount(value, fallback) { return Number(value) || fallback; }
|
||||
function normalizePlusAccountAccessStrategy(value = '') { return String(value || '').trim().toLowerCase() === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION ? PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION : PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH; }
|
||||
function normalizePhoneSmsProvider(value = '') { return String(value || '').trim().toLowerCase() === '5sim' ? '5sim' : 'hero-sms'; }
|
||||
function setPhoneSmsProviderSelectValue(provider) {
|
||||
const normalizedProvider = normalizePhoneSmsProvider(provider);
|
||||
@@ -363,6 +367,9 @@ test('applySettingsState restores icloud forward mailbox settings before UI refr
|
||||
|
||||
const api = new Function('calls', `
|
||||
let latestState = {};
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
||||
const DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY = PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH;
|
||||
const inputEmail = { value: '' };
|
||||
const inputVpsUrl = { value: '' };
|
||||
const inputVpsPassword = { value: '' };
|
||||
@@ -460,6 +467,7 @@ function normalizePanelMode(value = '') {
|
||||
const normalized = String(value || '').trim().toLowerCase();
|
||||
return normalized === 'sub2api' || normalized === 'codex2api' ? normalized : 'cpa';
|
||||
}
|
||||
function normalizePlusAccountAccessStrategy(value = '') { return String(value || '').trim().toLowerCase() === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION ? PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION : PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH; }
|
||||
function isCustomMailProvider() { return false; }
|
||||
function setMail2925Mode() {}
|
||||
function normalizeIcloudFetchMode(value) { return String(value || '') === 'always_new' ? 'always_new' : 'reuse_existing'; }
|
||||
|
||||
@@ -159,6 +159,9 @@ let latestState = {
|
||||
currentMail2925AccountId: 'acc-2',
|
||||
};
|
||||
const window = {};
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
||||
const DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY = PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH;
|
||||
let cloudflareDomainEditMode = false;
|
||||
let cloudflareTempEmailDomainEditMode = false;
|
||||
const selectCfDomain = { value: 'example.com' };
|
||||
@@ -258,6 +261,7 @@ function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) ||
|
||||
function normalizeAutoDelayMinutes(value) { return Number(value) || 30; }
|
||||
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
||||
function normalizeVerificationResendCount(value, fallback) { return Number(value) || fallback; }
|
||||
function normalizePlusAccountAccessStrategy(value = '') { return String(value || '').trim().toLowerCase() === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION ? PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION : PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH; }
|
||||
function normalizePhoneSmsProvider(value = '') { return String(value || '').trim().toLowerCase() === '5sim' ? '5sim' : 'hero-sms'; }
|
||||
function getSelectedPhoneSmsProvider() { return normalizePhoneSmsProvider(selectPhoneSmsProvider?.value || latestState?.phoneSmsProvider); }
|
||||
function normalizeFiveSimCountryId(value, fallback = DEFAULT_FIVE_SIM_COUNTRY_ID) { return String(value || '').trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '') || fallback; }
|
||||
|
||||
@@ -873,6 +873,9 @@ return {
|
||||
test('collectSettingsPayload keeps local helper sync enabled while persisting sms toggle state', () => {
|
||||
const api = new Function('normalizeIcloudTargetMailboxType', 'normalizeIcloudForwardMailProvider', `
|
||||
const window = {};
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
||||
const DEFAULT_PLUS_ACCOUNT_ACCESS_STRATEGY = PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH;
|
||||
let latestState = {
|
||||
contributionMode: false,
|
||||
mail2925UseAccountPool: false,
|
||||
@@ -1025,6 +1028,7 @@ function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) ||
|
||||
function normalizeAutoDelayMinutes(value) { return Number(value) || 30; }
|
||||
function normalizeAutoStepDelaySeconds(value) { return value === '' ? null : Number(value); }
|
||||
function normalizeVerificationResendCount(value, fallback) { return Number(value) || fallback; }
|
||||
function normalizePlusAccountAccessStrategy(value = '') { return String(value || '').trim().toLowerCase() === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION ? PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION : PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH; }
|
||||
${extractFunction('normalizePhoneSmsProvider')}
|
||||
${extractFunction('normalizePhoneSmsProviderValue')}
|
||||
${extractFunction('normalizeFiveSimCountryCode')}
|
||||
|
||||
@@ -70,8 +70,8 @@ test('shared source registry exposes canonical Kiro sources and drivers', () =>
|
||||
);
|
||||
assert.equal(
|
||||
registry.detectSourceFromLocation({
|
||||
url: 'https://view.awsapps.com/start',
|
||||
hostname: 'view.awsapps.com',
|
||||
url: 'https://app.kiro.dev/signin',
|
||||
hostname: 'app.kiro.dev',
|
||||
}),
|
||||
'kiro-register-page'
|
||||
);
|
||||
@@ -91,11 +91,19 @@ test('shared source registry exposes canonical Kiro sources and drivers', () =>
|
||||
'unknown-source'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
registry.matchesSourceUrlFamily(
|
||||
'kiro-register-page',
|
||||
'https://app.kiro.dev/signin',
|
||||
'https://app.kiro.dev/signin'
|
||||
),
|
||||
true
|
||||
);
|
||||
assert.equal(
|
||||
registry.matchesSourceUrlFamily(
|
||||
'kiro-register-page',
|
||||
'https://signin.aws/register',
|
||||
'https://view.awsapps.com/start'
|
||||
'https://app.kiro.dev/signin'
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user