From 2a1bd7ccf8fee5ee19f8896707aaa82fa0efbcec Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Tue, 3 Feb 2026 15:21:32 +0100 Subject: [PATCH 1/4] improve error message Signed-off-by: Sylwester Piskozub --- app/controlplane/pkg/data/referrer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controlplane/pkg/data/referrer.go b/app/controlplane/pkg/data/referrer.go index 4565e006b..d9d72ea44 100644 --- a/app/controlplane/pkg/data/referrer.go +++ b/app/controlplane/pkg/data/referrer.go @@ -1,5 +1,5 @@ // -// Copyright 2023 The Chainloop Authors. +// Copyright 2023-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. @@ -89,10 +89,10 @@ func (r *ReferrerRepo) Save(ctx context.Context, referrers []*biz.Referrer, work // Iterate on the items it refer to (references) var references []uuid.UUID for _, ref := range parentRef.References { - // amd find it in the DB + // and find it in the DB storedReference, ok := storedMap[ref.MapID()] if !ok { - return fmt.Errorf("referrer %v not found", ref) + return fmt.Errorf("an artifact or piece of evidence with digest %s (kind: %s) can't be found", ref.Digest, ref.Kind) } references = append(references, storedReference) From 8509a34ddda3594c5c79a27af77be483ecb9ab5f Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Fri, 13 Feb 2026 13:04:48 +0100 Subject: [PATCH 2/4] fix contract schema v2 name Signed-off-by: Sylwester Piskozub --- app/controlplane/pkg/data/workflow.go | 77 +++++++++++++++++++-------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/app/controlplane/pkg/data/workflow.go b/app/controlplane/pkg/data/workflow.go index 4b02cdca1..0b62eda22 100644 --- a/app/controlplane/pkg/data/workflow.go +++ b/app/controlplane/pkg/data/workflow.go @@ -110,31 +110,64 @@ func (r *WorkflowRepo) Create(ctx context.Context, opts *biz.WorkflowCreateOpts) } // We do not have an explicit contract - // 1 - try to find it with the default name - // 2 - if not found, create it with the default name if contractUUID == uuid.Nil { - defaultContractName := fmt.Sprintf("%s-%s", opts.Project, opts.Name) - // Try to find the one with the default name or create it - contract, err := contractInOrg(ctx, r.data.DB, orgUUID, nil, &defaultContractName) - if err != nil { - if ent.IsNotFound(err) { - // Check if contract creation is restricted to org admins - if opts.OrgRestrictContractCreationToAdmins && !opts.UserIsOrgAdmin { - return biz.NewErrUnauthorizedStr("contract creation is restricted to organization administrators. Please use existing contracts or contact your administrator") - } + var contract *ent.WorkflowContract + + // Try contract schema v2 + var metadataContractName string + if opts.DetectedContract != nil && opts.DetectedContract.Schemav2 != nil { + metadataContractName = opts.DetectedContract.Schemav2.GetMetadata().GetName() + } + + if metadataContractName != "" { + // Contract must not exist with the same name in the org, otherwise we might be linking to an existing contract that doesn't match the detected one + _, err := contractInOrg(ctx, r.data.DB, orgUUID, nil, &metadataContractName) + if err == nil { + return biz.NewErrAlreadyExistsStr(fmt.Sprintf("contract %q already exists", metadataContractName)) + } + if !ent.IsNotFound(err) { + return fmt.Errorf("failed to check contract: %w", err) + } - // Create a new contract associated with the workflow - contract, _, err = r.contractRepo.addCreateToTx(ctx, tx, &biz.ContractCreateOpts{ - OrgID: orgUUID, - Name: defaultContractName, - Contract: opts.DetectedContract, - ProjectID: &projectID, - }) - if err != nil { - return fmt.Errorf("creating contract: %w", err) + // Check if contract creation is restricted to org admins + if opts.OrgRestrictContractCreationToAdmins && !opts.UserIsOrgAdmin { + return biz.NewErrUnauthorizedStr("contract creation is restricted to organization administrators. Please use existing contracts or contact your administrator") + } + + // Create the contract + contract, _, err = r.contractRepo.addCreateToTx(ctx, tx, &biz.ContractCreateOpts{ + OrgID: orgUUID, + Name: metadataContractName, + Contract: opts.DetectedContract, + ProjectID: &projectID, + }) + if err != nil { + return fmt.Errorf("creating contract: %w", err) + } + } else { + // Try to find the one with the default name or create it + defaultContractName := fmt.Sprintf("%s-%s", opts.Project, opts.Name) + contract, err = contractInOrg(ctx, r.data.DB, orgUUID, nil, &defaultContractName) + if err != nil { + if ent.IsNotFound(err) { + // Check if contract creation is restricted to org admins + if opts.OrgRestrictContractCreationToAdmins && !opts.UserIsOrgAdmin { + return biz.NewErrUnauthorizedStr("contract creation is restricted to organization administrators. Please use existing contracts or contact your administrator") + } + + // Create a new contract associated with the workflow + contract, _, err = r.contractRepo.addCreateToTx(ctx, tx, &biz.ContractCreateOpts{ + OrgID: orgUUID, + Name: defaultContractName, + Contract: opts.DetectedContract, + ProjectID: &projectID, + }) + if err != nil { + return fmt.Errorf("creating contract: %w", err) + } + } else { + return fmt.Errorf("failed to find contract: %w", err) } - } else { - return fmt.Errorf("failed to find contract: %w", err) } } From cdbfb2e21c40ac48c2d824a28c589ae5b96b7e34 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Fri, 13 Feb 2026 13:19:53 +0100 Subject: [PATCH 3/4] check if user provided a contract Signed-off-by: Sylwester Piskozub --- app/controlplane/pkg/data/workflow.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controlplane/pkg/data/workflow.go b/app/controlplane/pkg/data/workflow.go index 0b62eda22..9f7b7573c 100644 --- a/app/controlplane/pkg/data/workflow.go +++ b/app/controlplane/pkg/data/workflow.go @@ -115,7 +115,7 @@ func (r *WorkflowRepo) Create(ctx context.Context, opts *biz.WorkflowCreateOpts) // Try contract schema v2 var metadataContractName string - if opts.DetectedContract != nil && opts.DetectedContract.Schemav2 != nil { + if opts.ContractBytes != nil && opts.DetectedContract != nil && opts.DetectedContract.Schemav2 != nil { metadataContractName = opts.DetectedContract.Schemav2.GetMetadata().GetName() } From 845e39837c81c740e52e163b6f8d8f66b45c4183 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Fri, 13 Feb 2026 13:24:23 +0100 Subject: [PATCH 4/4] remove accidental change Signed-off-by: Sylwester Piskozub --- app/controlplane/pkg/data/referrer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controlplane/pkg/data/referrer.go b/app/controlplane/pkg/data/referrer.go index d9d72ea44..4565e006b 100644 --- a/app/controlplane/pkg/data/referrer.go +++ b/app/controlplane/pkg/data/referrer.go @@ -1,5 +1,5 @@ // -// Copyright 2023-2026 The Chainloop Authors. +// Copyright 2023 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. @@ -89,10 +89,10 @@ func (r *ReferrerRepo) Save(ctx context.Context, referrers []*biz.Referrer, work // Iterate on the items it refer to (references) var references []uuid.UUID for _, ref := range parentRef.References { - // and find it in the DB + // amd find it in the DB storedReference, ok := storedMap[ref.MapID()] if !ok { - return fmt.Errorf("an artifact or piece of evidence with digest %s (kind: %s) can't be found", ref.Digest, ref.Kind) + return fmt.Errorf("referrer %v not found", ref) } references = append(references, storedReference)