diff --git a/docs/local-customizations-maintenance.md b/docs/local-customizations-maintenance.md index 927bde6..9273bf3 100644 --- a/docs/local-customizations-maintenance.md +++ b/docs/local-customizations-maintenance.md @@ -338,6 +338,8 @@ OAuth 登录流程打开新标签页,避免复用旧页面导致状态污染 ## 8. 接码平台多平台适配:HeroSMS + 5sim +边界说明:接码平台多平台适配当前只属于 OpenAI 注册 / OAuth 链路,不作为多注册 flow 架构的 core 通用服务。后续新增的注册项目默认不接入接码;只有出现第二个真实项目也需要短信生命周期时,再按实际复用点抽象 provider 层。 + ### 目标 手机号验证 Step 9 支持按平台切换接码能力: diff --git a/docs/多注册流程侧边栏能力矩阵.md b/docs/多注册流程侧边栏能力矩阵.md new file mode 100644 index 0000000..088d8e6 --- /dev/null +++ b/docs/多注册流程侧边栏能力矩阵.md @@ -0,0 +1,258 @@ +# 多注册流程侧边栏能力矩阵 + +本文解决的是一个很容易被低估的问题:sidepanel 现在不只是“渲染 UI”,它还承担了大量业务约束。如果未来要支持多个 flow,不能只做动态渲染,还必须把“哪些能力允许显示、允许切换、允许启动”做成统一能力矩阵。 + +## 1. 当前源码里的真实问题 + +当前手机号注册能力至少同时受这几组条件约束: + +- `phoneVerificationEnabled` +- `plusModeEnabled` +- `contributionMode` +- `panelMode === 'cpa'` 时还会触发额外提醒 + +而这些约束现在分散在多个地方: + +- `background.js`:`canUsePhoneSignup` +- `background/message-router.js`:同类判断 +- `sidepanel/sidepanel.js`:`canSelectPhoneSignupMethod` +- `sidepanel/sidepanel.js`:`shouldWarnCpaPhoneSignup` + +这说明 sidepanel 当前既在做展示,也在做策略判定,而且判定逻辑有重复。 + +## 2. 设计目标 + +后续 sidepanel 至少要拆成三层能力判断: + +1. `flowCapabilities` +2. `panelCapabilities` +3. `runtimeLocks` + +最终所有显示 / 禁用 / 启动校验都只读这三层组合结果。 + +## 3. 三层能力定义 + +### 3.1 `flowCapabilities` + +表示“当前 flow 业务上支持什么”。 + +示例: + +```js +flowCapabilities.openai = { + supportsEmailSignup: true, + supportsPhoneSignup: true, + supportsPhoneVerificationSettings: true, + supportsPlusMode: true, + supportsContributionMode: true, + supportsPlatformBinding: ['cpa', 'sub2api', 'codex2api'], + supportsLuckmail: true, + supportsOauthTimeoutBudget: true, + stepDefinitionMode: 'openai-dynamic', +}; + +flowCapabilities.siteA = { + supportsEmailSignup: true, + supportsPhoneSignup: false, + supportsPhoneVerificationSettings: false, + supportsPlusMode: false, + supportsContributionMode: false, + supportsPlatformBinding: ['siteA-panel'], + supportsLuckmail: false, + supportsOauthTimeoutBudget: false, + stepDefinitionMode: 'siteA', +}; +``` + +原则: + +- 没有真实需求,不要默认给新 flow 打开手机号、Plus、LuckMail +- 新 flow 默认从最小能力集合开始 + +### 3.2 `panelCapabilities` + +表示“当前面板来源允许什么交互”。 + +示例: + +```js +panelCapabilities = { + cpa: { + supportsPhoneSignup: true, + requiresPhoneSignupWarning: true, + }, + sub2api: { + supportsPhoneSignup: true, + requiresPhoneSignupWarning: false, + }, + codex2api: { + supportsPhoneSignup: true, + requiresPhoneSignupWarning: false, + }, +}; +``` + +注意:`contributionMode` 不是新的 `panelMode`,它是独立运行态锁。 + +### 3.3 `runtimeLocks` + +表示“当前这一次运行或当前 UI 状态是否允许操作”。 + +示例: + +```js +runtimeLocks = { + autoRunLocked: false, + contributionMode: false, + plusModeEnabled: false, + phoneVerificationEnabled: true, + settingsMenuLocked: false, +}; +``` + +它决定的是: + +- 现在能不能切换注册方式 +- 能不能改 flow +- 能不能导入导出配置 +- 能不能打开某些配置区 + +## 4. 统一选择器 + +建议提供一个中心 selector: + +```js +resolveSidepanelCapabilities({ + activeFlowId, + panelMode, + state, +}); +``` + +输出: + +```js +{ + effectiveSignupMethods: ['email', 'phone'], + canShowPhoneSettings: true, + canSelectPhoneSignup: true, + shouldWarnCpaPhoneSignup: true, + canShowPlusSettings: true, + canShowLuckmail: true, + canExportSettings: true, + canSwitchFlow: false, + stepDefinitionOptions: {}, +} +``` + +以后 sidepanel 与 background 都只消费这份结果,不再各写一套判断。 + +## 5. OpenAI 当前矩阵 + +### 5.1 仅看 flow 能力 + +OpenAI 当前业务上支持: + +- 邮箱注册 +- 手机号注册 +- OAuth 登录 +- 平台回调绑定 +- Plus +- LuckMail +- 接码配置 + +### 5.2 加上 runtime lock 后的真实结果 + +OpenAI 的手机号注册只有在以下条件同时成立时才可选: + +- `flowCapabilities.openai.supportsPhoneSignup === true` +- `phoneVerificationEnabled === true` +- `plusModeEnabled === false` +- `contributionMode === false` + +也就是说,手机号注册不是一个“单纯 UI 开关”,而是能力矩阵结果。 + +### 5.3 加上 panel 约束后的额外行为 + +当满足手机号注册可用,且当前 `panelMode === 'cpa'` 时: + +- 不阻止 +- 但要提示风险 + +这类“允许但要提醒”的逻辑也必须归到能力矩阵里,而不是散落在点击事件中。 + +## 6. 步骤列表也属于能力矩阵的一部分 + +当前步骤定义主要受: + +- `plusModeEnabled` +- `signupMethod` + +影响,并通过 `data/step-definitions.js` 动态切换。 + +多 flow 后必须升级成: + +```js +getStepDefinitions({ + activeFlowId, + signupVariant, + panelMode, + plusModeEnabled, + contributionMode, +}); +``` + +也就是说,步骤列表不再是全局 `10 步 / 13 步` 二选一,而是 flow-aware 的定义。 + +## 7. Sidepanel 分层职责 + +### 7.1 展示层 + +只负责: + +- show / hide +- enabled / disabled +- 文案与提示 + +### 7.2 能力判定层 + +只负责: + +- `resolveSidepanelCapabilities()` +- `validateAutoRunStart()` +- `validateModeSwitch()` + +### 7.3 后台复核层 + +后台在收到启动、切换注册方式、切换 flow 等消息时,仍要复核一遍同一套能力判断,避免 sidepanel 以外的入口绕过约束。 + +## 8. 新 flow 的默认能力策略 + +后续新增 flow 时,默认按以下最小集合开始: + +- 仅邮箱注册 +- 无手机号注册 +- 无 Plus +- 无 LuckMail +- 无贡献模式 +- 无 OpenAI 平台回调面板 + +只有真实需求出现时,再逐项打开 capability。 + +## 9. 迁移顺序 + +1. 提炼 `flowCapabilitiesRegistry` +2. 提炼 `panelCapabilitiesRegistry` +3. 新增 `resolveSidepanelCapabilities()` 与 `validateAutoRunStart()` +4. 让 `sidepanel.js`、`background.js`、`message-router.js` 共用同一套 selector +5. 再把步骤定义切换也改成 flow-aware + +## 10. 本文对应解决的缺口 + +本文主要补齐以下缺口: + +- sidepanel 不只是渲染层,还承接业务约束 +- 手机号注册能力由多个开关共同决定,当前逻辑分散且重复 +- `contributionMode` 与 `panelMode` 容易混淆 +- 多 flow 之后,步骤列表也必须纳入能力矩阵,而不是继续全局写死 + diff --git a/docs/多注册流程来源与驱动注册设计.md b/docs/多注册流程来源与驱动注册设计.md new file mode 100644 index 0000000..82a5f4c --- /dev/null +++ b/docs/多注册流程来源与驱动注册设计.md @@ -0,0 +1,246 @@ +# 多注册流程来源与驱动注册设计 + +本文解决的是另一个会在第二个 flow 接入时立刻爆炸的问题:当前项目虽然有 `tab-runtime`,但“来源 source 是谁、该注入什么脚本、URL family 怎么判定、localhost callback 应该清谁”仍然带着明显的 OpenAI 单流程假设。 + +## 1. 当前源码里的真实耦合 + +### 1.1 `signup-page` 其实不是抽象 source,而是 OpenAI Auth 标签页别名 + +目前这些地方都把 OpenAI Auth / Consent / Add-phone 页面统称为 `signup-page`: + +- `content/utils.js` 的 `detectScriptSource()` +- `background/navigation-utils.js` 的 `matchesSourceUrlFamily()` +- `background/tab-runtime.js` 的注册表、冲突清理、callback 清理 + +这说明当前的 source 体系不是“可扩展的来源注册表”,而是“OpenAI 时代遗留的 source 命名”。 + +### 1.2 `content/utils.js` 的默认回退不安全 + +当前 `detectScriptSource()` 在无法识别页面时会回退成 `vps-panel`。这对单流程时期问题不大,但多 flow 下会出现两个风险: + +1. 新 flow 页面被误识别成 `vps-panel` +2. `PING / READY / COMPLETE` 日志和标签注册打到错误 source + +### 1.3 `tab-runtime` 的 localhost cleanup 直接写死 `registry['signup-page']` + +`closeLocalhostCallbackTabs()` 现在默认把匹配 callback 的残留 tab 从 `signup-page` 名下清掉。将来只要第二个 flow 也有 callback,或者 callback 不是来自 OpenAI Auth 页,这里就会清错或漏清。 + +### 1.4 manifest 的静态注入列表目前基本围绕 OpenAI + +`manifest.json` 里的静态内容脚本匹配域名,目前只有 OpenAI Auth 页是明确的 flow 页面入口。第二个 flow 如果沿用这套做法,后续只会不断在 manifest 里继续加分散规则,缺少统一 source 定义中心。 + +## 2. 设计目标 + +后续必须拆成两层注册表: + +1. `sourceRegistry`:管理“页面来源与标签页生命周期” +2. `driverRegistry`:管理“这个来源页面由哪个 content driver 负责,支持哪些命令” + +这两层不要再混成一个 `signup-page` 字符串。 + +## 3. `sourceRegistry` 设计 + +建议 source 用稳定 ID,而不是模糊业务词。 + +```js +sourceRegistry = { + 'openai-auth': { + flowId: 'openai', + kind: 'flow-page', + label: 'OpenAI 认证页', + hostPatterns: [ + 'https://auth.openai.com/*', + 'https://auth0.openai.com/*', + 'https://accounts.openai.com/*', + ], + familyMatcher: 'openai-auth-family', + injectFiles: [ + 'content/activation-utils.js', + 'content/utils.js', + 'content/operation-delay.js', + 'content/auth-page-recovery.js', + 'content/phone-country-utils.js', + 'content/phone-auth.js', + 'content/signup-page.js', + ], + cleanupScopes: ['oauth-localhost-callback'], + }, + + 'mail-gmail': { + flowId: null, + kind: 'mail-provider', + label: 'Gmail', + hostPatterns: ['https://mail.google.com/*'], + familyMatcher: 'gmail-family', + injectFiles: ['content/activation-utils.js', 'content/utils.js', 'content/gmail-mail.js'], + }, + + 'panel-sub2api': { + flowId: 'openai', + kind: 'panel-page', + label: 'SUB2API 后台', + dynamicOnly: true, + familyMatcher: 'sub2api-panel-family', + injectFiles: ['content/utils.js', 'content/sub2api-panel.js'], + }, +}; +``` + +### 3.1 source 里至少要有这些字段 + +- `id` +- `flowId` +- `kind` +- `label` +- `hostPatterns` +- `familyMatcher` +- `injectFiles` +- `readyPolicy` +- `cleanupScopes` +- `tabReusePolicy` + +### 3.2 source 不等于 flow + +一个 flow 会有多个 source: + +- `openai-entry` +- `openai-auth` +- `openai-plus-checkout` +- `openai-paypal` +- `openai-gopay` +- `panel-sub2api` + +同样,一个 source 也可能不属于具体 flow,例如: + +- `mail-gmail` +- `mail-163` +- `mail-2925` +- `mail-inbucket` + +## 4. `driverRegistry` 设计 + +`driverRegistry` 解决的是“页面上能做什么”,不是“标签页如何复用”。 + +```js +driverRegistry = { + 'openai-auth': { + sourceId: 'openai-auth', + driverId: 'content/signup-page', + commands: [ + 'OPEN_SIGNUP', + 'SUBMIT_SIGNUP_IDENTIFIER', + 'SUBMIT_PASSWORD', + 'SUBMIT_PROFILE', + 'SUBMIT_LOGIN_CODE', + 'SUBMIT_PHONE_CODE', + 'DETECT_AUTH_STATE', + ], + }, + + 'mail-gmail': { + sourceId: 'mail-gmail', + driverId: 'content/gmail-mail', + commands: ['POLL_MAILBOX', 'OPEN_MESSAGE', 'DELETE_MESSAGE'], + }, +}; +``` + +这样做的好处是: + +- `tab-runtime` 只关心 source +- workflow / mail service 只关心 driver capability +- 后续换内容脚本实现时,不需要改 tab 生命周期代码 + +## 5. `signup-page` 的迁移策略 + +`signup-page` 不能直接继续作为未来通用 source 名字。 + +建议迁移方式: + +1. 新增正式 source:`openai-auth` +2. 在 `sourceRegistry.aliases` 里临时保留: + - `signup-page -> openai-auth` +3. `getSourceLabel()`、`matchesSourceUrlFamily()`、`ensureContentScriptReadyOnTab()` 全部优先读注册表 +4. 等 OpenAI 全链路迁完后,再删除 `signup-page` 别名 + +## 6. localhost callback cleanup 怎么改 + +当前 callback 清理逻辑最大的问题是“只知道 callback URL,不知道 callback 属于哪个 flow source”。 + +建议改成: + +```js +callbackRegistry = { + 'oauth-localhost-callback': { + ownerSourceId: 'openai-auth', + matcher: isLocalhostOAuthCallbackUrl, + clearOwnerTabOnClose: true, + }, +}; +``` + +`closeLocalhostCallbackTabs()` 的输入要升级为: + +- `cleanupScope` +- `callbackUrl` +- `ownerSourceId` + +而不是默认拿 `signup-page`。 + +## 7. `content/utils.js` 的改法 + +### 7.1 禁止默认回退成 `vps-panel` + +新的规则应该是: + +- 有 `window.__MULTIPAGE_SOURCE` 时,以注入 source 为准 +- 没有显式 source 时,只在静态 host map 里做白名单匹配 +- 仍无法识别时返回 `unknown-source` + +`unknown-source` 不参与 tab 注册,不自动 `reportReady()`,只记录诊断日志。 + +### 7.2 child frame ready 规则也要转到注册表 + +当前 `shouldReportReadyForFrame()` 里写死了多个 source 名称。后续应改成 source metadata: + +- `readyPolicy: 'top-frame-only'` +- `readyPolicy: 'allow-child-frame'` + +## 8. manifest / 动态注入策略 + +原则上以后由 `sourceRegistry` 作为单一事实来源,manifest 只是实现载体。 + +建议约定: + +- 稳定公共页面可继续走静态 `content_scripts` +- 变动大、域名多、只在运行期打开的页面改走 `chrome.scripting.executeScript` +- 每个 source 明确自己的 `hostPatterns` 和 `injectFiles` +- 新增 flow 时,不允许直接在业务代码里散写 `injectFiles = [...]` + +## 9. 与网络策略的关系 + +`sourceRegistry` 只负责页面来源,不负责代理策略;但每个 flow 应同时提供自己的 `networkProfile`,至少包含: + +- `guardDomains` +- `probeEndpoints` +- `failCloseDomains` + +否则 `ip-proxy-core` 仍会继续写死 `chatgpt.com / openai.com`。 + +## 10. 第一阶段迁移顺序 + +1. 引入 `sourceRegistry / driverRegistry` 与旧 source alias。 +2. 把 `getSourceLabel()`、`matchesSourceUrlFamily()`、`ensureContentScriptReadyOnTab()` 改成读注册表。 +3. 去掉 `detectScriptSource()` 的 `vps-panel` 默认回退。 +4. 改 `closeLocalhostCallbackTabs()`,不再写死 `signup-page`。 +5. 第二个 flow 接入时,严格要求先注册 source 和 driver,再写步骤逻辑。 + +## 11. 本文对应解决的缺口 + +本文主要补齐以下缺口: + +- `signup-page` 实际是 OpenAI source,不是通用注册页 +- source URL family / content ready / localhost callback cleanup 没有统一注册表 +- manifest 与动态注入没有统一入口 +- `content/utils.js` 的默认 source 回退会污染未来 flow + diff --git a/docs/多注册流程架构边界.md b/docs/多注册流程架构边界.md new file mode 100644 index 0000000..894b606 --- /dev/null +++ b/docs/多注册流程架构边界.md @@ -0,0 +1,124 @@ +# 多注册流程架构边界 + +本文记录后续从“OpenAI 注册扩展”升级到“多注册流程扩展”时的模块边界。当前结论是:需要引入多 flow 架构,但不要把所有能力都提前抽成通用服务。 + +## 1. 总体判断 + +后续新增注册项目时,不应继续在现有 OpenAI 步骤里堆 `if site === ...`。不同网站的注册入口、验证码、资料页、风控页、回调页和成功判定都可能完全不同,应按独立 flow 处理。 + +目标形态: + +```txt +core/ + flow-registry + workflow-engine + runtime-state + tab-runtime + logging + account-artifacts + email + mail-code-polling + network-proxy + +flows/ + openai/ + workflow.js + content-driver.js + mail-rules.js + network-profile.js + phone-verification-flow.js + phone-sms-providers/ + + site-a/ + workflow.js + content-driver.js + mail-rules.js + network-profile.js +``` + +第一阶段不需要立刻调整成上述目录,只需要按这个边界重构,避免新增项目继续污染 OpenAI 专用逻辑。 + +## 2. 必须通用化的部分 + +- `activeFlowId / runId / nodeId` 状态模型:替代只适合单流程的 `currentStep / stepStatuses`,同时避免与现有外部接口里的远端 `flow_id` 语义冲突。 +- Workflow engine:负责节点执行、跳转、停止、恢复、重试和超时,不理解具体网站页面。 +- Flow registry:负责注册 OpenAI、后续网站 A、网站 B 等独立流程。 +- Tab runtime:标签页注册、自动化窗口锁定、脚本注入、消息超时、页面 ready 检查。 +- Logging / status:结构化日志、节点状态、运行进度、停止和失败展示。 +- Account artifact store:记录账号产物、身份、凭据、回调结果和失败信息。 +- Email identity:邮箱生成、邮箱池、别名、转发收件目标等身份能力。 +- Mail polling:邮件验证码、magic link、激活链接的轮询框架;具体过滤和提取规则由 flow 提供。 +- IP proxy / network policy:代理应用、切换、出口检测、防泄漏;目标域名和探测 URL 由 flow 提供。 +- Sidepanel dynamic renderer:按 flow capability 显示配置区、步骤列表和运行状态。 +- Settings schema:通用配置与 flow 私有配置分层导入导出。 +- Error taxonomy / recovery policy:通用层只处理执行框架错误,业务错误由 flow 自己分类。 + +## 3. 暂不通用化的部分 + +以下能力当前只属于 OpenAI flow,不进入 core: + +- 手机接码:HeroSMS / 5sim / NexSMS、取号、复用、轮询、换号、释放、手机号注册和后置 add-phone。 +- LuckMail:当前 `project_code = openai` 的购邮、复用、已用/保留/禁用管理。 +- OpenAI / ChatGPT 页面 DOM 操作。 +- OpenAI OAuth 授权、localhost callback、CPA / SUB2API / Codex2API 绑定。 +- ChatGPT Plus、PayPal、GoPay、GPC 相关支付流程。 +- OpenAI 的验证码邮件过滤规则、登录状态判断、add-phone fatal 判断。 +- OpenAI 专属账号产物字段,如 Plus checkout、OAuth state、平台验证字段。 + +原因:当前除了 OpenAI,新项目暂不需要手机接码。过早把接码抽成通用服务会让新 flow 被迫理解手机号订单、短信平台、号码复用和页面 resend 细节,增加维护成本。 + +## 4. 手机接码边界 + +手机接码先保持为 OpenAI 专属能力。 + +当前这些模块在逻辑上归属 `flows/openai`,即使物理路径暂时还在旧目录: + +- `background/phone-verification-flow.js` +- `phone-sms/providers/hero-sms.js` +- `phone-sms/providers/five-sim.js` +- `phone-sms/providers/registry.js` +- `content/phone-auth.js` +- `content/phone-country-utils.js` +- sidepanel 中的接码配置区 +- 相关测试:`tests/phone-verification-flow.test.js`、`tests/five-sim-provider.test.js`、`tests/sidepanel-phone-verification-settings.test.js` + +后续新增 flow 默认 `sms: false`,不显示接码配置,不加载接码步骤,也不要求 workflow engine 理解短信订单。 + +如果未来第二个真实 flow 也需要接码,再按事实抽象,优先抽 provider API,而不是直接抽完整手机号验证编排: + +```js +flow.phoneVerification = { + acquirePolicy, + submitPhoneNumber, + submitCode, + classifyPhoneError, + recoverAfterTimeout, +} +``` + +只有两个以上 flow 共享相同短信供应商生命周期时,才考虑把 `phone-sms/providers/*` 下沉到 `core/services/sms`。 + +## 5. 迁移顺序 + +1. 引入 `activeFlowId / runId / currentNodeId / nodeStatuses / flowContext`,先兼容 OpenAI 旧步骤。 +2. 把邮箱、邮件轮询、代理、tab runtime、日志和账号记录逐步参数化,去掉 OpenAI 常量。 +3. 建立 `flows/openai` 边界,把 OpenAI 步骤、content driver、OAuth、Plus 和接码逻辑收拢进去。 +4. 用第二个真实注册项目验证 flow registry 和 workflow engine,而不是靠假想接口设计过度抽象。 +5. 稳定后清理旧 `step` 数字兼容层。 + +## 6. 新 flow 接入原则 + +新增注册项目时,只允许新增该 flow 的 workflow、content driver、mail rules、network profile 和必要的私有配置。不要直接修改 OpenAI 步骤,也不要把 OpenAI 的手机号验证、OAuth、Plus 支付逻辑提升为通用能力。 + +通用层只负责“怎么运行一个 flow”,具体 flow 负责“这个网站怎么注册”。 + +## 7. 配套设计文档 + +本边界文档只回答“什么该进 core、什么暂时不要抽”。要真正开工,还需要同时遵守下面四份配套设计: + +- `docs/多注册流程状态迁移设计.md`:解决 `DEFAULT_STATE` 扁平模型、旧 step 兼容、自动运行/日志/账号记录如何迁移。 +- `docs/多注册流程来源与驱动注册设计.md`:解决 `signup-page`、source family、内容脚本注入和 localhost callback cleanup 的注册表设计。 +- `docs/多注册流程邮件分层设计.md`:解决 provider driver 与 flow mail rules 的边界,以及 LuckMail 暂不通用化的问题。 +- `docs/多注册流程侧边栏能力矩阵.md`:解决 sidepanel 展示层与业务约束层混在一起的问题。 + +后续新 flow 设计如果与这四份文档冲突,以“先修正文档边界,再动代码”为准,不允许直接在现有 OpenAI 逻辑上叠条件分支。 diff --git a/docs/多注册流程状态迁移设计.md b/docs/多注册流程状态迁移设计.md new file mode 100644 index 0000000..fbce6e4 --- /dev/null +++ b/docs/多注册流程状态迁移设计.md @@ -0,0 +1,248 @@ +# 多注册流程状态迁移设计 + +本文是 `docs/多注册流程架构边界.md` 的落地补充,专门解决“现有扁平状态怎么迁到多 flow 架构”这个最容易把旧逻辑拖垮的问题。 + +## 1. 先说结论 + +当前项目不能直接在 `DEFAULT_STATE` 上继续堆字段。要支持多个完全不同的注册流程,必须先把“运行态”“持久配置”“共享服务状态”“flow 私有状态”分层,再保留一层 OpenAI 旧步骤兼容视图。 + +这次迁移的目标不是一步把全部字段搬完,而是先建立新的状态主模型,让旧代码通过 adapter 继续运行。 + +## 2. 当前源码里的真实问题 + +### 2.1 `DEFAULT_STATE` 仍然是单流程扁平模型 + +`background.js` 里的 `DEFAULT_STATE` 目前把这些不同层次的状态混在一起: + +- 流程进度:`currentStep`、`stepStatuses` +- 通用运行态:`automationWindowId`、`tabRegistry`、`logs` +- OpenAI OAuth / 平台回调:`oauthUrl`、`localhostUrl`、`sub2apiSessionId`、`codex2apiSessionId` +- OpenAI Plus:`plusCheckoutTabId`、`plusCheckoutUrl`、`plusBillingAddress` +- OpenAI 接码:`currentPhoneActivation`、`signupPhoneActivation`、`reusablePhoneActivation` +- OpenAI LuckMail:`currentLuckmailPurchase` +- 共享邮箱运行态:`registrationEmailState` + +这会带来两个直接后果: + +1. 新 flow 一接进来,就只能继续往全局 state 加字段。 +2. 任何 reset / retry / stop 都容易误清理别的业务域状态。 + +### 2.2 旧步骤数字模型已经渗透到多个模块 + +当前不只是 `background.js` 依赖 `currentStep / stepStatuses`,下列模块也在按“Step 1~13”理解流程: + +- `background/auto-run-controller.js` +- `background/logging-status.js` +- `background/account-run-history.js` + +所以新状态模型不能只改 `background.js`,必须给自动运行、日志、账号记录保留兼容出口。 + +### 2.3 `registrationEmailState` 名字看起来通用,内部却仍带 OpenAI 身份假设 + +`background/registration-email-state.js` 已经把邮箱运行态单独抽出来了,这是好事;但它的 `preserveAccountIdentity` 现在默认保留的是“手机号身份”,也就是: + +- `accountIdentifierType = phone` +- `signupPhoneNumber` +- `signupPhoneActivation` +- `signupPhoneCompletedActivation` + +这对 OpenAI 的 `add-email` 分支是对的,但对未来可能出现的“用户名主身份”“邀请码主身份”“钱包地址主身份”并不通用。 + +## 3. 目标状态分层 + +建议先建立“概念上的标准状态模型”,物理存储可以分阶段迁移。 + +```js +chrome.storage.session.runtimeState = { + activeFlowId: 'openai', + activeRunId: 'run_20260512_xxx', + currentNodeId: 'submit-signup-email', + nodeStatuses: { + 'open-chatgpt': 'completed', + 'submit-signup-email': 'running', + }, + + shared: { + automationWindowId: 123, + tabRegistry: {}, + sourceLastUrls: {}, + logs: [], + autoRun: {}, + accountArtifacts: {}, + }, + + services: { + mail: {}, + proxy: {}, + accountPools: {}, + }, + + flows: { + openai: { + auth: {}, + platformBinding: {}, + plus: {}, + phoneVerification: {}, + luckmail: {}, + identity: {}, + }, + }, + + legacyStepCompat: { + currentStep: 2, + stepStatuses: { 1: 'completed', 2: 'running' }, + }, +}; + +chrome.storage.local.settings = { + schemaVersion: 2, + + shared: { + autoRunDefaults: {}, + logging: {}, + }, + + services: { + mailProviders: {}, + ipProxy: {}, + hotmailPool: {}, + mail2925Pool: {}, + icloud: {}, + customEmailPool: {}, + }, + + flows: { + openai: { + signupMethod: 'email', + phoneVerificationEnabled: false, + plusModeEnabled: false, + plusPaymentMethod: 'paypal', + sub2api: {}, + codex2api: {}, + luckmail: {}, + smsProviders: {}, + }, + }, +}; +``` + +## 4. 四层状态边界 + +### 4.1 共享运行态 `runtimeState.shared` + +只放“运行任何 flow 都需要”的内容: + +- `activeFlowId / activeRunId / currentNodeId / nodeStatuses` +- `automationWindowId` +- `tabRegistry` +- `sourceLastUrls` +- `logs` +- 自动运行轮次、暂停、计时器计划 +- 账号产物总览,如最终身份、最终邮箱、最终手机号、完成时间 + +这里不要再放 OpenAI 特有概念,例如 `plusCheckoutTabId`、`currentPhoneActivation`。 + +### 4.2 共享服务状态 `runtimeState.services` + +放“可被多个 flow 复用的服务运行态”,而不是具体网站流程状态: + +- 邮箱 provider 当前会话 +- 2925 / Hotmail / iCloud / Cloud Mail 等共享邮箱服务上下文 +- IP 代理当前应用结果、探测结果、池游标 +- 可复用的共享账号池游标 + +注意:`LuckMail` 目前不进这一层,它仍属于 OpenAI flow 私有能力。 + +### 4.3 flow 私有运行态 `runtimeState.flows[flowId]` + +每个 flow 自己保管自己的业务运行态。当前 OpenAI 至少应拆成: + +- `auth`:`oauthUrl`、`localhostUrl` +- `platformBinding`:`sub2api*`、`codex2api*` +- `plus`:`plusCheckoutTabId`、`plusCheckoutUrl`、`plusBillingAddress` +- `phoneVerification`:`currentPhoneActivation`、`signupPhoneActivation`、`reusablePhoneActivation` +- `luckmail`:`currentLuckmailPurchase`、`currentLuckmailMailCursor` +- `identity`:OpenAI 特有的登录方式冻结结果、`step8VerificationTargetEmail` 等 + +### 4.4 持久配置 `settings` + +持久配置必须按“共享 / 服务 / flow 私有”拆开,不再把所有配置都平铺到同一个 namespace。 + +特别注意: + +- `signupMethod` 先保留在 `flows.openai`,不要急着抽成全局通用枚举。 +- `plusModeEnabled`、`plusPaymentMethod`、`gopay*`、`paypal*` 都属于 OpenAI flow 私有配置。 +- `phoneVerificationEnabled` 当前也属于 OpenAI flow 私有配置。 + +## 5. 旧步骤兼容层怎么做 + +迁移阶段仍要保留 `currentStep / stepStatuses`,但它们不再是主数据,只是 `legacyStepCompat` 的派生视图。 + +建议规则: + +1. 新的 canonical 状态只写 `activeFlowId / currentNodeId / nodeStatuses` +2. OpenAI flow 通过 node-to-step 映射生成 `legacyStepCompat` +3. `getState()` 对旧模块仍返回: + - `currentStep` + - `stepStatuses` + - OpenAI 旧字段镜像 +4. `setStepStatus(step, status)` 内部先更新 node,再回写 legacy step 视图 + +这样可以保证: + +- `background/auto-run-controller.js` 先不重写也能跑 +- `background/logging-status.js` 先不重写也能继续渲染 +- `background/account-run-history.js` 仍能按旧语义落盘 + +## 6. 账号记录与自动运行的兼容策略 + +### 6.1 自动运行 + +`background/auto-run-controller.js` 当前按数字步骤推断进度、失败点和恢复点。迁移阶段要增加一层统一 selector: + +- `getActiveRunProgress(state)` +- `getLegacyStepCompat(state)` +- `inferResumeNode(state, flowId)` + +第一阶段可以继续让 OpenAI flow 通过旧 step 恢复;第二个 flow 接入时再真正改成 node-based resume。 + +### 6.2 账号记录 + +`background/account-run-history.js` 不能只记“失败在第几步”,还要开始记录: + +- `activeFlowId` +- `activeRunId` +- `currentNodeId` +- `nodeStatuses` 摘要 +- `legacyFailedStep`(仅 OpenAI 兼容) + +否则未来多 flow 下,单看 `step7_failed` 已经没有意义。 + +## 7. 命名约束 + +仓库里已经存在别的 `flow_id` 语义,用在 GPC / GoPay 远端任务里。为了避免冲突: + +- 扩展内部运行态统一使用 `activeFlowId` +- 当前轮标识统一使用 `activeRunId` +- 节点标识统一使用 `currentNodeId` +- 不新增裸字段 `flowId` + +`flow_id` 只保留给外部接口 payload 兼容使用。 + +## 8. 第一阶段迁移顺序 + +1. 新增状态 selector / patch helper,不改业务步骤行为。 +2. 给 OpenAI flow 建立 `flowState.openai` 命名空间,同时保留旧字段镜像。 +3. 把日志、自动运行、账号记录改为优先读 selector,不直接拼 `stepStatuses`。 +4. 把新加字段一律放进 `shared / services / flows.openai`,禁止继续向 `DEFAULT_STATE` 顶层加 OpenAI 字段。 +5. 第二个 flow 接入前,再清理旧 step 镜像的写路径。 + +## 9. 本文对应解决的缺口 + +本文主要补齐以下缺口: + +- `DEFAULT_STATE` 扁平模型没有命名空间 +- 旧步骤状态与新 node 状态如何并存 +- 自动运行 / 日志 / 账号记录如何不被状态迁移打断 +- `registrationEmailState` 当前仍隐含“手机号是唯一可保留主身份”的假设 + diff --git a/docs/多注册流程邮件分层设计.md b/docs/多注册流程邮件分层设计.md new file mode 100644 index 0000000..2dc28c3 --- /dev/null +++ b/docs/多注册流程邮件分层设计.md @@ -0,0 +1,222 @@ +# 多注册流程邮件分层设计 + +本文专门解决“邮件轮询虽然看起来像公共能力,但实际 OpenAI 规则已经写进 provider 脚本和后台轮询里”这个问题。 + +## 1. 先说结论 + +邮件相关能力必须拆成两层,不能再只写一句“mail polling 通用化”: + +1. `mail provider driver` +2. `flow mail rules` + +前者负责“怎么从 Gmail / 163 / 2925 / Inbucket / API 邮箱里拿到邮件”,后者负责“哪封邮件算当前 flow 需要的验证码 / magic link / 激活链接”。 + +## 2. 当前源码里的真实耦合 + +### 2.1 后台轮询 payload 已经带着 OpenAI 过滤条件 + +`background/verification-flow.js` 当前在 `getVerificationPollPayload()` 里直接写死: + +- `senderFilters: ['openai', 'noreply', 'verify', 'auth', ...]` +- `subjectFilters: ['verify', 'verification', 'code', '验证码', 'confirm', ...]` + +这不是 provider 通用逻辑,而是 OpenAI flow 规则。 + +### 2.2 内容脚本也已经写死 OpenAI / ChatGPT 正则 + +当前多个 provider 脚本里直接内嵌了 OpenAI / ChatGPT 识别: + +- `content/gmail-mail.js` +- `content/mail-163.js` +- `content/mail-2925.js` +- `content/inbucket-mail.js` + +例如: + +- `openai` +- `chatgpt` +- `verification` +- `log-in code` +- `strictChatGPTCodeOnly` + +这意味着现在不是“通用 provider + OpenAI 规则”,而是“OpenAI 规则渗透进 provider 实现本身”。 + +### 2.3 LuckMail 不能直接算进共享邮件层 + +LuckMail 当前还有一个额外边界:它不只是“邮箱提供商”,还绑定了 OpenAI 项目购邮与复用语义。 + +当前事实包括: + +- `DEFAULT_LUCKMAIL_PROJECT_CODE = 'openai'` +- sidepanel 明确只展示 `openai` 项目的 LuckMail 邮箱 + +所以 LuckMail 当前应留在 OpenAI flow 内,不直接并入通用 `mailProviders`。 + +## 3. 目标分层 + +## 3.1 第一层:`mail provider driver` + +这一层只负责 provider 访问与消息归一化,不理解具体网站业务。 + +职责包括: + +- 打开 provider 页面或请求 provider API +- 等待页面 ready / 会话可用 +- 列邮件、开邮件、取正文、删邮件 +- 会话级去重 +- 输出统一格式的消息对象 + +建议输出结构: + +```js +{ + providerId: 'gmail', + messageId: 'abc123', + receivedAt: 1710000000000, + sender: 'OpenAI ', + subject: 'Your code is 123456', + previewText: 'Your code is 123456', + normalizedText: 'your code is 123456', + html: '...', + links: ['https://...'], + targetHints: ['user@example.com'], + metadata: {}, +} +``` + +这一层不要再写: + +- “这是不是 OpenAI 邮件” +- “是不是 ChatGPT 登录码” +- “这个 code 是否必须 6 位” + +## 3.2 第二层:`flow mail rules` + +这一层由具体 flow 定义: + +- 要找的邮件类型 +- 过滤条件 +- 选择规则 +- 提取规则 +- 命中后的消费动作 + +建议接口: + +```js +flow.mailRules = { + signupCode: { + buildQuery(state) {}, + matchMessage(message, state) {}, + extractArtifact(message, state) {}, + afterConsume(message, provider, state) {}, + }, + loginCode: { + buildQuery(state) {}, + matchMessage(message, state) {}, + extractArtifact(message, state) {}, + }, +}; +``` + +其中: + +- `buildQuery` 负责时间窗、目标邮箱、允许的发件人线索 +- `matchMessage` 负责判定这是不是当前 flow 的邮件 +- `extractArtifact` 负责提取 `code / magic-link / activation-link` +- `afterConsume` 负责删除邮件、记录 cursor、保存已试 code + +## 4. 建议的共享 mail service 接口 + +```js +mailService.poll({ + providerId: 'gmail', + rule: flow.mailRules.signupCode, + state, + maxAttempts: 5, + intervalMs: 3000, +}); +``` + +内部流程: + +1. provider driver 按 query 拉取候选消息 +2. rule 决定哪封命中 +3. rule 提取 artifact +4. service 返回统一结果 + +返回值示例: + +```js +{ + ok: true, + artifact: { + type: 'code', + value: '123456', + }, + message: { ...normalizedMessage }, +} +``` + +## 5. OpenAI flow 当前应该拆出的规则 + +OpenAI 至少需要单独拆出这些规则文件: + +- `flows/openai/mail-rules/signup-code.js` +- `flows/openai/mail-rules/login-code.js` +- `flows/openai/mail-rules/add-email-code.js` + +它们负责承接现在散落在这些地方的规则: + +- `verification-flow.js` 中的 sender / subject filters +- `gmail-mail.js` / `mail-163.js` / `mail-2925.js` / `inbucket-mail.js` 中的 OpenAI / ChatGPT 正则 +- `strictChatGPTCodeOnly` +- Step 4 与 Step 8 不同的时间窗和目标邮箱逻辑 + +## 6. provider driver 的拆分建议 + +### 6.1 可以进入共享层的 provider + +这些 provider 的访问方式本身有共享价值,可以做成共享 mail driver: + +- Gmail +- 163 / 126 / 163 VIP +- 2925 +- Inbucket +- iCloud Mail +- Hotmail helper / Graph Mail +- Cloud Mail / SkyMail + +### 6.2 暂时不进入共享层的 provider + +- LuckMail:当前仍是 OpenAI 项目购邮与验证码轮询能力的一部分 + +如果未来第二个 flow 也明确复用 LuckMail,且复用的是“同一套 project / token / 生命周期”,再考虑把它抽出来。 + +## 7. `registrationEmailState` 与邮件层的关系 + +`registrationEmailState` 负责“当前流程邮箱身份”,不是“provider 拉信规则”。 + +所以后续边界应是: + +- `registrationEmailState`:运行态身份记录 +- `mail provider driver`:拉信能力 +- `flow mail rules`:判定与提取 + +不要再在 `registrationEmailState` 或 provider driver 里夹带 OpenAI `add-email` 业务判断。 + +## 8. 迁移顺序 + +1. 先把 `background/verification-flow.js` 里的查询构造迁到 `flows/openai/mail-rules/*` +2. 再把各 provider 脚本里的 OpenAI / ChatGPT 正则搬出到 rule 层 +3. 保留 provider 里的“消息抓取 / 页面操作 / 删除策略” +4. 等第二个 flow 接入时,只新增它自己的 `mail-rules`,不改 Gmail / 163 / 2925 driver + +## 9. 本文对应解决的缺口 + +本文主要补齐以下缺口: + +- “Mail polling 通用化”表述过于粗糙,没有说明 provider 与 rule 两层 +- provider 内容脚本里已经嵌入 OpenAI 规则 +- `strictChatGPTCodeOnly` 这类开关的归属边界不清 +- LuckMail 当前其实还是 OpenAI flow 私有邮件能力,不是共享 provider + diff --git a/项目完整链路说明.md b/项目完整链路说明.md index ac1c021..39ac559 100644 --- a/项目完整链路说明.md +++ b/项目完整链路说明.md @@ -478,7 +478,7 @@ IP 代理模块在同步、切换、Change、出口探测和自动运行成功 - 打开邮箱页或 API 轮询入口 - 轮询登录验证码并回填 4. 当前是真实 `phone-verification` 页: - - 才复用手机号验证码共享流程,重新激活同一号码并轮询短信验证码 + - 才复用 OpenAI 专属手机号验证码流程,重新激活同一号码并轮询短信验证码 - 在当前 `phone-verification` 页回填短信验证码 5. 如果登录验证码提交后页面进入 `add-phone / 手机号页`,则邮箱注册模式下交给后续 OAuth 后置手机号验证链路;手机号注册模式不把 `signupPhone*` 身份误当成官方 add-phone 订单 6. 如遇邮箱轮询类失败或显式的 `STEP8_RESTART_STEP7` 恢复错误,则按有限次数回到 Step 7 重试;若仍停在验证码页、手机验证码页或 add-email 页,则优先在当前链路重试 @@ -503,8 +503,8 @@ IP 代理模块在同步、切换、Change、出口探测和自动运行成功 流程: 1. 监听 localhost callback -2. 准备 OAuth 同意页;如果页面已进入 `add-phone / phone-verification`,先切入手机号验证共享流程 -3. 手机号验证共享流程会按当前 sidepanel 中保存的接码平台 `phoneSmsProvider` 选择 HeroSMS 或 5sim,并使用对应平台的 API Key、国家/地区、价格上限申请或复用号码 +2. 准备 OAuth 同意页;如果页面已进入 `add-phone / phone-verification`,先切入 OpenAI 专属手机号验证流程 +3. OpenAI 手机号验证流程会按当前 sidepanel 中保存的接码平台 `phoneSmsProvider` 选择 HeroSMS / 5sim / NexSMS,并使用对应平台的 API Key、国家/地区、价格上限申请或复用号码 4. 后台提交号码后,会按 `currentPhoneActivation.provider` 分发后续查码、完成、取消、ban、reuse:HeroSMS 走原 `getStatus / setStatus` 逻辑,5sim 走 `/v1/user/check|finish|cancel|ban|reuse` 5. 验证码被拒绝或长时间收不到短信时,会按平台决定重发、换号、ban/取消当前激活,必要时把自动流拉回 Step 7 6. 手机号验证完成后,如果认证页偶发进入资料页,内容脚本会复用 Step 5 的姓名生日填写逻辑补齐资料,再继续等待 OAuth 同意页 @@ -514,7 +514,7 @@ IP 代理模块在同步、切换、Change、出口探测和自动运行成功 补充: -- HeroSMS 和 5sim 都归入接码平台适配层;默认平台是 HeroSMS,5sim 产品码固定为 `openai`,operator 默认 `any`。 +- HeroSMS / 5sim / NexSMS 都归入 OpenAI 接码平台适配层;默认平台是 HeroSMS,5sim 产品码固定为 `openai`,operator 默认 `any`。该适配层暂不进入多注册 flow 的 core 通用服务,后续只有第二个真实 flow 也需要接码时再按实际复用点抽象。 - 号码当前最多复用 3 次成功注册;超过上限后会清空可复用激活记录,下次重新申请新号码。 - 5sim 的国家/地区使用字符串 slug(当前开放 `indonesia / thailand / vietnam`),HeroSMS 仍使用数字国家 ID(当前开放印度尼西亚/泰国/越南)。 - 如果同一个号码在重发短信后仍收不到验证码,后台会按当前平台取消或 ban 激活并换号,而不是把当前号码无限重试下去。 diff --git a/项目文件结构说明.md b/项目文件结构说明.md index 015105f..b7482be 100644 --- a/项目文件结构说明.md +++ b/项目文件结构说明.md @@ -58,7 +58,7 @@ - `background/registration-email-state.js`:注册邮箱运行态共享模块,负责维护 `registrationEmailState = { current, previous, source, updatedAt }`,并提供“当前邮箱清空时保留上一比较基线”“Duck 生成前解析比较基线”“Step 8 `add-email` 写入邮箱时按需保留手机号身份”的统一工具。 - `background/navigation-utils.js`:导航与 URL 判断工具层,负责 callback、入口页、CPA / SUB2API / Codex2API 地址归一化、来源标签页家族判断与步骤跳转相关判断。 - `background/paypal-account-store.js`:PayPal 账号池持久化模块,负责保存账号列表、切换当前账号,并把当前选中账号同步回兼容字段 `paypalEmail / paypalPassword`。 -- `background/phone-verification-flow.js`:手机号验证码共享流程模块,负责复用 HeroSMS / 5sim / NexSMS 的取号、复用、轮询、重发、换号与收尾能力;既承接 OAuth 后置 `add-phone / phone-verification` 页面,也承接手机号注册 Step 4 和 Step 8 中真实出现的 `phone-verification` 页面,并保持 `signupPhone*` 运行态与 `currentPhoneActivation` 隔离;后置 add-phone 成功后会把已绑定手机号写入运行态 `phoneNumber`,供账号记录并入同一轮;提交后置手机号验证码时会一并透传可复用的资料页 payload,便于认证页偶发跳回资料页时继续补齐;该流程由调用方传入当前可见步骤号,手机号日志不会再固定显示普通模式 Step 9。 +- `background/phone-verification-flow.js`:OpenAI 专属手机号验证码流程模块,负责复用 HeroSMS / 5sim / NexSMS 的取号、复用、轮询、重发、换号与收尾能力;既承接 OpenAI OAuth 后置 `add-phone / phone-verification` 页面,也承接 OpenAI 手机号注册 Step 4 和 Step 8 中真实出现的 `phone-verification` 页面,并保持 `signupPhone*` 运行态与 `currentPhoneActivation` 隔离;后续多注册 flow 架构中,该模块应收拢到 `flows/openai` 边界内,不作为 core 通用接码服务提前抽象;后置 add-phone 成功后会把已绑定手机号写入运行态 `phoneNumber`,供账号记录并入同一轮;提交后置手机号验证码时会一并透传可复用的资料页 payload,便于认证页偶发跳回资料页时继续补齐;该流程由调用方传入当前可见步骤号,手机号日志不会再固定显示普通模式 Step 9。 - `background/panel-bridge.js`:来源桥接层;CPA / SUB2API 继续封装页面打开、脚本注入和通信,Codex2API 则直接通过后台协议生成 OAuth 地址。 - `background/signup-flow-helpers.js`:注册页辅助层,负责打开注册入口、Step 2 打开入口页后的加载完成与额外 3 秒稳定等待、等待密码页以及解析当前流程所用邮箱;在 Gmail 与 `2925 + provide` 模式下会优先复用已经存在且仍兼容的完整注册邮箱,只有不兼容或为空时才重新生成;当 provider 为 2925 且启用了 provide 模式下的号池时,会先确保账号池中已选中可用账号;若邮箱生成器在生成阶段已经写回运行态,这里不会再重复覆盖 `registrationEmailState`,但仍会在 Step 8 `add-email` 的手机号身份场景下通过共享持久化按需保留手机号身份。 - `background/tab-runtime.js`:标签页与内容脚本运行时基础设施,封装标签注册、冲突清理、消息超时、注入重试与队列;内容脚本恢复等待日志支持 `logStep / logStepKey`,用于保持 Plus 复用步骤的日志标签正确;当前等待标签完成、等待标签完成并短暂稳定、注入后的短暂延迟和内容脚本重试等待都已做 Stop 感知,避免用户停止后后台还继续等待并恢复执行。 @@ -69,7 +69,7 @@ - `background/steps/wait-registration-success.js`:步骤 6 实现,负责注册资料提交后等待 20 秒,让注册成功状态和页面跳转稳定;默认不清理 cookies,只有侧栏第六步 `清 Cookies` 开关开启时才会在等待结束后清理 ChatGPT / OpenAI 相关 cookies。 - `background/steps/confirm-oauth.js`:步骤 9 实现,负责 OAuth 同意页按钮定位、点击、localhost 回调监听与回调完成;等待 callback 期间会动态检查 OAuth 总预算开关,关闭后仅保留本地回调等待超时。 - `background/steps/create-plus-checkout.js`:Plus 模式第 6 步实现,负责在已登录 ChatGPT 页面创建 PayPal / GoPay checkout session,或在 GPC 模式下读取 accessToken 并通过 `https://gpc.qlhazycoder.top/api/gp/tasks` 创建队列任务,记录 checkout / GPC task 运行态。 -- `background/steps/fetch-login-code.js`:步骤 8 实现,负责按真实认证页状态分发登录后续流程:邮箱验证码页走邮箱轮询、验证码回填与回退控制;真实 `phone-verification` 页才复用手机号验证码共享流程;手机号注册登录后若进入 `add-email`,会先按共享邮箱状态持久化规则生成/解析邮箱并提交绑定,在不丢失当前手机号身份的前提下再进入邮箱验证码轮询;邮箱分支对非 2925 provider 会固定当前验证码页显示邮箱作为本次 Step 8 的目标邮箱,当 provider 为 2925 时,会在轮询前先确保当前 2925 账号已自动登录;命中 `email_in_use` 时会仅清空当前邮箱并保留上一轮比较基线,再在当前 Step 8 内重开 `add-email` 获取新邮箱,`max_check_attempts` 也只重启当前步骤恢复链。 +- `background/steps/fetch-login-code.js`:步骤 8 实现,负责按真实认证页状态分发登录后续流程:邮箱验证码页走邮箱轮询、验证码回填与回退控制;真实 `phone-verification` 页才复用 OpenAI 专属手机号验证码流程;手机号注册登录后若进入 `add-email`,会先按共享邮箱状态持久化规则生成/解析邮箱并提交绑定,在不丢失当前手机号身份的前提下再进入邮箱验证码轮询;邮箱分支对非 2925 provider 会固定当前验证码页显示邮箱作为本次 Step 8 的目标邮箱,当 provider 为 2925 时,会在轮询前先确保当前 2925 账号已自动登录;命中 `email_in_use` 时会仅清空当前邮箱并保留上一轮比较基线,再在当前 Step 8 内重开 `add-email` 获取新邮箱,`max_check_attempts` 也只重启当前步骤恢复链。 - `background/steps/fetch-signup-code.js`:步骤 4 实现,负责注册验证码阶段的页面准备与验证码流程入口;邮箱注册继续走邮箱验证码,手机号注册改走短信验证码;当 provider 为 2925 时,会在邮箱轮询前先确保当前 2925 账号已自动登录。 - `background/steps/fill-plus-checkout.js`:Plus 模式第 7 步实现,负责驱动 PayPal / GoPay checkout 页面选择付款方式、填写账单地址、提交订阅并等待跳转;GPC 模式则轮询队列任务,按远端 `api_waiting_for` 提交 OTP / PIN,并在任务失败、过期或取消时清理运行态。 - `background/steps/fill-password.js`:步骤 3 实现,负责密码生成、保存、回填与提交;当前已改为身份中立,手机号注册遇到无密码页时会按页面状态自动跳过。 @@ -112,14 +112,20 @@ - `docs/仓库协作者AI分析PR与合并标准流程.md`:仓库协作者进行 AI 分析 PR 与合并时的流程说明。 - `docs/ip-proxy-module.md`:IP Proxy 模块说明,记录模块定位、后台/侧栏代码结构、当前功能范围、711Proxy 参数联动、操作方式、发布策略与已知限制。 +- `docs/local-customizations-maintenance.md`:记录本地相对上游长期保留的定制能力、关键代码位置,以及后续同步上游时的检查点。 +- `docs/公告书写标准.md`:公告类文档的书写标准与维护约束。 - `docs/使用教程.md`:旧版完整使用教程,保留尚未完全拆分的 HeroSMS、IP 代理、GoPay 等补充章节。 - `docs/使用教程/使用教程.md`:分部分使用教程总索引。 - `docs/使用教程/使用教程书写模板.md`:后续维护分部分教程时使用的书写与拆分模板。 - `docs/使用教程/分部分/*.md`:按主题拆分后的使用教程正文。 +- `docs/错误重试分层策略.md`:记录错误分类、恢复边界与重试策略分层,避免不同模块各自定义失败语义。 +- `docs/多注册流程架构边界.md`:后续从 OpenAI 单注册流程升级到多注册 flow 时的架构边界说明,明确 core 通用能力、flow 私有能力,以及手机接码暂归 OpenAI flow、不提前抽成通用服务的决策。 +- `docs/多注册流程状态迁移设计.md`:多注册 flow 重构时的状态迁移设计,明确共享运行态、服务运行态、flow 私有状态与旧 step 兼容层。 +- `docs/多注册流程来源与驱动注册设计.md`:多注册 flow 下 source registry、driver registry、内容脚本注入与 localhost callback 清理的设计说明。 +- `docs/多注册流程邮件分层设计.md`:多注册 flow 下邮件 provider driver 与 flow mail rules 的分层设计说明。 +- `docs/多注册流程侧边栏能力矩阵.md`:多注册 flow 下 sidepanel 的 flow capability、panel capability 与 runtime lock 设计说明。 - `docs/images/交流群.jpg`:README 中展示的官网 / QQ 交流群入口图片。 -- `docs/refactor/2026-04-16-architecture-refactor-plan.md`:本轮重构阶段的结构设计与迁移计划记录。 -- `docs/superpowers/plans/2026-04-10-hotmail-oauth-mail-pool.md`:Hotmail OAuth 邮箱池实现计划文档。 -- `docs/superpowers/specs/2026-04-10-hotmail-oauth-design.md`:Hotmail OAuth + Graph Mail 的设计规格文档。 +- `docs/images/微信.png`:README 与文档中使用的微信相关展示图片。 ## `icons/` @@ -217,7 +223,7 @@ - `tests/background-verification-flow-module.test.js`:测试验证码流程模块已接入且导出工厂。 - `tests/phone-auth-country-match.test.js`:测试认证页手机号国家选择在页面本地化时,仍能用 HeroSMS 的英文国家名匹配对应国家选项。 - `tests/phone-country-utils.test.js`:测试手机号国家/区号共享工具的区号提取、最长前缀解析、国家别名匹配,以及 manifest 与后台动态注入顺序。 -- `tests/phone-verification-flow.test.js`:测试手机号验证共享流程对 HeroSMS 的取号、复用、重发、换号与 Step 7 重开错误分支。 +- `tests/phone-verification-flow.test.js`:测试 OpenAI 专属手机号验证流程对 HeroSMS / 5sim / NexSMS 的取号、复用、重发、换号与 Step 7 重开错误分支。 - `tests/paypal-approve-detection.test.js`:测试 Plus 第 8 步后台执行器对 PayPal 标签页发现、分离式账号/密码页识别、联合登录页识别,以及登录后直接离开 PayPal 页的分支判断。 - `tests/paypal-flow-content.test.js`:测试 PayPal 内容脚本对可见邮箱/密码输入框的识别,并覆盖邮箱页即使已预填相同账号也会先清空再重填后继续下一步。 - `tests/gpc-sms-helper-script.test.js`:测试 GPC macOS 本地短信 helper 在非 macOS 环境下会提示平台与 iPhone 短信转发要求。