@wneng/create-keel 0.3.6 → 0.4.1
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.
- package/dist/index.js +206 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/templates/ci-gitee/files/PULL_REQUEST_TEMPLATE.md +15 -2
- package/src/templates/ci-gitee/files/pipeline.yml +62 -0
- package/src/templates/ci-github/files/PULL_REQUEST_TEMPLATE.md +15 -2
- package/src/templates/ci-github/files/ci.yml +160 -0
- package/src/templates/db-go-elasticsearch/files/Makefile +18 -0
- package/src/templates/db-go-elasticsearch/files/apply_templates.go +80 -0
- package/src/templates/db-go-elasticsearch/files/db-README.md +57 -0
- package/src/templates/db-go-elasticsearch/files/go.mod +7 -0
- package/src/templates/db-go-elasticsearch/files/index-template-init.json +25 -0
- package/src/templates/db-go-elasticsearch/fragment.yaml +22 -0
- package/src/templates/db-go-migrate-mysql/files/000001_init.down.sql +3 -0
- package/src/templates/db-go-migrate-mysql/files/000001_init.up.sql +35 -0
- package/src/templates/db-go-migrate-mysql/files/Makefile +33 -0
- package/src/templates/db-go-migrate-mysql/files/db-README.md +77 -0
- package/src/templates/db-go-migrate-mysql/files/go.mod +8 -0
- package/src/templates/db-go-migrate-mysql/fragment.yaml +22 -0
- package/src/templates/db-go-migrate-postgres/files/000001_init.down.sql +3 -0
- package/src/templates/db-go-migrate-postgres/files/000001_init.up.sql +32 -0
- package/src/templates/db-go-migrate-postgres/files/Makefile +31 -0
- package/src/templates/db-go-migrate-postgres/files/db-README.md +71 -0
- package/src/templates/db-go-migrate-postgres/files/go.mod +8 -0
- package/src/templates/db-go-migrate-postgres/fragment.yaml +22 -0
- package/src/templates/db-java-elasticsearch/files/EsTemplateApplier.java +86 -0
- package/src/templates/db-java-elasticsearch/files/db-README.md +63 -0
- package/src/templates/db-java-elasticsearch/files/index-template-init.json +25 -0
- package/src/templates/db-java-elasticsearch/files/pom.xml +134 -0
- package/src/templates/db-java-elasticsearch/fragment.yaml +19 -0
- package/src/templates/db-java-flyway-mysql/files/V1__init.sql +44 -0
- package/src/templates/db-java-flyway-mysql/files/application.yaml +39 -0
- package/src/templates/db-java-flyway-mysql/files/db-README.md +102 -0
- package/src/templates/db-java-flyway-mysql/files/pom.xml +172 -0
- package/src/templates/db-java-flyway-mysql/fragment.yaml +19 -0
- package/src/templates/db-java-flyway-postgres/files/V1__init.sql +40 -0
- package/src/templates/db-java-flyway-postgres/files/application.yaml +37 -0
- package/src/templates/db-java-flyway-postgres/files/db-README.md +75 -0
- package/src/templates/db-java-flyway-postgres/files/pom.xml +166 -0
- package/src/templates/db-java-flyway-postgres/fragment.yaml +19 -0
- package/src/templates/db-node-elasticsearch/files/apply-templates.cjs +60 -0
- package/src/templates/db-node-elasticsearch/files/db-README.md +76 -0
- package/src/templates/db-node-elasticsearch/files/index-template-init.json +26 -0
- package/src/templates/db-node-elasticsearch/files/package.json +26 -0
- package/src/templates/db-node-elasticsearch/fragment.yaml +19 -0
- package/src/templates/db-node-knex-mysql/files/db-README.md +90 -0
- package/src/templates/db-node-knex-mysql/files/knexfile.cjs +72 -0
- package/src/templates/db-node-knex-mysql/files/migrations-init.cjs +42 -0
- package/src/templates/db-node-knex-mysql/files/package.json +31 -0
- package/src/templates/db-node-knex-mysql/files/seeds-dev-fixtures.cjs +38 -0
- package/src/templates/db-node-knex-mysql/files/seeds-prod-dictionaries.cjs +25 -0
- package/src/templates/db-node-knex-mysql/fragment.yaml +25 -0
- package/src/templates/db-node-knex-postgres/files/db-README.md +81 -0
- package/src/templates/db-node-knex-postgres/files/knexfile.cjs +67 -0
- package/src/templates/db-node-knex-postgres/files/migrations-init.cjs +42 -0
- package/src/templates/db-node-knex-postgres/files/package.json +31 -0
- package/src/templates/db-node-knex-postgres/files/seeds-dev-fixtures.cjs +36 -0
- package/src/templates/db-node-knex-postgres/files/seeds-prod-dictionaries.cjs +26 -0
- package/src/templates/db-node-knex-postgres/fragment.yaml +25 -0
- package/src/templates/db-python-alembic-mysql/files/0001_init.py +70 -0
- package/src/templates/db-python-alembic-mysql/files/alembic.ini +47 -0
- package/src/templates/db-python-alembic-mysql/files/db-README.md +87 -0
- package/src/templates/db-python-alembic-mysql/files/env.py +71 -0
- package/src/templates/db-python-alembic-mysql/files/pyproject.toml +52 -0
- package/src/templates/db-python-alembic-mysql/files/script.py.mako +26 -0
- package/src/templates/db-python-alembic-mysql/fragment.yaml +25 -0
- package/src/templates/db-python-alembic-postgres/files/0001_init.py +62 -0
- package/src/templates/db-python-alembic-postgres/files/alembic.ini +45 -0
- package/src/templates/db-python-alembic-postgres/files/db-README.md +70 -0
- package/src/templates/db-python-alembic-postgres/files/env.py +62 -0
- package/src/templates/db-python-alembic-postgres/files/pyproject.toml +52 -0
- package/src/templates/db-python-alembic-postgres/files/script.py.mako +25 -0
- package/src/templates/db-python-alembic-postgres/fragment.yaml +25 -0
- package/src/templates/db-python-elasticsearch/files/apply_templates.py +55 -0
- package/src/templates/db-python-elasticsearch/files/db-README.md +57 -0
- package/src/templates/db-python-elasticsearch/files/index-template-init.json +25 -0
- package/src/templates/db-python-elasticsearch/files/pyproject.toml +50 -0
- package/src/templates/db-python-elasticsearch/fragment.yaml +19 -0
- package/src/templates/docs-skeleton/files/governance-change-tiers.md +135 -76
- package/src/templates/docs-skeleton/files/governance-database.md +150 -0
- package/src/templates/docs-skeleton/fragment.yaml +3 -0
- package/src/templates/root-files/files/AGENTS.md +35 -17
- package/src/templates/server-python/files/README.md +75 -2
- package/src/templates/server-python/files/app-init.py +11 -1
- package/src/templates/server-python/files/config.py +40 -0
- package/src/templates/server-python/files/main.py +62 -0
- package/src/templates/server-python/files/pyproject.toml +14 -1
- package/src/templates/server-python/files/test_healthz.py +36 -0
- package/src/templates/server-python/fragment.yaml +10 -1
|
@@ -1,133 +1,192 @@
|
|
|
1
1
|
---
|
|
2
|
-
last-reviewed: 2026-05-
|
|
2
|
+
last-reviewed: 2026-05-17
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# 变更分级(Change Tiers)
|
|
6
6
|
|
|
7
7
|
> AGENTS.md §6 的细则。澄清"先文档先契约再 code"在不同场景下应该有多厚。
|
|
8
8
|
|
|
9
|
-
## 0.
|
|
9
|
+
## 0. 两件正交的事,不要绑死
|
|
10
10
|
|
|
11
|
-
`AGENTS.md` §2 的
|
|
11
|
+
`AGENTS.md` §2 的 Contract First 与 §6 的"变更分级"要拆成**两件独立的事**:
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
| 维度 | 是什么 | 谁定 |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| **Tier**(变更影响面) | 改动客观属性:动了哪些层、是否破坏性、有几个团队耦合 | AI 按决策树自动判定 |
|
|
16
|
+
| **Doc Weight**(文档投入) | 团队 / 项目 / 这次 PR 想花多少笔墨在 markdown 上 | AI 给默认建议;PR 作者最终决定 |
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
它们是 **and**,不是 **=**。
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
- **A. 方案讨论必须有书面结论**(载体可大可小)—— 总成立
|
|
21
|
-
- **B. 契约必须在 code 之前冻结**—— 仅当变更触及契约时成立
|
|
20
|
+
20 人银行项目和 2 人工具型 startup 改同一个 API 字段,Tier 都是 3,但前者会写后端设计 + 前端联动说明(Doc Weight = standard),后者只在 PR 描述里写一段(Doc Weight = lite)。框架不强行统一两者。
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
## 1. 六档 Tier(变更影响面)
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
| Tier | 名称 | 典型场景 | 是否动契约 |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| **0** | trivial | 拼写、注释、格式化、补测试、依赖 patch 升级 | 不动 |
|
|
27
|
+
| **1** | bugfix | 修 NPE、错误的 SQL、UI 显示错位(无新行为,行为符合既有契约) | 不动 |
|
|
28
|
+
| **2** | small change | 加按钮 / 排序 / 导出列、调文案、加配置项 | 通常不动 |
|
|
29
|
+
| **3** | contract change | 加 API / 字段 / 错误码 / 事件 / 状态(兼容新增) | **必须**先冻结契约 + CHANGELOG |
|
|
30
|
+
| **4** | architecture / breaking | 跨服务、鉴权变化、删字段、改类型、新依赖、数据迁移 | **必须** ADR + 契约 + 迁移说明 |
|
|
31
|
+
| **5** | spike | 探索性、方案未明 | 在 `spike/*` 分支自由探索;合入 `main` 前补到对应 tier |
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|---|---|---|---|---|
|
|
29
|
-
| **0** | trivial | 拼写、注释、格式化、补测试、依赖 patch 升级 | PR title + 1-2 行描述 | 不动 |
|
|
30
|
-
| **1** | bugfix | 修 NPE、错误的 SQL、UI 显示错位(无新行为) | PR 描述:**重现 + 根因 + 修复点 + 回归测试** | 不动 |
|
|
31
|
-
| **2** | small change | 加按钮 / 排序 / 导出列、调文案、加配置项 | PR 描述(含动机 + 方案 + 影响面),或 1 页 markdown 进 `docs/过程文档/drafts/` | 通常不动 |
|
|
32
|
-
| **3** | contract change | 加 API / 字段 / 错误码 / 事件 / 状态 | 简短设计章节(写在 `docs/04` 或 `docs/05` 的对应模块里)+ contracts 更新 + CHANGELOG | **必须**先冻结契约 |
|
|
33
|
-
| **4** | architecture / breaking | 新模块、跨服务、数据迁移、鉴权模型变化、删除字段 | PRD(若来自需求)→ ADR → 详细设计 → 契约 → code | **必须** ADR + 契约 + 迁移说明 |
|
|
34
|
-
| **5** | spike | 探索性、方案未明 | 在 `spike/*` 分支自由探索 | 合入 `main` 前补齐到对应 tier |
|
|
33
|
+
## 2. Tier 判定决策树
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
按从严到宽问自己:
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
1. 改了 `contracts/` 任何文件? → 至少 **Tier 3**
|
|
38
|
+
2. 改动会改变 API / DB schema / 事件 / 鉴权 / 安全语义?(即使现在 contracts 还没收录) → **Tier 3 或 4**,先补契约再继续
|
|
39
|
+
3. 删除或不兼容地修改了已有契约字段? → **Tier 4** 必须 ADR
|
|
40
|
+
4. 跨服务、跨模块边界、跨执行环境(server↔web↔mobile)? → **Tier 4**
|
|
41
|
+
5. 影响 ops/ 或 deploy/ 实际拓扑(新加 service / 新开端口 / 改加密策略)? → **Tier 4**
|
|
42
|
+
6. 探索 / 调研,方案不清楚? → **Tier 5**(`spike/*` 分支)
|
|
43
|
+
7. 以上都不是,纯局部、可逆的改动? → 按体量定 **Tier 0/1/2**
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
2. **改动会改变 API / DB schema / 事件 / 鉴权 / 安全语义?**(即使现在 contracts 还没收录)→ Tier 3 或 4,**先把契约补上再继续**
|
|
42
|
-
3. **删除或不兼容地修改了已有契约字段?** → Tier 4,**必须** ADR
|
|
43
|
-
4. **跨服务、跨模块边界、跨执行环境(server↔web↔mobile)?** → Tier 4
|
|
44
|
-
5. **会影响 ops/ 或 deploy/ 实际拓扑(新加一个 service / 新开一个端口 / 改加密策略)?** → Tier 4
|
|
45
|
-
6. **是探索 / 调研,方案还不清楚?** → Tier 5(用 `spike/*` 分支)
|
|
46
|
-
7. **以上都不是,纯局部、可逆的改动?** → 按体量定 Tier 0/1/2
|
|
45
|
+
## 3. 三档 Doc Weight(文档投入)
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
> **默认值**:每个 Tier 的"AI 推荐 doc weight"如下,PR 作者可在 PR 模板里覆盖。
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
| Tier | AI 默认推荐 | lite 时只要 | standard 时再加 | full 时再加 |
|
|
50
|
+
|---|---|---|---|---|
|
|
51
|
+
| **0** trivial | **lite**(除非异常) | PR 描述 1-2 行 | — | — |
|
|
52
|
+
| **1** bugfix | **lite** | PR 描述:重现 + 根因 + 修复 + 回归测试 | — | — |
|
|
53
|
+
| **2** small change | **lite** | PR 描述:动机 + 方案 + 影响面 | 1 页 markdown 进 `docs/过程文档/drafts/` | — |
|
|
54
|
+
| **3** contract change | **lite**(关键!) | PR 描述 + 契约 diff + CHANGELOG + 契约锚点 | 简短后端 / 前端设计章节进 `docs/04` 或 `docs/05`,每份 2-3 段 | + PRD(`docs/01/prd-<slug>.md`) |
|
|
55
|
+
| **4** arch / breaking | **standard** | PR 描述 + 契约 diff + CHANGELOG + ADR | 简化 04 / 05 详细设计 + 迁移 / 回滚预案 | + PRD + UI 设计稿(如涉及前端) |
|
|
56
|
+
| **5** spike | **lite**(探索期不需要文档) | spike 分支自由实验;合入 `main` 时按目标 tier 补齐 | — | — |
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|---|---|---|
|
|
54
|
-
| 修 `web/src/utils/format-date.ts` 的 typo 注释 | 0 | 写 PRD |
|
|
55
|
-
| `GET /users/{id}` 的实现里漏判 null,500 改 404 | 1(行为符合契约) | 改 OpenAPI |
|
|
56
|
-
| 给已有列表加"最近 7 天"筛选选项(前端筛选,后端无变化) | 2 | 写 ADR |
|
|
57
|
-
| `package.json` 里 `lodash 4.17.20 → 4.17.21`(patch) | 0 | 走完整升级流程 |
|
|
58
|
-
| 改 README 一段错别字 | 0 | 同步多份治理文件 |
|
|
59
|
-
| 重构一个内部 helper 函数(不导出) | 0 或 1 | 写详细设计 |
|
|
60
|
-
| 加测试覆盖既有功能 | 0 | 写 PRD |
|
|
58
|
+
**关键修正**(相对 0.4.0):**Tier 3 默认 doc weight 是 lite,不是 standard**。理由:契约 diff 本身就是设计真值;额外的中文设计文档反而和契约漂移。只在业务复杂度高到契约说不清时(复杂状态机、多模块交互、跨团队协作),作者主动升 standard / full。
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
### 3.1 lite 的最小载体
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
|---|---|---|
|
|
66
|
-
| 给 `GET /users/{id}` 加返回字段 `lastLoginAt` | 3 | 想成 Tier 2 / 文档"顺手补" |
|
|
67
|
-
| 给已有 List API 加 `?status=` 查询参数 | 3 | 想成 Tier 2 |
|
|
68
|
-
| 把鉴权从 cookie 改为 Bearer token | 4 | 想成 Tier 3 |
|
|
69
|
-
| 把 RBAC 从扁平改为支持继承 | 4 | 想成 Tier 3 |
|
|
70
|
-
| 引入新的消息队列 / 缓存层 / 第三方支付 | 4 | 想成 Tier 3 |
|
|
71
|
-
| 删除 `User.email` 字段 | 4 | 想成 Tier 3(删除 ≠ 兼容新增) |
|
|
72
|
-
| 升级 Spring Boot major 版本(3.x → 4.x) | 4 | 想成 Tier 0(只是版本号) |
|
|
62
|
+
**lite ≠ 没文档**。PR 描述本身就是文档;契约本身就是真值。lite 只是不再要求**额外的 markdown 文件**。
|
|
73
63
|
|
|
74
|
-
|
|
64
|
+
PR 描述至少包含:
|
|
75
65
|
|
|
76
|
-
|
|
66
|
+
- **What**:改了什么
|
|
67
|
+
- **Why**:为什么(业务动机 / 用户痛点 / 技术债)
|
|
68
|
+
- **影响面**:哪些路径 / 服务 / 团队会被影响
|
|
69
|
+
- 如有契约 diff:契约锚点(`contracts/openapi/api.yaml#/paths/~1users/post`)
|
|
70
|
+
- 如是 Tier 1 bugfix:重现步骤 + 根因 + 修复点 + 回归测试
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
- **Tier 3**:必须看到 contracts 同步、CHANGELOG 同步、契约锚点引用
|
|
80
|
-
- **Tier 4**:必须看到 ADR 存在或新增、详细设计文档、迁移 / 回滚预案
|
|
81
|
-
- **Tier 5**:分支必须是 `spike/*`;如果想合入 `main`,作者必须在合入 PR 中标明落地到了哪个 tier
|
|
72
|
+
### 3.2 何时升 standard / full
|
|
82
73
|
|
|
83
|
-
|
|
74
|
+
AI 在以下信号下**主动建议**升级 doc weight,并在 PR 描述里写一句理由:
|
|
84
75
|
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
| 信号 | 建议 |
|
|
77
|
+
|---|---|
|
|
78
|
+
| 契约 diff > 5 个 endpoint / schema 变化 | standard |
|
|
79
|
+
| 引入新状态机或改既有状态机的状态数 | standard |
|
|
80
|
+
| 跨服务联动(server 改 + web 改 + 第三方 webhook 改) | standard |
|
|
81
|
+
| 删字段 / 改类型 / 改鉴权(即 Tier 4) | standard 或 full |
|
|
82
|
+
| 业务规则复杂到契约的 description 字段写不下 | standard |
|
|
83
|
+
| 来源是产品同学的需求文档(PRD 是上游产物) | full(PRD 落到 `docs/01/`) |
|
|
84
|
+
| 跨多团队 / 多季度的项目 | full |
|
|
85
|
+
|
|
86
|
+
PR 作者也可主动**降级**:如果 AI 推荐 standard 但作者认为契约自身已说清楚,可以 lite 通过;reviewer 不应仅因"没写设计文档"而打回。
|
|
87
|
+
|
|
88
|
+
## 4. 反例
|
|
89
|
+
|
|
90
|
+
下面这些情况 **不要** 升级 tier 或 doc weight:
|
|
91
|
+
|
|
92
|
+
| 情形 | 正确 Tier | 推荐 Doc Weight | 错误反应 |
|
|
93
|
+
|---|---|---|---|
|
|
94
|
+
| 修 `web/src/utils/format-date.ts` 的 typo 注释 | 0 | lite | 写 PRD |
|
|
95
|
+
| `GET /users/{id}` 实现里漏判 null,500 改 404 | 1 | lite | 改 OpenAPI |
|
|
96
|
+
| 加"最近 7 天"前端筛选选项(后端无变化) | 2 | lite | 写 ADR |
|
|
97
|
+
| `lodash 4.17.20 → 4.17.21`(patch) | 0 | lite | 走完整升级流程 |
|
|
98
|
+
| 改 README 错别字 | 0 | lite | 同步多份治理文件 |
|
|
99
|
+
| 重构一个内部 helper 函数(不导出) | 0 或 1 | lite | 写详细设计 |
|
|
100
|
+
| 加测试覆盖既有功能 | 0 | lite | 写 PRD |
|
|
101
|
+
| **给 `GET /users/{id}` 加返回字段 `lastLoginAt`**(兼容新增) | **3** | **lite**(只改契约 + CHANGELOG) | 想成必须写 04 后端设计 |
|
|
102
|
+
| **给已有 List API 加 `?status=` 查询参数** | **3** | **lite** | 想成 Tier 2 / 必须写 PRD |
|
|
103
|
+
|
|
104
|
+
下面这些情况 **必须** 升级 tier:
|
|
87
105
|
|
|
88
|
-
|
|
106
|
+
| 情形 | 正确 Tier | 推荐 Doc Weight |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| 把鉴权从 cookie 改为 Bearer token | 4 | standard 或 full |
|
|
109
|
+
| 把 RBAC 从扁平改为支持继承 | 4 | full(PRD + ADR + 详细设计) |
|
|
110
|
+
| 引入新消息队列 / 缓存层 / 第三方支付 | 4 | full |
|
|
111
|
+
| 删除 `User.email` 字段 | 4 | standard(迁移预案 + ADR) |
|
|
112
|
+
| 升级 Spring Boot major 版本(3.x → 4.x) | 4 | standard(兼容性扫描 + 测试矩阵) |
|
|
113
|
+
|
|
114
|
+
## 5. PR 模板里的两个框
|
|
115
|
+
|
|
116
|
+
PR 作者填两件事:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
## Tier(影响面,AI 自动判)
|
|
120
|
+
- [ ] 0 trivial
|
|
121
|
+
- [ ] 1 bugfix
|
|
122
|
+
- [x] 2 small change ← AI 建议
|
|
123
|
+
- [ ] 3 contract change
|
|
124
|
+
- [ ] 4 architecture / breaking
|
|
125
|
+
- [ ] 5 spike
|
|
126
|
+
|
|
127
|
+
## Doc Weight(文档投入,AI 推荐 + 作者覆盖)
|
|
128
|
+
- [x] lite ← AI 推荐:PR 描述足够,不需额外文档
|
|
129
|
+
- [ ] standard
|
|
130
|
+
- [ ] full
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Reviewer 看到 Tier + Doc Weight 后:
|
|
134
|
+
|
|
135
|
+
- **Tier 0/1/2 + lite**:着重看代码 / 测试 / 描述完整性
|
|
136
|
+
- **Tier 3 + lite**:看契约 diff + CHANGELOG + 契约锚点;不要求 04/05 markdown
|
|
137
|
+
- **Tier 3 + standard**:以上 + 简短后端 / 前端设计章节(2-3 段就够)
|
|
138
|
+
- **Tier 3 + full**:以上 + PRD(如有产品需求来源)
|
|
139
|
+
- **Tier 4 + standard**:必须 ADR + 详细设计 + 迁移预案
|
|
140
|
+
- **Tier 4 + full**:以上 + PRD + UI 稿(如涉及)
|
|
141
|
+
|
|
142
|
+
CI 不强制 doc weight 与 tier 的对应关系(reviewer 责任);但 CI **会**校验:
|
|
143
|
+
|
|
144
|
+
- 改了 `contracts/` 必须同改 `contracts/CHANGELOG.md`(已有规则)
|
|
145
|
+
- `spike/*` 分支不能直接合入 `main`(PR 模板 + CODEOWNERS)
|
|
89
146
|
|
|
90
|
-
|
|
147
|
+
## 6. AI 引用义务(按 Tier,doc weight 无关)
|
|
91
148
|
|
|
92
149
|
| Tier | 引用义务 |
|
|
93
150
|
|---|---|
|
|
94
|
-
| 0/1/2 |
|
|
95
|
-
| 3 |
|
|
96
|
-
| 4 | 必须引用 ADR /
|
|
97
|
-
| 5 | 必须标明 spike
|
|
151
|
+
| 0/1/2 | 不强制 |
|
|
152
|
+
| 3 | 必须引用契约锚点(lite 也要) |
|
|
153
|
+
| 4 | 必须引用 ADR + 契约锚点;详细设计在 standard / full 时引用 |
|
|
154
|
+
| 5 | 必须标明 spike 分支与目标 tier |
|
|
98
155
|
|
|
99
|
-
AI
|
|
156
|
+
AI 在 Tier 0/1/2 不要主动制造文档噪音;reviewer 不要因"AI 没引用契约"打回 Tier 0/1/2 的 PR。
|
|
100
157
|
|
|
101
|
-
##
|
|
158
|
+
## 7. 与 spike 的关系
|
|
102
159
|
|
|
103
|
-
`spike/*` 分支是 Tier 5
|
|
160
|
+
`spike/*` 分支是 Tier 5 的载体,**doc weight 默认 lite**:
|
|
104
161
|
|
|
105
162
|
1. 创建 `spike/<topic>` 分支
|
|
106
163
|
2. 自由写代码、跑实验、改方向
|
|
107
164
|
3. 结论清楚后:
|
|
108
165
|
- 不采纳 → 文档进 `docs/过程文档/spike-investigations/`,分支保留备查
|
|
109
|
-
- 采纳 →
|
|
166
|
+
- 采纳 → 反向按目标 Tier 与 Doc Weight 补齐对应内容,再合入 `main`
|
|
110
167
|
|
|
111
|
-
Spike 不是"绕过框架的永久后门"。`spike/*` 不能直接合入 `main
|
|
168
|
+
Spike 不是"绕过框架的永久后门"。`spike/*` 不能直接合入 `main`。
|
|
112
169
|
|
|
113
|
-
##
|
|
170
|
+
## 8. 何时升级 / 降级
|
|
114
171
|
|
|
115
|
-
|
|
172
|
+
**Tier 升级**:开发过程中发现影响面比预想大 → 立即升 tier,停下补对应契约 / 文档。
|
|
173
|
+
**Tier 降级**:通常**不允许**。一旦你声明 Tier 3+ 并写了契约 / ADR / 设计,就保留它(除非改动被裁掉变成 Tier 2)。
|
|
116
174
|
|
|
117
|
-
|
|
175
|
+
**Doc Weight 升级**:欢迎随时升级(写更多文档不是错)。
|
|
176
|
+
**Doc Weight 降级**:作者可在 PR 评审中说明降级理由("契约已自解释"),reviewer 同意即可。
|
|
118
177
|
|
|
119
|
-
##
|
|
178
|
+
## 9. 与契约 SemVer 的关系
|
|
120
179
|
|
|
121
180
|
| Tier | 契约动作 | SemVer 影响 |
|
|
122
181
|
|---|---|---|
|
|
123
182
|
| 0/1/2 | 不动 | 无 |
|
|
124
183
|
| 3(兼容新增) | `MINOR` bump | `0.x.y → 0.(x+1).0`(pre-1.0)/ `x.y.z → x.(y+1).0`(≥1.0) |
|
|
125
|
-
| 3
|
|
184
|
+
| 3(破坏性,但 0.x) | `MINOR` bump + CHANGELOG 标 BREAKING | 同上(pre-1.0 允许) |
|
|
126
185
|
| 4(破坏性,≥1.0) | `MAJOR` bump | `x.y.z → (x+1).0.0` |
|
|
127
186
|
|
|
128
187
|
完整版本策略 → [`../../contracts/README.md`](../../contracts/README.md)。
|
|
129
188
|
|
|
130
|
-
##
|
|
189
|
+
## 10. 关联文档
|
|
131
190
|
|
|
132
191
|
- [`../../AGENTS.md`](../../AGENTS.md) §6(变更分级摘要)
|
|
133
192
|
- [`git-workflow.md`](git-workflow.md)(PR 模板与 CODEOWNERS 完整规则)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
last-reviewed: 2026-05-16
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# 数据库治理
|
|
6
|
+
|
|
7
|
+
> 本文件统一回答:"SQL / 索引 / 迁移 / 种子数据放哪个目录、与 `contracts/` 如何对齐"。
|
|
8
|
+
>
|
|
9
|
+
> 工具与命令的细节(哪个项目用 Knex / Flyway / Alembic / golang-migrate / ES applier)见各项目的 `server/db/README.md`,本文件不重复。
|
|
10
|
+
>
|
|
11
|
+
> 工具决策与 mongodb / sqlite 排除理由见 [`../02-系统方案与架构/adr-0005-database-conventions.md`](../02-系统方案与架构/adr-0005-database-conventions.md)。
|
|
12
|
+
|
|
13
|
+
## 1. 五类 SQL 文件的归属
|
|
14
|
+
|
|
15
|
+
数据库相关的产物分五类,每类只有一个合法位置:
|
|
16
|
+
|
|
17
|
+
| 类型 | 例子 | 归属 | 与契约关系 |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| **schema migration**(DDL,版本化) | `V1__create_users.sql` / `0001_init.py` / `000001_init.up.sql` | `server/db/migrations/`(Java 走 `src/main/resources/db/migration/`) | 与 `contracts/openapi/` 中的字段对齐 |
|
|
20
|
+
| **生产种子数据**(字典 / 码表) | 角色码表、状态枚举、错误码 lookup | `server/db/seeds/prod/`(Knex)/ 写入迁移文件(Flyway / Alembic / golang-migrate) | **真值在 `contracts/dictionaries/`**;当前手动同步 |
|
|
21
|
+
| **开发种子数据**(fixture) | 样例用户、demo 商品、调试数据 | `server/db/seeds/dev/` | 与契约无关;不进生产 |
|
|
22
|
+
| **存储过程 / 函数 / 视图 / 触发器** | `usp_calculate_amount.sql`、物化视图 | `server/db/procedures/` | 写入迁移文件,与代码同等对待 |
|
|
23
|
+
| **运维脚本**(一次性) | 数据回填、重建索引、清理过期数据 | `scripts/db/<date>-<topic>.sql` | 与契约无关;不进生产迁移历史 |
|
|
24
|
+
| **报表 / 分析 query**(BI 看板) | 仪表板背后的 SQL、临时调研 query | `docs/09-数据与埋点/`(启用 data 角色) | 与契约无关;与数据资产对齐 |
|
|
25
|
+
|
|
26
|
+
> Elasticsearch 的"migration"指**幂等的 index-template apply**,不在上述 RDBMS 表里;其归属规则:JSON template 在 `server/db/index-templates/`(Java 走 `src/main/resources/index-templates/`),applier 脚本在 `server/db/`。详见各项目 `server/db/README.md`。
|
|
27
|
+
|
|
28
|
+
## 2. 三类特殊场景
|
|
29
|
+
|
|
30
|
+
### 2.1 跨 service 共享同一个 DB(微服务但 DB 没拆)
|
|
31
|
+
|
|
32
|
+
DB schema 升格为契约:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
contracts/schemas/db/
|
|
36
|
+
├── README.md # 谁是 schema 拥有者("owner service")
|
|
37
|
+
├── ddl/ # 真值;其他 service 视为 read-only
|
|
38
|
+
│ ├── core_tables.sql
|
|
39
|
+
│ └── views.sql
|
|
40
|
+
└── CHANGELOG.md # 改 schema 必须 bump SemVer
|
|
41
|
+
server/apps/owner/db/migrations/ # 唯一执行迁移的 service
|
|
42
|
+
server/apps/consumer/db/ # 不存 DDL,只存 ORM 映射
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
只有 owner service 的 PR 能改 `contracts/schemas/db/ddl/`;consumer service 改 → CI 拒(按 contracts/ 现有规则)。
|
|
46
|
+
|
|
47
|
+
### 2.2 多租户 schema-per-tenant
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
server/db/migrations/
|
|
51
|
+
├── shared/ # 公共 schema(账户、租户元数据)
|
|
52
|
+
└── tenant/ # 应用到每个租户 schema 的迁移
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
文档说清楚"新租户 onboarding 要跑哪些 migrations"。
|
|
56
|
+
|
|
57
|
+
### 2.3 多 database per service
|
|
58
|
+
|
|
59
|
+
例如:postgres 主库 + elasticsearch 用作搜索。
|
|
60
|
+
|
|
61
|
+
- 选第二个 fragment:手动从对应 `db-<backend>-<other>` 复制配置
|
|
62
|
+
- 在 `server/db/README.md` 里说明双库各管什么
|
|
63
|
+
- CI 起两个 service container
|
|
64
|
+
|
|
65
|
+
scaffolder 0.4.0 不自动支持双库;用户合并两个 fragment 的内容。
|
|
66
|
+
|
|
67
|
+
## 3. 与 `contracts/` 的同步规则
|
|
68
|
+
|
|
69
|
+
### 3.1 字典数据 → 生产种子
|
|
70
|
+
|
|
71
|
+
`contracts/dictionaries/enums.yaml` 是字典(角色 / 错误码 / 状态枚举)的真值。改字典的 PR 必须**同步**:
|
|
72
|
+
|
|
73
|
+
- 加字典项 → 同 PR 在迁移文件中加 INSERT IGNORE / ON CONFLICT DO NOTHING
|
|
74
|
+
- 改字典项的 name / description → 写新迁移更新对应行(不要改既有迁移)
|
|
75
|
+
- 删字典项 → Tier 4,需 ADR
|
|
76
|
+
|
|
77
|
+
> 当前是**手动同步**。自动派生(codegen)留给后续 `contract-derived-seeds` 特性。
|
|
78
|
+
|
|
79
|
+
### 3.2 OpenAPI 字段 → DB 列
|
|
80
|
+
|
|
81
|
+
OpenAPI 中的实体字段与 DB 表的列**应当**对齐(同名、同类型映射)。手动维护;governance-lint 不强制(语义 diff 太复杂)。
|
|
82
|
+
|
|
83
|
+
### 3.3 AsyncAPI 事件 → ES index template
|
|
84
|
+
|
|
85
|
+
`contracts/asyncapi/asyncapi.yaml` 中的事件 schema 与 `server/db/index-templates/` 中的 mapping **应当**对齐。当前手动同步。
|
|
86
|
+
|
|
87
|
+
## 4. 改动分级(参见 `change-tiers.md`)
|
|
88
|
+
|
|
89
|
+
| 改动 | Tier | 备注 |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| 新增 migration 加表 / 加字段 | 3 | 同 PR 改 `contracts/CHANGELOG.md`(如果字段进契约) |
|
|
92
|
+
| 修改既有 migration 文件 | **不允许** | 写新 migration 代替;Flyway / Alembic / golang-migrate 都拒绝 |
|
|
93
|
+
| 删字段 / 改类型(破坏性) | 4 | ADR + 详细设计 + 数据迁移预案 |
|
|
94
|
+
| 改 dev seed | 1/2 | 不需要同步契约 |
|
|
95
|
+
| 改 prod seed(字典数据) | 3 | 同 PR 改 `contracts/dictionaries/` |
|
|
96
|
+
| 改 ES index-template 的 mapping | 4 | 破坏性 - 可能需要 reindex |
|
|
97
|
+
| 改 ES index-template 的 priority / settings | 2 | 局部行为调整 |
|
|
98
|
+
| 升级 Knex / Flyway / Alembic / golang-migrate / ES SDK | 2 | 同 PR 改 `tech-stack-server.md` 钉版本 |
|
|
99
|
+
|
|
100
|
+
## 5. CI 行为
|
|
101
|
+
|
|
102
|
+
每个 (backend, database) 组合的 CI 都跑 **migrate up + migrate down** smoke test:
|
|
103
|
+
|
|
104
|
+
- RDBMS:`db-migrate-smoke` job 起 service container,跑 `npm run db:migrate && npm run db:rollback`(或对应工具命令)
|
|
105
|
+
- ES:`db-es-template-apply` job 起 ES service container,跑 applier 脚本一次
|
|
106
|
+
|
|
107
|
+
CI **不**校验:
|
|
108
|
+
- schema 内容(用 DBA tool)
|
|
109
|
+
- 与 `contracts/` 字段对齐(语义 diff 太复杂)
|
|
110
|
+
- 数据回填脚本的正确性(一次性脚本不进 CI)
|
|
111
|
+
|
|
112
|
+
## 6. 目录布局速查(非 multi-app 模式)
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
server/
|
|
116
|
+
├── db/
|
|
117
|
+
│ ├── README.md # 工具与命令(按 backend 不同)
|
|
118
|
+
│ ├── migrations/ # Knex / Alembic / golang-migrate 路径
|
|
119
|
+
│ │ └── <ts/N>_<description>.<ext>
|
|
120
|
+
│ ├── index-templates/ # ES applier 模式
|
|
121
|
+
│ │ └── <ts>_<description>.json
|
|
122
|
+
│ ├── seeds/
|
|
123
|
+
│ │ ├── prod/ # 字典数据;与 contracts/dictionaries 对齐
|
|
124
|
+
│ │ └── dev/ # 仅本地 / 测试
|
|
125
|
+
│ └── apply-templates.{cjs,py,go} # ES applier(按 backend)
|
|
126
|
+
├── src/main/resources/db/migration/ # ← Java + Flyway 的迁移路径(与 server/db/ 分离)
|
|
127
|
+
└── src/main/resources/index-templates/ # ← Java + ES applier 的 template 路径
|
|
128
|
+
|
|
129
|
+
contracts/
|
|
130
|
+
├── dictionaries/enums.yaml # 字典真值(→ prod seed 派生)
|
|
131
|
+
├── openapi/api.yaml # API 字段(→ DB 列对齐)
|
|
132
|
+
└── asyncapi/asyncapi.yaml # 事件 schema(→ ES mapping 对齐)
|
|
133
|
+
|
|
134
|
+
scripts/db/ # 一次性运维(数据回填等)
|
|
135
|
+
└── 2026-05-backfill-tenants.sql
|
|
136
|
+
|
|
137
|
+
ops/db/ # DB 实例 / 权限 / 备份(IaC)
|
|
138
|
+
└── grants/
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 7. multi-app 模式
|
|
142
|
+
|
|
143
|
+
每个 `server/apps/<app>/` 自己一份 `db/`。共享 schema 时(多 app 同 DB)schema 真值进 `contracts/schemas/db/`,由 owner app 唯一执行迁移。完整规则与示例见 §2.1。
|
|
144
|
+
|
|
145
|
+
## 8. 不在本特性范围内的(推到下次 spec)
|
|
146
|
+
|
|
147
|
+
- mongodb 支持(详见 ADR-0005)
|
|
148
|
+
- sqlite 支持(详见 ADR-0005)
|
|
149
|
+
- contracts/dictionaries → seed migration 自动派生
|
|
150
|
+
- web/mobile/miniapp 本地数据库(IndexedDB / SQLite / Realm)
|
|
@@ -117,6 +117,9 @@ files:
|
|
|
117
117
|
- from: files/governance-change-tiers.md
|
|
118
118
|
to: docs/governance/change-tiers.md
|
|
119
119
|
render: false
|
|
120
|
+
- from: files/governance-database.md
|
|
121
|
+
to: docs/governance/database.md
|
|
122
|
+
render: false
|
|
120
123
|
- from: files/governance-checklists.md
|
|
121
124
|
to: docs/governance/checklists.md
|
|
122
125
|
render: true
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
| `.claude/` | AI | Claude Code slash-commands |
|
|
46
46
|
<% } %>
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
<% if (it.options.database !== 'none') { %>> **数据库相关产物**(已启用 `database=<%= it.options.database %>`):`server/db/`(迁移、种子<% if (it.options.database === 'elasticsearch') { %>、ES index template<% } %>、运维脚本入口)的归属规则见 [`docs/governance/database.md`](docs/governance/database.md)。<% if (it.options.backend === 'java') { %> Java + <%= it.options.database === 'elasticsearch' ? 'spring-data-elasticsearch' : 'Flyway' %> 因 Spring Boot classpath 约定,<%= it.options.database === 'elasticsearch' ? 'index template' : '迁移' %>文件实际在 `server/src/main/resources/<%= it.options.database === 'elasticsearch' ? 'index-templates/' : 'db/migration/' %>`。<% } %>
|
|
49
|
+
|
|
50
|
+
<% } %>### 1.1 单应用 vs 多应用模式
|
|
49
51
|
|
|
50
52
|
每个执行环境目录(`server/` `web/` `mobile/` `miniapp/` `agent/`)默认处于**单应用模式**。需要容纳第二个应用时切换到**多应用模式**:
|
|
51
53
|
|
|
@@ -138,31 +140,45 @@
|
|
|
138
140
|
- 完整规则 → [`docs/governance/integrations.md`](docs/governance/integrations.md)
|
|
139
141
|
<% } %>
|
|
140
142
|
|
|
141
|
-
## 6.
|
|
143
|
+
## 6. 核心协作规则(变更分级 + 文档投入)
|
|
144
|
+
|
|
145
|
+
变更走**两个独立维度**:**Tier**(影响面,AI 自动判)+ **Doc Weight**(文档投入,AI 推荐 + 作者覆盖)。完整判定决策树、反例、与 SemVer 关系 → [`docs/governance/change-tiers.md`](docs/governance/change-tiers.md)。
|
|
142
146
|
|
|
143
|
-
|
|
147
|
+
**Tier(影响面)**
|
|
144
148
|
|
|
145
|
-
| Tier | 典型 |
|
|
146
|
-
|
|
147
|
-
| 0 trivial | typo / 格式化 / patch 升级 / 补测试 |
|
|
148
|
-
| 1 bugfix | 修 NPE / SQL / UI 错位(无新行为) |
|
|
149
|
-
| 2 small | 加按钮 / 排序 / 文案 / 配置项 |
|
|
150
|
-
| 3 contract | 加 API / 字段 / 错误码 / 事件 / 状态 |
|
|
151
|
-
| 4 arch | 跨服务 / 鉴权变化 / 删字段 / breaking |
|
|
152
|
-
| 5 spike | 探索 / 方案未明 | `spike/*`
|
|
149
|
+
| Tier | 典型 | 是否动契约 |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| 0 trivial | typo / 格式化 / patch 升级 / 补测试 | 不动 |
|
|
152
|
+
| 1 bugfix | 修 NPE / SQL / UI 错位(无新行为) | 不动 |
|
|
153
|
+
| 2 small | 加按钮 / 排序 / 文案 / 配置项 | 通常不动 |
|
|
154
|
+
| 3 contract | 加 API / 字段 / 错误码 / 事件 / 状态 | **必须**先冻结契约 + CHANGELOG |
|
|
155
|
+
| 4 arch | 跨服务 / 鉴权变化 / 删字段 / breaking | **必须** ADR + 契约 + 迁移说明 |
|
|
156
|
+
| 5 spike | 探索 / 方案未明 | `spike/*` 分支自由探索;合入前补到对应 tier |
|
|
153
157
|
|
|
154
158
|
**判定**:改 `contracts/` → 至少 Tier 3;改鉴权 / 跨服务 / 删字段 → Tier 4;纯局部 → 0/1/2;探索 → 5。
|
|
155
159
|
|
|
156
|
-
**AI
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
**Doc Weight(文档投入,AI 推荐 + 作者覆盖)**
|
|
161
|
+
|
|
162
|
+
| Tier | AI 默认推荐 | lite 时 | standard 加 | full 加 |
|
|
163
|
+
|---|---|---|---|---|
|
|
164
|
+
| 0/1/2 | **lite** | PR 描述(含动机 / 方案 / 影响面) | — | — |
|
|
165
|
+
| 3 contract | **lite**(关键) | PR 描述 + 契约 diff + CHANGELOG + 锚点 | 简短 04 / 05 设计(2-3 段) | + PRD(`docs/01/prd-<slug>.md`) |
|
|
166
|
+
| 4 arch | **standard** | PR 描述 + 契约 + ADR | 简化 04 / 05 + 迁移 / 回滚预案 | + PRD + UI 稿 |
|
|
167
|
+
| 5 spike | **lite** | spike 分支自由实验 | — | — |
|
|
168
|
+
|
|
169
|
+
> **关键**:Tier 3 的默认 doc weight 是 **lite**——契约 diff 本身就是设计真值,额外的中文设计文档反而易和契约漂移。复杂度高时(多状态机、跨服务、跨团队)作者主动升 standard / full。
|
|
170
|
+
|
|
171
|
+
**AI 引用义务**(按 Tier,与 Doc Weight 无关):
|
|
172
|
+
- Tier 0/1/2:PR 描述自身即方案记录,**不强制**引用契约 / ADR
|
|
173
|
+
- Tier 3+:commit / PR 必须显式引用契约锚点(如 `contracts/openapi/api.yaml#/paths/~1users/post`)
|
|
174
|
+
- Tier 4:必须引用 ADR;详细设计在 standard / full 时引用
|
|
160
175
|
|
|
161
176
|
其他:
|
|
162
|
-
- `spike/*` 分支允许暂时跳过契约(即 Tier 5);合入 `main`
|
|
177
|
+
- `spike/*` 分支允许暂时跳过契约(即 Tier 5);合入 `main` 前必须补到对应 tier
|
|
163
178
|
- 完整 PR 模板与 CODEOWNERS → [`docs/governance/git-workflow.md`](docs/governance/git-workflow.md)
|
|
164
179
|
- 契约 SemVer / CHANGELOG / 废弃流程 → [`contracts/README.md`](contracts/README.md)
|
|
165
180
|
|
|
181
|
+
|
|
166
182
|
## 7. 按需加载索引
|
|
167
183
|
|
|
168
184
|
### 7.1 路径触发表
|
|
@@ -176,7 +192,8 @@
|
|
|
176
192
|
| `docs/assets/**` 或根 `.gitattributes` | `docs/governance/assets.md` |
|
|
177
193
|
| `ops/**` 或 `deploy/**` | `docs/governance/deploy-ops.md`、`docs/governance/security.md` |
|
|
178
194
|
| `tools/**` 或 `scripts/**` | `docs/governance/tools-scripts.md` |
|
|
179
|
-
<% if (it.options.
|
|
195
|
+
<% if (it.options.database !== 'none') { %>| `server/db/**`(迁移 / 种子 / ES template / applier) | `docs/governance/database.md`、`contracts/dictionaries/`(如改字典 seed) |
|
|
196
|
+
<% } %><% if (it.options.ci === 'gitee') { %>| `.gitee/**` | `docs/governance/ci.md`、`docs/governance/security.md` |
|
|
180
197
|
<% } else { %>| `.github/**` | `docs/governance/ci.md`、`docs/governance/security.md` |
|
|
181
198
|
<% } %>
|
|
182
199
|
|
|
@@ -205,6 +222,7 @@
|
|
|
205
222
|
| ops / deploy 完整规则 | [`docs/governance/deploy-ops.md`](docs/governance/deploy-ops.md) |
|
|
206
223
|
| tools / scripts 完整规则 | [`docs/governance/tools-scripts.md`](docs/governance/tools-scripts.md) |
|
|
207
224
|
| 变更分级(六档 Tier) | [`docs/governance/change-tiers.md`](docs/governance/change-tiers.md) |
|
|
225
|
+
| 数据库目录 / 迁移工具 / SQL 归属 | [`docs/governance/database.md`](docs/governance/database.md) |
|
|
208
226
|
| 完整 checklist | [`docs/governance/checklists.md`](docs/governance/checklists.md) |
|
|
209
227
|
| 治理细则索引 | [`docs/governance/README.md`](docs/governance/README.md) |
|
|
210
228
|
|
|
@@ -1,4 +1,77 @@
|
|
|
1
1
|
# server/
|
|
2
2
|
|
|
3
|
-
Python backend for **<%= it.options.projectName
|
|
4
|
-
|
|
3
|
+
Python backend for **<%= it.options.projectName %>**, built on **FastAPI**.
|
|
4
|
+
|
|
5
|
+
> Contract First:路由 / 请求体 / 响应体应当与 [`../contracts/openapi/api.yaml`](../contracts/openapi/api.yaml) 对齐。新增端点的工作流见根 `AGENTS.md` §6(变更分级)+ `docs/governance/change-tiers.md`:端点新增 / 字段新增是 Tier 3,必须先冻结 contracts 再写实现。
|
|
6
|
+
|
|
7
|
+
## 目录布局
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
server/
|
|
11
|
+
├── pyproject.toml # 依赖钉版本、ruff / mypy / pytest 配置
|
|
12
|
+
├── app/
|
|
13
|
+
│ ├── __init__.py # re-export `app` 给 `python -m app`
|
|
14
|
+
│ ├── main.py # FastAPI 实例 + /healthz + CORS
|
|
15
|
+
│ └── config.py # pydantic-settings;从环境 / .env 读配置
|
|
16
|
+
└── tests/
|
|
17
|
+
└── test_healthz.py # ASGI smoke test
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 工具与版本
|
|
21
|
+
|
|
22
|
+
| 项 | 值 |
|
|
23
|
+
|---|---|
|
|
24
|
+
| Python | 3.11+ |
|
|
25
|
+
| Framework | FastAPI `0.115.5` |
|
|
26
|
+
| ASGI server | uvicorn `0.32.0` |
|
|
27
|
+
| Validation | pydantic `2.9.2` + pydantic-settings `2.6.1` |
|
|
28
|
+
| Lint / format | ruff `0.6.8+` |
|
|
29
|
+
| Type check | mypy `1.11.0+`(strict-ish) |
|
|
30
|
+
| Test | pytest `8.3.0+` + pytest-asyncio + httpx |
|
|
31
|
+
|
|
32
|
+
版本钉死见 `pyproject.toml`,并镜像到 `docs/03-工程规范与研发基础设施/tech-stack-server.md`。governance-lint 检测两边漂移并阻断 PR。
|
|
33
|
+
|
|
34
|
+
## 常用命令
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# 创建虚拟环境 + 装依赖
|
|
38
|
+
python -m venv .venv && source .venv/bin/activate
|
|
39
|
+
pip install -e ".[dev]"
|
|
40
|
+
|
|
41
|
+
# 本地开发(热加载)
|
|
42
|
+
uvicorn app.main:app --reload --port 8000
|
|
43
|
+
# 浏览自动生成的 OpenAPI UI:http://127.0.0.1:8000/docs
|
|
44
|
+
|
|
45
|
+
# 测试 / lint / format / typecheck
|
|
46
|
+
pytest -q
|
|
47
|
+
ruff check .
|
|
48
|
+
ruff format --check .
|
|
49
|
+
mypy .
|
|
50
|
+
|
|
51
|
+
# 安全扫描
|
|
52
|
+
pip-audit
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 配置
|
|
56
|
+
|
|
57
|
+
环境变量优先级:CLI / 容器注入 > `.env` 文件 > `app/config.py` 默认值。
|
|
58
|
+
|
|
59
|
+
| 变量 | 默认 | 说明 |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `APP_NAME` | `<projectName>-server` | 显示在 OpenAPI title |
|
|
62
|
+
| `APP_VERSION` | `0.1.0` | 显示在 OpenAPI version |
|
|
63
|
+
| `CORS_ALLOW_ORIGINS` | `["http://localhost:5173","http://localhost:3000"]` | 逗号分隔;生产环境收紧 |
|
|
64
|
+
|
|
65
|
+
## 部署
|
|
66
|
+
|
|
67
|
+
打包 / 镜像 / 流水线归 `deploy/` 与 `ops/`,详见 [`../docs/governance/deploy-ops.md`](../docs/governance/deploy-ops.md)。最小生产命令示例:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 与契约的同步
|
|
74
|
+
|
|
75
|
+
- API 端点:`contracts/openapi/api.yaml` → `app/main.py` 路由;改契约同 PR 改实现
|
|
76
|
+
- 字典 / 枚举:`contracts/dictionaries/enums.yaml`(如启用)→ Pydantic Enum
|
|
77
|
+
- 错误码:`contracts/errors/error-codes.yaml` → Exception → HTTP status 映射
|
|
@@ -1 +1,11 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""<%= it.options.projectName %>-server.
|
|
2
|
+
|
|
3
|
+
Application package. Entry point: app.main:app
|
|
4
|
+
Run locally: `uvicorn app.main:app --reload`
|
|
5
|
+
|
|
6
|
+
Contract First:路由实现见 contracts/openapi/api.yaml;新端点先改契约再写代码。
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .main import app
|
|
10
|
+
|
|
11
|
+
__all__ = ["app"]
|