@antprofuse/saddle-db-design 0.1.1 → 0.1.3

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/SKILL.md CHANGED
@@ -40,6 +40,10 @@ description: 在 Saddle 后端研发前,从已编译 Islands Spec 设计可追
40
40
  - 每张表固定使用 `uid`、`gmt_create`、`gmt_modified`、`is_deleted` 四个系统列;业务 Agent 不增删或改写其语义。
41
41
  - 所有业务字段允许 `NULL`,且不设置数据库默认值。必填、枚举、值域、业务唯一性和关联完整性由 Saddle 业务逻辑负责。
42
42
  - 不设计业务唯一约束、普通索引或数据库外键。索引属于运行后的观测与运维优化。
43
- - 实体关联字段保留 Structure 的关联业务语义,值存储目标实体 `uid`。同一目标的多重关联依靠原始角色语义区分,例如卖家与买家。
43
+ - 实体关联字段保留 Structure 的关联业务语义;内部关联存目标 uid,external 关联存可长期解析的外部身份引用,不强制本地 UUID。多重关联依靠原始角色语义区分。不得为制造 uid 而给 external 实体建表,也不要求业务 Spec 定义技术编码。
44
+ - varchar 使用已确认的长度分档;人民币金额沿用有符号 BIGINT 分存储,不沿用 API 的元字符串作为物理列类型。
45
+ - 文章正文等长文本可使用 `type: {kind: text}`,对应 MySQL TEXT,不填写 length。仍需真实 Structure 字段来源、nullable 为 true 且无默认值;TEXT 不是无限容量,也不用于绕过不明确的结构化建模。具体容量边界见类型参考。
46
+ - 新版 Flow 使用真实板块/节点记录 Logic、Branch 访问责任,也覆盖 Visual 的持久读取;不虚构旧 Paragraph/Transaction。已传入 Row 的纯内存消费不等于再次读库。
44
47
  - 删除统一为软删除。Saddle 数据访问层必须对普通读取强制过滤 `is_deleted = false`;业务查询不得各自实现这条规则。
48
+ - 把业务状态更新为“已删除”仍是 update,不等于实体 delete,不自动联动 is_deleted。
45
49
  - 一个不完整实体只阻塞对应表,不阻塞其他完整表的交付。
@@ -35,10 +35,10 @@ columns:
35
35
  comment: 替换为字段业务语义。
36
36
  source: {entity: 替换为字段声明实体, field: 替换为Structure字段名}
37
37
  accessResponsibilities:
38
- - transaction:
39
- paragraph: 替换为段落
40
- branch: 替换为分支
41
- transactionId: 替换为事务ID
38
+ - source:
39
+ kind: logic
40
+ board: 替换为板块
41
+ node: 替换为Logic节点
42
42
  operations:
43
43
  - kind: read
44
44
  columns: [替换为Structure字段名]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antprofuse/saddle-db-design",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "从 Islands Spec 设计可追溯的 Saddle 逻辑数据库表契约。",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "files": ["SKILL.md", "agents", "assets", "references"],
@@ -54,9 +54,10 @@ columns:
54
54
  source: {entity: 用户账单, field: 所属用户}
55
55
  storesEntityUid: {entity: 用户}
56
56
  应缴金额:
57
- type: {kind: decimal, precision: 18, scale: 2}
57
+ type: {kind: bigint}
58
58
  nullable: true
59
- comment: 应缴金额,单位为人民币元
59
+ comment: 应缴金额,单位为人民币分
60
+ money: {currency: CNY, unit: minor, minorUnitsPerMajor: 100}
60
61
  source: {entity: 用户账单, field: 应缴金额}
61
62
  accessResponsibilities:
62
63
  - transaction:
@@ -120,7 +121,7 @@ source: {entity: 用户账单, field: 账单状态}
120
121
 
121
122
  所有业务列固定 `nullable: true`,不允许 `default` 或 `onUpdate`。Structure 的必填、枚举和值域仍是业务规则,由 Saddle 逻辑校验,不下沉为数据库约束。
122
123
 
123
- 关联字段保留原始业务角色名,并存储目标实体的 `uid`:
124
+ 内部实体关联保留原始业务角色名,并存储目标实体的 `uid`:
124
125
 
125
126
  ```yaml
126
127
  卖家:
@@ -137,12 +138,26 @@ source: {entity: 用户账单, field: 账单状态}
137
138
 
138
139
  同一目标实体被多次关联时,以 Structure 中不同的关联角色区分。不得改成含义不清的统一“用户”列,也不建立数据库外键。
139
140
 
141
+ external 关联使用 `storesExternalReference`,与 `storesEntityUid` 互斥:
142
+
143
+ ```yaml
144
+ 户号:
145
+ type: {kind: varchar, length: 256}
146
+ nullable: true
147
+ comment: 可长期解析的外部户号身份,包含区分机构和费种的身份语义。
148
+ source: {entity: 户号绑定关系, field: 户号}
149
+ storesExternalReference: {entity: 户号}
150
+ ```
151
+
152
+ 目标必须是真实 external 实体。引用必须跨请求持续定位同一外部身份,不强制本地 UUIDv7,不用可能重名的展示字段代替身份,不把有失效期的 API 令牌直接作为长期关联。长度是引用实现必须遵守的存储上界;不能静默截断,也不能宣称未知编码已经验证可用。具体编码和解析由实现层承担,出现冲突反馈讨论,不要求业务 Spec 表达技术细节。不因此新增本地映射表或 external 镜像表。
153
+
140
154
  ## 基础 MySQL 类型
141
155
 
142
156
  v1 只允许以下封闭类型:
143
157
 
144
158
  ```yaml
145
159
  {kind: varchar, length: 64}
160
+ {kind: text}
146
161
  {kind: bigint}
147
162
  {kind: decimal, precision: 18, scale: 2}
148
163
  {kind: boolean}
@@ -150,14 +165,27 @@ v1 只允许以下封闭类型:
150
165
  {kind: datetime, precision: 3}
151
166
  ```
152
167
 
153
- - `varchar.length` 必须是正整数,并有 Structure 值域、编码上界或已确认业务约束;不得任意统一为 255。
168
+ - `varchar.length` 默认采用已确认的64/256/1024档:标识符、编码、户号文本、枚举64;名称256;地址1024。明确的项目约定优先。外部复合身份引用不是裸户号文本,应按已确认编码预算选档;例如 bill 的用户引用64、户号引用256。内部 uid 固定32。不要求 Spec 精确给出数据库长度;超出已选上界或需要新类型时讨论,不静默截断。
154
169
  - `bigint` 固定生成 MySQL 64 位有符号整数。
170
+ - `text` 对应 MySQL `TEXT`,类型节点仅为 `{kind: text}`,不允许 length、precision 或 scale。适用于文章正文等有明确业务含义的长文本,不强制按 varchar 的长度分档。最大容量为 65,535 字节而非字符数,可容纳字符数取决于数据库字符集;环境字符集仍由运维负责,不新增实例配置。业务长度与内容格式由业务逻辑处理,不生成数据库约束,不静默截断。明确超过 TEXT 容量时反馈讨论,不自动升级 MEDIUMTEXT/LONGTEXT。依据:[MySQL 字符串类型](https://dev.mysql.com/doc/refman/8.4/en/string-type-syntax.html)。
171
+ - TEXT 字段继续使用 `nullable: true`、无数据库默认值和原始 Structure 字段来源。仅选择存储类型,不擅自规定正文是纯文本、HTML 或 Markdown,也不因正文可能很长而另拆表、增加索引或生成 DDL。不能用 TEXT 序列化未知对象来绕过未支持的结构或关联。
155
172
  - `decimal` 必须明确 precision、scale 和单位;精度与小数位来自 Structure/Rule。
173
+ - 人民币金额使用有符号 `bigint` 保存分,附加 `money: {currency: CNY, unit: minor, minorUnitsPerMajor: 100}`;与 API 的元精确十进制字符串在应用边界准确换算,不使用二进制浮点数。非负等业务值域仍由业务逻辑负责。其他币种或需要不足一分的精度时先讨论,不套用人民币比例。没有本地金额字段时不为使用此规则新增字段或表。
156
174
  - `boolean` 固定生成 MySQL `TINYINT(1)`,但契约保留布尔业务语义。
157
175
  - `date` 表示业务日期。
158
176
  - `datetime` 必须明确 precision;系统时间列固定为 3。
159
177
  - 枚举使用能够容纳全部合法值的 `varchar`;合法值由业务逻辑校验,不生成数据库 ENUM 或 CHECK。
160
- - JSON、TEXT、BLOB、浮点数、TIMESTAMP、数据库 ENUM、生成列等不在 v1 中;确定需要时产出 `unsupported-shape` finding。
178
+ - JSON、TINYTEXTMEDIUMTEXT、LONGTEXT、BLOB、浮点数、TIMESTAMP、数据库 ENUM、生成列等不在 v1 中;确定需要时产出 `unsupported-shape` finding。
179
+
180
+ 长文本业务列示例(只在输入确有此字段时使用,不是要求所有表增加正文):
181
+
182
+ ```yaml
183
+ 文章内容:
184
+ type: {kind: text}
185
+ nullable: true
186
+ comment: 文章正文内容
187
+ source: {entity: 文章, field: 文章内容}
188
+ ```
161
189
 
162
190
  ## 数据库约束边界
163
191
 
@@ -194,14 +222,30 @@ transaction:
194
222
 
195
223
  系统列生成、时间维护和默认软删除过滤是 Saddle 固定责任,不在每个 operation 中重复列出。
196
224
 
225
+ ### 新版 Flow 与 Visual 来源
226
+
227
+ 每项责任用 `transaction`(旧结构)或 `source`(新结构)之一,不能同时填写。新版 source 支持:
228
+
229
+ ```yaml
230
+ source: {kind: logic, board: 查询欠费单, node: 替换为新户号绑定}
231
+ source: {kind: branch, board: 查询欠费单, node: 校验户号绑定}
232
+ source: {kind: visualRead, page: 查询户号, read: $本人绑定列表}
233
+ ```
234
+
235
+ 节点类型必须与来源一致;名字通过编译元数据或稳定源码身份解析,不保存数组下标。责任覆盖当前持久查询和写入,不把每个页面对已传入 Row 的内存读取都编造为独立数据库查询;API 引用解析需要的按 uid 加载属于运行时实现责任,不能虚构 Spec 事务。
236
+
237
+ Logic 责任可附 `atomic: true` 表示来源明确要求该节点的多项操作同一事务提交,不代表整条 API 链路或外部调用具备原子性。更新传入 Row 时 operation 可附 `targetInput: 当前绑定`:必须对应该节点真实 Row 入参,通过其实体身份定位目标行;不把 uid 塞入业务 predicateColumns,也不把空 predicateColumns 解释为全表更新。新建行及同节点后续赋值可以合为一个 insert 责任,但必须包含全部赋值列。
238
+
239
+ Spec 把业务状态写为“已删除”时,记录 update 和相应业务列,不推导额外的 is_deleted 更新。只有实体 delete 语义才执行统一软删除。
240
+
197
241
  ## 完成门禁
198
242
 
199
243
  1. 实体已证明为 Saddle 内部持久化实体,且不是 `external: true`;
200
244
  2. 文件名、`table.name` 和 Structure 实体身份原样一致;
201
245
  3. 表包含固定且完整的四个系统列;
202
246
  4. 全部 Structure 字段均出现,且每个业务列解析到唯一 Structure 字段;
203
- 5. 关联字段明确存储目标实体 `uid`,多重关联角色无歧义;
247
+ 5. 内部关联声明 storesEntityUid;external 关联声明 storesExternalReference,引用稳定且长度明确;两者互斥,多重关联角色无歧义;
204
248
  6. 类型参数完整,全部业务字段 nullable 且无默认值;
205
- 7. 每个 Logic 事务身份可解析,字段访问责任完整;
249
+ 7. 每个旧事务或新版 Flow/Visual 来源身份可解析,字段访问责任完整;更新传入Row时目标身份明确;
206
250
  8. 不存在业务唯一约束、普通索引、外键、物理映射、TODO、占位符或诊断节点;
207
251
  9. 交付目录中不存在本 Skill 生成的 findings、DDL、迁移脚本或 `structure.sql`。
@@ -1,6 +1,6 @@
1
1
  # DB 设计 Findings v1
2
2
 
3
- 当 Islands Spec v1 格式无法支持完整表契约时,报告 DB finding。Finding 是过程诊断,不是正式 DB 交付物,也不授权 Agent 创建临时字段、宽泛类型、冗余表或物理约束绕过问题。
3
+ 当 Islands Spec 的业务表达无法支持完整表契约时,报告 DB finding。Skill 自身的格式问题由 lead 修复,不伪装为 Spec 问题;技术编码、长度选档和外部引用实现问题也不要求业务 Spec 补字段。Finding 是过程诊断,不是正式 DB 交付物,也不授权 Agent 创建临时字段、宽泛类型、冗余表或物理约束绕过问题。
4
4
 
5
5
  DB 交付目录只放完整的 `*.table.yaml`。用户指定过程协作位置时,可在那里写入 `db-design-findings.yaml`;未指定时直接向用户反馈,不自行在交付目录或其他仓库落盘。
6
6