bkd-dotcom/umbra

GitHub: bkd-dotcom/umbra

Umbra 为 AI 编码代理提供一层变更治理平面,通过准入契约、隔离沙箱、独立验证和签名凭证来管控并证明代理对代码仓库的每次变更。

Stars: 0 | Forks: 0

Umbra # Umbra **一个专为编码代理设计的变更控制平面。** [umbra.engineer](https://umbra.engineer) · [MIT](LICENSE)
编程代理现在可以更改您的代码库。Umbra 是一层控制机制,用于决定某项 变更获得了多少权限——并提供证明。在代理被授予您代码库的权限之前,Umbra 会 测试它*在*您的代码库中是否值得信任:一个可执行的契约限定了变更范围,不受信任的代码库文本会被 隔离,一个独立的验证器会检查结果,只有在运行通过后才授予其赢得的权限—— 每个操作都被封装在一个带有签名且可独立验证的凭证中。Codex 在一个一次性克隆仓库中提议补丁;Umbra 绝不会进行合并。 ## 代理准入测试 “AI 发现 CVE 并提交 PR”已经是一个拥挤的领域。Umbra 位于其上一层: 它决定是否应该允许代理进行更改,并 证明原因。在任何 PR 之前,都会运行一个受管控的流水线: ``` load executable contract (.umbra/admission.yaml) → redact untrusted repository text on disk (README / AGENTS.md / CLAUDE.md / … — the agent can't read what isn't there) → run required checks on the BASE commit (in an isolated worktree, per check, to tell a regression from a pre-existing failure) → run the bounded task in a disposable checkout (a real Codex run live, or a deterministic policy evaluation offline) → evaluate the changeset against the contract (deterministic, outside the model) → re-run required checks on the CHANGED tree (allowlisted profiles, secret-stripped env, network-jailed on Linux; missing/failing → cap at analyze) → independently verify it (the patch-writer can't self-approve) → grant only the authority the run EARNED (0 observe · 1 analyze · 2 branch-PR) → seal it in an Ed25519-signed Remediation Receipt (binds base commit + diff + advisory + checks) ``` 权限是证据的结果,绝不是一个简单的复选框——一次被禁止的路径尝试、 一次未通过的必需检查,或者一次验证器拦截,都会将其权限保持在分支 PR 级别以下。在任何级别下 `auto_merge` 均为 false,并且赢得的通行证实际上控制着 PR 的创建( 服务端的紧急制动器可将其吊销)。离线测试夹具作为 确定性策略评估运行(没有 Codex,没有网络),因此任何人都可以复现它们; 真实代码库的运行会执行一个真正有边界的 Codex 任务——报告会 标注实际执行的是哪个执行器。在仪表盘的“代理准入”面板(包含 五个已提交的离线测试夹具)或通过 API 即可零配置体验: ``` # 单命令验证(无需登录,无需网络):引入 fixture + 验证已签名的 receipt make judge # → earns L2 branch-PR, then verifies the Ed25519 receipt → OK make judge-adversarial # → prompt-injection redacted on disk, in-scope fix still permitted # 离线、确定性 —— 无需 auth,无需网络(judges/CI 可复现) curl -s -X POST localhost:8000/api/admit -d '{"fixture":"permitted-dependency-fix"}' # → earns L2 branch-PR (required check ran & passed) curl -s -X POST localhost:8000/api/admit -d '{"fixture":"adversarial-readme-injection"}' # → injection quarantined, fix still permitted curl -s -X POST localhost:8000/api/admit -d '{"fixture":"forbidden-scope-violation"}' # → BLOCKED at L0 (out of scope) curl -s -X POST localhost:8000/api/admit -d '{"fixture":"failing-check-caps-authority"}' # → capped at L1 (pre-existing check failure) curl -s -X POST localhost:8000/api/admit -d '{"fixture":"regression-detected"}' # → capped at L1 (change caused a regression) # 在 allowlisted 的公开 repo 上进行 LIVE run —— 无需登录,有速率限制(真实 clone + 实时 OSV) curl -s -X POST localhost:8000/api/admit/public-live -d '{"repo_url":"https://github.com/expressjs/express"}' # 使用 Umbra 自己的 pinned public key 验证 receipt(证明由 Umbra 签发) curl -s localhost:8000/api/verify-key ``` 测试夹具位于 [`evals/fixtures/`](evals/fixtures/);相关模块为 [`backend/contract.py`](backend/contract.py)、[`backend/verifier.py`](backend/verifier.py)、 [`backend/checks.py`](backend/checks.py)、 [`backend/trust_boundary.py`](backend/trust_boundary.py)、[`backend/admission.py`](backend/admission.py) 以及 [`backend/receipt.py`](backend/receipt.py)。 ## 测试(无需重新构建) - **在线网站:** [umbra.engineer](https://umbra.engineer) —— 托管于 Google Cloud Run。使用 **GitHub 或 Google** 登录,然后让“夜班团队”指向您自己的代码库之一(公开或私有)。 扫描发现是**真实的** —— OSV CVE、依赖图、Git 历史根因分析 —— 并且每个结果都会 标明其生成方式。 - **在 ChatGPT 中(插件 / GPT Action):** 只读操作是公开的(无需身份验证)。尝试共享的 **Umbra Engineer** GPT,或者根据提供的 schema 自行配置: - 插件清单: - OpenAPI(Actions): - 构建说明:[`custom_gpt/`](custom_gpt/instructions.md) —— 例如 *“扫描 github.com/expressjs/express”* - **自主模式:** 将 [`.github/workflows/umbra.yml`](.github/workflows/umbra.yml) 放入任何代码库中(添加一个 `OPENAI_API_KEY` 密钥)—— Umbra 会审查每个 PR 并运行每晚扫描, 从而提交仅限分支的修复 PR。或者一次性安装 **Umbra GitHub App**(任何账户/组织, 公开或私有代码库,在 GitHub 的 UI 中选择您的代码库)—— 每个 新 PR 都会获得由该 App 发布的咨询性审查评论( 绝不合并)。设置说明:[docs/github-app.md](docs/github-app.md)。 ## Umbra 与同类工具的区别 Umbra 并不是另一个“AI 审查您的 PR”或“AI 升级您的依赖”的工具——它位于其上一层, 决定代理的变更是否*被允许*,然后 提供证明。下表说明了各个类别真正擅长的功能,并展示了 Umbra 在何处增加了独特的机制(它反映了每个类别的典型/默认 行为;产品会不断演进)。 | 功能 | AI 审查机器人 (CodeRabbit / Greptile / Qodo) | 依赖机器人 (Dependabot / Snyk) | 编码代理 (Codex / Devin) | **Umbra** | |---|:---:|:---:|:---:|:---:| | 评论 / 审查变更 | ✅ | — | 部分 | ✅(确定性判定) | | 提交依赖修复 PR | — | ✅ | ✅ | ✅(仅限分支) | | 决定代理是否**被允许**修改 —— 可执行契约,失败即关闭 | — | — | — | **✅** | | 将代码库文本视为不受信任;**在运行前隔离磁盘上的提示词注入** | — | — | — | **✅** | | **补丁编写者无法绕过的独立验证器** | 部分 | — | — | **✅** | | 验证版本升级是否**真正清除了引用的 CVE** | — | 部分 | — | **✅** | | **赢得的、可撤销的、与运行绑定的权限**(L0 / L1 / L2 + 紧急制动器) | — | — | — | **✅** | | **Ed25519 签名、可独立验证的凭证**(对比固定密钥) | — | — | — | **✅** | | 在预检沙箱中运行必需的检查;如果不可用则**关闭** | — | — | 代理自己的沙箱 | **✅** | | 从不自动合并 | 视情况 | 视情况 | 视情况 | **✅(绝不)** | 关键不在于 Umbra 的审查更好——而在于审查/升级发生在受控的准入决策* 之后*,这在这些类别的其他产品中是没有的。 定位基础:OWASP Top 10 for LLM Apps 2025(LLM01 Prompt Injection,LLM06 Excessive Agency)以及各产品的公开文档。 ## 如何使用 Codex + GPT-5.6 - **Codex**(`codex exec`,ChatGPT 登录)会探索一个**一次性检出仓库**,编辑代码,在 沙箱中运行测试,并起草变更——绝不进行推送、提交或合并。参见 [`backend/codex_client.py`](backend/codex_client.py)。 - **推理**在 **GPT-5.6** 上运行:在可用时使用 Responses API(Sol / Terra / Luna — 深度 / 工作 / 快速), 否则使用 Codex CLI 本身(它运行 GPT-5.6 模型)。参见 [`backend/reasoning.py`](backend/reasoning.py)。Umbra 仅凭 **Codex 额度即可在线运行——无需 OpenAI API 密钥。** - **诚实账本:** 每次运行都会为每个部分标注实际提供服务的来源(`codex-cli` / `osv.dev` / `local-git` / `responses-api` / `demo-cache` / `unavailable`)。推理过程绝不会被 凭空捏造。参见 [docs/live-mode.md](docs/live-mode.md)。 - **Codex 在哪里加速了开发 & `/feedback` 会话 ID:** 参见 [docs/CODEX_USAGE.md](docs/CODEX_USAGE.md) 获取提交级别的凭证(哪个 Codex 创作的提交构建了契约、验证器、沙箱、凭证)以及 [SUBMISSION.md](SUBMISSION.md)。 ## 问责层 只有当你能信任自动驾驶团队夜间所做的工作时,它才有用。Umbra 将每一次 发现和修复都视为可审计的凭证,而不是盲目相信的声明: - **提供者账本** —— 每次运行的每个部分都标明了实际提供服务的来源 (`codex-cli` / `osv.dev` / `local-git` / `responses-api` / `cache-fallback` / `unavailable`)。 非实时提供者永远不会被伪装成实时的;团队未运行的阶段会被标记为 `SAMPLE`。 - **应用内 PR 审查** —— Codex 起草的补丁会渲染为一个真实的差异对比(逐文件、带有差异块头标, ±行号边栏),旁边附有确定性的 **Reviewer** 风险判定,以便您在*打开*之前审查确切的 变更。PR 是**仅限分支的** —— Umbra 绝不会合并。参见 [`frontend/components/ui/diff-view.tsx`](frontend/components/ui/diff-view.tsx)。 - **PR 账本** —— Umbra 打开的每个仅限分支的 PR 都会成为一份持久的凭证(PR 编号、分支、 它所修复的公告、记录的 Reviewer 判定、打开时间),并按代码库分组。 - **带原因的分类处理** —— 延迟处理或接受风险需要提供原因,并 在服务端进行记录,因此抑制操作是显示在活动时间线中的可审计行为——而绝不是静默隐藏。 - **证据包 + 完整性哈希** —— 任何运行都可以导出为一个便携、经过路径脱敏的 Markdown 包, 印有规范的 `sha256`;`POST /api/evidence-pack/verify` 会**重新计算**该哈希,以捕获 意外的篡改。这是一个*完整性校验和*,而不是防篡改的溯源——任何人都可以编辑 报告并重新计算哈希。如需防篡改证明,请使用下方的签名凭证。参见 [`backend/evidence.py`](backend/evidence.py)。 - **签名修复凭证(防篡改)** —— 每次准入运行都将其问责链 (基础提交、契约、信任边界、已执行的检查、验证器、赢得的权限、差异/公告 哈希,以及 Codex 运行时的 Codex 配置哈希)封装到一个 **Ed25519 签名** 的信封中。 `POST /api/receipt/verify` 会**根据 Umbra 自己固定的公钥**(可在 `GET /api/verify-key` 获取)验证签名 —— 因此它证明是 *Umbra* 签发了该凭证,而不仅仅是某个密钥对其进行了签名。 凭证会如实标明签名密钥是托管的生产密钥还是开发环境的备用密钥。参见 [`backend/receipt.py`](backend/receipt.py)。 - **赢得权限的通行证** —— 代理在每个代码库中赢得的权限会被持久化且可撤销,并且 与确切的运行绑定(凭证哈希、基础提交、执行器 + Codex 配置哈希、检查结果、7天 有效期)。重新运行准入会执行 upsert 操作,运行失败会将其降级,而紧急制动器 (`POST /api/my/authority/revoke`)会将其强制降为 Level 0 —— PR 打开路由会严格执行这一点(被撤销、 低于 L2 或过期的通行证将阻止 PR)。`auto_merge` 永远不会被存储为 true。设置 `UMBRA_REQUIRE_ADMISSION=true` 即可开启严格模式,在该模式下,没有通行证的代码库根本无法获得 由代理创建的 PR(否则准入机制仅管理*已注册*的代码库)。 - **活动 / 审计时间线** —— 按顺序记录的工作转换,包含真实的持续时间和提供者标签。 ## 电子邮件报告 Umbra 可以将代码库的早间报告发送到您的收件箱——一份简洁的 HTML 摘要(得分、发现、Codex 准备的内容、仍需审查的内容)——提供两种方式: - **按需获取:** 从仪表盘中,“立即通过电子邮件发送最新报告”会将当前 保存的报告发送到您的账户邮箱(`POST /api/my/reports/email`)。 - **按计划获取:** 创建针对特定代码库的计划(`POST /api/my/schedules`),一个 Cloud Scheduler 定时任务会触发 `POST /api/cron/run-due-scans`,该任务会运行每个到期的 扫描并通过电子邮件发送最新报告。计划支持列表查看、暂停和删除。 交付过程是诚实的。发送通过 **Resend** 进行,每个计划在 每次运行后都会记录真实的交付状态——`accepted_for_delivery` 表示 *Resend 接收了邮件*,绝不声称已成功投递到收件箱(退信和 垃圾邮件过滤不在 Umbra 的可知范围内)。其他状态会如实进行记录: `email_unavailable`(未配置提供者/收件人)、`email_rejected`(提供者 错误)、`scan_failed`、`skipped_opted_out`、`scheduled`。 每封邮件都带有一个**签名的一键退订**链接(`GET/POST /api/unsubscribe`,RFC 8058 `List-Unsubscribe` 标头),因此收件人无需登录即可 选择退出;该 token 使用会话密钥进行签名,并切换 账户的通知。电子邮件完全是可选的——在配置提供者之前, 发送过程会优雅降级并报告“未配置电子邮件”,而不是 直接失败。相关模块:[`backend/notifications.py`](backend/notifications.py)、 [`backend/schedules.py`](backend/schedules.py);操作员设置: [docs/scheduled-reports.md](docs/scheduled-reports.md)。 ## 自动化 —— 接收来自 GitHub 的审查 除了电子邮件之外,Umbra 还可以对入站的代码库事件做出反应。一次性安装 **Umbra GitHub App**,每个新的拉取请求都会作为 webhook 被**接收**( `POST` 应用 webhook),经过扫描,并由该 App 通过短期的安装 token 发布一条咨询性审查评论作为回复——仅限评论,绝不合并。参见 [docs/github-app.md](docs/github-app.md)。 ### 诚实的执行边界 Umbra 说明了它实际执行的内容,绝不夸大: - **必需的检查** 仅运行 **允许列表中的配置文件**(`npm test`/`ci`,`pytest` 等),并使用 **已剥离密钥的环境**,在实际预检成功的最强隔离下运行——并被 如实记录为以下三个级别之一: - **`sandboxed`** —— 一个 bubblewrap 文件系统+网络沙箱(只读 OS,仅在 一次性检出仓库上进行可写绑定,私有 HOME/tmp,所有命名空间均为未共享状态)。这是唯一被称为完整 沙箱的级别:代码库自己的构建脚本无法读取主机 home 目录,也无法在检出目录之外写入。 - **`network-isolated`** —— Linux `unshare -rn`(切断网络,保留主机文件系统 —— *不是*完整的沙箱)。 - **`host-restricted`** —— 没有可用的包装器(例如 macOS 开发环境):仅使用允许列表 + 已剥离密钥的环境。 每个包装器在声明其级别之前都会被**预检**(`… true`),因此初始化 失败的命名空间永远不会被错误标记。报告/凭证记录了实际达到的级别,UI 也会显示该信息 (*enforced · sandboxed* / *network-isolated runner* / *host-restricted · isolation pending*)。 - **信任边界:** 不受信任的指令文件(README / AGENTS.md / CLAUDE.md / .cursorrules 等)会在 Codex 运行*之前*在 一次性检出仓库的磁盘上被**脱敏**,因此代理无法读取到 操纵内容。之后这些文件会被恢复,并且变更集会**根据最终树上的 `git` 重新计算**,因此签名的差异仅反映代理的 真实更改(绝不包含脱敏内容);对指令文件 的任何代理编辑都将被丢弃并记录在案。它只能捕获*经过测试的*模式;这并不是声称可以 击败所有的提示词注入。 着陆页上的 **Night-Shift pipeline** 端到端地演示了这一过程(扫描 → 分类处理 → 根因分析 → 起草修复 → 证据收集 → 人工把关),并重放了一次真实的捕获扫描。 ## 威胁模型、隐私与执行标签 Umbra 明确指出了它保证什么,它仅能缓解什么,以及它不尝试做什么——因此 它的声明经得起怀疑的审视。 ### 各执行标签的含义(在每次报告/凭证中如实记录) - **`enforced · sandboxed`** —— 必需的检查在 **bubblewrap** 文件系统+网络沙箱下运行 (只读 OS,仅在一次性检出仓库上进行可写绑定,私有 HOME/tmp,所有 命名空间未共享,无网络)。在声明该级别之前会使用 `… true` 进行预检。 - **`network-isolated`** —— Linux `unshare -rn`(切断网络,保留主机文件系统 —— **不是**完整的沙箱)。 - **`host-restricted`** —— 没有可用的隔离包装器(例如 macOS 开发环境):仅使用允许列表 + 已剥离密钥的 环境。我们**不会**称之为“沙箱”。 - **`declared / unavailable`** —— 必需的检查无法在此处运行(缺少工具)。权限被 **限制在 analyze (L1)** —— branch-PR (L2) 要求契约检查必须已经实际运行并 通过。缺失/失败/被阻止的检查永远无法赢得 L2。 ### 信任边界 —— 威胁模型与非目标 - **被视为不受信任(数据,而非指令):** **Umbra 在其构建的上下文中提供的**源自代码库的 文本 —— README / AGENTS.md / CLAUDE.md / .cursorrules / CONTRIBUTING 以及其他被扫描的指令文件,以及作为上下文传递的代码库文档。只有 **Umbra 拥有的策略**(任务 + 契约)被视为指令。每次运行都会记录一个 签名的**上下文清单**,标明哪些内容被视为策略受信,哪些被视为引用证据提供,哪些已被 脱敏。 - **已强制执行的内容:** 已知的代理操纵模式(策略覆盖、机密访问、 范围扩大、代理指令、命令注入)会在 Codex 运行之前在 一次性检出仓库的磁盘上被**脱敏**,并且对指令文件的任何代理编辑都将被丢弃并记录在案。 - **非目标(明确不予保证):** Umbra **不**声称可以击败所有的提示词注入, 并且上下文清单**不**枚举代理可能独立读取的每个文件( 工作区访问代理可以自行打开文件;CLI 不暴露完整的读取日志)。不受信任的文本可以 存在于被扫描的集合之外;新颖的措辞可能会逃避模式检测器的检测。该边界能捕获 *经过测试的*模式,并将 Umbra 提供的代码库文本视为证据——它是一种缓解措施,而不是 安全的证明。必需的检查只能证明**声明的**契约,而不是证明整个 代码库是安全的。 ### 模型来源(Codex + GPT-5.6),仅在可观察时声明 每个凭证都带有签名的 `model_identity`:`executor`,观察到的 `codex_cli_version`, `model_configured`(Umbra 通过 `-m` **请求**的内容,例如 `gpt-5.6-luna`/`terra`/`sol`),一个 `model_resolved` 值,除非提供者/CLI 明确证明了运行使用的模型,否则该值保持为 **`unavailable`**(传递 `-m` 证明模型被*请求*,但不能证明它被确认——我们绝不会将 configured 提升为 resolved),以及一个 `model_evidence` 来源(用于 `-m` 请求的 `cli-argument`,未设置时的 `codex-default`,用于确定性离线路径的 `no-model`)。我们从不推断 CLI 选择的模型。 ### 策略所有权与变更控制 一个契约哈希证明了**运行了哪些**规则;凭证的 `policy_status` 如实声明了**谁授权了** 它们。声明的所有者/版本元数据**不是**加密签名,因此当在 `.umbra/admission.yaml` 中设置了 `policy_owner` + `policy_version` 时,状态为 `declared`;当缺少这些内容时,状态为 `incomplete`(故障安全默认值);并且 **仅**当策略带有可验证签名时(这是 Umbra 目前不主张的一种方案——存在该值是为了使字段 保持真实),状态才为 `cryptographically-signed`。权限始终会受到确定性契约、独立 验证器和必需检查的额外限制,因此宽松的策略本身无法超出这些机制允许的范围授予更多权限。 生产团队应该拥有并对他们自己的策略进行版本控制。 ### 隐私与数据处理(Umbra 控制的内容) Umbra 仅说明它在技术上控制的内容——而不是 Cloud Run、平台日志、 GitHub、OSV 或其他提供者所拥有的行为: - **一次性检出:** 实时代码库被克隆到一个临时的检出区,并移除了 `origin` 远程仓库; Codex 永远不会得到 GitHub 的写入凭证。当运行结束时,Umbra 会删除检出区。 - **绝不自动合并:** 在任何权限级别和签名凭证中,`auto_merge` 均为 false; PR 仅限分支,由人工进行合并。 - **剥离密钥的执行:** 必需检查的子进程运行在最小化环境中——OpenAI / GitHub / 云 / 会话密钥均被剥离。 - **凭证内容:** 凭证绑定了哈希(基础提交、差异、公告)和提供者标签; 证据包经过了**路径脱敏**(从自由文本中剥离了服务器的临时路径)。差异对比 是根据最终树上的 `git` 重新计算的,因此凭证中永远不会出现脱敏内容。 - **私有代码库:** 支持已登录的用户;发现结果在服务端运行。服务器上的实时 Codex 被严格限制为创始人账户(`UMBRA_FOUNDER_IDS`);其他用户只能看到发现结果,以及一个诚实的 “Codex 在您的机器上运行”标签。 - **Umbra 无法控制/承诺的内容:** 它不能保证托管平台及其 请求/标准输出日志、GitHub、OSV 或任何外部提供者的保留或删除行为;它不是一份 数据处理协议,也不是合规认证。请将此托管演示视为演示; 通过自托管来控制周边的基础设施。 ### 生产环境限制 - 在没有 Linux 隔离的环境中,检查为 `host-restricted`,而不是沙箱(标记正确; L2 仍然需要检查运行并通过)。 - 提示词注入边界仅捕获经过测试的模式(参见上文的非目标)。 - 实时 Codex 运行可能需要几分钟;捕获证明的路径是即时的离线评估路线。 ## 支持的平台 macOS、Linux、Windows(Python 3.11+,Node 20+)。任何公开的 GitHub 仓库。ChatGPT 插件 / GPT Action 适用于支持 ChatGPT Actions 的任何地方。 ## 从源码运行 该仓库以 [**uv**](https://docs.astral.sh/uv/) 作为标准工具: ``` git clone https://github.com/bkd-dotcom/umbra cd umbra uv sync --extra dev # backend deps + test tooling uv run uvicorn backend.main:app --reload # API at http://localhost:8000 cd frontend && npm install && npm run dev # dashboard at http://localhost:3000 ``` **两个服务必须同时运行。** 仪表盘会调用 `NEXT_PUBLIC_API_URL` 处的 API (默认为 `http://localhost:8000`),并且 API 仅接受 `UMBRA_FRONTEND_ORIGIN` 中设置的来源 (默认为 `http://localhost:3000`)。如果 Next.js 因为 `:3000` 被占用而选择了不同的端口(例如 `:3002`),请将它们进行固定匹配: ``` # terminal 1 —— API,允许 dashboard 的实际 origin UMBRA_FRONTEND_ORIGIN=http://localhost:3002 uv run uvicorn backend.main:app --reload # terminal 2 —— 同一端口上的 dashboard cd frontend && npm run dev -- -p 3002 ``` 如果无法访问 API,仪表盘将显示 **“API unavailable — start the backend on :8000”** 横幅,并回退到已清晰标记的示例工作转换。 **演示模式(零配置,无密钥,无网络):** ``` UMBRA_DEMO_MODE=true uv run uvicorn backend.main:app --reload ``` **仅凭 Codex 额度的实时模式(无 OpenAI API 密钥):** 使用 `codex login` 对 CLI 进行一次身份验证,然后执行: ``` UMBRA_DEMO_MODE=false UMBRA_ENABLE_LIVE_REPOS=true UMBRA_ENABLE_CODEX_CLI=true \ uv run uvicorn backend.main:app --reload # 可选 preflight(验证 codex/git + 真实 clone;添加 reasoning probe): UMBRA_ENABLE_LIVE_REPOS=true UMBRA_ENABLE_CODEX_CLI=true UMBRA_PREFLIGHT_REASONING=true \ uv run python -m backend.preflight ``` 工程和推理部分均通过 Codex CLI 运行。完整指南和 提供者账本请参见 [docs/live-mode.md](docs/live-mode.md)。 ## 配置 复制示例环境文件并填入您需要的内容(在演示模式下全部为可选): - 根目录:[`.env.example`](.env.example) —— 核心开关(`UMBRA_DEMO_MODE`、`UMBRA_ENABLE_LIVE_REPOS`、 `UMBRA_ENABLE_CLOUD_SCAN`、`UMBRA_CLONE_DEPTH`、`UMBRA_FOUNDER_IDS`、`SESSION_SECRET`、 `UMBRA_FERNET_KEY`、OAuth 客户端 ID/密钥)。 - 后端:[`backend/.env.example`](backend/.env.example)。前端:[`frontend/.env.example`](frontend/.env.example)(`NEXT_PUBLIC_API_URL`)。 自动化 / 插件附加配置(在线托管):`UMBRA_PUBLIC_URL`(插件清单的绝对基础路径)。PR 自动审查是一个 **一次安装的 GitHub App**:`GITHUB_APP_ID`、`GITHUB_APP_SLUG`、 `GITHUB_APP_WEBHOOK_SECRET` 和 `GITHUB_APP_PRIVATE_KEY`(PEM 或 base64;生产环境从 Secret Manager 挂载)。审查由 App 通过短期的安装 token 发布——不需要针对特定代码库的 webhook,也 不存储用户 token。完整设置请参见 [docs/github-app.md](docs/github-app.md)。`GITHUB_TOKEN` 为可选,并且 是只读的(零权限 token 仅用于提高公开读取的速率限制)。 电子邮件报告(可选):`RESEND_API_KEY` 和 `UMBRA_EMAIL_FROM` 启用发送;将它们留空, 计划/按需发送将优雅地降级为“未配置电子邮件”。计划发送通过经过 OIDC 身份验证的 cron 运行 —— `UMBRA_SCHEDULER_OIDC_AUDIENCE`(默认为 `UMBRA_PUBLIC_URL`)是 Cloud Scheduler 向 `POST /api/cron/run-due-scans` 提供的受众。设置说明:[docs/scheduled-reports.md](docs/scheduled-reports.md)。 ## 测试 ``` uv run pytest # 284 tests (backend/tests) ``` 前端:`cd frontend && npm run build`(必须生成干净的静态导出到 `out/`)。 ## 部署公共 URL 在 Google Cloud Run 上的单一服务(FastAPI 提供构建好的仪表盘)——一个 URL,无 CORS。 分步指南:[docs/deploy.md](docs/deploy.md)。 ## 许可证 [MIT](LICENSE) © 2026 Binay Dalai。
标签:AI编程代理, DevSecOps, Streamlit, 上游代理, 代码安全, 变更管理, 开发运维, 漏洞枚举, 自动化攻击, 访问控制, 逆向工具