From 5e25681e404de42dbd15427e4b1ab8f495d3095d Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 20 May 2026 14:49:51 +0200 Subject: [PATCH 1/4] feat(runner): add CHAINLOOP_SANDBOX runner type Introduces a new runner type CHAINLOOP_SANDBOX as a no-op placeholder. CheckEnv returns false so it is never auto-discovered; it must be selected explicitly via the contract's runner.type. Assisted-by: Claude Code Signed-off-by: Miguel Martinez Trivino --- app/cli/pkg/action/workflow_run_list.go | 1 + .../workflowcontract/v1/crafting_schema.ts | 6 ++ ...attestation.v1.Attestation.jsonschema.json | 6 +- .../attestation.v1.Attestation.schema.json | 6 +- ...ation.v1.RunnerEnvironment.jsonschema.json | 3 +- ...testation.v1.RunnerEnvironment.schema.json | 3 +- ...estationServiceInitRequest.jsonschema.json | 3 +- ....AttestationServiceInitRequest.schema.json | 3 +- ...lane.v1.MetricsRunnerCount.jsonschema.json | 6 +- ...rolplane.v1.MetricsRunnerCount.schema.json | 6 +- ...olplane.v1.WorkflowRunItem.jsonschema.json | 6 +- ...ontrolplane.v1.WorkflowRunItem.schema.json | 6 +- ...WorkflowServiceListRequest.jsonschema.json | 6 +- ....v1.WorkflowServiceListRequest.schema.json | 6 +- ...t.v1.CraftingSchema.Runner.jsonschema.json | 3 +- ...tract.v1.CraftingSchema.Runner.schema.json | 3 +- .../workflowcontract/v1/crafting_schema.pb.go | 12 ++- .../workflowcontract/v1/crafting_schema.proto | 1 + pkg/attestation/crafter/runner.go | 3 + .../crafter/runners/chainloopsandbox.go | 73 +++++++++++++++++++ 20 files changed, 136 insertions(+), 26 deletions(-) create mode 100644 pkg/attestation/crafter/runners/chainloopsandbox.go diff --git a/app/cli/pkg/action/workflow_run_list.go b/app/cli/pkg/action/workflow_run_list.go index 075294fbc..c00801a7b 100644 --- a/app/cli/pkg/action/workflow_run_list.go +++ b/app/cli/pkg/action/workflow_run_list.go @@ -194,6 +194,7 @@ func humanizedRunnerType(in v1.CraftingSchema_Runner_RunnerType) string { *v1.CraftingSchema_Runner_DAGGER_PIPELINE.Enum(): "Dagger Pipeline", *v1.CraftingSchema_Runner_TEAMCITY_PIPELINE.Enum(): "TeamCity Pipeline", *v1.CraftingSchema_Runner_TEKTON_PIPELINE.Enum(): "Tekton Pipeline", + *v1.CraftingSchema_Runner_CHAINLOOP_SANDBOX.Enum(): "Chainloop Sandbox", } hrt, ok := mapping[in] diff --git a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts index f42f96f67..e6ed9bf7a 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -103,6 +103,7 @@ export enum CraftingSchema_Runner_RunnerType { DAGGER_PIPELINE = 6, TEAMCITY_PIPELINE = 7, TEKTON_PIPELINE = 8, + CHAINLOOP_SANDBOX = 9, UNRECOGNIZED = -1, } @@ -135,6 +136,9 @@ export function craftingSchema_Runner_RunnerTypeFromJSON(object: any): CraftingS case 8: case "TEKTON_PIPELINE": return CraftingSchema_Runner_RunnerType.TEKTON_PIPELINE; + case 9: + case "CHAINLOOP_SANDBOX": + return CraftingSchema_Runner_RunnerType.CHAINLOOP_SANDBOX; case -1: case "UNRECOGNIZED": default: @@ -162,6 +166,8 @@ export function craftingSchema_Runner_RunnerTypeToJSON(object: CraftingSchema_Ru return "TEAMCITY_PIPELINE"; case CraftingSchema_Runner_RunnerType.TEKTON_PIPELINE: return "TEKTON_PIPELINE"; + case CraftingSchema_Runner_RunnerType.CHAINLOOP_SANDBOX: + return "CHAINLOOP_SANDBOX"; case CraftingSchema_Runner_RunnerType.UNRECOGNIZED: default: return "UNRECOGNIZED"; diff --git a/app/controlplane/api/gen/jsonschema/attestation.v1.Attestation.jsonschema.json b/app/controlplane/api/gen/jsonschema/attestation.v1.Attestation.jsonschema.json index 79631f02e..b05ac4c34 100644 --- a/app/controlplane/api/gen/jsonschema/attestation.v1.Attestation.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/attestation.v1.Attestation.jsonschema.json @@ -61,7 +61,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" @@ -168,7 +169,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/attestation.v1.Attestation.schema.json b/app/controlplane/api/gen/jsonschema/attestation.v1.Attestation.schema.json index 733a8dbed..5b4b85c8c 100644 --- a/app/controlplane/api/gen/jsonschema/attestation.v1.Attestation.schema.json +++ b/app/controlplane/api/gen/jsonschema/attestation.v1.Attestation.schema.json @@ -61,7 +61,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" @@ -168,7 +169,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/attestation.v1.RunnerEnvironment.jsonschema.json b/app/controlplane/api/gen/jsonschema/attestation.v1.RunnerEnvironment.jsonschema.json index 66d729043..3410911c2 100644 --- a/app/controlplane/api/gen/jsonschema/attestation.v1.RunnerEnvironment.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/attestation.v1.RunnerEnvironment.jsonschema.json @@ -30,7 +30,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/attestation.v1.RunnerEnvironment.schema.json b/app/controlplane/api/gen/jsonschema/attestation.v1.RunnerEnvironment.schema.json index cf6cb244d..52ecf4b52 100644 --- a/app/controlplane/api/gen/jsonschema/attestation.v1.RunnerEnvironment.schema.json +++ b/app/controlplane/api/gen/jsonschema/attestation.v1.RunnerEnvironment.schema.json @@ -30,7 +30,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.AttestationServiceInitRequest.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.AttestationServiceInitRequest.jsonschema.json index 5e6e99f59..cec86633a 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.AttestationServiceInitRequest.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.AttestationServiceInitRequest.jsonschema.json @@ -65,7 +65,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.AttestationServiceInitRequest.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.AttestationServiceInitRequest.schema.json index 51049ed78..6f2c78c2b 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.AttestationServiceInitRequest.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.AttestationServiceInitRequest.schema.json @@ -65,7 +65,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.MetricsRunnerCount.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.MetricsRunnerCount.jsonschema.json index 63d9c4a21..e1566dfb9 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.MetricsRunnerCount.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.MetricsRunnerCount.jsonschema.json @@ -15,7 +15,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" @@ -46,7 +47,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.MetricsRunnerCount.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.MetricsRunnerCount.schema.json index 54a36e983..11be4f591 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.MetricsRunnerCount.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.MetricsRunnerCount.schema.json @@ -15,7 +15,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" @@ -46,7 +47,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowRunItem.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowRunItem.jsonschema.json index 588a45c34..b1ba1a924 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowRunItem.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowRunItem.jsonschema.json @@ -47,7 +47,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" @@ -112,7 +113,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowRunItem.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowRunItem.schema.json index f0063d825..6e2f1ee7c 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowRunItem.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowRunItem.schema.json @@ -47,7 +47,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" @@ -112,7 +113,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowServiceListRequest.jsonschema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowServiceListRequest.jsonschema.json index d870a1966..40da111f9 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowServiceListRequest.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowServiceListRequest.jsonschema.json @@ -83,7 +83,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" @@ -186,7 +187,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowServiceListRequest.schema.json b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowServiceListRequest.schema.json index 7f7ddac4d..5920fcfdd 100644 --- a/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowServiceListRequest.schema.json +++ b/app/controlplane/api/gen/jsonschema/controlplane.v1.WorkflowServiceListRequest.schema.json @@ -83,7 +83,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" @@ -186,7 +187,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.Runner.jsonschema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.Runner.jsonschema.json index ae0d21cb3..94541b958 100644 --- a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.Runner.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.Runner.jsonschema.json @@ -15,7 +15,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.Runner.schema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.Runner.schema.json index ac54e3edc..28911318a 100644 --- a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.Runner.schema.json +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.Runner.schema.json @@ -15,7 +15,8 @@ "CIRCLECI_BUILD", "DAGGER_PIPELINE", "TEAMCITY_PIPELINE", - "TEKTON_PIPELINE" + "TEKTON_PIPELINE", + "CHAINLOOP_SANDBOX" ], "title": "Runner Type", "type": "string" diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index c03dce46f..b5b457566 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -100,6 +100,7 @@ const ( CraftingSchema_Runner_DAGGER_PIPELINE CraftingSchema_Runner_RunnerType = 6 CraftingSchema_Runner_TEAMCITY_PIPELINE CraftingSchema_Runner_RunnerType = 7 CraftingSchema_Runner_TEKTON_PIPELINE CraftingSchema_Runner_RunnerType = 8 + CraftingSchema_Runner_CHAINLOOP_SANDBOX CraftingSchema_Runner_RunnerType = 9 ) // Enum value maps for CraftingSchema_Runner_RunnerType. @@ -114,6 +115,7 @@ var ( 6: "DAGGER_PIPELINE", 7: "TEAMCITY_PIPELINE", 8: "TEKTON_PIPELINE", + 9: "CHAINLOOP_SANDBOX", } CraftingSchema_Runner_RunnerType_value = map[string]int32{ "RUNNER_TYPE_UNSPECIFIED": 0, @@ -125,6 +127,7 @@ var ( "DAGGER_PIPELINE": 6, "TEAMCITY_PIPELINE": 7, "TEKTON_PIPELINE": 8, + "CHAINLOOP_SANDBOX": 9, } ) @@ -1953,7 +1956,7 @@ var File_workflowcontract_v1_crafting_schema_proto protoreflect.FileDescriptor const file_workflowcontract_v1_crafting_schema_proto_rawDesc = "" + "\n" + - ")workflowcontract/v1/crafting_schema.proto\x12\x13workflowcontract.v1\x1a\x1bbuf/validate/validate.proto\"\xa1\x0f\n" + + ")workflowcontract/v1/crafting_schema.proto\x12\x13workflowcontract.v1\x1a\x1bbuf/validate/validate.proto\"\xb8\x0f\n" + "\x0eCraftingSchema\x122\n" + "\x0eschema_version\x18\x01 \x01(\tB\v\xbaH\x06r\x04\n" + "\x02v1\x18\x01R\rschemaVersion\x12N\n" + @@ -1962,9 +1965,9 @@ const file_workflowcontract_v1_crafting_schema_proto_rawDesc = "" + "\x06runner\x18\x04 \x01(\v2*.workflowcontract.v1.CraftingSchema.RunnerB\x02\x18\x01R\x06runner\x12E\n" + "\vannotations\x18\x05 \x03(\v2\x1f.workflowcontract.v1.AnnotationB\x02\x18\x01R\vannotations\x12=\n" + "\bpolicies\x18\x06 \x01(\v2\x1d.workflowcontract.v1.PoliciesB\x02\x18\x01R\bpolicies\x12S\n" + - "\rpolicy_groups\x18\a \x03(\v2*.workflowcontract.v1.PolicyGroupAttachmentB\x02\x18\x01R\fpolicyGroups\x1a\xb3\x02\n" + + "\rpolicy_groups\x18\a \x03(\v2*.workflowcontract.v1.PolicyGroupAttachmentB\x02\x18\x01R\fpolicyGroups\x1a\xca\x02\n" + "\x06Runner\x12W\n" + - "\x04type\x18\x01 \x01(\x0e25.workflowcontract.v1.CraftingSchema.Runner.RunnerTypeB\f\xbaH\a\x82\x01\x04\x10\x01 \x00\x18\x01R\x04type\"\xcb\x01\n" + + "\x04type\x18\x01 \x01(\x0e25.workflowcontract.v1.CraftingSchema.Runner.RunnerTypeB\f\xbaH\a\x82\x01\x04\x10\x01 \x00\x18\x01R\x04type\"\xe2\x01\n" + "\n" + "RunnerType\x12\x1b\n" + "\x17RUNNER_TYPE_UNSPECIFIED\x10\x00\x12\x11\n" + @@ -1975,7 +1978,8 @@ const file_workflowcontract_v1_crafting_schema_proto_rawDesc = "" + "\x0eCIRCLECI_BUILD\x10\x05\x12\x13\n" + "\x0fDAGGER_PIPELINE\x10\x06\x12\x15\n" + "\x11TEAMCITY_PIPELINE\x10\a\x12\x13\n" + - "\x0fTEKTON_PIPELINE\x10\b:\x02\x18\x01\x1a\x83\t\n" + + "\x0fTEKTON_PIPELINE\x10\b\x12\x15\n" + + "\x11CHAINLOOP_SANDBOX\x10\t:\x02\x18\x01\x1a\x83\t\n" + "\bMaterial\x12[\n" + "\x04type\x18\x01 \x01(\x0e29.workflowcontract.v1.CraftingSchema.Material.MaterialTypeB\f\xbaH\a\x82\x01\x04\x10\x01 \x00\x18\x01R\x04type\x12\x99\x01\n" + "\x04name\x18\x02 \x01(\tB\x84\x01\xbaH\x7f\xba\x01|\n" + diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index 7f15ec531..180395658 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -64,6 +64,7 @@ message CraftingSchema { DAGGER_PIPELINE = 6; TEAMCITY_PIPELINE = 7; TEKTON_PIPELINE = 8; + CHAINLOOP_SANDBOX = 9; } } diff --git a/pkg/attestation/crafter/runner.go b/pkg/attestation/crafter/runner.go index af80e15c1..9c34995ef 100644 --- a/pkg/attestation/crafter/runner.go +++ b/pkg/attestation/crafter/runner.go @@ -101,6 +101,9 @@ var RunnerFactories = map[schemaapi.CraftingSchema_Runner_RunnerType]RunnerFacto schemaapi.CraftingSchema_Runner_TEKTON_PIPELINE: func(_ string, logger *zerolog.Logger) SupportedRunner { return runners.NewTektonPipeline(timeoutCtx, logger) }, + schemaapi.CraftingSchema_Runner_CHAINLOOP_SANDBOX: func(_ string, _ *zerolog.Logger) SupportedRunner { + return runners.NewChainloopSandbox() + }, } // Load a specific runner diff --git a/pkg/attestation/crafter/runners/chainloopsandbox.go b/pkg/attestation/crafter/runners/chainloopsandbox.go new file mode 100644 index 000000000..eb41a64db --- /dev/null +++ b/pkg/attestation/crafter/runners/chainloopsandbox.go @@ -0,0 +1,73 @@ +// +// Copyright 2026 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package runners + +import ( + "context" + + schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/runners/commitverification" +) + +type ChainloopSandbox struct { + *Generic +} + +func NewChainloopSandbox() *ChainloopSandbox { + return &ChainloopSandbox{ + Generic: NewGeneric(), + } +} + +func (r *ChainloopSandbox) ID() schemaapi.CraftingSchema_Runner_RunnerType { + return schemaapi.CraftingSchema_Runner_CHAINLOOP_SANDBOX +} + +func (r *ChainloopSandbox) CheckEnv() bool { + return false +} + +func (r *ChainloopSandbox) ListEnvVars() []*EnvVarDefinition { + return []*EnvVarDefinition{} +} + +func (r *ChainloopSandbox) RunURI() string { + return "" +} + +func (r *ChainloopSandbox) ResolveEnvVars() (map[string]string, []*error) { + return resolveEnvVars(r.ListEnvVars()) +} + +func (r *ChainloopSandbox) WorkflowFilePath() string { + return "" +} + +func (r *ChainloopSandbox) IsAuthenticated() bool { + return false +} + +func (r *ChainloopSandbox) Environment() RunnerEnvironment { + return Unknown +} + +func (r *ChainloopSandbox) VerifyCommitSignature(_ context.Context, _ string) *commitverification.CommitVerification { + return nil +} + +func (r *ChainloopSandbox) Report(_ []byte, _ string) error { + return nil +} From 54c168664721e3d78f079f4c26df2cb942601db1 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 20 May 2026 14:57:38 +0200 Subject: [PATCH 2/4] feat(runner): auto-discover CHAINLOOP_SANDBOX via env var The sandbox runner is now picked up when the CHAINLOOP_SANDBOX environment variable is set. Assisted-by: Claude Code Signed-off-by: Miguel Martinez Trivino Chainloop-Trace-Sessions: 3f5608e5-e869-4677-8c44-97a0b5aec207 --- pkg/attestation/crafter/runners/chainloopsandbox.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/attestation/crafter/runners/chainloopsandbox.go b/pkg/attestation/crafter/runners/chainloopsandbox.go index eb41a64db..46435abc2 100644 --- a/pkg/attestation/crafter/runners/chainloopsandbox.go +++ b/pkg/attestation/crafter/runners/chainloopsandbox.go @@ -17,11 +17,14 @@ package runners import ( "context" + "os" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/runners/commitverification" ) +const chainloopSandboxEnvVar = "CHAINLOOP_SANDBOX" + type ChainloopSandbox struct { *Generic } @@ -37,7 +40,7 @@ func (r *ChainloopSandbox) ID() schemaapi.CraftingSchema_Runner_RunnerType { } func (r *ChainloopSandbox) CheckEnv() bool { - return false + return os.Getenv(chainloopSandboxEnvVar) != "" } func (r *ChainloopSandbox) ListEnvVars() []*EnvVarDefinition { From 38c69938235cc9263bd6cbe961883cd707834f63 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 20 May 2026 14:58:22 +0200 Subject: [PATCH 3/4] test(runner): add tests for ChainloopSandbox runner Assisted-by: Claude Code Signed-off-by: Miguel Martinez Trivino Chainloop-Trace-Sessions: 3f5608e5-e869-4677-8c44-97a0b5aec207 --- .../crafter/runners/chainloopsandbox_test.go | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 pkg/attestation/crafter/runners/chainloopsandbox_test.go diff --git a/pkg/attestation/crafter/runners/chainloopsandbox_test.go b/pkg/attestation/crafter/runners/chainloopsandbox_test.go new file mode 100644 index 000000000..4ee653655 --- /dev/null +++ b/pkg/attestation/crafter/runners/chainloopsandbox_test.go @@ -0,0 +1,99 @@ +// +// Copyright 2026 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package runners + +import ( + "testing" + + "github.com/stretchr/testify/suite" +) + +type chainloopSandboxSuite struct { + suite.Suite + runner *ChainloopSandbox +} + +func (s *chainloopSandboxSuite) TestCheckEnv() { + testCases := []struct { + name string + env map[string]string + want bool + }{ + { + name: "env var not set", + env: map[string]string{}, + want: false, + }, + { + name: "env var set to non-empty value", + env: map[string]string{"CHAINLOOP_SANDBOX": "1"}, + want: true, + }, + { + name: "env var set to empty string", + env: map[string]string{"CHAINLOOP_SANDBOX": ""}, + want: false, + }, + } + + for _, tc := range testCases { + s.T().Run(tc.name, func(t *testing.T) { + t.Setenv("CHAINLOOP_SANDBOX", "") + for k, v := range tc.env { + t.Setenv(k, v) + } + s.Equal(tc.want, s.runner.CheckEnv()) + }) + } +} + +func (s *chainloopSandboxSuite) TestListEnvVars() { + s.Empty(s.runner.ListEnvVars()) +} + +func (s *chainloopSandboxSuite) TestResolveEnvVars() { + resolved, errors := s.runner.ResolveEnvVars() + s.Empty(errors) + s.Empty(resolved) +} + +func (s *chainloopSandboxSuite) TestRunURI() { + s.Empty(s.runner.RunURI()) +} + +func (s *chainloopSandboxSuite) TestWorkflowFilePath() { + s.Empty(s.runner.WorkflowFilePath()) +} + +func (s *chainloopSandboxSuite) TestIsAuthenticated() { + s.False(s.runner.IsAuthenticated()) +} + +func (s *chainloopSandboxSuite) TestEnvironment() { + s.Equal(Unknown, s.runner.Environment()) +} + +func (s *chainloopSandboxSuite) TestRunnerName() { + s.Equal("CHAINLOOP_SANDBOX", s.runner.ID().String()) +} + +func (s *chainloopSandboxSuite) SetupTest() { + s.runner = NewChainloopSandbox() +} + +func TestChainloopSandboxRunner(t *testing.T) { + suite.Run(t, new(chainloopSandboxSuite)) +} From 884a669237687cfedde8a215f7643b2d031e9407 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Wed, 20 May 2026 15:11:15 +0200 Subject: [PATCH 4/4] test(cli): add CHAINLOOP_SANDBOX to humanized runner type test Assisted-by: Claude Code Signed-off-by: Miguel Martinez Trivino Chainloop-Trace-Sessions: 3f5608e5-e869-4677-8c44-97a0b5aec207 --- app/cli/pkg/action/workflow_run_list_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/cli/pkg/action/workflow_run_list_test.go b/app/cli/pkg/action/workflow_run_list_test.go index fd452ef27..fe7c3ff94 100644 --- a/app/cli/pkg/action/workflow_run_list_test.go +++ b/app/cli/pkg/action/workflow_run_list_test.go @@ -68,6 +68,10 @@ func (s *workflowRunListSuite) TestHumanizedRunnerType() { name: "tekton runner", testInput: v1.CraftingSchema_Runner_TEKTON_PIPELINE, expectedOutput: "Tekton Pipeline", + }, { + name: "chainloop sandbox runner", + testInput: v1.CraftingSchema_Runner_CHAINLOOP_SANDBOX, + expectedOutput: "Chainloop Sandbox", }, { name: "unknown runner", testInput: -34,