Commit Graph

79 Commits

Author SHA1 Message Date
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
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
49dac32a9e Merge pull request #65 from Silentely/fix/bff-security-hardening
fix(auth): harden BFF routing and preserve internal calls
2026-06-02 22:22:48 +08:00
Abner
be5cd3940b feat: 支持 eSIM 激活流程中 ref 过期自动重发验证码
- 在 `giffgaff-mfa-validation.js` 中将 400 错误细分为 ref 过期(返回 410)和验证码错误(返回 400),通过正则匹配 `error`/`message`/`error_description` 字段识别 ref 过期场景
- 在 `esim-service.js` 的 `smsActivateFlow` 方法中捕获 410 错误后自动调用 `mfaHandler.sendSimSwapMFAChallenge()` 重新发送验证码,并抛出 `REF_REFRESHED_NEEDS_NEW_CODE` 错误码供 UI 层识别
- 在 `giffgaff-app.js` 的错误处理分支中新增对 `REF_REFRESHED_NEEDS_NEW_CODE` 的判断,清空验证码输入框并自动聚焦,引导用户输入新收到的验证码
- 在 `i18n-data.js` 的中英文翻译文件中分别添加 `giffgaff.esim.log.refExpiredRetrying` 和 `giffgaff.esim.errors.refExpired` 日志与错误提示文案
- `validateMFACodeForSwap` 方法在错误中附加 `statusCode` 字段,使上层能够根据状态码区分不同错误类型并执行对应恢复策略
2026-06-02 00:26:46 +08:00
Abner
d9dfc73986 📝 docs: 全面更新和完善项目文档内容
- 简化 README.md 的标题和章节样式,移除冗余 emoji 图标,添加原生 ES6 模块架构说明,调整描述文字使其更简洁清晰
- 优化了四个语言版本的 QR Code API 文档(中英文 Giffgaff 和 Simyo),将原来的简单描述更新为详细的三级回退链说明,包含每个服务商的 5 超时机制和 LPA 字符串降级方案
- 在 docs/ARCHITECTURE.md 中新增模块依赖关系图和关键设计决策说明,补充 BFF 模式、无框架设计、中间件统一等架构要点
- 将英文用户指南中的视频和提示信息移至附录章节,改进文档阅读体验;删除中英文用户指南顶部的视频占位内容
- 修正 CORS_SOLUTION.md 中的脚本路径引用,添加 `scripts/` 前缀使其与实际文件结构一致
- 清理 SECURITY.md 中重复的 CSP 说明,精简为单条以 server.js 为基准的说明;在通知系统文档顶部增加快速摘要说明;在 CLAUDE.md 中补充缺失的 `cors.js` 相关文件引用
2026-06-02 00:03:12 +08:00
Abner
4ba791b660 🔧 chore: 优化 Cookie 验证分支逻辑并补充跨文件 CORS 注释
- 重构 `cookieHandler.checkResult` 的条件分支,将"验证通过但未拿到 JWT"的场景从模糊的 `!result.valid` 升级为更精确的 `result.success && !result.valid`,使三类结果路径语义更清晰
- 为三个分支各自添加中文注释,分别标注"完全成功"、"部分成功"和"硬错误,不可继续",提升代码可维护性
- 在 `bff-proxy.js` 顶部新增注释说明该文件运行在 Deno 环境,无法直接引用 Node.js 的 `_shared/cors.js`,并提醒需与 `netlify/functions/_shared/cors.js` 的 `parseOrigins` 保持同步
2026-05-31 21:46:01 +08:00
Abner
33b8e20440 ♻️ refactor: 抽取内部请求头构建并规范 Cookie 验证返回语义
- 新增共享模块 netlify/functions/_shared/internal-headers.js,集中构建内部函数互调请求头,统一 ACCESS_KEY 未配置时的 500 抛错逻辑
- 更新 giffgaff-graphql.js / giffgaff-mfa-challenge.js / giffgaff-mfa-validation.js,移除各自重复的 getInternalHeaders 实现,改为复用 getInternalHeaders
- 调整 verify-cookie.js 返回语义:以 success 表示 HTTP 层请求是否成功、以 valid 表示是否具备可用于后续 API 的 JWT 令牌
- 修正 verify-cookie.js 错误提示文案中的乱码问题,确保提示“无法通过Cookie获取访问令牌”表述正确
2026-05-31 20:30:31 +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
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
11ba72663a ♻️ refactor: 优化 CORS 处理和 API 响应解析逻辑
- 将 `createHeaders` 默认参数从固定 `ALLOWED_ORIGIN` 改为 `null`,改为由 `resolveCorsOrigin` 函数动态解析来源,统一 CORS 处理入口
- 为 `parseOrigins`、`isAllowedOrigin`、`resolveCorsOrigin` 三个 CORS 工具函数添加 JSDoc 类型注释,提高代码可读性和可维护性
- 代理转发时通过展开运算符条件传递 `X-Session-Token` 请求头,避免转发空字符串导致的鉴权问题
- 修复 URL 代理路径截断问题,保留原始查询字符串拼接,确保后端 API 能正确接收所有参数
- 增加对非 JSON 响应内容的处理分支,直接返回文本内容
2026-05-24 21:18:21 +08:00
Abner
61bf73c0a0 ♻️ refactor(cors): 抽取 CORS 共享模块 + 通配符告警 + 响应解析容错
- 新增 _shared/cors.js 统一管理 CORS 解析与校验,消除 middleware/server 重复
- ALLOWED_ORIGIN 含通配符(*)时启动期输出安全警告
- handleApiResponse JSON 解析加 try/catch,处理空体/坏体场景
2026-05-24 20:44:18 +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
ba24c5b949 perf: swapSim 上游 500 错误自动重试并优化 UI/日志行为
- 在 giffgaff-graphql 的 swapSim 调用中,针对上游返回 GraphQL errors 且疑似 500 的场景启用最多 2 次的延迟重试(按 attempt 递增延迟),并对业务校验错误(非 500)保持原有失败处理
- 保留 401 未授权场景下基于 cookie 刷新 access token 的重试逻辑,刷新成功后跳出重试循环并直接返回结果
- UIController 在清空页面状态时额外清理会员信息、隐藏 eSIM 信息展示区并清空结果容器内容,避免残留的动态内容
- 调整会员信息日志输出字段,从 memberId 改为 memberProfile.id;同步将 logger 改为默认导出 export default Logger,避免混用 ESM/CJS 引发的构建解析异常
2026-05-19 15:21:28 +08:00
Abner
9702d04071 🐛 fix(graphql): 正确处理 Giffgaff GraphQL errors 响应
swapSim 等操作中 Giffgaff 返回 HTTP 200 但 GraphQL body 含 errors,
原代码无条件返回 200 导致前端无法区分成功与业务失败。
现在检测 errors 并返回 422 + 透传实际错误消息。
2026-05-19 14:16:40 +08:00
Abner
8559563e39 🔧 chore: 为 BFF 代理和 GraphQL 函数添加调试日志以排查 500 错误
- Edge Function (bff-proxy): 添加请求入口、ACCESS_KEY 检查、body 读取、
  转发目标、fetch 结果等关键节点日志
- Function (giffgaff-graphql): 添加操作名、参数完整性、上游调用状态、
  token 刷新链路等全链路日志
- 修复: fetch 异常时不再向客户端暴露内部错误详情(安全加固)
- 所有日志仅记录布尔态和状态码,不泄露 token/签名等敏感信息
2026-05-19 12:17:46 +08:00
Abner
319c7da15f 📝 docs: 同步文档和日志规范
- Logger.env() 添加 isDev 门禁,生产环境不再打印 UA 信息
- 更新 CLAUDE.md 移除 Turnstile 验证码描述
- 更新 edge-functions/CLAUDE.md 简化 BFF 职责说明
- 更新 functions/CLAUDE.md 移除 turnstileToken 字段
2026-05-18 20:31:06 +08:00
Abner
3148a3564c ♻️ refactor: 移除 Turnstile 验证码、修复 CSP 和 Netlify 构建警告
- 移除 Turnstile 验证码逻辑,仅保留 reCAPTCHA 作为可选 fallback
- 修复 Google Fonts CSP 违规:style-src 添加 fonts.googleapis.com
- 移除 netlify.toml 中 /.netlify/functions/* 无效重定向规则
- 为 Giffgaff 和 Simyo 添加调试日志(环境信息 + 操作步骤)
- 简化 bff-proxy.js,移除验证码校验逻辑
2026-05-18 20:16:34 +08:00
Abner
4e9dc0ae76 🐛 fix: 进行 SIM 交换时向 GraphQL 传递正确的 mfaRef
- 在 giffgaff-graphql 函数的 swap 分支中补齐 graphqlBody.variables.mfaRef,确保后续 GraphQL 调用携带 MFA challenge reference
- 在 giffgaff-sms-activate 中引入 effectiveSwapRef(优先使用 swapRef,否则回退 ref),并将 mfaRef 作为 SwapSim 变量传入以避免空 mfaRef
- 更新 src/giffgaff/js/modules/api-config.js 的 swapSim GraphQL 变更签名,新增 $mfaRef 入参并在 swapSim 请求中透传 mfaRef
- 在 src/giffgaff/js/modules/esim-service.js 的 SwapSim 调用中增加 mfaRef 到 variables,并确保传参与 mfaRef 字段对齐以保证后端校验一致
2026-05-18 19:47:48 +08:00
Abner
909b4c592f feat: 完善 swapSim 接口的 MFA 相关头部处理与校验
- 在 `giffgaff-graphql.js` 中为 `swapSim` 操作显式添加 `X-GG-MFA-REF` 和 `x-gg-mfa-ref` 请求头,提升与上游服务的兼容性
- 当 `isSwap` 为真但缺少 `resolvedMfaRef` 时,抛出明确的 `AuthError` 提示,确保必填参数完整性
- 在 `middleware.js` 的 CORS 配置中新增 `X-MFA-Ref` 和 `X-MFA-Challenge-Ref` 到允许的请求头列表中,支持前端跨域请求
- 保持原有 `mfaRef` 作为 GraphQL 请求体顶层字段的逻辑不变,补充请求头层面的双重保障机制
2026-05-18 19:43:03 +08:00
Abner
5a88dc6af3 🐛 fix: eSIM 交换流程补齐/归一化 MFA ref 并增强校验
- 在 eSIM 交换前对 mfaRef 进行 trim 归一化,按需同时设置 X-MFA-Ref 与 X-MFA-Challenge-Ref,并将 mfaRef 作为 GraphQL 顶层字段传入
- 完整短信激活流程中统一从 MFA 校验结果 ref 或 emailCodeRef 获取并校验 swapMfaRef,缺失时抛出缺少 ref 的本地化错误
- MFA 校验增加对 signature 缺失的保护,成功返回时同时携带 ref 供后续交换步骤使用
- Netlify GraphQL 代理函数解析 X-MFA-Ref / X-MFA-Challenge-Ref 与请求体中的 mfaRef,进行 trim 后优先取体内 ref 并回填到 graphqlBody.mfaRef,确保 schema 需要的顶层字段始终可用
2026-05-18 19:36:28 +08:00
Abner
c2853d2820 🐛 fix: 修复 swapSim 请求 500 错误
- api-config.js: 移除 swapSim mutation 中不存在的 $mfaRef 参数
- esim-service.js: 将 mfaRef 从 GraphQL variables 移至 body 顶层字段
- giffgaff-graphql.js: 转发 mfaRef 至 Giffgaff API(匹配后端 giffgaff-sms-activate 的正确模式)

根因:前端发送了 Giffgaff schema 不接受的 $mfaRef GraphQL 参数,
同时 BFF 函数在构建请求体时丢弃了 mfaRef 顶层字段。
修复后与用户 HAR 中成功的请求格式完全一致。

Fixes #51
2026-05-17 23:58:36 +08:00
Abner
c3926b14eb 📝 docs: 修正误导性描述,明确工具仅支持已有用户 eSIM 设备更换 2026-05-17 21:57:13 +08:00
Abner
643c16f393 🐛 fix: 修复 markdown-negotiation.js 全部 Code Scanning 安全警报
- bad-tag-filter:结束标签正则改用 \b[^>]* 匹配所有变体
- double-escaping:HTML 实体解码改为单次遍历回调,避免 < 双重解码
- incomplete-multi-character-sanitization:标签移除从正则改为逐字符 while 循环扫描,彻底消除 CodeQL 误报
2026-05-11 23:05:56 +08:00
Abner
de35542bc9 🐛 fix: 修正 Simyo QR 码支持描述
- Simyo 官方不支持 QR 码,但本工具可生成 eSIM QR 码
- 更新教程、对比表、FAQ 中的相关描述
2026-05-11 09:20:56 +08:00
Abner
4308c302bb feat: 根据 GEO 报告优化首页内容结构
- 添加设备兼容性说明(Apple/Android 设备列表 + EID 检查方法)
- 添加 Giffgaff/Simyo 分步使用教程
- 添加与官方 App 的对比表格
- 添加地区与时间限制说明(Giffgaff UK 时间窗口、Simyo NL 地区)
- 添加技术术语解释(OAuth、GraphQL、LPA、SM-DP+、MFA、EID)
- 添加 FAQ 常见问题(6 个高频问题)
- 添加安全声明区块(第三方工具风险、建议使用非主力号码)
- 更新 Markdown for Agents 主页内容
2026-05-11 09:19:43 +08:00
Abner
7d6faea4df 🐛 fix(security): 修复 markdown-negotiation Edge Function 的 HTML 清理逻辑
- 修复正则表达式匹配带空格的结束标签(如 </script >)
- 添加 \b 单词边界避免部分匹配
- 修复 HTML 实体解码潜在双重反转义问题
2026-05-11 09:06:36 +08:00
Abner
81dd2ce662 feat: 添加 AI Agent 友好元数据与 Markdown 协商支持
- 新增 robots.txt 生成(含 AI 爬虫规则 GPTBot/ClaudeBot/Content-Signal)
- 新增 sitemap.xml 生成(列出规范 URL)
- 新增 .well-known/api-catalog(RFC 9727 API 目录)
- 新增 .well-known/oauth-protected-resource(RFC 9728)
- 新增 .well-known/mcp/server-card.json(SEP-1649)
- 新增 .well-known/agent-skills/index.json(Agent Skills 发现)
- 新增 Link 响应头指向 agent 发现资源(RFC 8288)
- 新增 markdown-negotiation Edge Function(Accept: text/markdown 协商)
2026-05-11 08:59:39 +08:00
Abner
5ed5bb678b docs: 更新项目文档与安全配置
- 更新 PROJECT_SUMMARY.md,新增 notification-manager.js 和 notification-service.js 模块说明,并将通用工具中的 i18n 移至括号内
- 完善 SECURITY.md,重构 CORS 配置为动态白名单校验并禁用 credentials,增强 CSP 策略并统一生产与本地环境的安全基准说明
- 重写 SERVICE_TIME_CHECK.md,采用模块化三层架构(utils/dom/app),使用 Intl API 处理英国时区与夏令时,支持双时间显示与国际化的同时强化 XSS 防护
- 修订 notification-system.md,明确通知 API 公开接口无需认证,细化安全实践并规范消息转义方式
- 调整 netlify/functions/CLAUDE.md,标注 notifications API 为公开接口(requireAuth: false)
2026-05-03 23:04:19 +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
cc49daa993 🐛 fix: 修复通知 401 错误和 CSP 违规
- middleware withAuth 新增 requireAuth: false 跳过密钥校验
- CSP style-src 添加 fonts.googleapis.com (修复字体加载拦截)
- CSP font-src 添加 fonts.gstatic.com (修复字体资源拦截)
- CSP connect-src 添加 cdn.jsdelivr.net (修复 source map 加载)
- server.js CSP 同步更新与 netlify.toml 保持一致
2026-04-25 16:46:50 +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
1d8e37003c chore: 删除 .gemini-clipboard 文件夹并添加到 .gitignore
- 从 Git 仓库中移除 .gemini-clipboard 临时文件
- 将 .gemini-clipboard/ 添加到 .gitignore 防止未来提交
- 保持仓库整洁,避免临时文件污染
2026-01-22 22:47:35 +08:00
Abner
32a32541c5 fix: 更新 giffgaff OAuth 登录流程以适应外部变更
* 针对 giffgaff OAuth 登录增加了前置条件,要求用户在进行 OAuth 授权前必须先登录 giffgaff 官网。
* 修正了获取回调 URL 的指引,现在引导用户在浏览器控制台中查找报错信息中的回调 URL,而非网络标签页。
* 提供了更详细的控制台报错信息示例,以帮助用户准确复制回调 URL。
* 更新了内部通知系统,添加了关于 giffgaff OAuth 登录方式变更的通知。
* 将原有“OAuth 交换时报错 400 问题”的通知类型从“success”调整为“info”,并设置为非活跃。
2026-01-22 22:43:48 +08:00
Abner
f71b50e498 refactor: 简化设备更换流程,移除设备更换选项页面
重构了Simyo应用的设备更换流程,主要变更包括:

- 移除了设备更换选项选择页面,简化用户操作流程
- 直接展示设备更换步骤,提升用户体验
- 删除了相关的UI控制器方法和事件绑定
- 更新了应用状态恢复逻辑,自动进入设备更换流程
- 添加了新的通知消息,提示Simyo端点更新

此次重构减少了用户操作步骤,使设备更换流程更加直观和高效。
2026-01-13 12:39:39 +08:00
Abner
a2dae5413f refactor: 移除多余的 Simyo eSIM 设备更换功能
* 删除了用于申请新 eSIM、发送短信验证码和验证验证码的 Netlify 函数。
* 清理了 `netlify.toml` 中与这些已删除函数相关的特定重定向规则。
* 简化了架构,这些函数主要返回静态提示信息,现在已不再需要,仅依赖通用的 Simyo API 代理。
* 降低了代码库的复杂性和维护开销。
2026-01-12 21:33:23 +08:00
Abner
82710d880e feat: 添加 Simyo eSIM 设备更换相关端点和函数
*   实现了三个新的 Netlify 函数:`simyo-apply-new-esim`、`simyo-send-sms-code` 和 `simyo-verify-code`,以支持 Simyo eSIM 设备更换流程。
*   `simyo-apply-new-esim` 函数旨在指导用户在 Simyo APP 中完成初始的 eSIM 申请步骤,然后返回工具继续操作。
*   `simyo-send-sms-code` 函数模拟发送短信验证码,并提示用户下一步输入验证码。
*   `simyo-verify-code` 函数用于验证用户输入的 6 位数字验证码,确保其格式正确。
*   更新了 `netlify.toml` 配置,为这些新的 Simyo eSIM 相关功能添加了特定的重定向规则,确保请求正确路由到相应的 Netlify 函数。
*   将这些特定重定向规则置于通用 Simyo API 代理规则之前,以保证优先匹配。
2026-01-12 21:04:32 +08:00
Abner
0d99f1f600 feat: 集成 Sentry 错误监控系统
前端监控 (src/js/modules/sentry-init.js):
- 使用 @sentry/browser SDK v10+ 和 browserTracingIntegration()
- 智能环境检测,开发环境自动禁用
- 敏感数据过滤 (authKey, token, password, cookie)
- 性能追踪采样率 10%

后端监控 (netlify/functions/_shared/sentry.js):
- 使用 @sentry/node 用于 Netlify Functions
- 仅上报 5xx 服务端错误,节省配额
- Serverless 环境 flush() 确保错误发送

构建集成 (webpack.config.js):
- @sentry/webpack-plugin 自动上传 Source Maps
- 自动使用 Netlify COMMIT_REF 作为 release 版本
- 上传后自动删除本地 source maps

环境变量:
- SENTRY_DSN: 错误上报端点
- SENTRY_AUTH_TOKEN: Source Maps 上传认证
- SENTRY_ORG / SENTRY_PROJECT: 组织和项目标识
2025-12-13 22:03:02 +08:00
Abner
4987f1a7fe feat: 添加无需认证的内部通知API并更新前端调用
新增无需认证的内部通知API函数,提供系统状态和功能更新通知服务
- 创建 notifications-internal.js Netlify 函数,支持获取活跃通知及最新通知
- 实现CORS支持,允许指定来源的前端直接调用
- 包含预置通知数据,支持优先级排序和活跃状态过滤
- 更新前端 notification-service 模块以使用新的内部API端点
- 提供错误处理和日志记录机制确保服务稳定性
2025-11-30 19:07:37 +08:00
Abner
abf9063b20 docs: 添加通知系统使用指南和完整实现文档
- 新增详细的通知系统使用指南,涵盖架构设计、快速开始、后端配置和故障排查
- 添加通知管理器组件,支持 success、warning、error、info 四种通知类型
- 实现通知服务,支持自动轮询和已读状态管理
- 创建 Netlify Functions 通知 API,提供通知消息查询接口
- 集成通知系统到主页面,在DOM加载完成后自动初始化
- 提供完整的样式系统,包含响应式设计和无障碍访问支持
2025-11-30 18:43:38 +08:00
Abner
188d4af85a feat: 实现多提供商验证码系统,支持 Cloudflare Turnstile 和 Google reCAPTCHA
- 新增 CaptchaManager 类,统一管理 Turnstile 和 reCAPTCHA 验证码的初始化和 token 管理
- 扩展 BFF 代理支持多验证码提供商,根据配置自动切换验证逻辑
- 新增公共配置端点,动态下发验证码提供商配置到前端
- 重构 API 管理器,统一处理验证码 token 的头部和载荷注入
- 更新 CSP 策略,支持两种验证码服务的域名和资源
- 保留原有 Turnstile 功能的同时,支持 reCAPTCHA 作为备选方案
- 提供灵活的配置选项,可通过环境变量控制提供商开关和强制验证
2025-11-24 19:03:43 +08:00
Abner
05318df88a feat: 为 Turnstile 验证添加强制执行控制功能
- 新增 TURNSTILE_ENFORCE 环境变量,可在紧急情况下跳过 BFF Turnstile 验证
- 在 CLAUDE.md 和 env.example 中添加完整的 Turnstile 配置说明
- 修改 BFF 代理逻辑,仅在启用强制执行时进行 Turnstile 验证
- 优化前端 JavaScript 代码,移除冗余的验证状态变量
- 在跳过验证时输出警告日志,便于调试和监控
2025-11-24 17:38:12 +08:00
Abner
4a0fcc94fe feat: 重构Netlify Functions架构并增强代码质量
- 新增统一的中间件模块,提供鉴权、CORS和错误处理功能
- 重构所有Functions使用withAuth中间件简化代码结构
- 添加安全存储模块替代localStorage,防御XSS攻击
- 引入HTML清理工具,自动转义特殊字符和验证URL安全性
- 创建代码质量检查脚本,验证语法、环境变量和依赖完整性
- 添加构建日志工具和重构脚本,统一替换console.log为Logger
- 引入ESLint配置,提升代码质量和一致性
- 重构Giffgaff相关API,统一错误处理和验证逻辑
- 优化构建脚本,添加压缩和图片优化功能
- 新增健康检查端点,用于服务监控和状态报告
2025-11-23 22:20:02 +08:00
Abner
5a29e64ec7 feat: 重构部署流程并移除 Service Worker
- 新增部署工具脚本:添加 `build-static.js`、`deploy-prepare.js`、`deploy-analyze.js` 和 `test-deploy-config.js` 标准化构建部署流程
- 配置 Netlify 发布目录:修改 `netlify.toml` 将 `publish` 从根目录切换到 `dist` 目录以增强安全性
- 移除 Service Worker 相关代码:删除 `sw.js` 并清理相关注册逻辑,简化性能优化策略
- 增强服务器静态文件服务:重构静态资源中间件,增加环境检查和错误处理
- 改进 API 密钥处理逻辑:统一 Netlify Functions 的密钥验证流程,增加配置缺失提示
- 添加 Serena AI 配置文件:包含项目元数据、语言服务器设置和常用命令记忆
- 重构 HTML 页面路由:使用配置化的路由表替代硬编码路径,提高可维护性
2025-11-23 19:44:45 +08:00
Abner
f982bd8649 fix(netlify): 移除多余的 MFA 请求头字段
移除了重复的 MFA 签名和引用请求头,现在只保留必要的 X-MFA-Signature 头。
更新了注释以反映 swapSim 接口只需要签名,不再需要 ref 参数。
2025-10-28 21:35:21 +08:00
Abner
f93a539130 feat(giffgaff-graphql): 更新请求头以使用真实的 iOS App 用户代理和设备信息
调整 GraphQL 请求头配置,使用更真实的 iOS App 用户代理字符串及设备元数据,
包括新增对 simSwapMfaChallenge 操作的支持。同时优化请求头结构以贴近实际客户端行为,
并支持通过环境变量自定义相关字段。

- 将 User-Agent、Accept-Language、Accept-Encoding 等设置为更贴近移动端的值
- 新增对 simSwapMfaChallenge 操作识别并应用 App Headers
- 调整 x-gg-app-* 相关头部为真实 iOS 设备参数
- 引入 baggage 和 x-gg-app-device-id 等新头部字段
2025-10-28 21:21:52 +08:00
Abner
a0167de84c feat(netlify): 支持解析数组格式的GraphQL请求体
当GraphQL请求体为数组时,取第一个元素进行处理;若数组为空,则返回400错误。
同时保持对对象格式请求体的兼容性。
2025-10-27 23:41:43 +08:00
Abner
e20fe9a95c refactor(giffgaff): 优化验证码发送渠道和调试提示
- 在 eSIM 激活页面添加验证码发送渠道选择
- 根据选择的验证码渠道显示不同的提示信息
- 在控制台添加 API 调用的日志记录
- 优化 MFA Challenge 请求的处理逻辑
2025-08-12 00:17:46 +08:00
Abner
9d78e48fe3 fix(esim): 优化 eSIM 激活流程中的 swap 操作
- 在 swapSim 之前增加 simSwapMfaChallenge 步骤,获取专用的 swap ref
- 更新 swapSim 请求,使用新获取的 swap ref 或回退到旧的 ref
- 优化错误处理,确保流程在遇到问题时能够继续进行
2025-08-11 23:08:52 +08:00