新增: df-im-gateway 网关骨架
This commit is contained in:
@@ -152,3 +152,194 @@ IM 用户 @机器人 "把登录任务推进到 in_review"
|
||||
- **df-mcp**:对外 stdio 暴露数据层(本地进程级);本规划是远程人类入口(IM 级),互补不重叠
|
||||
- **u-relay**:零改动(除非 D5 触发多 token 需求)
|
||||
- **df-tunnel / AI 引擎**:零改动
|
||||
|
||||
## 附录A、PostgreSQL 多租户 × DevFlow 结合分析(§十 S3 展开论证)
|
||||
|
||||
### A.1 概念:多租户三模式
|
||||
|
||||
| 模式 | 结构 | 优点 | 缺点 | 适合 |
|
||||
|---|---|---|---|---|
|
||||
| **行级隔离** | 同库同表,每行 `tenant_id` 列,查询强制 WHERE | 成本最低、迁移跑一份、跨租户统计易 | 隔离最弱(漏写 WHERE 即泄漏)、noisy neighbor | 租户多单租户数据小,SaaS 主流 |
|
||||
| **独立 Schema** | 一实例每租户一 schema | 隔离较强,按 schema 备份 | 租户多时爆炸;DDL 迁移跑 N 遍 | 租户几百内 |
|
||||
| **独立 Database** | 每租户一库 | 最强隔离 | 资源贵、连接池复杂、跨租户查询难 | 租户少而大、合规严 |
|
||||
|
||||
行级隔离通常配合 **PG RLS(Row Level Security)**:租户过滤下沉数据库层——session 设 `SET app.tenant_id`,策略自动过滤,应用层漏写 WHERE 也不泄漏。这是 PG 多租户的核心王牌。
|
||||
|
||||
### A.2 激活时机
|
||||
|
||||
DevFlow 当前是本地优先单机应用(SQLite/单用户/零运维),「租户」不存在。多租户仅在 **S3 AI 引擎上云**时被激活:SQLite 单写者模型扛不住云端多用户并发写,且「本地优先」范式失效——隔离必须显式设计。**多租户是需求,PostgreSQL 是载体**(PG 因并发写 + RLS + 生态成为默认答案)。
|
||||
|
||||
### A.3 租户模型与选型
|
||||
|
||||
- 租户模型:`tenant`=团队(付费主体),`user`=成员;现有全部表(projects/tasks/ideas/workflows/ai_messages/knowledge/audit…)挂 `tenant_id`
|
||||
- 选型:**行级隔离 + RLS**(非 schema/database 隔离)。决定性理由是迁移演进节奏:V1-V16+ 已 20+ 表且快速迭代,per-tenant schema 下每次迁移要循环跑 N 遍并处理失败重试,直接拖死迭代速度;行级隔离迁移只跑一份
|
||||
|
||||
### A.4 落点三抓手
|
||||
|
||||
1. **df-storage trait 层**(对齐 F-07 下沉思路):存储访问收敛 Repository trait,多租户化 = trait 实现层注入租户上下文(依赖 PG session 变量),上层 commands 无感——现有分层红利
|
||||
2. **迁移体系**:SQLite 手写迁移换 sqlx/refinery 版本化迁移,一套脚本跑一份
|
||||
3. **RLS 策略**:每表 `USING (tenant_id = current_setting('app.tenant_id')::uuid)`,连接池(pgbouncer)按事务设租户变量
|
||||
|
||||
### A.5 配套改造清单(多租户 ≠ 换数据库驱动)
|
||||
|
||||
缓存键带租户(防 Redis 串数据)/ 对象存储按租户前缀隔离 / 日志审计按租户切分 / 备份恢复按租户粒度。**全链路改造**——这正是 §十 把 PG 多租户列入「显式不做」的原因:现在做 = 为不存在的需求付全链路成本。
|
||||
|
||||
### A.6 与本期规划的交集
|
||||
|
||||
唯一交集 = P0 已预留的会话映射表 `owner_user_id` 列(S2 时是「用户归属」,S3 升级语义为「租户内用户」),成本≈0。时序红线重申:S2 各人数据仍在各自桌面端 SQLite,云端只有路由表,**不需要 PG**;S3 才引入 PG+RLS,与引擎多租户化统一做。
|
||||
|
||||
## 附录B、引入云端后的多人架构模式(C4 视图)
|
||||
|
||||
> 按 C4 模型整理:C1 上下文(现状基线 → S2 多人 → S3 引擎上云)+ C2 容器(网关内部)+ 部署视图 + 数据归属演进表。
|
||||
> 贯穿不变量:**TunnelCommand/TunnelEvent 是网关↔执行端唯一契约**,执行端可从「桌面端 df-tunnel」无缝换成「云端 df-agent」,网关与 IM 端零改动。
|
||||
|
||||
### B.1 C1 上下文 —— 现状基线(S0:单机 + 小程序遥控)
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph local["💻 用户本地(数据主权 100% 在个人)"]
|
||||
desktop["DevFlow 桌面端 (Tauri v2)<br/>AI Chat 引擎(Agentic Loop+审批) · SQLite · df-tunnel(Agent)"]
|
||||
end
|
||||
subgraph cloud["☁️ 云端 u-relay.1216.top(nginx TLS 终止)"]
|
||||
relay["u-relay :9180<br/>channel_id 配对 · payload 透传零业务耦合"]
|
||||
end
|
||||
mini["📱 df-miniapp 微信小程序<br/>(Commander)"]
|
||||
mini <-->|"WSS"| relay
|
||||
relay <-.->|"WS Agent 出站穿NAT<br/>单 channel 配对"| desktop
|
||||
```
|
||||
|
||||
### B.2 C1 上下文 —— S2 团队多人(云端路由化,数据仍归各人)
|
||||
|
||||
本期 IM 网关落地后的直接形态:**云端只有「路由与审计」,业务数据仍在各桌面端**。
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph users["👥 多人入口"]
|
||||
direction LR
|
||||
im["飞书 / 钉钉 / 企微<br/>企业机器人"]
|
||||
web["Web Chat<br/>浏览器/手机"]
|
||||
mini["df-miniapp<br/>微信小程序"]
|
||||
end
|
||||
|
||||
subgraph cloud["☁️ 云端(nginx TLS 终止)"]
|
||||
direction TB
|
||||
gw["df-im-gateway :9190<br/>平台适配器 · 会话映射 · 白名单<br/>节流聚合 · 审批分级 · 审计"]
|
||||
relay["u-relay :9180<br/>多 channel 配对转发"]
|
||||
gw <-->|"WS Commander(多channel)<br/>TunnelCommand / TunnelEvent"| relay
|
||||
end
|
||||
|
||||
subgraph deskA["用户A 本地"]
|
||||
dA["DevFlow 桌面端<br/>AI引擎 + SQLite(A) · df-tunnel"]
|
||||
end
|
||||
subgraph deskB["用户B 本地"]
|
||||
dB["DevFlow 桌面端<br/>AI引擎 + SQLite(B) · df-tunnel"]
|
||||
end
|
||||
|
||||
im --> gw
|
||||
web <-->|"HTTP/WS"| gw
|
||||
mini <-->|"WSS Commander"| relay
|
||||
relay <-.->|"WS Agent · chan-userA"| dA
|
||||
relay <-.->|"WS Agent · chan-userB"| dB
|
||||
```
|
||||
|
||||
**路由链路**:IM 消息 → 网关查映射表 `chat_id → (owner_user_id, channel_id, conv_id)` → 发 `TunnelCommand::Send` 到对应 channel → 该用户桌面端执行。**用户隔离靠 channel 隔离**(一人一 channel,per-channel token 为 u-relay 演进观察项)。
|
||||
|
||||
### B.3 C2 容器 —— df-im-gateway 内部(适配器 trait 分层,S4 扩展点)
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph adapters["平台适配器层(各平台差异收敛于此)"]
|
||||
feishu["feishu_adapter<br/>长连接+卡片流式"]
|
||||
dingtalk["dingtalk_adapter<br/>Stream Mode"]
|
||||
wecom["wecom_adapter<br/>回调验签+AES"]
|
||||
webui["web_adapter<br/>WS 直连+静态页"]
|
||||
end
|
||||
subgraph core["核心(平台无关,S4 加端零改动)"]
|
||||
unify["统一模型<br/>InboundEvent / OutboundAction"]
|
||||
sess["会话映射表 (SQLite)<br/>chat_id | conv_id | owner_user_id | platform | channel_id"]
|
||||
throttle["节流聚合器<br/>TextDelta 时间窗"]
|
||||
acl["白名单 + 审批分级"]
|
||||
audit["审计日志<br/>IM消息 ↔ TunnelCommand"]
|
||||
unify --> sess
|
||||
sess --> throttle
|
||||
acl --> sess
|
||||
sess --> audit
|
||||
end
|
||||
relay["u-relay WS Commander"]
|
||||
feishu --> unify
|
||||
dingtalk --> unify
|
||||
wecom --> unify
|
||||
webui <--> unify
|
||||
core <-->|"TunnelCommand / TunnelEvent"| relay
|
||||
```
|
||||
|
||||
### B.4 C1 上下文 —— S3 引擎上云(云端多人完整形态,PG 多租户)
|
||||
|
||||
执行端从「各人桌面端」切换为「云端 df-agent 服务」,**同一协议**,网关/IM 端零改动;桌面端退化为瘦客户端/管理台,本地优先形态仍可用(不废弃)。
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph users["👥 多人入口"]
|
||||
direction LR
|
||||
im["飞书/钉钉/企微"]
|
||||
web["Web Chat"]
|
||||
end
|
||||
subgraph cloud["☁️ 云端"]
|
||||
direction TB
|
||||
gw["df-im-gateway<br/>(零改动)"]
|
||||
relay["u-relay<br/>(零改动)"]
|
||||
agent["df-agent 云端执行服务<br/>AI 引擎(Agentic Loop) · 工具沙箱<br/>多会话/多租户调度"]
|
||||
gw <--> relay
|
||||
relay <-.->|"同协议<br/>TunnelCommand / TunnelEvent"| agent
|
||||
end
|
||||
subgraph data["数据层(附录A 落点)"]
|
||||
pg[("PostgreSQL<br/>行级 tenant_id + RLS<br/>projects/tasks/messages/audit")]
|
||||
redis[("Redis<br/>租户前缀缓存键")]
|
||||
oss[("对象存储<br/>租户前缀隔离")]
|
||||
end
|
||||
thin["💻 桌面端=瘦客户端/管理台<br/>本地 SQLite 留个人配置"]
|
||||
im --> gw
|
||||
web <--> gw
|
||||
agent --> pg
|
||||
agent --> redis
|
||||
agent --> oss
|
||||
thin <-.-> relay
|
||||
```
|
||||
|
||||
### B.5 部署视图(S2 落地形态,单机双服务 + nginx)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph inet["互联网"]
|
||||
u["用户 IM / 浏览器 / 小程序"]
|
||||
end
|
||||
subgraph server["云端主机(u-relay 同机,复用 nginx+systemd 模式)"]
|
||||
nginx["nginx :443 TLS 终止<br/>/ws/* → 9180<br/>/im/* /chat/* → 9190"]
|
||||
ur["u-relay :9180<br/>systemd · musl 单二进制 ~3.6MB"]
|
||||
gig["df-im-gateway :9190<br/>systemd · musl 单二进制<br/>静态 Web Chat 页托管"]
|
||||
nginx --> ur
|
||||
nginx --> gig
|
||||
end
|
||||
subgraph homes["各用户本地"]
|
||||
dt["DevFlow 桌面端<br/>出站 WSS → /ws/agent"]
|
||||
end
|
||||
u -->|"wss://u-relay.1216.top"| nginx
|
||||
dt <-.->|"出站穿NAT"| nginx
|
||||
```
|
||||
|
||||
### B.6 数据归属与信任边界演进表
|
||||
|
||||
| 维度 | S0 现状 | S2 团队多人 | S3 引擎上云 |
|
||||
|---|---|---|---|
|
||||
| 身份/会话映射 | 桌面端 Settings | **网关 SQLite**(owner/channel 列已预留) | 网关 → 并入 PG |
|
||||
| 项目/任务/工作流 | 桌面端 SQLite | **各桌面端 SQLite**(主权在个人) | PG(tenant_id+RLS) |
|
||||
| AI 消息/溯源 | 桌面端 ai_messages | 各桌面端 | PG |
|
||||
| IM↔指令审计 | — | 网关审计日志 | PG(租户维度) |
|
||||
| 信任边界 | 个人设备 | 云端只见「指令与脱敏结果」 | 云端见全部业务数据(需租户隔离+合规) |
|
||||
| 桌面端角色 | 全栈主体 | 执行主体 | 瘦客户端/管理台(可选保留本地优先) |
|
||||
|
||||
### B.7 演进的三条设计不变量
|
||||
|
||||
1. **协议不变性**:网关↔执行端唯一契约是 TunnelCommand/TunnelEvent(df-tunnel crate 类型),S3 换执行端零成本——这是全方案最重要的远期红利
|
||||
2. **u-relay 纯转发零耦合**不破例:业务逻辑只进 df-im-gateway / df-agent,中继永远轻
|
||||
3. **数据主权渐进上移**:S0/S2 数据在个人(本地优先不被废弃),S3 才集中上云并配套 RLS 隔离——每一步都由真实需求触发,不过度设计
|
||||
|
||||
Reference in New Issue
Block a user