From 3ede0799abde0bf21a4b691d99dae73ce2294f4b Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 19 Aug 2026 04:31:55 +0200 Subject: [PATCH] Carry delegated Eve invocation identity --- .../dist/generated/command-invocation.d.ts | 5 +++ .../eve-contracts/dist/generated/schemas.d.ts | 19 +++++++++++ .../eve-contracts/dist/generated/schemas.js | 23 +++++++++++++ .../src/generated/command-invocation.ts | 5 +++ .../eve-contracts/src/generated/schemas.ts | 23 +++++++++++++ .../GameCult.Eve.Surface.csproj | 2 +- .../Runtime/EveCommandInvocationHash.cs | 3 ++ .../Runtime/EveSurfaceDocument.cs | 32 +++++++++++++++++-- .../org.gamecult.eve.surface/package.json | 2 +- ...cult.eve.command_invocation.v1.schema.json | 12 ++++++- ...eSurfaceSerializationCompatibilityTests.cs | 16 ++++++++++ 11 files changed, 136 insertions(+), 6 deletions(-) diff --git a/packages/eve-contracts/dist/generated/command-invocation.d.ts b/packages/eve-contracts/dist/generated/command-invocation.d.ts index b0818b2..aba9560 100644 --- a/packages/eve-contracts/dist/generated/command-invocation.d.ts +++ b/packages/eve-contracts/dist/generated/command-invocation.d.ts @@ -18,4 +18,9 @@ export interface EveCommandInvocation { clientId: string; commandBoundary: string; receiptSchema: string; + delegation?: { + originalInvocationHash: string; + originalClientId: string; + delegatingRuntimeId: string; + }; } diff --git a/packages/eve-contracts/dist/generated/schemas.d.ts b/packages/eve-contracts/dist/generated/schemas.d.ts index 0f1f0a4..8ea315a 100644 --- a/packages/eve-contracts/dist/generated/schemas.d.ts +++ b/packages/eve-contracts/dist/generated/schemas.d.ts @@ -564,6 +564,25 @@ export declare const eveContractSchemas: { readonly type: "string"; readonly minLength: 1; }; + readonly delegation: { + readonly type: "object"; + readonly required: readonly ["originalInvocationHash", "originalClientId", "delegatingRuntimeId"]; + readonly properties: { + readonly originalInvocationHash: { + readonly type: "string"; + readonly minLength: 1; + }; + readonly originalClientId: { + readonly type: "string"; + readonly minLength: 1; + }; + readonly delegatingRuntimeId: { + readonly type: "string"; + readonly minLength: 1; + }; + }; + readonly additionalProperties: false; + }; }; readonly additionalProperties: false; }; diff --git a/packages/eve-contracts/dist/generated/schemas.js b/packages/eve-contracts/dist/generated/schemas.js index 403420e..c036cf9 100644 --- a/packages/eve-contracts/dist/generated/schemas.js +++ b/packages/eve-contracts/dist/generated/schemas.js @@ -671,6 +671,29 @@ export const eveContractSchemas = { "receiptSchema": { "type": "string", "minLength": 1 + }, + "delegation": { + "type": "object", + "required": [ + "originalInvocationHash", + "originalClientId", + "delegatingRuntimeId" + ], + "properties": { + "originalInvocationHash": { + "type": "string", + "minLength": 1 + }, + "originalClientId": { + "type": "string", + "minLength": 1 + }, + "delegatingRuntimeId": { + "type": "string", + "minLength": 1 + } + }, + "additionalProperties": false } }, "additionalProperties": false diff --git a/packages/eve-contracts/src/generated/command-invocation.ts b/packages/eve-contracts/src/generated/command-invocation.ts index 5c15093..8c72787 100644 --- a/packages/eve-contracts/src/generated/command-invocation.ts +++ b/packages/eve-contracts/src/generated/command-invocation.ts @@ -20,4 +20,9 @@ issuedAt: string clientId: string commandBoundary: string receiptSchema: string +delegation?: { +originalInvocationHash: string +originalClientId: string +delegatingRuntimeId: string +} } diff --git a/packages/eve-contracts/src/generated/schemas.ts b/packages/eve-contracts/src/generated/schemas.ts index bd01380..18c877e 100644 --- a/packages/eve-contracts/src/generated/schemas.ts +++ b/packages/eve-contracts/src/generated/schemas.ts @@ -671,6 +671,29 @@ export const eveContractSchemas = { "receiptSchema": { "type": "string", "minLength": 1 + }, + "delegation": { + "type": "object", + "required": [ + "originalInvocationHash", + "originalClientId", + "delegatingRuntimeId" + ], + "properties": { + "originalInvocationHash": { + "type": "string", + "minLength": 1 + }, + "originalClientId": { + "type": "string", + "minLength": 1 + }, + "delegatingRuntimeId": { + "type": "string", + "minLength": 1 + } + }, + "additionalProperties": false } }, "additionalProperties": false diff --git a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj b/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj index 4d03a28..b74ed1f 100644 --- a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj +++ b/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj @@ -6,7 +6,7 @@ enable Portable Eve surface and provider contracts. GameCult.Eve.Surface - 0.3.4 + 0.3.5 GameCult MPL-2.0 https://github.com/GameCult/Eve diff --git a/packages/org.gamecult.eve.surface/Runtime/EveCommandInvocationHash.cs b/packages/org.gamecult.eve.surface/Runtime/EveCommandInvocationHash.cs index 507b163..d7ee976 100644 --- a/packages/org.gamecult.eve.surface/Runtime/EveCommandInvocationHash.cs +++ b/packages/org.gamecult.eve.surface/Runtime/EveCommandInvocationHash.cs @@ -32,6 +32,9 @@ namespace GameCult.Eve.Surface Append(request.ClientId); Append(request.CommandBoundary); Append(request.ReceiptSchema); + Append(request.Delegation?.OriginalInvocationHash); + Append(request.Delegation?.OriginalClientId); + Append(request.Delegation?.DelegatingRuntimeId); using var sha256 = SHA256.Create(); var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(canonical.ToString())); var digest = new StringBuilder(bytes.Length * 2); diff --git a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs b/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs index 4bb33f5..c9c2f39 100644 --- a/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs +++ b/packages/org.gamecult.eve.surface/Runtime/EveSurfaceDocument.cs @@ -335,7 +335,8 @@ namespace GameCult.Eve.Surface DateTimeOffset issuedAt, string clientId, string commandBoundary = "", - string receiptSchema = "") + string receiptSchema = "", + EveCommandDelegationRecord? delegation = null) : this( SchemaId, providerId, @@ -346,7 +347,8 @@ namespace GameCult.Eve.Surface issuedAt, clientId, commandBoundary, - receiptSchema) + receiptSchema, + delegation) { } @@ -360,7 +362,8 @@ namespace GameCult.Eve.Surface DateTimeOffset issuedAt, string clientId, string commandBoundary, - string receiptSchema) + string receiptSchema, + EveCommandDelegationRecord? delegation = null) { Schema = string.IsNullOrWhiteSpace(schema) ? SchemaId : schema; ProviderId = providerId; @@ -373,6 +376,7 @@ namespace GameCult.Eve.Surface ClientId = clientId; CommandBoundary = commandBoundary ?? ""; ReceiptSchema = receiptSchema ?? ""; + Delegation = delegation; } [Key(0)] @@ -411,10 +415,32 @@ namespace GameCult.Eve.Surface [Key(8)] public string ReceiptSchema { get; } + [Key(9)] + public EveCommandDelegationRecord? Delegation { get; } + [IgnoreMember] public string CommandId => Operation.IdempotencyKey ?? ""; } + [MessagePackObject] + public sealed class EveCommandDelegationRecord + { + [SerializationConstructor] + public EveCommandDelegationRecord( + string originalInvocationHash, + string originalClientId, + string delegatingRuntimeId) + { + OriginalInvocationHash = originalInvocationHash ?? ""; + OriginalClientId = originalClientId ?? ""; + DelegatingRuntimeId = delegatingRuntimeId ?? ""; + } + + [Key(0)] public string OriginalInvocationHash { get; } + [Key(1)] public string OriginalClientId { get; } + [Key(2)] public string DelegatingRuntimeId { get; } + } + /// /// Reads the current Eve surface envelope and the original seven-field v1 envelope. /// diff --git a/packages/org.gamecult.eve.surface/package.json b/packages/org.gamecult.eve.surface/package.json index 939a870..378f218 100644 --- a/packages/org.gamecult.eve.surface/package.json +++ b/packages/org.gamecult.eve.surface/package.json @@ -1,7 +1,7 @@ { "name": "org.gamecult.eve.surface", "displayName": "Eve Surface Contract", - "version": "0.3.4", + "version": "0.3.5", "unity": "2021.3", "description": "Renderer-neutral C# contracts and builders for gamecult.eve.surface.v1 documents.", "dependencies": { diff --git a/schemas/gamecult.eve.command_invocation.v1.schema.json b/schemas/gamecult.eve.command_invocation.v1.schema.json index e3697fb..1df8dcc 100644 --- a/schemas/gamecult.eve.command_invocation.v1.schema.json +++ b/schemas/gamecult.eve.command_invocation.v1.schema.json @@ -33,7 +33,17 @@ "issuedAt": { "type": "string" }, "clientId": { "type": "string", "minLength": 1 }, "commandBoundary": { "type": "string", "minLength": 1 }, - "receiptSchema": { "type": "string", "minLength": 1 } + "receiptSchema": { "type": "string", "minLength": 1 }, + "delegation": { + "type": "object", + "required": ["originalInvocationHash", "originalClientId", "delegatingRuntimeId"], + "properties": { + "originalInvocationHash": { "type": "string", "minLength": 1 }, + "originalClientId": { "type": "string", "minLength": 1 }, + "delegatingRuntimeId": { "type": "string", "minLength": 1 } + }, + "additionalProperties": false + } }, "additionalProperties": false } diff --git a/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs b/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs index 52d71cc..be11714 100644 --- a/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs +++ b/tests/GameCult.Eve.Surface.Serialization.Tests/EveSurfaceSerializationCompatibilityTests.cs @@ -106,6 +106,22 @@ public sealed class EveSurfaceSerializationCompatibilityTests Assert.That(EveCommandInvocationHash.Compute(same), Is.EqualTo(EveCommandInvocationHash.Compute(request))); Assert.That(EveCommandInvocationHash.Compute(changedPayload), Is.Not.EqualTo(EveCommandInvocationHash.Compute(request))); + var delegated = new EveSurfaceCommandRequest( + request.Schema, + request.ProviderId, + request.SurfaceId, + request.OperationRecord, + new Dictionary(request.PayloadFields, StringComparer.Ordinal), + request.IssuedAt, + "progression-router", + request.CommandBoundary, + request.ReceiptSchema, + new EveCommandDelegationRecord( + EveCommandInvocationHash.Compute(request), + request.ClientId, + "progression-router")); + Assert.That(EveCommandInvocationHash.Compute(delegated), Is.Not.EqualTo(EveCommandInvocationHash.Compute(request))); + Assert.That(delegated.Delegation!.OriginalInvocationHash, Is.EqualTo(EveCommandInvocationHash.Compute(request))); } [Test]