games-development-ai/contracts/game-artifact-manifest.schema.json
lili a513ae38fd
Some checks failed
contract-gates / contract-gates (push) Has been cancelled
docs-gate / docs-gate (push) Has been cancelled
fix(storage): harden source authorization and committed CAS
Provision the isolated game-source writer path, bind source uploads to
GameSourceArchive manifests, and require every immutable storage field for
pending-to-committed CAS. Reuse the gate-validated runtime manifest snapshot,
normalize remote storage errors, and record the staging object/CAS evidence.
2026-07-29 19:10:09 -07:00

133 lines
5.9 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" },
"sourceRevision": {
"properties": {
"manifestRef": { "pattern": "^tier2-source-project:" }
}
}
}
}
},
{
"if": {
"properties": {
"sourceRevision": {
"properties": { "provider": { "const": "game_source_archive" } }
}
}
},
"then": {
"properties": {
"sourceRevision": {
"properties": {
"manifestRef": { "pattern": "^game-source-archive:" }
}
}
}
}
}
],
"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}$" }
}
}