主题
第 20 周 · Day 7:周复盘——用一条用户旅程给平台验收
手册任务:周复盘 + 整理。走一遍「登录 → 对话 → RAG → 工具审批」完整流程,写 300 字周记,当日产出:流程验证 + 周记。 本篇解决的问题只有一个:这六天每个模块各自的验收都过了,怎么证明它们拼在一起还是一座平台,而不是六个能各自跑的零件。
今日目标
- 用真实账号把主链路 12 步完整走一遍,每步都有可观察的验证点,全程不抄开发者的近路
- 按四段模板写一篇 300 字周记
- 过一遍 10 题自检清单,答不上来的标记出来,回读对应 Day 的教程
概念讲解:为什么整合周的复盘是走链路,不是画图
第 1 周 Day 7 的复盘画结构图,检验的是结构在不在脑子里。本周不适用。第 20 周的主题是整合:BFF、多租户、认证、流式 UI、导航,每一件都在当天单独验收过。整合工作的风险不在零件,在接缝。Day 2 的 curl 三连全过,浏览器里照样可能整段蹦字,因为攒流的位置(代理缓冲、压缩中间件)只有真实浏览器旅程才暴露;Day 6 的租户切换同理,接口返回 200,页面纹丝不动,断的是 server component 不会自己刷新这条接缝。
所以本周复盘的动作从「画」换成「走」:扮成一个真实用户,从打开首页到退出登录,把一条旅程走完,每步打勾。检验标准也从「能不能复述」升级成两层:能不能走通,走通了还能不能说清每步背后为什么这样设计。前者验工程,后者验理解。输出还是三种,各逼一样东西:
| 输出方式 | 逼出什么 | 对应今天的产出 |
|---|---|---|
| E2E 走查 | 接缝是否真的通 | 12 步验收清单 |
| 写作 | 认知是否变成自己的话 | 300 字周记 |
| 自测 | 细节是否记牢 | 10 题自检清单 |
模板变了没
没变,还是输出倒逼输入。变的只是第一件:单点深入的周画图,整合类的周走链路。判断标准一句话,这周学的是「零件」就画它,学的是「装配」就走它。
核心知识
1. 主链路 E2E 验收:12 步逐步打勾
先立三条纪律,没有它们走查会退化成瞎点:
- 从浏览器走,不许 curl 抄近路。curl 留给失败后的定位,验收必须走用户的真实路径
- 每步两个必填项:预期(应该发生什么)、验证点(在哪里看到)。验证点必须是可观察的事实,「看起来正常」不算
- 链条中途断了,修完从第 ① 步重走,不从断点续走。修复可能弄坏上游,整条重走才算数
前置准备:起四个服务(Next.js 3000、BFF 3001、FastAPI 8000、数据库和向量库),确认 Day 3 的种子数据还在(租户 1 三条文档、租户 2 两条),准备甲公司 admin 账号一个。然后开走。
① 打开首页。 预期:未登录直接访问 /,被 middleware 拦下重定向。验证点:地址栏变成 /login?from=%2F,from 参数记着来路;登录页不带侧边栏,它排在平台壳的路由组外面。
② 跳到登录页。 预期:登录页正常渲染,表单可输入。验证点:邮箱、密码、租户三个字段都在;此刻 Network 面板没有任何业务请求,未登录状态不预拉数据。
③ 登录成功,带着租户进平台。 预期:甲公司 admin 账号登录,跳回 from 指向的对话页。验证点:Application 面板里 refresh_token 这条 cookie 的 httpOnly 列打着勾,Console 执行 document.cookie 读不到它;顶栏显示用户与租户;侧边栏五项全出,审批中心角标显示当前待办数。
④ 对话页提问。 预期:问一个会命中知识库的问题(用种子文档里的内容),回复流式吐出。验证点:正文逐字出现,不是等几秒整段蹦出。攒流类问题一定在这步现形,curl 看不出来,浏览器一翻便知。
⑤ 看到 Thought 折叠面板。 预期:答案生成途中,上方出现可展开的思考过程。验证点:默认收起,点开能看到先检索、再组织、后回答的路径;思考内容先于最终答案到达,这是事件分型在干活。
⑥ RAG 引用卡。 预期:答案下方挂引用卡,列出命中的文档与片段。验证点:引用全部来自租户 1 的种子文档。想较真就换乙公司账号问同一问题,引用应当完全不同,这是向量库租户过滤的现场检验。
⑦ 高危工具触发审批。 预期:问一个会调高危工具的问题(对照工具页的高危清单,比如删一笔测试订单),Agent 中途暂停。验证点:对话流出现等待审批的挂起卡片;侧边栏审批中心角标加一。
⑧ 审批中心批准。 预期:进审批中心,待办列表里有刚触发的条目,含工具名、参数、理由。验证点:点批准后条目消失或状态变更,角标归零;全程不用回对话流里找按钮,这就是 Day 6 升级的意义。
⑨ 答案返回。 预期:回到对话页,Agent 从中断处继续,答案补全。验证点:回复里包含工具执行的结果;流正常收尾,连接没挂死;Console 无未捕获报错。
⑩ 知识库页上传。 预期:传一份新文档,切片入库。验证点:列表出现新条目,切片数大于零。加深一步:回对话页问一个只有新文档答得上的问题,引用卡指向它。
⑪ 工具页看到 MCP 状态。 预期:工具管理页有两块内容,MCP Server 状态和高危工具清单。验证点:Server 状态为运行中;第 ⑦ 步触发的那件工具在清单里,标着调用需审批。
⑫ 退出登录。 预期:清掉会话,回到登录页。验证点:退出后直接敲 /,重新被拦到 /login;用户信息和侧边栏全部消失;再登录一次能原路进来,链路首尾闭合。
哪步红了,按这张账单回读:①②③⑫ 的守卫与双 token 是 Day 4 和 Day 6 的活;④⑤ 的流式链路是 Day 2 加 Day 5 的流式 UI;⑥⑩ 是第 15 周知识库加 Day 3 的租户过滤;⑦⑧⑨ 是第 13、18 周的 interrupt 加 Day 6 的审批中心;⑪ 是 Day 6 的工具管理页。定位顺序从断点往上游查:比如 ⑨ 答案没返回,先看 ⑧ 的批准有没有真调到放行端点,再看 BFF 日志,最后才动 Agent。
2. 300 字周记
模板还是第 1 周那四段:最大收获、卡得最久、还含糊、下周前补。规则不变,这里只给本周示例,照这个密度写:
text
① 本周最大收获:分段信任。用户 token 止于 BFF,FastAPI 只认 BFF 现签的
短命 service token,每层只信它该信的人。这条链想通之后,多租户、审批、
流式都只是往上面挂的货。
② 卡得最久:浏览器里回复整段蹦出,curl -N 明明是逐块的。查了一个多小
时,发现是压缩中间件在攒流,res.write 之后补 res.flush 才好。攒流的几
个位置我全踩了一遍。
③ 还含糊:AI SDK 流式事件的全集记不全;NextAuth 的 jwt 会话策略没实际
跑过;with_loader_criteria 管不到 raw SQL 的边界,想一遍才敢说。
④ 下周前补:把流式事件分型整理成卡片贴桌上;用 member 账号把 Day 6 自
测清单再点一遍;把 Day 3 的三发攻击测试写成脚本存进仓库。300 字的限制照旧,逼你从「这周学了六样」里挑出真正改变认知的那一样。
3. 第 20 周知识自检清单
规则同第 1 周:每题先口头回答,说完整了再点开答案对照。说不出来的记下题号,回读对应 Day 的教程。
问题 1:BFF 给前端带来哪四个收益?各解决什么问题?(Day 2)
答案
聚合:页面要什么形状就返回什么形状,多接口数据一次给全。鉴权收口:用户 token 只在 BFF 验一次,Agent 不必认识用户。裁剪:model、trace_id、成本这类内部字段止步内网。隔离:Agent 不发公网,独立扩容重启都不牵动前端,浏览器只认识一个域名。
问题 2:为什么不能把用户 token 从 BFF 原样透传给 FastAPI?(Day 4)
答案
三颗雷。暴露面:内网每个服务都握着有效用户凭证,任何一处日志泄露就泄密。耦合:FastAPI 被迫理解 access 过期、refresh 撤销这些会话细节。轮换:密钥共享导致用户密钥一换,所有服务跟着改。正确做法是 BFF 验签后换发短命 service token。
问题 3:service token 由谁签发?为什么短命还不用 refresh?(Day 2、Day 4)
答案
由 BFF 签发。BFF 验完用户 token 后,用服务密钥(SERVICE_JWT_SECRET)现签一枚 60 秒上下的 service token 发给 FastAPI;FastAPI 只认这把密钥,自己不签发。短命是因为它只需要活过一次内网转发,每次现签成本忽略不计,换来被截获后几乎没有利用窗口。refresh 是为用户会话长期存活设计的,服务间调用没有这个需求。
问题 4:多租户三种隔离方案是什么?本教程选了哪个,什么时候该升级?(Day 3)
答案
独立数据库(隔离最强、成本最高,金融医疗类)、同库独立 Schema(居中)、共享表加 tenant_id(行级隔离、成本最低)。教程选共享表:改动最小、硬件全客户共享,是中小规模 SaaS 的主流。代价是安全靠工程纪律,全局 filter 和越权测试不能省。升级信号:大客户拖慢共享库(吵闹邻居)、合同要求物理隔离、连接数顶不住。tenant_id 从第一天就在,迁移只是搬数据,业务代码不改。
问题 5:tenant 隔离要过哪些存储?各用什么手段?(Day 3)
答案
三处。业务表:tenant_id 列加 SQLAlchemy 全局 filter,查询自动过滤、写入自动盖章。LangGraph checkpointer:thread_id 加租户前缀,续聊前还要过归属校验,防的是抄别人的 thread_id。向量库:写入时 metadata 带 tenant_id,检索端永远带租户过滤。清单不是一次性的,每加一种新存储(文件、缓存)都要重新过一遍。
问题 6:什么时候值得上 NextAuth?它管哪段、不管哪段?(Day 4)
答案
要接 Google、GitHub 这类第三方 OAuth 登录时值得上,Provider、回调、token 刷新、CSRF 全是现成的,至少省一周。只有邮箱密码登录、且第 5 周的 JWT 体系已经在跑,自建更顺手。它只管浏览器到 BFF 这半段的登录与会话,BFF 到 FastAPI 的 service token 换发不归它管,该手写的照样手写。
问题 7:stream updates 为什么要做事件分型?说出至少四类。(Day 5)
答案
因为流式响应不是一锅字符,是带类型的消息序列:正文文本增量、思考过程(Thought)、工具调用、工具结果(Observation)、引用来源、错误。前端按类型路由到不同 UI:正文进打字机、思考进折叠面板、来源进引用卡、错误进兜底提示。不分型就全挤在一个文本框里,思考过程展示无从谈起。
问题 8:把 Thought 折叠面板展示给用户,价值在哪?(Day 5)
答案
信任。黑盒答案用户只能选择信或不信;把 Thought、Action、Observation 摊开,用户能核对它检索了什么、为什么这么做。高危工具调用前,审批人有依据判断该不该批;出错时也能分辨是检索没命中还是推理跑偏。信任从赌结果变成看过程。
问题 9:五页导航按什么排序?member 看不到的页面怎么处理?(Day 6)
答案
按使用频率加角色可见性排,不按功能分类:对话(日频、所有人)第一,审批中心(日频、approver 和 admin)第二,知识库(周频)第三,工具管理(低频、admin)第四,监控低频且 Grafana 本身是完整界面,直接外链。member 看不到的页面不是置灰,是从导航里消失。
问题 10:前端路由守卫的边界在哪?为什么说它只做体验?(Day 6)
答案
页面代码跑在用户浏览器里,cookie 可以伪造、代码可以篡改,攻击者根本不需要浏览器,拿着 member 的 token 直接 curl BFF 接口,前端一行都拦不住。所以 middleware 拦未登录、403 页拦角色不够,都只是让用户别白点;真正的防线在 BFF 和 Agent,每个接口独立验 token、角色、租户。一句话:前端挡君子,后端挡所有人。
全对也别飘
题全对加上链路全绿,本周才算收口。只对题没走链,是纸上平台;只走链答不上题,是碰巧能跑。
动手任务:走链路,收一周
五步,全程 90 分钟上下。
第一步:起服务备数据(10 分钟)。 四个服务全起,种子数据、两个租户的账号各就各位。数据没备齐别开走,第 ⑥ 步引用卡没有文档可挂,你会误判成 RAG 坏了。
第二步:走 12 步打勾(40 分钟)。 照核心知识第 1 节逐步走,每步打勾或记红。红项只有挡住后续步骤才当场修,否则记下步号继续,先摸清一共断了几处。
第三步:红项定位修复(20 分钟)。 按「断点往上游查」的顺序:先看 Network 面板请求发没发出去,再查 BFF 日志,最后才动 Agent。回读哪篇教程,照第 1 节那张账单。修完从第 ① 步整条重走。
第四步:写周记(20 分钟)。 四段模板,对照示例的密度。「还含糊」那段别敷衍,它是下周的输入。
第五步:自检加 git 收口(20 分钟)。 10 题口头过一遍;本周改动分开提交,打 tag 收口:
bash
git add apps/bff
git commit -m "feat(bff): 多租户与认证贯通收尾"
git add frontend
git commit -m "feat(web): 平台导航与审批中心"
git tag week20-done原则照旧:一个提交只做一件事,代码、配置、文档各走各的。
常见踩坑
用 curl 代替浏览器走查。 图快全程 curl 打接口,十二步「全过」。攒流、激活态全站高亮、租户切换不刷新这类只在浏览器现形的问题全漏掉。curl 是调试工具,替代不了验收的用户视角。
验证点写成「页面正常」。 不可观察的验证点等于没验证。改成事实:cookie 的 httpOnly 列打着勾、角标数字从 1 变 0、引用卡里文档名对得上种子数据。写得出来的才叫验。
断点续走。 第 ⑦ 步修好直接从 ⑧ 接着走,修复波及上游的可能性没排除。E2E 的纪律是修复后整条回归,麻烦,但唯一可信。
走查途中顺手重构。 看到别扭的代码忍不住动手,走查中断,改出新 bug,验收烂尾。走查日只记录不重构,重构是验收之后另起的事。那份打过勾的清单收好,它是下周回归测试的底稿。
延伸阅读
- Martin Fowler:The Practical Test Pyramid,端到端测试为什么贵但不可替代的原典,今天手走的 12 步就是金字塔顶上那一层
- Playwright 文档,今天的 12 步以后可以逐条固化成 Playwright 用例,回归从人肉 40 分钟降到跑一次脚本
- 本周六天的教程都在第 20 周目录,红项定位时按第 1 节的账单回读;复盘模板的出处见第 1 周 Day 7
12 步全绿的那张清单收好,它是这座平台的底片。第 20 周到此收口。