Files
ClassHelper/AGENTS.md
T
LoveChengke 66be3a63b1 feat(authz): 重写权限模板分配与班级授权边界
拆分能力、分配范围和业务关系,固定管理员能力并收紧组织级写入口。
补齐内容、课表、设备会话和实时通道授权,兼容旧库分配及历史快照。
重写权限分配预览,按实际可操作范围展示维护入口,合并学生入口并独立学年升级页。
增加授权攻击矩阵及静态门禁,更新隔离回归与开发契约。

验证:授权矩阵 23 段通过,Node 24 下 Web 63/63,类型检查、lint 与文档严格构建通过。
2026-10-31 09:40:23 +08:00

132 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md — ClassHelper(Class Helper)
本文件供本仓库的 AI 编码代理使用。先读这里,再改代码。当前工作目录为 `F:\ClassHelper`。
现行规则按工作区源码维护;产品说明见 `docs/app/`,开发契约见 `docs/dev/`,部署见 `docs/management/`。
查证路径见 `docs/reference.md`。文档与代码冲突时,阅读实现及其校验规则后同步修正文档,不沿用历史报告中的结论。
## 1. 项目与目录
pnpm monorepo,根 `package.json` 是版本单一来源。文档、注释、界面文案及提交描述使用中文。
远端为 `LoveChengke/ClassHelper`,默认分支 `master`。
| 目录 | 用途 |
| -------------------------- | --------------------------------------------------------- |
| `packages/shared/src/` | 三端共享类型、权限、常量、动效、岛方案与课件契约 |
| `packages/server/` | Express、Prisma、Socket.IO;API 前缀 `/api` |
| `packages/web-admin/` | Vue Web 管理端,PWA |
| `packages/desktop-client/` | Electron 主进程、preload、主窗口与独立灵动岛渲染进程 |
| `scripts/` | 版本、构建、验证、打包、图标与 Pages 脚本 |
| `deploy/` | Windows/Linux/Docker 部署与运维模板 |
| `docs/` | docfx 文档;`images/` 为展示图,`screenshots/` 为回归截图 |
| `website/` | 纯静态官网与下载页 |
| `releases/` | 按组件和版本存放本地交付物,gitignored |
不要在文档中手抄模块、表、权限键、测试用例的总数;分别查注册表、schema、共享目录与本次验证输出。
## 2. 服务端与数据边界
- 模块由 `packages/server/src/modules/registry.ts` 注册;新增或下线功能改注册表,不另改 `app.ts` 挂载。
- 路由用 `middleware/validate.ts` 与 zod;响应复用 `lib/http.ts`,错误交给统一中间件。
- 学生是 `Student` 名单记录,没有账号、角色或密码。教师/管理员存 `User`;班级登录读取 `Class.code/passwordHash`,会话角色 `CLASS_DEVICE`,主体 id 为班级 id。
- 任课关系只在 `Course(classId, name, teacherId)`。班主任不自动获得别的科目的作业、成绩写权限,统一走 `lib/authz/assert.ts` 的 `assertContentWrite`。班级端可录作业,不可写成绩;员工还须对应功能权限。
- 功能、范围、关系统一由 `lib/authz/` 判定,所有服务显式传权限键。ADMIN 固定全部能力;TEACHER 永久忽略管理员专用键;CLASS_DEVICE 为空集,接口明确允许并校验本班。权限管理仅 ADMIN。
- 岗位模板只管能力与建议范围,生效范围存 `UserPermissionGroup.scope/scopeValue`,使用 TEACHING/HEAD/GRADE/DIVISION/ALL。无显式分配的教师使用默认模板与固定 TEACHING;空或未知年级拒绝。按键独立合并范围,无键查询为空集;班级账号/学期设置永远要求本班班主任,科目写检查原/目标科目。具体断言和迁移见 `docs/dev/permissions.md`。
- 只有一份 `prisma/schema.prisma`,切库改 provider;保持 SQLite/MySQL 通用,不加 Prisma enum 或 `@db.*`。模型变动同步迁移、`lib/snapshot.ts` 的 `SNAPSHOT_TABLES` 与旧库兼容逻辑。
- `deleteTeacher` 必须保护班主任、课程任课、发布的作业/通知和所属课件,避免级联删除业务内容。
- 作业和通知按本地 `assignDate` 归类,使用 `dayKeyLocal/isDayKey/shiftDayKey`,不用 UTC 日期切片。
- 批量通知/作业逐班返回结果;跨班作业按科目名匹配既有课程,找不到则该班失败,不自动把发布者设为任课老师。
- 两个登录接口共用登录限流。附件链接校验 scheme;表格文件上限 8 MB、JSON 请求体 12 MB,超限映射 413。
- AI 助手只解析待确认动作,前端确认后调既有发布接口;参数重新校验,Key 加密存储且不回传。自动化用 mock,不访问外网。
## 3. 课表、周次、成绩与学年
- 课表真值是 `ClassPlan/ClassPlanEntry/TimeLayoutItem`;旧 `Schedule` 与 `TimeLayout.items` 保留迁移审计用途,不双写或回读复活旧业务。
- `/api/schedules/*` 是新模型兼容门面。启用解析统一走 `lib/class-plan.ts`,在线客户端不得另写启用优先级。
- 时间点有上课、课间、分割线、行动四种;课程显式引用时间点外键。排序不能靠数组下标代替关联。
- 支持 1–9 周轮换、群组、预定及临时层;完整档案导入走 `profile-import.service.ts`,不经过单双周有损格式。
- 全校时间表写入仅管理员;班级时间表按存储 classId 校验 `schedule:write` 与班主任关系,引用班级也校验。日课表/名单在 TEACHING/HEAD 范围要求班主任,显式年级/部/全校分配可在范围内维护。离线整套课表导入可建立班级自有作息,不把 JSON 的 TeacherName 当授权。
- 周次统一 `loadTermContext/resolveCurrentWeek`:班级逐周区间优先于全校区间,缺省再线性推算。开学日会参考班级设置、第 1 周区间、全校设置与环境兜底,详见 `lib/term.ts`。
- 全校周数上限存 `term.maxWeeks`,默认 30、范围 1–60;服务端 `getMaxTermWeeks()`,shared 做归一化与离线兜底。班级周数不超全校上限。
- 关闭个人成绩查询后,班级端仍可看服务端集体聚合;个人明细、原始全班成绩和排名拒绝读取。稀疏样本及补集抑制,不下发原始成绩后在客户端聚合。
- 总分开关属于 `Exam`;排名同学生同科取最高分,并列排名为 1、2、2、4。客户端只展示,不能修改成绩查询或考试配置。
- 年度升级由 `term.promotionAt` 配置,`PromotionRun.year` 保证幂等,升级前保存快照。运行期到点自动执行,启动漏跑先预览补跑;开发机启动不得擅自升级业务数据。
- 高三归档,其余升一级;新班仅建骨架,不复制班主任/任课关系。转出过滤复用 `lib/students.ts`,学号不复用,归档页保留历史与撤回转出。
## 4. 客户端、灵动岛与课件
- preload 仅暴露 contextBridge 白名单,不暴露 ipcRenderer;跨桥接传纯数据,不传 Vue Proxy。契约写在 `src/types/desktop.d.ts`。
- 保留 CSP、导航同源校验与弹窗限制。安装包不能含凭据,保留 `check-bundle-secrets` 构建门禁。
- 离线缓存按服务端与班级隔离,缓存故障不应阻断在线读取。退出、切服务器时清理会话状态,设备 `deviceKey` 保持不变,渲染层不能改写它。
- 设备维护只走 `/api/clients/*`,管理页 `ClientsView.vue`;心跳、进度、回执仅接受本班 CLASS_DEVICE,deviceKey 不可跨班迁移。心跳约 30 秒,90 秒窗口判在线;未登录不报,401/403 退避,切配置重置计时并隔离迟到响应。
- 远控须 `remote:control`,只允许 shutdown/restart/logoff/lock,客户端立即执行、持久去重并回执。冒烟始终假执行,不得真关机/重启/注销/锁屏。
- 安装包登记/删除为管理员 `client:update`;班级推送用 `client:update-push`;服务端缓存包并登记 SHA256,教室机从本服务下载;无哈希拒收,按立即/放学后/空闲策略执行,关闭自动更新不得强装。冒烟不运行安装器。
- 灵动岛方案保存在本机 `config.json.islandLayout`,默认 `layout=fixed`;`custom` 当前即常驻模式,旧 `residentEnabled` 是兼容字段。新尺寸上报仅在 custom 模式执行。
- `LayoutIslandApp.vue` 选择经典 `IslandApp.vue` 或 `CustomIslandRuntime.vue`,共用一个原生岛窗口;课件传输状态优先显示 `CoursewareTransfer.vue`。
- 经典模式:普通通知/作业上课暂存;普通叫人保留可点击胶囊;紧急消息立即展开。自定义常驻模式:消息先提示铃铛数量,用户主动展开;上课也可主动查看。不要把两个模式规则混写。
- 自定义方案的常态 `rows` 与无消息展开 `expandedRows` 分开编辑。课程、时钟、容器等使用 shared 组件契约;测量自然内容并按工作区约束适配。
- 保留经典岛连续圆角、投影常驻、触摸输入、失焦宽限与固定窗口几何护栏。不要调用 `setBackgroundMaterial()` 破坏逐像素透明。左右边距仅左/右停靠生效。
- 消息按 id 去重,通知/叫人双播不得重复;列表布局复用 shared 度量。崩溃恢复保持限流,冒烟不得自重启。
- 课件权限和任课范围独立校验:拥有文件、文件可见范围与本人授课班级共同约束推送,岗位范围不代替任课授权。
- 课件最大 512 MB,流式收发、临时文件、SHA256 校验;客户端不自动运行文件,每设备独立回执。JSON 快照只含元数据,完整备份另带文件目录。
## 5. 实时、界面与资源
- 事件名与房间名取 shared 常量。班级房间为 `class:{id}:{channel}`,教师按每域读键及范围订阅,班级端仅本班全部通道;握手回查数据库身份。业务用 `emitToClass/emitToSession`,由总线选择事件域。
- 会话房间为 `session:{id}`;教师/管理员 id 为账号 id,班级端为班级 id。`students` 是班级端广播房间,不是个人学生账号房间。
- 新实时事件同步服务端、Web 订阅、客户端订阅。成绩实时载荷不可泄漏个人成绩。
- Web 菜单分组在 `config/navigation.ts`,标题/图标/权限取路由;守卫与服务端都检查权限,前端隐藏不能代替鉴权。
- 侧栏折叠用 CSS 保持 DOM,关怀模式放大字号/控件,不改变几何令牌。使用语义色,动效统一 shared 令牌;图标新增后检查注册表。
- 图标源是 `build/classhelper.png` 与设计导出的 `.ico`,`pnpm icons` 派生其余资源。ICO 原样透传,客户端兜底 `build/icon.*` 同步保留。
- Web 品牌图用 `/logo.png`,客户端用 `BRAND_LOGO_URL`,避免 file:// 绝对路径问题。
- 官网和文档站共用一个 Pages 站点,`scripts/build-pages.mjs` 拼装根站与 `/docs/`;文档不写指向 docs 树外的相对链接,源码用 GitHub 绝对链接。
- 展示图引用 `docs/images/`,回归图放 `docs/screenshots/`。官网 `.reveal-grad` 不拆逐字节点,动效改 token 表。
- ClassIsland 联动插件、设备令牌、提醒渠道与镜像接口已退役;保留离线 JSON 导入和设计参考,不恢复在线联动依赖。
## 6. 本机命令与验证
脚本以根/各包 `package.json` 为准;端口:后端 4000,Web dev 5173,客户端 dev 5174,官网 5180,文档 5181。
先构建 shared 再启动下游。新环境按需执行 install → db:generate → server db:deploy → build:shared;`db:seed/db:reset` 会清业务表,只用于明确选择的演示/隔离库。
本机 Node 路径为 `D:\Node.js\node.exe`。受限终端的 pnpm 可能解析到运行时兜底版本,先看 `Get-Command pnpm` 与 `pnpm --version`。
仓库锁定 pnpm 11.8.0,可用 `C:\Users\hck16\AppData\Local\node\corepack\v1\pnpm\11.8.0\bin\pnpm.cjs`。
经 DSH 转发壳时可设置:
```powershell
$env:PATH = 'C:\Users\hck16\AppData\Local\deepseek-harness\bin;' + $env:PATH
$env:DSH_NODE = 'D:\Node.js\node.exe'
$env:DSH_PNPM_BIN = 'C:\Users\hck16\AppData\Local\node\corepack\v1\pnpm\11.8.0\bin\pnpm.cjs'
Remove-Item Env:DSH_PNPM -ErrorAction SilentlyContinue
pnpm --version
```
受限 electron-builder 调 pnpm list 曾报 `ERR_SQLITE_ERROR`,这是进程访问限制,不据此认定依赖缺失。
Prisma 使用 driver adapter;本机优先应用已有迁移,不用 `migrate dev` 排查 Windows 初始化问题。
本地 HTTP 探测绕过代理;运行中数据库及 WAL/SHM 不按临时文件清理。
| 命令 | 范围 |
| ----------------------------------------------------------- | ------------------------------------------------------ |
| `pnpm lint` / `pnpm typecheck` / `pnpm check:icons` | 代码静态门禁;按改动范围执行 |
| `pnpm docs:check` | 文档严格构建,警告即失败 |
| `pnpm verify:e2e` | 自动创建临时 SQLite 和账号,无需先开开发服务,禁止外网 |
| `pnpm verify:web:isolated` | 构建 Web 后运行隔离服务和隐藏 UI 回归 |
| `pnpm verify:courseware` / `pnpm verify:v14` | 课件/课表等隔离专项 |
| `pnpm verify:desktop` / `pnpm verify:packaged --exe <路径>` | 默认后台快速检查,不创建可见岛或托盘 |
| `pnpm verify:desktop:online` | 显式联网,使用临时教师和班级 |
| `pnpm verify:desktop:visual` / packaged 的 `--visual` | 显式视觉模式,动画、透明度、截图;会使用桌面 |
禁止为验收回退到真实班级、重置其密码或发送测试通知。验收数量只记录本次实际输出。
仅文档修改做格式、链接、构建检查,不为此反复占用桌面或重打安装包。
Prettier 用 LF,只格式化本次改动;不要为旧基线批量格式化源码。
改 Linux 交付脚本还要 bash 语法检查和 Linux 真机/CI 验证;改打包逻辑需打包后副本复验。
## 7. 发布与工作区清理
- 版本只由 `scripts/version.mjs` 修改;日常维护不涨版,指定固定版本重构建时保持该版本。发布流程见 `docs/dev/release.md`。
- 本地 `pnpm dist:all` 产出 Windows 服务端和客户端;Linux 正式包由 `release-linux-server.yml` 在 Linux runner 构建,非 Linux 交叉构建仅供验证。
- 本地文件名与 Release 的 ASCII 上传名不同,校验清单应明确映射;保留当前版本清单、更新日志及最新包。
- `releases/` 只放交付物及少量构建信息,不留 win-unpacked、服务端 staging、解包副本;staging 在 `.cache/server-staging/`,成功后脚本删除。
- 2026-10-18 按用户要求清除 1.4.0 旧重构建归档,只保留 `client/1.4.0`、`server/1.4.0` 与当前清单/说明。以后同号重构建可临时留回滚副本,最新包验证完成且用户要求清理时再删除。
- 递归删除/移动前核实绝对路径在指定工作区,禁止误删源代码、真实数据库、配置、凭据、工具缓存或其他版本交付物。
- 不清理 `node_modules`、`.pnpm-store`、`.cache/{nuget,npm-cache,dotnet-home,mingit}`、`packages/*/dist`、生成的 Prisma Client,除非任务明确要求。
- 保留已有未提交工作;提交前查看 diff,中文 Conventional Commits 描述。只有用户要求发布/同步时才执行远端发布链。