Files
storage-labos/CONTRIBUTING.md
T
yuanshuai 79813e56f9
CI / Python 3.12 (push) Waiting to run
CI / Python 3.9 (push) Waiting to run
docs(ai): add standalone system operating guide
2026-07-27 20:51:45 +08:00

566 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STORAGE LABOS / FlashOps — AI 协作与系统操作指南
> 文档版本:1.0
>
> 核对日期:2026-07-27
>
> 适用对象:Codex、Claude Code、Cursor、GitHub Copilot Agent,以及参与项目的人类开发者
>
> 目标:只把本文件交给 AI,也能让它安全地理解、运行、修改、验证和交付本系统
本文件是 AI 接手项目时的第一入口。更完整的产品、架构、数据模型、状态机和生产运维说明见
[ProjectManual.md](ProjectManual.md)。如果本文件与代码冲突,以代码和测试为准,并在本次变更中
同步修正文档;如果生产信息与代码冲突,先做只读核验,不要凭文档直接修改服务器。
---
## 0. 直接交给 AI 的任务开场词
把下面内容和具体任务一起发给 AI
~~~text
你正在维护 STORAGE LABOS / FlashOps。
请先完整阅读仓库根目录 CONTRIBUTING.md,再按其中的权限边界、架构红线、测试门禁和
Git 交付流程工作。需要深入理解时再阅读 ProjectManual.md 及 flashops/docs/。
先检查仓库状态并保护现有未提交改动。默认只操作本地开发环境;除非任务明确要求,不得修改
生产服务器、生产数据、DNS、证书、Gitea 设置或调用生产环境写接口。任何真实硬件、固件刷写、
Format、Sanitize、Reset、断电或 OOB 动作都必须停下并取得明确授权。
任务:<在这里写具体目标>
完成后请报告:改动文件、关键决策、测试结果、未完成项、风险、提交号和远程分支。
~~~
---
## 1. AI 必须先记住的系统事实
| 项目 | 当前值 |
|---|---|
| 产品 | STORAGE LABOS,后端代号 FlashOps |
| 用途 | 存储固件回归测试的无人值守控制平面 |
| Git 网页 | <https://git.imagebrewing.com/yuanshuai/storage-labos> |
| 克隆地址 | <https://git.imagebrewing.com/yuanshuai/storage-labos.git> |
| 默认分支 | main |
| 公网预览 | <https://flashops.imagebrewing.com/> |
| 公网 API 文档 | <https://flashops.imagebrewing.com/docs> |
| 本地控制台 | <http://localhost:8000/console/Dashboard.dc.html> |
| 本地 API 文档 | <http://localhost:8000/docs> |
| 后端 | Python 3.9+、FastAPI、SQLAlchemy |
| 当前数据库 | SQLite,必须保持单 worker |
| 当前执行能力 | 模拟 Run 与 Agent dry-run;不代表真实硬件动作已交付 |
| 当前测试基线 | 25 项 |
| 生产认证边界 | 预览站匿名开放,尚无应用级 RBAC |
| Gitea | 公开仓库匿名可读;注册账号需管理员批准 |
| CI | 生产服务器没有 Runner,测试结果必须由提交者本地提供 |
重要:公网预览虽然没有登录限制,但这不等于 AI 获得了生产写权限。当前部分 POST 接口在技术上
也能匿名调用,这是尚未补齐 RBAC 的原型边界,不应被当作授权。
---
## 2. 权限与行为边界
AI 应按以下顺序判断是否可以行动:
| 行为 | 默认是否允许 | 条件 |
|---|---:|---|
| 阅读仓库、文档、Git 历史 | 是 | 保持只读 |
| 查看公网页面、调用健康检查和 GET 查询 | 是 | 不产生业务状态变化 |
| 在本地新分支修改代码和文档 | 用户要求开发时允许 | 保护已有改动 |
| 本地运行测试和模拟演示 | 是 | 不连接真实设备 |
| 创建本地模拟 Run | 是 | 仅使用本地数据库 |
| 提交 Git | 用户要求开发或交付时允许 | 检查范围、测试和秘密后提交 |
| 推送功能分支 | 用户要求共享或交付时允许 | 不强推 main |
| 合并 Pull Request | 否 | 需要仓库负责人明确授权或正常评审 |
| 调用生产 POST、PATCH、PUT、DELETE | 否 | 必须得到针对该动作的明确授权 |
| 修改 DNS、Nginx、systemd、证书、Gitea 设置 | 否 | 必须明确要求部署或运维 |
| 操作真实 DUT、NVMe、固件或 OOB | 否 | 必须明确目标、批准范围和回滚方案 |
| Format、Sanitize、刷写、Reset、断电 | 绝不默认执行 | 需要明确授权、可牺牲 DUT、审批和证据链 |
遇到权限不清时,继续完成安全的本地分析、测试或方案设计,把真正需要授权的动作单独列出。
---
## 3. 信息源优先级
AI 不应只根据文件名或旧说明猜测当前能力,按下面顺序取证:
1. 当前用户的明确任务与限制;
2. 当前工作树、Git diff 和实际源码;
3. 自动化测试及可重复的本地运行结果;
4. 本文件;
5. ProjectManual.md
6. flashops/docs/ 下的架构、状态机和 ADR;
7. README、历史提交、部署模板;
8. 推测。
如果代码、测试和文档互相矛盾,必须在交付说明中指出。不得把“规划”“草案”“静态页面”描述成
已经可用于真实硬件的能力。
---
## 4. 第一次接手:安全启动流程
### 4.1 全新克隆
~~~bash
git clone https://git.imagebrewing.com/yuanshuai/storage-labos.git
cd storage-labos
git status -sb
cd flashops
make setup
make test
make demo
~~~
make setup 会初始化本地虚拟环境,并重建 flashops/var 下的本地 SQLite 数据。它只适合全新克隆
或确认可以重置的本地开发环境;如果工作目录里已有需要保留的本地演示数据,不要直接运行。
### 4.2 已存在的工作目录
~~~bash
git status -sb
git diff
git diff --cached
git log -5 --oneline
~~~
先识别用户已有的未提交改动。不得使用 reset --hard、checkout 丢弃文件、clean -fd 或其他会
抹掉用户工作的命令。不得把不相关改动混进自己的提交。
### 4.3 推荐阅读路线
按任务读取最少但足够的资料:
| 任务 | 必读文件 |
|---|---|
| 普通开发 | 本文件、根 README、flashops/README.md |
| 状态机或恢复 | flashops/docs/state-machine.md、decisions/0003-* |
| 事件和数据一致性 | flashops/docs/domain-model.md、decisions/0002-* |
| 安全门禁 | flashops/docs/decisions/0004-*、safety/gates.py |
| Agent | flashops/docs/agent-protocol.md、services/host-agent/README.md |
| 工作流 | flashops/docs/workflow-spec.md |
| 适配器或真实工具 | flashops/docs/adapter-sdk.md |
| 部署、域名、备份 | ProjectManual.md 第 12 章、flashops/deploy/ |
---
## 5. 系统结构与当前边界
~~~text
STORAGE LABOS/
├── CONTRIBUTING.md AI 与团队统一入口
├── ProjectManual.md 完整产品、开发和运维手册
├── README.md 项目总览
├── .gitea/ PR 模板与未来 CI 工作流
├── flashops/
│ ├── services/control-plane/ FastAPI 控制平面
│ ├── services/host-agent/ 拉模式 Host Agent
│ ├── docs/ 架构、协议、状态机、ADR
│ ├── deploy/ FlashOps 与 Gitea 部署模板
│ ├── var/ 本地数据库和证据,禁止提交
│ ├── Makefile 开发和验证入口
│ └── README.md 可运行能力说明
└── 前端UI八页面完成/ FastAPI 同源挂载的静态控制台
~~~
当前已经具备:
- FastAPI 控制平面、14 张持久化表和 SQLite 数据库;
- Run 事件溯源、状态投影、状态机和安全门禁;
- 模拟回归、故障注入、L1–L3 恢复演示和 Evidence Bundle
- Agent 注册、token、心跳、步骤租约、ACK、续租、事件、完成、超时回收和幂等链路;
- 公开预览控制台及部分真实 API 接入页面。
当前不应声称已经具备:
- 真实 nvme-cli 固件刷写、Format 或 Sanitize
- 真实 JetKVM、PDU 或 AC 断电控制;
- 完整 SSO、RBAC、审批与审计授权;
- 多工位生产调度、PostgreSQL 高可用;
- 已验收的失败聚类自动决策。
---
## 6. AI 如何安全使用正在运行的系统
### 6.1 公网只读检查
以下请求只读取公开信息,可用于健康诊断:
~~~bash
curl -fsS https://flashops.imagebrewing.com/api/v1/health
curl -fsS https://flashops.imagebrewing.com/api/v1/dashboard/summary
curl -fsS 'https://flashops.imagebrewing.com/api/v1/runs?limit=10'
curl -fsS https://flashops.imagebrewing.com/api/v1/agent/hosts
~~~
不要在诊断任务中为了“试一下”调用生产 POST 接口。健康检查成功不代表业务能力或真实硬件已经验收。
### 6.2 本地启动
~~~bash
cd flashops
make dev
~~~
另开终端检查:
~~~bash
curl -fsS http://127.0.0.1:8000/api/v1/health
curl -fsS http://127.0.0.1:8000/api/v1/dashboard/summary
~~~
### 6.3 本地创建安全的模拟 Run
只在 localhost 使用下面示例:
~~~bash
curl -fsS -X POST http://127.0.0.1:8000/api/v1/runs \
-H 'Content-Type: application/json' \
-d '{
"name": "AI local verification",
"loops": 2,
"inject_failure": true,
"execution_mode": "simulated",
"created_by": "ai-local"
}'
~~~
返回 Run ID 后:
~~~bash
curl -fsS http://127.0.0.1:8000/api/v1/runs/RUN_ID
curl -fsS 'http://127.0.0.1:8000/api/v1/runs/RUN_ID/events?after_seq=0'
~~~
也可以直接执行 make demo;它会创建独立的本地模拟链路并输出 Evidence Bundle 路径。
### 6.4 API 快速索引
| 方法与路径 | 含义 | 默认安全级别 |
|---|---|---|
| GET /api/v1/health | 服务健康 | 只读 |
| GET /api/v1/dashboard/summary | 汇总指标 | 只读 |
| GET /api/v1/runs | Run 列表 | 只读 |
| GET /api/v1/runs/{run_id} | Run 详情与证据 | 只读 |
| GET /api/v1/runs/{run_id}/events | 增量事件 | 只读 |
| GET /api/v1/agent/hosts | Agent Host 状态 | 只读 |
| POST /api/v1/preflight | 安全预检 | 计算型;生产调用仍需明确目的 |
| POST /api/v1/runs | 创建 Run | 写操作;生产默认禁止 |
| POST /api/v1/runs/demo | 创建演示 Run | 写操作;生产默认禁止 |
| POST /api/v1/runs/{id}/pause | 暂停 | 写操作 |
| POST /api/v1/runs/{id}/resume | 继续 | 写操作 |
| POST /api/v1/runs/{id}/emergency-stop | 紧急停止 | 高影响写操作 |
| POST /api/v1/agent/* | Agent 注册与执行协议 | 凭据操作;不得随意调用 |
请求体和响应模型以运行时 OpenAPI 为准。本地启动后优先读取
<http://localhost:8000/openapi.json> 或 <http://localhost:8000/docs>,不要凭记忆构造字段。
### 6.5 Agent 使用规则
- 生产注册需要 X-FlashOps-Enrollment-Token
- 注册成功返回的原始 bearer token 只出现一次,只能保存到权限 0600 的本机状态文件;
- 后续 Agent 请求使用 Authorization: Bearer
- ACK、续租、事件和完成接口要求 UUID 格式的 Idempotency-Key
- 不得把 enrollment token、bearer token 或 agent-state.json 输出到聊天、日志或 Git;
- 未经授权不得代表真实 Host 注册、轮换 token 或领取生产步骤;
- 日常开发优先使用 make dev-agent、make agent-demo 和测试夹具。
---
## 7. 三条不可破坏的架构红线
### 7.1 控制面是状态唯一真相
Agent 和测试主机只持有执行缓存。Run、Step、锁、检查点和证据索引的权威状态在控制平面。
不得把 Agent 本地状态反向当成数据库真相。
### 7.2 状态变化必须追加事件
所有 Run 状态变化必须经过 events/recorder.py 的 append_event。不得绕过事件记录直接 UPDATE
Run 状态。新增状态或事件时必须同步修改枚举、转移表、投影逻辑、测试和文档。
### 7.3 安全默认拒绝
序列号、破坏性授权、系统盘、固件型号、Host 和 OOB 任一条件不满足都必须拒绝下发。危险步骤
默认不可自动重试。数据完整性失败要冻结现场,不能为了完成率自动重跑并覆盖证据。
---
## 8. AI 修改代码的标准流程
### 8.1 开始前
1. 确认用户目标属于解释、诊断、开发还是部署;
2. 检查 Git 状态、当前分支和已有改动;
3. 阅读与任务直接相关的源码、测试和文档;
4. 找到当前行为的证据,不能只根据 UI 文案猜测;
5. 若涉及高影响选择,先说明方案和边界。
### 8.2 实现时
- 修改现有项目,不随意建立第二套平行架构;
- 优先小而完整的改动,不混入无关格式化;
- 修复缺陷时增加能复现问题的测试;
- API、状态、事件、环境变量或部署变化必须同步文档;
- 保持 Python 3.9 兼容,不在未修改运行基线前使用更高版本独占语法;
- SQLite 环境保持单 worker
- 不绕过 service、event recorder、state machine 或 safety gate
- 保留用户未提交的改动,不擅自覆盖或清理。
### 8.3 完成前
~~~bash
cd flashops
make test
make demo
~~~
回到仓库根目录:
~~~bash
git status -sb
git diff --check
git diff --stat
~~~
只暂存本次任务相关文件:
~~~bash
git add <明确的文件或目录>
git diff --cached --stat
git diff --cached --check
~~~
AI 还必须确认暂存区没有:
- .env、密码、Token、私钥或证书私钥;
- SQLite、日志、Evidence Bundle、Agent state
- 虚拟环境、缓存、构建输出;
- 未脱敏的客户数据或真实设备标识;
- 无关的用户改动。
---
## 9. 测试与验收门禁
| 变更类型 | 最低验证 |
|---|---|
| 纯文档 | 链接和命令核对、git diff --check |
| Python 逻辑 | make test |
| 状态机、恢复、安全 | 对应单测 + make test + make demo |
| API | 正常、错误、幂等或冲突路径测试 |
| Agent | 控制面与 host-agent 测试,凭据权限检查 |
| 前端 | 真实浏览器检查受影响页面,确认控制台与 API 一致 |
| Nginx | nginx -t 后才能 reload |
| systemd | systemd-analyze verify 或目标机安全验证 |
| 生产部署 | 本地测试、备份、健康检查、HTTPS、日志和回滚检查 |
测试失败时不得把失败包装成完成。先判断是本次回归、环境差异还是已有问题,并保留原始证据。
---
## 10. Git 与 Gitea 交付规范
### 10.1 分支
- main:稳定、可测试、可发布,禁止强推;
- feat/<short-name>:功能;
- fix/<short-name>:缺陷;
- docs/<short-name>:文档;
- chore/<short-name>:工具、依赖和部署。
~~~bash
git switch main
git pull --ff-only
git switch -c docs/ai-operating-guide
~~~
### 10.2 提交
使用 Conventional Commits
| 类型 | 示例 |
|---|---|
| feat | feat(agent): add signed command registry |
| fix | fix(events): preserve sequence under concurrent writes |
| docs | docs(ai): add system operating guide |
| test | test(safety): reject system disk target |
| refactor | refactor(runs): isolate checkpoint projection |
| perf | perf(api): reduce event timeline query cost |
| chore | chore(deploy): pin gitea image |
一次提交只表达一个完整意图。提交前检查暂存区,不能用一条模糊提交吞掉多项无关工作。
### 10.3 推送与 Pull Request
~~~bash
git commit -m 'docs(ai): add system operating guide'
git push -u origin docs/ai-operating-guide
~~~
在 Gitea 创建 Pull Request,说明:
- 改了什么、为什么;
- 影响的系统边界;
- 实际运行的测试及结果;
- 安全影响;
- 风险、回滚方法和未完成项。
至少一名团队成员评审后合并。优先 Squash mergePR 标题使用 Conventional Commit。
生产服务器没有 Gitea Actions Runner;仓库中的工作流是未来隔离 Runner 的模板,不能把“工作流存在”
误报成“CI 已运行”。
### 10.4 凭据
公开仓库允许匿名读取和克隆。写操作需要经过批准的 Gitea 账号。管理员密码和访问令牌只允许存在于
系统钥匙串、密码管理器或被 .gitignore 覆盖的本机文件中;不得写进 remote URL、文档、脚本或提交。
---
## 11. 生产部署上下文
| 资源 | 当前值 |
|---|---|
| 云服务器 | 腾讯云 CVM62.234.39.66 |
| FlashOps 域名 | flashops.imagebrewing.com |
| FlashOps 服务 | flashops.service |
| 应用目录 | /data/wangzhan/app/storage-labos |
| 内部端口 | 127.0.0.1:18080 |
| 应用数据 | /data/wangzhan/app/storage-labos/flashops/var |
| 私有环境文件 | /etc/flashops/flashops.env |
| Gitea 域名 | git.imagebrewing.com |
| Gitea 容器 | gitea,镜像版本固定为 1.27.0 |
| Gitea 内部端口 | 127.0.0.1:13000 |
| Gitea 实时数据 | /data/gitea/data |
| COS 挂载 | /chucun |
| Gitea 备份 | /chucun/wangzhan-production/backups/gitea/ |
生产操作规则:
1. 只有用户明确要求部署或运维时才连接服务器;
2. 先核对主机、域名、当前服务、端口和目标文件;
3. 部署前运行本地测试并备份当前版本和数据;
4. 不直接在服务器编辑项目源码,应由 Git 提交或可核验发布包交付;
5. Nginx 修改必须先测试配置再 reload;
6. SQLite 继续使用单 worker,扩展并发前先迁移 PostgreSQL
7. Gitea 实时仓库和 SQLite 不得放到 COSFS
8. COS 只作备份目标,备份需要 ZIP 与 SHA-256 sidecar
9. 不在输出中展示 SSH、Gitea、Agent、DNS 或云平台凭据;
10. 部署后验证内部 health、外部 HTTPS、最终跳转、日志和回滚点。
FlashOps 当前是匿名预览环境。接入真实硬件或非公开数据前,必须先完成应用级 SSO / RBAC、
审批、审计和命令模板签名;不能只依赖 Nginx Basic Auth。
---
## 12. 常见任务剧本
### 12.1 “看看项目并继续完善”
1. 阅读本文件、README 和相关源码;
2. 运行测试与演示建立基线;
3. 区分已实现、部分实现和待实现;
4. 优先选择一个能独立验收的纵向切片;
5. 实现、补测试、同步文档;
6. 报告实际证据,不把规划写成完成。
### 12.2 “排查网站打不开”
1. 从公网检查 DNS、TLS、重定向和最终状态码;
2. 检查 Nginx 生效配置和日志;
3. 检查本机内部端口和服务状态;
4. 区分 401、403、404、502 和浏览器缓存;
5. 诊断任务只报告原因,除非用户同时要求修复。
### 12.3 “修改 API”
1. 阅读路由、schema、service 和相关测试;
2. 保持业务逻辑不堆在 route
3. 状态写入走事件记录;
4. 为正常与错误路径增加测试;
5. 检查 OpenAPI
6. 更新 ProjectManual 和本文件中的接口索引。
### 12.4 “增加真实硬件能力”
先停止直接实现危险命令。必须先确认:
- 使用可牺牲 DUT,不是系统盘;
- 有明确序列号和固件型号匹配;
- 已实现签名命令模板与 allowlist;
- 有审批、短期授权、审计和 Evidence Bundle
- Agent 与控制面身份可信;
- 有恢复、急停和人工接管方案;
- 用户明确批准真实动作。
条件不完整时,只允许实现接口、模拟器、只读探针和测试。
### 12.5 “发布一个版本”
1. 确认工作树和目标提交;
2. 运行完整测试与演示;
3. 检查秘密和发布范围;
4. 备份服务器应用数据;
5. 部署可追溯提交;
6. 重启并验证内部与公网健康;
7. 检查日志、证书和备份;
8. 记录提交号、时间、验证结果和回滚点。
---
## 13. AI 交付时的固定报告格式
AI 最终回复至少包含:
~~~text
结果:
- 本次目标是否完成
改动:
- 文件与关键行为
验证:
- 实际运行的命令
- 通过/失败数量
- 浏览器或生产验收结果
Git
- 分支
- 提交号
- Pull Request 或远程地址
风险与边界:
- 尚未实现或未验证的内容
- 是否涉及生产、真实设备或凭据
下一步:
- 仅列真正需要用户决定或后续开发的事项
~~~
不得只说“应该可以”“理论上完成”。必须区分已执行验证、静态检查和推断。
---
## 14. 完成定义
一项 AI 开发任务只有同时满足以下条件才算完成:
- 用户要求的行为已经实现,而不是只写方案;
- 原有未提交工作得到保护;
- 相关测试通过,或失败原因被明确记录;
- 安全门禁、事件写路径和状态机未被绕过;
- 文档与实际代码、API 和部署保持一致;
- 没有提交凭据、生产数据或运行产物;
- Git 提交范围清晰并可回滚;
- 如果要求部署,公网、内部健康、日志和备份均已验证;
- 最终报告包含证据、提交号、风险和边界。
当本文件中的域名、端口、路径、API、安全策略、测试数量或部署结构发生变化时,修改代码的 AI
必须在同一个 Pull Request 中同步更新本文件。