gwickman/sf-clean-room
GitHub: gwickman/sf-clean-room
一个 AI 驱动的 Salesforce org 只读评估 CLI,在将数据交付给 AI 和自动化工具前对 PII 进行匿名化处理。
Stars: 0 | Forks: 0
# sf-clean-room
[](https://deepwiki.com/gwickman/sf-clean-room)
sf-clean-room 是一个由 AI 操作的只读 Salesforce org 评估 CLI。它将 Salesforce 元数据、选定记录、EventLogFile 数据、技术对象、Security Health Check 结果和代码分析报告导出到本地文件夹中,供受控的下游自动化消费者使用:AI agent、代码分析器、搜索索引器、CI 作业和治理工作流。
该工具专为架构师、顾问、安全审查人员和托管服务团队设计,他们希望在 Salesforce org 中获得 AI 的协助,而不希望让 AI 获取 Salesforce 会话或原始机密数据。敏感元数据在检索前会被排除;记录和事件日志 PII 在处理过程中会被丢弃、哈希或派生;只有在哨兵文件确认运行完成后才会发布输出。
## 使用与责任
该工具降低了风险,但并未完全消除风险。确保符合您的 AI 使用策略、客户协议以及适用的数据保护法,仍然是 AI 和工具使用者的唯一责任。本仓库提供了操作手册和流程来帮助降低此类风险。
sf-clean-room 采用 Apache License 2.0 授权,并在“原样”基础上分发,不提供任何形式的保证或条件。请参阅 [LICENSE](LICENSE) 文件以获取完整条款,包括免责声明和责任限制。
## 何时使用
当您需要对 Salesforce org 进行受控、结构化的读取时,即可使用 sf-clean-room:一次性评估(健康状况、安全性、技术债务)、售前范围界定和估算、持续的治理和托管服务监控、审计和事件处理、文档记录以及跨客户基准测试。
常见用例包括 Salesforce AI org 评估、Salesforce 元数据匿名化、EventLogFile 匿名化、security-health 证据包、技术债务发现、售前 org 发现、托管服务治理快照,以及为代码编写 agent 提供受控的本地上下文。
**评估与建议**
- Org 健康状况检查
- 安全审查
- Well-Architected 审查
- 技术债务记分卡,包含环比趋势
- 自动化整合(Workflow Rule / Process Builder → Flow)
- 数据模型整合(未使用的字段、空对象、数据倾斜)
**赢取与界定工作**
- 对陌生 org 的售前与发现
- 基于证据的估算
- 尽职调查、M&A 以及 org 整合
**运行与治理**
- 持续的治理与标准检查
- 配置漂移和权限蔓延检测
- 托管服务健康监控
- 审计与合规证据包
- 事件取证与 RCA
- 许可证和权限的合理缩减
**了解与赋能**
- Org 文档生成
- 入职与知识转移
- 为代码编写 agent 和 CI 门禁提供上下文
**跨项目组合**
- 跨客户基准测试
相关公开文档:
- [用例](docs/use-cases/salesforce-org-assessment.md)
- [与相邻 Salesforce 工具的比较](docs/comparison.md)
- [Agent 提示词示例](docs/agent-prompts.md)
- [合成示例输出](examples/sample-output/README.md)
## 安装
```
git clone https://github.com/gwickman/sf-clean-room.git
cd sf-clean-room
pip install .
```
为了进行开发,请连同 dev 依赖项一起以可编辑模式安装。setuptools 后端要求使用 `editable_mode=compat` 以实现真正的可编辑安装。
```
pip install -e ".[dev]" --config-settings editable_mode=compat
pytest
```
该包安装了一个带有子命令调度器的控制台脚本:
```
sf-clean-room --version
sf-clean-room --help # top-level: lists available commands
sf-clean-room get_metadata --help # per-command: full contract
```
## 快速设置
**前置条件**
- **Python 3.11+**
- 您 PATH 上的 **Salesforce CLI** (`sf`) — [安装指南](https://developer.salesforce.com/tools/salesforcecli)
- **预先认证的 org 别名** — 该工具使用现有的 Salesforce CLI 会话;它本身不处理认证。您想要分析的每个 org 必须在运行任何命令之前完成认证:
sf org login web --alias myorg
您可以根据需要拥有任意数量的别名(每个 org、sandbox 或环境对应一个)。
- **仅限 `get_code_analysis`:** `sf code-analyzer` 插件(`sf plugins install @salesforce/plugin-code-analyzer`)以及您 PATH 上的 **Java 11+**(PMD 和 CPD 引擎需要;若无,Apex 规则覆盖将不可用)。
**最高效的入门方式**
这里假设您在终端或 Claude Desktop 或 Codex 等专用应用程序中使用企业级代码编写 agent,而不是使用聊天机器人或作为插件使用。
向代码编写 agent(如 Claude Code)说明您的用例,指引它访问本仓库,并要求其阅读文档。该 agent 会找出适用于您情况的命令,验证上述先决条件是否满足,并引导您完成任何尚待处理的事项。
```
I want to [describe your use case — e.g. "run a security and code-quality review of a client org"].
Please read the sf-clean-room repository at [path or URL] and advise me on how to proceed.
```
文档被设计为机器可读的:每一级的 `--help` 都会提供完整的命令契约,而 `docs/` 中的设计文档涵盖了具体细节。一旦 agent 阅读了它们,它就可以驱动整个工作流,从选择正确的命令到审查输出。请参阅 [agent 提示词示例](docs/agent-prompts.md) 获取可复制粘贴的提示词。
## 工作原理
提取 Salesforce 的 **元数据、记录数据、事件日志、技术对象和安全态势** 并运行 **代码分析**,生成本地文件夹供受控的下游自动化消费者使用:其他 AI agent、代码分析器、搜索索引器、CI pipeline。
其安全保障是结构性的,而非行为性的:任何敏感信息在被写入到已发布的文件**之前**,都会被排除、匿名化或派生。敏感元数据类型绝不会离开 Salesforce;记录 PII 会被分类并在处理过程中丢弃/哈希;事件日志的 IP、用户名和自由文本会被派生/哈希/丢弃,而原始下载的数据仅存在于内存中。消费者读取的是一个目录——它们从不持有 Salesforce 会话,也看不到原始提取数据。
`sf-clean-room` 是一个 **由 AI 操作的只读 CLI**。它专为可能没有先前上下文的 agent 发现和使用而设计——`--help` 会打印出 agent 正确使用它所需的所有信息。每个命令首先会发布到单次运行的临时区域,最后才将一个**哨兵文件**移动到输出中:看到哨兵文件,即表示发布完成;没有哨兵文件,就不要读取。
## 命令
| 命令 | 功能说明 | 哨兵文件 |
|---|---|---|
| `get_metadata` | 导出 org **元数据**(对象、字段、Apex、flow 等)。源代码控制的拒绝列表会在枚举时(即任何检索之前)排除包含凭证和脆弱的类型。按类型的权限缺口会被跳过并记录在案(`_skipped-types.csv`),这并不是致命错误。 | `package.xml` |
| `get_records` | 导出 org **记录数据**,在处理过程中进行匿名化。每个字段都会被分类(RAW / DROP / HASH / PASS / DERIVE);原始 PII 绝不会到达磁盘。经过审查的计划会持久化保存分类信息,以便进行无人值守、计划内的重复运行。 | `_field-handling-applied.csv` |
| `get_event_logs` | 导出 org **EventLogFile** 活动数据,在处理过程中进行匿名化并 **增量** 导出——每次运行都会添加一个带日期的子文件夹,从而构建超出 Salesforce 约 30 天保留期限的历史记录。IP → 网络前缀,URL → 去除查询参数,用户名哈希,自由文本丢弃;Salesforce ID 作为关联键保留。 | `_field-handling-applied.csv` |
| `get_technical_objects` | 导出 **40 个编目的技术对象**(Tooling 实体、系统表、REST 指标端点),在处理过程中进行匿名化。涵盖 Apex 代码健康状况、作业机制、权限拓扑、登录/会话/MFA 活动、设置审计历史记录、使用遥测数据和 org 限制。IP → 网络前缀,地理位置粗化到国家/细分级别,电子邮件/用户名哈希,自由文本丢弃;权限位和 ID 保持完整。快照发布模型(清除并重新发布)。 | `_field-handling-applied.csv` |
| `get_security_health_check` | 通过 Tooling API 导出 org 的 **Security Health Check** 分数和每个设置的风险表(HIGH_RISK / MEDIUM_RISK / LOW_RISK / INFORMATIONAL / MEETS_STANDARD)。全部为 org 配置数据——无分类器,无 PII。快照发布模型(每次运行时覆盖)。 | `securityhealthcheck_.json` |
| `get_code_analysis` | 对本地的 `get_metadata` 输出文件夹运行 **Salesforce Code Analyzer**(`sf code-analyzer`),并发布 HTML + CSV + JSON 报告。**无需 Salesforce 会话**——直接针对磁盘上的文件在本地运行。需要 `sf code-analyzer` 插件和已完成的 `get_metadata` 运行(即 `package.xml` 必须存在于 `--metadata-path` 中)。 | `_summary.json` |
```
sf-clean-room --help # tool overview + command list
sf-clean-room --help # full per-command contract
```
这些功能共同为 AI agent 提供了一个受控的、本地的 org 全貌:它的*结构*(`get_metadata`)、它的*数据形态和分布*(`get_records`)、它的*运营/安全活动*(`get_event_logs`)、它的*技术内部结构*(`get_technical_objects`)、它的*安全态势*(`get_security_health_check`)以及它的*代码质量和漏洞*(`get_code_analysis`),而 agent 无需直接接触 Salesforce 或查看原始 PII、凭证或机密。所有命令均为只读,且在失败时会自动关闭(fail closed),并对每次运行进行审计。所有命令均支持 `--dry-run`。(`get_code_analysis` 不需要 Salesforce 会话;它在本地对先前的 `get_metadata` 输出运行。)
## 预计耗时
单 org 单次运行各命令的大致实际耗时。
| 命令 | 小型 | 中型 | 大型 |
|---|---|---|---|
| `get_metadata` | ~3.5 分钟 | ~25 分钟 | ~50 分钟 |
| `get_records` | ~1 分钟 | ~12 分钟 | ~60 分钟 |
| `get_event_logs` | ~10 秒 | ~8 分钟 | ~30 分钟 |
| `get_technical_objects` | ~1 分钟 | ~8 分钟 | ~35 分钟 |
| `get_security_health_check` | ~7 秒 | ~15 秒 | ~30 秒 |
| `get_code_analysis` | ~20 秒 | ~3 分钟 | ~4 分钟 |
| **全部六个,端到端** | **~6 分钟** | **~55 分钟** | **~3 小时** |
Org 配置:
- **小型** — 单团队 / Developer-Edition org。最小限度的自定义 schema,少数标准对象,极少的历史或日志数据。
- **中型** — 中型生产 org 或集成 sandbox。中等规模的自定义元数据,几十个自定义对象,中等的记录和事件日志数据量。
- **大型** — 完整的企业级生产 org。大量的自定义配置和托管包,极高的记录数,庞大的 EventLogFile 和技术对象数据量。
## 元数据流水线
```
enumerate → filter → batch → retrieve+extract (to temp) → scrub (no-op in v1) → publish
```
* **枚举 (Enumerate)** — 针对目标 org 的 API 版本执行 `describeMetadata` + `listMetadata`(对于文件夹类型,针对每个文件夹执行)。
* **过滤 (Filter)** — 应用硬编码的拒绝列表。剔除敏感和运行环境脆弱的类型。
* **批处理 (Batch)** — 感知权重的批处理,遵守 Salesforce 每次检索 10,000 个组件的上限以及 SOAP ZIP 大小限制(压缩后 39 MB / 未压缩 400 MB)。大多数运行只会生成单个批次。
* **检索并提取 (Retrieve + extract)** — 异步检索,轮询至完成,将返回的 zip 解码到单次运行的临时目录中,同时具备 zip-slip 防护、Windows 长路径支持和文件名清理。任何被重写的路径都会记录在 `_path_renames.csv` 中。
* **清理 (Scrub)** — 可插拔的阶段列表。v1 版本内置了一个无操作阶段;保留此契约是为了让密钥扫描器、PII 哈希器和内容重写器能够在日后无需更改消费者可见输出的情况下插入。
* **发布 (Publish)** — 清除发布目录,将每个文件移动到其中,并 **最后** 移动 `package.xml`。`package.xml` 的存在是向消费者发出的发布完成的信号。
失败即关闭:在发布之前发生的任何错误都会保持发布路径原封不动(在 `docs/design/01-design-v1.md` §8 中记录了一个狭窄的例外情况)。发生故障时,单次运行的临时目录将被保留以供检查。
## 命令帮助
所有命令都共享审计日志、“先临时后发布”的原则,以及最后发布哨兵文件的规则。各命令的帮助信息:
```
sf-clean-room get_metadata --help # metadata export contract
sf-clean-room get_records --help # record export contract
sf-clean-room get_event_logs --help # event-log export contract
sf-clean-room get_technical_objects --help # technical objects export contract
sf-clean-room get_security_health_check --help # security health check contract
sf-clean-room get_code_analysis --help # code analysis contract
```
## 元数据 (`get_metadata`)
```
# 仅规划 — 枚举、过滤、批处理、报告。不调用 retrieve,不进行任何写入。
sf-clean-room get_metadata --org-alias myorg --path ./out --dry-run
# 实际运行 — 生成包含 package.xml 作为 sentinel 的 ./out。
sf-clean-room get_metadata --org-alias myorg --path ./out
```
这就是 `get_metadata` 的全部接口。此外还有顶层的 `--help` 和 `--version`。没有任何标志可以用来放宽拒绝列表、更改临时根目录或跳过清理阶段——因为这些操作会削弱安全保障,它们只存在于源代码中而不在 CLI 上。
### 消费者看到的内容
成功运行后,`--path` 中包含:
* 一个标准的 Salesforce 元数据树(`classes/`、`objects/`、`flows/` 等)。
* 位于根目录的 `package.xml` — **仅当**发布完成时才存在。它列出了实际检索到的内容。
* 位于根目录的 `_skipped-types.csv` — 已认证身份无法枚举或完全检索的类型(`type,bucket,components_requested,components_retrieved`)。如果没有跳过任何内容,则仅包含表头。按类型的权限缺口会记录在此处,并且运行会继续而不是中止;详细的错误信息会进入审计日志,而不是此文件。拒绝列表中的类型绝不会出现在这里。
* `_path_renames.csv`(如果在提取过程中重写了任何路径组件)。
消费者应该:
1. 等待直到 `package.xml` 出现在 `--path` 中。
2. 从树中读取它需要的任何内容。
消费者 **不应** 对缺少 `package.xml` 的 `--path` 执行操作:这意味着发布可能正在进行中、不完整或已失败。
### 退出代码
* `0` — 发布完成(包括“过滤后无组件”的情况,该情况仍会生成一个空的清单)。
* 非零 — 中止。发布路径保持原样,或者——在 `docs/design/01-design-v1.md` §8 中描述的狭窄的原子性间隙中——缺少其 `package.xml` 哨兵文件。无论哪种方式,哨兵规则都是可靠的:没有 `package.xml`,就不应消费。
## 记录 (`get_records`)
`get_records` 导出记录 **数据**,并在处理过程中进行匿名化。分类器
读取每个字段的描述元数据并推荐一个操作——`RAW`(Salesforce
ID)、`DROP`(直接 PII、特殊类别、文章、公式泄露)、`HASH_EMAIL`
/ `HASH_ID`(冻结的、从不加盐的 SHA-256,以便哈希列能够跨数据源关联)、
`PASS`(分析信号)、`DERIVE`(选择性加入)。原始查询结果仅保留在进程
内存中;DROP 字段绝对不会被选中;哈希处理发生在任何值被
写入之前。该工具是 **只读的**——它只发出 describe 和 `SELECT` 查询。
工作流程是:推荐 → 审查 → 提取,并且经过审查的计划是一个
可持久化、可调度的规范:
```
# 1. 规划 (dry-run):probe + describe + classify。写入可编辑的 plan。不读取任何 record 值。
sf-clean-room get_records --org-alias myorg --path ./out --only Account Contact --plan plan.toml --dry-run
# 2. 审查:根据需要编辑 plan.toml 中的 [overrides.*] / [reasons.*]。
# 3. 提取:应用 plan,为每个 object 写入一个
标签:AI辅助审计, DevSecOps, JS文件枚举, Salesforce, 上游代理, 代码分析, 凭证管理, 命令行工具(CLI), 数据脱敏, 逆向工具