diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index 6c4bf9c..2579a53 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -825,6 +825,11 @@ Recently cut: TeX ABI fixtures must name those same schemas, and parity fails if a sidecar advertises a request/response schema that is missing from the contract catalog. +- Runtime release/capture request schema names are now backed by Eve contract + documents. `gamecult.eve.runtime_release_request.v1` and + `gamecult.eve.runtime_capture_request.v1` live under `schemas/`; runtime + lifecycle manifests must name catalog-backed request schemas, so release and + capture status cannot hide a missing wire contract. - Conformance export now carries a root `schemaCatalog` and copies schema documents under `schemas/` in the export. Plugin owners can assert `gamecult.eve.plugin_abi.request.v1` and diff --git a/schemas/gamecult.eve.runtime_capability.v1.schema.json b/schemas/gamecult.eve.runtime_capability.v1.schema.json index 14c6ce5..ed9e3c4 100644 --- a/schemas/gamecult.eve.runtime_capability.v1.schema.json +++ b/schemas/gamecult.eve.runtime_capability.v1.schema.json @@ -209,6 +209,9 @@ "versionSource", "tagPattern", "artifactKind", + "requestSchema", + "requestBuilder", + "artifactPattern", "publishProof" ], "properties": { @@ -394,6 +397,10 @@ "required": [ "ownerRepo", "runtimeId", + "targetId", + "requestSchema", + "requestBuilder", + "advertisementPath", "captureKind", "artifactKind", "artifactPattern", diff --git a/schemas/gamecult.eve.runtime_capture_request.v1.schema.json b/schemas/gamecult.eve.runtime_capture_request.v1.schema.json new file mode 100644 index 0000000..b2d75da --- /dev/null +++ b/schemas/gamecult.eve.runtime_capture_request.v1.schema.json @@ -0,0 +1,88 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "gamecult.eve.runtime_capture_request.v1", + "title": "Eve Runtime Capture Request", + "type": "object", + "required": [ + "schema", + "runtimeId", + "ownerRepo", + "providerId", + "surfaceId", + "targetId", + "captureKind", + "artifactKind", + "artifactPath", + "conformanceAttachment", + "authority", + "issuedAtUtc" + ], + "properties": { + "schema": { + "const": "gamecult.eve.runtime_capture_request.v1" + }, + "runtimeId": { + "type": "string", + "minLength": 1 + }, + "ownerRepo": { + "type": "string", + "minLength": 1 + }, + "providerId": { + "type": "string", + "minLength": 1 + }, + "surfaceId": { + "type": "string", + "minLength": 1 + }, + "surfaceKind": { + "type": "string" + }, + "targetId": { + "type": "string", + "minLength": 1 + }, + "projectionKind": { + "type": "string" + }, + "commandBoundary": { + "type": "string" + }, + "receiptSchema": { + "type": "string" + }, + "captureKind": { + "type": "string", + "minLength": 1 + }, + "artifactKind": { + "type": "string", + "minLength": 1 + }, + "artifactPath": { + "type": "string", + "minLength": 1 + }, + "conformanceAttachment": { + "type": "string", + "minLength": 1 + }, + "authority": { + "type": "string", + "minLength": 1 + }, + "sourceAdvertisementPath": { + "type": "string" + }, + "sourceCapabilityManifestPath": { + "type": "string" + }, + "issuedAtUtc": { + "type": "string", + "minLength": 1 + } + }, + "additionalProperties": true +} diff --git a/schemas/gamecult.eve.runtime_release_request.v1.schema.json b/schemas/gamecult.eve.runtime_release_request.v1.schema.json new file mode 100644 index 0000000..6740b97 --- /dev/null +++ b/schemas/gamecult.eve.runtime_release_request.v1.schema.json @@ -0,0 +1,89 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "gamecult.eve.runtime_release_request.v1", + "title": "Eve Runtime Release Request", + "type": "object", + "required": [ + "schema", + "ownerRepo", + "repository", + "packageName", + "version", + "packageRoot", + "versionSource", + "tagName", + "artifactKind", + "artifactPath", + "publishProof" + ], + "properties": { + "schema": { + "const": "gamecult.eve.runtime_release_request.v1" + }, + "ownerRepo": { + "type": "string", + "minLength": 1 + }, + "repository": { + "type": "string", + "minLength": 1 + }, + "packageName": { + "type": "string", + "minLength": 1 + }, + "displayName": { + "type": "string" + }, + "version": { + "type": "string", + "pattern": "^\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.-]+)?$" + }, + "unity": { + "type": "string" + }, + "packageRoot": { + "type": "string", + "minLength": 1 + }, + "versionSource": { + "type": "string", + "minLength": 1 + }, + "tagName": { + "type": "string", + "minLength": 1 + }, + "artifactKind": { + "type": "string", + "minLength": 1 + }, + "artifactPath": { + "type": "string", + "minLength": 1 + }, + "publishProof": { + "type": "string", + "minLength": 1 + }, + "sourceCapabilityManifestPath": { + "type": "string" + }, + "sourcePackageManifestPath": { + "type": "string" + }, + "main": { + "type": "string" + }, + "scripts": { + "type": "object" + }, + "dependencies": { + "type": "object" + }, + "devDependencies": { + "type": "object" + } + }, + "additionalProperties": true +} diff --git a/scripts/run-conformance-consumer-smoke.ps1 b/scripts/run-conformance-consumer-smoke.ps1 index 223d6cf..fffdd59 100644 --- a/scripts/run-conformance-consumer-smoke.ps1 +++ b/scripts/run-conformance-consumer-smoke.ps1 @@ -35,6 +35,8 @@ try { --expect-schema gamecult.eve.conformance_export.v1 ` --expect-schema gamecult.eve.plugin_abi.request.v1 ` --expect-schema gamecult.eve.plugin_abi.response.v1 ` + --expect-schema gamecult.eve.runtime_release_request.v1 ` + --expect-schema gamecult.eve.runtime_capture_request.v1 ` --expect-capability-gap runtime:Fensalir:direct2d:capture:missing ` --expect-world-lowering-coverage aetheria:aetheria.daemon.game:web-reference:claimed:Eve:web ` --expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-uitoolkit:claimed:EveUnity:unity-uitoolkit ` diff --git a/scripts/run-eveconformance-handoff-smoke.ps1 b/scripts/run-eveconformance-handoff-smoke.ps1 index 1e8773d..1502f51 100644 --- a/scripts/run-eveconformance-handoff-smoke.ps1 +++ b/scripts/run-eveconformance-handoff-smoke.ps1 @@ -81,6 +81,8 @@ foreach ($contract in @( "gamecult.eve.plugin_abi_fixture.v1", "gamecult.eve.plugin_abi.request.v1", "gamecult.eve.plugin_abi.response.v1", + "gamecult.eve.runtime_release_request.v1", + "gamecult.eve.runtime_capture_request.v1", "gamecult.eve.provider_advertisement.v1", "gamecult.eve.runtime_capability.v1" )) { @@ -116,7 +118,9 @@ if (Test-Path -LiteralPath (Join-Path $absoluteExportDirectory "index.json")) { "gamecult.eve.plugin_advertisement.v1", "gamecult.eve.plugin_abi_fixture.v1", "gamecult.eve.plugin_abi.request.v1", - "gamecult.eve.plugin_abi.response.v1" + "gamecult.eve.plugin_abi.response.v1", + "gamecult.eve.runtime_release_request.v1", + "gamecult.eve.runtime_capture_request.v1" )) { $schema = @($export.schemaCatalog) | Where-Object { $_.schemaId -eq $schemaId } | Select-Object -First 1 if (-not $schema) { diff --git a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 index 3b27b37..b1bc2f0 100644 --- a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 +++ b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 @@ -41,6 +41,8 @@ node $consumerScript $consumerExport ` --expect-runtime electron-shell ` --expect-runtime tui ` --expect-runtime direct2d ` + --expect-schema gamecult.eve.runtime_release_request.v1 ` + --expect-schema gamecult.eve.runtime_capture_request.v1 ` --expect-runtime-status web:active ` --expect-runtime-status windows-flutter:active ` --expect-runtime-status linux-flutter:active ` diff --git a/tools/conformance/eveconformance-handoff.json b/tools/conformance/eveconformance-handoff.json index 5491d12..482864f 100644 --- a/tools/conformance/eveconformance-handoff.json +++ b/tools/conformance/eveconformance-handoff.json @@ -28,7 +28,9 @@ "schemas/gamecult.eve.plugin_advertisement.v1.schema.json", "schemas/gamecult.eve.plugin_abi_fixture.v1.schema.json", "schemas/gamecult.eve.plugin_abi.request.v1.schema.json", - "schemas/gamecult.eve.plugin_abi.response.v1.schema.json" + "schemas/gamecult.eve.plugin_abi.response.v1.schema.json", + "schemas/gamecult.eve.runtime_release_request.v1.schema.json", + "schemas/gamecult.eve.runtime_capture_request.v1.schema.json" ], "replacementProof": "EveConformance publishes the schema catalog and copied schema documents needed by conformance, plugin, provider, and runtime consumers." }, @@ -69,6 +71,8 @@ "gamecult.eve.plugin_abi_fixture.v1", "gamecult.eve.plugin_abi.request.v1", "gamecult.eve.plugin_abi.response.v1", + "gamecult.eve.runtime_release_request.v1", + "gamecult.eve.runtime_capture_request.v1", "gamecult.eve.provider_advertisement.v1", "gamecult.eve.runtime_capability.v1" ], diff --git a/tools/parity/parity-manifest.json b/tools/parity/parity-manifest.json index 7d45252..41e3a80 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -16,6 +16,8 @@ "gamecult.eve.plugin_abi_fixture.v1": "schemas/gamecult.eve.plugin_abi_fixture.v1.schema.json", "gamecult.eve.plugin_advertisement.v1": "schemas/gamecult.eve.plugin_advertisement.v1.schema.json", "gamecult.eve.runtime_capability.v1": "schemas/gamecult.eve.runtime_capability.v1.schema.json", + "gamecult.eve.runtime_release_request.v1": "schemas/gamecult.eve.runtime_release_request.v1.schema.json", + "gamecult.eve.runtime_capture_request.v1": "schemas/gamecult.eve.runtime_capture_request.v1.schema.json", "gamecult.eve.provider_scenario.v1": "schemas/gamecult.eve.provider_scenario.v1.schema.json", "gamecult.eve.provider_advertisement.v1": "schemas/gamecult.eve.provider_advertisement.v1.schema.json" }, diff --git a/tools/parity/run-parity.mjs b/tools/parity/run-parity.mjs index 89ae362..0c56d53 100644 --- a/tools/parity/run-parity.mjs +++ b/tools/parity/run-parity.mjs @@ -1321,6 +1321,9 @@ function compareCaptureContract(expected, actual, label) { errors.push(`${label}.${key}:expected ${expected[key] || ""} got ${actual[key] || ""}`); } } + if (actual.requestSchema && !manifest.schemas?.[actual.requestSchema]) { + errors.push(`${label}.requestSchema:${actual.requestSchema}:missing-schema-catalog-entry`); + } return errors; } @@ -1363,6 +1366,9 @@ function compareReleaseContract(expected, actual, label) { errors.push(`${label}.${key}:expected ${expected[key] || ""} got ${actual[key] || ""}`); } } + if (actual.requestSchema && !manifest.schemas?.[actual.requestSchema]) { + errors.push(`${label}.requestSchema:${actual.requestSchema}:missing-schema-catalog-entry`); + } for (const key of ["packageRoot", "versionSource", "requestBuilder"]) { if (actual[key] && !existsSync(path.join(repoRoot, actual[key]))) { errors.push(`${label}.${key}:${actual[key]}:missing`);