@brightliu/ai-control 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +126 -0
  3. package/addons/export-adapters.js +132 -0
  4. package/bin/ai.js +58 -0
  5. package/lib/change.js +62 -0
  6. package/lib/core.js +94 -0
  7. package/lib/doctor.js +68 -0
  8. package/lib/gate.js +193 -0
  9. package/lib/init.js +88 -0
  10. package/lib/junit.js +76 -0
  11. package/lib/testrun.js +136 -0
  12. package/package.json +37 -0
  13. package/payload/AGENTS.md +62 -0
  14. package/payload/agents/agent-dba.md +104 -0
  15. package/payload/agents/agent-dev.md +100 -0
  16. package/payload/agents/agent-spec.md +209 -0
  17. package/payload/agents/agent-test.md +74 -0
  18. package/payload/agents/dev/go.md +23 -0
  19. package/payload/agents/dev/java.md +71 -0
  20. package/payload/agents/dev/php.md +23 -0
  21. package/payload/agents/dev/web.md +62 -0
  22. package/payload/hooks/guard-bash.js +37 -0
  23. package/payload/hooks/guard-write.js +92 -0
  24. package/payload/rules/00-agent-base.md +56 -0
  25. package/payload/rules/01-code-change.md +27 -0
  26. package/payload/rules/02-product-ux.md +141 -0
  27. package/payload/rules/10-db-schema.md +84 -0
  28. package/payload/rules/20-api.md +160 -0
  29. package/payload/rules/21-jwt.md +25 -0
  30. package/payload/rules/22-rbac.md +38 -0
  31. package/payload/rules/24-openapi.md +14 -0
  32. package/payload/rules/30-frontend.md +58 -0
  33. package/payload/rules/31-vue3.md +20 -0
  34. package/payload/rules/32-react.md +20 -0
  35. package/payload/rules/40-backend.md +63 -0
  36. package/payload/rules/41-spring-boot.md +184 -0
  37. package/payload/rules/42-go-gin.md +20 -0
  38. package/payload/rules/43-php.md +19 -0
  39. package/payload/rules/44-java-enum.md +108 -0
  40. package/payload/rules/50-testing.md +39 -0
  41. package/payload/rules/51-security.md +50 -0
  42. package/payload/rules/52-performance.md +45 -0
  43. package/payload/rules/53-release.md +141 -0
  44. package/payload/rules/README.md +12 -0
  45. package/payload/templates/design.md +15 -0
  46. package/payload/templates/proposal-lite.md +21 -0
  47. package/payload/templates/proposal.md +28 -0
  48. package/payload/templates/review-prompt.md +20 -0
  49. package/payload/templates/spec.md +13 -0
  50. package/payload/templates/test-cases.md +18 -0
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ // Claude Code PreToolUse 钩子(Bash):危险 SQL 在“执行前的一瞬间”拦截。
3
+ // 协议:stdin 收 JSON;exit 0 放行,exit 2 拦截(stderr 会反馈给 Claude)。
4
+ // 原则:只拦“错了不可逆”的模式;解析失败一律放行(fail-open,不能把用户会话搞瘫)。
5
+ // 逃生阀:环境变量 AI_CONTROL_HOOKS=off 时直接放行。
6
+
7
+ if (process.env.AI_CONTROL_HOOKS === "off") process.exit(0);
8
+
9
+ let raw = "";
10
+ process.stdin.on("data", (d) => (raw += d));
11
+ process.stdin.on("end", () => {
12
+ let cmd = "";
13
+ try {
14
+ cmd = (JSON.parse(raw).tool_input || {}).command || "";
15
+ } catch {
16
+ process.exit(0);
17
+ }
18
+ // 确认必须出自用户之手:AI 代跑 ai confirm 会让"确认留痕"失去意义
19
+ if (/(^|[;&|]\s*|\$\(\s*)(node\s+|npx\s+)?(\S*\/)?ai(\.js)?\s+confirm\b/.test(cmd)) {
20
+ console.error("[ai-control] 已拦截:ai confirm 必须由用户本人在终端执行。请向用户输出确认单,并把 `ai confirm <change-id>` 这条命令交给用户运行。");
21
+ process.exit(2);
22
+ }
23
+ const hits = [];
24
+ if (/\bdrop\s+(table|database)\b/i.test(cmd)) hits.push("DROP TABLE/DATABASE");
25
+ if (/\btruncate\s+(table\s+)?\S+/i.test(cmd)) hits.push("TRUNCATE");
26
+ if (/\bdelete\s+from\b/i.test(cmd) && !/\bwhere\b/i.test(cmd)) hits.push("无 WHERE 的 DELETE");
27
+ if (/\bupdate\s+\S+\s+set\b/i.test(cmd) && !/\bwhere\b/i.test(cmd)) hits.push("无 WHERE 的 UPDATE");
28
+
29
+ if (hits.length) {
30
+ console.error(
31
+ `[ai-control] 已拦截危险 SQL(${hits.join("、")})。` +
32
+ `数据库破坏性操作必须走两阶段确认:输出变更确认包(目标 SQL + 回滚 SQL + 影响说明)等用户确认后,由用户执行或用户明确授权后执行;DROP/TRUNCATE 前默认备份(原表名_copy_yyyyMMdd)。`
33
+ );
34
+ process.exit(2);
35
+ }
36
+ process.exit(0);
37
+ });
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ // Claude Code PreToolUse 钩子(Write/Edit):把“change 确认前禁止写业务代码”从
3
+ // 提示词约束前移为写入瞬间的机械拦截——违规不再是“写完被 check 打回”,而是第一行就写不进去。
4
+ // 协议:stdin 收 JSON;exit 0 放行,exit 2 拦截(stderr 反馈给 Claude)。
5
+ // 原则:fail-open——解析失败/结构异常一律放行;只拦最明确的两种违规:
6
+ // 1) 存在变更单但一个都没确认 → 禁止写业务代码(文档/测试/.ai 内除外)
7
+ // 2) 已有确认的变更 → 业务代码路径必须落在某个已确认变更的 affected_files 内
8
+ // 逃生阀:AI_CONTROL_HOOKS=off,或 .ai/config.json 里 "hooks": "off"。
9
+
10
+ const fs = require("fs");
11
+ const path = require("path");
12
+
13
+ if (process.env.AI_CONTROL_HOOKS === "off") process.exit(0);
14
+
15
+ let raw = "";
16
+ process.stdin.on("data", (d) => (raw += d));
17
+ process.stdin.on("end", () => {
18
+ try {
19
+ main(JSON.parse(raw));
20
+ } catch {
21
+ process.exit(0);
22
+ }
23
+ });
24
+
25
+ function main(input) {
26
+ const fp = (input.tool_input || {}).file_path || (input.tool_input || {}).notebook_path || "";
27
+ if (!fp) process.exit(0);
28
+ const root = process.cwd();
29
+ try {
30
+ if ((JSON.parse(fs.readFileSync(path.join(root, ".ai", "config.json"), "utf8")).hooks || "") === "off") process.exit(0);
31
+ } catch { /* 无配置则默认开启 */ }
32
+
33
+ const rel = path.relative(root, path.resolve(root, fp)).replace(/\\/g, "/");
34
+
35
+ // 永远放行:文档、测试、框架自身目录(简单任务与流程文件不受限)
36
+ const FREE = [
37
+ /\.md$/i,
38
+ /(^|\/)\.(ai|claude|workbuddy|github|git)\//,
39
+ /(^|\/)(tests?|__tests__|test-results)\//,
40
+ /\.(test|spec)\.[jt]sx?$/,
41
+ /Test\.(java|kt|php)$/,
42
+ /_test\.go$/,
43
+ ];
44
+ if (rel.startsWith("..") || FREE.some((re) => re.test(rel))) process.exit(0);
45
+
46
+ const changesDir = path.join(root, ".ai", "changes");
47
+ let ids = [];
48
+ try {
49
+ ids = fs.readdirSync(changesDir).filter((d) => fs.statSync(path.join(changesDir, d)).isDirectory());
50
+ } catch { process.exit(0); } // 未安装/无变更目录:不拦(契约仍然管)
51
+ if (!ids.length) process.exit(0);
52
+
53
+ const confirmed = ids.filter((id) => fs.existsSync(path.join(changesDir, id, "confirmed.json")));
54
+ if (!confirmed.length) {
55
+ console.error(
56
+ `[ai-control] 已拦截:存在变更单(${ids.join(", ")})但均未确认。` +
57
+ `change 确认前禁止写业务代码——先 ai check 通过、向用户输出确认单,用户点头后 ai confirm <id> 再实现。`
58
+ );
59
+ process.exit(2);
60
+ }
61
+
62
+ // 汇总已确认变更声明的影响文件
63
+ const declared = [];
64
+ for (const id of confirmed) {
65
+ try {
66
+ const text = fs.readFileSync(path.join(changesDir, id, "proposal.md"), "utf8");
67
+ const m = text.match(/^[ \t]*affected_files:[ \t]*([^\n]*)\n?((?:[ \t]*-[ \t]*[^\n]*\n?)*)/m);
68
+ if (!m) continue;
69
+ if (m[1] && m[1].trim()) declared.push(m[1].trim());
70
+ for (const l of (m[2] || "").split("\n")) {
71
+ const v = l.replace(/^[ \t]*-[ \t]*/, "").replace(/[`'"]/g, "").trim();
72
+ if (v && !/^(none|无|暂无|n\/a)$/i.test(v)) declared.push(v);
73
+ }
74
+ } catch { /* 单个变更读取失败不影响其他 */ }
75
+ }
76
+ if (!declared.length) process.exit(0); // 声明为空/异常:fail-open
77
+
78
+ const norm = (s) => s.replace(/^\.\//, "").replace(/\\/g, "/");
79
+ const ok = declared.some((e) => {
80
+ const d = norm(e);
81
+ if (d.endsWith("/")) return rel.startsWith(d) || rel.includes("/" + d);
82
+ return rel === d || rel.endsWith("/" + d) || d.endsWith("/" + rel) || rel.endsWith(d);
83
+ });
84
+ if (!ok) {
85
+ console.error(
86
+ `[ai-control] 已拦截:${rel} 不在任何已确认变更的 affected_files 内` +
87
+ `(已确认: ${confirmed.join(", ")})。禁止修改无关文件;确需修改则更新 proposal 影响范围并重新经用户确认(ai confirm)。`
88
+ );
89
+ process.exit(2);
90
+ }
91
+ process.exit(0);
92
+ }
@@ -0,0 +1,56 @@
1
+ # Agent 公共模板
2
+
3
+ 本文件是新增或维护 `agents/agent-*.md` 时的公共基线。
4
+
5
+ ## 标准章节
6
+
7
+ ```md
8
+ # 中文角色名(agent-name)
9
+
10
+ ## 角色名称
11
+
12
+ 中文角色名
13
+
14
+ ## 职责
15
+
16
+ ## 适用场景
17
+
18
+ ## 必须读取
19
+
20
+ ## 工作流程
21
+
22
+ ## 停止并询问
23
+
24
+ ## 禁止事项
25
+
26
+ ## 输出
27
+ ```
28
+
29
+ ## 公共规则
30
+
31
+ - 只保留本 agent 执行所需的核心规则,不把所有全局规则复制进来。
32
+ - 详细工程规则放在 `.ai/rules/`,由 `必须读取` 引用。
33
+ - 可执行、可重复、易错的动作优先固化为 `ai` 命令(new/check/test/ship),不靠人肉步骤。
34
+ - OpenSpec 相关操作只放 产品规格工程师(`agent-spec`)。
35
+ - 产品、业务建模与架构影响评估只放产品规格工程师(`agent-spec`)。
36
+
37
+ ## 停止并询问基线
38
+
39
+ 出现以下情况必须停止并询问:
40
+
41
+ - 输入信息缺失会影响正确性。
42
+ - 业务规则、字段、枚举、权限、租户、状态流转或 API 响应不清。
43
+ - 需要覆盖、删除、重命名或迁移已有产物。
44
+ - 需要引入新依赖或改变架构。
45
+ - 当前 agent 与其他 agent 职责冲突且无法按 `AGENTS.md` 的角色路由判定顺序。
46
+
47
+ ## 输出基线
48
+
49
+ 输出至少包含:
50
+
51
+ - 使用的中文角色和 agent id。
52
+ - 读取的事实源。
53
+ - 实施或审查结果。
54
+ - 变更文件,如有。
55
+ - 验证步骤。
56
+ - 假设和风险。
@@ -0,0 +1,27 @@
1
+ # 代码变更规则
2
+
3
+ 跨技术栈通用的精准修改、代码精简与无效代码清理规则。所有实现类与设计类 agent(Java/Go/PHP 后端、Web 前端、系统架构师)必须遵守;各 agent 手册只补充本栈特有的清单和验证方式,不得复述本文件内容。
4
+
5
+ ## 精准修改
6
+
7
+ - 只修改用户需求、OpenSpec change、已确认规格或明确验证失败直接要求的内容;每一行变更都必须能追溯到本次任务。
8
+ - 禁止顺手优化、顺手重构、顺手改格式、顺手改注释、顺手调整样式或清理无关历史代码;即使有不同实现偏好,也必须优先匹配既有代码风格、组件体系和设计系统。
9
+
10
+ ## 代码精简
11
+
12
+ - 优先选择最少且清楚的生产级实现;能用 50 行清楚实现的,不写成 200 行。代码变多必须带来更清晰的业务或交互语义、更少重复、更容易测试或隔离真实变化。
13
+ - 一眼能看懂的顺序逻辑不为了“分层感”强行抽函数、hook、utils 或子组件;只使用一次且没有清晰业务名字的代码块通常不抽函数。
14
+ - 重复 3 次且语义一致时再考虑抽象;抽出的函数、hook 或组件必须表达业务意图或明确副作用,并降低调用方理解成本,不能让读者频繁跳转文件才能理解主流程。
15
+ - 简单赋值、简单 if、简单字段搬运、简单条件渲染、简单事件转发,不要拆成多个一行函数或空壳组件。
16
+ - 禁止没有真实差异的接口、策略、模板方法、工厂类和扩展点,禁止为了套模式制造空壳层。
17
+
18
+ ## 无效代码清理
19
+
20
+ - 本次改动造成的 unused import、未使用变量、未使用私有方法或引用、无意义转发、临时日志、调试代码和注释代码必须清理。
21
+ - 改动前已存在的疑似 dead code 只能指出位置和风险,不得直接删除,除非用户明确要求且已完成静态引用、配置引用、框架引用、契约引用、测试引用和发布影响检查。
22
+ - 被框架、配置、路由、权限、序列化或契约隐式引用的产物,即使 IDE 显示 `0 usages`,也不能直接删除;各栈的具体不可删清单见对应 agent 手册。
23
+
24
+ ## 清理后的验证
25
+
26
+ - 清理 unused import / unused variable 后,至少运行编译、lint 或类型检查。
27
+ - 删除类、方法、组件、路由、状态或工具函数后,必须运行对应栈的编译、测试、构建或手动验证;无法验证时必须说明残留风险。
@@ -0,0 +1,141 @@
1
+ # 产品、业务与体验规则
2
+
3
+ ## 业务规则
4
+
5
+ ## 必须沉淀到 OpenSpec
6
+ 以下内容必须进入 `.ai/specs/<capability>/spec.md`:
7
+ - 领域对象
8
+ - 字段含义
9
+ - 枚举值
10
+ - 状态流转
11
+ - 权限规则
12
+ - 租户规则
13
+ - 删除行为
14
+ - 通知规则
15
+ - 时间冲突规则
16
+ - 支付、退款、套餐扣减和回滚规则
17
+ - 审计、日志和追踪规则
18
+
19
+ ### 业务建模要求
20
+ - 使用一致的领域语言。
21
+ - 明确对象生命周期。
22
+ - 明确创建、更新、审核、删除、取消、完成等动作的前置条件和结果。
23
+ - 明确数据归属和租户隔离。
24
+ - 明确历史数据兼容策略。
25
+
26
+ ### 停止条件
27
+ 如果字段含义、状态枚举、权限、租户、删除或支付规则不清楚,必须停止并询问。
28
+
29
+ ## 产品规则
30
+
31
+ ## 必须明确
32
+ - 目标用户是谁。
33
+ - 用户要完成什么任务。
34
+ - 当前需求解决什么业务问题。
35
+ - 成功指标是什么。
36
+ - 功能范围和非范围是什么。
37
+ - 是否影响已有用户工作流。
38
+
39
+ ### 禁止事项
40
+ - 禁止把实现细节当作产品目标。
41
+ - 禁止为了技术方便改变业务流程。
42
+ - 禁止发明用户角色、业务目标、权限或通知规则。
43
+ - 禁止忽略异常场景、空数据场景和失败场景。
44
+
45
+ ### 输出要求
46
+ 涉及产品决策时必须说明:
47
+ - 用户角色
48
+ - 使用场景
49
+ - 业务目标
50
+ - 成功指标
51
+ - 核心流程
52
+ - 异常流程
53
+ - 非范围
54
+ - 待确认问题
55
+
56
+ ### 待确认问题格式
57
+
58
+ 待确认问题必须帮助用户做选择,不能只写“待确认”。每个问题必须包含:
59
+
60
+ - 需要确认:用户必须拍板的事项。
61
+ - 建议方案:AI 助手的默认建议。
62
+ - 推荐原因:为什么这样更稳、更小或更符合项目。
63
+ - 影响范围:影响哪些表、接口、页面、权限、测试或发布。
64
+ - 可选方案:其他可选方案,如有。
65
+ - 默认处理:用户确认后才按建议进入设计和实现,未确认前不得写成已确认规则。
66
+
67
+ ## UX 规则
68
+
69
+ ## 必须考虑
70
+ - 用户进入页面的入口。
71
+ - 用户完成任务的主路径。
72
+ - 空态、加载态、错误态、成功态。
73
+ - 权限不足、数据不存在、网络失败。
74
+ - 表单校验、错误提示和提交反馈。
75
+ - 批量操作和高风险操作确认。
76
+ - 移动端和桌面端可用性,如项目需要。
77
+
78
+ ### 状态设计
79
+ - 加载态必须说明触发时机、持续期间可执行动作和超时反馈。
80
+ - 空态必须区分“无权限查看”“有权限但无数据”“筛选条件无结果”。
81
+ - 错误态必须提供可执行恢复路径,例如重试、返回、修改输入或联系管理员。
82
+ - 成功态必须说明下一步去向,避免用户不知道操作是否生效。
83
+ - 权限态必须避免暴露用户无权操作的数据细节。
84
+
85
+ ### 表单和批量操作
86
+ - 表单字段必须明确必填、格式、范围、默认值和禁用条件。
87
+ - 提交中必须防重复提交。
88
+ - 批量操作必须说明选择范围、跨页选择语义、失败项展示和部分成功处理。
89
+ - 高风险操作必须二次确认,确认文案应包含对象、影响和不可逆风险。
90
+ - 删除、作废、扣减、发布、回滚等动作必须说明撤销或补救路径。
91
+
92
+ ### 导航和信息架构
93
+ - 页面入口必须可从既有导航或业务流程自然到达。
94
+ - 列表、详情、编辑、创建之间的返回路径必须明确。
95
+ - 筛选、排序、分页和刷新不能让用户丢失关键上下文。
96
+ - 多角色页面必须说明不同角色可见内容和可执行动作。
97
+
98
+ ### 禁止事项
99
+ - 禁止用说明文字代替清晰交互。
100
+ - 禁止缺失失败反馈。
101
+ - 禁止高风险操作无确认。
102
+ - 禁止在用户未确认时自动执行破坏性动作。
103
+
104
+ ### 输出要求
105
+ 涉及 UI/UX 时必须说明:
106
+ - 页面或流程入口
107
+ - 用户主流程
108
+ - 异常流程
109
+ - 状态设计
110
+ - 权限态设计
111
+ - 表单和校验
112
+ - 批量操作和高风险确认,如有
113
+ - 返回、刷新和重复提交策略
114
+ - 待确认交互
115
+
116
+ ## UI 设计规则
117
+
118
+ ## 原则
119
+ - 遵循既有设计系统。
120
+ - 优先使用项目已有组件、图标、颜色、间距和表单模式。
121
+ - 业务系统应清晰、克制、可扫描,不做营销式装饰。
122
+ - 控件尺寸稳定,避免因动态文本导致布局跳动。
123
+ - 文案必须适配容器,不得重叠或溢出。
124
+
125
+ ### 必须检查
126
+ - 页面层级
127
+ - 表格和列表密度
128
+ - 表单分组
129
+ - 按钮主次
130
+ - 空态、加载态、错误态
131
+ - 弹窗和抽屉
132
+ - 权限态和禁用态
133
+ - 响应式布局
134
+
135
+ ### 禁止事项
136
+ - 禁止无意义装饰。
137
+ - 禁止卡片套卡片。
138
+ - 禁止一色到底的单调配色。
139
+ - 禁止文字遮挡或溢出。
140
+ - 禁止凭空引入新设计系统。
141
+
@@ -0,0 +1,84 @@
1
+ # 数据库结构规则
2
+
3
+ ## MySQL 基线
4
+ - MySQL 8
5
+ - 字符集:`utf8mb4`
6
+ - 推荐排序规则:`utf8mb4_unicode_ci`,除非既有表已经使用其他排序规则。
7
+
8
+ ## 主键和业务 ID
9
+ - 数据库可以保留 `pk_id` 作为内部自增主键。
10
+ - 对外 API 和前端统一使用业务 ID `id`。
11
+ - `id` 如使用雪花算法或其他长整型,前端必须按字符串处理。
12
+ - 禁止把 `pk_id`、`pkId`、`pk_id_list` 或 `pkIdList` 暴露为 API 请求/响应字段。
13
+ - 后端内部可把 API 字符串 `id` 校验后转换为 `Long` 查询。
14
+
15
+ ## 基础字段建议
16
+ 业务表应考虑:
17
+
18
+ ```sql
19
+ `pk_id` bigint NOT NULL AUTO_INCREMENT COMMENT '数据库主键',
20
+ `id` bigint NOT NULL COMMENT '业务ID,雪花算法生成',
21
+ `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户ID',
22
+ `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否删除:0否 1是',
23
+ `gmt_created` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
24
+ `gmt_modified` datetime(3) NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
25
+ `gmt_deleted` datetime(3) NULL COMMENT '删除时间',
26
+ `create_by` varchar(255) NULL COMMENT '创建人',
27
+ `update_by` varchar(255) NULL COMMENT '更新人'
28
+ ```
29
+
30
+ ## SQL 规则
31
+ - 禁止 `SELECT *`。
32
+ - 必须显式列名。
33
+ - UPDATE/DELETE 必须有精确 WHERE。
34
+ - 存在租户上下文时必须带租户条件。
35
+ - 存在软删除时必须带软删除条件。
36
+ - 避免索引字段函数计算。
37
+ - 避免隐式类型转换。
38
+
39
+ ## JOIN 查询规则
40
+ - 禁止隐式逗号连接,例如 `FROM a, b`。
41
+ - 每个 `JOIN` 必须有明确的 `ON` 或 `USING` 条件,禁止无条件 JOIN 造成笛卡尔乘积。
42
+ - `ON` 条件必须使用已确认的表关系字段,禁止猜测关联字段。
43
+ - 多表查询必须先确认主表粒度,例如一行代表一个订单、一个用户或一条审批记录。
44
+ - 存在一对多或多对多关系时,列表查询、分页查询和统计查询不得直接把子表明细 JOIN 到主表后再分页或计数。
45
+ - 一对多数据需要展示时,应优先使用子查询预聚合、`EXISTS`、二次查询组装或明确的明细列表接口。
46
+ - 禁止把 `DISTINCT` 或 `GROUP BY` 当作修复重复数据的默认手段;必须先确认重复来源和业务粒度。
47
+ - 涉及租户、软删除、状态过滤的 JOIN 查询,每张参与表都必须按业务规则补齐对应过滤条件。
48
+ - 编写或修改 JOIN SQL 后,必须使用覆盖一对零、一对一、一对多、多对多边界数据的样例验证结果行数。
49
+
50
+ ## 表结构设计审查
51
+ 只要涉及创建或修改表结构、字段、索引、约束、初始化数据或迁移数据,必须先输出表结构设计审查并等待用户确认。用户确认表结构设计审查前,禁止输出数据库变更确认包、执行 SQL、写入 migration 文件或实现依赖新表结构的代码。
52
+
53
+ 表结构设计审查必须包含:
54
+ - 查询场景:列表、详情、导出、统计、后台筛选、定时任务、JOIN 和排序分页等真实入口;不明确时必须 STOP and ASK。
55
+ - 写入场景:新增、编辑、删除、状态流转、批量导入、同步任务和历史数据迁移。
56
+ - 数据量级:当前量级、增长速度、冷热数据、租户数量和单租户数据量;不明确时标记待确认。
57
+ - 字段必要性分析:逐字段说明字段含义、事实来源、是否必须存储、是否可计算、是否建议新增/保留/修改/删除。
58
+ - 索引建议:基于 WHERE、JOIN、ORDER BY、GROUP BY 和唯一性约束提出索引,说明字段顺序、选择性、是否覆盖租户和软删除字段、写入成本,以及不建议加索引的原因。
59
+ - 冗余字段建议:仅在避免高频 JOIN、固化历史快照、提升列表/统计性能或隔离外部对象变更时提出;必须说明来源字段、同步时机、一致性策略、补偿方式和是否允许短暂不一致。
60
+ - 删除字段建议:默认只作为建议,不进入执行 DDL;必须说明代码/API/报表/导出依赖、历史数据备份、灰度删除、回滚方式和不删除的代价。
61
+ - Laravel / Hyperf 迁移策略:识别到 Laravel 或 Hyperf 项目时,说明建议的 migration 文件名、路径、up/down 逻辑摘要和是否需要模型/实体同步;用户确认前禁止写入 migration 文件或执行 migrate。
62
+ - 待用户确认项:字段含义、类型长度、默认值、枚举、索引、冗余字段、删除/重命名/合并字段、迁移策略和业务查询场景。
63
+
64
+ ## 数据库变更确认包
65
+ 用户确认表结构设计审查后,才允许输出数据库变更确认包。该阶段只能放入已确认的变更,未确认建议必须保留在“建议和待确认项”中,禁止混入可执行 SQL。
66
+
67
+ 数据库变更确认包必须包含:
68
+ - 当前结构摘要:涉及表、字段、索引、约束、租户字段、软删除字段和审计字段。
69
+ - 本次确认变更:已确认的新增字段、修改字段、删除字段、新增索引、删除索引、约束变化、初始化数据和迁移数据。
70
+ - 目标结构 DDL:展示变更完成后的完整目标结构,用于用户整体观察和再次确认,不默认作为直接执行 SQL。
71
+ - 本地手动执行 DDL:用户可以复制到本地或 dev 环境执行的 SQL,必须按执行顺序排列,并与已确认变更一致。
72
+ - rollback SQL:本地执行失败、验证不通过或需要回退时使用的 SQL。
73
+ - Laravel / Hyperf migration 文件预览:识别到对应框架时,展示建议文件路径、文件名和完整 up/down 内容;用户确认前禁止写入文件或执行 `php artisan migrate`、`php bin/hyperf.php migrate`。
74
+ - 历史数据兼容策略。
75
+ - 索引影响和查询路径影响。
76
+ - Entity/Mapper/XML/DTO/VO/API 联动清单。
77
+ - 建议和待确认项:未确认的冗余字段、删除字段、重命名字段、迁移策略和风险建议必须留在此处,不得写入本地手动执行 DDL。
78
+ - 待用户确认项:字段含义、类型长度、默认值、枚举、删除/重命名/合并字段、迁移策略和是否允许执行。
79
+
80
+ 本地手动执行 DDL 禁止包含 DROP、删除字段、重命名字段、截断表、全表 UPDATE/DELETE 或不可逆迁移,除非用户已经对该项明确确认。
81
+
82
+ ## 高风险操作
83
+ CREATE、UPDATE、DELETE、ALTER、DROP、TRUNCATE 执行前必须确认。
84
+ DROP/TRUNCATE 默认先备份,备份表名:`原表名_copy_yyyyMMdd`。
@@ -0,0 +1,160 @@
1
+ # API 规则
2
+
3
+ ## 路径和兼容
4
+ - API 路径必须遵循本文件的入口、版本、模块和动作规则。
5
+ - 禁止发明新响应结构。
6
+ - 禁止破坏已有接口兼容性,除非用户明确批准。
7
+ - 新增、修改、删除接口必须写清影响范围。
8
+ - 后台、管理端、平台管理接口必须写清访问控制模式、责任系统、权限点或明确不适用原因。
9
+
10
+ ## 入口前缀
11
+ 所有新增 API 必须带版本号。
12
+
13
+ | 场景 | 路径前缀 | 说明 |
14
+ |------|----------|------|
15
+ | 管理后台 | `/api/admin/v1` | 平台管理、运营后台、管理端 |
16
+ | 移动端 | `/api/app/v1` | App、H5、小程序共用用户端接口 |
17
+ | 小程序端 | `/api/app/v1` | 与移动端共用;差异使用 header 或业务参数区分 |
18
+ | 对外开放接口 | `/openapi/app/v1` | 给第三方系统或合作方调用 |
19
+ | 对内服务接口 | `/innerapi/app/v1` | 系统内部服务调用,不给前端直接访问 |
20
+
21
+ ## 路径格式
22
+ 路径格式必须为:
23
+
24
+ ```text
25
+ /入口/端类型/v版本/业务模块/动作
26
+ ```
27
+
28
+ 示例:
29
+
30
+ ```text
31
+ /api/admin/v1/supplier/page
32
+ /api/admin/v1/supplier/detail
33
+ /api/admin/v1/supplier/create
34
+ /api/admin/v1/supplier/update
35
+ /api/admin/v1/supplier/delete
36
+ /api/app/v1/supplier-onboarding/submit
37
+ /openapi/app/v1/order/push
38
+ /innerapi/app/v1/order/sync
39
+ ```
40
+
41
+ 路径命名规则:
42
+ - URL path 只允许小写字母、数字、`/` 和中横线 `-`。
43
+ - 多单词业务模块必须使用中横线,例如 `supplier-onboarding`、`audit-log`。
44
+ - 禁止驼峰命名,例如 `supplierOnboarding`。
45
+ - 禁止下划线命名,例如 `supplier_onboarding`。
46
+ - 禁止大写路径段。
47
+ - 业务模块使用单数业务名,例如 `supplier`、`audit-log`、`user-role`,禁止为了 REST 风格改成复数资源名。
48
+
49
+ ## 请求方法
50
+ 只允许:
51
+
52
+ ```text
53
+ GET
54
+ POST
55
+ ```
56
+
57
+ 禁止:
58
+
59
+ ```text
60
+ PUT
61
+ DELETE
62
+ PATCH
63
+ ```
64
+
65
+ 方法使用规则:
66
+ - 查询、分页、列表、详情、选项使用 `GET`。
67
+ - 新增、修改、删除、批量删除、提交、审核、通过、驳回、启用、禁用使用 `POST`。
68
+
69
+ ## 参数位置
70
+ 禁止路径参数。
71
+
72
+ 禁止:
73
+
74
+ ```text
75
+ /api/admin/v1/supplier/{id}
76
+ /api/admin/v1/supplier/123
77
+ /api/admin/v1/supplier/detail/123
78
+ ```
79
+
80
+ 必须:
81
+
82
+ ```text
83
+ GET /api/admin/v1/supplier/detail?id=123
84
+ POST /api/admin/v1/supplier/update
85
+ POST /api/admin/v1/supplier/delete
86
+ ```
87
+
88
+ POST body:
89
+
90
+ ```json
91
+ {
92
+ "id": "123"
93
+ }
94
+ ```
95
+
96
+ ## 动作命名
97
+ 常用动作必须使用以下路径段:
98
+
99
+ | 动作 | 路径段 | Method |
100
+ |------|--------|--------|
101
+ | 分页 | `page` | GET |
102
+ | 列表 | `list` | GET |
103
+ | 详情 | `detail` | GET |
104
+ | 下拉选项 | `options` | GET |
105
+ | 新增 | `create` | POST |
106
+ | 修改 | `update` | POST |
107
+ | 删除 | `delete` | POST |
108
+ | 批量删除 | `batch-delete` | POST |
109
+ | 提交 | `submit` | POST |
110
+ | 审核 | `review` | POST |
111
+ | 通过 | `approve` | POST |
112
+ | 驳回 | `reject` | POST |
113
+ | 启用 | `enable` | POST |
114
+ | 禁用 | `disable` | POST |
115
+
116
+ ## API 契约位置
117
+ - API 事实源必须先进入 `.ai/changes/<change-id>/`。
118
+ - `api-contracts/` 只用于把已确认或待确认的接口细节展开成便于前后端联调的文档。
119
+ - `api-contracts/` 不得与 OpenSpec 写两套冲突规则。
120
+ - 如果两者不一致,以 OpenSpec 中已确认的 `spec.md` 和用户确认记录为准,并立即同步 `api-contracts/`。
121
+ - 示例项目可以保留 `api-contracts/`,但必须在 README 中说明它和 OpenSpec 的关系。
122
+
123
+ ## 请求
124
+ - Create/Update 请求必须校验。
125
+ - 分页、筛选、排序参数必须有明确含义和默认值。
126
+ - 禁止只依赖前端校验。
127
+ - 请求 DTO 必须明确必填、长度、格式、枚举、数值范围和数组数量限制,供前端表单校验对齐。
128
+ - 请求字段约束必须与数据库字段长度、后端验证层和 OpenSpec/API 契约一致;不一致时必须先确认。
129
+ - 对外 ID 参数统一命名为 `id` 或 `idList`,禁止使用 `pk_id`、`pkId`、`pk_id_list` 或 `pkIdList`。
130
+ - 长整型 ID 在 JSON、URL query 和前端状态中必须按字符串传递。
131
+
132
+ ## 响应
133
+ - 必须使用既有统一响应包装。
134
+ - 如果存在 VO,禁止直接返回 Entity。
135
+ - 禁止暴露敏感字段。
136
+ - 禁止暴露异常堆栈。
137
+ - 响应中的长整型业务 ID 必须序列化为字符串,避免前端精度丢失。
138
+
139
+ ## 错误
140
+ - `id` 为空、非数字、非正数或越界时返回参数错误。
141
+ - 按 `id` 查询不到数据时返回业务不存在。
142
+ - 禁止把 ID 解析失败、空指针或数据不存在变成 500。
143
+
144
+ ## 分页
145
+ 分页响应必须明确:
146
+ - list/data
147
+ - total
148
+ - pageNum/current
149
+ - pageSize
150
+
151
+ ## 输出要求
152
+ 涉及 API 变化时必须说明:
153
+ - API 路径
154
+ - 请求 DTO
155
+ - 响应 VO
156
+ - 分页结构
157
+ - 兼容性影响
158
+ - 前端联动影响
159
+ - 前端表单校验规则来源,包括必填、长度、格式、枚举和范围
160
+ - 鉴权方式、访问控制模式、责任系统、权限点和无权限返回
@@ -0,0 +1,25 @@
1
+ # JWT 功能规则
2
+
3
+ ## 适用范围
4
+
5
+ 适用于登录、登出、刷新 token、权限认证、token 吊销和会话安全。
6
+
7
+ ## 必须确认
8
+
9
+ - 登录账号类型:用户名、手机号、邮箱或第三方身份。
10
+ - 密码存储方式和加密算法。
11
+ - access token 有效期。
12
+ - refresh token 是否启用及有效期。
13
+ - 登出后是否加入 Redis 黑名单。
14
+ - 多端登录策略:允许多端、互踢或按设备管理。
15
+ - token 中允许放哪些 claim。
16
+ - 未登录、过期、无权限的错误码和响应格式。
17
+
18
+ ## 默认安全规则
19
+
20
+ - token 中禁止放密码、手机号明文、身份证号、密钥或高敏感信息。
21
+ - access token 有效期不宜过长。
22
+ - 登出、改密、禁用账号后,旧 token 必须失效或进入黑名单。
23
+ - 管理端接口必须经过认证中间件或过滤器。
24
+ - 登录失败不能暴露“账号存在但密码错误”等可枚举信息,除非业务确认允许。
25
+
@@ -0,0 +1,38 @@
1
+ # RBAC / 访问控制功能规则
2
+
3
+ ## 适用范围
4
+
5
+ 适用于后台菜单、按钮、接口权限、角色授权、外部权限服务、网关鉴权、IAM/SSO、数据范围和越权检查。
6
+
7
+ ## 项目级开关
8
+
9
+ 项目可以通过 `.ai/config.json` 的 `accessControlMode` 字段说明访问控制模式(未声明视为 `pending`):
10
+
11
+ | 值 | 含义 |
12
+ |----|------|
13
+ | `local` | 本服务建设 RBAC,本服务负责角色、权限点、菜单权限、按钮权限、接口权限和数据范围 |
14
+ | `external` | 外部系统、网关、IAM 或 SSO 负责访问控制,本服务不维护 RBAC,但必须校验外部传入的身份和权限上下文 |
15
+ | `none` | 当前项目或功能不适用访问控制,必须写清原因、暴露面和风险 |
16
+ | `pending` | 待确认,进入实现前必须确认 |
17
+
18
+ ## 新后台功能必查
19
+
20
+ - 本服务是否建设 RBAC。
21
+ - 如果本服务不建设,哪个外部系统负责访问控制。
22
+ - 外部系统如何把用户身份、角色、权限点、租户或数据范围传给本服务。
23
+ - 是否需要菜单权限。
24
+ - 是否需要按钮权限。
25
+ - 是否需要接口权限。
26
+ - 是否区分平台管理、专家、供应商、普通用户等角色。
27
+ - 是否需要数据范围隔离。
28
+ - 无权限时返回什么错误码和前端状态。
29
+ - 越权访问时如何处理和记录审计日志。
30
+
31
+ ## 规则
32
+
33
+ - 后台管理功能默认不能裸奔,必须明确访问控制方案。
34
+ - 本服务建设 RBAC 时,权限码命名必须跟随目标项目已有约定。
35
+ - 外部系统负责访问控制时,必须写清责任系统、调用凭证、失败处理和越权处理。
36
+ - 当前功能不适用访问控制时,必须写清原因、暴露面和风险。
37
+ - 前端隐藏按钮不等于后端已授权,后端或责任系统必须校验。
38
+ - 涉及租户、组织、供应商、专家等数据边界时,查询和写入都要校验数据归属。