games-development-ai/contracts/game-artifact-manifest.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

108 lines
5.3 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://wanxiang.ai/contracts/game-artifact-manifest.schema.json",
"title": "GameArtifactManifest",
"description": "具体游戏版本的对象存储索引。它不是 GamePackage/1 运行时 manifest运行时仍读取同一版本前缀下的 manifest.json状态由 game_runtime_package.status 管理。实际游戏内容只存 MinIO/S3。",
"type": "object",
"additionalProperties": false,
"allOf": [
{
"if": {
"properties": {
"sourceRevision": {
"properties": { "provider": { "const": "tier2_source_project" } }
}
}
},
"then": {
"properties": { "packageType": { "const": "phaser" } }
}
}
],
"required": [
"schemaVersion",
"tenantId",
"gameId",
"versionId",
"packageType",
"keyPrefix",
"sourceRevision",
"runtimeManifest",
"objects",
"totals",
"assetHash",
"bundleHash",
"manifestHash"
],
"properties": {
"schemaVersion": { "const": "GameArtifactManifest/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]*$" },
"versionId": { "description": "project.game_version.id 的十进制字符串", "type": "string", "pattern": "^[1-9][0-9]*$" },
"packageType": { "type": "string", "enum": ["phaser", "littlejs", "canvas"] },
"keyPrefix": { "type": "string", "pattern": "^tenants/[A-Za-z0-9][A-Za-z0-9._-]*/games/[1-9][0-9]*/versions/[1-9][0-9]*$" },
"sourceRevision": {
"description": "源工程由既有 Tier2 SourceProjectStore 或引擎无关 GameSourceArchive 持有;运行制品只绑定其不可变身份,不复制源文件。",
"type": "object",
"additionalProperties": false,
"required": ["provider", "gameId", "revisionId", "manifestRef", "sourceHash", "objects", "bytes"],
"properties": {
"provider": { "type": "string", "enum": ["tier2_source_project", "game_source_archive"] },
"gameId": { "type": "string", "minLength": 1, "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$" },
"revisionId": { "type": "string", "minLength": 1, "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$" },
"manifestRef": { "type": "string", "minLength": 1, "maxLength": 1024, "pattern": "^(tier2-source-project|game-source-archive):[^:]+:[^:]+$" },
"sourceHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
"objects": { "type": "integer", "minimum": 1, "maximum": 10000 },
"bytes": { "type": "integer", "minimum": 1 }
}
},
"runtimeManifest": {
"description": "现有 GamePackage/1 manifest.json 的稳定对象身份;不能把 artifact-manifest.json 当作该运行时清单。",
"type": "object",
"additionalProperties": false,
"required": ["store", "key", "sourcePath", "bytes", "sha256", "mime"],
"properties": {
"store": { "const": "artifact", "type": "string" },
"key": { "type": "string", "minLength": 1 },
"sourcePath": { "type": "string", "minLength": 1, "pattern": "^(?!/)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*\\\\).+$" },
"bytes": { "type": "integer", "minimum": 0, "maximum": 104857600 },
"sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
"mime": { "type": "string", "minLength": 1 }
}
},
"objects": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["category", "store", "path", "sourcePath", "key", "bytes", "sha256", "mime"],
"properties": {
"category": { "type": "string", "enum": ["asset", "runtime", "evidence"] },
"store": { "type": "string", "enum": ["artifact", "evidence"] },
"path": { "type": "string", "minLength": 1, "pattern": "^(assets|runtime|evidence)/[^/].*" },
"sourcePath": { "type": "string", "minLength": 1, "pattern": "^(?!/)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*\\\\).+$" },
"key": { "type": "string", "minLength": 1, "pattern": "^tenants/.+/games/[1-9][0-9]*/versions/[1-9][0-9]*/(assets|runtime|evidence)/[^/].*" },
"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", "assetBytes", "runtimeBytes", "evidenceBytes"],
"properties": {
"objects": { "type": "integer", "minimum": 0 },
"bytes": { "type": "integer", "minimum": 0 },
"assetBytes": { "type": "integer", "minimum": 0 },
"runtimeBytes": { "type": "integer", "minimum": 0 },
"evidenceBytes": { "type": "integer", "minimum": 0 }
}
},
"assetHash": { "description": "SHA-256(GameArtifactTreeHash/1\\0 + canonical JSON entries)", "type": "string", "pattern": "^[a-f0-9]{64}$" },
"bundleHash": { "type": ["string", "null"], "pattern": "^[a-f0-9]{64}$" },
"manifestHash": { "description": "SHA-256(GameArtifactManifest/1\\0 + 去除 manifestHash 后的 UTF-8、NFC 路径、键排序紧凑 JSON)", "type": "string", "pattern": "^[a-f0-9]{64}$" }
}
}