27 KiB
企业级架构规范化实施计划
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 消除所有架构违规 + 补齐大仓工程基建 + 升级 TypeScript/CI 配置,使项目达到企业级规范标准
Architecture: 严格分阶段(P0→P1→P2),每阶段独立 git 提交,失败可回滚。P0 修复 32 个无权限 Action + 5 个超长文件;P1 补齐文档 + 提交钩子 + tech-debt;P2 开启 noUncheckedIndexedAccess + CI 加 unit test + 可观测性补充
Tech Stack: TypeScript 5 / Next.js 16 / Drizzle / ESLint 9 / husky / commitlint / vitest / @next/bundle-analyzer
Spec: docs/superpowers/specs/2026-07-07-enterprise-architecture-normalization-design.md
阶段 1: P0 安全合规
Task 1: arch:scan 添加 @public 豁免标记机制
Files:
-
Modify:
scripts/arch-scan/schema.ts(symbols 表加 is_public 列) -
Modify:
scripts/arch-scan/scanner.ts(识别 JSDoc @public) -
Modify:
scripts/arch-scan/query.ts(violations 过滤 is_public) -
Test:
scripts/arch-scan/scanner.test.ts -
Step 1: 给 symbols 表加 is_public 列
修改 scripts/arch-scan/schema.ts,在 symbols 表定义中加:
is_public: integer("is_public", { mode: "boolean" }).notNull().default(false),
删除 scripts/arch-scan/arch.db 让 schema 重建。
- Step 2: scanner.ts 识别 JSDoc @public 标记
修改 scripts/arch-scan/scanner.ts 的符号扫描逻辑。对每个 async function 导出,检查其上方的 JSDoc 注释是否包含 @public 标记。若是,设 is_public: true。
参考实现(ts-morph API):
const jsDocs = symbolNode.getJsDocs();
const isPublic = jsDocs.some(doc => doc.getTags().some(tag => tag.getTagName() === "public"));
- Step 3: query.ts violations 过滤 is_public
修改 scripts/arch-scan/query.ts 的 printViolations 函数,Server Actions without requirePermission 查询加 AND is_public = 0。
- Step 4: 运行测试验证
npm run test:arch-scan
Expected: 所有测试 PASS(25/25)。若 schema 变更导致测试失败,更新测试 fixture。
- Step 5: 重新扫描验证
npm run arch:scan
npm run arch:query -- violations
Expected: violations 输出仍是 32 个(因为还没给 Action 加 @public)。
- Step 6: Commit
git add scripts/arch-scan/
git commit -m "feat(arch-scan): add @public tag exemption mechanism for server actions"
Task 2: 给 12 个豁免 Action 加 @public 标记
Files:
-
Modify:
src/modules/auth/actions.ts -
Modify:
src/modules/invitation-codes/actions.ts -
Modify:
src/modules/onboarding/actions.ts -
Modify:
src/modules/settings/actions-security.ts -
Modify:
src/modules/rbac/actions.ts -
Modify:
src/shared/lib/audit-logger.ts -
Modify:
src/shared/lib/change-logger.ts -
Modify:
src/shared/lib/login-logger.ts -
Step 1: auth/actions.ts 加 @public
对 registerAction、checkEmailAvailabilityAction、preflightTwoFactorAction 三个函数,在 JSDoc 中加 @public 标记。示例:
/**
* 注册新用户(登录前,无需权限校验)
* @public
*/
export async function registerAction(...): Promise<ActionState<...>> { ... }
- Step 2: invitation-codes/actions.ts 加 @public
对 validateInvitationCodeAction 加 @public(注册时校验邀请码)。
- Step 3: onboarding/actions.ts 加 @public
对 getOnboardingStatusAction、completeOnboardingAction 加 @public(引导阶段,已登录但未完成引导)。
- Step 4: settings/actions-security.ts 加 @public
对 preflightTwoFactorAction、verifyTwoFactorForLogin 加 @public(登录中 2FA 流程)。
- Step 5: rbac/actions.ts 加 @public
对 isAdminRole 加 @public(内部辅助函数,非对外 Action)。
- Step 6: shared/lib 三个 logger 加 @public
对 audit-logger.ts 的 logAudit、change-logger.ts 的 logDataChange、login-logger.ts 的 logLoginEvent 加 @public(基础设施,被 Action 内部调用,非对外 Action)。
- Step 7: 重新扫描验证豁免生效
npm run arch:scan
npm run arch:query -- violations
Expected: Server Actions without requirePermission 从 32 降至 20(豁免 12 个)。
- Step 8: 验证 tsc + lint
npx tsc --noEmit
npm run lint
Expected: 0 errors。
- Step 9: Commit
git add src/modules/ src/shared/lib/
git commit -m "fix(permissions): mark 12 public/infrastructure actions with @public tag"
Task 3: 修复 ai 模块 6 个 Action 权限
Files:
-
Modify:
src/modules/ai/actions.ts -
Possibly modify:
src/shared/types/permissions.ts(若需新增权限点) -
Step 1: 读取 ai/actions.ts 理解 6 个 Action 签名
# 用 Read 工具读取 src/modules/ai/actions.ts
确认每个 Action 的参数和现有权限校验方式。
- Step 2: 确认所需权限点存在
检查 src/shared/types/permissions.ts 是否有:QUESTION_READ、HOMEWORK_GRADE、LESSON_PLAN_CREATE、QUESTION_CREATE、DIAGNOSTIC_READ、ERROR_BOOK_READ。若缺失,新增并注册到 5 处(permissions.ts → ROLE_PERMISSIONS_SEED → permission-bitmap.ts → permission-catalog.ts → i18n/rbac.json)。
- Step 3: 给 6 个 Action 加 requirePermission
import { requirePermission } from "@/shared/lib/auth-guard";
import { Permissions } from "@/shared/types/permissions";
export async function suggestSimilarQuestionsAction(...) {
const ctx = await requirePermission(Permissions.QUESTION_READ);
// ... 原 logic 使用 ctx.userId
}
6 个映射:suggestSimilarQuestionsAction→QUESTION_READ、suggestGradingAction→HOMEWORK_GRADE、generateLessonContentAction→LESSON_PLAN_CREATE、generateQuestionVariantAction→QUESTION_CREATE、analyzeWeaknessAction→DIAGNOSTIC_READ、explainErrorAction→ERROR_BOOK_READ。
- Step 4: 验证 tsc + lint
npx tsc --noEmit
npm run lint
Expected: 0 errors。
- Step 5: Commit
git add src/modules/ai/ src/shared/types/
git commit -m "fix(ai): add requirePermission to 6 ai server actions"
Task 4: 修复 parent 模块 6 个 Action 权限
Files:
-
Modify:
src/modules/parent/actions.ts -
Possibly modify:
src/shared/types/permissions.ts -
Step 1: 读取 parent/actions.ts
确认 6 个 Action 的现有实现。parent 模块的特殊性:需要同时校验 parentId + studentId 防跨家庭信息泄露。
- Step 2: 确认 PARENT_DASHBOARD_VIEW 权限点存在
若不存在,新增 PARENT_DASHBOARD_VIEW 到 permissions.ts + 5 处注册。
- Step 3: 给 6 个 Action 加 requirePermission + parentId/studentId 校验
export async function getChildrenAction() {
const ctx = await requirePermission(Permissions.PARENT_DASHBOARD_VIEW);
// ctx.userId 即 parentId
return getChildren(ctx.userId);
}
export async function getChildDashboardDataAction(studentId: string) {
const ctx = await requirePermission(Permissions.PARENT_DASHBOARD_VIEW);
await verifyParentChildRelationAction(ctx.userId, studentId); // 防越权
return getChildDashboardData(studentId);
}
6 个:getChildrenAction、getChildBasicInfoAction、getChildDashboardDataAction、getParentDashboardDataAction、getChildNameListAction、verifyParentChildRelationAction。
- Step 4: 验证 tsc + lint + arch:scan
npx tsc --noEmit
npm run lint
npm run arch:scan
npm run arch:query -- violations
Expected: tsc/lint 0 errors;violations 中 parent 模块的 6 个消失。
- Step 5: Commit
git add src/modules/parent/ src/shared/types/
git commit -m "fix(parent): add requirePermission + parent-child relation check to 6 actions"
Task 5: 修复 settings 模块 5 个 Action 权限
Files:
-
Modify:
src/modules/settings/actions.ts(4 个) -
Modify:
src/modules/settings/actions-service.ts(1 个: updateProfileAction) -
Step 1: 确认权限点
确认 SYSTEM_SETTINGS_READ、SYSTEM_SETTINGS_MANAGE、USER_PROFILE_UPDATE 存在。USER_PROFILE_UPDATE 若不存在,用 getAuthContext() 替代(自身资料更新,任何登录用户均可)。
- Step 2: 给 5 个 Action 加权限校验
actions.ts 中 4 个:getAiProviderSummaries→SYSTEM_SETTINGS_READ、upsertAiProviderAction→SYSTEM_SETTINGS_MANAGE、testAiProviderAction→SYSTEM_SETTINGS_MANAGE、deleteAiProviderAction→SYSTEM_SETTINGS_MANAGE、canConfigurePublicAiProvider→SYSTEM_SETTINGS_READ。
actions-service.ts 中 updateProfileAction:用 getAuthContext()(任何登录用户可改自己资料)。
- Step 3: 验证
npx tsc --noEmit && npm run lint
- Step 4: Commit
git add src/modules/settings/
git commit -m "fix(settings): add requirePermission to 5 settings server actions"
Task 6: 修复剩余 3 个 Action 权限
Files:
-
Modify:
src/modules/leave-requests/actions.ts(listMyLeaveRequests) -
Modify:
src/modules/lesson-preparation/actions.ts(duplicateLessonPlanFormAction) -
Step 1: leave-requests listMyLeaveRequests
用 getAuthContext()(查自己的请假记录,任何登录用户可查自己)。
- Step 2: lesson-preparation duplicateLessonPlanFormAction
加 requirePermission(Permissions.LESSON_PLAN_CREATE)。
- Step 3: 验证全部 P0 权限修复完成
npm run arch:scan
npm run arch:query -- violations
Expected: Server Actions without requirePermission = 0。
- Step 4: tsc + lint
npx tsc --noEmit && npm run lint
- Step 5: Commit P0 权限修复完成
git add src/modules/
git commit -m "fix(permissions): complete requirePermission for remaining 3 actions"
Task 7: 拆分 shared/db/schema.ts (2245 行 → 按域拆分)
Files:
-
Create:
src/shared/db/schema/users.ts -
Create:
src/shared/db/schema/academic.ts -
Create:
src/shared/db/schema/exams.ts -
Create:
src/shared/db/schema/grades.ts -
Create:
src/shared/db/schema/attendance.ts -
Create:
src/shared/db/schema/messaging.ts -
Create:
src/shared/db/schema/notifications.ts -
Create:
src/shared/db/schema/audit.ts -
Create:
src/shared/db/schema/rbac.ts -
Create:
src/shared/db/schema/files.ts -
Create:
src/shared/db/schema/scheduling.ts -
Create:
src/shared/db/schema/misc.ts -
Modify:
src/shared/db/schema.ts(改为 barrel re-export) -
Step 1: 读取 schema.ts 按表分组
读取 src/shared/db/schema.ts,按域将 54 张表分组到上述 12 个文件。
- Step 2: 创建 schema/ 目录,按域拆分
每个 schema/<domain>.ts 文件:
import { mysqlTable, varchar, ... } from "drizzle-orm/mysql-core";
// 该域的表定义
export const users = mysqlTable("users", { ... });
- Step 3: schema.ts 改为 barrel
// src/shared/db/schema.ts
export * from "./schema/users";
export * from "./schema/academic";
export * from "./schema/exams";
// ... 12 个 re-export
- Step 4: 验证所有 import 仍正常
npx tsc --noEmit
Expected: 0 errors(因为 barrel re-export 保持 import 路径不变)。
- Step 5: 验证文件行数
Get-Content src/shared/db/schema.ts | Measure-Object -Line
# Expected: < 50 行(barrel)
Get-ChildItem src/shared/db/schema/*.ts | ForEach-Object { "$($_.Name): $((Get-Content $_.FullName | Measure-Object -Line).Lines)" }
# Expected: 每个文件 < 500 行
- Step 6: Commit
git add src/shared/db/
git commit -m "refactor(db): split schema.ts (2245 lines) into 12 domain files"
Task 8: 拆分 shared/lib/cache/invalidation-map.ts (1195 行)
Files:
-
Create:
src/shared/lib/cache/invalidation/<module>.ts(按模块拆分) -
Modify:
src/shared/lib/cache/invalidation-map.ts(改为 barrel + registerInvalidationMaps) -
Step 1: 读取 invalidation-map.ts 按模块分组
-
Step 2: 按模块拆分到 invalidation/ 目录
每个模块的 invalidation map 移到独立文件,导出该模块的 invalidation 配置对象。
- Step 3: invalidation-map.ts 改为 barrel + 聚合注册
import { examsInvalidation } from "./invalidation/exams";
// ...
export function registerInvalidationMaps() {
register(examsInvalidation);
// ...
}
- Step 4: 验证
npx tsc --noEmit && npm run lint
- Step 5: Commit
git add src/shared/lib/cache/
git commit -m "refactor(cache): split invalidation-map.ts (1195 lines) by module"
Task 9: 拆分 messaging/actions.ts (973 行)
Files:
-
Create:
src/modules/messaging/actions-conversations.ts -
Create:
src/modules/messaging/actions-messages.ts -
Create:
src/modules/messaging/actions-starred.ts -
Create:
src/modules/messaging/actions-read.ts -
Modify:
src/modules/messaging/actions.ts(改为 barrel) -
Step 1: 读取 actions.ts 按职责分组
-
Step 2: 按职责拆分到 4 个文件
每个文件顶部 "use server",按职责归类 Action。
- Step 3: actions.ts 改为 barrel
export * from "./actions-conversations";
export * from "./actions-messages";
export * from "./actions-starred";
export * from "./actions-read";
- Step 4: 验证
npx tsc --noEmit && npm run lint && npm run arch:scan
npm run arch:query -- violations
Expected: messaging/actions.ts 不再在超长文件列表。
- Step 5: Commit
git add src/modules/messaging/
git commit -m "refactor(messaging): split actions.ts (973 lines) by responsibility"
Task 10: 拆分 textbooks/data-access.ts (907 行)
Files:
-
Create:
src/modules/textbooks/data-access-chapters.ts -
Create:
src/modules/textbooks/data-access-knowledge-points.ts -
Modify:
src/modules/textbooks/data-access.ts(改为 barrel + 核心) -
Step 1: 拆分章节 CRUD 到 data-access-chapters.ts
-
Step 2: 拆分知识点 CRUD 到 data-access-knowledge-points.ts
-
Step 3: data-access.ts 保留核心 + barrel re-export
-
Step 4: 验证
npx tsc --noEmit && npm run lint && npm run arch:scan
npm run arch:query -- violations
Expected: textbooks/data-access.ts 不再在超长文件列表。
- Step 5: Commit
git add src/modules/textbooks/
git commit -m "refactor(textbooks): split data-access.ts (907 lines) by entity"
Task 11: 拆分 questions/data-access.ts (828 行)
Files:
-
Create:
src/modules/questions/data-access-search.ts -
Modify:
src/modules/questions/data-access.ts(保留核心 CRUD + barrel) -
Step 1: 拆分 FULLTEXT 检索到 data-access-search.ts
-
Step 2: data-access.ts 保留核心 CRUD + re-export
-
Step 3: 验证 P0 全部完成
npm run arch:scan
npm run arch:query -- violations
Expected: Long files = 0;Server Actions without requirePermission = 0。
npx tsc --noEmit && npm run lint
Expected: 0 errors。
- Step 4: 更新 known-issues.md 工作经验日志
在 docs/troubleshooting/known-issues.md 工作经验日志区追加 P0 完成记录。
- Step 5: Commit P0 阶段完成
git add src/modules/questions/ docs/troubleshooting/
git commit -m "refactor(questions): split data-access.ts and complete P0 security phase"
git push
阶段 2: P1 大仓工程基建
Task 12: 创建大仓文档
Files:
-
Create:
LICENSE -
Create:
CHANGELOG.md -
Create:
CONTRIBUTING.md -
Create:
SECURITY.md -
Create:
.env.example -
Step 1: 创建 LICENSE(专有协议)
Copyright (c) 2026 EazyGame. 保留所有权利。
未经版权所有者书面许可,不得以任何形式复制、修改、合并、发布、分发、再许可或销售本软件的任何部分。
- Step 2: 创建 CHANGELOG.md(Keep-a-changelog 格式)
# 更新日志
本项目遵循 [Keep a Changelog](https://keepachangelog.com/) 格式,版本号遵循 [Semantic Versioning](https://semver.org/)。
## [1.0.0] - 2026-07-07
### Added
- arch.db 架构元数据库 + 扫描器(ts-morph + SQLite)
- 35 个模块 README.md(含 mermaid 架构图与流程图)
- 004 架构设计文档 V3(14 章节 + 13 mermaid 图)
- known-issues.md 索引式速查手册
### Changed
- 004 从"影响地图"重构为"架构设计文档"(458→912 行)
- project_rules.md 引入 arch.db + AI 工作强制流程
- coding-standards.md 更新令牌分层 + cacheFn + 5 层状态模型
- Step 3: 创建 CONTRIBUTING.md
包含:分支策略(main 保护)、Conventional Commits 规范、提交前检查(lint+tsc+arch:scan)、模块 README 维护规则、代码审查清单。
- Step 4: 创建 SECURITY.md
包含:漏洞报告流程、安全联系人、响应 SLA、不公开披露策略。
- Step 5: 创建 .env.example
读取 src/env.mjs 提取所有环境变量键,加注释:
# 数据库
DATABASE_URL="mysql://user:pass@localhost:3306/next_edu"
# NextAuth
NEXTAUTH_SECRET="your-secret-here"
NEXTAUTH_URL="http://localhost:3000"
# AI Provider(可选)
OPENAI_API_KEY=""
ANTHROPIC_API_KEY=""
# Redis(可选)
REDIS_URL=""
# 文件存储
UPLOAD_DIR="./uploads"
# ... 其余从 env.mjs 提取
- Step 6: Commit
git add LICENSE CHANGELOG.md CONTRIBUTING.md SECURITY.md .env.example
git commit -m "docs: add enterprise baseline docs (LICENSE/CHANGELOG/CONTRIBUTING/SECURITY/env.example)"
Task 13: 安装 husky + lint-staged + commitlint
Files:
-
Modify:
package.json(dependencies + scripts) -
Create:
.husky/pre-commit -
Create:
.husky/commit-msg -
Create:
commitlint.config.js -
Create:
lint-staged.config.js -
Step 1: 安装依赖
npm install -D husky lint-staged @commitlint/cli @commitlint/config-conventional
- Step 2: 初始化 husky
npx husky init
这会创建 .husky/ 目录并生成 .husky/pre-commit 示例。
- Step 3: 配置 pre-commit 钩子
.husky/pre-commit:
npx lint-staged
- Step 4: 配置 commit-msg 钩子
.husky/commit-msg:
npx commitlint --edit "$1"
- Step 5: 创建 commitlint.config.js
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: {
"scope-enum": [2, "always", [
// 35 模块名
"exams", "homework", "questions", "textbooks", "grades",
"lesson-preparation", "classes", "school", "scheduling",
"attendance", "course-plans", "users", "messaging",
"notifications", "parent", "audit", "rbac", "auth",
"onboarding", "ai", "dashboard", "diagnostic",
"adaptive-practice", "error-book", "elective",
"proctoring", "leave-requests", "invitation-codes",
"files", "settings", "layout", "student", "search",
"announcements", "standards",
// 架构层
"arch-scan", "db", "cache", "ui", "deps", "config",
// 文档
"docs", "architecture", "troubleshooting",
]],
},
};
- Step 6: 创建 lint-staged.config.js
module.exports = {
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{js,mjs,cjs}": ["prettier --write"],
"*.md": ["prettier --write"],
"*.{json,yml,yaml}": ["prettier --write"],
};
- Step 7: package.json 加 prepare 脚本
"scripts": {
"prepare": "husky"
}
- Step 8: 验证钩子工作
# 测试 commitlint 拒绝非规范提交
git commit -m "bad commit message" --allow-empty
# Expected: FAIL (commitlint 拒绝)
# 测试规范提交
git commit -m "test(husky): verify commitlint works" --allow-empty
# Expected: PASS
- Step 9: Commit
git add .husky/ commitlint.config.js lint-staged.config.js package.json package-lock.json
git commit -m "chore(deps): add husky + lint-staged + commitlint for commit convention enforcement"
Task 14: 填充 tech-debt.md
Files:
-
Modify:
docs/architecture/roadmap/tech-debt.md -
Step 1: 整理待解决技术债
从 known-issues 工作经验日志 + 本次诊断补充,整理至少 6 条待解决技术债:
- scripts 目录混放治理(.sh/.ps1/.js/.mjs/.ts 统一)
- API 文档自动化(OpenAPI 生成)
- proctoring 模块的 exams 依赖未被 arch.db 捕获(scanner 改进)
- FULLTEXT 索引迁移工具化
- client-error 上报机制完善(Task 12-14)
- React Flow 移除后的历史包袱清理
- noUncheckedIndexedAccess 历史债务(本次 P2 解决)
- coverage 阈值渐进提升(本次设 60% 起步)
- Step 2: 写入 tech-debt.md
每条含:描述、影响、建议方案、优先级(P0/P1/P2)。
- Step 3: Commit P1 阶段完成
git add docs/architecture/roadmap/tech-debt.md
git commit -m "docs(roadmap): populate tech-debt.md with 8 pending items"
git push
阶段 3: P2 配置升级
Task 15: 开启 noUncheckedIndexedAccess + 全量修复
Files:
-
Modify:
tsconfig.json -
Modify: 多个源文件(修复类型错误)
-
Step 1: tsconfig.json 开启 noUncheckedIndexedAccess
"noUncheckedIndexedAccess": true,
- Step 2: 运行 tsc 收集所有错误
npx tsc --noEmit 2>&1 | Select-String "error TS"
记录所有错误位置。
- Step 3: 批量修复类型错误
按模块批量修复:
-
数组索引
arr[0]→arr[0]!(确认存在)或arr.at(0) ?? defaultValue(可能不存在) -
对象索引
obj[key]→ 显式判空if (key in obj) { ... } -
split/match结果 →?? []兜底 -
Record<string, T>访问 →T | undefined处理 -
Step 4: 验证 tsc 0 错误
npx tsc --noEmit
Expected: 0 errors。
- Step 5: 验证 lint + arch:scan
npm run lint && npm run arch:scan
- Step 6: Commit
git add tsconfig.json src/
git commit -m "refactor(ts): enable noUncheckedIndexedAccess and fix all type errors"
Task 16: CI 加 unit test + coverage
Files:
-
Modify:
.gitea/workflows/ci.yml -
Modify:
vitest.unit.config.ts -
Modify:
package.json(加 engines + packageManager) -
Step 1: ci.yml 在 Lint 后、Typecheck 前加 Unit test
- name: Lint
run: npm run lint
- name: Unit tests
run: npm run test:unit
- name: Typecheck
run: npm run typecheck
- Step 2: vitest.unit.config.ts 加 coverage 配置
test: {
name: "unit",
environment: "jsdom",
include: ["src/**/*.test.{ts,tsx}"],
clearMocks: true,
restoreMocks: true,
mockReset: true,
coverage: {
provider: "v8",
reporter: ["text", "json-summary"],
lines: 60,
functions: 60,
branches: 60,
statements: 60,
},
},
- Step 3: package.json 加 engines + packageManager
"engines": {
"node": ">=22"
},
"packageManager": "npm@10.9.0",
- Step 4: 验证 unit test 通过
npm run test:unit
Expected: 全部 PASS。
- Step 5: Commit
git add .gitea/workflows/ci.yml vitest.unit.config.ts package.json
git commit -m "ci: add unit test step and coverage threshold to CI"
Task 17: /api/health 端点 + Dockerfile HEALTHCHECK
Files:
-
Create:
src/app/api/health/route.ts -
Modify: Dockerfile(在 .next/standalone/Dockerfile)
-
Step 1: 创建 /api/health 路由
// src/app/api/health/route.ts
import { NextResponse } from "next/server";
export async function GET(): Promise<NextResponse> {
return NextResponse.json({
status: "ok",
uptime: process.uptime(),
timestamp: new Date().toISOString(),
version: process.env.npm_package_version ?? "unknown",
});
}
- Step 2: 读取并修改 Dockerfile
读取 .next/standalone/Dockerfile(若不存在,读取项目根 Dockerfile)。加:
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:3000/api/health || exit 1
- Step 3: 验证
npx tsc --noEmit && npm run lint
- Step 4: Commit
git add src/app/api/health/ Dockerfile
git commit -m "feat(observability): add /api/health endpoint and Docker HEALTHCHECK"
Task 18: bundle-analyzer
Files:
-
Modify:
package.json(devDeps + scripts) -
Modify:
next.config.ts(若存在)或next.config.mjs -
Step 1: 安装 @next/bundle-analyzer
npm install -D @next/bundle-analyzer
- Step 2: 配置 next.config
读取现有 next.config 文件,用 @next/bundle-analyzer 包装:
import bundleAnalyzer from "@next/bundle-analyzer";
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === "true",
});
export default withBundleAnalyzer(nextConfig);
- Step 3: package.json 加 analyze 脚本
"analyze": "ANALYZE=true next build"
- Step 4: 验证
npm run lint
- Step 5: Commit
git add next.config.* package.json package-lock.json
git commit -m "feat(perf): add @next/bundle-analyzer for bundle visualization"
Task 19: API 文档
Files:
-
Create:
docs/api/README.md -
Step 1: 创建 docs/api/README.md
列出 17 个 API 路由,每个含:方法、路径、用途、请求 schema、响应 schema、权限要求。从 withApiErrorHandler 与 ActionState 推导统一格式。
- Step 2: Commit P2 阶段完成
git add docs/api/
git commit -m "docs(api): add API documentation for 17 routes"
git push
Task 20: 最终验收 + 经验沉淀
- Step 1: 全量验证
npm run arch:scan
npm run arch:query -- violations
npx tsc --noEmit
npm run lint
npm run test:unit
Expected:
-
violations: Long files = 0, Server Actions without requirePermission = 0
-
tsc: 0 errors
-
lint: 0 errors
-
test:unit: 全部 PASS
-
Step 2: 更新 known-issues.md 工作经验日志
追加本次规范化治理的经验记录。
- Step 3: 更新 004(若架构意图变化)
若 P0 阶段的文件拆分改变了架构描述,更新 docs/architecture/004_architecture_impact_map.md。
- Step 4: 最终 commit + push
git add docs/
git commit -m "docs: final validation and experience logging for architecture normalization"
git push
验收标准
| 阶段 | 验收项 | 验证命令 |
|---|---|---|
| P0 | 0 个超长文件 + 0 个无权限 Action | npm run arch:query -- violations |
| P0 | tsc + lint 0 错误 | npx tsc --noEmit && npm run lint |
| P1 | 5 个文档存在 | ls LICENSE CHANGELOG.md CONTRIBUTING.md SECURITY.md .env.example |
| P1 | husky 钩子工作 | git commit -m "bad" 被拒绝 |
| P1 | tech-debt.md 含 6+ 条 | Get-Content docs/architecture/roadmap/tech-debt.md | Measure-Object -Line |
| P2 | noUncheckedIndexedAccess=true | cat tsconfig.json | Select-String noUncheckedIndexedAccess |
| P2 | CI 跑 unit test | Select-String "Unit tests" .gitea/workflows/ci.yml |
| P2 | /api/health 可用 | curl http://localhost:3000/api/health |
| P2 | bundle-analyzer 可用 | npm run analyze |