# M2 鉴权与角色：最小登录闭环教程大纲

## 一、文章定位

- 目标读者：正在从前端项目迈向全栈、希望用 `NestJS + Next.js` 做教程型项目的开发者
- 文章目标：带读者从零理解为什么 `M2` 先做“角色模型 + JWT 登录 + 最小后台壳”，而不是直接进入简历 CRUD
- 文章形式：系列教程中的一个里程碑章节，可拆为 2~4 篇独立文章

## 二、背景与问题

- 为什么 `Monorepo` 刚搭起来后，不应该马上进入内容管理
- 为什么“角色与鉴权”要先于后台功能落地
- 为什么教程型项目更需要“小闭环”，而不是一次性把权限体系做满

## 三、本里程碑解决了什么

- 建立唯一业务后端：`apps/server`
- 固定 `admin / viewer` 角色边界
- 跑通最小 JWT 登录闭环
- 建立最小 `apps/admin` 登录壳
- 落地 `viewer` 只读守卫与体验

## 四、里程碑拆解过程

### 1. issue-05 `apps/server` 最小 NestJS 脚手架

- 为什么先把唯一业务后端入口立住
- 为什么暂时不接数据库
- 本步产出和边界

### 2. issue-06 鉴权领域与角色模型

- 为什么角色模型要先于登录接口
- `admin / viewer` 的最小能力矩阵怎么设计
- 如何避免角色语义散落在前后端多个地方

### 3. issue-07 JWT 登录最小闭环

- 为什么先用 demo 账号完成教学闭环
- 登录、签发 token、受保护接口三件事怎么最小实现
- 为什么本轮不急着上 refresh token / Passport 全家桶

### 4. issue-08 `apps/admin` 最小登录壳

- 为什么后台先做“壳”，不先做“内容管理”
- `Next.js` 负责什么，`NestJS` 负责什么
- 如何保证不落入“双后端”

### 5. issue-09 viewer 只读守卫与体验

- 为什么后端守卫和前端只读提示要同时存在
- `viewer` 和 `admin` 的真实差异如何体现在接口与页面上
- 如何用 demo 动作做教学验证

## 五、关键设计决策

### 1. 为什么坚持唯一业务后端

- `Next.js` 只做页面、壳层、路由承接
- `NestJS` 统一承载业务 API、权限、文件、导出、AI
- 避免双份 DTO、双份鉴权、双份错误处理

### 2. 为什么先不接数据库

- 当前重点是教学节奏与闭环验证
- 先固定角色语义和接口边界，再进入持久化更清晰

### 3. 为什么 viewer 不能触发真实 AI

- 成本控制
- 教学边界清晰
- 为后续缓存报告模式留口

## 六、关键文件讲解

- `apps/server/src/modules/auth/domain/auth-role-policy.ts`
- `apps/server/src/modules/auth/auth.service.ts`
- `apps/server/src/modules/auth/guards/jwt-auth.guard.ts`
- `apps/server/src/modules/auth/guards/role-capabilities.guard.ts`
- `apps/admin/components/admin-login-shell.tsx`
- `apps/admin/components/admin-dashboard-shell.tsx`
- `apps/admin/components/role-action-panel.tsx`

## 七、关键测试如何设计

- 角色策略测试：固定能力边界
- 登录服务单测：固定 demo 账号登录行为
- 认证 E2E：固定 `/auth/login` 与 `/auth/me`
- viewer 权限 E2E：固定只读限制
- 前端组件测试：固定登录表单与只读体验

## 八、踩坑与取舍

- `NestJS` 装饰器元数据下的 `import type` 问题
- 本地真实浏览器联调时的 CORS 问题
- `viewer` 语义如果只写在文档里，后续一定会漂移
- 推送 GitHub 时 `https`/`ssh` 的切换问题

## 九、与后续里程碑的衔接

- `M3`：在已有鉴权和后台壳上接双语内容模型与发布态
- `M4`：在已有角色边界上接 AI 工具链
- `M5`：在已有统一后端上接导出链路
- `M6`：把当前链路纳入测试、CI/CD、部署

## 十、文章拆分建议

### 文章 1：为什么教程型项目要先做最小登录闭环

- 重点：节奏、边界、唯一后端、角色模型

### 文章 2：如何用 NestJS 跑通最小 JWT 登录

- 重点：demo 账号、token、受保护接口、测试

### 文章 3：如何给 Next.js 后台搭一个最小登录壳

- 重点：前端壳层、登录页、受保护页、联调

### 文章 4：viewer 只读守卫应该怎么设计

- 重点：后端 guard、前端体验、成本控制、后续扩展

## 十一、后续补写素材来源

- `docs/30-开发日志/M2-issue-05-apps-server-最小-NestJS-脚手架.md`
- `docs/30-开发日志/M2-issue-06-鉴权领域与角色模型.md`
- `docs/30-开发日志/M2-issue-07-JWT-登录最小闭环.md`
- `docs/30-开发日志/M2-issue-08-apps-admin-最小登录壳.md`
- `docs/30-开发日志/M2-issue-09-viewer-只读守卫与体验.md`

## 十二、写作完成标准

- 能让读者理解 M2 为什么这样拆
- 能让读者按 Issue 维度复现 M2
- 能解释当前设计边界与后续扩展口
- 能与 M3 / M4 无缝衔接，不需要大改结构
