# Cloudflare 托管与访问控制

## 内容边界

记录 Cloudflare Pages 项目、生产分支、自定义域名、Access 策略和复核动作。不要记录 Access secret、API Token、验证码或绕过登录的链接。

## 当前口径

- 内部站仓库：`novocube/novocube-internal`
- 建议生产分支：`main`
- 建议托管：Cloudflare Pages
- 建议访问控制：Cloudflare Access
- 内部域名：`internal.novocube.ai`

## Codex Cloudflare MCP 环境

Cloudflare 官方 agent setup 文档发布在：

```text
https://developers.cloudflare.com/agent-setup/prompt.md
```

本仓建议在 Codex 中安装 Cloudflare skills，并注册 Cloudflare MCP servers。这样后续 agent 可以直接查询 Cloudflare 文档、Pages 项目、构建状态、绑定和观测信息，减少手工切换控制台。

### 安装 Cloudflare skills

官方命令是：

```bash
npx -y skills add cloudflare/skills --skill '*' --yes --global
```

如果本机 `npx` 因 npm 临时安装问题失败，可以使用：

```bash
pnpm dlx skills add cloudflare/skills --skill '*' --yes --global
```

安装后应能在 `~/.agents/skills/` 看到以下 Cloudflare skills：

| Skill | 用途 |
| --- | --- |
| `cloudflare` | Cloudflare 平台总入口 |
| `wrangler` | Wrangler、Pages、Workers 部署与配置 |
| `workers-best-practices` | Workers / Pages Functions 生产建议 |
| `web-perf` | Web 性能检查 |
| `durable-objects` | Durable Objects 设计与实现 |
| `agents-sdk` | Cloudflare Agents SDK |
| `sandbox-sdk` | Cloudflare Sandbox SDK |
| `cloudflare-one` | Zero Trust / Access |
| `cloudflare-one-migrations` | Cloudflare One 迁移 |
| `cloudflare-email-service` | Email Service |
| `turnstile-spin` | Turnstile 相关场景 |

### 注册 MCP servers

在 Codex 中执行：

```bash
codex mcp add cloudflare --url https://mcp.cloudflare.com/mcp
codex mcp add cloudflare-docs --url https://docs.mcp.cloudflare.com/mcp
codex mcp add cloudflare-bindings --url https://bindings.mcp.cloudflare.com/mcp
codex mcp add cloudflare-builds --url https://builds.mcp.cloudflare.com/mcp
codex mcp add cloudflare-observability --url https://observability.mcp.cloudflare.com/mcp
```

各 server 的用途：

| MCP | 是否需要 OAuth | 用途 |
| --- | --- | --- |
| `cloudflare` | 是 | Cloudflare API 总入口，适合查询和管理账号、Pages、Workers 等资源 |
| `cloudflare-docs` | 否 | 查询 Cloudflare 官方文档 |
| `cloudflare-bindings` | 是 | 查询和管理 Workers / Pages 的绑定、变量和相关资源 |
| `cloudflare-builds` | 是 | 查询 Pages / Workers Builds、部署和构建状态 |
| `cloudflare-observability` | 是 | 查询日志、指标和观测信息 |

注册后登录：

```bash
codex mcp login cloudflare
```

部分 server 会在首次添加或首次使用时自动打开 OAuth 授权页。按浏览器提示授权即可。完成后执行：

```bash
codex mcp list
```

确认这些 server 为 `enabled`，其中 `cloudflare`、`cloudflare-bindings`、`cloudflare-builds`、`cloudflare-observability` 的 Auth 应为 `OAuth`，`cloudflare-docs` 可显示为 public / unsupported auth。

### 日常使用规则

1. 查询 Cloudflare 文档时优先使用 `cloudflare-docs`，不要凭记忆猜最新配置。
2. 查询 Pages 项目、部署、变量、绑定和构建状态时优先使用 Cloudflare MCP；写入配置前先读取当前配置，避免覆盖 build command、output directory、compatibility date 或现有 binding。
3. Secret 只通过 Cloudflare Dashboard、Wrangler 或 Cloudflare MCP 写入，不写入仓库、README、docs、终端历史或前端页面。
4. 如果 MCP 写入权限不足，可使用 Wrangler 作为后备：

```bash
pnpm dlx wrangler@3.114.14 pages secret put GITHUB_TOKEN --project-name novocube-internal
pnpm dlx wrangler@3.114.14 pages deploy dist --project-name novocube-internal --branch main
```

5. 更新 Secret 后需要重新部署一次生产环境，确保 Pages Functions 运行时能读取新绑定。
6. 变更 Cloudflare Access、域名、构建命令、Pages Functions 或 Secrets 后，同步更新本文件和 `README.md` 的相关段落。

## Pages 构建配置

| 项 | 值 |
| --- | --- |
| Repository | `novocube/novocube-internal` |
| Framework preset | Astro |
| Build command | `npm run build` |
| Build output directory | `dist` |
| Root directory | `/` |
| Node.js version | `22` |

不要使用 `npx wrangler deploy` 作为 Pages 构建命令。该仓库由 Astro 生成静态文件，Cloudflare Pages 只需要执行构建并发布 `dist/`。

## 动态 API

内部站从 2026-06-29 起预留 Cloudflare Pages Functions，用于把静态入口逐步升级成动态工作台。

| API | 用途 | 数据边界 |
| --- | --- | --- |
| `/api/github/status` | 实时读取 `novocube` 组织仓库状态，返回仓库数、Open PR、Open Issues、最近提交和 7 日内更新数 | 只返回仓库级摘要，不返回 Secret、成员邮箱、私有文件内容或 Issue 正文 |
| `/api/email/members` | 实时读取企业微信通讯录中的 `@novocube.ai` 邮箱成员，返回成员数、启用数、停用数和邮箱清单 | 只返回内部站已有权限范围内的成员姓名、邮箱、状态、角色和部门 ID，不返回手机号、密码、验证码或通讯录 Secret |

该 API 成功响应会写入 Cloudflare Edge Cache，默认 `s-maxage=300` 秒。页面会显示最后同步时间；API 失败时前端保留下方构建时静态台账作为兜底。

### GitHub Secret

在 Cloudflare Pages 项目的生产环境变量 / Secrets 中设置其一：

| Secret | 用途 |
| --- | --- |
| `GITHUB_TOKEN` | 推荐。GitHub fine-grained token 或 GitHub App installation token，至少具备读取 `novocube` 组织仓库 metadata / contents / issues / pull requests 的权限 |
| `NOVOCUBE_REPO_READ_TOKEN` | 兼容本仓已有同步脚本的备用名称 |

可选变量：

| 变量 | 默认值 | 用途 |
| --- | --- | --- |
| `GITHUB_OWNER` | `novocube` | 需要读取的 GitHub 组织 |

Token 只放 Cloudflare Secret，不写入仓库、页面、日志或文档。前端只访问 `/api/github/status` 的摘要结果。

### 企业微信通讯录同步

邮箱成员主路径采用定时同步到 `data/email-accounts.json`，不依赖 Cloudflare Pages/Workers 实时访问企业微信。同步脚本在一台已加入企业微信可信 IP 的固定机器上运行：

```bash
npm run sync:email
```

该机器需要设置：

| 环境变量 | 用途 |
| --- | --- |
| `WECOM_CORP_ID` | 企业微信 CorpID |
| `WECOM_CONTACT_SECRET` | 企业微信通讯录 Secret |
| `WECOM_SECRET` | 备用名称 |
| `WECOM_DEPARTMENT_ID` | 可选，默认 `1`，从根部门递归读取 |
| `EMAIL_DOMAIN` | 可选，默认 `novocube.ai` |

Cloudflare Pages Function `/api/email/members` 保留为可选实时接口。若未来启用实时接口，在 Pages 项目的生产环境变量 / Secrets 中设置：

| Secret / 变量 | 用途 |
| --- | --- |
| `WECOM_CORP_ID` | 企业微信 CorpID |
| `WECOM_CONTACT_SECRET` | 企业微信通讯录 Secret，推荐名称 |
| `WECOM_SECRET` | 备用名称 |
| `WECOM_DEPARTMENT_ID` | 可选，默认 `1`，从根部门递归读取 |
| `EMAIL_DOMAIN` | 可选，默认 `novocube.ai` |
| `WECOM_PROXY_URL` | 可选，固定出口代理地址，配置后优先使用代理 |
| `WECOM_PROXY_TOKEN` | 可选，调用固定出口代理的 Bearer Token |

企业微信通讯录 Secret 只放 Cloudflare Secret，不写入仓库、页面、日志或文档。前端只访问 `/api/email/members` 的摘要结果；API 失败时资产页继续显示静态邮箱台账。

企业微信通讯录 API 对来源 IP 有可信 IP 限制。Cloudflare Pages/Workers 的直连出口 IP 可能变化，触发 `60020` 时应部署 `proxy/wecom-email-proxy/` 到一台有固定公网 IPv4 的服务器，把该固定 IP 加入企业微信可信 IP，并在 Pages production Secrets 中设置 `WECOM_PROXY_URL` 和 `WECOM_PROXY_TOKEN`。内部站会优先走固定出口代理，未配置代理时才回退到直连企业微信。

### 未来智能体边界

智能体功能应作为 Cloudflare Worker / Pages Function 后端能力逐步加入，不直接在前端保存模型密钥。第一批建议能力：

- 总结最近 24 小时 GitHub 项目变化。
- 发现长时间未推进的仓库或待办。
- 生成公司级待办草案，写入人工确认队列。
- 检查 Data Room、PoC、风险和周报数据源是否需要更新。

需要历史趋势或人工确认队列时，再引入 D1；只做短期状态缓存时用 KV 即可。

## 复核动作

每季度确认 Pages 项目绑定、生产分支、自定义域名、Access 允许范围、部署状态、Functions 是否可用和 GitHub Secret 是否仍有效。涉及域名或访问控制变更时，同步 `docs/domains.md`、`data/domains.json` 和 `ledger.html`。
