版本:v1.0 | 2026-08-16 | 面向:新加入的工程师、业务方技术对接人
上游事实源:CLAUDE.md(ADR 与选型定案)| docs/dev-charter.md v1.3(域划分/Schema 三分法/流程分级)| docs/dev/msgbridge-contract.md v1.0(消息域契约)| docs/dev/influencer-schema-design.md(达人域模型)| docs/dev/jixing-api-notes.md(集星 API)| 代码实况(server/app/、console/src/、server/.env.example)
本文只写架构,不写业务口径:任何判定数字(达标线/分级/时效)以 docs/business/xijian-business-baseline.md v2.1 为唯一口径源,代码一律 cfg() 取值,本文只指出机制不复述数值。
一句话定位:达人运营除跑客户之外的全部工作在一个运营台完成,把达运 8–9 人的人力占用压到 2 人乃至 1 人。
产品边界:console(运营台前端)+ server(后端)+ miniapp(达人端)+ 消息台服务是一个产品。消息台深度融入统一运营台——主工作面板就是消息台形态,也是与达人端的主要沟通面板(charter §5、契约 §1 定位澄清);"集成契约"指的是代码层面的服务间接口(消息台作为企微执行层服务化部署),不是两个系统对接。
┌──────────────────── 统一运营台(一个产品边界) ─────────────────────┐
│ │
│ 运营/管理员 ─▶ console 消息台服务 │
│ (React19+Vite) ┌────────────┐ (Flask+gunicorn)│
│ │ /api │ │ ┌──────────────┐ │
│ ▼ │ server │ │ 企微执行层 │ │
│ nginx ────────────▶│ (FastAPI) │◀▶│ 发送/限流/加人│ │
│ │ │ │ SQLite │ │
│ 达人 ─微信─▶ miniapp ────────────▶│ │ └──────────────┘ │
│ (uni-app+Vue3) └─────┬──────┘ 127.0.0.1:5040 │
└─────────────────────────────────────────┼──────────────────────────┘
│
┌──────────────┬──────────────┬───────┴──────┬──────────────┐
▼ ▼ ▼ ▼ ▼
MySQL xijian lynoxi 旧库 集星 API 数据中台 API 方舟 ARK
/xijian_test (跨库只读) dls.lynoxi.com ai.iphome.cn (视频理解)
新库·权威 历史价/旧订单 达人档案指标 项目经营数据 P1-6 起
(现役) (将来主来源)
外部方向一律只出不入:外部系统不主动写犀见库,犀见也不直连任何外部数据库(§5 铁律)。
| # | 决策 | 理由(一句话) | 日期/出处 |
|---|---|---|---|
| 1 | 后端从零重写,Python 3.12 + FastAPI | 旧 Spring Boot 对内部工具过重;与消息服务同语言可真复用 qiwe/store/ai 能力;AI 集成走 Python 生态 | 2026-08-15 CLAUDE.md |
| 2 | 数据库 MySQL(不是 PG) | 业务数据在现 MySQL 8.0,同实例部署是低险解;PG 的 JSONB/CTE 优势在本规模不构成决定性差异 | 2026-08-15 CLAUDE.md |
| 3 | 独立新库 xijian + 跨库只读旧库(原「共库启动」的演进) |
新系统全新口径自由设计;同实例便于跨库只读历史数据;旧 lynoxi 系完全解耦 | 2026-08-17 charter §4(用户拍板) |
| 4 | 本系统不做 RPA(无 Playwright 抓取) | 业务数据从远程数据中台拉;犀见不负责数据抓取 | 2026-08-15 CLAUDE.md |
| 5 | 外部数据一律走 API,绝不直连外部数据库;中台统一 API 为唯一通道(专用 token),MCP 弃用(2026-08-17) | 减少外部依赖;类型契约/超时重试/缓存/易 mock 全在 API 侧成熟 | 2026-08-17 charter §4 |
| 6 | 消息域融合:产品一体、代码层服务化 | 主工作面板即消息台;老代码不动不管,吸收经验而非重写已验证接入层 | 2026-08-16 契约 §1 |
| 7 | 触达能力 shadow-first:off/shadow/live 三态,live 走全评审链 | 企微封号=整条触达链全断,代价不可逆 | 契约 §1.4 / charter §6 |
| 8 | miniapp 不基于旧代码迭代,按新定位大量重构(旧代码仅作设计风格参考) | 旧小程序线上逻辑与新定位差距过大 | 2026-08-16 CLAUDE.md |
| 9 | UI 自研组件 + Radix 原语,不引入 shadcn/ui | 已是同配方;shadcn 组件 100–300 行且自带独立 CSS 变量体系,与 tokens.css 唯一色源冲突 | 2026-08-15 CLAUDE.md |
| 10 | 达人广场数据源演进:中台接入后为主来源,集星 API 现役先用 | 中台达人信息最全;结构调整再议,不预设 | 2026-08-16 二批确认 |
| 11 | 旧 api 生产容器与其 8 个定时任务不动不打扰 | 它们持续维护 lynoxi 数据;犀见只跨库只读消费 | 2026-08-17 charter §4 |
| 层 | 选型 | 一句话理由 |
|---|---|---|
| server 语言/框架 | Python 3.12 + FastAPI | 见 ADR 1;REST + pydantic 自动文档,双端消费 |
| ORM/迁移 | SQLAlchemy 2.x(sync)+ Alembic | 成熟稳、类型友好;schema 演进只加不破坏 |
| 包管理 | uv | 快、锁定可靠 |
| HTTP 客户端 | httpx | 同步异步一套 API(app/central.py、app/domains/jixing/client.py) |
| 任务调度 | APScheduler(进程内,app/scheduler.py 注册表模式) |
轮询/催发/同步够用;Celery 属过重预设计 |
| 认证 | JWT(无状态)+ 测试令牌;飞书 OAuth 后补 | 照搬 admin-v3 已验证模式 |
| console | React 19 + TS + Vite 8 + Tailwind v4 + Radix 原语 + cva + recharts | 迁自 admin-v3 已验证配方 |
| console 测试/检查 | vitest + oxlint + 自研结构机检 | 约定变可执行检查(§9) |
| miniapp | uni-app + Vue 3(微信小程序 AppID wx120205414255fb5b) |
达人端既有触点 |
| 数据库 | MySQL 8.0(115 机容器 33306),库 xijian / xijian_test |
见 ADR 2/3 |
| 部署 | systemd + uvicorn + nginx | 与消息服务同款运维形态;不上 Docker 全家桶 |
| 日志监控 | 结构化日志 + journald / nginx 现状 | 不上 Prometheus;journalctl -u xijian-server 够查 |
| AI | 方舟(豆包)官方 API SDK,key 走 .env | 视频理解模型(P1-6 起);日请求上限走配置中心 |
| 企微接入 | 沿用消息台 QiWe 接入层 | 已验证,坑都踩平了 |
入口 app/main.py::create_app():装 envelope 异常处理器 → 请求日志中间件 → 各域 router(统一前缀 /api)→ 可选启动 APScheduler。新接口三件套 = domains 内实现 + tests/contract/ 契约测试 + main.py 登记。
响应壳(envelope 语义,全站唯一出口 app/envelope.py)
| 场景 | HTTP | 壳 |
|---|---|---|
| 成功 | 200 | {code:0,message:"ok",data,success:true} |
| 业务错误(含权限不足 403、唯一键冲突 409、参数不合法 422) | 200 | {code:<业务码>,message,data:null,success:false} |
| 会话失效/未登录 | 401 | 同 err 壳(前端据此清 token 跳登录) |
| 未捕获异常 | 500 | 固定文案,诊断信息只进结构化日志 |
domains 清单
| 域 | 目录 | 职责 | 状态 |
|---|---|---|---|
| 认证 | domains/auth |
JWT 签发/解码、测试令牌登录(TEST_LOGIN_TOKEN 非空才注册路由) |
已建成 |
| 健康 | domains/health |
探活;无库时报 db=skipped |
已建成 |
| 系统 | domains/system |
权限注册表、用户/角色 CRUD、审计查询;store 有库/内存双分支 | 已建成 |
| 配置中心 | domains/config_center |
cfg() 全域读、写接口挂权限+审计、缓存失效 |
已建成 |
| 达人域 | domains/influencers |
档案/账号 CRUD、三层判定(layer.py)、分级(grade.py)、唯一键匹配(match.py)、名单过滤器(scope.py)、收款掩码 |
已建成 |
| 集星富化 | domains/jixing |
client/retry/parse/enrich + 手动富化路由 | 已建成 |
| 消息集成 | domains/msgbridge |
三态门 gate.py、touch 计数去重 touch.py、动作编排 actions.py、HTTP client |
已建成(无对外路由,域内能力) |
| 项目与计划 / 商单 / 结算 / 数据域 | — | charter §1 已定域映射 | 规划中 |
横切能力
deps.require_perm(perm) 依赖注入,权限码从 JWT 携带的 perms 快照校验。domains/system/audit.py::audit() 是 service 层函数(不是 HTTP 接口),三 sink——结构化日志必写 / 有库 INSERT xijian_audit_log / 无库进程内内存兜底。app/middleware.py 一行一请求(method/path/status/耗时/操作人),跳过 /api/health 防灌水。DATABASE_URL 空):health 报 skipped、system 走内存 store、cfg() 走 seed 兜底——前端联调轻路径。例外:msgbridge touch 去重无库直接报错拒绝执行(去重失效的代价是重复骚扰达人/触发风控,不可退化)。src/lib/router.tsx(matchRoute 精确表 + :param 段),src/routes.tsx 为 lazy 拆包登记表。新页面三步:routes.tsx → components/layout/nav-items.ts → feature 目录(机检强制两表一致,历史上真出过 nav 有页面无路由的 404)。features/<模块>/ = page.tsx(只做拼装)/ api.ts(该模块所有请求)/ types.ts / hooks/(一个 hook 一件事)/ columns/(一列一个文件)/ components/。当前已建:dashboard、auth、influencers、system-users/roles/audit/config。src/lib/http.ts 统一解 envelope、带 token(localStorage xijian.token)、15s 超时、401 清 token 跳登录;禁止裸 fetch。components/ui/ 基础件不含业务、单文件 ≤80 行有效代码、一个文件 useState ≤6;颜色只出 src/styles/tokens.css——写死 hex 与"tokens 里不存在的语义类"都会被机检拦下。当前目录是 xijian-legacy/app 的工作区快照(来源 commit 记于 miniapp/README.md),存量页面九个(入驻/报名/任务详情/入园回填等)。按 ADR 8,后续按新定位大量重构,不在旧逻辑上迭代;旧代码作设计风格/样式参考。达人端在架构中的两个硬链路不变:小程序绑定身份(openId/unionId)与 wcid 回流(§6.2)。新信息架构待产品方案落地,标待定。
生产库 xijian、测试库 xijian_test,同 MySQL 实例(115 机容器 33306)与 lynoxi 系解耦。当前仓库默认 DATABASE_URL 留空(无库模式),DSN 已在 .env.example 备妥,正式接线时点由主会话拍板。
| 域 | 表(14 张,全部 Alembic 建) |
|---|---|
| 达人域(7) | influencer(主档)、douyin_account(账号,三层 layer 唯一落点)、douyin_account_metric(近 30 天指标快照,1:1)、influencer_binding(企微绑定镜像)、influencer_payment_info(收款/敏感字段)、influencer_service_region、influencer_blacklist(可逆拉黑) |
| 系统域(6) | xijian_config(配置中心)、xijian_audit_log(审计)、admin_user / admin_role / admin_user_role / admin_role_perm(RBAC) |
| 消息集成域(1) | msgbridge_touch_log(触达去重占位,计数制) |
命名与类型约定(达人域设计 §0,全域沿用):新表无 xijian_ 前缀(xijian_config/xijian_audit_log 是前定案时期历史命名,不追改);枚举用 VARCHAR + 应用层 StrEnum(全小写下划线);金额列名带 _fen、比率 DECIMAL 标度统一 0–1、多值走 JSON 数组、软删 deleted_at、有旧库映射源的表带 legacy_id 做导入幂等锚;不建物理外键,靠索引 + 应用层保证。
| 类型 | 策略 | 适用 |
|---|---|---|
| 新域新表 | 按 v2.1 口径自由设计,建在 xijian 库 | 配置中心、RBAC、推荐子系统、邀约批次、计划库 |
| 演进域 | 新表按新模型设计;切流时自 lynoxi 一次性映射导入(可重跑、有对账、reject 清单落文件) | 商单(新状态机)、达人三层库 |
| 历史旧表 | 跨库只读 lynoxi.*,不重建不写 |
历史成交价(行情锚)、旧订单 |
跨库只读纪律:独立只读 engine + 只读账号,SQL 一律写全限定名 lynoxi.xxx(新旧同名表存在),分页按主键游标、禁 OFFSET 深分页。
xijian_config(key / value / value_type / description 说明 / source 出处 / updated_by / updated_at),key 命名规范 域.蛇形名;分组由 key 前缀派生(key.split(".")[0],无独立 group 列)。当前种子 50 键、9 个前缀域(grade / sla / settlement / recommend / msgbridge / data / growth / ark / bf)。cfg(key) / cfg_num(key) 是全项目取阈值的唯一入口,模块级缓存惰性全量加载;写接口挂 system.config.write 权限 + 审计打点,写库成功调 invalidate()(下次读自然拿新值,不在写请求路径里现算全量)。seed.py;迁移文件是历史快照冻结不改,seed.py 是"当前默认值"的活源,两处漂移由单测挡住。value="待确认"(value_type=str)原样返回字符串,绝不静默转 0;依赖该键的判定短路并显式告警。每个键注明 baseline 出处。铁律:外部数据一律走 API,绝不直连外部数据库。(charter §4,2026-08-17 定案)MCP 只是人与 agent 的调研通道,服务端运行时集成一律 REST API。
| 源 | 通道 | 犀见用途 | 状态与要点 |
|---|---|---|---|
| 集星 | https://dls.lynoxi.com GET,无认证(白名单可达) |
达人档案富化 + 近 30 天指标快照 | 现役。超时单独配 120s(内部要爬);四坑:取 digit_value 不取 value;status_code != 0 多为反爬应重试;data 空 + status_code=0 是采集侧 session 过期,等重试、绝不调登录接口;比率字段 digit 已是 0–1,再 /100 错 100 倍 |
| 数据中台 | https://ai.iphome.cn,Bearer token(CENTRAL_BASE/CENTRAL_TOKEN),client app/central.py |
项目经营数据、达人带货归因/视频/订单/售后;接入后为达人广场主来源 | 骨架已在,业务接入随 P0-4/数据域 |
| 林客计划数据 | 中台补充中 | 计划同步 | 待定,就绪前 mock 不卡开发 |
| 消息台 SQLite | HTTP 127.0.0.1:5040(§6) |
会话/消息/绑定关系/定价/群发任务——只存在消息台,MySQL 里没有 | 现役,只能走 HTTP |
| lynoxi 旧库 | 同实例跨库只读 | 历史成交价、旧订单、一次性导入源 | 只读;旧 api 的 8 个定时任务继续维护它,不打扰 |
| 方舟 ARK | 官方 API SDK,ARK_API_KEY 走 .env |
视频内容理解 | P1-6 起,日请求上限走配置中心 |
| 项 | 事实 |
|---|---|
| 定位 | 消息台深度融入统一运营台,对用户是一个产品;服务间是代码层接口,不是"两个系统对接" |
| 分工 | 犀见 server 编排:圈人、判发不发、文案组装、幂等去重、审计留痕、批次归因、结果回执;消息台执行:企微通道本身(发送、限流、设备在线、风控熔断、加人节流、群发分批) |
| 通道 | http://127.0.0.1:5040(同机 115)。不走公网 message.lynoxi.com(公网入口由 nginx Basic Auth 挡,非服务间通道) |
| 身份头 | 每请求必带 X-Auth-User: xijian-server、X-Auth-Oid: system-xijian;配置在 .env(部署事实,不进配置中心) |
| 安全边界 | 消息台内网 /api/* 无凭证,全部安全性来自「只监听回环 + 同机」;跨机部署即失效,升级钩子 MSGBRIDGE_AUTH_MODE(v1 唯一值 header) |
| 限流 | 只继承不复制:额度实时读消息台接口,闸值绝不抄进 cfg(抄了就是两份真相,必然漂移到突破企微真实上限) |
| 发送通道 | 犀见绝不自建企微发送通道,所有主动触达经消息台 API |
| 三态门 | msgbridge.mode(off/shadow/live)+ 场景级 msgbridge.scene_mode.<scene>,取二者更保守档;未知值收敛为 off。shadow = 名单/文案/幂等/审计全跑但零写类出站;off = 连请求都不构造 |
| 去重 | msgbridge_touch_log 计数制(每日上限走 cfg),先占后发;超时无响应标 unknown 不自动重发(发送接口无幂等键,重发代价高于漏发) |
| 红线 | 数据不达标催发只接受人工触发(trigger=auto → 422)——"系统绝不自动催发不达标达人" |
| 轮询三原则 | 受控集合(只轮活跃实体,永不全量扫)/ 变更才写(fingerprint 比对,值未变零写入零事件)/ 水位游标;频率全部走 cfg,无活跃实体时零出站 |
消息台发小程序卡片(wcid) ─▶ 达人点开 ─▶ miniapp 拿 wcid + openId
│ │
│ ① 权威兑现(先) ▼
└──────────── api.lynoxi.com/qiwe/wcid/redeem(HMAC 自证 + TTL)
│
② 通知犀见(后,失败不阻塞达人流程)
▼
server 写 influencer_binding 镜像 ─▶ 触发建联入档 + 层级重算
▲
③ 兜底:定期对账轮询(synced_at 游标)补齐 ②
签发与兑现留在消息台(密钥不跨服务、绑定权威表单一),犀见只做镜像。绑定关系是"业务身份 → 企微身份"的唯一可靠桥——企微不给外部联系人手机号/微信号,别指望用手机号在企微侧搜人;未命中绑定的达人一律进"无法触达清单"显式呈现,不静默跳过。
POST /api/admin/douyin-accounts/{id}/enrich(挂 influencer.write)→ jixing/client.py(120s 超时、重试策略内置、trust_env=False)→ 两接口(档案 + 带货表现)→ parse.py 解 digit_value → 更新 douyin_account 档案字段 + upsert douyin_account_metric;metric 行按 fingerprint 比对,值未变整行不写(零 UPDATE、零 binlog)。批量/定时富化排 P1。
domains/system/perms.py,当前 10 个:system.* 7 个 + influencer.read/write/payment.read),角色—权限绑定是运行时数据落 admin_role_perm;JWT 携带 roles/perms 快照,require_perm 不足时 HTTP 200 + code 403(不是会话问题,不踢登录),仅会话失效走 401。audit(username, action, target, detail, ip)。已打点面包括 config.update、influencer.create/update/delete、influencer.grade.change、influencer.blacklist.create/revoke、influencer.payment.create、influencer.payment.reveal、influencer.account.create/update/bind、roles.*、users.*、auth.login、msgbridge 触达(记 scene/mode/trigger/operator/批次)。masked 标记;明文需 influencer.payment.read 权限,且查看动作单独审计。身份证从达人主档下沉到收款表,收敛读取面。.env 不入库不提交(JWT_SECRET / ARK_API_KEY / DB 密码);配置中心只存业务口径,不存任何密钥;Alembic 迁移里不得出现明文;机检扫描旧仓泄漏特征前缀(scripts/check_structure.py),console 侧另有 check-pii.mjs 测试库 PII 检查。115.190.214.120(主机,一台机承载全部)
| 组件 | 形态 | 位置/端口 |
|---|---|---|
| console 静态站 | nginx | /var/www/admin-v3.lynoxi.com → http://admin-v3.lynoxi.com(打磨期访问地址) |
| 文档中心 | nginx 静态 | /var/www/xijian-docs/ → /docs/(HTML 由 MD 渲染同步,§9) |
| MySQL 8.0 | 容器 | 33306,库 xijian / xijian_test |
| 消息台服务 | systemd message,Flask + gunicorn(-w 1 --threads 4,单进程) |
/opt/message/,监听 127.0.0.1:5040 与 172.17.0.1:5040(docker 网桥,供容器内 nginx 反代);SQLite /opt/message/xijian.db |
| 犀见 server | systemd xijian-server + uvicorn(单元文件样例已备 server/scripts/xijian-server.service,Restart=always) |
/opt/xijian/server,127.0.0.1:8000;日志 journalctl -u xijian-server |
| 旧 api 生产容器 | 冻结只修 bug,8 个定时任务在跑 | 不擅自动;犀见跨库只读消费 |
121.196.161.103(大千 ECS,备用):/var/www/xijian.daqian.ai 预热目录,正式域名 xijian.daqian.ai 切换时只改 nginx;机上另有大千其他系统。
公网固定入口(不可迁):api.lynoxi.com 上的企微回调 /qiwe/callback、小程序回传 /qiwe/wcid/redeem、卡片封面 /qiwe/share.png、待发送媒体 /qiwe/up/*。
部署纪律:① 生产库写操作前先在测试库实证,生产切流由用户拍板时点;② console scripts/deploy.sh 先跑构建自检、失败即停,产物指纹与线上比对防版本漂移;③ 不擅自动旧 api 服务与容器、不接管消息台部署机的其他系统;④ 危险外呼(企微发送)先 shadow,真实执行走确认机制。
测试库策略(澄清,2026-08-17):犀见生产/测试环境 100% MySQL(xijian / xijian_test)。自动化测试(pytest)用 SQLite 内存临时库跑逻辑正确性——每用例独立建库毫秒级、零污染(Alembic 迁移以
with_variant保证双方言兼容,MySQL 为权威方言)。SQLite 测试的已知盲区是网络成本被掩盖(本项目两次性能事故的根源),因此配第二道门:qa 验收必须连 MySQL 测试库以真实数据量实测。另注:消息工作台(legacy)自有 SQLite 存储属天择侧现状,犀见只经 API 消费。
三条铁律:① 文件小而专一(server 单模块 ≤200 行、console ≤80 行有效代码);② 口径数字不硬编码在业务逻辑里——集中配置并标注基线出处;③ 写库前判"值是否真变",轮询按实体去重(旧仓 binlog 日增 5G 的教训)。
机检(约定变成可执行检查)
| 侧 | 命令 | 规则 |
|---|---|---|
| server | uv run python scripts/check_structure.py |
单模块 ≤200 行有效代码;密钥模式扫描;domains/ 下裸数字比较告警(疑似口径魔法数字,白名单豁免机制) |
| console | npm run check |
单文件/page ≤80 行;useState ≤6;写死色值拦截 + tokens.css 语义类存在性校验;routes ↔ nav-items 一致性 |
测试基线(2026-08-16 实测):server uv run pytest 315 用例(contract 契约测试 + unit),console npx vitest run 76 用例全绿;CI 每 push 跑两端全链兜底。新接口无契约测试不算完成;涉及口径判定的逻辑,契约测试必须覆盖阈值边界并验证"阈值可配"。
文档双份管线:一切文档 MD 为源进 git;在 docs/render-docs.py 的 REGISTRY 注册即获线上 HTML;docs/sync-docs.sh 一键渲染 + scp 到 115 文档中心。本文件已注册(architecture.html)。
文档驱动开发协议:进度唯一事实源是 docs/dev/execution-plan.md;业务开发会话开局先读它对齐,再读 charter(流程)与基线(口径),不依赖对话记忆;每完成一个子任务在当次提交内更新状态与 commit 号。口径变化 → 先改基线再写代码;基线没有的判定不编,标待确认。
流程分级(charter §6 摘要):日常功能开发走单 agent 承包 + 自验全绿 + 主会话终验;涉及口径判定加阈值边界测试;写旧库 / 资金相关 / 对外发送(企微)走全评审链;合入生产/切流需全评审链 + 测试环境实证 + 用户拍板。口径数字硬编码 = review 一票否决项。
| 日期 | 版本 | 变更 |
|---|---|---|
| 2026-08-16 | v1.0 | 首版:系统总览/ADR 摘要/技术栈/应用·数据·集成·安全·部署架构/工程纪律。事实源为 CLAUDE.md、charter v1.3、msgbridge 契约 v1.0、达人域设计、集星笔记与代码实况 |