# 交付说明 — plane-gptproto-integration 本压缩包包含 Plane v1.3.0 (AGPL-3.0 开源项目管理工具) 自部署 + gptproto.com AI 聚合 API 集成的完整代码。已脱敏,可直接交付外部团队部署。 ## 包内容速览 ``` plane-gptproto-integration/ ├── HANDOFF.md ← 你正在看的这份 ├── README.md 项目简介 ├── CLAUDE.md / AGENTS.md 开发期 AI 协作上下文 (可保留作技术参考) ├── docs/ │ ├── PLAN.md 完整方案 + 后门/隐私评估 │ └── USER_GUIDE.md 给最终用户的使用说明 ├── deploy/ │ ├── local/ 本地 Docker 部署 (推荐先在这跑通) │ │ ├── .env.template 所有密钥占位符,部署前需填 │ │ ├── docker-compose.override.yml │ │ ├── pull-plane.sh 从 GitHub 拉 Plane v1.3.0 源码 (源码已附带,通常无需运行) │ │ ├── README.md 本地部署详细步骤 │ │ └── src/ Plane v1.3.0 上游源码 (已随包附带,离线可部署) │ └── remote/ 生产部署 (1Panel + OpenResty 反代 + 自签 SSL) │ ├── .env.template │ ├── docker-compose.override.yml │ ├── install.sh 生产一键安装脚本 │ ├── plane.conf OpenResty 反代配置 │ ├── tdb.js 前端注入脚本 │ └── README.md ├── ai-agent/ FastAPI AI 聚合服务源码 │ ├── ai_agent/main.py 4 个端点: /healthz /ai/create-issue /ai/summarize /ai/search │ ├── Dockerfile │ ├── requirements.txt │ └── tests/ pytest TDD 用例 ├── plane-dashboard/ 自定义前端 (React + Vite + Semi UI) │ ├── src/ 源码 │ ├── dist/ 预编译产物 (可直接 docker build 不必本机 npm install) │ ├── Dockerfile │ ├── nginx.conf │ └── package.json └── qa/ ├── verify-local.sh 6 项健康检查 └── checklist.md ``` ## 已脱敏 - ✅ 所有真实密钥/Token 已剔除,`deploy/*/.env.template` 全部为 `CHANGEME_*` 占位符 - ✅ 生产服务器 IP 已替换为占位符 `YOUR_SERVER_IP` - ✅ docker-compose 中的本机绝对路径已改为相对路径 (`../../ai-agent`、`../../plane-dashboard`) - ✅ `__pycache__` / `.venv` / `node_modules` / `.DS_Store` / `.omc` 已剔除 ## 反遥测 / 反回拨锁定 (LOCKDOWN) ★ 必读 Plane v1.3.0 默认有几个"回拨家里"通道,**本包已用 env-gated 开关全部封堵**。 设计原则: 不动上游业务代码逻辑,只在 1 个文件加 2 处 if 守卫,通过 .env 里的开关控制开关。 升级 Plane 时几乎不会和上游冲突,改动可审计、可一键还原。 | 通道 | 默认状态 | 已采取的措施 | |---|---|---| | OpenTelemetry → `telemetry.plane.so` (每 6 小时 + 启动各一次,发送 instance_id / 用户数 / issue 数等) | 上游默认 **开** | (1) `register_instance.py` 新建 Instance 时根据 env `DISABLE_TELEMETRY=1` 把 `is_telemetry_enabled` 置 False (2) tracer.py 上游本身的 `if instance.is_telemetry_enabled:` 守卫会直接跳过上报逻辑 (3) 防御纵深: `OTLP_ENDPOINT=http://127.0.0.1:1` 让 exporter 连黑洞 | | GitHub release 检查 → `api.github.com/repos/makeplane/.../releases/latest` (启动一次) | 上游默认 **开,无 env 关** | `register_instance.py` 的 `check_for_latest_version()` 加 env 守卫: `DISABLE_GITHUB_VERSION_CHECK=1` 时直接返回 fallback,后面 try/requests.get 流程保留(便于将来想恢复) | | PostHog 事件追踪 → 用户邀请/工作区删除等 | 关 (需 env 配置才会发) | `.env.template` 显式空 `POSTHOG_API_KEY` / `POSTHOG_HOST` | | Microsoft Clarity 前端会话录制 → `clarity.ms` | 关 (需 env 配置才会发) | `.env.template` 显式空 `VITE_SESSION_RECORDER_KEY` | | Intercom 客服 widget → `widget.intercom.io` | 上游默认 **开** | `IS_INTERCOM_ENABLED=0` | 代码改动只有 1 个文件,2 处新增 if 守卫(共 6 行),其他逻辑 100% 原样: - `apps/api/plane/license/management/commands/register_instance.py` - diff 在 `deploy/local/patches/01-env-gated-register-instance.patch` - override.yml 通过 `volumes:` bind-mount 把这个 patched 文件覆盖到上游容器内的 `/code/plane/...` (绕过预构建镜像不能改源码的限制) ### 部署后如何验证 LOCKDOWN 生效 ```bash # 1. DB 里 telemetry 标志位 docker compose exec plane-db psql -U plane -d plane -c \ "SELECT instance_id, is_telemetry_enabled FROM instances;" # 期望: is_telemetry_enabled = f (false) # 2. 容器内确认 env-gated 补丁已挂载 docker compose exec api grep -n "LOCKDOWN" \ /code/plane/license/management/commands/register_instance.py # 期望: 2 行 (check_for_latest_version 守卫 + create 默认值) # 3. 容器里看 env 开关已注入 docker compose exec api sh -c 'env | grep -E "DISABLE_TELEMETRY|DISABLE_GITHUB"' # 期望: DISABLE_TELEMETRY=1 DISABLE_GITHUB_VERSION_CHECK=1 ``` ### 想恢复上游原版行为(关闭 LOCKDOWN)? 只需在 .env 里把 `DISABLE_TELEMETRY=0` 和 `DISABLE_GITHUB_VERSION_CHECK=0`,然后 `docker compose up -d --force-recreate api`。 代码逻辑完整无缺,不需要改源码。 ## 快速部署 (本地 Docker) 前置: Docker Desktop ≥ 4.30,8090 / 8100 端口空闲。 ```bash # 1. 解压 unzip plane-gptproto-integration.zip cd plane-gptproto-integration # 2. 准备环境变量 (复制模板 → 替换所有 CHANGEME_*) cp deploy/local/.env.template deploy/local/.env chmod 600 deploy/local/.env # 用你喜欢的编辑器把所有 CHANGEME_xxx 改成强随机值 # 必填项: # POSTGRES_PASSWORD 强密码 (随机 32 字符) # RABBITMQ_PASSWORD 强密码 (随机 32 字符) # SECRET_KEY Django 密钥 (≥ 50 字符) # AWS_ACCESS_KEY_ID MinIO 用,任意字符串 # AWS_SECRET_ACCESS_KEY MinIO 用,任意字符串 # LIVE_SERVER_SECRET_KEY ≥ 32 字符 # GPTPROTO_API_KEY gptproto.com 控制台申请 # PLANE_API_TOKEN 留空,Plane 首次登录后在 god-mode 生成再回填 ${EDITOR:-vim} deploy/local/.env # 3. 启动 cd deploy/local docker compose \ -f src/deployments/cli/community/docker-compose.yml \ -f docker-compose.override.yml \ --env-file .env \ up -d # 4. 等约 30s 让 migrator 跑完,然后健康检查 bash ../../qa/verify-local.sh # 5. 浏览器访问 # http://localhost:8090 Plane Web # http://localhost:8100/healthz AI Agent # http://localhost:8103 自定义 dashboard ``` ## 生产部署 (Linux + 1Panel + OpenResty) 参见 `deploy/remote/README.md` 和 `docs/PLAN.md`。要点: - 容器只绑 `127.0.0.1:`,公网入口由 OpenResty 反代到 HTTPS - `plane.conf` 反代配置已包含 HTTP/1.1 修复 (避免 uvicorn keepalive 超时) - `$http_host` 必须透传 (非 `$host`),否则 MinIO presigned URL 会丢端口导致 CORS 失败 ## 已知坑点 (来自原作者实战,务必读 `CLAUDE.md` 完整版) 1. **Plane v1.3.0 compose 路径** = `src/deployments/cli/community/docker-compose.yml` (旧版的 `src/deploy/selfhost/docker-compose.yml` 已废弃) 2. **macOS Docker Desktop 走系统代理会导致 TLS 失败**: Settings → Resources → Proxies → Manual 但全留空 → Quit (非 Restart) → 重开 3. **gptproto 的 `claude-sonnet-4-6` 当前 60s timeout 不可用**,改用 `claude-sonnet-4-5-20250929` 或 `claude-haiku-4-5-20251001` 4. **改 .env 后 plane-ai 容器要 `up -d --force-recreate plane-ai`**,普通 restart 不彻底 5. **生产路径上禁用 `rsync --delete`** (会清掉服务器上的 git clone 的 src/) ## 端口规划速查 | 服务 | 本地端口 | 生产容器内 | 生产对外 (经 OpenResty) | |---|---|---|---| | Plane Web (proxy) | 8090 | 127.0.0.1:8092 | YOUR_SERVER_IP:8445 (HTTPS) | | AI Agent (FastAPI) | 8100 | 127.0.0.1:8101 | YOUR_SERVER_IP:8446 (HTTPS) | | 自定义 dashboard | 8103 | 127.0.0.1:8103 | YOUR_SERVER_IP:8445/dashboard/ | | Postgres / Redis / MinIO / RabbitMQ | 仅 docker 网络 | 仅 docker 网络 | - | ## 许可证 - Plane 上游源码: AGPL-3.0 (见 `deploy/local/src/LICENSE.txt`) - 本集成代码: 内部使用,请按贵团队规定处理 ## 联系/反馈 部署遇到问题,优先看 `CLAUDE.md` 的"非显然坑点"一节——基本覆盖了实战中遇到的所有陷阱。