- backend: FastAPI 应用工厂、统一错误信封、JWT、短信登录、工作区/成员/邀请、幂等中间件 - alembic 0001: workspace/member/invitation/audit_log/app_user + RLS 策略 + 双角色 GRANT - tests: 认证/工作区/租户隔离/幂等 四组用例(尚未在本机执行) - web: React18+Vite 骨架(登录、工作区、邀请落地页) - android: Compose 骨架(登录、工作区列表) - 2.Design: PRODUCT-PLAN / ROADMAP-M0-M1 / NAMING / DEVELOPMENT
494 lines
28 KiB
Markdown
494 lines
28 KiB
Markdown
# DadaoTask 产品与技术方案
|
||
|
||
> 版本 **v1.0** · 2026-10-28 · 状态:已确认关键技术决策,可进入 M0
|
||
> v0.1 → v1.0 的变化:单租户改为 **SaaS 多租户**;删除离线同步;LLM 明确为 **OpenAI 兼容网关 + BYOK**;新增微信/飞书集成层与合规章节。
|
||
|
||
---
|
||
|
||
## 1. 一页纸结论
|
||
|
||
**定位**:一个"个人工作流"内核 + 按需外扩的协作 + 自动沉淀的知识库,三者由 LLM 贯通。**SaaS 形态,个人版免费起步,团队版按席位收费。**
|
||
|
||
**核心判断**:任务、工单、知识库不是三个并列模块,而是**同一件事的三个阶段**。拆成三个独立产品(滴答清单/禅道/Notion)的代价是重复输入、信息断层、知识库沦为第二个垃圾场。
|
||
|
||
```
|
||
想法 ──▶ 任务 ──(需要别人)──▶ 工单 ──(验收通过)──▶ 知识卡
|
||
│ │ │ │
|
||
└────────┴────────────────────┴─────────────────────┘
|
||
LLM 在每一段之间自动搬运、结构化、建立索引
|
||
```
|
||
|
||
**三条不可妥协**:
|
||
|
||
| 原则 | 含义 | 反面 |
|
||
|---|---|---|
|
||
| 一条流 | 任务升级工单不搬数据,时间线不断裂,知识卡可回链源头 | 工单从任务"复制"出去,两边各改各的 |
|
||
| 闭环沉淀 | 知识由已完成工作自动生成草稿,人只做确认/丢弃 | 让人下班后回忆今天学了什么再手敲 |
|
||
| LLM 只出草稿 | AI 写入一律 `suggestion` 待审,人点确认才落库 | AI 自动建 200 条任务,用户从此关闭该功能 |
|
||
|
||
**工期**:2 人约 14 周;第 10 周末可对外测(有任务+工单+知识+AI 的完整闭环)。
|
||
|
||
---
|
||
|
||
## 2. 已确认的决策(决策记录)
|
||
|
||
| # | 决策 | 选择 | 对方案的影响 |
|
||
|---|---|---|---|
|
||
| 1 | 商业模式 | **SaaS,未来对外卖** | 多租户、注册引导、套餐计量、计费钩子必须进 M0;数据隔离是最高优先级风险 |
|
||
| 2 | 离线能力 | **不需要,在线优先** | 删掉 outbox/冲突合并/CRDT,省约 4 周;安卓变成"在线客户端 + 只读缓存" |
|
||
| 3 | LLM 接入 | **标准 OpenAI 兼容接口**;系统自带 DeepSeek,用户可配 Ollama 等 | 引入 LLM 网关:provider 注册、密钥加密、能力探测、按租户路由与计量 |
|
||
| 4 | 后端 | **FastAPI** | 直接支持 SSE 流式、async、OpenAPI 自动出两端 SDK |
|
||
| 5 | 集成 | **微信 + 飞书** | 新增集成层(SSO / 通知 / Bot 三平面);需先明确"微信"= 企业微信还是公众号(见 §10.0) |
|
||
| 6 | 历史数据 | **无** | 知识库冷启动要靠"闭环沉淀 + 示例内容 + IM 聊天抽取",不能指望导入 |
|
||
|
||
---
|
||
|
||
## 3. 服务谁(SaaS 下的定位)
|
||
|
||
不是"更好的 Jira",也不是"更全的 Notion"。定位:
|
||
|
||
> **给"一个人干很多事、偶尔要拉人协作"的角色用。** 先服务单个专业用户(免费),当他的协作半径变大,自然升级到团队版。
|
||
|
||
| 阶段 | 用户 | 付费理由 |
|
||
|---|---|---|
|
||
| 免费 | 独立开发者、技术负责人、一人公司 | 任务 + 知识 + 少量 AI 额度 |
|
||
| Pro | 重度个人用户 | AI 额度、语义检索、画像、周报 |
|
||
| Team | 3–50 人小团队 | 席位、工单 SLA、权限、飞书/企微集成、审计 |
|
||
|
||
**与现有产品的边界**(写清楚是为了不被打):
|
||
|
||
| 产品 | 我们不做 | 我们做它做不了的 |
|
||
|---|---|---|
|
||
| 滴答 / Todoist | 极致 GTD、习惯打卡 | 任务能升级成有验收的工单并沉淀知识 |
|
||
| 禅道 / Jira | 大型敏捷、sprint、缺陷全家桶 | 轻到一个人就能用,不需要流程专家 |
|
||
| Notion / 语雀 | 块编辑器、Wiki 治理 | 知识从工作流里自动长出来 |
|
||
| 飞书 / 企微 | IM 本体 | 把聊天里的"事"沉淀成可追踪对象(我们做它的插件) |
|
||
|
||
---
|
||
|
||
## 4. 九个核心设计决策
|
||
|
||
### D1 · 统一实体 `item`,任务与工单同表
|
||
`item` 存共有字段,`type ∈ {task, ticket, note}`;工单专属字段放 1:1 的 `ticket_ext`。
|
||
**理由**:两者 80% 字段重合;分表会导致升级搬数据、时间线断裂、搜索 UNION、知识来源挂两套外键。**放弃**:全单表 + JSONB(SLA 计算要写 JSON 路径,约束退化)。
|
||
|
||
### D2 · 一切皆事件:`activity` 是唯一真相源
|
||
所有变更写 `activity`(who/what/changed_fields)。一张表同时喂四个消费者:时间线、审计、知识沉淀素材、LLM 上下文。
|
||
|
||
### D3 · 知识是工作流的产物
|
||
`knowledge_doc` 独立成表(有审核/版本/过期生命周期),但**必须能**带 `source_item_id`。入口三个:工单关闭自动生成、手动随手记、IM 消息抽取。
|
||
**理由**:知识库失败从来不是功能少,是没人写。
|
||
|
||
### D4 · 人的画像 `person_profile`
|
||
由 activity/item/knowledge 聚合,LLM 定期生成结构化事实(负责领域、近期事项、待跟进),带生成时间与"过期重算"。
|
||
只描述**工作事实**,不做性格或绩效评价 —— 产品伦理,也避免用户反感。
|
||
|
||
### D5 · LLM 写入必须过审:`suggestion` 表
|
||
AI 一切结构性写入(建任务、改状态、打标签、合并知识)都落 `suggestion(status=pending)`,人接受/修改/忽略后才 apply。
|
||
**理由**:AI 直接写库是所有 AI 产品翻车的头号原因;审批流同时把 AI 从"黑箱"变成"助理"。
|
||
|
||
### D6 · 多租户:共享库 + `workspace_id` + PostgreSQL RLS
|
||
**这是 v1.0 最重要的变更。** 每个租户表都带 `workspace_id`,靠 RLS 做第二道防线(应用层照常过滤,RLS 兜底漏写条件的 bug)。
|
||
**放弃**:schema-per-tenant(迁移要跑 N 次、连接池难管)、DB-per-tenant(成本高)。
|
||
**逃生口**:大客户私有化 = 同一套代码换 DSN,即"cell 模式",不为它改代码。
|
||
**铁律**:多租户必须第一天做对,事后补是灾难 —— 一条漏写 `workspace_id` 的查询就是一次数据泄露事故。
|
||
|
||
### D7 · 在线优先,不做离线同步
|
||
写操作走乐观 UI + 幂等键重试;安卓用 Room 仅作**只读缓存**(不是真相源)。
|
||
**理由**:已确认不需要离线。省掉 outbox、冲突合并、墓碑、单调游标这 4 周工作量。
|
||
|
||
### D8 · 检索只用 Postgres
|
||
`pg_trgm` + 中文分词(`zhparser` / `pg_bigm`)+ `pgvector` HNSW。
|
||
**多租户细节**:向量检索必须带 `workspace_id` 过滤;用 pgvector ≥ 0.8 的 iterative scan,或按租户建**部分索引**,避免"跨租户召回再过滤"把 top-k 稀释。
|
||
|
||
### D9 · LLM 网关:OpenAI 兼容 + BYOK + 平台兜底
|
||
一个 `LLMProvider` 抽象层兼容所有 OpenAI 协议实现(DeepSeek / OpenAI / Ollama / 通义 / 智谱 / 月之暗面)。
|
||
平台自带 DeepSeek 按套餐给额度;用户可自带 key 与 base_url。密钥加密存储、永不回显、永不进日志。
|
||
|
||
### D10 · 集成层三平面
|
||
SSO(扫码登录)/ 通知(消息卡片)/ Bot(在 IM 里建任务)。三者各自是适配器,不耦合进领域逻辑;出站通知落库后由异步分发,IM 挂了不阻塞主流程。
|
||
|
||
---
|
||
|
||
## 5. 领域模型
|
||
|
||
### 5.1 实体关系
|
||
|
||
```mermaid
|
||
erDiagram
|
||
WORKSPACE ||--o{ MEMBER : has
|
||
USER ||--o{ MEMBER : joins
|
||
WORKSPACE ||--o| SUBSCRIPTION : "billed by"
|
||
WORKSPACE ||--o{ LLM_PROVIDER : configures
|
||
WORKSPACE ||--o{ INTEGRATION : connects
|
||
USER ||--o{ ITEM : owns
|
||
ITEM ||--o| TICKET_EXT : extends
|
||
ITEM ||--o{ ITEM_LINK : links
|
||
ITEM ||--o{ COMMENT : has
|
||
ITEM ||--o{ ACTIVITY : logs
|
||
ITEM ||--o| KNOWLEDGE_DOC : "distills to"
|
||
KNOWLEDGE_DOC ||--o{ CHUNK : "split into"
|
||
USER ||--o| PERSON_PROFILE : "profiled by"
|
||
SUGGESTION }o--|| ITEM : "applies to"
|
||
THREAD ||--o{ MESSAGE : contains
|
||
WORKSPACE ||--o{ USAGE_EVENT : meters
|
||
```
|
||
|
||
### 5.2 表清单(22 张;MVP 需 14 张)
|
||
|
||
| 表 | 作用 | 关键字段 | MVP |
|
||
|---|---|---|---|
|
||
| `workspace` | 租户 | id, name, slug, plan, status | ✅ |
|
||
| `user` | 账号(跨租户唯一) | id, phone, email, name, avatar, password_hash | ✅ |
|
||
| `member` | 成员与角色 | ws_id, user_id, role, status, invited_by | ✅ |
|
||
| `invitation` | 邀请 | ws_id, token, role, expires_at | ✅ |
|
||
| `item` | 统一实体 | id, ws_id, type, title, body_md, status, priority, owner_id, due_at, done_at, visibility, ext, version, deleted_at | ✅ |
|
||
| `item_assignee` | 多负责人 | item_id, user_id, role | ✅ |
|
||
| `ticket_ext` | 工单专属 | item_id, requester_id, sla_due_at, accepted_at, resolved_at, verified_at, verify_result | ✅ |
|
||
| `item_link` | 关系 | from_id, to_id, kind | ✅ |
|
||
| `comment` | 评论/内部备注 | item_id, author_id, body_md, internal | ✅ |
|
||
| `activity` | 事件流 | item_id, ws_id, actor_id, verb, changed_fields, at | ✅ |
|
||
| `tag` / `item_tag` | 标签 | — | ✅ |
|
||
| `knowledge_doc` | 知识卡 | ws_id, title, summary, body_md, source_item_id, status, review_at, version | ✅ |
|
||
| `suggestion` | AI 待审草稿 | ws_id, kind, payload, target_id, status, model, confidence | ✅ |
|
||
| `subscription` / `usage_event` | 套餐与计量 | plan, seats, period, kind, qty | ✅ |
|
||
| `chunk` | 切片 + vector(1024) | doc_id, seq, text, tsvector, embedding | V1 |
|
||
| `attachment` | 附件 | owner_id, oss_key, mime, size | V1 |
|
||
| `llm_provider` | 租户 LLM 配置 | ws_id, kind, base_url, model, key_enc, status | V1 |
|
||
| `integration` | 集成配置 | ws_id, provider, plane, config_enc, status | V1 |
|
||
| `thread` / `message` | AI 会话 | anchor_item_id, role, content, citations, tokens | V1 |
|
||
| `person_profile` | 人物画像 | user_id, ws_id, summary_md, facts, generated_at | V2 |
|
||
| `notification` | 出站消息队列 | ws_id, channel, payload, status, retry | V1 |
|
||
| `audit_log` | 管理操作审计 | ws_id, actor, action, target, ip | V1 |
|
||
|
||
### 5.3 状态机
|
||
|
||
**任务**:`inbox → todo → doing → done`,旁挂 `blocked`、`canceled`
|
||
**工单**:`open → accepted → in_progress → pending_verify → done`,旁挂 `reassigned`、`canceled`
|
||
**知识**:`draft → in_review → published → archived`
|
||
|
||
> **一条流的关键机关**:任务升级为工单后自动进 `blocked`;工单验收通过自动回流 `doing/done`。
|
||
> 用户不需要在两个地方各改一次状态 —— 比任何 AI 功能都更能说明"这是一个产品"。
|
||
|
||
---
|
||
|
||
## 6. 功能地图
|
||
|
||
### 6.1 MVP(第 1–10 周,目标:自己天天用 + 可对外测)
|
||
|
||
**任务**:一句话快速录入(全局快捷键/分享面板)、收件箱/今天/本周/全部四视图、优先级/截止/标签/子任务、看板拖拽、移动端列表。
|
||
|
||
**工单**:任务一键升级(选人+期望时间+说明)、我发起的/待我处理/我参与的、状态流转、评论与内部备注、验收通过或打回、关闭时触发沉淀。
|
||
|
||
**知识**:手动新建、从工单生成四段式草稿(问题/根因/处理/验证)、全文搜索、来源回链。
|
||
|
||
**AI 三场景**:NL → 结构化任务/工单;工单关闭 → 知识草稿;基于知识库问答(必须带引用,无来源就说不知道)。
|
||
|
||
**SaaS 必备**:手机号验证码注册、创建团队、邀请成员、四角色权限、免费额度与用量页、数据导出、管理后台(看租户/用量/封禁)。
|
||
|
||
**基础**:站内通知 + 邮件;安卓端(在线)。
|
||
|
||
### 6.2 V1(第 11–16 周)
|
||
|
||
- 语义检索(pgvector)+ 混合排序
|
||
- 对话式 Agent(对话里查任务/改状态,仍走审批)
|
||
- 人物画像、自动周报
|
||
- 飞书/企微:扫码登录、消息卡片通知、Bot 建任务
|
||
- 附件 + 图片 OCR 入知识
|
||
- 套餐升级与在线支付(支付宝/微信)
|
||
- 审计日志、知识卡过期提醒
|
||
|
||
### 6.3 V2
|
||
|
||
- 知识图谱与可视化
|
||
- 相似去重与自动归档(>0.92 提示合并)
|
||
- 自定义工单字段与流程模板
|
||
- 开放 API / Webhook
|
||
- 小程序端(承接微信生态的轻量入口)
|
||
- 安卓桌面小组件
|
||
|
||
### 6.4 明确不做
|
||
|
||
甘特图与资源负载 · BPMN 审批引擎 · 实时协同编辑 · 自建 IM · 离线模式 · 细粒度字段级权限 · 对外开放插件市场(至少两年内)
|
||
|
||
---
|
||
|
||
## 7. LLM 网关设计(v1.0 重写)
|
||
|
||
### 7.1 Provider 模型
|
||
|
||
```python
|
||
class LLMProvider(BaseModel):
|
||
ws_id: str | None # None = 平台内置
|
||
kind: Literal["openai_compatible"]
|
||
base_url: str # https://api.deepseek.com/v1 ; http://ollama:11434/v1
|
||
model: str # deepseek-chat / qwen2.5:14b ...
|
||
embedding_model: str | None
|
||
key_enc: bytes | None # AES-256-GCM 密文,永不回显
|
||
status: Literal["ok", "invalid", "unreachable"]
|
||
capabilities: dict # 探测结果:stream / tools / json_mode / vision
|
||
```
|
||
|
||
- **预置模板**:DeepSeek(平台默认,给额度)、OpenAI、Ollama(本地/内网)、通义千问、智谱、月之暗面、硅基流动 —— 全部是 OpenAI 兼容协议,只是 `base_url` 与模型名不同。
|
||
- **能力探测**:保存时调一次 `GET /models` + 一次 8 token 的 chat,标记 `capabilities`;流式/tools 不支持就自动降级(例如不支持的走两段式:先出 JSON 再渲染)。
|
||
- **密钥安全**:AES-256-GCM,主密钥来自环境变量或 KMS;前端只看到 `sk-****abcd`;日志、追踪、错误上报统一脱敏中间件。
|
||
- **分层覆盖**:租户默认 → 功能级覆盖(打标签用便宜模型,问答用强模型)→ 全局兜底(平台 key)。
|
||
- **网络可达性**:Ollama 场景下用户填的是自己内网地址,SaaS 后端根本连不上 —— **必须支持"客户端代理调用"模式**:浏览器/安卓直接请求用户的 Ollama,结果回传后端只落库不入模型链路。这是私有化用户最常见的坑,M4 就要处理。
|
||
|
||
### 7.2 六个能力
|
||
|
||
| 能力 | 输入 | 输出 | 边界 |
|
||
|---|---|---|---|
|
||
| A 结构化录入 | 一句话 | item 草稿 | 只建议不建 |
|
||
| B 闭环沉淀 | 工单 activity 流 | 四段式知识卡草稿 | 必须回链 source_item_id |
|
||
| C 自动索引 | 知识正文 | 标签/实体/相似卡 | 标签库受控,不许乱造 |
|
||
| D 问答 | 问题 + 检索 | 带引用回答 | 无来源就说不知道 |
|
||
| E 人物画像 | 某人 activity | 5–8 条事实 | 只写工作事实 |
|
||
| F 主动提醒 | 全局状态 | 风险项 | 每日最多 1 条 |
|
||
|
||
### 7.3 上下文组装
|
||
|
||
```
|
||
[系统] 角色 + 输出格式约束 + 工作区一句话摘要
|
||
[对象] 对话对象画像(≤5 条,各 1 行)
|
||
[事实] 相关 item 摘要(top 8,各 1 行)
|
||
[证据] 相关 chunk(top 12,各 ≤200 字,带 [doc#seq] 来源标记)
|
||
[历史] 本会话最近 6 轮
|
||
[输入] 用户当前话语
|
||
```
|
||
超预算裁剪顺序:chunk 细节 → item 数量 → 画像条数 → **绝不砍系统规则与来源标记**。
|
||
预算:输入 ≤ 8k tokens,输出 ≤ 1.5k。
|
||
|
||
### 7.4 计量、限流、降级
|
||
|
||
- 每次调用写 `usage_event`(tokens_in/out, model, latency, ws_id)→ 套餐月度汇总 → 超限只降级不硬断(降级为关键词检索 + 模板回答)。
|
||
- 租户级 QPS 与并发上限;平台 key 按租户配额,BYOK 只做滥用防护。
|
||
- 缓存:同问题 + 同检索结果哈希 → 命中即回,省 30%+。
|
||
- **隐私**:prompt/response 默认不落库;调试开关 7 天自动清除,且界面上明确告知。
|
||
- **评测**:20 条黄金用例(含 5 条"应当回答不知道"),改 prompt 必跑。
|
||
|
||
---
|
||
|
||
## 8. 多租户、权限与计费(SaaS 核心)
|
||
|
||
### 8.1 隔离
|
||
|
||
- **应用层**:所有仓储方法强制要求 `ws_id`(类型层面让它成为必填参数,而不是可选)。
|
||
- **数据库层**:`SET LOCAL app.ws_id = $1` 于每个请求事务开头,RLS 策略 `USING (workspace_id = current_setting('app.ws_id')::uuid)`。
|
||
- **测试层**:每个资源一套「跨租户越权测试」,断言必须 0 行 / 403。这条测试进 CI,红了不许合并。
|
||
- **对象存储**:key 前缀 `ws/{ws_id}/...`,签名 URL 绑定租户。
|
||
|
||
### 8.2 角色(4 个,不做矩阵)
|
||
|
||
`owner`(含计费与删除租户)/ `admin`(管人与配置)/ `member`(读写团队内容)/ `guest`(仅被指派的工单)。
|
||
实现:`PERMISSIONS` 集中式守卫表(资源 → 动作 → 最低角色),绝不散落 `if`。PosSync 的 `PERMISSION_GUARDS` 写法可直接搬。
|
||
|
||
### 8.3 套餐与计量
|
||
|
||
| 套餐 | 席位 | AI 额度 | 关键功能 |
|
||
|---|---|---|---|
|
||
| Free | 1 | 少量/月 | 任务、工单、知识、基础搜索 |
|
||
| Pro | 1 | 中 | 语义检索、画像、周报、更大附件 |
|
||
| Team | 3+ | 按席位 | SLA、集成、审计、SLA 提醒、优先支持 |
|
||
|
||
计量只做三样:AI tokens、存储、席位数。**MVP 不做在线支付**(先手工开通/邀请码),避免把 3 周花在支付对账上;V1 再接支付宝/微信。
|
||
|
||
### 8.4 注册与引导
|
||
|
||
手机号验证码 → 建个人工作区 → 3 条示例任务(可一键清空)→ "要不要接入 AI?"(默认平台额度)→ 完成。
|
||
**关键指标**:从注册到"完成第一个任务"的时间,目标 < 90 秒。
|
||
|
||
---
|
||
|
||
## 9. 技术架构
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph C[客户端]
|
||
W["PC Web · React 18 + Vite + Tailwind"]
|
||
A["Android · Kotlin + Compose"]
|
||
B["飞书 / 企微 Bot"]
|
||
end
|
||
subgraph G[接入]
|
||
N["Nginx · TLS · 限流 · 静态资源"]
|
||
end
|
||
subgraph S[应用层 · FastAPI]
|
||
API["REST + SSE"]
|
||
AUTH["认证 · JWT · OAuth"]
|
||
SVC["领域服务 item / ticket / knowledge"]
|
||
AI["AI 编排 · suggestion 审批 · 上下文组装"]
|
||
JOB["异步任务 · arq + Redis"]
|
||
INT["集成适配器 · SSO / 通知 / Bot"]
|
||
end
|
||
subgraph D[数据层]
|
||
PG["PostgreSQL 16 · RLS · pgvector"]
|
||
R["Redis · 缓存 / 队列 / 限流"]
|
||
OSS["MinIO/S3 · 附件"]
|
||
end
|
||
AI --> GW["LLM 网关"]
|
||
GW --> P1["平台 DeepSeek"]
|
||
GW --> P2["用户 BYOK"]
|
||
GW --> P3["用户 Ollama · 客户端代理"]
|
||
W --> N --> API
|
||
A --> N
|
||
B --> N
|
||
API --> SVC --> PG
|
||
API --> AI
|
||
JOB --> SVC
|
||
INT --> B
|
||
```
|
||
|
||
| 层 | 选择 | 理由 |
|
||
|---|---|---|
|
||
| 后端 | FastAPI + Pydantic v2 | SSE 流式、OpenAPI 出 SDK、async |
|
||
| 数据库 | PostgreSQL 16 + pgvector | 关系/全文/向量一库;RLS 直接可用 |
|
||
| 队列 | Redis + arq | 轻量 asyncio;Celery 更重 |
|
||
| 前端 | React 18 + Vite + Tailwind | 沿用 PosSync 栈,熟 |
|
||
| 安卓 | Kotlin + Compose | 沿用已有经验;Flutter 收益不明显 |
|
||
| SDK | OpenAPI → TS/Kotlin 生成 | 手写两端必漂移 |
|
||
| 部署 | Docker Compose 单机起步 | 早期不上 K8s;按 cell 预留水平扩展 |
|
||
| 分发 | 官网 APK + 华为/小米/OPPO/vivo/应用宝 | 国内不上 Google Play |
|
||
|
||
**代码结构**
|
||
|
||
```
|
||
DadaoTask/
|
||
├─ 2.Design/ 设计文档、数据库、部署、事故记录
|
||
├─ backend/
|
||
│ ├─ app/api/ items, tickets, knowledge, ai, auth, admin, sync(无)
|
||
│ ├─ app/domain/ 状态机、权限、SLA、租户上下文
|
||
│ ├─ app/infra/ db, redis, oss, llm, integration
|
||
│ ├─ app/ai/ context builder, prompts, retriever, suggestion
|
||
│ └─ app/jobs/ embedding、周报、画像、通知分发
|
||
├─ web/ React
|
||
├─ android/ Kotlin Compose
|
||
└─ deploy/ compose、nginx、备份
|
||
```
|
||
|
||
**沿用 PosSync 的铁律**(写进 AGENTS.md):改完必须提交并 push;生产不得领先仓库;前端产物只能由仓库 HEAD 构建,部署后校验 build 标记。
|
||
|
||
---
|
||
|
||
## 10. 微信与飞书集成
|
||
|
||
### 10.0 纠正:个人微信**有**官方 Bot 通道
|
||
|
||
v1.0 初稿这里写错了(原判断"个人微信没有官方机器人接口")。核实后的事实:腾讯已开放 **微信 ClawBot / iLink Bot 协议**(`https://ilinkai.weixin.qq.com`),DSH 的 IM 插件 `@michengai/dsh-im-connect` 微信渠道就是基于它实现,源码里明确写着"腾讯官方产品,非逆向方案"。
|
||
|
||
已核实的技术事实(来源:`@michengai/dsh-im-connect` 的 `src/channels/weixin.ts`、`src/channels/qr/weixin.ts`、README 支持矩阵):
|
||
|
||
| 事实 | 内容 | 对产品的影响 |
|
||
|---|---|---|
|
||
| 登录方式 | `POST /ilink/bot/get_bot_qrcode?bot_type=3` 取二维码 → 轮询 `/ilink/bot/get_qrcode_status` → 拿到 `bot_token` | 用户扫码即绑定,不用填任何密钥,接入摩擦极低 |
|
||
| 收消息 | 长轮询(poller),必须持久化 `syncBuf` 游标防丢防重 | 一个绑定 = 一条常驻长轮询连接,这是架构约束 |
|
||
| 回消息 | `POST /ilink/bot/sendmessage`,按 `context_token` 回复 | — |
|
||
| 媒体 | 图片/语音/文件/视频,CDN AES-128-ECB 加密,单文件上限 50 MB | 可以语音记任务、直接把文件甩进知识库 |
|
||
| 会话范围 | **仅单聊**,不支持群 | 团队协作的消息面仍得靠飞书/企微 |
|
||
| 账号模型 | **一个微信号一个 poller**,官方建议用专用小号 | 见 10.3 的架构分歧,这是最关键的决策点 |
|
||
| 合规 | 官方 iLink,插件声明 "no reverse-engineered personal protocol";使用即同意《微信 ClawBot 功能使用条款》 | 不能用 hook/逆向;条款原文的商用边界需甲方自查(我无法联网检索条款全文) |
|
||
|
||
### 10.0.1 其他微信通道(仍然有效,按需用)
|
||
|
||
| 通道 | 能做什么 | 建议 |
|
||
|---|---|---|
|
||
| **企业微信** | 应用消息、审批、扫码登录、群机器人 | ✅ 团队协作首选 |
|
||
| **公众号/服务号** | 模板消息(提醒推送)、扫码关注绑定、H5 入口 | ✅ 个人用户的推送通道 |
|
||
| **小程序** | 轻量移动入口,可替代部分安卓场景 | 后续,若安卓分发成本过高再做 |
|
||
| **个人微信 iLink** | 扫码绑定、单聊收发、语音/文件 | ✅ 个人用户入口(见 10.3) |
|
||
|
||
### 10.1 三个平面
|
||
|
||
| 平面 | 飞书 | 企微 | MVP |
|
||
|---|---|---|---|
|
||
| SSO | 网页扫码/免登 | 网页授权扫码 | V1 |
|
||
| 通知 | 消息卡片(可带"接受/完成"按钮) | 应用消息 / 群机器人 | V1 |
|
||
| Bot | 事件订阅 → 建任务/查工单 | 群机器人 → 同上 | V2 |
|
||
|
||
### 10.2 设计要点
|
||
|
||
- `integration` 表存 provider + plane + 加密配置,每个租户可挂多个。
|
||
- 出站走 `notification` 队列 + 重试 + 死信,IM 故障不阻塞业务。
|
||
- 入站必须验签(飞书 encrypt key / 企微 token+sha1),并且**幂等**(同一 event_id 只处理一次)。
|
||
- Bot 收到的自然语言 → 走 §7 能力 A → 返回**卡片待确认**,用户点确认才建。避免"群里一句话建了十条任务"。
|
||
- 双向价值:群里的讨论也能反向抽成知识卡(V2 的差异化点,别人没有)。
|
||
|
||
### 10.3 个人微信在 SaaS 里的三种接法(要你拍板)
|
||
|
||
约束源自 10.0 表格最后两行:**单聊 only + 一个微信号一个 poller + 建议专用小号**。这直接推出三种互斥的架构:
|
||
|
||
| 接法 | 怎么做 | 优点 | 代价 |
|
||
|---|---|---|---|
|
||
| **A 用户自带微信号** | 每个用户自己扫码,把一个小号变成"我的助理",主号私聊它记任务 | 风险分散到用户;我们不用养号;天然多租户隔离 | 用户得有第二个微信号 → 对普通用户是转化率杀手,只适合重度用户 |
|
||
| **B 平台统一号** | 我们运营一个微信助理号,所有用户加它,按白名单识别身份 | 零门槛,注册即用,是真正能拉新的入口 | 一条 poller 承载全平台会话(要压测);好友数上限;**一个号被封 = 全员失联**;条款是否允许商用未知 |
|
||
| **C 本地 bridge** | 用户在自己电脑上跑轻量转发程序(DSH 插件就是这种形态),微信连接留在用户侧,云端只收结构化数据 | 最稳、最合规、服务器最省 | 要装东西;电脑关机就断;不适合纯手机用户 |
|
||
|
||
**我的建议**:MVP 走 **A**,但设计成"高级开关、默认关闭"——先把数据模型和 `integration` 表做对,接不接微信都不影响主流程。B 等条款核实 + 压测数据出来再评估,不要现在押注。C 等桌面端有了再说。
|
||
|
||
⚠️ **但选型前必须做 0.5 天 spike**,验证三件必须实测才知道的事(拍脑袋会返工):
|
||
|
||
1. **谁是 bot** —— 扫码的那个微信号自己变成 bot,还是被授权成某个服务实体?(决定"用户要不要备小号")
|
||
2. **能否多用户共用** —— 不同微信号私聊同一个 bot,是否都能收到、且会话互不串?(决定 B 是否可行)
|
||
3. **风控边界** —— 连续/并发发消息的限流阈值、长轮询断线重连行为、`bot_token` 有效期与失效时机。
|
||
|
||
结论写进 `2.Design/SPIKE-WECHAT-ILINK.md`,再回来定 10.3 的最终选型。
|
||
|
||
---
|
||
|
||
## 11. 安全与合规(SaaS 必答)
|
||
|
||
| 事项 | 现在要做 | 说明 |
|
||
|---|---|---|
|
||
| 个人信息保护法 | 隐私政策、最小采集、导出/删除接口、注销 | 卖给企业客户时会被问到 |
|
||
| 数据出境 | 默认用境内模型(DeepSeek 等);用境外模型时明确告知并取得同意 | 用户 BYOK 到 OpenAI 属于用户自选,需二次确认弹窗 |
|
||
| ICP 备案 | 域名必须备案;涉及在线交易可能需 EDI | 提前办,别卡上线 |
|
||
| 等保 | 面向企业客户大概率要求等保二级 | 初期至少做到:日志留存 6 个月、堡垒机、备份、漏洞扫描 |
|
||
| 密钥 | 加密入库、不进日志、支持轮换 | 一条脱敏中间件统一处理 |
|
||
| 越权 | RLS + 跨租户测试进 CI | 最高优先级 |
|
||
| 备份 | 每日全量 + WAL 归档,恢复演练每季度 | 复用现有备份脚本 |
|
||
|
||
---
|
||
|
||
## 12. 里程碑(2 人)
|
||
|
||
| 阶段 | 周 | 交付 | 验收 |
|
||
|---|---|---|---|
|
||
| M0 骨架 | 1–2 | 多租户认证、RLS、迁移、CI、Compose、部署 | 两个租户互不可见(有测试证明) |
|
||
| M1 任务 | 3–4 | 四视图、看板、标签、搜索 | 自己连续 3 天全量使用不别扭 |
|
||
| M2 工单 | 5–6 | 升级、状态机、评论、验收、blocked 联动 | 两人真实跑通一个工单闭环 |
|
||
| M3 知识 | 7–8 | 知识卡、来源回链、工单草稿、全文搜索 | 关一个工单能顺手产出一张有用卡 |
|
||
| M4 AI | 9–10 | 三场景、suggestion 审批、LLM 网关、BYOK | 黄金用例 ≥ 80%;换模型不改业务代码 |
|
||
| **对外测** | **10** | 邀请制内测,10–20 个真实用户 | 周留存与"第一个任务完成率"有数 |
|
||
| M5 安卓 | 11–12 | Compose 主界面、推送、在线缓存 | 弱网可用、崩溃率 < 1% |
|
||
| M6 集成 | 13 | 飞书/企微登录与通知卡片 | 群里能收到并一键处理工单 |
|
||
| M7 SaaS | 14 | 套餐计量、用量页、管理后台、导出 | 能手工开单、看用量、封禁滥用 |
|
||
| M8 打磨 | 15 | 性能、合规材料、文档、商店上架 | 可公开注册 |
|
||
|
||
> 提前到第 10 周对外测,是为了让真实用户决定 M5 之后做什么,而不是我猜。
|
||
|
||
---
|
||
|
||
## 13. 风险与对策
|
||
|
||
| 风险 | 概率 | 影响 | 对策 |
|
||
|---|---|---|---|
|
||
| 多租户越权泄露 | 中 | 致命 | 仓储层强制 ws_id + RLS + 跨租户测试进 CI |
|
||
| 范围蔓延(三产品叠加) | 高 | 致命 | §6.4 不做清单当合同;加功能必砍功能 |
|
||
| 免费用户刷 AI 额度 | 高 | 中 | 硬配额 + 每日衰减 + 异常检测(同 IP 多账号) |
|
||
| LLM 幻觉 | 中 | 高 | 强制引用、无来源不答、黄金用例回归 |
|
||
| Ollama 内网不可达 | 高 | 中 | 客户端代理调用模式(§7.1) |
|
||
| 知识冷启动无人写 | 中 | 高 | 闭环沉淀 + 示例内容 + IM 抽取;首批种子由我们代写 20 张 |
|
||
| 一个人维护三端 | 中 | 中 | OpenAPI 生成 SDK;安卓只做读写与推送 |
|
||
| 三个月后自己不用了 | 中 | 致命 | M1 起强制 dogfooding,每周记一条"用得不爽"并优先修 |
|
||
| 备案/等保卡上线 | 中 | 高 | 现在就去办 ICP;等保按客户要求提前准备 |
|
||
|
||
---
|
||
|
||
## 14. 下一步
|
||
|
||
1. **M0 骨架**:仓库结构、Compose(PG16/Redis/MinIO)、多租户认证、RLS、迁移、CI、部署脚本。
|
||
2. **`2.Design/DATABASE.md`**:22 张表落成 DDL + RLS 策略 + 索引。
|
||
3. **`2.Design/API.md`** + OpenAPI 导出脚本:三端并行开发的契约。
|
||
4. 确认三件小事:产品名/域名、端口分配(避开 PosSync 的 5888/5176)、Gitea 仓库创建。
|
||
|
||
> 顺序建议:**先让"任务"这条腿站住,再谈 AI**。反着做的项目,两周后演示很炫,用户却没有真实数据可用。
|