跳转至

English

Recipe:领域无关的契约对象校验

1. 场景与非场景

适用:需要校验一份文档是否符合 Foundation 已登记的契约对象(如 project-manifest),按方言选择校验策略。

不适用:需要校验消费者自有业务 Schema(消费者应自行持有,Foundation 不取代);需要把领域语义校验混入通用契约。

Quickstart Profile v2 是单独的 candidate 路径。消费者仍拥有业务 Schema;Engineering Kit 只在构建阶段把显式 Schema 集合编译成按 $id 查询的离线 validator,不接管 method 到 Schema 的选择。

2. 架构选择及能力 ID

首选能力:foundation.contracts.object-validationvalidateDocument / compileSchema / detectDialect)。纯 Ajv 实现,支持 draft-07 与 2020-12。

3. 前置条件与信任边界

  • 待校验文档带有已登记契约对象的 $id
  • 信任边界:validateDocument 永不修改调用者输入;规范化副本只在结果 data 字段返回。

4. 最小代码

import { validateDocument } from "skill-family-contracts";

const document = {
  schemaVersion: 1,
  kind: "skill-family.project-manifest",
  project: { id: "my-project", name: "My Project", description: "Example" },
  contracts: { version: "1.0.0", profile: "generic" },
  managedFiles: ["package.json"],
  updatedAt: "2026-01-01T00:00:00Z",
};

const result = validateDocument(document, {
  schemaId: "https://contracts.skill-family.example/v1/project-manifest.json",
  dialect: "2020-12",
});
if (!result.valid) console.error(result.errorCode);

以上代码展示了用 $id 指定目标 Schema 并取回 { valid, errorCode, errors, data }

5. 预期输出与证据

校验通过时 result.valid 为 true;失败时 errorCodeSFC1001 等稳定码。证据:packages/skill-family-contracts/test/validator.test.mjstest/schemas.test.mjs

6. 安全/失败负例

// 负例:未知 $id -> 返回 valid:false,errorCode = SFC1002 (UNKNOWN_SCHEMA_ID)
const bad = validateDocument(document, {
  schemaId: "https://contracts.skill-family.example/v1/does-not-exist.json",
  dialect: "2020-12",
});
// 不抛异常,返回结构化结果:
// { valid: false, errorCode: "SFC1002",
//   errors: [{ message: "unknown schema $id: https://contracts.skill-family.example/v1/does-not-exist.json" }] }
if (!bad.valid) console.error(bad.errorCode); // SFC1002

7. 可复制验证命令

node --test packages/skill-family-contracts/test/validator.test.mjs \
           packages/skill-family-contracts/test/schemas.test.mjs

8. 调用方继续拥有的业务逻辑

  • 具体业务字段的语义解释。
  • 领域级校验规则(不在 Foundation 通用契约内)。

9. 升级与回滚注意事项

  • 契约权威版本 CONTRACTS_VERSION = 1.4.0,npm 包版本 0.3.0 并行,不混用。
  • 错误码冻结不漂移;Schema 变更作为新的合同版本任务进行,不就地改冻结内容。
  • candidate v2 必须精确锁定 0.3.0;仍需 v1 的接入继续精确锁定 0.2.1。