Abner
|
c6bf3a0238
|
🔧 chore: 升级 js-yaml 依赖并优化测试环境的加密随机数生成
- `tests/setup.js` 中 `getRandomValues` 模拟改用 Node.js `crypto.randomBytes` 填充,替代基于 `Math.random` 的不安全随机源,确保测试环境使用 CSPRNG 生成随机值
- 新增 `crypto` 模块导入,移除手动循环填充逻辑,简化代码实现并降低随机数偏差风险
- 将 `js-yaml@3` 补丁版本从 3.15.0 升级至 3.15.1,`js-yaml@4` 从 4.3.0 升级至 4.3.1
- 同步更新 `package-lock.json`,保持依赖锁文件与 `package.json` 声明一致
|
2026-08-18 18:33:01 +08:00 |
|
Abner
|
093310d25e
|
♻️ refactor: 优化通知与性能监控模块,加固通知消息 XSS 防护
- 通知服务新增页面可见性监听:标签页隐藏时暂停轮询,回到前台后恢复定时,离开期间超过检查周期则立即补查,节省 Netlify Function 配额
- 性能监控改为批量缓冲写入 sessionStorage,达到 1 秒间隔或 20 条上限自动落盘,并在页面隐藏/卸载时冲刷剩余缓冲,避免逐条读写开销
- 通知管理器改用原生 DOM API 构建节点并以 textContent 渲染消息,移除 innerHTML 与 escapeHtml 方法,从结构上杜绝 XSS 注入
- 新增 notification-service、notification-manager、performance-monitor 三组单元测试,覆盖后台暂停恢复、缓冲落盘、XSS 防护与空消息容错等场景
- 合并共享 Toast 样式至 design-system.css 并支持主题色定制,入场动画改为渐进增强,清理废弃请求日志中间件、SW 预缓存路径等冗余代码
|
2026-08-09 18:33:34 +08:00 |
|
Abner
|
49be510892
|
✨ feat(simyo): 支持登录 MFA 双路径并统一会话守卫
新用户默认 MFA 时经 v2 verifyOTP 换正式会话;老用户未开启 MFA 时跳过步骤 2。
补齐 v2 代理、5 步 UI、i18n 与单元测试,抽取 requireSessionToken 避免业务接口遗漏守卫。
|
2026-07-22 21:12:59 +08:00 |
|
Abner
|
f41b21ab02
|
📝 docs: 规范 Simyo 测试注释表述
统一测试文件中的客户端身份与请求头相关描述。
|
2026-07-22 19:26:13 +08:00 |
|
Abner
|
4c8ab4b916
|
📝 docs: 规范 Simyo 客户端与接口注释表述
将注释与测试描述改为中性技术说明,仅保留接口路径与配置语义。
|
2026-07-22 19:26:13 +08:00 |
|
Abner
|
0a70ce47cb
|
✨ feat(simyo): 完善 eSIM 更换流程(仅 EMAIL)
- 修 handleApiResponse:登录/查询体无 result.success 时正确判定成功
- 设备更换:先 GET settings/simcard,再 POST EMAIL 申请;等待验证码时跳过重复下单
- 登录识别 mfaStatus,未关闭 MFA 时明确阻断
- bad session 单独文案;UA 更新为 iOS 18.2 / iPhone12,8
|
2026-07-22 19:26:12 +08:00 |
|
Abner
|
b042a47807
|
🐛 fix: 控制台 copyEsimDiagnostics 失焦时降级复制并不再抛 rejection
DevTools 调用时 Document is not focused 会导致 clipboard.writeText 失败。
Clipboard 失败后降级 execCommand;诊断导出始终打印全文,避免 unhandledrejection 与 Sentry 弹窗。
|
2026-07-22 19:26:12 +08:00 |
|
Abner
|
704d385d8a
|
✨ feat(simyo): 将 HTTP 426 等错误映射为用户可读文案
避免界面直接展示「HTTP 426」「missing X-Device-ID」等原始信息,
按状态码与已知业务短语输出中英文友好提示。
|
2026-07-22 19:26:12 +08:00 |
|
Abner
|
2bbe2f9bc4
|
♻️ refactor(simyo): 统一客户端版本与 User-Agent 配置
抽取 client-identity 作为版本、设备型号与 User-Agent 的单一事实来源;
本地与 Netlify 代理强制使用配置的 User-Agent,不再透传浏览器 UA。
|
2026-07-22 19:26:12 +08:00 |
|
Abner
|
5a65dd3d01
|
🐛 fix(simyo): 补齐请求头 X-Device-ID
Simyo 4.28+ 要求每个请求携带 UUID 形态的 X-Device-ID,
缺失会返回 400 missing X-Device-ID。前端生成并持久化设备 ID,
本地与代理同步转发该请求头,并将上游 API 路径切换为 webapi。
|
2026-07-22 19:26:12 +08:00 |
|
Abner
|
0ef5ea82e2
|
🐛 fix(simyo): 升级 iOS 客户端版本至 4.28.0 修复 HTTP 426
Simyo API 拒绝过旧的 X-Client-Version/User-Agent(4.23.5),
导致登录失败 HTTP 426。同步更新前端配置、本地代理与测试页。
Closes #94
|
2026-07-22 17:49:11 +08:00 |
|
Abner
|
81b86c7ec3
|
✅ test: 补充 Logger Release 与 env 输出用例
|
2026-07-17 21:02:07 +08:00 |
|
Abner
|
2eda195a89
|
✅ test: 补充诊断导出与帮助弹窗防护用例
同步更新 AuthHandler 断言与模块文档说明。
|
2026-07-17 20:53:32 +08:00 |
|
Abner
|
890e05f27f
|
✅ test: 补充 OAuth、登录、剪贴板与反馈相关单测
修复 sentry-feedback 与 qrcode 断言,新增 clipboard/PKCE/OAuth 回调/AuthHandler/showToast 覆盖。
|
2026-07-17 20:49:10 +08:00 |
|
Abner
|
68e931b901
|
♻️ refactor: 将日志输出格式从 JSON 重构为人类可读的字符串
- 修改 `server-logger.js` 核心逻辑,将日志输出从 `JSON.stringify` 改为模板字符串拼接,格式变更为 `[LEVEL] [function] [requestId] message | key=value`
- 同步更新 `bff-proxy.js` 和 `markdown-negotiation.js` 中的 Deno 环境内联日志函数,保持 Edge Function 与 Node.js 环境日志格式一致
- 调整 context 序列化方式,使用 `key=value` 空格分隔,无 context 时不输出分隔符 `|`,并移除 `timestamp` 字段
- 更新 `server-logger.test.js` 测试用例,断言日志输出为字符串匹配而非 JSON 解析,并增加单行输出及无 context 时不包含分隔符的验证
|
2026-06-26 21:48:03 +08:00 |
|
Abner
|
574506bcbf
|
✨ feat: 添加结构化日志支持并优化错误处理
- 在 netlify/functions/_shared/server-logger.js 中重构日志函数,统一日志输出格式,支持 context 字段覆盖基础字段(如 message)
- 在 netlify/functions/_shared/middleware.js 中增强 withAuth 中间件,注入结构化 logger 到上下文,增加 request_start / request_end / request_error 日志追踪,并记录请求耗时
- 为所有 Netlify Function(giffgaff-sms-activate、giffgaff-graphql、auto-activate-esim、verify-cookie、giffgaff-token-exchange、giffgaff-mfa-challenge、giffgaff-mfa-validation、health)添加结构化日志,替换原有 console 输出,包含请求入参、状态和耗时
- 在 netlify/edge-functions/bff-proxy.js 和 markdown-negotiation.js 中实现 Deno 内联结构化日志,生成 requestId 并统一日志输出格式,支持 INFO/WARN/ERROR/DEBUG 级别控制
- 更新测试用例 tests/modules/server-logger.test.js 和 tests/functions/middleware-logging.test.js,新增日志级别过滤、context 覆盖、多实例隔离、OPTIONS 预检处理等测试场景
|
2026-06-26 21:28:21 +08:00 |
|
Abner
|
89bacd46ed
|
✨ feat: 新增服务端结构化日志模块并完善日志相关测试
- 新增 `server-logger` 工具,输出单行 JSON 日志,统一包含 level、message、function、requestId、timestamp 等字段并支持 context 扩展
- 实现日志级别控制(`LOG_LEVEL` 环境变量),通过 `createLogger` 工厂按需抑制 DEBUG 日志并提供 `parseLogLevel/LOG_LEVELS` 供测试验证
- 新增中间件集成测试 `middleware-logging.test.js`,验证请求开始/结束/异常日志、耗时统计、logger 注入以及每次请求生成唯一 requestId
- 新增模块单元测试 `server-logger.test.js`,覆盖 JSON 结构、context 合并、warn/error 路由到对应 console 方法、以及 DEBUG 级别在不同环境下的输出行为
|
2026-06-26 21:22:26 +08:00 |
|
Neo Vern
|
7298ae4a0d
|
✨ feat: QR 码本地打包 + Edge Function 直接生成 (#86)
* ✨ feat: 打包 qrcode-generator@1.4.4 到本地 ES 模块
* ♻️ refactor(qrcode): 移除 CDN 加载逻辑,改用本地 import 引入 qrcode-generator
* 🔧 chore: 移除 CDN preconnect 提示,QR 码库已内联
* 🔧 chore: 清理 CSP 配置,移除不再需要的 CDN 域名
* ✨ feat: 将 QR 码生成迁移到 Edge Function,消除后端冷启动延迟
- 在 Edge Function 中内联 qrcode-generator 库(~20KB),直接生成 QR 码
- 删除废弃的 Netlify Function (qrcode-generate.js)
- 更新 server.js 移除对已删除函数的引用
- 更新测试文件适配新的 Edge 内联架构
* ♻️ refactor: 代码质量修复 — 移除死代码、消除变量遮蔽、添加交叉引用注释
* 🔧 chore: 修复非阻塞风险 — 补充 strict 模式、移除废弃 qrcode 依赖
- Edge Function qrcode-lib.js 补充 'use strict' 声明,与浏览器版保持一致
- 移除已废弃的 qrcode npm 依赖(原用于已删除的 Netlify Function)
* ♻️ refactor: 消除魔法数字、补充脆耦合和 async 技术债注释
- Edge Function 中 QR margin 魔法数字 8 替换为 QR_MARGIN_MODULES 常量
- generateQRCodeLocal 补充 async 无 await 的技术债说明
- error.message.startsWith 条件补充校验函数耦合关系注释
* 🐛 fix: 修复边界条件 — null JSON body、vendor 字符串异常、CDN preconnect 残留
- Edge Function: null JSON body 解构移到 try/catch 内,添加 null/非对象检查
- qrcode-generator: 库 throw 字符串时统一转换为 Error 对象,避免 .startsWith 崩溃
- index.html: 移除不再需要的 CDN preconnect 提示(jsdelivr/cdnjs)
* ♻️ refactor: 修复 CSP 恢复、异常归一化、自定义 Error 类、负面路径测试
- netlify.toml: 恢复 script-src 中 cdn.jsdelivr.net(Bootstrap JS 仍依赖)
- Edge Function catch: 归一化非 Error 异常(库可能 throw 字符串)
- Edge Function QR margin: createDataURL(cellSize, 2) → createDataURL(cellSize, cellSize * 2) 对齐模块边距
- Edge Function: 补充认证模型和 QR 格式变更注释
- qrcode-generator.js: 引入 QRCodeValidationError 替代 error.message.startsWith 脆耦合
- tests/bff-proxy: 添加 6 个 Edge QR 负面路径测试(无效 JSON、空/超长/非字符串 data、超范围 size)
- tests/qrcode-generator: 添加库 throw 字符串异常的测试
- scripts/sync-qrcode-lib.js: 新增库代码同步验证脚本
* 🐛 fix: 修复 server.js CSP 缺少 jsdelivr、同步脚本 CRLF 归一化、fallback 拦截校验错误
- server.js: 恢复 script-src 中 cdn.jsdelivr.net(本地开发 Bootstrap JS 依赖)
- sync-qrcode-lib.js: 归一化 CRLF 换行符避免跨平台误报
- qrcode-generator.js: generateQRCodeWithFallback 入口处拦截 QRCodeValidationError,避免无效输入触发无意义的后端降级
|
2026-06-25 22:15:17 +08:00 |
|
Abner
|
7221eb2e49
|
🐛 fix(qrcode): 添加 loadQRCodeLibrary 返回值防御性验证
解决 ESIM-TOOLS-15:浏览器扩展污染或缓存竞态导致 qrCodeLib 不是函数的极端情况。
新增重试机制:清除缓存后重新加载 CDN,避免用户看到 QR 码生成失败。
|
2026-06-24 23:03:30 +08:00 |
|
Neo Vern
|
bb80d3dc0a
|
✨ feat(sentry): 添加用户反馈功能 (#83)
* ✨ feat(sentry): 添加用户反馈功能
- 升级 CDN bundle 以支持 feedback 模块
- 添加 feedbackIntegration 内置 Widget(主动反馈)
- 实现错误后自动弹窗(Crash-Report Modal)
- 添加冷却机制防止频繁弹窗(60秒冷却 + 同一错误不重复)
* ♻️ refactor(sentry): 修复审查发现的问题
- 消除指纹计算重复(DRY 违反)
- 统一使用 const/let 替代 var
- 复用已有 showReportDialog 函数
- 添加 beforeSend UI 副作用设计说明注释
* 🐛 fix(sentry): 修复 SentryMock 缺失方法
- 添加 feedbackIntegration 和 replayIntegration 到 SentryMock
- 修复 CDN 加载失败时 TypeError
- 删除多余空行
* 🐛 fix(sentry): 修复代码质量问题
- sentry-loader.js 添加 replayIntegration 和 feedbackIntegration 配置
- sentry-loader.js 添加错误后自动弹窗逻辑(冷却机制 + try-catch)
- sentry-init.js 添加 showReportDialog try-catch 保护
- 弹窗延迟从 100ms 改为 500ms(弱网兼容)
* ✨ feat(sentry): 修复所有代码质量问题
- H1: CSP 添加 *.sentry.io 到 script-src(4 个文件)
- M1: Feedback Widget 和自动弹窗添加中文文案
- M2: 同步两套初始化路径配置(tracing、脱敏、ignoreErrors)
- M3: sentry-entry.js 添加 feedbackIntegration 导出
- M4: 新增专项测试(13 个测试用例)
- L1: SentryMock 补齐 showReportDialog/lastEventId
- L2: 空事件对象防御
* ✨ feat(sentry): 修复 PR 审查发现的全部问题
功能正确性:
- query_string 添加类型检查(字符串/对象兼容)
- 指纹计算移到脱敏前(避免不同错误被误判为重复)
- 冷却状态更新移到 setTimeout 内部(避免空转)
- subtitleLine2 改为 subtitle2(修正字段名)
CSP 修复:
- script-src 移除 *.sentry.io(减少攻击面)
- frame-src 添加 *.sentry.io(支持弹窗 iframe)
- 添加 worker-src/child-src blob:(支持 Session Replay)
- server.js helmet CSP 同步更新
- netlify.toml 注释与实际策略对齐
配置/架构:
- sentry-entry.js 添加 lastEventId 导出
- tracePropagationTargets 添加 CORS 风险注释
- CDN 架构添加说明注释
代码质量:
- URL 参数脱敏支持大小写不敏感
- 移除过宽的 ignoreErrors 规则
- 测试文件添加 use strict
- 添加 i18n 和漂移风险注释
* fix: apply CodeRabbit auto-fixes (#85)
Fixed 3 file(s) based on 5 unresolved review comments.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
* ✨ feat(sentry): 修复新一轮审查意见
CSP 修复:
- script-src 恢复 *.sentry.io(showReportDialog 需要)
- netlify.toml Header CSP 同步 Cloudflare/Google
- server.js helmet CSP 同步
冷却竞态修复:
- 状态预留移到 setTimeout 之前(防止 500ms 内重复弹窗)
- 弹窗失败时回滚冷却状态
脱敏修复:
- query_string 对象分支改为大小写不敏感
- sanitizeQueryString 迭代改为安全模式(先收集键再遍历)
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
|
2026-06-24 19:04:38 +08:00 |
|
Abner
|
6379bbef90
|
♻️ refactor: 移除外部二维码服务依赖,改用本地生成方案
- 将前端二维码生成从 `qrcode.show` 远程服务切换为 `qrcode-generator` 本地库(UMD 格式),消除对外部 CDN 渲染服务的依赖,降低隐私风险和第三方服务不可用时的故障点
- 重写 `generateQRCodeLocal` 函数适配 `qrcode-generator` API,使用 `qrcode(typeNumber, errorCorrectionLevel).addData().make().createDataURL()` 模式,并基于 QR 码模块数动态计算 `cellSize`,新增大尺寸预览图支持(400px)
- 移除所有页面中的 `qrcode.show` 域名引用,包括 CSP `connectSrc` 策略、preconnect 标签、resource-hints DNS 预解析配置及 Simyo/Giffgaff API 配置中的 `qrcode` 端点
- 完善二维码生成的日志与监控:在 CDN 加载成功后输出 `console.log`,本地/后端生成成功及失败时分别输出对应级别日志,并在 `trackQRCodeEvent` 中增加 `isBrowser` 守卫避免非浏览器环境报错
- 增加生成耗时和 QR 码长度(不含内容)到后端 BFF 日志,同时统一使用 `Date.now()` 计算请求耗时,避免 LPA 激活码等敏感信息进入日志
- 全面更新所有相关测试用例,适配新的 `window.qrcode` 工厂函数 mock,新增日志输出和 Sentry 上报断言,验证本地成功、本地失败降级、后端成功、后端失败四种场景的可观测性
|
2026-06-23 21:22:16 +08:00 |
|
Abner
|
51e50b62ff
|
🐛 fix: 修复 QR 码生成中的标签解构与错误处理问题,增强安全性
- 修复 `createQRCodeContainer` 函数中 `labels` 参数为 `undefined` 时导致解构崩溃的问题,添加默认空对象
- 简化 QR 码库加载逻辑,移除脚本已存在且加载完成时直接返回的冗余检查
- 移除 `showQRResult` 方法中冗余的 `.catch()` 处理,错误已由 `generateQRCode` 内部统一处理
- 在 Netlify 函数中创建 sanitizedError 对象,避免包含 LPA 字符串的错误信息泄露到 Sentry 日志
- 更新测试用例以匹配重构后的函数名和错误消息,并移除无效的 jest mock 配置
|
2026-06-13 20:15:23 +08:00 |
|
Abner
|
5450a0ddb5
|
✅ test: 增强二维码生成参数校验与错误处理测试,优化UI错误提示
- 为客户端 `generateQRCodeLocal` 增加非整数/越界size、非字符串data的输入校验测试用例
- 为后端 `qrcode-generate` 函数增加size整性、越界及非字符串data的测试用例
- 为后端 `qrcode-generate` 增加QRCode生成失败返回500的测试用例,并重构测试中Mock方式为全局Mock
- 在两个UI控制器移除废弃的 `qrTimeoutId` 字段,避免未捕获Promise拒绝并改用DOM API安全创建错误提示
- 前端 `generateQRCodeWithFallback` 增加后端超时(AbortError)和无效响应JSON的降级错误测试
|
2026-06-13 19:57:03 +08:00 |
|
Abner
|
0152277b4d
|
🐛 fix: 修复二维码生成 Promise 挂起、XSS 风险和 i18n 硬编码问题
- 修复 loadQRCodeLibrary Promise 永久挂起(Issue #75 根因)
- 检测已存在脚本标签,移除失效脚本并重新加载
- 添加 5 秒超时保护,防止 Session 恢复后二维码冻结
- 统一 cleanup 函数清理监听器和定时器
- 修复 XSS 风险
- 使用 DOM API 创建错误提示,避免 innerHTML 注入
- 移除模板字符串 ${t(...)} 直接注入
- 修复 i18n 硬编码
- createQRCodeContainer 接受 labels 参数支持多语言
- generateQRCode* 函数支持 labels 透传
- UIController 传入 tl() 翻译后的可访问性标签
- Schema 验证优化
- qrcode-generate 保留手动验证,确保 405 优先级
- 添加注释说明设计意图
- 代码规范
- tests/security/qrcode-generate.test.js 添加 'use strict'
✅ 测试: 8 passed, 0 failed
|
2026-06-13 19:43:50 +08:00 |
|
Abner
|
f5c5dee5ab
|
🐛 fix: 修复 Session 恢复后二维码和 LPA 不显示的问题
问题:
- 用户完成 eSIM 激活后,因外部二维码服务不可用导致页面空白
- Session 恢复时未调用 showESimResult() 显示二维码和 LPA 信息
解决方案:
1. 新增通用二维码生成模块 (src/js/modules/qrcode-generator.js)
- 实现三层降级策略:本地 CDN → 后端 Function → 文本提示
- 消除对外部服务的依赖,提升隐私保护
2. 新增后端 Function (netlify/functions/qrcode-generate.js)
- POST /bff/qrcode-generate 接口
- 返回 base64 编码的 PNG 二维码
- withAuth 中间件保护 + 输入验证
3. 重构前端二维码生成逻辑
- Giffgaff/Simyo 统一使用 generateQRCodeWithFallback()
- 保留并发调用防护和 tooltip 交互
- 使用 i18n 翻译替代硬编码错误提示
4. 修复 Session 恢复逻辑
- 在 handleSessionRestore() 中调用 showESimResult()
- 确保刷新页面后二维码和 LPA 正常显示
技术改进:
- 懒加载 qrcode.js(~13KB gzip),仅在首次调用时加载
- 完整的测试覆盖(前端单元测试 + 后端安全测试)
- 更新 BFF 路由配置(Edge Function + 本地开发服务器)
Closes #75
|
2026-06-13 19:20:22 +08:00 |
|
Abner
|
4a7e842d40
|
🐛 fix: 修复 giffgaff session 恢复后 LPA 和二维码不显示的问题(Issue #75)
- `showESimResult` 中移除 `!state.lpaString` 的提前返回,即使 lpaString 为空也显示结果容器,确保用户看到明确的错误提示和可能的排查信息
- 在 session 恢复流程(`giffgaff-app.js`)中显式调用 `uiController.showESimResult()`,使刷新页面后能正确显示二维码和 LPA 字符串,而不再跳过关键渲染步骤
- 为 `showESimResult` 添加完整的 try-catch 包裹及防御性 DOM 元素校验,在二维码生成失败时降级显示错误提示,避免页面静默失败
- 新增 i18n 键 `giffgaff.app.error.lpaStringMissing`(中英文),用于替代硬编码的错误文案,保持国际化一致性
- 新增 `tests/giffgaff/session-restore-lpa.test.js`,覆盖正常 LPA 展示、空 lpaString 错误降级、二维码生成、状态不一致降级以及延迟显示等场景
|
2026-06-12 23:54:05 +08:00 |
|
Abner
|
00a0e58d81
|
📝 docs: 更新架构与安全文档并扩展测试模块清单
- 更新 CLAUDE.md、docs/ARCHITECTURE.md 中的模块与阶段状态,补充 verify-cookie/health/public-config/notifications 等新节点,并将基础设施阶段由规划中标注为进行中
- 完善 docs/SECURITY.md 的 BFF 代理层与 withAuth 中间件说明,明确 x-esim-key 注入、函数白名单校验以及 CORS/体验验证的统一错误格式化策略
- 更新 src/giffgaff/MODULE_ARCHITECTURE.md 的安全考虑条目,补充 cookie 有效性检查间隔、CSP/Helmet 策略、HTML sanitization(escapeHtml/escapeAttr)以及通过 BFF 代理转发的传输层防护细则
- 扩展 tests/CLAUDE.md 测试范围与表格结构,新增 modules、giffgaff、security 三类的独立测试文件清单,并补充 tests/setup.js 的全局初始化说明
- 调整脚本与模块文档:scripts/CLAUDE.md 新增部署与构建相关脚本清单;src/js/modules/CLAUDE.md 更新 CaptchaManager 集成说明与模块覆盖状态,补充 notification-service/browser-utils 等相关条目
|
2026-06-02 22:50:26 +08:00 |
|
Abner
|
df2b6ca814
|
🐛 fix(auth): 收紧 BFF 鉴权并修复内部调用链路
|
2026-05-31 19:25:23 +08:00 |
|
Abner
|
b815225845
|
🐛 fix(auth): 收紧 BFF 鉴权并保持内部路由兼容
|
2026-05-31 18:15:45 +08:00 |
|
Abner
|
75da15edff
|
🐛 fix: 修复 PR 评审发现的 11 项问题
- data.data 空值保护:data?.data?.eSims 防止 TypeError
- directFetchMode 移至成功路径设置,失败时重置为 false
- SMS 卡片切换时隐藏 directFetchSection,避免双内联区同时可见
- modeBadge 直取模式下隐藏"设备更换"徽标
- tl() 文案迁移至 LITERAL_TRANSLATIONS,修复英文环境回退中文
- "拉取中"状态类型从 success 改为 info
- SSN radio 查询限定到 picker 容器内
- jest.config 补全 .spec.js 排除规则
- innerHTML 改用 DOM API 构建(pullBtn + renderSsnPicker)
- 测试 fail() 替换为 expect().rejects 惯用写法
|
2026-05-28 20:12:19 +08:00 |
|
Abner
|
60c3bd1cce
|
✨ feat: 新增「已支付直取 eSIM」功能,支持已购用户直接拉取 eSIM 生成二维码
在第 4 步新增第三张卡片「已支付直取 eSIM」,跳过 reserve/swap 流程,
直接调用 eSims(DOWNLOADABLE) 查询账户已有 eSIM 并生成 QR 码。
- BFF 白名单追加 eSims 查询的 App 头判定
- 新增 getESims GraphQL 查询与 fetchExistingESims/directFetchFlow 方法
- 支持多 eSIM 选择器(radio 列表)与空列表/错误状态处理
- 状态面板新增 directFetchMode 模式显示(运行时,不持久化)
- 补充 zh/en 双语 i18n 文案与 .status.info 样式
- 新增 9 个单元测试,全量测试 118 用例通过
Closes #62
|
2026-05-28 19:20:48 +08:00 |
|
Abner
|
59a7a97c29
|
✨ feat: CORS 多源支持 + Simyo 代理修复 + API 响应处理重构
- CORS 支持逗号分隔多源列表和通配符,新增 isAllowedOrigin/resolveCorsOrigin
- Simyo 代理路径从 req.path 改为 req.originalUrl,修复查询参数丢失
- Simyo 客户端配置提取为常量,支持环境变量覆盖
- API 端点检测浏览器协议,HTTP 访问时使用相对路径
- handleApiResponse 重构:content-type 检查、HTTP 错误优先、兼容三种响应格式
- 新增 X-Session-Token 头透传
- Logger 简化,移除前端模块依赖
- 同步更新测试 mock 以匹配新接口契约
|
2026-05-24 20:36:05 +08:00 |
|
Abner
|
ae7e30b5b1
|
✨ feat: 添加手机浏览器环境检测与警告功能
- 新增 browser-utils.js 模块,提供 isMobileBrowser 检测和 showMobileWarning 警告功能
- 实现会话级去重机制,避免重复显示手机环境警告通知
- 在 SimyoApp 的登录和设备更换流程中添加手机环境检测逻辑
- 在 GiffgaffApp 的 OAuth 登录流程中添加手机环境检测逻辑
- 添加多语言翻译支持,包括中文和英文版本的环境警告提示文本
|
2026-05-19 23:15:55 +08:00 |
|
Abner
|
fe28aec804
|
📝 docs: 修复 bot 审查发现的文档一致性问题
- 更新 tests/CLAUDE.md:移除已删除的 giffgaff 测试文件引用
- 更新 src/simyo/MODULE_ARCHITECTURE.md:移除对已删除目录的引用
- 更新 CLAUDE.md:修正 Webpack 相关描述,移除已废弃的别名说明
所有测试通过,文档与代码保持一致。
|
2026-05-18 22:23:10 +08:00 |
|
Abner
|
404fc88332
|
🧹 chore(cleanup): 移除未使用的模块化版本并修复文档问题
- 删除 src/js/modules/giffgaff/ 和 src/js/modules/simyo/ 目录(未完成的重构尝试)
- 移除 webpack.config.js 中未使用的别名配置和入口文件
- 修复文档错链:移除对不存在的 DEVELOPMENT_GUIDE.md 引用
- 修复文档错链:将 CORS_SOLUTION.md 中的 simyo_proxy_server.js 更正为 server.js
- 更新 tests/CLAUDE.md 中 Jest 版本为 30.3.0
- 移除 src/simyo/MODULE_ARCHITECTURE.md 中过时的重构计划
- 精简 docs/reference/ 下的技术文档,移除与根 README 重复的内容
- 删除已弃用的 .serena/ 工具目录
- 更新根 CLAUDE.md 反映清理后的新目录结构
- 删除 3 个引用已删除模块的测试文件
所有测试通过,构建成功,质量检查和安全检查均通过。
|
2026-05-18 21:58:42 +08:00 |
|
Abner
|
c3926b14eb
|
📝 docs: 修正误导性描述,明确工具仅支持已有用户 eSIM 设备更换
|
2026-05-17 21:57:13 +08:00 |
|
Abner
|
b5ec8eb18a
|
🐛 fix: 修复受限环境下 secure-storage 触发 sessionStorage SecurityError
- 新增 safeGetStorage 探测能力探针,捕获 sessionStorage/localStorage 读取与写入探测时抛出的 SecurityError,返回可用的 Storage 或 null
- 将顶层敏感数据迁移逻辑外层包裹 try-catch,避免 iframe/sandbox/隐私设置等受限上下文导致模块初始化阶段未捕获异常中断
- 在 migrateFromLocalStorage 中基于 safeGetStorage 动态获取 localStorage,localStorage 不可用时直接跳过迁移而非抛错
- 补充受限环境降级单元测试:模拟 sessionStorage/localStorage 属性读取被拒、以及 sessionStorage 写入失败时确保降级到 fallbackStorage 且不抛异常
|
2026-05-08 18:33:59 +08:00 |
|
Abner
|
a1628aa33a
|
🐛 fix(security): 修复全部 76 个 CodeQL 安全扫描告警
修复 GitHub 代码扫描发现的所有安全问题,涵盖 20 个文件、76 个告警:
- Actions 工作流:添加 Fork 仓库限制、来源验证、persist-credentials: false、移除 npm cache
- 明文存储:localStorage 迁移到 secureStorage (sessionStorage + TTL)
- 日志注入:新增 sanitizeLog() 过滤换行符,覆盖全部 console.log 调用
- SSRF:新增 isAllowedTarget() 域名白名单校验
- SRI 完整性:为 Bootstrap/Font Awesome/GTM 添加 integrity + crossorigin
- XSS 防护:错误消息 HTML 转义、Service Worker origin 验证
- URL 清洗:hostname.includes() 替换为精确域名匹配
- HTML 过滤:扩展标签黑名单、添加事件属性过滤
- 限流:全局引入 createRateLimiter (200 req/min/IP)
|
2026-05-06 21:46:25 +08:00 |
|
Abner
|
9ed51287c0
|
✅ test: 新增多个核心模块的单元测试并优化 Jest 配置
- 在 `jest.config.js` 中启用 V8 覆盖率提供器(兼容 Node.js 22+),提升覆盖率检测性能与准确性
- 调整覆盖率收集范围为 `src/js/modules/**/*.js`,排除测试文件,使报告更聚焦于实际业务逻辑
- 降低全局覆盖率阈值至当前可达成水平(statements/branches 30%-70%),制定逐步提升计划
- 新增 6 个模块的完整单元测试:`APIService`、`AppConfig`、`HTMLSanitizer`、`Logger`、`SecureStorage` 和 `utils`,总计约 840 行测试代码
- 修复 `HTMLSanitizer.sanitizeURL()` 中对 `data:text/html` 协议的正则检测逻辑,增强 XSS 防护能力
|
2026-05-05 10:35:14 +08:00 |
|
Abner
|
8f9bd3a6be
|
📝 docs: 新增模块化文档文件并更新主文档索引
- 新增 `src/js/modules/CLAUDE.md`,详细描述通用工具模块的职责、接口和使用方式
- 新增 `netlify/functions/CLAUDE.md`,系统化说明 11 个 Serverless 函数的功能和中间件架构
- 新增 `netlify/edge-functions/CLAUDE.md`,明确 BFF 代理层的验证码校验规则和转发流程
- 新增 `scripts/CLAUDE.md`,梳理 22 个构建和质量检查脚本的用途和执行命令
- 新增 `tests/CLAUDE.md`,说明 Jest 测试框架配置、覆盖率要求和各模块测试文件
- 更新根目录 `CLAUDE.md`,精简内容并添加模块结构图和详细索引导航
|
2026-04-28 20:14:59 +08:00 |
|
Abner
|
7fd54dde39
|
♻️ refactor: 修复安全漏洞并优化架构债务
安全修复:
- 修复 dom.js 和 simyo/app.js 中的 innerHTML XSS 注入风险
- 使用 HTMLSanitizer.escapeHtml/escapeAttr 替代直接模板拼接
- 将 onclick 内联事件替换为 data-* 属性 + addEventListener
- 移除 server.js 中硬编码的 Simyo X-Client-Token
架构优化:
- 新增 _shared/rate-limiter.js 分布式限流模块 (Netlify Blobs)
- verify-cookie.js 内存限流替换为 KV 跨实例共享方案
- giffgaff/utils.js debounce/throttle 改为委托共享实现
- simyo/app.js 会话存储迁移至 SecureStorage (自动 TTL 过期)
- 合并 notifications-internal.js 至 notifications.js 消除双维护路径
|
2026-04-25 16:30:19 +08:00 |
|
Abner
|
6282507d12
|
♻️ refactor(simyo): 移除模块化流程的 sendSmsCode 路径
|
2026-04-18 22:25:45 +08:00 |
|
Abner
|
f7151c9283
|
♻️ refactor: 优化设备更换验证码流程并添加相关测试
- 修改中英文帮助文档,将“获取或接收验证码”调整为更准确的“发送与接收验证码”
- 简化 `device-change-handler.js` 中的验证码发送逻辑,移除冗余的错误处理,统一回退机制
- 当新版流程仅支持邮箱验证时,即使短信接口不可用也返回成功提示,提升用户体验
- 新增 `device-change-handler.test.js` 测试文件,覆盖 `applyNewEsim`、`verifyCode` 和 `sendSmsCode` 方法的正常与异常场景
- 新增 `simyo-app-device-change.test.js` 测试文件,验证主流程中设备更换的自动化操作和UI交互逻辑
|
2026-04-18 22:08:35 +08:00 |
|
Abner
|
a1fa26dc40
|
🔧 chore(hooks): 提交前同步远程并静默无效URL测试日志
|
2026-04-18 00:36:30 +08:00 |
|
Abner
|
2b8f293506
|
chore: 更新 Simyo 客户端版本和用户代理字符串
* 将所有 Simyo 相关配置中的客户端版本从 4.8.0 更新为 4.23.5。
* 将默认的用户代理字符串更新为反映 MijnSimyoFT/4.23.5 (iOS 26.3; iPhone16,1)。
* 确保代理服务器和 API 配置与最新的 Simyo 客户端版本保持一致,以模拟最新的客户端行为。
* 更新了测试文件中的对应值,以确保测试环境使用最新的客户端信息。
|
2026-01-12 19:14:43 +08:00 |
|
Abner
|
1f48e0fd9e
|
fix(simyo): close help removes overlay
|
2025-12-31 11:29:37 +08:00 |
|
Abner
|
dd27453c97
|
feat(qrcode): 更新二维码生成供应商并调整相关配置
- 将二维码生成供应商从 api.qrserver.com 更新为 qrcode.show
- 更新了相关文档、代码和测试中的二维码生成 URL
- 调整了内容安全策略(CSP)以允许新的二维码生成 URL
- 更新了 webpack 配置,为新的二维码生成 URL 添加缓存策略
|
2025-08-11 21:41:54 +08:00 |
|
Abner
|
ee034d3cb9
|
feat(giffgaff): 支持 PKCE 公有客户端和机密客户端的 OAuth 令牌交换
- 新增 giffgaff-token-exchange.js 函数处理 OAuth 令牌交换
- 增加对 PKCE 公有客户端和机密客户端的支持
- 优化令牌交换流程,支持可选的 Basic 认证
- 更新前端和后端的 OAuth 配置
|
2025-08-10 19:23:20 +08:00 |
|
Abner
|
f97d8339e4
|
feat(auth): 增加 OAuth 2.0 PKCE 令牌交换功能
- 新增 giffgaff-token-exchange.js 函数,用于交换 authorization code 和 access token
- 更新 verify-cookie.js 函数,增加对 cookie 中 access token 的提取和验证
- 修改 giffgaff-graphql.js、giffgaff-mfa-challenge.js 和 giffgaff-mfa-validation.js 函数,支持使用 access token 或 cookie 进行身份验证
- 更新 README.md 和 COOKIE_LOGIN_SETUP.md 文档,说明新的身份验证流程和安全注意事项
|
2025-08-09 14:39:29 +08:00 |
|
Abner
|
e1e6f3ec58
|
fix(giffgaff): 优化服务时间判断逻辑
- 重新定义服务不可用时间范围:04:30-12:30
- 改进时间判断逻辑,提高准确性和可读性
- 增加边界情况测试,确保时间判断的精确性
- 用户报告晚上10:40无法使用,修正后应恢复正常
|
2025-08-07 22:48:32 +08:00 |
|