# 📅 2026-05-12 日报 · lijian

## 概览

收尾 meeting-attendance 系列层一个角色权限漂移 bug（PR #345），全天主要工作量是把 develop/staging/production 升级合并策略切到 **fast-forward-only**——首日就被 FF 几何前提坑了，写了 5 篇 learnings + 3 个 ERR 沉淀经验。

---

## 一、产出

### 🟡 P1 · fix(meeting-attendance) 系列改角色 403 — 权限漂移修复

**根因**：系列层"修改参会人角色"接口校验时**硬编码** creator 才能改，但 PRD 写的是 meeting-admin 角色也能改；前端调用方在多个入口拼了 4 处不一致的鉴权判断，部分代码路径甚至直接拿 `role.name` 做字符串比较（角色改名字就漂移）。

**方案**：
- 鉴权统一收敛到 [`utils/meeting-roles.ts`](backend/src/modules/meeting-attendance/utils/meeting-roles.ts)，按权限点而非角色名判断
- [`services/series.service.ts`](backend/src/modules/meeting-attendance/services/series.service.ts) 4 处 `if (creator)` 替换为 `assertCanManageSeries(user, series)`
- 配套 i18n 加 `修改参会人角色` 的错误文案
- 配套 probe 脚本 [`verify-update-attendee-role.ts`](backend/scripts/probes/verify-update-attendee-role.ts) 一次性验证 3 种角色 × 3 种入口 = 9 种组合

**影响范围**：8 文件 / +208 / -9；修复非 creator 管理员调"改角色"接口的 403；触发 PR #345 完成 merge。

commit: [`573f9abe`](https://43.130.59.228/FFAIWorkspace/workspace/commit/573f9abe)

---

## 二、今日合入的 PR

| PR | 标题 | 状态 | 备注 |
|----|------|------|------|
| #345 | feat(meeting-attendance): 系列层参会人排除清单 — 修复删了又被 Outlook 同步回来 | ✅ merged 13:19 | 包含上面这条 role drift 修复 |
| #344 | fix(meeting-attendance): 系列参会人改角色 403 — 4 处硬编码鉴权统一权限点 | ✅ merged 13:05 | hotfix 路径，回流 develop |
| #348 | chore: sync-back staging → develop（解锁 PR #346）| ✅ merged 13:39 | FF-only 政策首日的兜底操作（见 §五） |

---

## 三、Git 活动

```
573f9abe | 11:01 | fix(meeting-attendance): 修复系列改角色权限漂移导致非 creator 管理员 403
+ 8 files changed, 208 insertions(+), 9 deletions(-)
```

热点目录：`backend/src/modules/meeting-attendance/` + `frontend/src/app/(modules)/meetingattendance/` + `frontend/src/locales/meetingAttendance/`

---

## 五、事故 & 教训

今日有 3 个 ERR 写入：

### ⚠️ ERR-20260512-001 (slot-cwd): slot 工作目录混乱 + pre-commit hook 链式拦截

- **现象**：在 slot-1 worktree 跑 commit，pre-commit hook 一连串 fail，根因是 hook 脚本里写死了 `cd $repo_root` 而 worktree root 不是真 repo root
- **缓解**：hook 改用 `git rev-parse --show-toplevel` 自动定位
- **教训**：写跨 worktree 的脚本一律不能假设 `pwd == repo_root`
- 详见 [.learnings/ERRORS/ERR-20260512-001-slot-cwd-and-precommit-hooks.md](.learnings/ERRORS/ERR-20260512-001-slot-cwd-and-precommit-hooks.md)

### ⚠️ ERR-20260512-001 (git-config): `git config` key 含下划线被静默丢

- **现象**：`git config --global fetch.prune true` 正常，但 `git config --global fetch.prune_when_needed` 写不进去
- **根因**：Git config 不接受 key 含下划线，只接受小写 + 点 + 短划线；不会报错只是静默忽略
- **教训**：写 git config key 时若不在 git 文档里出现的拼写，先怀疑命名规则
- 详见 [.learnings/ERRORS/ERR-20260512-001-git-config-key-underscore.md](.learnings/ERRORS/ERR-20260512-001-git-config-key-underscore.md)

### ⚠️ ERR-20260512-002: force-push 共享分支后部署镜像 git pull 报 divergent branches

- **现象**：staging/production 走 force-push 后，部署机上的 `git pull` 报 `Need to specify how to reconcile divergent branches`
- **根因**：FF-only 启用前后的分支历史不连续，部署镜像本地 ref 还停留在 old HEAD
- **缓解**：部署脚本加 `git fetch + git reset --hard origin/<branch>`，明确"远端是 source of truth"
- **教训**：环境镜像（部署机 / CI 缓存）的 git ref 在 force-push 上游后必须显式 reset，不能 pull
- 详见 [.learnings/ERRORS/ERR-20260512-002-force-push-divergence-on-deploy-mirrors.md](.learnings/ERRORS/ERR-20260512-002-force-push-divergence-on-deploy-mirrors.md)

---

## 六、新增 learnings

| 文件 | 类型 | 适用场景 |
|------|------|---------|
| [ff-only-rollout-reset](.learnings/2026-05-12-ff-only-rollout-reset.md) | project | FF-only 启用首日 staging/production 强制对齐到共同祖先的实操记录 |
| [gitea-ff-only-is-repo-level](.learnings/2026-05-12-gitea-ff-only-is-repo-level.md) | reference | Gitea "Fast-forward only" 是仓库级开关而非 PR 级，启用前提是 base HEAD 是 head 祖先 |
| [promotion-pr-no-update-button](.learnings/2026-05-12-promotion-pr-no-update-button.md) | reference | develop→staging 类 promotion PR 卡 outdated 时 Gitea 不给 "Update branch" 按钮，必须开 sync-back PR |
| [check-existing-docs-before-drafting](.learnings/2026-05-12-check-existing-docs-before-drafting.md) | feedback | 起草新模块前先 `ls + Read` 已有文档，避免重复造 |
| [showcase-static-page-pattern](.learnings/2026-05-12-showcase-static-page-pattern.md) | reference | 静态页（无数据库）模块的轻量路由 + 资源组织模式 |

---

## 七、未提交改动

```
M .claude/settings.json
```

仅 Claude Code session 累积的 allowlist，与本日功能无关；不必入 PR。

---

## 八、待决策 / 明日计划

无明确悬挂（今日工作完整收尾 + 教训沉淀）。次日（5-13）专注新模块 internal-app-platform 的契约设计。
