Carry delegated Eve invocation identity

This commit is contained in:
Meta Vens 2026-08-19 04:31:55 +02:00
commit 3ede0799ab
11 changed files with 136 additions and 6 deletions

View file

@ -18,4 +18,9 @@ export interface EveCommandInvocation {
clientId: string;
commandBoundary: string;
receiptSchema: string;
delegation?: {
originalInvocationHash: string;
originalClientId: string;
delegatingRuntimeId: string;
};
}

View file

@ -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;
};

View file

@ -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

View file

@ -20,4 +20,9 @@ issuedAt: string
clientId: string
commandBoundary: string
receiptSchema: string
delegation?: {
originalInvocationHash: string
originalClientId: string
delegatingRuntimeId: string
}
}

View file

@ -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

View file

@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Description>Portable Eve surface and provider contracts.</Description>
<PackageId>GameCult.Eve.Surface</PackageId>
<Version>0.3.4</Version>
<Version>0.3.5</Version>
<Authors>GameCult</Authors>
<PackageLicenseExpression>MPL-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/GameCult/Eve</PackageProjectUrl>

View file

@ -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);

View file

@ -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; }
}
/// <summary>
/// Reads the current Eve surface envelope and the original seven-field v1 envelope.
/// </summary>

View file

@ -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": {

View file

@ -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
}

View file

@ -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<string, string>(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]