项目:商品描述审阅与协作工作台
设计草稿版本、审阅权限和证据校验,让 AI 建议经过人工批准后导出,处理多租户访问与旧版本冲突。
设计一条受权限和版本约束的审阅路径,并验证拒绝、重试与导出失败。
商品描述审阅工作台接收已有描述和佐证材料,让 AI 提出修改建议,再由有权限的审阅者批准具体版本。它适合练习多租户权限、版本冲突和模型结果校验:生成建议、批准版本、导出内容是三个独立动作。
先把范围定小:支持一个商品的一份草稿、一次模型建议和一次人工审阅。例子中的租户、商品和成员都是合成数据,不代表真实客户。完成这条路径后,再增加批量操作、通知和团队管理。
把需求写成可验收的行为
作者可以创建草稿、查看原文与建议、提交新版本;审阅者可以批准或退回自己有权处理的版本;导出只读取已批准内容。AI 没有批准或发布权限。收到一次模型响应,不应让草稿自动进入已批准状态。
验收要包含失败行为:另一租户看不到草稿,作者不能冒充审阅者,旧页面不能批准已被修改的内容。模型超时后保留原文,重复提交不会创建第二次逻辑审阅,导出失败不撤销已完成的批准。
这些规则应写进接口和数据约束,不能只靠页面隐藏按钮。浏览器发送的租户、角色和操作者字段都是输入,服务端要从已验证身份和成员关系确定实际权限。
为版本与审阅分别建模
核心实体可以分为租户、成员关系、商品、草稿版本、审阅记录和模型运行记录。商品保存稳定标识,草稿版本保存不可变内容及父版本,审阅记录明确针对哪个版本、由谁以何种权限决定。
不要把一个 approved 布尔值放在会不断变化的文本上,然后认为批准永远有效。新修改应形成新版本;旧版本的批准仍作为历史保留,但不能被借来导出新文本。审阅结果还需要理由、时间和规则版本等可追溯信息。
模型运行记录关联输入版本、引用材料版本、输出、错误类别和处理状态。审计记录描述谁执行了什么动作,不默认复制整段用户内容。模型调用在数据库事务外执行,避免长时间等待占住事务和锁。
用 Supabase 划清访问边界
对 Data API 暴露的表配置表权限与 RLS。它们处理不同层次:角色是否有权访问表,与能访问表里的哪些行,需要分别定义。仅写 TO authenticated 不能限制租户或资源范围,还要结合可信的成员关系判断。
读取草稿检查当前用户属于对应租户;写入还检查允许的角色和动作。更新策略应同时考虑旧行可访问性、新行约束以及所需的读取权限,防止改写 tenant_id 或所有者把资源移到另一个范围。租户身份不能由用户可编辑的元数据直接授权。
前端使用适当的公开客户端配置,管理用 secret key 或旧式 service-role 凭据只留在服务端。当前文档说明:没有用户 access token 的管理请求可通过 service_role 绕过 RLS;带用户 token 的请求会按该用户策略执行。因此,不要把“客户端初始化用了管理密钥”当成唯一权限判断。特权服务还要显式检查业务授权。
把接口和模型结果分开校验
创建草稿接口接收商品标识、内容和请求去重标识,服务端验证长度、身份与商品归属。提交审阅需要目标版本与预期版本;批准接口同时验证审阅角色和版本,失败时返回稳定的权限或冲突类别。
模型建议可以包含替换文本、引用片段、建议理由和待确认事项。结构化输出约束字段和形式,不会证明引用支持结论。程序应校验引用确实来自允许使用的材料、商品标识正确、字段长度受限,再让审阅者比较原文与建议。
拒绝、输出中断、供应商错误和业务校验失败分别保留状态。不要把流式输出的一小段 JSON 当成完整建议,也不要因为重试成功就抹掉此前的失败记录。模型适配器返回业务需要的结果,页面无需理解供应商的所有事件格式。
用版本检查阻止旧页面批准
下面只模拟租户边界和乐观版本检查。草稿版本从 1 变为 2 后,仍提交版本 1 的审阅请求返回冲突,另一个租户的请求返回禁止。
draft = {"tenant": "T-1", "version": 1, "text": "original", "approved": False}
def approve(tenant, version):
if tenant != draft["tenant"]:
return "forbidden"
if version != draft["version"]:
return "conflict"
draft["approved"] = True
return "approved"
assert approve("T-2", 1) == "forbidden"
draft["version"] = 2
assert approve("T-1", 1) == "conflict"
assert approve("T-1", 2) == "approved"
print(draft)
输出中的版本为 2,approved 为 True。这段代码没有验证真实身份、审阅角色、数据库并发或 RLS,也没有保存历史版本。它只展示两个检查条件。真实服务要在可协调的事务或条件更新中检查并记录批准,不能把先读取、后写入的内存步骤当成并发保证。
按一条完整路径实施
先建立实体和约束,用两名合成用户及两个租户验证读写边界。随后实现创建、读取和修订草稿,确认刷新后内容与版本一致。再实现批准和退回,把权限、版本检查及审计写入同一个业务操作。
接下来用固定建议结果接通界面:原文、修改差异、出处、状态和按钮都要能工作。最后接入模型适配器,加入超时、拒绝和无效引用。固定结果可以帮助隔离界面问题与模型问题,不代表模型质量已经通过。
导出请求是独立操作,绑定已批准版本的不可变内容,保存目标格式、版本和状态;后台任务重试时不能读取最新草稿代替已批准内容。若版本已撤回批准,是否仍允许正在执行的导出需要明确政策。
批量导出要限制条数、并发与总预算。每项有独立状态和结果,部分失败时仍能查看已经完成的内容,并按原版本重试失败项,不能用整批成功掩盖遗漏。
练习:证明权限与版本都有效
构造作者、审阅者、另一租户成员三种身份。检查跨租户读取、作者批准、审阅者提交旧版本,以及两次相同请求。每次拒绝后,草稿内容、版本和批准记录都不应出现未经授权的变化。
再模拟模型给出不存在的引用和导出中断。无依据建议应进入待处理或失败分支;已批准版本应能重新导出,不能重新批准一个不同版本来掩盖错误。完成后保留接口请求、预期状态和数据库检查结果,单独记录模型建议的人工评估。
资料来源与延伸阅读
资料核验:2026-11-10。本文为原创工程讲解,教学示例不代表线上实测。