Repository Wiki
jason5ng32/MyIP

隐私政策与数据存储边界

MyIP 的隐私边界不是“所有数据都留在浏览器”,而是区分本地设置、即时查询、用户主动发布的报告,以及分析、账户和故障遥测等不同数据流。本页结合隐私政策文案与已核验的初始化、读取和脱敏代码,说明哪些数据会离开设备、由谁处理,以及哪些保留期限仍属于政策层声明。

目的与范围

本页覆盖数据类别、处理方、主动操作与自动处理的区别、存储与保留承诺,以及本地偏好和后端 Sentry 的实现边界。报告生成算法、Persona Check 评分规则、账户鉴权和部署步骤应由各自功能文档展开,本页仅解释其隐私相关接口与影响。

**证据范围:**政策依据是仓库中的隐私政策文案;实现核验限于浏览器启动时的偏好读取、后端 Sentry 初始化及其脱敏函数。报告 KV 写入、自动删除任务、前端遥测中继、分析脚本和账户存储实现未在本页核验,因此下文明确将相关描述标为“政策声明”,不将其视为已经验证的运行保证。

概述:处理、传输与保存是三个不同问题

理解这套政策时,需要分别回答:

  1. **在哪里计算?**工具结果可能在浏览器计算,也可能通过实时查询获得。
  2. **向谁传输?**IP 地理位置查询会将被查询 IP 发送给第三方;Persona Check 会将运行所需数据交给评分服务。
  3. **是否保存?**政策声明通常不在项目服务器保存工具结果,但明确列出主动分享报告、访问计数、账户和遥测等例外。

因此,“不保存诊断结果”不能推导出“无网络传输”“无第三方处理”或“无任何访问记录”。同样,“设置保存在 localStorage”也不等于整个站点不使用 Cookie。政策中的工具说明与存储说明分别定义了这些边界。

架构:已核验的本地读取与后端脱敏

下图只展示实际读取到的代码关系,不把尚未核验的报告服务和遥测中继画成已确认的实现链路。

Loading diagram...

Sources: index.html;sentry-instrument.js;sentry-scrub.js。

这两个局部机制分别解决不同问题:浏览器在首屏绘制前读取主题,避免启动画面与应用主题不一致;后端在遥测发送前替换特定查询参数值,减少上游 API 密钥进入监控系统的风险。二者都不能单独证明整个应用的存储或隐私行为。

数据分类与存储边界

普通诊断、主动分享与评分服务

以下表格整理的是政策声明。对应存储 TTL、删除执行方式和请求载荷仍需在相关服务实现中核验。

场景数据与处理方触发和存储边界
普通工具结果IP 信息、浏览器指纹、DNS、连通性、测速结果浏览器计算或实时查询;除主动创建分享链接外,不在项目服务器保存结果供他人访问
IP 地理位置查询被查询的 IP → ipinfo.io、ip-api.com 等供应商适用供应商自己的隐私政策;项目的不保存声明不约束第三方
分享诊断报告用户选中的测试结果 → Cloudflare Workers KV必须主动创建;可在创建前遮蔽 IP 尾部;保留期可选 1、3、7 天
复制给 AI/下载 JSON报告在浏览器中生成或复制该操作本身不向项目服务器保存内容;不代表用户随后提交给外部 AI 的行为仍在此边界内
In-depth Persona Check时区、语言、固定日期和数字的格式、字体与语音覆盖的文字系统、键盘布局,以及已有 IP/WebRTC/DNS 结果 → 评分服务单次输入和返回报告不保存;主动分享时仅携带等级与各检查结论,不携带背后原始值
Persona Check 可选输入位置及银行卡前 6–8 位位置离开设备前取整至约一公里精度,仅用于推导国家;卡号前缀交由第三方发卡行数据库查询

来源:工具与分享报告、Persona Check。

**分享链接不是身份鉴权。**政策声明链接使用难以猜测的随机 ID、不维护现存报告目录,同时明确“持有链接的任何人”都能在过期前查看。随机性降低枚举风险,却不阻止收件人转发链接;IP 遮蔽是创建前的可选措施,也不能被写成默认启用。分享报告政策未描述提前撤销接口,因此本页不承诺此能力。

访问状态、文档助手与账户

场景政策声明的数据流保留与授权边界
Earth Online 访问计数访问时记录匿名计数及边缘网络根据 IP 推导的国家/地区完整 IP 仅瞬时使用,不保存完整地址
Earth Online 预设状态主动分享后记录状态 ID、国家/地区、遮蔽后的 IP 前缀数日内自动删除;只允许固定状态列表,没有自由文本
文档助手按需加载;提问由浏览器发送给 GitBook对话不经过项目服务器,项目不保存;受 GitBook 条款约束
助手读取当前测试结果IP、位置、网络及已执行的测试结果助手须请求,并由用户在聊天确认按钮中批准;拒绝后仍可回答文档问题
可选登录Firebase Authentication 管理登录并同步成就;收集登录邮箱及高级功能使用次数用于身份识别与防滥用;账户存在期间保留账户数据
防滥用分析日志已登录用户的相关分析记录每个计费/统计周期结束清除分析日志,仅保留总使用次数;文案没有给出周期长度

来源:Earth Online、文档助手、账户与保留期、账户数据保留。

政策声明 Google Analytics 收集 IP 推导的近似位置、浏览器语言、访问页面、设备/浏览器类型、来源站点,以及 Cookie 中随机生成的访客 ID;Google 不向项目提供完整 IP。分析数据按 Google Analytics 设置保留,最长 14 个月。这不是由本页代码验证的本地 TTL。分析政策、保留期。

遥测政策则明确涉及技术错误报告、页面性能、错误发生前的回放,以及经过项目中继时附加到错误报告的 IP,保留 30 天。**不能因为后端配置了 sendDefaultPii: false,就推断整个遥测链路不含 IP。**后端 SDK 默认收集行为与政策所描述的前端中继附加行为是不同边界;本页未读取中继实现,也未验证 30 天删除设置。遥测政策。

政策还说明当前没有 Cookie 同意横幅;用户可使用内容拦截器、Google 官方退出插件、阻止第三方 Cookie 或清除站点 Cookie 等方式退出分析,自托管实例只有在运营者配置后才运行分析。这些是文案中的操作说明,不应当被改写为代码已经实现的完整同意管理系统。Cookie 与退出说明。

本地偏好:启动读取与异常降级

政策将主题、语言、工具偏好定义为仅保存在浏览器本地、不离开设备的设置。已核验的启动代码读取 userPreferences_v7,并将主题应用于 <html>;该片段没有网络调用,但不能据此证明其他模块从不传输偏好。

源码示例:容错读取

javascript
1 window.jnReadPrefs = function () { 2 try { 3 return JSON.parse(localStorage.getItem('userPreferences_v7') || '{}') || {}; 4 } catch (e) { 5 /* malformed entry or storage disabled — fall back to defaults */ 6 return {}; 7 } 8 };

Source: index.html。

读取顺序为:获取字符串 → 缺失时使用空对象 JSON → 解析 → 解析结果为假值时返回空对象。存储访问被禁用或 JSON 损坏时,catch 同样返回空对象。这里没有写回、修复损坏数据或删除旧键的操作,也没有检查结果是否符合偏好对象的结构。

源码示例:首屏主题决策

javascript
1 var theme = window.jnReadPrefs().theme || 'auto'; 2 var isDark = 3 theme === 'dark' || 4 (theme === 'auto' && 5 window.matchMedia && 6 window.matchMedia('(prefers-color-scheme: dark)').matches); 7 if (isDark) document.documentElement.classList.add('dark');

Source: index.html。

theme 缺失或为假值时回退到 auto;只有明确的 dark,或 auto 且系统偏好深色时,才添加 dark 类。这段同步代码位于应用加载之前,目的是让启动屏与后续应用从第一帧保持一致。它只展示初始读取,不包含跨标签页监听、偏好写入、键迁移或清理机制。启动时序说明。

后端遥测:初始化门控与发送前脱敏

启用条件和配置

sentry-instrument.js先加载 dotenv,然后检查环境变量。只有 SENTRY_DSN_BACKEND 为真值,且 SENTRY_ENVIRONMENT 不等于精确字符串 development 时,才动态导入 @sentry/node 并初始化 SDK。未启用时不加载 SDK;源码注释说明该模块通过 Node 的 --import 在 Express 加载前启动,以便注册自动路由追踪所需的钩子。

配置/键类型默认或固定值已核验行为
SENTRY_DSN_BACKEND环境字符串未设置时禁用非空值作为 SDK 的 dsn
SENTRY_ENVIRONMENT环境字符串初始化时回退为 production精确等于 development 时跳过初始化
tracesSampleRate数值固定 1.0后端追踪配置为 100% 采样
enableLogs布尔值固定 true启用 Sentry Logs;日志转发实现未在本页核验
sendDefaultPii布尔值固定 false关闭 SDK 默认 PII 发送,不构成所有载荷均匿名的保证
userPreferences_v7localStorage 键缺失时读取 {}启动代码使用的本地偏好键
theme偏好字段auto启动时识别 auto、light、dark

来源:Sentry 配置、本地读取。

源码示例:四个发送前处理入口

javascript
1 beforeBreadcrumb: scrubBreadcrumb, 2 beforeSendSpan: scrubSpan, 3 beforeSend: scrubEventRequest, 4 beforeSendTransaction: scrubEventRequest,

Source: sentry-instrument.js。

相同的敏感查询参数可能出现在 breadcrumb、span 描述、请求上下文或根 trace 属性中,因此实现并非只清理一个 URL 字段:

  • scrubBreadcrumb 处理 breadcrumb.data 的已知 URL/query 属性。
  • scrubSpan 同时处理 description 和 data。
  • scrubEventRequest 处理 request.url、字符串形式的 request.query_string,以及 contexts.trace.data。
  • 普通错误事件和事务事件共用 scrubEventRequest。
Loading diagram...

Source: sentry-scrub.js。

图中的属性处理按字段存在且为字符串时执行;redactUrlQuery 在找不到问号时直接返回,不调用查询参数处理。

源码示例:敏感参数匹配和替换

javascript
const SENSITIVE_PARAMS = /^(key|api[-_]?key|token|secret|password|auth)$/i;

Source: sentry-scrub.js。

javascript
1export const redactQueryString = (query) => { 2 if (typeof query !== 'string') return query; 3 return query.split('&').map((pair) => { 4 const eq = pair.indexOf('='); 5 if (eq === -1) return pair; 6 const rawName = pair.slice(0, eq); 7 const name = rawName.charAt(0) === '?' ? rawName.slice(1) : rawName; 8 return SENSITIVE_PARAMS.test(name) ? `${rawName}=[redacted]` : pair; 9 }).join('&'); 10};

Source: sentry-scrub.js。

算法按 & 分段,以每段第一个 = 分离名字和值。参数名匹配忽略大小写,覆盖 key、apikey、api-key、api_key、token、secret、password、auth;比较时容忍参数名前面的 ?,输出仍保留原名字,值统一替换成 [redacted]。不匹配的内容原样保留,这是代码注释明确说明的调试上下文取舍,而不是通用匿名化。

内部函数参考

这些是 JavaScript 源码中的实际函数形式,不是 HTTP API。源码未声明静态参数类型或返回类型,下表描述运行时处理。

函数参数与返回行为边界
window.jnReadPrefs = function ()无参数;返回 JSON 解析结果或 {}捕获存储读取和 JSON 解析异常;不验证对象模式
redactQueryString = (query) =>非字符串原样返回;字符串返回清理后的字符串仅匹配列出的参数名;无 = 的片段保持不变
redactUrlQuery = (value) =>非字符串或无 ? 时原样返回保留第一个 ? 之前的全部内容,对后续内容调用 redactQueryString
scrubBreadcrumb = (breadcrumb) =>返回输入 breadcrumb原地修改 data 中已知属性;使用可选链访问数据
scrubSpan = (span) =>假值原样返回;否则返回原 span修改字符串描述及已知属性
scrubEventRequest = (event) =>假值原样返回;否则返回原 event修改请求 URL、字符串 query 和 trace 属性

来源:偏好读取、全部脱敏函数。这些脱敏函数没有显式 throw,也没有内部 try/catch;不能据此承诺对冻结对象、异常 getter 等任意 JavaScript 输入都不会抛异常。

失败模式、边界条件与并发

脱敏不是全字段清洗

根据匹配与字段遍历实现,有以下重要限制:

  • **只匹配完整参数名。**未列出的名称不被清理,也没有对参数名做百分号解码。
  • **IP 不在敏感参数列表中。**查询串中的 IP 参数不会因为这些函数而被自动遮蔽。
  • 路径和主机部分不清理。redactUrlQuery 明确保留第一个问号之前的内容。
  • **没有递归扫描。**仅处理 url、url.full、http.url、http.target、url.query、http.query 及上述显式事件字段。
  • **不清理任意请求体、请求头或日志消息。**这些字段未出现在本页读取的函数中;其他 SDK 机制是否另行清理,未核验。
  • **不是标准 URL 解析器。**实现基于字符串拆分,没有独立处理 URL fragment,也不会规范化参数编码。

因此不能把此机制描述成“自动删除所有密钥和个人信息”。它解决的是已知上游查询参数值泄漏,而不是完整的数据防泄漏系统。

对象修改与并发语义

字符串处理函数返回新字符串;三个 SDK hook 则原地修改对象并返回原引用。源码中没有异步操作、共享可变缓存、锁或重试循环。因此这里不存在需要等待的异步脱敏过程,但同一对象的其他持有者会观察到清理后的字段,不能把这些 hook 当作返回深拷贝的转换函数。实现依据。

本地偏好读取也没有同步多个标签页状态的实现。分享报告多实例一致性、过期读取行为和删除并发控制,在本页证据中未找到实现细节。

运行与扩展注意事项

  1. **分别审查每条数据流。**后端 sendDefaultPii: false、政策中的中继附加 IP、分析 Cookie 和报告 KV 是不同链路,不能用一个配置代表全站隐私状态。
  2. **脱敏不等于删除。**发送前替换参数值,并不落实政策中的 30 天遥测保留或 1/3/7 天报告 TTL;部署审计仍需核对相应服务与供应商设置。
  3. **注意采样成本。**当前后端固定 tracesSampleRate: 1.0;清理在发送前执行,不是降低采样率的机制。字符串查询处理会逐段扫描并构造结果,已知属性遍历使用固定字段列表。初始化与清理逻辑、属性处理。
  4. **新增供应商时复核参数名。**若凭据放入不同 query 名称、路径或请求体,现有规则不会自动覆盖;需要扩展匹配或针对载荷结构增加处理,不能只依赖现有 hook。
  5. **偏好键迁移须考虑启动脚本。**启动代码注释明确要求该键与偏好默认配置中的键保持一致;只改变应用侧存储键可能使启动阶段读不到主题。同步约束。

测试证据与建议验证项

本页未读取测试文件,也未执行测试,不能声称已有自动化覆盖。脱敏模块注释说明这些 helper 被保持为可独立测试的函数,不要求加载 SDK。设计说明。

适合后续验证的项目包括:敏感名字的大小写与连字符变体、开头带 ?、重复参数、非字符串输入、没有等号的片段、未知参数保留、事件字段缺失、原地修改行为,以及 localStorage 不可用和损坏 JSON 的降级。这些是由源码边界导出的测试建议,不是已有测试清单。

相关链接

当前运行上下文未提供其他 Wiki 页面的实际路径,因此这里不构造未经确认的跨页链接。

Sources

(4 files)
frontend/locales/privacy