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