当前方案不是完整白标化方案,而是“品牌注入 + 页面配置 + 部署复制”的雏形。最大问题不是缺一个字段,而是缺少一套可审计的租户控制面、配置版本体系、运行时隔离机制和发布回滚机制。
按严重程度,最容易翻车的不是 BFF 48 条路由,而是:
现有三层:
这三层是必要条件,但在模式 A 下仍遗漏以下层。
需要统一管理以下配置:
依据:材料只提到 site-texts 文案域、页面 JSON Schema、品牌注入和种子脚本,没有说明这些配置是否统一存储、是否版本化、是否可回滚、是否区分环境。
如果没有配置治理层,最终会出现:
site-texts;这不叫白标化,叫多处打补丁的复制部署。
最低要求:
TenantConfig
├── brand
├── theme
├── content
├── page_schema
├── navigation
├── feature_flags
├── permissions
├── platform
└── release_version
每类配置必须具备:
模式 A 虽然是一租户一部署、一数据库,但系统仍然需要明确的租户上下文:
请求
→ 域名 / appid / 部署实例
→ tenant_id
→ 数据库连接
→ 配置版本
→ 品牌与页面运行时上下文
依据:材料只提出“域名→租户识别”的问题,没有给出租户上下文如何贯穿 BFF、FastAPI、缓存、日志、任务和存储。
即便数据库物理隔离,也必须有:
tenant_id;deployment_id;否则会发生:
需要区分并管理:
依据:材料有“种子 v1.6.0”“契约 v1.2/v1.3”“脚本生成与源码同步”,但没有定义它们之间的兼容矩阵和发布策略。
必须能回答:
某租户当前运行:
前端包 vX
API vY
DSL vZ
DB Schema vN
Seed vM
否则一旦页面 DSL 升级,旧租户是否兼容无法判断。
最低要求:
schema_version;“主题色 + logo + 标语”不等于主题系统。
至少要覆盖:
依据:材料只有“brand_name/logo/主题色/标语”,没有设计 Token 和组件级主题能力。已有“设计规范七件套”也不能替代运行时主题引擎,因为材料未说明七件套已被编码为可配置 Token。
结论:如果只注入主题色,换一个品牌仍然只是换 logo 的同一套产品。
多语言不是模式 A 的必选项,但语言、时区、货币、地区格式必须抽象。
至少包括:
依据:材料提到 site-texts 文案域和“分元”纪律,但没有提到语言包、时区、货币、地区格式。因此多语言及本地化目前属于『材料未涉及』。
建议:即使第一期只支持中文,也不要把文案结构设计成只能容纳单语言字符串。
“同构 DB + 种子”不等于可迁移。
需要区分:
依据:材料只明确“种子 v1.6.0(16 模块)”,没有说明迁移、幂等、失败恢复、版本升级和生产数据迁移策略。
当前有鉴权标注、权限纪律和后台 CRUD,但材料没有说明白标之后:
依据:材料只说明端点有鉴权/缓存标注,没有说明租户级 RBAC 初始化和运营后台白标化。
小程序系统通常不只有 appid,还会涉及:
依据:材料只明确 appid、域名、HTTPS,没有列出密钥、支付、地图、短信、存储或回调配置。因此这些均为『材料未涉及』,但不能因此认为不需要。
不要一开始做“任意页面可编程”。最小可行架构应当是:
页面实例 + 受限组件树 + 数据绑定 + 动作白名单 + 权限/能力校验 + Schema 版本化 + 静态校验 + 回退页面。
如果允许 DSL 直接表达任意业务逻辑,项目会立刻变成“自研低代码平台”,范围失控。
建议模型如下:
{
"pageId": "home",
"schemaVersion": "1.0",
"route": "/pages/home/index",
"titleKey": "home.title",
"status": "published",
"version": 3,
"permissions": [],
"featureFlags": [],
"dataSources": [
{
"id": "recommendations",
"type": "api",
"endpoint": "/api/v2/recommendations",
"method": "GET",
"cache": true
}
],
"nodes": [
{
"id": "banner_1",
"type": "Banner",
"props": {
"image": "{{recommendations.data[0].image}}",
"title": "{{recommendations.data[0].title}}"
},
"events": {
"onTap": {
"action": "navigate",
"target": "/pages/detail/index",
"params": {
"id": "{{recommendations.data[0].id}}"
}
}
}
}
]
}
最小字段:
pageId:页面稳定标识;schemaVersion:DSL 版本;route:页面路由;status:草稿、测试、已发布、下线;version:页面版本;permissions:访问权限;featureFlags:功能开关;dataSources:数据来源;nodes:组件树;events:白名单动作。第一期只允许有限组件,例如:
依据:材料已有首页、天气、推荐、SOS、品类页、订单状态机等 P0 范围。应优先抽取这些真实场景所需组件,而不是先设计通用低代码平台。
每个组件必须有:
type
props schema
children rule
data binding rule
event rule
permission rule
fallback rule
禁止:
否则会绕过鉴权、缓存、审计和发布治理。
允许:
{{recommendations.data[0].title}}
不允许:
{{任意表达式}}
建议仅支持:
格式化函数也必须白名单化,例如:
currency()
date()
maskPhone()
join()
依据:材料已有“字段 camelCase、分元、空值语义、幂等、权限”等对账纪律。DSL 必须复用这些契约,不能另造一套字段和金额语义。
第一期只允许固定动作:
navigate;back;request;submit;openModal;showToast;login;callPhone;openMap;refresh。其中 request 只能引用已经登记的 BFF 能力 ID:
{
"action": "request",
"operationId": "getRecommendations"
}
不要让页面 DSL 直接拼接 /api/v2/*。
依据:材料已有 BFF 48 条路由映射表,并且包含鉴权、缓存标注。DSL 如果绕开这张表,BFF 的治理价值会被削弱。
材料已有统一响应包装 {success,data,request_id},应把 request_id 贯穿 DSL 数据请求和页面错误定位。
第一期建议只做:
不要第一期 DSL 化:
依据:材料将 SOS 主流程和订单状态机列为 P0,但“P0 要接入”不等于“P0 要 DSL 化”。这类流程应保留原生代码,由 DSL 通过 NativeSlot 或固定业务组件调用。
材料中的“一键初始化”描述漏项明显。appid + DB + 种子 + nginx + 品牌注入 只能覆盖基础部署,距离“10 分钟出新小程序”还差密钥、迁移、管理员、配置发布、验证、回滚、监控和平台审核准备。
必须先校验:
tenant_id 是否唯一;材料现状:未涉及。
必须生成或登记:
tenant_id;deployment_id;密钥不能写进源码、镜像或普通配置文件,必须进入 Secret Manager 或至少加密配置中心。
依据:材料只提 appid,没有提 appsecret、密钥托管和第三方凭证。
步骤应为:
不能只执行“种子 v1.6.0”。
依据:材料明确有种子 v1.6.0,但未说明 migration、租户配置种子、管理员初始化和幂等重试。
必须初始化:
配置必须带:
目前材料只覆盖品牌字段和 site-texts,其余大多为『材料未涉及』。
必须完成:
依据:材料只说明已有三端 HTTPS 和 nginx 需求,没有列出小程序各类合法域名和回调白名单。
需要部署并绑定:
每个租户必须有可确认的:
tenant_id
deployment_id
service version
config version
db schema version
依据:材料提到监控、备份 cron,但没有说明这些是否按租户完成绑定。
必须包含:
材料只确认“小程序已上传验证”,没有证明新租户的自动化发布链路已建立。
脚本不能以“命令执行成功”作为成功标准,必须做业务探活:
必备:
材料未涉及。没有回滚的“一键部署”,只是“一键制造半成品”。
BFF 48 条路由不是白标化本身,只是接口映射资产。BFF 必须新增完整的租户识别、租户上下文传递、配置解析、缓存隔离、权限隔离和可观测性能力。
“根据域名识别租户”远远不够。
建议优先级:
内部可信 tenant header
> 部署实例绑定 tenant_id
> Host / 子域名映射
> 小程序 appid 映射
> 管理后台登录上下文
注意:
tenant_id 不能直接信任;Host 必须经过服务端白名单映射;依据:材料提出“域名→租户识别”,但没有可信来源、优先级和防伪机制。
每个请求进入 BFF 后,执行:
resolve_tenant()
→ validate_deployment()
→ load_tenant_context()
→ attach_context()
→ downstream_request()
租户上下文至少包括:
{
"tenant_id": "t_001",
"deployment_id": "d_001",
"appid": "wx_xxx",
"config_version": 12,
"db_target": "db_t_001",
"environment": "prod",
"user_id": "u_001",
"request_id": "r_001"
}
下游 FastAPI 必须接收并校验上下文,而不是只靠 BFF 自己知道租户。
每条路由至少登记:
operation_id
path
method
tenant_scope
auth_required
permission
cache_policy
rate_limit
idempotency
data_isolation
config_dependency
audit_required
材料已有“鉴权/缓存标注”,但白标化还需要:
错误示例:
recommendations:{user_id}
正确示例:
tenant:{tenant_id}:recommendations:{user_id}:{config_version}
至少隔离:
依据:材料已有缓存标注,但未说明缓存 key 是否带租户。模式 A 物理隔离数据库并不能自动隔离共享 Redis/CDN。
模式 A 下通常是:
tenant_id
→ deployment_id
→ db connection
要求:
品牌、页面 DSL、文案、功能开关都应通过统一配置服务或统一配置模块读取:
get_config(tenant_id, config_type, version)
不要在 48 个接口里各自读取不同配置表。
配置缓存 key:
tenant:{tenant_id}:config:{type}:{version}
用户身份不等于租户身份。建议授权判断至少是:
user_id + tenant_id + role + permission
必须防止:
材料有鉴权和权限纪律,但未说明 JWT、Session、审计和异步任务是否带租户信息。
不同租户的流量、接口能力和配额可能不同,至少要支持:
否则单一租户的流量会拖垮同一套共享基础设施。
需要补充测试矩阵:
租户 A 正常访问
租户 B 正常访问
A 用户访问 B 数据
A 的缓存命中 B 数据
A 的配置影响 B
未识别租户访问
伪造 tenant header
域名与 appid 不匹配
租户停用后访问
配置版本回滚后访问
材料中没有证明上述多租户隔离测试已完成,不能假设 48 条映射已经具备白标能力。
这是第一风险。
材料把“页面结构配置化(JSON schema→动态渲染)”列为核心方向,但没有给出:
而当前业务包含天气、推荐、SOS、订单状态机、会员、护照、路线等不同复杂度模块。若全部用自由 JSON 描述,最终一定会出现:
第二风险。
当前租户层状态是“未启动”,方案只列出:
新 appid + 同构 DB + 种子 + 域名 nginx + 品牌注入
但未覆盖:
没有幂等和回滚的初始化脚本,不是“一键开租户”,而是“一键留下半套基础设施”。
脚本必须是有状态的分阶段执行:
precheck
→ provision
→ migrate
→ seed
→ configure
→ deploy
→ verify
→ publish
每一步要有:
第三风险,但一旦发生,后果最严重。
模式 A 能保证“独立 DB”,但材料没有证明以下共享资源已经按租户隔离:
材料只明确了数据库物理隔离和 BFF 路由映射,未说明这些外围资源的租户隔离策略。
所有共享资源统一使用租户命名空间:
tenant:{tenant_id}:cache
tenant:{tenant_id}:files
tenant:{tenant_id}:jobs
tenant:{tenant_id}:logs
tenant:{tenant_id}:metrics
并建立自动化隔离测试,不能靠开发规范和人工检查。
当前方案可以继续推进,但必须改名为:
模式 A 多租户复制部署的白标化一期方案
不能直接宣称“全栈可配置、无缝移植”。
上线前至少补齐四个控制面:
否则所谓“每开一个小程序就是复制部署”,最终会变成:
复制代码、复制数据库、复制问题,并且每个租户的问题都无法统一修复。