diff --git a/go.mod b/go.mod index 5382b86..e90a7b9 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.26.3 require ( github.com/GoCodeAlone/workflow v0.62.0 github.com/GoCodeAlone/workflow-compute v0.0.0-20260524063206-b3e8de8ce8d6 - github.com/GoCodeAlone/workflow-plugin-compute-core v0.0.0-20260524082635-d967d825f9d3 + github.com/GoCodeAlone/workflow-plugin-compute-core v0.0.0-20260524090838-d0045a893984 ) require ( diff --git a/go.sum b/go.sum index 2deb597..5888c8c 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/GoCodeAlone/workflow v0.62.0 h1:emFkTomDpVmBcEfw7quRO4V/J4qDsWNx/CrBd github.com/GoCodeAlone/workflow v0.62.0/go.mod h1:659GGDrw3QJ7b625y9rf8QhKIpt1VCoEG0MxKu5tGQs= github.com/GoCodeAlone/workflow-compute v0.0.0-20260524063206-b3e8de8ce8d6 h1:R2YBH5Vnkn/O1ksTRbzn5vaMN/GtnuFNiTDRF/FR0GY= github.com/GoCodeAlone/workflow-compute v0.0.0-20260524063206-b3e8de8ce8d6/go.mod h1:T8yGXrRBm2USwkRFvMaoq4aPDt/f7JciZY9Y/l/upYs= -github.com/GoCodeAlone/workflow-plugin-compute-core v0.0.0-20260524082635-d967d825f9d3 h1:EPYnvSU3sZNnTbFyqZARKvHH00eUL5t7yWHLiBuKnOU= -github.com/GoCodeAlone/workflow-plugin-compute-core v0.0.0-20260524082635-d967d825f9d3/go.mod h1:1T6uCpUWPCNk6XPYgKq5CL/7LkD24MphKYsYVzF4jnI= +github.com/GoCodeAlone/workflow-plugin-compute-core v0.0.0-20260524090838-d0045a893984 h1:VPhpVv/1pNvwI4dVhPmHc6S2uh53+6ikWOqnfHyGS7o= +github.com/GoCodeAlone/workflow-plugin-compute-core v0.0.0-20260524090838-d0045a893984/go.mod h1:1T6uCpUWPCNk6XPYgKq5CL/7LkD24MphKYsYVzF4jnI= github.com/GoCodeAlone/yaegi v0.17.2 h1:WK6Y6e0t1a6U7r+S2dN3CGWW1PizYD3zO0zneToZPxM= github.com/GoCodeAlone/yaegi v0.17.2/go.mod h1:z5Pr6Wse6QJcQvpgxTxzMAevFarH0N37TG88Y9dprx0= github.com/IBM/sarama v1.47.0 h1:GcQFEd12+KzfPYeLgN69Fh7vLCtYRhVIx0rO4TZO318= diff --git a/internal/module_test.go b/internal/module_test.go index 5a31461..8f1e641 100644 --- a/internal/module_test.go +++ b/internal/module_test.go @@ -174,6 +174,74 @@ func TestProviderCatalogAcceptsRuntimeProfileResiduePolicy(t *testing.T) { } } +func TestProviderCatalogAcceptsAccessScopedOperations(t *testing.T) { + contract := validProviderContract() + contract.OrgID = "gocodealone" + contract.PoolID = "ci-runners" + contract.AccessPolicy = coreprotocol.AccessPolicy{ + ProviderUsageVisibility: coreprotocol.AccessVisibilityNetwork, + WorkloadVisibility: coreprotocol.AccessVisibilityPrivate, + ArtifactVisibility: coreprotocol.AccessVisibilityPrivate, + } + contract.WorkloadKinds = append(contract.WorkloadKinds, string(coreprotocol.WorkloadProvider)) + contract.Operations = []coreprotocol.ProviderOperation{{ + ID: "dispatch", + InputSchemaRef: "schema://providers/workflow-plugin-compute/operations/dispatch/input/v1", + InputSchemaDigest: coreprotocol.CanonicalHash(map[string]string{"input": "object"}), + OutputSchemaRef: "schema://providers/workflow-plugin-compute/operations/dispatch/output/v1", + OutputSchemaDigest: coreprotocol.CanonicalHash(map[string]string{"output": "object"}), + Artifacts: []string{"logs"}, + ArtifactSpecs: []coreprotocol.ProviderArtifactSpec{{ + Name: "logs", + ContentType: "text/plain", + MaxBytes: 1 << 20, + RetentionSeconds: 3600, + Forwardable: true, + }}, + }} + module, err := newProviderCatalogModule("catalog", map[string]any{ + "contracts": []any{toMap(t, contract)}, + }) + if err != nil { + t.Fatalf("newProviderCatalogModule: %v", err) + } + got := module.config.Contracts[0] + if got.AccessPolicy.ProviderUsageVisibility != coreprotocol.AccessVisibilityNetwork { + t.Fatalf("access policy not decoded: %+v", got.AccessPolicy) + } + if !got.SupportsOperation("dispatch") { + t.Fatalf("operation not decoded: %+v", got.Operations) + } + if specs := got.Operations[0].NormalizedArtifactSpecs(); len(specs) != 1 || specs[0].Name != "logs" { + t.Fatalf("artifact specs not decoded: %+v", specs) + } +} + +func TestProviderCatalogRejectsMismatchedProductVersion(t *testing.T) { + contract := validProviderContract() + product := coreprotocol.NetworkProduct{ + ProviderConfig: coreprotocol.ProviderConfig{ + PluginID: contract.PluginID, + ProviderID: contract.ProviderID, + ContractID: contract.ContractID, + Version: "v9.9.9", + }, + OperatingMode: coreprotocol.NetworkModeBatch, + WorkloadKinds: []string{string(coreprotocol.WorkloadCommand)}, + SecurityFloor: coreprotocol.PlacementRequirements{ + ExecutorProvider: "sandboxed-command", + ExecutionSecurityTier: coreprotocol.ExecutionSandboxedContainer, + ProofTier: coreprotocol.ProofArtifactHash, + }, + NetworkModes: []coreprotocol.NetworkMode{coreprotocol.NetworkModeRelay}, + } + + err := contract.SupportsProduct(product) + if err == nil || !strings.Contains(err.Error(), "version") { + t.Fatalf("expected version mismatch error, got %v", err) + } +} + func TestProviderCatalogRejectsReusableResidueWithoutWorkspace(t *testing.T) { contract := validProviderContract() contract.RuntimeContract.Profiles[0].HostWorkspaceSupported = false