冻结 GameArtifactManifest/GameSourceArchive 契约和 V34 pending/committed 状态记录,增加专用 writer 的全量回读物化校验,并让 Runtime API 在消费和发布前对账 committed、GamePackage checksum 与实际 engineBundle hash。隔离 staging 已验证真实消费拒绝未提交版本;源码桶权限仍保持 fail-closed,正式金标不切换。
104 lines
3.3 KiB
JSON
104 lines
3.3 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://wanxiang.ai/contracts/game-source-archive.schema.json",
|
|
"title": "GameSourceArchive",
|
|
"description": "引擎无关的游戏源工程对象清单。源代码和源配置进入独立 game-sources 桶;运行包、发布素材和验收证据仍由 GameArtifactManifest/1 管理。",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"schemaVersion",
|
|
"tenantId",
|
|
"gameId",
|
|
"revisionId",
|
|
"engine",
|
|
"keyPrefix",
|
|
"objects",
|
|
"totals",
|
|
"sourceHash",
|
|
"manifestHash"
|
|
],
|
|
"properties": {
|
|
"schemaVersion": { "const": "GameSourceArchive/1", "type": "string" },
|
|
"tenantId": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
},
|
|
"gameId": {
|
|
"description": "project.game_project.id 的十进制字符串。",
|
|
"type": "string",
|
|
"pattern": "^[1-9][0-9]*$"
|
|
},
|
|
"revisionId": {
|
|
"description": "源工程不可变修订标识,不承载路径分隔符。",
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
},
|
|
"engine": {
|
|
"description": "生产源工程使用的引擎或宿主描述,只作元数据,不把非 Phaser 游戏伪装成 Tier2。",
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 64,
|
|
"pattern": "^[A-Za-z0-9][A-Za-z0-9._+-]*$"
|
|
},
|
|
"keyPrefix": {
|
|
"type": "string",
|
|
"pattern": "^tenants/[A-Za-z0-9][A-Za-z0-9._-]*/games/[1-9][0-9]*/source-revisions/[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
},
|
|
"objects": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"maxItems": 10000,
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["path", "sourcePath", "key", "bytes", "sha256", "mime"],
|
|
"properties": {
|
|
"path": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"pattern": "^source/[^/].*"
|
|
},
|
|
"sourcePath": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"pattern": "^(?!/)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*\\\\).+$"
|
|
},
|
|
"key": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"pattern": "^tenants/.+/games/[1-9][0-9]*/source-revisions/[A-Za-z0-9][A-Za-z0-9._-]*/source/[^/].*"
|
|
},
|
|
"bytes": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 104857600
|
|
},
|
|
"sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
|
|
"mime": { "type": "string", "minLength": 1 }
|
|
}
|
|
}
|
|
},
|
|
"totals": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["objects", "bytes"],
|
|
"properties": {
|
|
"objects": { "type": "integer", "minimum": 0, "maximum": 10000 },
|
|
"bytes": { "type": "integer", "minimum": 1 }
|
|
}
|
|
},
|
|
"sourceHash": {
|
|
"description": "SHA-256(GameSourceArchiveTreeHash/1\\0 + 按 NFC 路径排序的 path/bytes/sha256 规范 JSON)。",
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]{64}$"
|
|
},
|
|
"manifestHash": {
|
|
"description": "SHA-256(GameSourceArchive/1\\0 + 去除 manifestHash 后的规范 JSON)。",
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]{64}$"
|
|
}
|
|
}
|
|
}
|