@antprofuse/saddle-skill 0.3.1 → 0.3.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
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: saddle-service-0-3
3
- description: 使用 Saddle 0.3.1 Skill 开发或审查带 profusegw 固定入口和 profusecontract 强类型外部函数调用的 Rust 业务应用。用于定义 protobuf 契约、声明强类型业务配置、编写固定 ProfuseGwContext 四参数 handler、以框架响应映射业务拒绝和技术失败,或运行正式业务门禁。
3
+ description: 使用 Saddle 0.3.3 Skill 开发或审查带 profusegw 固定入口和 profusecontract 强类型外部函数调用的 Rust 业务应用。用于定义 protobuf 契约、声明强类型业务配置、编写固定 ProfuseGwContext 四参数 handler、以框架响应映射业务拒绝和技术失败,或运行正式业务门禁。
4
4
  ---
5
5
 
6
- # Saddle 0.3.1 业务研发契约
6
+ # Saddle 0.3.3 业务研发契约
7
7
 
8
8
  业务 Agent 的直接输入只有业务 spec 与本 Skill。不要要求用户阅读 Saddle 仓库、审计报告、组件提交或内部实现。
9
9
 
@@ -29,7 +29,7 @@ description: 使用 Saddle 0.3.1 Skill 开发或审查带 profusegw 固定入口
29
29
 
30
30
  ```toml
31
31
  [dependencies]
32
- saddle-framework = "=0.3.1"
32
+ saddle-framework = "=0.3.3"
33
33
  ```
34
34
 
35
35
  `saddle-framework` 是唯一业务 facade。业务不得直接依赖 `saddle-core`、`saddle-admission`、`saddle-boundary`、`saddle-db`、`saddle-macros`、`saddle-observability`、`saddle-runtime` 或 `saddle-service`。
@@ -40,7 +40,7 @@ saddle-framework = "=0.3.1"
40
40
  - profusegw 唯一入口是 `POST /saddle/v1/ingress/profusegw/invoke`;不得手写 listener、HTTP handler 或第二路由。
41
41
  - 应用声明唯一字面量 `deployment_app`;请求 `target.app` 必须逐字匹配。每个字面量 `target.interfaceId` 只由静态 `operation_type` 分派,业务 handler 不读取或自行路由它。
42
42
  - profusegw body 固定且只含 `target`、`profuseGwContext`、`requestData`;`profuseGwContext.userInfo.userId` 由框架形成 `ProfuseGwContext { user_id }`,业务 payload 不得覆盖。
43
- - 每个应用必须声明 `business_config Type;`,每个 handler 的第四参数必须是同一 `BusinessConfig<Type>`。有配置应用从 [完整配置样例](assets/saddle-configured.toml) 起步;没有业务配置时唯一写法是 `business_config ();`,使用 [无业务配置样例](assets/saddle-unit.toml),`saddle.toml` 省略 `[business]`,测试只使用受控 `BusinessConfig::unit()`。
43
+ - 每个应用必须声明 `business_config Type;`,每个 handler 的第四参数必须是同一 `saddle::BusinessConfig<Type>`。有配置应用从 [完整配置样例](assets/saddle-configured.toml) 起步;没有业务配置时唯一写法是 `business_config ();`,使用 [无业务配置样例](assets/saddle-unit.toml),`saddle.toml` 省略 `[business]`,测试只使用受控 `saddle::BusinessConfig::unit()`。禁止旧模块路径。
44
44
  - 所有 handler 使用 `saddle::ingress::ProfuseGwContext`;只读取正式 API 提供的只读、有界字段,不得读取 Header、Cookie、原始 JSON 或任意上下文 Map。有效 ingress traceId 原样继承,每次外部调用派生 child rpcId;业务不得解析或重写 opaque trace/rpc identity。
45
45
  - 固定调用上下文协议见 [trace/LDC 模板](assets/saddle_call_context.proto):trace 只有 `trace_id/rpc_id`,LDC 只有 `zone/idc/env`。业务请求和结果不得重复这些上下文字段。
46
46
  - 所有 handler 直接返回 `saddle::ingress::ProfuseGwResponse<Data, Code>`。成功只形成 `Success { data }`;失败只形成 `Failure { failure: { code, message } }`。
@@ -55,7 +55,9 @@ saddle-framework = "=0.3.1"
55
55
  - 业务只使用生成的应用级强类型 capability,不接触 channel、stub、裸 protobuf bytes、动态函数名或通用依赖容器。
56
56
  - 不支持 contract 多版本路由、`Any`、开放 Map、任意 JSON、streaming、cancel 或框架自动业务重试。
57
57
  - 不创建线程、第二 Runtime、后台 task、裸 DB/网络 I/O、日志 subscriber 或第二执行面。
58
- - profusecontract 部署只接受 `[framework].profusecontractAuthorityTemplate`:值为一个 `http://host:port` plaintext authority,可含唯一 `{zone}` 占位;不得携带 URL path、凭据、TLS、服务发现或 per-call endpoint。业务 handler 不读取该配置。
58
+ - 唯一配置入口是一个 `saddle.toml`,进程唯一参数为 `--config <path>`。生产启动使用绝对路径,例如 `target/release/my-app --config /etc/my-app/saddle.toml`;`--config saddle.toml` `--config ./saddle.toml` 也合法,均相对当前工作目录定位文件,文件内相对路径则相对该配置文件所在目录解析。
59
+ - profusecontract 部署只接受 `[framework.profusecontract].authority`:值为一个固定 `http://host:port` plaintext authority,或含唯一 `{zone}` 占位的模板;不得携带 URL path、凭据、TLS、服务发现或 per-call endpoint。业务 handler 不读取该配置。
60
+ - 配置在 listener 建立前一次解析、校验、解析 secret 环境引用并冻结。普通配置不接受环境变量覆盖;secret 只能通过 `[secrets]` 明确声明的环境变量名注入。未知字段、缺失必填字段、类型错误、secret 缺失、数据库 secret/mapping 配置不成对或相对路径非法均须 fail-fast。
59
61
 
60
62
  ## 立即停止
61
63
 
@@ -68,6 +70,7 @@ saddle-framework = "=0.3.1"
68
70
  - handler 返回 Rust `Result`/`Err`、空成功、任意 JSON,或业务自建第二响应结构;
69
71
  - 业务拒绝或任一技术失败组合没有显式映射,机器码不稳定,或 `FailureMessage` 超过 256 bytes;
70
72
  - 出现旧响应字段、顶层 code/message 或任何旧协议兼容叙述;
71
- - Cargo 不是精确 `=0.3.1` Rust facade、缺 lock,或正式 Gate 不通过。
73
+ - Cargo 不是精确 `=0.3.3` Rust facade、缺 lock,或正式 Gate 不通过。
74
+ - 出现旧扁平 authority 长键或旧配置类型模块路径。
72
75
 
73
76
  停止时只交最小复现和期望业务表达,由 Saddle 修复公共能力缺口。
@@ -1,4 +1,4 @@
1
1
  interface:
2
2
  display_name: "Saddle 0.3 业务应用"
3
3
  short_description: "使用 Saddle 0.3 开发受控边界的 Rust 业务应用"
4
- default_prompt: "请安装 Saddle 0.3.1 Skill(npm install --save-exact --ignore-scripts --no-audit --no-fund @antprofuse/saddle-skill@0.3.1),结合业务 spec 开始研发。"
4
+ default_prompt: "请安装 Saddle 0.3.3 Skill(npm install --save-exact --ignore-scripts --no-audit --no-fund @antprofuse/saddle-skill@0.3.3),结合业务 spec 开始研发。"
@@ -1,6 +1,8 @@
1
1
  [framework]
2
2
  listen = "127.0.0.1:39101"
3
- profusecontractAuthorityTemplate = "http://127.0.0.{zone}:39102"
3
+
4
+ [framework.profusecontract]
5
+ authority = "http://127.0.0.{zone}:39102"
4
6
 
5
7
  [secrets]
6
8
 
@@ -0,0 +1,15 @@
1
+ [framework]
2
+ listen = "0.0.0.0:8080"
3
+
4
+ [framework.profusecontract]
5
+ authority = "http://profusecontract-{zone}.internal:50051"
6
+
7
+ [secrets]
8
+ databaseUrlEnv = "SADDLE_DATABASE_URL"
9
+
10
+ [database]
11
+ mappingDir = "mappings"
12
+
13
+ [business]
14
+ region = "cn-prod"
15
+ dataPath = "data"
@@ -1,5 +1,7 @@
1
1
  [framework]
2
2
  listen = "127.0.0.1:39101"
3
- profusecontractAuthorityTemplate = "http://127.0.0.{zone}:39102"
3
+
4
+ [framework.profusecontract]
5
+ authority = "http://127.0.0.{zone}:39102"
4
6
 
5
7
  [secrets]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@antprofuse/saddle-skill",
3
- "version": "0.3.1",
4
- "description": "Saddle 0.3.1 中文 AI Coding 研发契约与业务门禁。",
3
+ "version": "0.3.3",
4
+ "description": "Saddle 0.3.3 中文 AI Coding 研发契约与业务门禁。",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "files": ["SKILL.md", "agents", "references", "scripts", "assets"],
7
7
  "bin": {"saddle-03-gate": "scripts/saddle-03-gate.js"},
@@ -46,7 +46,7 @@ Saddle 在编译期从 `contract_dir` 确定性递归收集 `.proto`,闭合 im
46
46
 
47
47
  ## 阶段 3:Rust 实现
48
48
 
49
- 业务 crate 精确使用 `saddle-framework = "=0.3.1"`,然后按 [最小编程模型](programming-model.md) 编写固定 `deployment_app`、显式 `business_config`、静态 operation 声明和四参数 handler。不得直接依赖任何 Saddle 中间件 crate。
49
+ 业务 crate 精确使用 `saddle-framework = "=0.3.3"`,然后按 [最小编程模型](programming-model.md) 编写固定 `deployment_app`、显式 `business_config`、静态 operation 声明和四参数 handler。不得直接依赖任何 Saddle 中间件 crate。
50
50
 
51
51
  实现通过 Gate 后,按 [本地联调](local-integration.md) 由外部 harness 注入唯一 plaintext profusecontract authority,并以固定 profusegw body 验证真实 typed call。endpoint、request/call identity 和 deadline 都是框架或部署输入,不写入业务 spec。
52
52
 
@@ -63,6 +63,6 @@ Saddle 在编译期从 `contract_dir` 确定性递归收集 `.proto`,闭合 im
63
63
  - 缺少固定 `deployment_app`,或 app/interfaceId/endpoint 被做成动态业务输入;
64
64
  - 技术失败码或执行确定性存在 catch-all/default;
65
65
  - 需要裸 gRPC/channel/bytes、第二入口、动态 descriptor 或未声明外部 I/O;
66
- - `saddle-framework` 不是精确 `=0.3.1`,或 [正式 Gate](validation.md) 失败。
66
+ - `saddle-framework` 不是精确 `=0.3.3`,或 [正式 Gate](validation.md) 失败。
67
67
 
68
68
  停止产物只包含最小复现、缺失身份和期望业务表达,不包含中间件替代实现。
@@ -15,7 +15,7 @@
15
15
  - `puc` 是业务单元,例如 `puc`。
16
16
  - `function` 是契约原始函数名,允许中文,例如 `查询用户绑定户号`。
17
17
  - protobuf method、Rust 方法和 Java 方法使用各语言合法的本地标识符;它们不是跨系统身份。
18
- - 0.3.1 不定义 contract version、多版本路由、翻译表、alias 或 fallback。
18
+ - 0.3.3 不定义 contract version、多版本路由、翻译表、alias 或 fallback。
19
19
 
20
20
  ## 定义步骤
21
21
 
@@ -82,4 +82,4 @@ message BoundAccount {
82
82
 
83
83
  ## 变更规则
84
84
 
85
- 先修改共同契约目录并重新通过双方 conformance,再修改两侧实现。禁止两侧各自维护近似定义后人工对齐;0.3.1 遇到不兼容变化时停止并共同升级,不在运行时并存或猜测版本。
85
+ 先修改共同契约目录并重新通过双方 conformance,再修改两侧实现。禁止两侧各自维护近似定义后人工对齐;0.3.3 遇到不兼容变化时停止并共同升级,不在运行时并存或猜测版本。
@@ -27,14 +27,25 @@ profusegw 只向固定路径发送通用 JSON body;业务接口不新增 URL
27
27
 
28
28
  固定 HTTP profile 是 `POST /saddle/v1/ingress/profusegw/invoke` 与 `application/json`。本地 harness 必须给出受控 request identity、call identity 和绝对 deadline;不要在业务 handler 中构造它们。
29
29
 
30
- ## 唯一 plaintext endpoint
30
+ ## 正式启动与唯一配置
31
31
 
32
- 0.3.1 部署配置只接受 `saddle.toml` 的正式键 `[framework].profusecontractAuthorityTemplate`。有业务配置的完整最小文件是 [saddle-configured.toml](../assets/saddle-configured.toml),`business_config ();` 应用使用不含 `[business]` 的 [saddle-unit.toml](../assets/saddle-unit.toml)。例如:
32
+ 先构建 release 制品,再以前台进程启动:
33
+
34
+ ```bash
35
+ cargo +1.95.0 build --release --locked
36
+ target/release/my-saddle-app --config /etc/my-saddle-app/saddle.toml
37
+ ```
38
+
39
+ 生产推荐传绝对配置路径。`--config saddle.toml` 与 `--config ./saddle.toml` 也合法,它们都相对进程当前工作目录定位配置文件;配置中的 `mappingDir` 和业务 `resolve_path()` 则相对 `saddle.toml` 所在目录解析。进程只接受这一对参数,不从默认位置搜索、不合并多文件、不热更新。
40
+
41
+ 0.3.3 部署配置只接受 `[framework.profusecontract].authority`。有业务配置的完整最小文件是 [saddle-configured.toml](../assets/saddle-configured.toml),`business_config ();` 应用使用不含 `[business]` 的 [saddle-unit.toml](../assets/saddle-unit.toml):
33
42
 
34
43
  ```toml
35
44
  [framework]
36
45
  listen = "127.0.0.1:39101"
37
- profusecontractAuthorityTemplate = "http://127.0.0.{zone}:39102"
46
+
47
+ [framework.profusecontract]
48
+ authority = "http://127.0.0.{zone}:39102"
38
49
 
39
50
  [secrets]
40
51
 
@@ -43,9 +54,17 @@ region = "cn-test"
43
54
  dataPath = "fixtures/data"
44
55
  ```
45
56
 
46
- 键值必须是 `http` plaintext 的 `host:port`,可选且只能出现受控 `{zone}` 模板;模板用同一请求的 LDC zone 在连接前解析。不得包含其他模板、path、query、fragment、userinfo、凭据或动态函数信息。键缺失、近似键、缺失或非法 zone 都必须 fail-fast,禁止普通环境变量 fallback。所有强类型函数共享这一部署级连接目标;线上 gRPC method 固定为 `ProfuseContractBoundary/Invoke`,应用不得按函数配置 endpoint。
57
+ 字段合同:
58
+
59
+ - `[framework].listen`:必填字符串、无默认值,格式为可解析的 `IP:port`,决定实际 ProfuseGW bind 地址。
60
+ - `[framework.profusecontract].authority`:必填字符串、无默认值;必须是 plaintext `http://host:port` 固定地址,或只含一个 `{zone}` 的模板。模板由同一请求的 LDC zone 在调用前解析;禁止 path、query、fragment、userinfo、凭据和其他模板。
61
+ - `[secrets].databaseUrlEnv`:仅数据库应用使用;值是必填环境变量的名称,不是连接串本身。启动时该环境变量必须存在且有效。
62
+ - `[database].mappingDir`:仅数据库应用使用;必须和 `databaseUrlEnv` 同时出现,指向相对配置文件目录的映射目录。数据库模板见 [saddle-database.toml](../assets/saddle-database.toml)。
63
+ - `[business]`:仅 `business_config Type;` 应用使用;字段由该强类型 `Type` 决定,没有框架默认值。字段缺失、额外或类型错误均拒绝。`business_config ();` 必须省略整节。
64
+
65
+ 所有配置在 listener 建立前一次解析和冻结。普通字段不能由环境变量覆盖;secret 只能通过 `[secrets]` 中明确声明的环境变量引用注入。文件不可读、未知/旧键、缺失字段、类型错误、非法 bind/authority、secret 缺失、数据库配置不完整或映射目录非法都必须 fail-fast,并返回稳定的 `saddle.process.*` 错误码。
47
66
 
48
- endpoint 是部署输入,不进入业务 spec、request 或 handler。TLS、鉴权、服务发现、负载均衡和生产凭据不属于 0.3.1;需要其中任一能力时立即停止,不得在业务 crate 自建 client。
67
+ authority 是部署输入,不进入业务 spec、request 或 handler。TLS、鉴权、服务发现、负载均衡和生产凭据不属于 0.3.3;需要其中任一能力时立即停止,不得在业务 crate 自建 client。
49
68
 
50
69
  ## 联调完成条件
51
70
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 应用显式声明
4
4
 
5
- 业务应用使用 `saddle-framework = "=0.3.1"` 的公开编程面:
5
+ 业务应用使用 `saddle-framework = "=0.3.3"` 的公开编程面:
6
6
 
7
7
  ```rust
8
8
  saddle::application! {
@@ -53,7 +53,7 @@ async fn query_my_bound_accounts(
53
53
  request: QueryMyBoundAccountsRequest,
54
54
  context: saddle::ingress::ProfuseGwContext,
55
55
  contract: PucProfuseContract,
56
- config: saddle::config::BusinessConfig<BusinessSettings>,
56
+ config: saddle::BusinessConfig<BusinessSettings>,
57
57
  ) -> saddle::ingress::ProfuseGwResponse<QueryMyBoundAccountsResult, BusinessCode>;
58
58
  ```
59
59
 
@@ -73,7 +73,7 @@ business_config ();
73
73
 
74
74
  此时 `saddle.toml` 省略 `[business]`,测试 harness 传入 `BusinessConfig::unit()`。有配置时使用 `business_types!` 声明封闭类型,并在 `saddle.toml` 的单一 `[business]` 表中提供值;不得使用动态 Map、普通环境变量覆盖或多文件 merge。
75
75
 
76
- 完整配置从 [有配置模板](../assets/saddle-configured.toml) 复制;无业务配置从 [unit 模板](../assets/saddle-unit.toml) 复制。两者都必须在 `[framework]` 中显式写 `profusecontractAuthorityTemplate`,不能改成 `profusecontractAuthority`、endpoint 环境变量或其他近似键。有配置模板的 `region/dataPath` 对应示例 `BusinessSettings`;实际字段必须与应用声明的强类型配置逐字一致。
76
+ 完整配置从 [有配置模板](../assets/saddle-configured.toml) 复制;无业务配置从 [unit 模板](../assets/saddle-unit.toml) 复制;使用数据库时从 [数据库模板](../assets/saddle-database.toml) 复制相关两节。三者都只在 `[framework.profusecontract]` 中写 `authority`。禁止旧长键、近似键或 endpoint 环境变量。有配置模板的 `region/dataPath` 对应示例 `BusinessSettings`;实际字段必须与应用声明的强类型配置逐字一致。公开配置类型路径只有 `saddle::BusinessConfig`,禁止旧模块路径。
77
77
 
78
78
  生成的强类型 async 调用必须等待结果,并分别处理完成结果与技术失败:
79
79
 
@@ -1,4 +1,4 @@
1
- # Saddle 0.3.1 Skill 正式业务 Gate
1
+ # Saddle 0.3.3 Skill 正式业务 Gate
2
2
 
3
3
  ## 依赖与锁
4
4
 
@@ -12,7 +12,7 @@ edition = "2024"
12
12
  rust-version = "1.95"
13
13
 
14
14
  [dependencies]
15
- saddle-framework = "=0.3.1"
15
+ saddle-framework = "=0.3.3"
16
16
  ```
17
17
 
18
18
  在允许访问正式 registry 的依赖准备阶段生成并提交 `Cargo.lock`。禁止 `path`、`git`、`[patch]`、source replacement 或宽松 Saddle 版本。
@@ -25,16 +25,16 @@ saddle-framework = "=0.3.1"
25
25
  npx --no-install saddle-03-gate --manifest-path Cargo.toml
26
26
  ```
27
27
 
28
- 命令由已安装的 `@antprofuse/saddle-skill@0.3.1` 提供,不需要 Saddle 源码仓库。它会检查:
28
+ 命令由已安装的 `@antprofuse/saddle-skill@0.3.3` 提供,不需要 Saddle 源码仓库。它会检查:
29
29
 
30
30
  - facade 精确版本、禁止直接中间件依赖和 Cargo source 旁路;
31
- - `Cargo.lock` 中 boundary、db、framework、macros、observability、runtime、service 七包统一精确映射 `0.3.1`;
31
+ - `Cargo.lock` 中 admission、boundary、core、db、framework、macros、observability、runtime、service 九包统一精确映射 `0.3.3`;
32
32
  - 唯一 `contract_dir`、目录存在、禁止旧单文件 contract 声明;
33
33
  - 目录根部 `saddle_external_function.proto` 与 Skill 权威模板逐字一致且仅出现一次,使用 option 的业务 proto 必须 direct import 根文件;
34
34
  - 编译期递归扫描/import 闭包、option-only 索引、身份唯一、请求结果类型匹配,以及所有 function 均有实际 `uses`;
35
35
  - 固定 `ProfuseGwContext`、应用声明、八类技术失败与三种 certainty 均被显式引用;
36
36
  - `application/2` 显式 `business_config Type`(无配置为 `()`),handler 四参数接收同型冻结 `BusinessConfig<Type>`;
37
- - 部署配置使用唯一正式键 `[framework].profusecontractAuthorityTemplate`;有配置与 unit 应用分别使用 Skill 的完整样例,unit 文件不得出现 `[business]`;
37
+ - 部署配置使用唯一正式键 `[framework.profusecontract].authority`;有配置与 unit 应用分别使用 Skill 的完整样例,unit 文件不得出现 `[business]`;旧长键与旧配置类型模块路径均拒绝;
38
38
  - handler 直接返回框架 `ProfuseGwResponse`,应用声明封闭 `response_code`,业务码实现 `ProfuseGwCode` 并注册无碰撞稳定机器码;
39
39
  - 失败只使用 `ProfuseGwFailure { code, FailureMessage }`,拒绝旧字段、重复分类、顶层 code/message、Rust `Result`/`Err`、第二响应外壳、任意 JSON、无界展示文案、空成功及技术失败 wildcard/default;
40
40
  - 唯一字面量 `deployment_app`、静态 `operation_type`,并拒绝业务代码读取或动态路由 `target.app/interfaceId`;
@@ -30,8 +30,8 @@ if (/^\s*\[(patch|replace)\b/m.test(cargo) || /\b(path|git|branch|tag)\s*=/.test
30
30
  stop("DEPENDENCY_SOURCE", "禁止 path/git/patch/replace 依赖旁路");
31
31
  }
32
32
  const facade = cargo.match(/^\s*saddle-framework\s*=\s*(.+)$/m);
33
- if (!facade || !/^"=0\.3\.1"\s*(?:#.*)?$/.test(facade[1].trim())) {
34
- stop("SADDLE_VERSION", '必须直接且精确依赖 saddle-framework = "=0.3.1"');
33
+ if (!facade || !/^"=0\.3\.3"\s*(?:#.*)?$/.test(facade[1].trim())) {
34
+ stop("SADDLE_VERSION", '必须直接且精确依赖 saddle-framework = "=0.3.3"');
35
35
  }
36
36
  const internals = ["saddle-core","saddle-admission","saddle-boundary","saddle-db","saddle-macros","saddle-observability","saddle-runtime","saddle-service"];
37
37
  for (const name of internals) {
@@ -41,11 +41,11 @@ if (!fs.existsSync(lockPath)) {
41
41
  stop("LOCK", "缺少 Cargo.lock");
42
42
  } else {
43
43
  const lock = fs.readFileSync(lockPath, "utf8");
44
- const publicClosure = ["saddle-boundary", "saddle-db", "saddle-framework", "saddle-macros", "saddle-observability", "saddle-runtime", "saddle-service"];
44
+ const publicClosure = ["saddle-admission", "saddle-boundary", "saddle-core", "saddle-db", "saddle-framework", "saddle-macros", "saddle-observability", "saddle-runtime", "saddle-service"];
45
45
  for (const name of publicClosure) {
46
46
  const escaped = name.replaceAll("-", "\\-");
47
- if (!new RegExp(`name = "${escaped}"\\nversion = "0\\.3\\.1"`).test(lock)) {
48
- stop("LOCK", `Cargo.lock 未绑定 ${name} 0.3.1`);
47
+ if (!new RegExp(`name = "${escaped}"\\nversion = "0\\.3\\.3"`).test(lock)) {
48
+ stop("LOCK", `Cargo.lock 未绑定 ${name} 0.3.3`);
49
49
  }
50
50
  }
51
51
  }
@@ -67,18 +67,18 @@ if (!fs.existsSync(configPath)) {
67
67
  } else {
68
68
  const config = fs.readFileSync(configPath, "utf8");
69
69
  let section = "";
70
- const authorityTemplates = [];
70
+ const authorities = [];
71
71
  for (const line of config.split(/\r?\n/)) {
72
72
  const header = line.match(/^\s*\[([^\]]+)\]\s*(?:#.*)?$/);
73
73
  if (header) { section = header[1]; continue; }
74
- const authority = line.match(/^\s*profusecontractAuthorityTemplate\s*=\s*"([^"]+)"\s*(?:#.*)?$/);
75
- if (authority && section === "framework") authorityTemplates.push(authority[1]);
74
+ const authority = line.match(/^\s*authority\s*=\s*"([^"]+)"\s*(?:#.*)?$/);
75
+ if (authority && section === "framework.profusecontract") authorities.push(authority[1]);
76
76
  }
77
- if (authorityTemplates.length !== 1 || !/^http:\/\/[^"/]+:\d+$/.test(authorityTemplates[0])) {
78
- stop("AUTHORITY_TEMPLATE", "[framework] 必须显式配置合法 profusecontractAuthorityTemplate");
77
+ if (authorities.length !== 1 || !/^http:\/\/[^"/]+:\d+$/.test(authorities[0])) {
78
+ stop("AUTHORITY_TEMPLATE", "[framework.profusecontract] 必须显式配置合法 authority");
79
79
  }
80
- if (/^\s*(?:profusecontractEndpointEnv|profusecontractAuthority)\s*=/m.test(config)) {
81
- stop("AUTHORITY_TEMPLATE", "禁止旧 endpoint/近似 authority 配置键");
80
+ if (/^\s*(?:profusecontractAuthorityTemplate|profusecontractEndpointEnv|profusecontractAuthority)\s*=/m.test(config)) {
81
+ stop("AUTHORITY_TEMPLATE", "禁止旧长键或近似 authority 配置键");
82
82
  }
83
83
  const unitConfig = /\bbusiness_config\s+\(\)\s*;/.test(source);
84
84
  const hasBusinessTable = /^\s*\[business\]\s*$/m.test(config);
@@ -89,6 +89,7 @@ if (!fs.existsSync(configPath)) {
89
89
  if (!source.includes("application!")) stop("APPLICATION", "缺少 Saddle application! 声明");
90
90
  if (!/\bbusiness_config\s+(?:\(\)|[A-Za-z_][A-Za-z0-9_:<>]*)\s*;/.test(source)) stop("BUSINESS_CONFIG", "application/2 必须显式声明 business_config 类型或 ()");
91
91
  if (!source.includes("BusinessConfig")) stop("BUSINESS_CONFIG", "handler 必须接收冻结 BusinessConfig");
92
+ if (source.includes("saddle::config::BusinessConfig")) stop("BUSINESS_CONFIG", "公开类型路径必须是 saddle::BusinessConfig");
92
93
  if (!source.includes("ProfuseGwContext")) stop("CONTEXT", "handler 必须使用固定 ProfuseGwContext");
93
94
  if (!source.includes("ProfuseGwResponse")) stop("RESPONSE", "handler 必须直接返回框架 ProfuseGwResponse");
94
95
  if (!source.includes("ProfuseGwCode")) stop("RESPONSE_CODE", "业务码必须实现 ProfuseGwCode");
@@ -174,4 +175,4 @@ try {
174
175
  fs.rmSync(target, {recursive: true, force: true});
175
176
  }
176
177
  if (process.exitCode) process.exit(process.exitCode);
177
- process.stdout.write("SADDLE_03_GATE PASS; SKILL=0.3.1; RUST=0.3.1; CLOSED_RESPONSE; CLOSED_CODES; FAILURE_MESSAGE_256; FAILURE_8X3; LOCKED_OFFLINE\n");
178
+ process.stdout.write("SADDLE_03_GATE PASS; SKILL=0.3.3; RUST=0.3.3; CLOSED_RESPONSE; CLOSED_CODES; FAILURE_MESSAGE_256; FAILURE_8X3; LOCKED_OFFLINE\n");