You asked for all local code to be committed before the broader telemetry-removal pass. This commit snapshots the current bridge/session ingress changes together with the local audit documents so the next cleanup can proceed from a stable rollback point. Constraint: Preserve the exact local worktree state before the telemetry-removal refactor begins Constraint: Avoid mixing this baseline snapshot with the upcoming telemetry deletions Rejected: Fold these staged changes into the telemetry-removal commit | Would blur the before/after boundary and make rollback harder Confidence: medium Scope-risk: moderate Reversibility: clean Directive: Treat this commit as the pre-removal checkpoint when reviewing later telemetry cleanup diffs Tested: Not run (baseline snapshot commit requested before the next cleanup pass) Not-tested: Runtime, build, and typecheck for the staged bridge/session changes
15 KiB
free-code-main 本地系统信息外发移除实现报告
- 分析时间: 2026-04-03
- 对照文档:
docs/local-system-info-egress-audit.md - 分析对象:
/Users/yovinchen/Downloads/free-code-main - 对照基线:
/Users/yovinchen/project/claude - 分析方式: 静态代码审计 + 关键链路比对 + 同名文件差异核查
- 说明: 本报告只基于源码静态分析,不包含运行时抓包或服务端验证。
结论摘要
结论是: free-code-main 只“部分移除”了审计文档里的本地系统信息外发链路。
更准确地说,它做的是:
-
把 telemetry / analytics / OTel 相关外发出口失活了
- Datadog
- Anthropic 1P event logging
- OTel 事件与 metrics/tracing 初始化
- GrowthBook 远程评估链路也被间接短路
-
但没有把“所有本地信息外发”都移除
- 模型请求里的环境/项目上下文注入仍在
- Feedback 上传仍在
- Transcript Share 仍在
- Remote Control / Bridge 上传
hostname、目录、分支、git remote URL 的链路仍在 - Trusted Device 注册仍在
/insights的 ant-only 上传逻辑仍在
-
移除方式不是“彻底删代码”,而是“保留兼容接口 + 启动链路短路 + sink/no-op stub 化”
- 这意味着仓库里仍然保留了不少采集/导出代码。
- 但默认运行时,关键出口函数已经被改成空实现,导致这些链路无法真正发出请求。
因此,如果问题是:
free-code-main是否已经把docs/local-system-info-egress-audit.md中描述的“本地系统信息外发”整体移除?
答案是:
没有整体移除,只移除了其中“遥测/观测”这一类外发;产品主链路里的上下文外发和若干用户触发上传链路仍然存在。
对照矩阵
| 审计项 | free-code-main 状态 |
结论 |
|---|---|---|
| F1 模型请求 system prompt / user context | 未移除 | 默认仍会把 cwd、git 状态、CLAUDE.md、日期,以及 prompts 里的平台/壳层/OS 版本注入到模型请求 |
| F2 Datadog analytics | 已移除 | Datadog 初始化与上报函数被 stub 成 no-op |
| F3 Anthropic 1P event logging | 已移除 | 1P logger 整体改为空实现,启用判断恒为 false |
| F4 GrowthBook remote eval | 实际已失活 | 依赖 is1PEventLoggingEnabled(),而 1P 已被硬关,默认不会创建 GrowthBook client |
| F5 Feedback | 未移除 | 用户触发后仍会 POST 到 claude_cli_feedback |
| F6 Transcript Share | 未移除 | 用户触发后仍会 POST 到 claude_code_shared_session_transcripts |
| F7 Remote Control / Bridge | 未移除 | 仍会采集并上送 hostname、目录、分支、git remote URL |
| F8 Trusted Device | 未移除 | 仍会注册 Claude Code on <hostname> · <platform> |
| F9 OpenTelemetry | 已移除 | telemetry 初始化与 logOTelEvent() 都被改成 no-op |
F10 /insights 内部上传 |
未移除 | ant-only S3 上传逻辑仍保留 |
关键判断
这次比对里最重要的判断有两个:
README.md里的 “Telemetry removed” 只覆盖了“遥测/观测”语义,不等于“所有本地信息外发已删除”。free-code-main的移除策略主要是“切断出口”,而不是“删除所有采集代码”。
这也是为什么你会看到:
src/services/analytics/metadata.ts这类环境信息构造代码还在src/utils/api.ts里上下文统计代码还在src/services/analytics/firstPartyEventLoggingExporter.ts、src/utils/telemetry/bigqueryExporter.ts这类导出器文件也还在
但是:
- 事件 sink
- telemetry bootstrap
- OTel event logging
- Datadog / 1P logger 初始化
都已经被改成空实现或被前置条件短路掉了。
已移除部分: 实现方式分析
1. Analytics 公共入口被改成 compatibility boundary + no-op
/Users/yovinchen/Downloads/free-code-main/src/services/analytics/index.ts:4-40 明确写到:
- “open build intentionally ships without product telemetry”
- 保留模块只是为了不改动现有调用点
attachAnalyticsSink()、logEvent()、logEventAsync()都是空实现
这意味着:
- 各业务模块里仍然可以继续
import { logEvent } - 但这些调用不会再入队、不会再挂 sink、也不会再向任何后端发送
对照 /Users/yovinchen/project/claude/src/services/analytics/index.ts,当前工作区版本还保留:
- 事件队列
attachAnalyticsSink()的真实绑定logEvent()/logEventAsync()的真实分发
所以这里是非常明确的“出口 stub 化”。
2. Datadog 被直接 stub 掉
/Users/yovinchen/Downloads/free-code-main/src/services/analytics/datadog.ts:1-12 中:
initializeDatadog()直接返回falseshutdownDatadog()空实现trackDatadogEvent()空实现
而对照 /Users/yovinchen/project/claude/src/services/analytics/datadog.ts:12-140,基线版本仍然保留:
- Datadog endpoint
- 批量缓冲
axios.post(...)
因此 F2 可以判定为已移除。
3. 1P event logging 被整体空实现
/Users/yovinchen/Downloads/free-code-main/src/services/analytics/firstPartyEventLogger.ts:1-48 中:
is1PEventLoggingEnabled()恒为falselogEventTo1P()空实现initialize1PEventLogging()空实现reinitialize1PEventLoggingIfConfigChanged()空实现
这和基线 /Users/yovinchen/project/claude/src/services/analytics/firstPartyEventLogger.ts:141-220 中真实存在的:
getEventMetadata(...)getCoreUserData(true)- OTel logger emit
形成了直接对照。
需要注意的是:
src/services/analytics/firstPartyEventLoggingExporter.ts文件仍然存在- 里面仍保留
/api/event_logging/batch的完整实现
但由于 logger 初始化入口已经空了,这个 exporter 在默认路径上已经不会被接上。
因此 F3 的移除方式属于:
保留 exporter 源码,但把“上游 logger/provider 初始化”整体切断。
4. Analytics sink 初始化被清空,启动调用点保留
/Users/yovinchen/Downloads/free-code-main/src/services/analytics/sink.ts:1-10 中:
initializeAnalyticsGates()空实现initializeAnalyticsSink()空实现
但启动链路并没有删调用点:
/Users/yovinchen/Downloads/free-code-main/src/main.tsx:83-86,416-417仍然 import 并调用initializeAnalyticsGates()/Users/yovinchen/Downloads/free-code-main/src/setup.ts:371仍然调用initSinks()
这说明作者的思路不是“到处改业务调用点”,而是:
保留启动顺序与依赖图,统一在 sink 层面把行为变空。
5. OTel 初始化被显式短路
/Users/yovinchen/Downloads/free-code-main/src/entrypoints/init.ts:207-212 直接把:
initializeTelemetryAfterTrust()
改成了立即 return。
同时:
/Users/yovinchen/Downloads/free-code-main/src/utils/telemetry/instrumentation.ts:1-24bootstrapTelemetry()空实现isTelemetryEnabled()恒为falseinitializeTelemetry()返回nullflushTelemetry()空实现
/Users/yovinchen/Downloads/free-code-main/src/utils/telemetry/events.ts:1-12logOTelEvent()空实现- 用户 prompt 内容默认只会被
redactIfDisabled()处理成<REDACTED>
而调用点仍保留:
/Users/yovinchen/Downloads/free-code-main/src/main.tsx:2595-2597仍会调用initializeTelemetryAfterTrust()- 多个业务模块仍会调用
logOTelEvent(...)
所以 F9 的移除方式也是:
不删调用点,只把 telemetry bootstrap 和 event emit 统一改成 no-op。
6. GrowthBook 不是“彻底删文件”,而是被前置条件短路
/Users/yovinchen/Downloads/free-code-main/src/services/analytics/growthbook.ts:420-425:
isGrowthBookEnabled()直接返回is1PEventLoggingEnabled()
而 1P 在 firstPartyEventLogger.ts:26-27 中已经被硬编码为 false。
继续往下看:
growthbook.ts:490-493在 client 创建前就会因为!isGrowthBookEnabled()返回nullgrowthbook.ts:685-691、748-750会在取 feature value 时直接返回默认值
这意味着从当前源码推断:
- 默认路径不会创建 GrowthBook client
- 默认路径不会执行 remote eval 网络请求
- 默认路径不会把
deviceID/sessionId/platform/org/email发出去
所以 F4 应该判定为:
远程评估外发链路实际上已失活。
这里有一个值得单独记录的点:
README.md:58-64写的是 “GrowthBook feature flag evaluation still works locally but does not report back”- 但从当前代码看,更准确的说法应该是:
- 默认的远程评估链路已经被短路
- 留下的是兼容性结构和本地 override/cache 框架
这条判断是基于源码的推断。
7. 本地采集代码仍有残留,但最终不会出网
这部分很关键,容易误判。
free-code-main 不是把所有采集逻辑都删掉了。典型例子:
/Users/yovinchen/Downloads/free-code-main/src/services/analytics/metadata.ts:574-740- 仍会构造
platform、arch、nodeVersion、terminal、Linux distro、process.memoryUsage()、process.cpuUsage()、repo remote hash 等元数据
- 仍会构造
/Users/yovinchen/Downloads/free-code-main/src/utils/api.ts:479-562- 仍会收集
gitStatusSize、claudeMdSize、项目文件数、MCP tool 数量 - 最后仍调用
logEvent('tengu_context_size', ...)
- 仍会收集
/Users/yovinchen/Downloads/free-code-main/src/main.tsx:2521-2522- 启动时仍会执行
logContextMetrics(...)
- 启动时仍会执行
但由于 src/services/analytics/index.ts:28-38 中 logEvent() 已经是空实现,这些数据虽然可能仍在本地被计算,但不会从该链路继续发出。
所以更准确的评价是:
移除的是 egress,不是所有 collection 语句。
未移除部分: 逐项核对
F1. 默认模型请求上下文外发未移除
这部分在 free-code-main 里仍然存在,而且关键文件与基线高度一致。
直接证据:
/Users/yovinchen/Downloads/free-code-main/src/constants/prompts.ts:606-648computeEnvInfo()仍拼接:Working directoryIs directory a git repoPlatformShellOS Version
/Users/yovinchen/Downloads/free-code-main/src/constants/prompts.ts:651-709computeSimpleEnvInfo()仍拼接:Primary working directoryPlatformShellOS Version
/Users/yovinchen/Downloads/free-code-main/src/context.ts:36-109getGitStatus()仍读取:- 当前分支
- 默认分支
git status --short- 最近 5 条提交
git config user.name
/Users/yovinchen/Downloads/free-code-main/src/context.ts:116-149getSystemContext()仍把gitStatus放入上下文
/Users/yovinchen/Downloads/free-code-main/src/context.ts:155-187getUserContext()仍把CLAUDE.md内容和日期放入上下文
/Users/yovinchen/Downloads/free-code-main/src/utils/api.ts:437-474appendSystemContext()/prependUserContext()仍会把这些内容拼进消息
/Users/yovinchen/Downloads/free-code-main/src/query.ts:449-451,659-661- 查询时仍将这些上下文交给模型调用
/Users/yovinchen/Downloads/free-code-main/src/services/api/claude.ts:1822-1832- 最终仍通过
anthropic.beta.messages.create(...)发送
- 最终仍通过
补充比对:
src/constants/prompts.tssrc/context.tssrc/utils/api.tssrc/query.ts
与基线仓库对应文件比对时,未看到针对这条链路的“移除性改造”。
因此 F1 在 free-code-main 中没有被移除。
F5. Feedback 上传未移除
/Users/yovinchen/Downloads/free-code-main/src/components/Feedback.tsx:523-550 仍会在用户触发时:
- 刷新 OAuth
- 取 auth headers
- POST 到
https://api.anthropic.com/api/claude_cli_feedback
这个文件与基线对应文件比对无差异。
因此 F5 未移除。
F6. Transcript Share 上传未移除
/Users/yovinchen/Downloads/free-code-main/src/components/FeedbackSurvey/submitTranscriptShare.ts:37-94 仍会收集:
platformtranscriptsubagentTranscriptsrawTranscriptJsonl
并 POST 到:
https://api.anthropic.com/api/claude_code_shared_session_transcripts
这个文件与基线对应文件比对无差异。
因此 F6 未移除。
F7. Remote Control / Bridge 未移除
/Users/yovinchen/Downloads/free-code-main/src/bridge/bridgeMain.ts:2340-2435 仍会采集:
branchgitRepoUrlmachineName = hostname()dir
随后:
/Users/yovinchen/Downloads/free-code-main/src/bridge/bridgeApi.ts:142-178
仍会把这些字段 POST 到:
/v1/environments/bridge
上传体中明确包含:
machine_namedirectorybranchgit_repo_url
src/bridge/bridgeApi.ts 与基线对应文件比对无差异。
因此 F7 未移除。
F8. Trusted Device 未移除
/Users/yovinchen/Downloads/free-code-main/src/bridge/trustedDevice.ts:142-159 仍会向:
${baseUrl}/api/auth/trusted_devices
提交:
display_name: Claude Code on ${hostname()} · ${process.platform}
这条链路虽然会受 isEssentialTrafficOnly() 影响,但代码并未被删除。
src/bridge/trustedDevice.ts 与基线对应文件比对无差异。
因此 F8 未移除。
F10. /insights ant-only 上传未移除
/Users/yovinchen/Downloads/free-code-main/src/commands/insights.ts:3075-3098 仍保留:
process.env.USER_TYPE === 'ant'分支- 使用
ff cp上传 HTML report 到 S3
这条链路不是默认外部版路径,但它在源码里仍然存在。
因此 F10 未移除。
与基线仓库的“未改动区域”总结
以下文件经对比未看到差异,说明 free-code-main 没有在这些链路上做“移除”改造:
src/constants/prompts.tssrc/context.tssrc/utils/api.tssrc/query.tssrc/components/Feedback.tsxsrc/components/FeedbackSurvey/submitTranscriptShare.tssrc/bridge/bridgeApi.tssrc/bridge/trustedDevice.tssrc/commands/insights.ts
这也是为什么报告结论是“部分移除”,而不是“整体移除”。
最终结论
如果把 docs/local-system-info-egress-audit.md 中的链路拆开看,free-code-main 的状态可以总结为:
-
遥测类默认外发
- Datadog: 已移除
- 1P event logging: 已移除
- OTel: 已移除
- GrowthBook remote eval: 默认已失活
-
产品主链路或用户触发上传
- 模型 system/user context 外发: 未移除
- Feedback: 未移除
- Transcript Share: 未移除
- Remote Control / Bridge: 未移除
- Trusted Device: 未移除
/insightsant-only 上传: 未移除
因此,free-code-main 的真实定位更适合表述为:
它移除了“遥测/观测型外发实现”,但没有移除“产品功能本身依赖的本地信息外发”。
如果后续目标是做“彻底版本地信息外发移除”,还需要继续处理至少这些区域:
src/constants/prompts.tssrc/context.tssrc/utils/api.tssrc/components/Feedback.tsxsrc/components/FeedbackSurvey/submitTranscriptShare.tssrc/bridge/*src/commands/insights.ts