From d35746569604d6fd5461cd4637cac207bdc2b351 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 03:53:05 -0400 Subject: [PATCH] feat: share resource constrained executor check --- protocol/types.go | 43 +++++++++++++++++++++++++++++++++++++++++ protocol/types_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/protocol/types.go b/protocol/types.go index 10c1e4f..6ba8b4d 100644 --- a/protocol/types.go +++ b/protocol/types.go @@ -260,6 +260,49 @@ func ExecutorMatchesPlacementRequirements(executor ExecutorRef, req PlacementReq return true } +type ExecutorCapabilities struct { + Executors []ExecutorRef `json:"executors,omitempty"` + ExecutionTiers []ExecutionSecurityTier `json:"execution_tiers,omitempty"` +} + +func ResourceLimitsRequireResourceConstrainedExecutor(limits ResourceLimits) bool { + return limits.CPUPercent > 0 || limits.MemoryBytes > 0 +} + +func ExecutorCapabilitiesHaveResourceConstrainedMatch(req PlacementRequirements, caps ExecutorCapabilities) bool { + if len(caps.Executors) == 0 { + for _, tier := range caps.ExecutionTiers { + if ExecutionTierSupportsResourceLimits(tier) { + return true + } + } + return false + } + for _, executor := range caps.Executors { + if !ExecutorMatchesPlacementRequirements(executor, req) { + continue + } + if ExecutionTierSupportsResourceLimits(executor.ExecutionSecurityTier) { + return true + } + } + return false +} + +func ExecutionTierSupportsResourceLimits(tier ExecutionSecurityTier) bool { + switch tier { + case ExecutionHardenedContainer, + ExecutionSandboxedContainer, + ExecutionMicroVM, + ExecutionConfidentialCPU, + ExecutionConfidentialGPU, + ExecutionWASMCapability: + return true + default: + return false + } +} + type ResourceUsage struct { CPUMillis int64 `json:"cpu_millis,omitempty"` GPUMillis int64 `json:"gpu_millis,omitempty"` diff --git a/protocol/types_test.go b/protocol/types_test.go index e95b46c..9ecbcdc 100644 --- a/protocol/types_test.go +++ b/protocol/types_test.go @@ -371,6 +371,50 @@ func TestExecutorMatchesPlacementRequirements(t *testing.T) { } } +func TestExecutorCapabilitiesHaveResourceConstrainedMatch(t *testing.T) { + req := protocol.PlacementRequirements{ + ExecutorProvider: "sandboxed-command", + ExecutionSecurityTier: protocol.ExecutionSandboxedContainer, + ProofTier: protocol.ProofArtifactHash, + } + + if !protocol.ResourceLimitsRequireResourceConstrainedExecutor(protocol.ResourceLimits{CPUPercent: 50}) { + t.Fatal("cpu_percent limits should require resource-constrained executor") + } + if !protocol.ResourceLimitsRequireResourceConstrainedExecutor(protocol.ResourceLimits{MemoryBytes: 128 << 20}) { + t.Fatal("memory_bytes limits should require resource-constrained executor") + } + if protocol.ResourceLimitsRequireResourceConstrainedExecutor(protocol.ResourceLimits{WorkspaceBytes: 1 << 30}) { + t.Fatal("workspace-only limits should not require resource-constrained executor") + } + + if protocol.ExecutorCapabilitiesHaveResourceConstrainedMatch(req, protocol.ExecutorCapabilities{ + Executors: []protocol.ExecutorRef{{ + Provider: "command", + ExecutionSecurityTier: protocol.ExecutionTrustedNative, + ProofTier: protocol.ProofReceiptOnly, + }}, + }) { + t.Fatal("trusted native executor should not satisfy resource-constrained placement") + } + + if !protocol.ExecutorCapabilitiesHaveResourceConstrainedMatch(req, protocol.ExecutorCapabilities{ + Executors: []protocol.ExecutorRef{{ + Provider: "sandboxed-command", + ExecutionSecurityTier: protocol.ExecutionSandboxedContainer, + ProofTier: protocol.ProofArtifactHash, + }}, + }) { + t.Fatal("matching sandboxed executor should satisfy resource-constrained placement") + } + + if !protocol.ExecutorCapabilitiesHaveResourceConstrainedMatch(protocol.PlacementRequirements{}, protocol.ExecutorCapabilities{ + ExecutionTiers: []protocol.ExecutionSecurityTier{protocol.ExecutionSandboxedContainer}, + }) { + t.Fatal("legacy tier-only capabilities should satisfy when they include a constrained tier") + } +} + func TestResourceLimitsRejectNegativeValues(t *testing.T) { limits := protocol.ResourceLimits{ CPUPercent: -1,