games-development-ai/contracts/game-source-archive.schema.json
lili 17727d08c3
Some checks failed
contract-gates / contract-gates (push) Has been cancelled
docs-gate / docs-gate (push) Has been cancelled
feat(storage): 接入游戏内容对象存储与运行时提交门
冻结 GameArtifactManifest/GameSourceArchive 契约和 V34 pending/committed 状态记录,增加专用 writer 的全量回读物化校验,并让 Runtime API 在消费和发布前对账 committed、GamePackage checksum 与实际 engineBundle hash。隔离 staging 已验证真实消费拒绝未提交版本;源码桶权限仍保持 fail-closed,正式金标不切换。
2026-07-29 12:02:22 -07:00

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}$"
}
}
}