diff --git a/README.md b/README.md index 3b51685..566acc0 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,143 @@ -# SenlinAI Agent Workbench +# 森林AI -SenlinAI Agent Workbench 是一个以项目为中心的私有化工作台 MVP。 +## 产品定位 -## 本地开发 +森林AI 是一个以项目为中心、面向私有化部署的工作台 MVP,服务于个人知识工作者、团队负责人和可信的内部用户。它把项目、任务、Inbox 收集、Markdown 笔记、文件资料、AI 会话、项目内标签和轻量任务分发组织在同一工作区中。 -启动本地 PostgreSQL: +Web 客户端桌面优先,同时保留移动浏览器可用性;登录页允许输入私有部署服务器的 IP 地址或域名。 + +## MVP 范围 + +当前版本包含: + +- 项目创建、设置和聚合工作区。 +- 项目内任务、标签、文件资料和计划任务元数据。 +- Inbox 收集、分析建议和用户确认创建对象的流程。 +- 项目、任务和笔记的关键词搜索。 +- 项目内 AI 会话入口、密钥选择、限流与调用审计。 +- React Web 客户端和 Tauri 桌面壳。 + +当前版本不包含实时即时通讯、项目级成员角色体系、匿名公开分享、自主 Agent 执行、语义或向量搜索、第三方数据源集成、原生移动 App、浏览器扩展、离线编辑或本地优先同步。 + +## 技术栈 + +- 后端:Go 1.26.1、Gin、Gorm、PostgreSQL 16。 +- Web:React 18、TypeScript、Vite 8、Arco Design。 +- 桌面端:Tauri 2、Rust stable,共用 Web 构建产物。 +- 本地基础设施:Docker Compose。 + +本仓库当前验证环境使用 Node.js 24.11.0、npm 11.12.1、Rust 1.97.1;其他版本应满足各锁文件与工具链要求。 + +## 目录结构 + +```text +. +├── backend/ # Go API、数据库模型、业务逻辑和演示数据 +│ ├── cmd/api/ # API 入口 +│ ├── cmd/seed/ # 开发演示数据入口 +│ ├── etc/ # 按模式加载的 YAML 配置 +│ └── internal/ # httpx、models 与各业务包 +├── apps/web_v1/ # React + TypeScript 主 Web 客户端 +├── apps/desktop/ # Tauri 桌面壳 +├── infra/docker-compose.yml # 本地 PostgreSQL 16 +└── docs/ # 规格、计划与 MVP 验证说明 +``` + +## 快速开始 + +### 1. 准备环境 + +安装 Go、Node.js/npm 和 Docker Desktop,并确保 Docker Desktop 已启动。桌面端构建还需要 Rust stable 与平台编译工具链。 + +### 2. 启动 PostgreSQL + +在仓库根目录运行: ```powershell docker compose -f infra/docker-compose.yml up -d ``` -启动后端 API: +Compose 只用于本地开发,创建 PostgreSQL 16 服务并监听 `localhost:5432`。其中的默认数据库凭据不得用于生产环境。 + +### 3. 初始化演示数据 + +```powershell +Set-Location backend +go run ./cmd/seed +``` + +默认演示账号为 `demo@senlin.ai`,默认密码为 `password123`。它们只用于本地开发;生产部署必须创建正式用户并替换所有默认凭据与密钥。 + +### 4. 启动 API + +在新的终端中运行: ```powershell Set-Location backend go run ./cmd/api ``` -启动 Web 客户端: +开发配置默认监听 `http://localhost:9150`。可用 `GET /healthz` 检查进程健康状态;Web 登录页使用 `GET /api/v1/status` 检查服务器连接。 + +### 5. 启动 Web 客户端 + +在新的终端中运行: ```powershell Set-Location apps/web_v1 +npm ci npm run dev ``` -## 后端配置 +Vite 默认地址为 `http://localhost:5173`。登录时服务器地址填写 `http://localhost:9150`;也可以通过 `VITE_API_BASE_URL` 指定 Web 的初始 API 地址。 -后端配置不再从多个环境变量直接读取,而是从 `backend/etc/agent..yaml` 读取。 +## 配置 -配置模式由环境变量 `SENLIN_APP_MODE` 决定: +后端从 `backend/etc/agent..yaml` 读取配置。`SENLIN_APP_MODE` 未设置时使用 `backend/etc/agent.dev.yaml`;例如设置 `$env:SENLIN_APP_MODE='prod'` 时读取 `backend/etc/agent.prod.yaml`,该生产文件需由部署方安全提供。 -- 未设置 `SENLIN_APP_MODE` 时,默认读取 `backend/etc/agent.dev.yaml`。 -- 设置 `SENLIN_APP_MODE=prod` 时,读取 `backend/etc/agent.prod.yaml`。 -- 设置其他值时,按同样规则读取 `backend/etc/agent..yaml`。 +| 字段 | 用途 | +| --- | --- | +| `env` | 运行环境标识。 | +| `port` | API 监听端口;开发值为 `9150`。 | +| `dsn` | PostgreSQL 连接串。 | +| `storage_dir` | 服务端文件存储根目录。 | +| `max_upload_bytes` | multipart 请求体大小上限;开发值为 32 MiB。 | +| `auth_secret` | 邀请和登录会话签名密钥。 | +| `system_ai_key` | 可选的系统级 AI provider fallback key。 | +| `ai_key_encryption_secret` | 用户 AI key 的静态加密密钥。 | +| `allowed_origins` | 允许访问 API 的 Web/Tauri 来源列表。 | -默认开发配置文件: +不要提交生产数据库连接串、AI key、会话凭据或真实密钥。开发配置中的固定值和 Compose 数据库账号仅供本地使用,生产环境必须全部替换。修改 Web 来源或端口时,应同步更新 `allowed_origins`,否则浏览器会拦截跨域请求。 -```text -backend/etc/agent.dev.yaml -``` +`go run ./cmd/seed` 还支持 `DATABASE_DSN` 或 `DATABASE_URL` 临时覆盖数据库地址,以及 `SENLIN_SEED_EMAIL`、`SENLIN_SEED_NAME`、`SENLIN_SEED_PASSWORD` 覆盖演示用户信息。 -配置字段: +## API v1 概览 -- `env`: 运行环境,例如 `development`。 -- `port`: API 监听端口,默认开发值为 `8080`。 -- `dsn`: PostgreSQL 连接串。不要提交真实生产或测试凭据。 -- `storage_dir`: 服务端本地文件存储目录。 -- `auth_secret`: 邀请 token 和 session token 的 HMAC 密钥。 -- `system_ai_key`: 可选的系统级 AI provider fallback key。 -- `ai_key_encryption_secret`: 用户 AI key 静态加密密钥。 +业务接口前缀为 `/api/v1`,JSON 字段使用 camelCase,对外 ID 使用 UUIDv7 字符串,时间使用 UTC RFC 3339。除连接状态和登录外,接口都要求有效的 `Authorization: Bearer` 会话凭据。 -## 前端 +| 方法 | 路径 | 成功响应 | +| --- | --- | --- | +| `GET` | `/api/v1/status` | `200`,包含 `timestamp` 的对象;无需登录。 | +| `POST` | `/api/v1/auth/login` | `200`,包含签名且会过期的 `token` 字段;请求体为 `email`、`password`。 | +| `GET` | `/api/v1/projects` | `200`,项目 DTO 数组。 | +| `POST` | `/api/v1/projects` | `201`,项目 DTO。 | +| `GET` | `/api/v1/projects/:projectId` | `200`,项目 DTO。 | +| `PATCH` | `/api/v1/projects/:projectId` | `200`,更新后的项目 DTO。 | +| `GET` | `/api/v1/projects/:projectId/workspace` | `200`,聚合项目、频道、标签、Inbox、任务、AI 会话、笔记资料和计划任务的工作区 DTO。 | +| `POST` | `/api/v1/projects/:projectId/tasks` | `201`,任务 DTO。 | +| `PATCH` | `/api/v1/projects/:projectId/tasks/:taskId` | `200`,更新后的任务 DTO。 | +| `GET` | `/api/v1/projects/:projectId/tags` | `200`,该项目的标签 DTO 数组。 | +| `POST` | `/api/v1/projects/:projectId/tags` | `201`,标签 DTO。 | +| `POST` | `/api/v1/projects/:projectId/sources` | `201`,文件资料 DTO;请求为含 `file` 和可选 `title` 的 multipart 表单。 | +| `POST` | `/api/v1/projects/:projectId/cron-plans` | `201`,计划任务 DTO;只管理元数据,不执行自主 Agent。 | +| `POST` | `/api/v1/projects/:projectId/inbox` | `201`,Inbox 条目 DTO。 | +| `POST` | `/api/v1/inbox/:inboxId/analyze` | `200`,`suggestions` 草稿数组,不创建正式对象。 | +| `POST` | `/api/v1/inbox/:inboxId/confirm` | `200`,含 `createdCount`;只确认服务端已保存且由用户选中的建议。 | +| `GET` | `/api/v1/search?q=...` | `200`,`items` 数组,当前检索项目、任务和笔记。 | +| `GET` | `/api/v1/projects/:projectId/ai-sessions` | `200`,AI 会话 DTO 数组。 | +| `POST` | `/api/v1/projects/:projectId/ai-sessions` | `201`,AI 会话 DTO;请求体只接收 `title`、`context`。 | -Web 客户端使用 React、TypeScript、Vite 和 Arco Design。登录界面允许用户输入服务器 IP 地址或域名,并将其保存为 API base URL。 - -## 桌面端 - -桌面端使用 Tauri 包装 Web 客户端。 - -构建桌面可执行文件: - -```powershell -Set-Location apps/desktop -npm run build -``` - -生成安装包: - -```powershell -Set-Location apps/desktop -npm run bundle -``` +错误统一返回 `{"error":{"code":"...","message":"..."}}`。路径中的项目、任务和 Inbox ID 必须是 UUIDv7;数据库自增 ID 不对外暴露。 ## 验证 @@ -78,7 +145,7 @@ npm run bundle ```powershell Set-Location backend -go test ./... -v +go test ./... ``` Web: @@ -90,11 +157,64 @@ npm run build npm run lint ``` -桌面端: +如果设置了指向隔离测试库的 `DATABASE_URL`,再运行 PostgreSQL 集成检查: + +```powershell +Set-Location backend +go test -tags integration ./internal/models -run TestPostgresPing -v +``` + +不得把真实测试数据库凭据写入仓库。当前机器的逐项执行结果与产物路径见 [MVP 验证说明](docs/mvp-verification.md)。 + +## 桌面端 + +先完成 Web 依赖安装,再构建 Tauri 可执行文件: ```powershell Set-Location apps/desktop +npm ci npm run build ``` -更多验证说明见 `docs/mvp-verification.md`。 +`npm run build` 会先执行 Web 生产构建,再运行 `tauri build --no-bundle`。Windows 产物位于 `apps/desktop/src-tauri/target/release/senlinai_workbench.exe`。 + +需要安装包时运行: + +```powershell +Set-Location apps/desktop +npm run bundle +``` + +打包需要 Rust stable、平台编译工具链和对应安装器依赖;它与无安装包的可执行文件构建是两个独立验证项。 + +## 常见问题 + +### 数据库连接或认证失败 + +确认 Docker Desktop 和 Compose 服务正在运行,并用 `docker compose -f infra/docker-compose.yml ps` 查看状态。若本机已有 PostgreSQL 占用 `5432`,请停止冲突服务或同步修改 Compose 映射与 `backend/etc/agent.dev.yaml` 中的 `dsn`。演示数据和 API 必须连接到同一个数据库。 + +### 浏览器提示无法连接或 CORS 错误 + +先访问 `http://localhost:9150/api/v1/status`。如果 API 可达但浏览器仍失败,检查登录页的服务器地址、协议和端口,并把实际 Web 来源加入 `allowed_origins` 后重启 API。 + +### Vite 端口被占用 + +默认端口是 `5173`。可以停止占用进程,或让 Vite 选择可用端口;使用其他端口时必须同步配置后端 `allowed_origins`。 + +### 演示账号无法登录 + +先成功运行 `go run ./cmd/seed`,再使用 seed 命令输出所对应的开发账号。若通过环境变量覆盖过演示用户信息,应使用覆盖后的值。生产环境不得使用默认演示密码。 + +### AI 会话返回缺少密钥或限流错误 + +创建 AI 会话前会执行每用户、每动作限流并选择加密存储的用户 key 或系统 fallback key。缺少可用 key 时返回服务不可用,超过配额时返回 `429`;不要在前端或提交记录中粘贴 key。 + +## 安全说明 + +- 登录会话使用签名且会过期的 bearer token;服务端从认证中间件读取当前用户,不接受可伪造的用户 ID 字符串。 +- 用户 AI key 加密存储。AI 操作先限流,再选择 provider/key,并记录 provider、key 类型、action、status 和 error;日志不得记录 key 明文。 +- AI 分析和会话不会自动创建正式任务、笔记或资料。Inbox 只有在用户确认服务端保存的建议后才创建对象,并保留来源 Inbox ID。 +- 项目标签只在项目内有效。任务移动、标签写入和文件上传都校验项目所有权。 +- 任务分享遵循最小可见范围:被指派人只能看到任务以及被显式分享的关联对象;分享的 note/source 必须与任务属于同一项目。 +- 文件存储路径只由文件服务构造,上传在写磁盘前校验所有权和请求体大小。 +- 生产部署必须替换所有开发凭据和密钥、限制 CORS 来源、使用独立数据库与受控存储目录,并通过 HTTPS 暴露服务。 diff --git a/docs/mvp-verification.md b/docs/mvp-verification.md index 8ad1e9c..a76ab8f 100644 --- a/docs/mvp-verification.md +++ b/docs/mvp-verification.md @@ -1,101 +1,213 @@ -# MVP Verification +# 森林AI MVP 验证 -## Backend +本文记录 2026-07-21 在 Windows、PowerShell 环境中对当前仓库实际执行的验证。只有获得成功退出码或明确 HTTP 响应的命令列为通过;未满足环境条件的项目单独列出,不视为通过。 -Run: +## 环境基线 + +- Go `1.26.1 windows/amd64` +- Node.js `24.11.0` +- npm `11.12.1` +- Rust `1.97.1` +- Cargo `1.97.1` +- Docker CLI:当前机器不可用 +- `DATABASE_URL`:当前 shell 未设置 + +本地 Compose 与 `backend/etc/agent.dev.yaml` 约定 PostgreSQL 监听 `localhost:5432`,API 监听 `localhost:9150`,Vite 默认监听 `localhost:5173`。Compose 和开发配置中的固定数据库凭据只供本地开发,生产环境必须替换。 + +## 本次结果摘要 + +| 验证项 | 结果 | 说明 | +| --- | --- | --- | +| `go test ./...` | 通过 | 全部 Go 包通过;另以 `-count=1` 无缓存复核通过。 | +| `go run ./cmd/api` | 未通过 | 本机现有 PostgreSQL 的账号配置与开发配置不匹配,初始化时认证失败。 | +| `go run ./cmd/seed` | 未通过 | 与 API 相同,因本机 PostgreSQL 认证失败。 | +| Compose 启动 | 未验证 | 当前机器没有可用的 Docker CLI,未声称启动成功。 | +| Web 依赖安装 | 通过 | `npm ci` 成功,审计未发现漏洞。 | +| Web 短时启动 | 通过 | `npm run dev` 启动;因默认端口已有用户进程,占用时自动选择可用端口,HTTP 根路径返回 `200`。本次进程随后已停止。 | +| Web 视觉检查 | 通过 | `node scripts/visual-check.mjs` 退出 `0`,无未预期 console error。 | +| Web 生产构建 | 通过 | `npm run build` 退出 `0`;存在 bundle 大小警告,不影响构建结果。 | +| Web lint | 通过 | `npm run lint` 退出 `0`。 | +| Web 结构检查 | 通过 | `node scripts/structure-check.mjs` 输出 `structure ok`。 | +| 桌面端依赖安装 | 通过 | `apps/desktop` 下 `npm ci` 成功。 | +| Tauri 可执行文件构建 | 通过 | 冷构建超过单次 240 秒工具等待上限,但已完成 release 编译;同一命令增量重跑 58.3 秒退出 `0`。 | +| Tauri 安装包 | 未验证 | 本次未运行 `npm run bundle`。 | +| PostgreSQL 集成测试 | 未运行 | 当前 shell 未提供 `DATABASE_URL`。 | + +## 本地启动检查 + +### PostgreSQL + +需要 Docker Desktop。仓库根目录的预期命令是: + +```powershell +docker compose -f infra/docker-compose.yml up -d +docker compose -f infra/docker-compose.yml ps +``` + +当前机器无法识别 `docker` 命令,因此这两条命令未验证。不要根据本记录推断 Compose 已成功启动。 + +### 演示数据与 API + +数据库可用后,在两个独立终端中运行: ```powershell Set-Location backend -go test ./... -v +go run ./cmd/seed ``` -Expected: all backend tests pass. +```powershell +Set-Location backend +go run ./cmd/api +``` -## PostgreSQL Integration - -Set `DATABASE_URL` to the live PostgreSQL test database before running integration checks. Do not commit real credentials. - -Run: +本次两条命令都真实执行过,但均在连接本机 PostgreSQL 时因开发账号认证失败而退出。排除本机数据库冲突并成功启动后,应检查: ```powershell +Invoke-RestMethod http://localhost:9150/healthz +Invoke-RestMethod http://localhost:9150/api/v1/status +``` + +预期分别返回 `status: ok` 和 UTC RFC 3339 `timestamp`。`/api/v1/status` 是登录页使用的公开连接检查;其他业务接口除登录外均要求有效 bearer 会话。 + +### Web 开发服务器 + +```powershell +Set-Location apps/web_v1 +npm ci +npm run dev +``` + +本次 `npm ci` 通过。短时启动时默认端口已被用户原有 Vite 进程占用,本次实例自动选择另一个可用端口;对该实例根路径请求得到 HTTP `200`。验证结束后仅停止了本次新建的进程树,用户原有进程未被修改。 + +## 自动化验证 + +### 后端 + +```powershell +Set-Location backend +go test ./... +``` + +本次退出 `0`。为排除 Go 测试缓存影响,还执行了: + +```powershell +go test -count=1 ./... +``` + +无缓存复核同样退出 `0`,覆盖配置、HTTP 路由、认证、项目/工作区、任务、标签、资料、Inbox、关键词搜索、AI key 加密、限流与审计等包。 + +### PostgreSQL 集成测试 + +仅在准备了隔离的实时测试数据库时运行: + +```powershell +$env:DATABASE_URL='<隔离测试库连接串>' Set-Location backend go test -tags integration ./internal/models -run TestPostgresPing -v ``` -Expected: `TestPostgresPing` passes. +连接串必须通过安全的本地或 CI secret 注入,不能提交到仓库。本次 `DATABASE_URL` 未设置,因此没有运行,也不列为通过。 -## Web - -The primary frontend is the React + Arco Design client under `apps/web_v1`. - -Run: +### Web ```powershell Set-Location apps/web_v1 node scripts/visual-check.mjs npm run build npm run lint +node scripts/structure-check.mjs ``` -Expected: visual smoke checks, production build, and lint pass. +四条命令本次均退出 `0`。视觉检查覆盖桌面和移动登录页、工作台、项目导航、Inbox 确认、AI 会话受控创建、深色模式、无横向溢出和无未预期 console error。 -## Desktop +`npm run build` 生成: -Run: +- `apps/web_v1/dist/index.html` +- `apps/web_v1/dist/assets/` +- `apps/web_v1/dist/senlinai-icon.svg` + +`node scripts/visual-check.mjs` 生成的本地证据位于 `apps/web_v1/test-results/`,包括: + +- `login-react-acro.png` +- `login-react-acro-mobile.png` +- `workbench-react-acro-light.png` +- `project-react-acro-light.png` +- `project-react-acro-dark.png` +- `project-navigation-mobile.png` +- `channel-navigation-mobile.png` +- `project-inbox-confirmed.png` +- `project-inbox-confirmed-mobile.png` +- `project-ai-controlled.png` + +`dist/` 与 `test-results/` 都是本地产物,已被 `.gitignore` 排除,不应提交。 + +### 桌面端 ```powershell -Set-Location apps/web_v1 -npm run build -Set-Location ../desktop +Set-Location apps/desktop +npm ci npm run build ``` -Expected: the Tauri desktop executable builds when Rust/Cargo is installed and the stable Rust toolchain is complete. +本次最终重跑退出 `0`。`npm run build` 使用 `tauri build --no-bundle`,并先执行 Web 生产构建。Windows 可执行文件为: -Installer packaging is a separate step: +```text +apps/desktop/src-tauri/target/release/senlinai_workbench.exe +``` + +本次产物大小为 `8,783,360` 字节。冷构建需要下载或编译 Rust 依赖,可能耗时数分钟;本次第一次调用因外部等待工具达到 240 秒上限而返回超时,但编译日志已显示 release 完成和产物生成,随后相同命令增量重跑获得退出码 `0`。 + +安装包是独立验证项: ```powershell Set-Location apps/desktop npm run bundle ``` -Current machine status: -- Cargo and rustc are installed under `%USERPROFILE%\.cargo\bin`. -- If the current shell does not see Cargo yet, prepend `%USERPROFILE%\.cargo\bin` to `PATH` or open a new terminal. -- `npx tauri build --no-bundle --verbose` passes and produces `apps/desktop/src-tauri/target/release/senlinai_workbench.exe`. -- Full installer bundling through `npm run bundle` currently times out in the Tauri CLI bundling stage on this machine before producing `target/release/bundle` artifacts. +本次没有运行该命令,不记录安装包结果。 -## Latest Audit Verification +## API 契约抽查 -Last audited: 2026-07-18. +当前路由注册与 Web API client 均使用 `/api/v1`: -- `backend`: `go test ./... -v` passed. -- `apps/web_v1`: `node scripts/visual-check.mjs` passed. -- `apps/web_v1`: `npm run build` passed. -- `apps/web_v1`: `npm run lint` passed. -- `apps/desktop`: `npx tauri build --no-bundle --verbose` passed and produced the desktop executable. -- `apps/desktop`: installer packaging is still blocked by Tauri CLI bundling timeout on the current machine. +- 公共:`GET /api/v1/status`、`POST /api/v1/auth/login`。 +- 项目与工作区:项目列表/创建/读取/更新,以及项目工作区读取。 +- 任务与标签:任务创建/更新、项目标签列表/创建。 +- 资料与计划任务:multipart 文件资料创建、计划任务元数据创建。 +- Inbox:收集、生成建议、按服务端建议 ID 确认。 +- 搜索:带 `q` 参数的关键词搜索,响应为 `items` 数组。 +- AI 会话:项目会话列表与受控创建,响应为会话 DTO。 -Audit fixes included: +抽查结论:创建接口返回 `201`,读取和当前更新接口返回 `200`;JSON DTO 使用 camelCase,对外路径参数使用 UUIDv7,错误为 `error.code` 与 `error.message` 包装结构。API 不直接返回 Gorm 模型或内部自增 ID。 -- Signed expiring auth session tokens replaced forgeable `user:` tokens. -- Project and inbox HTTP handlers now read the authenticated user from bearer middleware instead of hard-coding user `1`. -- Project dashboard loading now checks project ownership before returning counters. -- Inbox confirmation preserves provenance with `source_inbox_item_id` on generated tasks, notes, and sources. -- Task sharing now rejects note/source links from another project. -- AI user keys are encrypted before storage, decrypted on selection, and can be checked with a per-user action rate limit. -- Web API calls use the backend `/api` prefix, and the active client is now the React + Arco Design workbench. +## 人工 MVP 流程 -## Manual MVP Flow +在 Compose、seed、API 和 Web 均成功启动后,按以下顺序人工验收: -1. Open the client and enter the server IP or domain on the login screen. -2. Create or log in as a private-deployment user. -3. Create a project. -4. Add text to project inbox. -5. Click Analyze/Organize. -6. Confirm one task and one note from the suggestion list. -7. Assign the task to another system user. -8. Explicitly share one note with the task. -9. Search for text from the note body in global search. -10. Open an AI session under the project and reference the note. -11. Use Tauri quick capture to send text into the active project inbox. +1. 打开 Web 客户端,在登录页输入服务器 IP 地址或域名。 +2. 使用仅供开发的演示账号登录,并确认生产部署未使用默认凭据。 +3. 创建项目,修改项目设置,再刷新确认数据保留。 +4. 创建项目内标签和任务,验证任务卡显示真实标签与状态。 +5. 上传文件资料,确认返回路径是相对存储路径,且越权项目不能留下文件。 +6. 创建计划任务元数据,确认界面没有暗示自主 Agent 已执行。 +7. 收集一条 Inbox 内容,先分析建议;此时不应出现正式对象。 +8. 选择一条或多条服务端建议并确认,验证生成对象保留来源 Inbox ID。 +9. 用关键词搜索项目、任务和笔记,确认用户只能看到有权访问的结果。 +10. 创建项目 AI 会话,确认缺 key、限流和服务错误有明确提示,且不会自动生成正式对象。 +11. 在桌面与移动视口检查项目/频道导航、焦点状态和横向溢出。 +12. 启动桌面可执行文件,逐项检查登录持久化、拖拽上传、通知和全局快捷收集等 MVP 目标;未实际走通的能力不得记为通过。 + +## 安全复核清单 + +- 生产环境已替换数据库凭据、`auth_secret`、AI key 加密密钥和所有开发默认值。 +- 未提交数据库连接串、用户 AI key、会话凭据、日志、数据库文件、上传文件或构建产物。 +- 登录凭据由签名且会过期的 bearer session 校验,handler 从认证上下文获取用户。 +- 用户 AI key 加密存储;AI 操作在 key/provider 选择前占用限流配额,并写 provider、key 类型、action、status 和 error 审计。 +- AI 输出只形成待确认草稿;用户确认前不创建任务、笔记或资料。 +- 项目标签保持项目内范围;任务分享的 note/source 与任务属于同一项目。 +- 被指派人只看到任务和明确分享的关联对象。 +- PostgreSQL 集成测试只使用显式 `DATABASE_URL` 指向的隔离测试库。 + +## 文档一致性检查 + +已对两份文档执行旧品牌、旧 API 前缀、旧前端目录和旧技术栈关键词扫描,结果无匹配。还应抽查 Markdown 相对链接存在,所有命令的工作目录与仓库实际脚本一致。