Files
probo/pkg/server/api/mcp/v1/schema.resolvers.go
Bryan Frimin ce1b64b529 Update GraphQL, MCP, and CLI for the portal
Rewire the console and visitor resolvers onto the management and visitor
services with compliance-portal authorization. Rename the GraphQL and MCP
ComplianceExternalURL type to ComplianceCustomLink, expose trust center
profile fields, default and custom domains, public URL, and the managed
flag, and drop the profile fields from the organization surface.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:08 +02:00

7325 lines
270 KiB
Go

package mcp_v1
// This file will be automatically regenerated based on the schema, any resolver implementations
// will be copied through when generating and any unknown code will be moved to the end.
// Code generated by mcpgen. DO NOT EDIT.
import (
"context"
"encoding/json"
"errors"
"fmt"
"time"
"github.com/modelcontextprotocol/go-sdk/mcp"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/complianceportal"
"go.probo.inc/probo/pkg/complianceportal/management"
"go.probo.inc/probo/pkg/cookiebanner"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/resourcealias"
"go.probo.inc/probo/pkg/riskmanagement"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/authz"
"go.probo.inc/probo/pkg/server/api/mcp/v1/types"
"go.probo.inc/probo/pkg/thirdparty"
"go.probo.inc/probo/pkg/validator"
)
// ListOrganizationsTool handles the listOrganizations tool
// List all organizations the user has access to
func (r *Resolver) ListOrganizationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListOrganizationsInput) (*mcp.CallToolResult, types.ListOrganizationsOutput, error) {
user := authn.IdentityFromContext(ctx)
organizations, err := r.iamSvc.AccountService.ListOrganizations(ctx, user.ID)
if err != nil {
return nil, types.ListOrganizationsOutput{}, fmt.Errorf("failed to list organizations: %w", err)
}
result := types.ListOrganizationsOutput{
Organizations: make([]*types.Organization, 0, len(organizations)),
}
for _, org := range organizations {
result.Organizations = append(result.Organizations, types.NewOrganization(org))
}
return nil, result, nil
}
// ListThirdPartiesTool handles the listThirdParties tool
// List all thirdParties for the organization
func (r *Resolver) ListThirdPartiesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartiesInput) (*mcp.CallToolResult, types.ListThirdPartiesOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyList)
if err != nil {
return nil, types.ListThirdPartiesOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ThirdPartyOrderField]{
Field: coredata.ThirdPartyOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ThirdPartyOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
thirdPartyFilter := coredata.NewThirdPartyFilter(nil, input.Level, nil, nil, nil)
page, err := prb.ThirdParties.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, thirdPartyFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization thirdParties: %w", err))
}
return nil, types.NewListThirdPartiesOutput(page), nil
}
// AddThirdPartyTool handles the addThirdParty tool
// Add a new thirdParty to the organization
func (r *Resolver) AddThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddThirdPartyInput) (*mcp.CallToolResult, types.AddThirdPartyOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyCreate)
if err != nil {
return nil, types.AddThirdPartyOutput{}, err
}
svc := r.proboSvc
var category *coredata.ThirdPartyCategory
if input.Category != nil {
cat := coredata.ThirdPartyCategory(*input.Category)
category = &cat
}
var countries coredata.CountryCodes
if len(input.Countries) > 0 {
countries = make(coredata.CountryCodes, len(input.Countries))
for i, c := range input.Countries {
countries[i] = coredata.CountryCode(c)
}
}
thirdParty, err := svc.ThirdParties.Create(
ctx, scope,
probo.CreateThirdPartyRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Category: category,
HeadquarterAddress: input.HeadquarterAddress,
LegalName: input.LegalName,
WebsiteURL: input.WebsiteURL,
PrivacyPolicyURL: input.PrivacyPolicyURL,
ServiceLevelAgreementURL: input.ServiceLevelAgreementURL,
DataProcessingAgreementURL: input.DataProcessingAgreementURL,
BusinessAssociateAgreementURL: input.BusinessAssociateAgreementURL,
SubprocessorsListURL: input.SubprocessorsListURL,
Certifications: input.Certifications,
Countries: countries,
BusinessOwnerID: input.BusinessOwnerID,
SecurityOwnerID: input.SecurityOwnerID,
StatusPageURL: input.StatusPageURL,
TermsOfServiceURL: input.TermsOfServiceURL,
SecurityPageURL: input.SecurityPageURL,
TrustPageURL: input.TrustPageURL,
},
)
if err != nil {
return nil, types.AddThirdPartyOutput{}, fmt.Errorf("failed to create thirdParty: %w", err)
}
return nil, types.NewAddThirdPartyOutput(thirdParty), nil
}
// UpdateThirdPartyTool handles the updateThirdParty tool
// Update an existing thirdParty
func (r *Resolver) UpdateThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateThirdPartyInput) (*mcp.CallToolResult, types.UpdateThirdPartyOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyUpdate)
if err != nil {
return nil, types.UpdateThirdPartyOutput{}, err
}
svc := r.proboSvc
var description **string
if input.Description != nil {
description = &input.Description
}
var headquarterAddress **string
if input.HeadquarterAddress != nil {
headquarterAddress = &input.HeadquarterAddress
}
var legalName **string
if input.LegalName != nil {
legalName = &input.LegalName
}
var websiteURL **string
if input.WebsiteURL != nil {
websiteURL = &input.WebsiteURL
}
var privacyPolicyURL **string
if input.PrivacyPolicyURL != nil {
privacyPolicyURL = &input.PrivacyPolicyURL
}
var serviceLevelAgreementURL **string
if input.ServiceLevelAgreementURL != nil {
serviceLevelAgreementURL = &input.ServiceLevelAgreementURL
}
var dataProcessingAgreementURL **string
if input.DataProcessingAgreementURL != nil {
dataProcessingAgreementURL = &input.DataProcessingAgreementURL
}
var businessAssociateAgreementURL **string
if input.BusinessAssociateAgreementURL != nil {
businessAssociateAgreementURL = &input.BusinessAssociateAgreementURL
}
var subprocessorsListURL **string
if input.SubprocessorsListURL != nil {
subprocessorsListURL = &input.SubprocessorsListURL
}
var statusPageURL **string
if input.StatusPageURL != nil {
statusPageURL = &input.StatusPageURL
}
var termsOfServiceURL **string
if input.TermsOfServiceURL != nil {
termsOfServiceURL = &input.TermsOfServiceURL
}
var securityPageURL **string
if input.SecurityPageURL != nil {
securityPageURL = &input.SecurityPageURL
}
var trustPageURL **string
if input.TrustPageURL != nil {
trustPageURL = &input.TrustPageURL
}
var businessOwnerID **gid.GID
if input.BusinessOwnerID != nil {
businessOwnerID = &input.BusinessOwnerID
}
var securityOwnerID **gid.GID
if input.SecurityOwnerID != nil {
securityOwnerID = &input.SecurityOwnerID
}
var category *coredata.ThirdPartyCategory
if input.Category != nil {
cat := coredata.ThirdPartyCategory(*input.Category)
category = &cat
}
var countries coredata.CountryCodes
if len(input.Countries) > 0 {
countries = make(coredata.CountryCodes, len(input.Countries))
for i, c := range input.Countries {
countries[i] = coredata.CountryCode(c)
}
}
thirdParty, err := svc.ThirdParties.Update(
ctx, scope,
probo.UpdateThirdPartyRequest{
ID: input.ID,
Name: input.Name,
Description: description,
Category: category,
HeadquarterAddress: headquarterAddress,
LegalName: legalName,
WebsiteURL: websiteURL,
PrivacyPolicyURL: privacyPolicyURL,
ServiceLevelAgreementURL: serviceLevelAgreementURL,
DataProcessingAgreementURL: dataProcessingAgreementURL,
BusinessAssociateAgreementURL: businessAssociateAgreementURL,
SubprocessorsListURL: subprocessorsListURL,
Certifications: input.Certifications,
Countries: countries,
BusinessOwnerID: businessOwnerID,
SecurityOwnerID: securityOwnerID,
StatusPageURL: statusPageURL,
TermsOfServiceURL: termsOfServiceURL,
SecurityPageURL: securityPageURL,
TrustPageURL: trustPageURL,
},
)
if err != nil {
return nil, types.UpdateThirdPartyOutput{}, fmt.Errorf("failed to update thirdParty: %w", err)
}
return nil, types.NewUpdateThirdPartyOutput(thirdParty), nil
}
func (r *Resolver) ListRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRisksInput) (*mcp.CallToolResult, types.ListRisksOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskList)
if err != nil {
return nil, types.ListRisksOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
Field: coredata.RiskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
riskFilter := coredata.NewRiskFilter(nil)
if input.Filter != nil {
riskFilter = coredata.NewRiskFilter(input.Filter.Query)
}
page, err := prb.Risks.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, riskFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization risks: %w", err))
}
return nil, types.NewListRisksOutput(page), nil
}
func (r *Resolver) GetRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskInput) (*mcp.CallToolResult, types.GetRiskOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskGet)
if err != nil {
return nil, types.GetRiskOutput{}, err
}
prb := r.proboSvc
risk, err := prb.Risks.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskOutput{}, fmt.Errorf("failed to get risk: %w", err)
}
return nil, types.GetRiskOutput{
Risk: types.NewRisk(risk),
}, nil
}
func (r *Resolver) AddRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskInput) (*mcp.CallToolResult, types.AddRiskOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskCreate)
if err != nil {
return nil, types.AddRiskOutput{}, err
}
svc := r.proboSvc
risk, err := svc.Risks.Create(
ctx, scope,
probo.CreateRiskRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Category: input.Category,
Treatment: input.Treatment,
InherentLikelihood: input.InherentLikelihood,
InherentImpact: input.InherentImpact,
ResidualLikelihood: input.ResidualLikelihood,
ResidualImpact: input.ResidualImpact,
},
)
if err != nil {
return nil, types.AddRiskOutput{}, fmt.Errorf("failed to create risk: %w", err)
}
return nil, types.AddRiskOutput{
Risk: types.NewRisk(risk),
}, nil
}
func (r *Resolver) UpdateRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskInput) (*mcp.CallToolResult, types.UpdateRiskOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskUpdate)
if err != nil {
return nil, types.UpdateRiskOutput{}, err
}
svc := r.proboSvc
risk, err := svc.Risks.Update(
ctx, scope,
probo.UpdateRiskRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
Category: input.Category,
Treatment: input.Treatment,
OwnerID: UnwrapOmittable(input.OwnerID),
InherentLikelihood: input.InherentLikelihood,
InherentImpact: input.InherentImpact,
ResidualLikelihood: input.ResidualLikelihood,
ResidualImpact: input.ResidualImpact,
Note: input.Note,
},
)
if err != nil {
return nil, types.UpdateRiskOutput{}, fmt.Errorf("failed to update risk: %w", err)
}
return nil, types.UpdateRiskOutput{
Risk: types.NewRisk(risk),
}, nil
}
func (r *Resolver) ListMeasuresTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasuresInput) (*mcp.CallToolResult, types.ListMeasuresOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionMeasureList)
if err != nil {
return nil, types.ListMeasuresOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
var measureFilter = coredata.NewMeasureFilter(nil, nil, nil)
if input.Filter != nil {
measureFilter = coredata.NewMeasureFilter(input.Filter.Query, input.Filter.State, input.Filter.Category)
}
page, err := prb.Measures.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, measureFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization measures: %w", err))
}
return nil, types.NewListMeasuresOutput(page), nil
}
func (r *Resolver) GetMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetMeasureInput) (*mcp.CallToolResult, types.GetMeasureOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionMeasureGet)
if err != nil {
return nil, types.GetMeasureOutput{}, err
}
prb := r.proboSvc
measure, err := prb.Measures.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetMeasureOutput{}, fmt.Errorf("failed to get measure: %w", err)
}
return nil, types.GetMeasureOutput{
Measure: types.NewMeasure(measure),
}, nil
}
func (r *Resolver) AddMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddMeasureInput) (*mcp.CallToolResult, types.AddMeasureOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionMeasureCreate)
if err != nil {
return nil, types.AddMeasureOutput{}, err
}
svc := r.proboSvc
measure, err := svc.Measures.Create(
ctx, scope,
probo.CreateMeasureRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Category: input.Category,
},
)
if err != nil {
return nil, types.AddMeasureOutput{}, fmt.Errorf("failed to create measure: %w", err)
}
return nil, types.AddMeasureOutput{
Measure: types.NewMeasure(measure),
}, nil
}
func (r *Resolver) UpdateMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMeasureInput) (*mcp.CallToolResult, types.UpdateMeasureOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionMeasureUpdate)
if err != nil {
return nil, types.UpdateMeasureOutput{}, err
}
svc := r.proboSvc
measure, err := svc.Measures.Update(
ctx, scope,
probo.UpdateMeasureRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
Category: input.Category,
State: input.State,
},
)
if err != nil {
return nil, types.UpdateMeasureOutput{}, fmt.Errorf("failed to update measure: %w", err)
}
return nil, types.UpdateMeasureOutput{
Measure: types.NewMeasure(measure),
}, nil
}
func (r *Resolver) ListFrameworksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListFrameworksInput) (*mcp.CallToolResult, types.ListFrameworksOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFrameworkList)
if err != nil {
return nil, types.ListFrameworksOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.FrameworkOrderField]{
Field: coredata.FrameworkOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.FrameworkOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.Frameworks.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization frameworks: %w", err))
}
return nil, types.NewListFrameworksOutput(page), nil
}
func (r *Resolver) GetFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetFrameworkInput) (*mcp.CallToolResult, types.GetFrameworkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionFrameworkGet)
if err != nil {
return nil, types.GetFrameworkOutput{}, err
}
prb := r.proboSvc
framework, err := prb.Frameworks.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetFrameworkOutput{}, fmt.Errorf("failed to get framework: %w", err)
}
return nil, types.GetFrameworkOutput{
Framework: types.NewFramework(framework),
}, nil
}
func (r *Resolver) AddFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddFrameworkInput) (*mcp.CallToolResult, types.AddFrameworkOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFrameworkCreate)
if err != nil {
return nil, types.AddFrameworkOutput{}, err
}
svc := r.proboSvc
framework, err := svc.Frameworks.Create(
ctx, scope,
probo.CreateFrameworkRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
},
)
if err != nil {
return nil, types.AddFrameworkOutput{}, fmt.Errorf("failed to create framework: %w", err)
}
return nil, types.AddFrameworkOutput{
Framework: types.NewFramework(framework),
}, nil
}
func (r *Resolver) UpdateFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateFrameworkInput) (*mcp.CallToolResult, types.UpdateFrameworkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionFrameworkUpdate)
if err != nil {
return nil, types.UpdateFrameworkOutput{}, err
}
svc := r.proboSvc
framework, err := svc.Frameworks.Update(
ctx, scope,
probo.UpdateFrameworkRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
},
)
if err != nil {
return nil, types.UpdateFrameworkOutput{}, fmt.Errorf("failed to update framework: %w", err)
}
return nil, types.UpdateFrameworkOutput{
Framework: types.NewFramework(framework),
}, nil
}
func (r *Resolver) ListAssetsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAssetsInput) (*mcp.CallToolResult, types.ListAssetsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAssetList)
if err != nil {
return nil, types.ListAssetsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.AssetOrderField]{
Field: coredata.AssetOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AssetOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.Assets.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization assets: %w", err))
}
return nil, types.NewListAssetsOutput(page), nil
}
func (r *Resolver) GetAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAssetInput) (*mcp.CallToolResult, types.GetAssetOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionAssetGet)
if err != nil {
return nil, types.GetAssetOutput{}, err
}
prb := r.proboSvc
asset, err := prb.Assets.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetAssetOutput{}, fmt.Errorf("failed to get asset: %w", err)
}
return nil, types.GetAssetOutput{
Asset: types.NewAsset(asset),
}, nil
}
func (r *Resolver) AddAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAssetInput) (*mcp.CallToolResult, types.AddAssetOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAssetCreate)
if err != nil {
return nil, types.AddAssetOutput{}, err
}
svc := r.proboSvc
asset, err := svc.Assets.Create(
ctx, scope,
probo.CreateAssetRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Amount: input.Amount,
OwnerID: input.OwnerID,
AssetType: input.AssetType,
DataTypesStored: input.DataTypesStored,
ThirdPartyIDs: input.ThirdPartyIds,
},
)
if err != nil {
return nil, types.AddAssetOutput{}, fmt.Errorf("failed to create asset: %w", err)
}
return nil, types.AddAssetOutput{
Asset: types.NewAsset(asset),
}, nil
}
func (r *Resolver) UpdateAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAssetInput) (*mcp.CallToolResult, types.UpdateAssetOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionAssetUpdate)
if err != nil {
return nil, types.UpdateAssetOutput{}, err
}
svc := r.proboSvc
asset, err := svc.Assets.Update(
ctx, scope,
probo.UpdateAssetRequest{
ID: input.ID,
Name: input.Name,
Amount: input.Amount,
OwnerID: input.OwnerID,
AssetType: input.AssetType,
DataTypesStored: input.DataTypesStored,
ThirdPartyIDs: input.ThirdPartyIds,
},
)
if err != nil {
return nil, types.UpdateAssetOutput{}, fmt.Errorf("failed to update asset: %w", err)
}
return nil, types.UpdateAssetOutput{
Asset: types.NewAsset(asset),
}, nil
}
func (r *Resolver) ListDataTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDataInput) (*mcp.CallToolResult, types.ListDataOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDatumList)
if err != nil {
return nil, types.ListDataOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.DatumOrderField]{
Field: coredata.DatumOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DatumOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.Data.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization data: %w", err))
}
return nil, types.NewListDataOutput(page), nil
}
func (r *Resolver) GetDatumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDatumInput) (*mcp.CallToolResult, types.GetDatumOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDatumGet)
if err != nil {
return nil, types.GetDatumOutput{}, err
}
prb := r.proboSvc
datum, err := prb.Data.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetDatumOutput{}, fmt.Errorf("failed to get datum: %w", err)
}
return nil, types.GetDatumOutput{
Datum: types.NewDatum(datum),
}, nil
}
func (r *Resolver) AddDatumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddDatumInput) (*mcp.CallToolResult, types.AddDatumOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDatumCreate)
if err != nil {
return nil, types.AddDatumOutput{}, err
}
svc := r.proboSvc
datum, err := svc.Data.Create(
ctx, scope,
probo.CreateDatumRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
DataClassification: input.DataClassification,
OwnerID: input.OwnerID,
ThirdPartyIDs: input.ThirdPartyIds,
},
)
if err != nil {
return nil, types.AddDatumOutput{}, fmt.Errorf("failed to create datum: %w", err)
}
return nil, types.AddDatumOutput{
Datum: types.NewDatum(datum),
}, nil
}
func (r *Resolver) UpdateDatumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateDatumInput) (*mcp.CallToolResult, types.UpdateDatumOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDatumUpdate)
if err != nil {
return nil, types.UpdateDatumOutput{}, err
}
svc := r.proboSvc
datum, err := svc.Data.Update(
ctx, scope,
probo.UpdateDatumRequest{
ID: input.ID,
Name: input.Name,
DataClassification: input.DataClassification,
OwnerID: input.OwnerID,
ThirdPartyIDs: input.ThirdPartyIds,
},
)
if err != nil {
return nil, types.UpdateDatumOutput{}, fmt.Errorf("failed to update datum: %w", err)
}
return nil, types.UpdateDatumOutput{
Datum: types.NewDatum(datum),
}, nil
}
func (r *Resolver) ListFindingsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListFindingsInput) (*mcp.CallToolResult, types.ListFindingsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFindingList)
if err != nil {
return nil, types.ListFindingsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.FindingOrderField]{
Field: coredata.FindingOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.FindingOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
findingFilter := coredata.NewFindingFilter(nil, nil, nil, nil)
if input.Filter != nil {
findingFilter = coredata.NewFindingFilter(
input.Filter.Kind,
input.Filter.Status,
input.Filter.Priority,
input.Filter.OwnerID,
)
}
page, err := prb.Findings.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, findingFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization findings: %w", err))
}
return nil, types.NewListFindingsOutput(page), nil
}
func (r *Resolver) GetFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetFindingInput) (*mcp.CallToolResult, types.GetFindingOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionFindingGet)
if err != nil {
return nil, types.GetFindingOutput{}, err
}
prb := r.proboSvc
finding, err := prb.Findings.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetFindingOutput{}, fmt.Errorf("cannot get finding: %w", err)
}
return nil, types.GetFindingOutput{
Finding: types.NewFinding(finding),
}, nil
}
func (r *Resolver) AddFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddFindingInput) (*mcp.CallToolResult, types.AddFindingOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFindingCreate)
if err != nil {
return nil, types.AddFindingOutput{}, err
}
svc := r.proboSvc
finding, err := svc.Findings.Create(
ctx, scope,
&probo.CreateFindingRequest{
OrganizationID: input.OrganizationID,
Kind: input.Kind,
Description: input.Description,
Source: input.Source,
IdentifiedOn: input.IdentifiedOn,
RootCause: input.RootCause,
CorrectiveAction: input.CorrectiveAction,
OwnerID: input.OwnerID,
DueDate: input.DueDate,
Status: input.Status,
Priority: input.Priority,
RiskID: input.RiskID,
EffectivenessCheck: input.EffectivenessCheck,
},
)
if err != nil {
return nil, types.AddFindingOutput{}, fmt.Errorf("failed to create finding: %w", err)
}
return nil, types.AddFindingOutput{
Finding: types.NewFinding(finding),
}, nil
}
func (r *Resolver) UpdateFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateFindingInput) (*mcp.CallToolResult, types.UpdateFindingOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionFindingUpdate)
if err != nil {
return nil, types.UpdateFindingOutput{}, err
}
svc := r.proboSvc
finding, err := svc.Findings.Update(
ctx, scope,
&probo.UpdateFindingRequest{
ID: input.ID,
Description: UnwrapOmittable(input.Description),
Source: UnwrapOmittable(input.Source),
IdentifiedOn: UnwrapOmittable(input.IdentifiedOn),
RootCause: UnwrapOmittable(input.RootCause),
CorrectiveAction: UnwrapOmittable(input.CorrectiveAction),
OwnerID: input.OwnerID,
DueDate: UnwrapOmittable(input.DueDate),
Status: input.Status,
Priority: input.Priority,
RiskID: UnwrapOmittable(input.RiskID),
EffectivenessCheck: UnwrapOmittable(input.EffectivenessCheck),
},
)
if err != nil {
return nil, types.UpdateFindingOutput{}, fmt.Errorf("failed to update finding: %w", err)
}
return nil, types.UpdateFindingOutput{
Finding: types.NewFinding(finding),
}, nil
}
func (r *Resolver) ListObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListObligationsInput) (*mcp.CallToolResult, types.ListObligationsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionObligationList)
if err != nil {
return nil, types.ListObligationsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
Field: coredata.ObligationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.Obligations.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization obligations: %w", err))
}
return nil, types.NewListObligationsOutput(page), nil
}
func (r *Resolver) GetObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetObligationInput) (*mcp.CallToolResult, types.GetObligationOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionObligationGet)
if err != nil {
return nil, types.GetObligationOutput{}, err
}
prb := r.proboSvc
obligation, err := prb.Obligations.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetObligationOutput{}, fmt.Errorf("failed to get obligation: %w", err)
}
return nil, types.GetObligationOutput{
Obligation: types.NewObligation(obligation),
}, nil
}
func (r *Resolver) AddObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddObligationInput) (*mcp.CallToolResult, types.AddObligationOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionObligationCreate)
if err != nil {
return nil, types.AddObligationOutput{}, err
}
svc := r.proboSvc
obligation, err := svc.Obligations.Create(
ctx, scope,
&probo.CreateObligationRequest{
OrganizationID: input.OrganizationID,
Area: input.Area,
Source: input.Source,
Requirement: input.Requirement,
ActionsToBeImplemented: input.ActionsToBeImplemented,
Regulator: input.Regulator,
OwnerID: input.OwnerID,
LastReviewDate: input.LastReviewDate,
DueDate: input.DueDate,
Status: *input.Status,
Type: *input.Type,
},
)
if err != nil {
return nil, types.AddObligationOutput{}, fmt.Errorf("failed to create obligation: %w", err)
}
return nil, types.AddObligationOutput{
Obligation: types.NewObligation(obligation),
}, nil
}
func (r *Resolver) UpdateObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateObligationInput) (*mcp.CallToolResult, types.UpdateObligationOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionObligationUpdate)
if err != nil {
return nil, types.UpdateObligationOutput{}, err
}
svc := r.proboSvc
obligation, err := svc.Obligations.Update(
ctx, scope,
&probo.UpdateObligationRequest{
ID: input.ID,
Area: UnwrapOmittable(input.Area),
Source: UnwrapOmittable(input.Source),
Requirement: UnwrapOmittable(input.Requirement),
ActionsToBeImplemented: UnwrapOmittable(input.ActionsToBeImplemented),
Regulator: UnwrapOmittable(input.Regulator),
OwnerID: input.OwnerID,
LastReviewDate: UnwrapOmittable(input.LastReviewDate),
DueDate: UnwrapOmittable(input.DueDate),
Status: input.Status,
Type: input.Type,
},
)
if err != nil {
return nil, types.UpdateObligationOutput{}, fmt.Errorf("failed to update obligation: %w", err)
}
return nil, types.UpdateObligationOutput{
Obligation: types.NewObligation(obligation),
}, nil
}
func (r *Resolver) ListProcessingActivitiesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListProcessingActivitiesInput) (*mcp.CallToolResult, types.ListProcessingActivitiesOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionProcessingActivityList)
if err != nil {
return nil, types.ListProcessingActivitiesOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ProcessingActivityOrderField]{
Field: coredata.ProcessingActivityOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ProcessingActivityOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.ProcessingActivities.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization processing activities: %w", err))
}
return nil, types.NewListProcessingActivitiesOutput(page), nil
}
func (r *Resolver) GetProcessingActivityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetProcessingActivityInput) (*mcp.CallToolResult, types.GetProcessingActivityOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionProcessingActivityGet)
if err != nil {
return nil, types.GetProcessingActivityOutput{}, err
}
prb := r.proboSvc
processingActivity, err := prb.ProcessingActivities.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetProcessingActivityOutput{}, fmt.Errorf("failed to get processing activity: %w", err)
}
return nil, types.GetProcessingActivityOutput{
ProcessingActivity: types.NewProcessingActivity(processingActivity),
}, nil
}
func (r *Resolver) AddProcessingActivityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddProcessingActivityInput) (*mcp.CallToolResult, types.AddProcessingActivityOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionProcessingActivityCreate)
if err != nil {
return nil, types.AddProcessingActivityOutput{}, err
}
svc := r.proboSvc
processingActivity, err := svc.ProcessingActivities.Create(
ctx, scope,
&probo.CreateProcessingActivityRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Purpose: input.Purpose,
DataSubjectCategory: input.DataSubjectCategory,
PersonalDataCategory: input.PersonalDataCategory,
SpecialOrCriminalData: input.SpecialOrCriminalData,
ConsentEvidenceLink: input.ConsentEvidenceLink,
LawfulBasis: input.LawfulBasis,
Recipients: input.Recipients,
Location: input.Location,
InternationalTransfers: input.InternationalTransfers,
TransferSafeguard: input.TransferSafeguard,
RetentionPeriod: input.RetentionPeriod,
SecurityMeasures: input.SecurityMeasures,
DataProtectionImpactAssessmentNeeded: input.DataProtectionImpactAssessmentNeeded,
TransferImpactAssessmentNeeded: input.TransferImpactAssessmentNeeded,
LastReviewDate: input.LastReviewDate,
NextReviewDate: input.NextReviewDate,
Role: input.Role,
DataProtectionOfficerID: input.DataProtectionOfficerID,
ThirdPartyIDs: input.ThirdPartyIds,
},
)
if err != nil {
return nil, types.AddProcessingActivityOutput{}, fmt.Errorf("failed to create processing activity: %w", err)
}
return nil, types.AddProcessingActivityOutput{
ProcessingActivity: types.NewProcessingActivity(processingActivity),
}, nil
}
func (r *Resolver) UpdateProcessingActivityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateProcessingActivityInput) (*mcp.CallToolResult, types.UpdateProcessingActivityOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionProcessingActivityUpdate)
if err != nil {
return nil, types.UpdateProcessingActivityOutput{}, err
}
svc := r.proboSvc
var thirdPartyIDs *[]gid.GID
if input.ThirdPartyIds != nil {
thirdPartyIDs = &input.ThirdPartyIds
}
processingActivity, err := svc.ProcessingActivities.Update(
ctx, scope,
&probo.UpdateProcessingActivityRequest{
ID: input.ID,
Name: input.Name,
Purpose: UnwrapOmittable(input.Purpose),
DataSubjectCategory: UnwrapOmittable(input.DataSubjectCategory),
PersonalDataCategory: UnwrapOmittable(input.PersonalDataCategory),
SpecialOrCriminalData: input.SpecialOrCriminalData,
ConsentEvidenceLink: UnwrapOmittable(input.ConsentEvidenceLink),
LawfulBasis: input.LawfulBasis,
Recipients: UnwrapOmittable(input.Recipients),
Location: UnwrapOmittable(input.Location),
InternationalTransfers: input.InternationalTransfers,
TransferSafeguard: UnwrapOmittable(input.TransferSafeguard),
RetentionPeriod: UnwrapOmittable(input.RetentionPeriod),
SecurityMeasures: UnwrapOmittable(input.SecurityMeasures),
DataProtectionImpactAssessmentNeeded: input.DataProtectionImpactAssessmentNeeded,
TransferImpactAssessmentNeeded: input.TransferImpactAssessmentNeeded,
LastReviewDate: UnwrapOmittable(input.LastReviewDate),
NextReviewDate: UnwrapOmittable(input.NextReviewDate),
Role: input.Role,
DataProtectionOfficerID: UnwrapOmittable(input.DataProtectionOfficerID),
ThirdPartyIDs: thirdPartyIDs,
},
)
if err != nil {
return nil, types.UpdateProcessingActivityOutput{}, fmt.Errorf("failed to update processing activity: %w", err)
}
return nil, types.UpdateProcessingActivityOutput{
ProcessingActivity: types.NewProcessingActivity(processingActivity),
}, nil
}
func (r *Resolver) DeleteProcessingActivityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteProcessingActivityInput) (*mcp.CallToolResult, types.DeleteProcessingActivityOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionProcessingActivityDelete)
if err != nil {
return nil, types.DeleteProcessingActivityOutput{}, err
}
svc := r.proboSvc
err = svc.ProcessingActivities.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteProcessingActivityOutput{}, fmt.Errorf("failed to delete processing activity: %w", err)
}
return nil, types.DeleteProcessingActivityOutput{
DeletedProcessingActivityID: input.ID,
}, nil
}
func (r *Resolver) ListDataProtectionImpactAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDataProtectionImpactAssessmentsInput) (*mcp.CallToolResult, types.ListDataProtectionImpactAssessmentsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDataProtectionImpactAssessmentList)
if err != nil {
return nil, types.ListDataProtectionImpactAssessmentsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.DataProtectionImpactAssessmentOrderField]{
Field: coredata.DataProtectionImpactAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DataProtectionImpactAssessmentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.DataProtectionImpactAssessments.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization data protection impact assessments: %w", err))
}
return nil, types.NewListDataProtectionImpactAssessmentsOutput(page), nil
}
func (r *Resolver) GetDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.GetDataProtectionImpactAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentGet)
if err != nil {
return nil, types.GetDataProtectionImpactAssessmentOutput{}, err
}
prb := r.proboSvc
dpia, err := prb.DataProtectionImpactAssessments.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetDataProtectionImpactAssessmentOutput{}, fmt.Errorf("failed to get data protection impact assessment: %w", err)
}
return nil, types.GetDataProtectionImpactAssessmentOutput{
DataProtectionImpactAssessment: types.NewDataProtectionImpactAssessment(dpia),
}, nil
}
func (r *Resolver) AddDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.AddDataProtectionImpactAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ProcessingActivityID, probo.ActionDataProtectionImpactAssessmentCreate)
if err != nil {
return nil, types.AddDataProtectionImpactAssessmentOutput{}, err
}
svc := r.proboSvc
dpia, err := svc.DataProtectionImpactAssessments.Create(
ctx, scope,
&probo.CreateDataProtectionImpactAssessmentRequest{
ProcessingActivityID: input.ProcessingActivityID,
Description: input.Description,
NecessityAndProportionality: input.NecessityAndProportionality,
PotentialRisk: input.PotentialRisk,
Mitigations: input.Mitigations,
ResidualRisk: input.ResidualRisk,
},
)
if err != nil {
return nil, types.AddDataProtectionImpactAssessmentOutput{}, fmt.Errorf("failed to create data protection impact assessment: %w", err)
}
return nil, types.AddDataProtectionImpactAssessmentOutput{
DataProtectionImpactAssessment: types.NewDataProtectionImpactAssessment(dpia),
}, nil
}
func (r *Resolver) UpdateDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.UpdateDataProtectionImpactAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentUpdate)
if err != nil {
return nil, types.UpdateDataProtectionImpactAssessmentOutput{}, err
}
svc := r.proboSvc
dpia, err := svc.DataProtectionImpactAssessments.Update(
ctx, scope,
&probo.UpdateDataProtectionImpactAssessmentRequest{
ID: input.ID,
Description: UnwrapOmittable(input.Description),
NecessityAndProportionality: UnwrapOmittable(input.NecessityAndProportionality),
PotentialRisk: UnwrapOmittable(input.PotentialRisk),
Mitigations: UnwrapOmittable(input.Mitigations),
ResidualRisk: input.ResidualRisk,
},
)
if err != nil {
return nil, types.UpdateDataProtectionImpactAssessmentOutput{}, fmt.Errorf("failed to update data protection impact assessment: %w", err)
}
return nil, types.UpdateDataProtectionImpactAssessmentOutput{
DataProtectionImpactAssessment: types.NewDataProtectionImpactAssessment(dpia),
}, nil
}
func (r *Resolver) ListTransferImpactAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTransferImpactAssessmentsInput) (*mcp.CallToolResult, types.ListTransferImpactAssessmentsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionTransferImpactAssessmentList)
if err != nil {
return nil, types.ListTransferImpactAssessmentsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.TransferImpactAssessmentOrderField]{
Field: coredata.TransferImpactAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.TransferImpactAssessmentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.TransferImpactAssessments.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization transfer impact assessments: %w", err))
}
return nil, types.NewListTransferImpactAssessmentsOutput(page), nil
}
func (r *Resolver) GetTransferImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTransferImpactAssessmentInput) (*mcp.CallToolResult, types.GetTransferImpactAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTransferImpactAssessmentGet)
if err != nil {
return nil, types.GetTransferImpactAssessmentOutput{}, err
}
prb := r.proboSvc
tia, err := prb.TransferImpactAssessments.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetTransferImpactAssessmentOutput{}, fmt.Errorf("failed to get transfer impact assessment: %w", err)
}
return nil, types.GetTransferImpactAssessmentOutput{
TransferImpactAssessment: types.NewTransferImpactAssessment(tia),
}, nil
}
func (r *Resolver) AddTransferImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTransferImpactAssessmentInput) (*mcp.CallToolResult, types.AddTransferImpactAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ProcessingActivityID, probo.ActionTransferImpactAssessmentCreate)
if err != nil {
return nil, types.AddTransferImpactAssessmentOutput{}, err
}
svc := r.proboSvc
tia, err := svc.TransferImpactAssessments.Create(
ctx, scope,
&probo.CreateTransferImpactAssessmentRequest{
ProcessingActivityID: input.ProcessingActivityID,
DataSubjects: input.DataSubjects,
LegalMechanism: input.LegalMechanism,
Transfer: input.Transfer,
LocalLawRisk: input.LocalLawRisk,
SupplementaryMeasures: input.SupplementaryMeasures,
},
)
if err != nil {
return nil, types.AddTransferImpactAssessmentOutput{}, fmt.Errorf("failed to create transfer impact assessment: %w", err)
}
return nil, types.AddTransferImpactAssessmentOutput{
TransferImpactAssessment: types.NewTransferImpactAssessment(tia),
}, nil
}
func (r *Resolver) UpdateTransferImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTransferImpactAssessmentInput) (*mcp.CallToolResult, types.UpdateTransferImpactAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTransferImpactAssessmentUpdate)
if err != nil {
return nil, types.UpdateTransferImpactAssessmentOutput{}, err
}
svc := r.proboSvc
tia, err := svc.TransferImpactAssessments.Update(
ctx, scope,
&probo.UpdateTransferImpactAssessmentRequest{
ID: input.ID,
DataSubjects: UnwrapOmittable(input.DataSubjects),
LegalMechanism: UnwrapOmittable(input.LegalMechanism),
Transfer: UnwrapOmittable(input.Transfer),
LocalLawRisk: UnwrapOmittable(input.LocalLawRisk),
SupplementaryMeasures: UnwrapOmittable(input.SupplementaryMeasures),
},
)
if err != nil {
return nil, types.UpdateTransferImpactAssessmentOutput{}, fmt.Errorf("failed to update transfer impact assessment: %w", err)
}
return nil, types.UpdateTransferImpactAssessmentOutput{
TransferImpactAssessment: types.NewTransferImpactAssessment(tia),
}, nil
}
func (r *Resolver) DeleteTransferImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTransferImpactAssessmentInput) (*mcp.CallToolResult, types.DeleteTransferImpactAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTransferImpactAssessmentDelete)
if err != nil {
return nil, types.DeleteTransferImpactAssessmentOutput{}, err
}
svc := r.proboSvc
err = svc.TransferImpactAssessments.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteTransferImpactAssessmentOutput{}, fmt.Errorf("failed to delete transfer impact assessment: %w", err)
}
return nil, types.DeleteTransferImpactAssessmentOutput{
DeletedTransferImpactAssessmentID: input.ID,
}, nil
}
func (r *Resolver) ListAuditsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAuditsInput) (*mcp.CallToolResult, types.ListAuditsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAuditList)
if err != nil {
return nil, types.ListAuditsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
Field: coredata.AuditOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.Audits.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization audits: %w", err))
}
return nil, types.NewListAuditsOutput(page), nil
}
func (r *Resolver) GetAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAuditInput) (*mcp.CallToolResult, types.GetAuditOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionAuditGet)
if err != nil {
return nil, types.GetAuditOutput{}, err
}
prb := r.proboSvc
audit, err := prb.Audits.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetAuditOutput{}, fmt.Errorf("cannot get audit: %w", err)
}
var file *coredata.File
if audit.ReportFileID != nil {
file, err = prb.Files.Get(ctx, scope, *audit.ReportFileID)
if err != nil {
return nil, types.GetAuditOutput{}, fmt.Errorf("cannot get audit report file: %w", err)
}
}
return nil, types.GetAuditOutput{
Audit: types.NewAudit(audit, file),
}, nil
}
func (r *Resolver) AddAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAuditInput) (*mcp.CallToolResult, types.AddAuditOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAuditCreate)
if err != nil {
return nil, types.AddAuditOutput{}, err
}
svc := r.proboSvc
audit, err := svc.Audits.Create(
ctx, scope,
&probo.CreateAuditRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
ValidFrom: input.ValidFrom,
ValidUntil: input.ValidUntil,
State: input.State,
FrameworkID: input.FrameworkID,
},
)
if err != nil {
return nil, types.AddAuditOutput{}, fmt.Errorf("failed to create audit: %w", err)
}
return nil, types.AddAuditOutput{
Audit: types.NewAudit(audit, nil),
}, nil
}
func (r *Resolver) UpdateAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAuditInput) (*mcp.CallToolResult, types.UpdateAuditOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionAuditUpdate)
if err != nil {
return nil, types.UpdateAuditOutput{}, err
}
svc := r.proboSvc
audit, err := svc.Audits.Update(
ctx, scope,
&probo.UpdateAuditRequest{
ID: input.ID,
Name: UnwrapOmittable(input.Name),
ValidFrom: input.ValidFrom,
ValidUntil: input.ValidUntil,
State: input.State,
TrustCenterVisibility: input.TrustCenterVisibility,
},
)
if err != nil {
return nil, types.UpdateAuditOutput{}, fmt.Errorf("cannot update audit: %w", err)
}
var file *coredata.File
if audit.ReportFileID != nil {
file, err = svc.Files.Get(ctx, scope, *audit.ReportFileID)
if err != nil {
return nil, types.UpdateAuditOutput{}, fmt.Errorf("cannot get audit report file: %w", err)
}
}
return nil, types.UpdateAuditOutput{
Audit: types.NewAudit(audit, file),
}, nil
}
func (r *Resolver) ListControlsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlsInput) (*mcp.CallToolResult, types.ListControlsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionControlList)
if err != nil {
return nil, types.ListControlsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
var controlFilter = coredata.NewControlFilter(nil)
if input.Filter != nil {
controlFilter = coredata.NewControlFilter(input.Filter.Query)
}
var (
controlPage *page.Page[*coredata.Control, coredata.ControlOrderField]
)
if input.Filter != nil && input.Filter.FrameworkID != nil {
controlPage, err = prb.Controls.ListForFrameworkID(ctx, scope, *input.Filter.FrameworkID, cursor, controlFilter)
} else {
controlPage, err = prb.Controls.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor, controlFilter)
}
if err != nil {
panic(fmt.Errorf("cannot list organization controls: %w", err))
}
return nil, types.NewListControlsOutput(controlPage), nil
}
func (r *Resolver) GetControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetControlInput) (*mcp.CallToolResult, types.GetControlOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionControlGet)
if err != nil {
return nil, types.GetControlOutput{}, err
}
prb := r.proboSvc
control, err := prb.Controls.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetControlOutput{}, fmt.Errorf("failed to get control: %w", err)
}
return nil, types.GetControlOutput{
Control: types.NewControl(control),
}, nil
}
func (r *Resolver) AddControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddControlInput) (*mcp.CallToolResult, types.AddControlOutput, error) {
scope, err := r.Authorize(ctx, input.FrameworkID, probo.ActionControlCreate)
if err != nil {
return nil, types.AddControlOutput{}, err
}
svc := r.proboSvc
control, err := svc.Controls.Create(
ctx, scope,
probo.CreateControlRequest{
FrameworkID: input.FrameworkID,
Name: input.Name,
Description: input.Description,
SectionTitle: input.SectionTitle,
BestPractice: input.BestPractice,
MaturityLevel: coredata.ControlMaturityLevel(input.MaturityLevel),
NotImplementedJustification: input.NotImplementedJustification,
},
)
if err != nil {
return nil, types.AddControlOutput{}, fmt.Errorf("failed to create control: %w", err)
}
return nil, types.AddControlOutput{
Control: types.NewControl(control),
}, nil
}
func (r *Resolver) UpdateControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateControlInput) (*mcp.CallToolResult, types.UpdateControlOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionControlUpdate)
if err != nil {
return nil, types.UpdateControlOutput{}, err
}
svc := r.proboSvc
var maturityLevel *coredata.ControlMaturityLevel
if input.MaturityLevel != nil {
v := coredata.ControlMaturityLevel(*input.MaturityLevel)
maturityLevel = &v
}
control, err := svc.Controls.Update(
ctx, scope,
probo.UpdateControlRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
SectionTitle: input.SectionTitle,
BestPractice: input.BestPractice,
MaturityLevel: maturityLevel,
NotImplementedJustification: UnwrapOmittable(input.NotImplementedJustification),
},
)
if err != nil {
return nil, types.UpdateControlOutput{}, fmt.Errorf("failed to update control: %w", err)
}
return nil, types.UpdateControlOutput{
Control: types.NewControl(control),
}, nil
}
func (r *Resolver) LinkControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkControlInput) (*mcp.CallToolResult, types.LinkControlOutput, error) {
svc := r.proboSvc
switch input.ResourceID.EntityType() {
case coredata.MeasureEntityType:
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlMeasureMappingCreate)
if err != nil {
return nil, types.LinkControlOutput{}, err
}
if _, _, err := svc.Controls.CreateMeasureMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to measure: %w", err)
}
case coredata.DocumentEntityType:
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlDocumentMappingCreate)
if err != nil {
return nil, types.LinkControlOutput{}, err
}
if _, _, err := svc.Controls.CreateDocumentMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to document: %w", err)
}
case coredata.AuditEntityType:
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlAuditMappingCreate)
if err != nil {
return nil, types.LinkControlOutput{}, err
}
if _, _, err := svc.Controls.CreateAuditMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to audit: %w", err)
}
case coredata.ObligationEntityType:
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlObligationMappingCreate)
if err != nil {
return nil, types.LinkControlOutput{}, err
}
if _, _, err := svc.Controls.CreateObligationMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to obligation: %w", err)
}
default:
return nil, types.LinkControlOutput{}, fmt.Errorf("unsupported resource type for control linking: entity type %d", input.ResourceID.EntityType())
}
return nil, types.LinkControlOutput{}, nil
}
func (r *Resolver) UnlinkControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkControlInput) (*mcp.CallToolResult, types.UnlinkControlOutput, error) {
svc := r.proboSvc
switch input.ResourceID.EntityType() {
case coredata.MeasureEntityType:
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlMeasureMappingDelete)
if err != nil {
return nil, types.UnlinkControlOutput{}, err
}
if _, _, err := svc.Controls.DeleteMeasureMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from measure: %w", err)
}
case coredata.DocumentEntityType:
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlDocumentMappingDelete)
if err != nil {
return nil, types.UnlinkControlOutput{}, err
}
if _, _, err := svc.Controls.DeleteDocumentMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from document: %w", err)
}
case coredata.AuditEntityType:
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlAuditMappingDelete)
if err != nil {
return nil, types.UnlinkControlOutput{}, err
}
if _, _, err := svc.Controls.DeleteAuditMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from audit: %w", err)
}
case coredata.ObligationEntityType:
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlObligationMappingDelete)
if err != nil {
return nil, types.UnlinkControlOutput{}, err
}
if _, _, err := svc.Controls.DeleteObligationMapping(ctx, scope, input.ControlID, input.ResourceID); err != nil {
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from obligation: %w", err)
}
default:
return nil, types.UnlinkControlOutput{}, fmt.Errorf("unsupported resource type for control unlinking: entity type %d", input.ResourceID.EntityType())
}
return nil, types.UnlinkControlOutput{}, nil
}
func (r *Resolver) ListControlObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlObligationsInput) (*mcp.CallToolResult, types.ListControlObligationsOutput, error) {
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlGet)
if err != nil {
return nil, types.ListControlObligationsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
Field: coredata.ObligationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
obligationPage, err := prb.Obligations.ListForControlID(ctx, scope, input.ControlID, cursor)
if err != nil {
return nil, types.ListControlObligationsOutput{}, fmt.Errorf("failed to list control obligations: %w", err)
}
return nil, types.NewListControlObligationsOutput(obligationPage), nil
}
func (r *Resolver) ListControlMeasuresTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlMeasuresInput) (*mcp.CallToolResult, types.ListControlMeasuresOutput, error) {
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlGet)
if err != nil {
return nil, types.ListControlMeasuresOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
measurePage, err := prb.Measures.ListForControlID(ctx, scope, input.ControlID, cursor, coredata.NewMeasureFilter(nil, nil, nil))
if err != nil {
return nil, types.ListControlMeasuresOutput{}, fmt.Errorf("failed to list control measures: %w", err)
}
return nil, types.NewListControlMeasuresOutput(measurePage), nil
}
func (r *Resolver) ListControlDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlDocumentsInput) (*mcp.CallToolResult, types.ListControlDocumentsOutput, error) {
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlGet)
if err != nil {
return nil, types.ListControlDocumentsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
docPage, err := prb.Documents.ListForControlID(ctx, scope, input.ControlID, cursor, coredata.NewDocumentFilter(nil))
if err != nil {
return nil, types.ListControlDocumentsOutput{}, fmt.Errorf("failed to list control documents: %w", err)
}
return nil, types.NewListControlDocumentsOutput(docPage), nil
}
func (r *Resolver) ListControlAuditsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlAuditsInput) (*mcp.CallToolResult, types.ListControlAuditsOutput, error) {
scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlGet)
if err != nil {
return nil, types.ListControlAuditsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
Field: coredata.AuditOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
auditPage, err := prb.Audits.ListForControlID(ctx, scope, input.ControlID, cursor)
if err != nil {
return nil, types.ListControlAuditsOutput{}, fmt.Errorf("failed to list control audits: %w", err)
}
return nil, types.NewListControlAuditsOutput(auditPage), nil
}
func (r *Resolver) ListRiskObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskObligationsInput) (*mcp.CallToolResult, types.ListRiskObligationsOutput, error) {
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskGet)
if err != nil {
return nil, types.ListRiskObligationsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
Field: coredata.ObligationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
obligationPage, err := prb.Obligations.ListForRiskID(ctx, scope, input.RiskID, cursor)
if err != nil {
return nil, types.ListRiskObligationsOutput{}, fmt.Errorf("failed to list risk obligations: %w", err)
}
return nil, types.NewListRiskObligationsOutput(obligationPage), nil
}
func (r *Resolver) LinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkRiskInput) (*mcp.CallToolResult, types.LinkRiskOutput, error) {
svc := r.proboSvc
switch input.ResourceID.EntityType() {
case coredata.DocumentEntityType:
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingCreate)
if err != nil {
return nil, types.LinkRiskOutput{}, err
}
if _, _, err := svc.Risks.CreateDocumentMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to document: %w", err)
}
case coredata.MeasureEntityType:
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingCreate)
if err != nil {
return nil, types.LinkRiskOutput{}, err
}
if _, _, err := svc.Risks.CreateMeasureMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to measure: %w", err)
}
case coredata.ObligationEntityType:
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskObligationMappingCreate)
if err != nil {
return nil, types.LinkRiskOutput{}, err
}
if _, _, err := svc.Risks.CreateObligationMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to obligation: %w", err)
}
default:
return nil, types.LinkRiskOutput{}, fmt.Errorf("unsupported resource type for risk linking: entity type %d", input.ResourceID.EntityType())
}
return nil, types.LinkRiskOutput{}, nil
}
func (r *Resolver) UnlinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkRiskInput) (*mcp.CallToolResult, types.UnlinkRiskOutput, error) {
svc := r.proboSvc
switch input.ResourceID.EntityType() {
case coredata.DocumentEntityType:
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingDelete)
if err != nil {
return nil, types.UnlinkRiskOutput{}, err
}
if _, _, err := svc.Risks.DeleteDocumentMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from document: %w", err)
}
case coredata.MeasureEntityType:
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingDelete)
if err != nil {
return nil, types.UnlinkRiskOutput{}, err
}
if _, _, err := svc.Risks.DeleteMeasureMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from measure: %w", err)
}
case coredata.ObligationEntityType:
scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskObligationMappingDelete)
if err != nil {
return nil, types.UnlinkRiskOutput{}, err
}
if _, _, err := svc.Risks.DeleteObligationMapping(ctx, scope, input.RiskID, input.ResourceID); err != nil {
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from obligation: %w", err)
}
default:
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("unsupported resource type for risk unlinking: entity type %d", input.ResourceID.EntityType())
}
return nil, types.UnlinkRiskOutput{}, nil
}
func (r *Resolver) ListTasksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTasksInput) (*mcp.CallToolResult, types.ListTasksOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionTaskList)
if err != nil {
return nil, types.ListTasksOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.TaskOrderField]{
Field: coredata.TaskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.TaskOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.Tasks.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization tasks: %w", err))
}
return nil, types.NewListTasksOutput(page), nil
}
func (r *Resolver) GetTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTaskInput) (*mcp.CallToolResult, types.GetTaskOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskGet)
if err != nil {
return nil, types.GetTaskOutput{}, err
}
prb := r.proboSvc
task, err := prb.Tasks.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetTaskOutput{}, fmt.Errorf("failed to get task: %w", err)
}
return nil, types.GetTaskOutput{
Task: types.NewTask(task),
}, nil
}
func (r *Resolver) AddTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTaskInput) (*mcp.CallToolResult, types.AddTaskOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionTaskCreate)
if err != nil {
return nil, types.AddTaskOutput{}, err
}
svc := r.proboSvc
priority := coredata.TaskPriorityMedium
if input.Priority != nil {
priority = *input.Priority
}
task, err := svc.Tasks.Create(
ctx, scope,
probo.CreateTaskRequest{
OrganizationID: input.OrganizationID,
MeasureID: input.MeasureID,
Name: input.Name,
Description: input.Description,
Priority: priority,
TimeEstimate: input.TimeEstimate,
Deadline: input.Deadline,
AssignedToID: input.AssignedToID,
},
)
if err != nil {
return nil, types.AddTaskOutput{}, fmt.Errorf("failed to create task: %w", err)
}
return nil, types.AddTaskOutput{
Task: types.NewTask(task),
}, nil
}
func (r *Resolver) UpdateTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTaskInput) (*mcp.CallToolResult, types.UpdateTaskOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskUpdate)
if err != nil {
return nil, types.UpdateTaskOutput{}, err
}
svc := r.proboSvc
task, err := svc.Tasks.Update(
ctx, scope,
probo.UpdateTaskRequest{
TaskID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
State: input.State,
Priority: input.Priority,
Rank: input.Rank,
TimeEstimate: UnwrapOmittable(input.TimeEstimate),
Deadline: UnwrapOmittable(input.Deadline),
AssignedToID: UnwrapOmittable(input.AssignedToID),
MeasureID: UnwrapOmittable(input.MeasureID),
},
)
if err != nil {
return nil, types.UpdateTaskOutput{}, fmt.Errorf("failed to update task: %w", err)
}
return nil, types.UpdateTaskOutput{
Task: types.NewTask(task),
}, nil
}
func (r *Resolver) AssignTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AssignTaskInput) (*mcp.CallToolResult, types.AssignTaskOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskAssign)
if err != nil {
return nil, types.AssignTaskOutput{}, err
}
svc := r.proboSvc
task, err := svc.Tasks.Assign(ctx, scope, input.ID, input.AssignedToID)
if err != nil {
return nil, types.AssignTaskOutput{}, fmt.Errorf("failed to assign task: %w", err)
}
return nil, types.AssignTaskOutput{
Task: types.NewTask(task),
}, nil
}
func (r *Resolver) UnassignTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnassignTaskInput) (*mcp.CallToolResult, types.UnassignTaskOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskUnassign)
if err != nil {
return nil, types.UnassignTaskOutput{}, err
}
svc := r.proboSvc
task, err := svc.Tasks.Unassign(ctx, scope, input.ID)
if err != nil {
return nil, types.UnassignTaskOutput{}, fmt.Errorf("failed to unassign task: %w", err)
}
return nil, types.UnassignTaskOutput{
Task: types.NewTask(task),
}, nil
}
func (r *Resolver) DeleteTaskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTaskInput) (*mcp.CallToolResult, types.DeleteTaskOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTaskDelete)
if err != nil {
return nil, types.DeleteTaskOutput{}, err
}
svc := r.proboSvc
err = svc.Tasks.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteTaskOutput{}, fmt.Errorf("failed to delete task: %w", err)
}
return nil, types.DeleteTaskOutput{
DeletedTaskID: input.ID,
}, nil
}
func (r *Resolver) ListDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentsInput) (*mcp.CallToolResult, types.ListDocumentsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDocumentList)
if err != nil {
return nil, types.ListDocumentsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
documentFilter := coredata.NewDocumentFilter(nil).
WithStatus([]coredata.DocumentStatus{coredata.DocumentStatusActive})
if input.Filter != nil {
var query *string
if input.Filter.Query != nil && *input.Filter.Query != "" {
query = input.Filter.Query
}
documentFilter = coredata.NewDocumentFilter(query).
WithWriteModes(input.Filter.WriteModes).
WithDocumentTypes(input.Filter.DocumentTypes).
WithClassifications(input.Filter.Classifications).
WithStatus(input.Filter.Status)
if len(input.Filter.Status) == 0 {
documentFilter = documentFilter.WithStatus([]coredata.DocumentStatus{coredata.DocumentStatusActive})
}
}
docPage, err := prb.Documents.ListByOrganizationID(ctx, scope, input.OrganizationID, cursor, documentFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization documents: %w", err))
}
return nil, types.NewListDocumentsOutput(docPage), nil
}
func (r *Resolver) GetDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentInput) (*mcp.CallToolResult, types.GetDocumentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentGet)
if err != nil {
return nil, types.GetDocumentOutput{}, err
}
prb := r.proboSvc
document, err := prb.Documents.Get(ctx, scope, input.ID)
if err != nil {
panic(fmt.Errorf("cannot get document: %w", err))
}
return nil, types.GetDocumentOutput{
Document: types.NewDocument(document),
}, nil
}
func (r *Resolver) AddDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddDocumentInput) (*mcp.CallToolResult, types.AddDocumentOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDocumentCreate)
if err != nil {
return nil, types.AddDocumentOutput{}, err
}
svc := r.proboSvc
var trustCenterVisibility *coredata.TrustCenterVisibility
if input.TrustCenterVisibility != nil {
trustCenterVisibility = input.TrustCenterVisibility
}
contentJSON, err := markdownToProseMirrorJSON(input.Content)
if err != nil {
panic(fmt.Errorf("cannot convert markdown to prosemirror: %w", err))
}
document, documentVersion, err := svc.Documents.Create(
ctx, scope,
probo.CreateDocumentRequest{
OrganizationID: input.OrganizationID,
Title: input.Title,
Content: contentJSON,
Classification: input.Classification,
DocumentType: input.DocumentType,
TrustCenterVisibility: trustCenterVisibility,
DefaultApproverIDs: input.DefaultApproverIds,
},
)
if err != nil {
panic(fmt.Errorf("cannot create document: %w", err))
}
return nil, types.NewAddDocumentOutput(document, documentVersion), nil
}
func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateDocumentInput) (*mcp.CallToolResult, types.UpdateDocumentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentUpdate)
if err != nil {
return nil, types.UpdateDocumentOutput{}, err
}
svc := r.proboSvc
var defaultApproverIDs *[]gid.GID
if input.DefaultApproverIds != nil {
defaultApproverIDs = &input.DefaultApproverIds
}
var content *string
if input.Content != nil {
c, err := markdownToProseMirrorJSON(*input.Content)
if err != nil {
panic(fmt.Errorf("cannot convert markdown to prosemirror: %w", err))
}
content = &c
}
document, documentVersion, _, err := svc.Documents.Update(
ctx, scope,
probo.UpdateDocumentRequest{
DocumentID: input.ID,
Title: input.Title,
Content: content,
Classification: input.Classification,
DocumentType: input.DocumentType,
TrustCenterVisibility: input.TrustCenterVisibility,
DefaultApproverIDs: defaultApproverIDs,
},
)
if err != nil {
panic(fmt.Errorf("cannot update document: %w", err))
}
output := types.UpdateDocumentOutput{
Document: types.NewDocument(document),
}
if documentVersion != nil {
output.DocumentVersion = types.NewDocumentVersion(documentVersion)
}
return nil, output, nil
}
func (r *Resolver) ListDocumentVersionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionsInput) (*mcp.CallToolResult, types.ListDocumentVersionsOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentID, probo.ActionDocumentVersionList)
if err != nil {
return nil, types.ListDocumentVersionsOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.DocumentVersionOrderField]{
Field: coredata.DocumentVersionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentVersionOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
svc := r.proboSvc
versionFilter := coredata.NewDocumentVersionFilter()
if input.Filter != nil && len(input.Filter.Statuses) > 0 {
versionFilter = versionFilter.WithStatuses(input.Filter.Statuses...)
}
versionPage, err := svc.Documents.ListVersions(ctx, scope, input.DocumentID, cursor, versionFilter)
if err != nil {
panic(fmt.Errorf("cannot list document versions: %w", err))
}
return nil, types.NewListDocumentVersionsOutput(versionPage), nil
}
func (r *Resolver) GetDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionInput) (*mcp.CallToolResult, types.GetDocumentVersionOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentVersionGet)
if err != nil {
return nil, types.GetDocumentVersionOutput{}, err
}
svc := r.proboSvc
version, err := svc.Documents.GetVersion(ctx, scope, input.ID)
if err != nil {
panic(fmt.Errorf("cannot get document version: %w", err))
}
return nil, types.GetDocumentVersionOutput{
DocumentVersion: types.NewDocumentVersion(version),
}, nil
}
func (r *Resolver) ListDocumentVersionSignaturesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionSignaturesInput) (*mcp.CallToolResult, types.ListDocumentVersionSignaturesOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSignatureList)
if err != nil {
return nil, types.ListDocumentVersionSignaturesOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
Field: coredata.DocumentVersionSignatureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
var (
signatureStates []coredata.DocumentVersionSignatureState
activeContract *bool
profileState *coredata.ProfileState
)
if input.Filter != nil {
if input.Filter.States != nil {
signatureStates = input.Filter.States
}
if input.Filter.ActiveContract != nil {
activeContract = input.Filter.ActiveContract
}
if input.Filter.ProfileState != nil {
profileState = input.Filter.ProfileState
}
}
signatureFilter := coredata.NewDocumentVersionSignatureFilter(signatureStates, activeContract, profileState)
page, err := prb.Documents.ListSignatures(ctx, scope, input.DocumentVersionID, cursor, signatureFilter)
if err != nil {
panic(fmt.Errorf("cannot list document version signatures: %w", err))
}
return nil, types.NewListDocumentVersionSignaturesOutput(page), nil
}
func (r *Resolver) GetDocumentVersionSignatureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionSignatureInput) (*mcp.CallToolResult, types.GetDocumentVersionSignatureOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentVersionSignatureGet)
if err != nil {
return nil, types.GetDocumentVersionSignatureOutput{}, err
}
prb := r.proboSvc
signature, err := prb.Documents.GetVersionSignature(ctx, scope, input.ID)
if err != nil {
panic(fmt.Errorf("cannot get document version signature: %w", err))
}
return nil, types.GetDocumentVersionSignatureOutput{
DocumentVersionSignature: types.NewDocumentVersionSignature(signature),
}, nil
}
func (r *Resolver) RequestDocumentVersionSignatureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RequestDocumentVersionSignatureInput) (*mcp.CallToolResult, types.RequestDocumentVersionSignatureOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSignatureRequest)
if err != nil {
return nil, types.RequestDocumentVersionSignatureOutput{}, err
}
svc := r.proboSvc
documentVersionSignature, err := svc.Documents.RequestSignature(
ctx, scope,
probo.RequestSignatureRequest{
DocumentVersionID: input.DocumentVersionID,
Signatory: input.SignatoryID,
},
)
if err != nil {
if _, ok := errors.AsType[*probo.ErrDocumentVersionNotCurrent](err); ok {
return nil, types.RequestDocumentVersionSignatureOutput{}, fmt.Errorf("cannot request signature: %w", err)
}
panic(fmt.Errorf("cannot request signature: %w", err))
}
return nil, types.RequestDocumentVersionSignatureOutput{
DocumentVersionSignature: types.NewDocumentVersionSignature(documentVersionSignature),
}, nil
}
func (r *Resolver) DeleteDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDocumentInput) (*mcp.CallToolResult, types.DeleteDocumentOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentID, probo.ActionDocumentDelete)
if err != nil {
return nil, types.DeleteDocumentOutput{}, err
}
svc := r.proboSvc
err = svc.Documents.SoftDelete(ctx, scope, input.DocumentID)
if err != nil {
panic(fmt.Errorf("cannot soft delete document: %w", err))
}
return nil, types.DeleteDocumentOutput{
DeletedDocumentID: input.DocumentID,
}, nil
}
func (r *Resolver) CancelSignatureRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CancelSignatureRequestInput) (*mcp.CallToolResult, types.CancelSignatureRequestOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentVersionSignatureID, probo.ActionDocumentVersionCancelSignature)
if err != nil {
return nil, types.CancelSignatureRequestOutput{}, err
}
svc := r.proboSvc
err = svc.Documents.CancelSignatureRequest(ctx, scope, input.DocumentVersionSignatureID)
if err != nil {
panic(fmt.Errorf("cannot cancel signature request: %w", err))
}
return nil, types.CancelSignatureRequestOutput{
DeletedDocumentVersionSignatureID: input.DocumentVersionSignatureID,
}, nil
}
func (r *Resolver) DeleteRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskInput) (*mcp.CallToolResult, types.DeleteRiskOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskDelete)
if err != nil {
return nil, types.DeleteRiskOutput{}, err
}
svc := r.proboSvc
err = svc.Risks.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteRiskOutput{}, fmt.Errorf("failed to delete risk: %w", err)
}
return nil, types.DeleteRiskOutput{
DeletedRiskID: input.ID,
}, nil
}
func (r *Resolver) DeleteMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteMeasureInput) (*mcp.CallToolResult, types.DeleteMeasureOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionMeasureDelete)
if err != nil {
return nil, types.DeleteMeasureOutput{}, err
}
svc := r.proboSvc
err = svc.Measures.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteMeasureOutput{}, fmt.Errorf("failed to delete measure: %w", err)
}
return nil, types.DeleteMeasureOutput{
DeletedMeasureID: input.ID,
}, nil
}
func (r *Resolver) ListMeasureRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureRisksInput) (*mcp.CallToolResult, types.ListMeasureRisksOutput, error) {
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
if err != nil {
return nil, types.ListMeasureRisksOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
Field: coredata.RiskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
riskPage, err := prb.Risks.ListForMeasureID(ctx, scope, input.MeasureID, cursor, coredata.NewRiskFilter(nil))
if err != nil {
return nil, types.ListMeasureRisksOutput{}, fmt.Errorf("failed to list measure risks: %w", err)
}
return nil, types.NewListMeasureRisksOutput(riskPage), nil
}
func (r *Resolver) ListMeasureControlsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureControlsInput) (*mcp.CallToolResult, types.ListMeasureControlsOutput, error) {
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
if err != nil {
return nil, types.ListMeasureControlsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
controlPage, err := prb.Controls.ListForMeasureID(ctx, scope, input.MeasureID, cursor, coredata.NewControlFilter(nil))
if err != nil {
return nil, types.ListMeasureControlsOutput{}, fmt.Errorf("failed to list measure controls: %w", err)
}
return nil, types.NewListMeasureControlsOutput(controlPage), nil
}
func (r *Resolver) ListMeasureTasksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureTasksInput) (*mcp.CallToolResult, types.ListMeasureTasksOutput, error) {
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
if err != nil {
return nil, types.ListMeasureTasksOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.TaskOrderField]{
Field: coredata.TaskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.TaskOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
taskPage, err := prb.Tasks.ListForMeasureID(ctx, scope, input.MeasureID, cursor)
if err != nil {
return nil, types.ListMeasureTasksOutput{}, fmt.Errorf("failed to list measure tasks: %w", err)
}
return nil, types.NewListMeasureTasksOutput(taskPage), nil
}
func (r *Resolver) ListMeasureEvidencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureEvidencesInput) (*mcp.CallToolResult, types.ListMeasureEvidencesOutput, error) {
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
if err != nil {
return nil, types.ListMeasureEvidencesOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.EvidenceOrderField]{
Field: coredata.EvidenceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
evidencePage, err := prb.Evidences.ListForMeasureID(ctx, scope, input.MeasureID, cursor)
if err != nil {
return nil, types.ListMeasureEvidencesOutput{}, fmt.Errorf("failed to list measure evidences: %w", err)
}
return nil, types.NewListMeasureEvidencesOutput(evidencePage), nil
}
func (r *Resolver) LinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkMeasureInput) (*mcp.CallToolResult, types.LinkMeasureOutput, error) {
svc := r.proboSvc
switch input.ResourceID.EntityType() {
case coredata.ControlEntityType:
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingCreate)
if err != nil {
return nil, types.LinkMeasureOutput{}, err
}
if _, _, err := svc.Controls.CreateMeasureMapping(ctx, scope, input.ResourceID, input.MeasureID); err != nil {
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to control: %w", err)
}
case coredata.RiskEntityType:
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingCreate)
if err != nil {
return nil, types.LinkMeasureOutput{}, err
}
if _, _, err := svc.Risks.CreateMeasureMapping(ctx, scope, input.ResourceID, input.MeasureID); err != nil {
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to risk: %w", err)
}
case coredata.DocumentEntityType:
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingCreate)
if err != nil {
return nil, types.LinkMeasureOutput{}, err
}
if _, _, err := svc.Measures.CreateDocumentMapping(ctx, scope, input.MeasureID, input.ResourceID); err != nil {
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to document: %w", err)
}
case coredata.ThirdPartyEntityType:
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureThirdPartyMappingCreate)
if err != nil {
return nil, types.LinkMeasureOutput{}, err
}
if _, _, err := svc.Measures.CreateThirdPartyMapping(ctx, scope, input.MeasureID, input.ResourceID); err != nil {
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to third party: %w", err)
}
default:
return nil, types.LinkMeasureOutput{}, fmt.Errorf("unsupported resource type for measure linking: entity type %d", input.ResourceID.EntityType())
}
return nil, types.LinkMeasureOutput{}, nil
}
func (r *Resolver) UnlinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkMeasureInput) (*mcp.CallToolResult, types.UnlinkMeasureOutput, error) {
svc := r.proboSvc
switch input.ResourceID.EntityType() {
case coredata.ControlEntityType:
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingDelete)
if err != nil {
return nil, types.UnlinkMeasureOutput{}, err
}
if _, _, err := svc.Controls.DeleteMeasureMapping(ctx, scope, input.ResourceID, input.MeasureID); err != nil {
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from control: %w", err)
}
case coredata.RiskEntityType:
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingDelete)
if err != nil {
return nil, types.UnlinkMeasureOutput{}, err
}
if _, _, err := svc.Risks.DeleteMeasureMapping(ctx, scope, input.ResourceID, input.MeasureID); err != nil {
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from risk: %w", err)
}
case coredata.DocumentEntityType:
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingDelete)
if err != nil {
return nil, types.UnlinkMeasureOutput{}, err
}
if _, _, err := svc.Measures.DeleteDocumentMapping(ctx, scope, input.MeasureID, input.ResourceID); err != nil {
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from document: %w", err)
}
case coredata.ThirdPartyEntityType:
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureThirdPartyMappingDelete)
if err != nil {
return nil, types.UnlinkMeasureOutput{}, err
}
if _, _, err := svc.Measures.DeleteThirdPartyMapping(ctx, scope, input.MeasureID, input.ResourceID); err != nil {
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from third party: %w", err)
}
default:
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("unsupported resource type for measure unlinking: entity type %d", input.ResourceID.EntityType())
}
return nil, types.UnlinkMeasureOutput{}, nil
}
func (r *Resolver) ListUsersTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListUsersInput) (*mcp.CallToolResult, types.ListUsersOutput, error) {
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionMembershipProfileList); err != nil {
return nil, types.ListUsersOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
Field: coredata.MembershipProfileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.MembershipProfileOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
filter := coredata.NewMembershipProfileFilter(nil).WithMembership()
if input.Filter != nil {
filter = coredata.NewMembershipProfileFilter(input.Filter.ContractEnded).WithMembership()
if input.Filter.State != nil {
filter.WithState(*input.Filter.State)
}
}
pageResult, err := r.iamSvc.OrganizationService.ListProfiles(ctx, input.OrganizationID, cursor, filter)
if err != nil {
return nil, types.ListUsersOutput{}, fmt.Errorf("list users: %w", err)
}
users := make([]*types.Profile, 0, len(pageResult.Data))
for _, p := range pageResult.Data {
users = append(users, types.NewProfile(p))
}
var nextCursor *page.CursorKey
if len(pageResult.Data) > 0 && pageResult.Cursor != nil {
cursorKey := pageResult.Data[len(pageResult.Data)-1].CursorKey(pageResult.Cursor.OrderBy.Field)
nextCursor = &cursorKey
}
return nil, types.ListUsersOutput{
Users: users,
NextCursor: nextCursor,
}, nil
}
func (r *Resolver) GetUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetUserInput) (*mcp.CallToolResult, types.GetUserOutput, error) {
profile, err := r.iamSvc.OrganizationService.GetProfile(ctx, input.ID)
if err != nil {
if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); ok {
return nil, types.GetUserOutput{}, fmt.Errorf("user not found: %w", err)
}
return nil, types.GetUserOutput{}, fmt.Errorf("get user: %w", err)
}
if _, err := r.Authorize(ctx, profile.OrganizationID, iam.ActionMembershipProfileGet); err != nil {
return nil, types.GetUserOutput{}, err
}
return nil, types.GetUserOutput{User: types.NewProfile(profile)}, nil
}
func (r *Resolver) CreateUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateUserInput) (*mcp.CallToolResult, types.CreateUserOutput, error) {
scope, err := r.Authorize(
ctx,
input.OrganizationID,
iam.ActionMembershipProfileCreate,
authz.WithAttr("target_role", input.Role.String()),
)
if err != nil {
return nil, types.CreateUserOutput{}, err
}
var contractStart, contractEnd **time.Time
if input.ContractStartDate != nil {
contractStart = &input.ContractStartDate
}
if input.ContractEndDate != nil {
contractEnd = &input.ContractEndDate
}
profile, err := r.iamSvc.OrganizationService.CreateUser(ctx, scope, &iam.CreateUserRequest{
OrganizationID: input.OrganizationID,
EmailAddress: input.EmailAddress,
Role: input.Role,
FullName: input.FullName,
AdditionalEmailAddresses: input.AdditionalEmailAddresses,
Kind: input.Kind,
Position: input.Position,
ContractStartDate: contractStart,
ContractEndDate: contractEnd,
})
if err != nil {
if _, ok := errors.AsType[*iam.ErrUserAlreadyExists](err); ok {
return nil, types.CreateUserOutput{}, fmt.Errorf("user with email already exists: %w", err)
}
return nil, types.CreateUserOutput{}, fmt.Errorf("create user: %w", err)
}
return nil, types.CreateUserOutput{User: types.NewProfile(profile)}, nil
}
func (r *Resolver) InviteUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.InviteUserInput) (*mcp.CallToolResult, types.InviteUserOutput, error) {
if _, err := r.Authorize(ctx, input.ProfileID, iam.ActionInvitationCreate); err != nil {
return nil, types.InviteUserOutput{}, err
}
invitation, err := r.iamSvc.OrganizationService.InviteUser(ctx, &iam.CreateInvitationRequest{
OrganizationID: input.OrganizationID,
ProfileID: input.ProfileID,
})
if err != nil {
if _, ok := errors.AsType[*iam.ErrOrganizationNotFound](err); ok {
return nil, types.InviteUserOutput{}, fmt.Errorf("organization not found: %w", err)
}
if _, ok := errors.AsType[*iam.ErrUserAlreadyExists](err); ok {
return nil, types.InviteUserOutput{}, fmt.Errorf("user already in organization: %w", err)
}
return nil, types.InviteUserOutput{}, fmt.Errorf("invite user: %w", err)
}
return nil, types.InviteUserOutput{InvitationID: invitation.ID}, nil
}
func (r *Resolver) UpdateUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateUserInput) (*mcp.CallToolResult, types.UpdateUserOutput, error) {
if _, err := r.Authorize(ctx, input.ID, iam.ActionMembershipProfileUpdate); err != nil {
return nil, types.UpdateUserOutput{}, err
}
var additionalEmails []mail.Addr
if input.AdditionalEmailAddresses != nil {
additionalEmails = *input.AdditionalEmailAddresses
}
var position *string
if p := UnwrapOmittable(input.Position); p != nil {
position = *p
}
var contractStart, contractEnd **time.Time
if p := UnwrapOmittable(input.ContractStartDate); p != nil {
contractStart = p
}
if p := UnwrapOmittable(input.ContractEndDate); p != nil {
contractEnd = p
}
profile, err := r.iamSvc.OrganizationService.UpdateUser(ctx, &iam.UpdateUserRequest{
ID: input.ID,
FullName: input.FullName,
AdditionalEmailAddresses: additionalEmails,
Kind: input.Kind,
Position: position,
ContractStartDate: contractStart,
ContractEndDate: contractEnd,
})
if err != nil {
return nil, types.UpdateUserOutput{}, fmt.Errorf("update user: %w", err)
}
return nil, types.UpdateUserOutput{User: types.NewProfile(profile)}, nil
}
func (r *Resolver) UpdateMembershipTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMembershipInput) (*mcp.CallToolResult, types.UpdateMembershipOutput, error) {
if _, err := r.Authorize(
ctx,
input.MembershipID,
iam.ActionMembershipUpdate,
authz.WithAttr("target_role", input.Role.String()),
); err != nil {
return nil, types.UpdateMembershipOutput{}, err
}
membership, err := r.iamSvc.OrganizationService.UpdateMembership(ctx, input.OrganizationID, input.MembershipID, input.Role)
if err != nil {
return nil, types.UpdateMembershipOutput{}, fmt.Errorf("update membership: %w", err)
}
return nil, types.UpdateMembershipOutput{
Membership: &types.Membership{
ID: membership.ID,
Role: membership.Role,
CreatedAt: membership.CreatedAt,
},
}, nil
}
func (r *Resolver) RemoveUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RemoveUserInput) (*mcp.CallToolResult, types.RemoveUserOutput, error) {
scope, err := r.Authorize(ctx, input.ProfileID, iam.ActionMembershipDelete)
if err != nil {
return nil, types.RemoveUserOutput{}, err
}
err = r.iamSvc.OrganizationService.RemoveUser(ctx, scope, input.OrganizationID, input.ProfileID)
if err != nil {
if _, ok := errors.AsType[*iam.ErrUserManagedBySCIM](err); ok {
return nil, types.RemoveUserOutput{}, fmt.Errorf("user is managed by SCIM and cannot be removed: %w", err)
}
if _, ok := errors.AsType[*iam.ErrLastActiveOwner](err); ok {
return nil, types.RemoveUserOutput{}, fmt.Errorf("cannot remove last active owner: %w", err)
}
if _, ok := errors.AsType[*iam.ErrProfileInUse](err); ok {
return nil, types.RemoveUserOutput{}, fmt.Errorf("cannot remove person: referenced by other resources: %w", err)
}
return nil, types.RemoveUserOutput{}, fmt.Errorf("remove user: %w", err)
}
return nil, types.RemoveUserOutput{DeletedUserID: input.ProfileID}, nil
}
func (r *Resolver) ArchiveUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ArchiveUserInput) (*mcp.CallToolResult, types.ArchiveUserOutput, error) {
scope, err := r.Authorize(ctx, input.ProfileID, iam.ActionMembershipProfileDelete)
if err != nil {
return nil, types.ArchiveUserOutput{}, err
}
err = r.iamSvc.OrganizationService.ArchiveUser(ctx, scope, input.OrganizationID, input.ProfileID)
if err != nil {
if _, ok := errors.AsType[*iam.ErrUserManagedBySCIM](err); ok {
return nil, types.ArchiveUserOutput{}, fmt.Errorf("user is managed by SCIM and cannot be archived: %w", err)
}
if _, ok := errors.AsType[*iam.ErrLastActiveOwner](err); ok {
return nil, types.ArchiveUserOutput{}, fmt.Errorf("cannot archive last active owner: %w", err)
}
return nil, types.ArchiveUserOutput{}, fmt.Errorf("archive user: %w", err)
}
return nil, types.ArchiveUserOutput{ArchivedUserID: input.ProfileID}, nil
}
func (r *Resolver) DeleteDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.DeleteDataProtectionImpactAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentDelete)
if err != nil {
return nil, types.DeleteDataProtectionImpactAssessmentOutput{}, err
}
svc := r.proboSvc
err = svc.DataProtectionImpactAssessments.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteDataProtectionImpactAssessmentOutput{}, fmt.Errorf("failed to delete data protection impact assessment: %w", err)
}
return nil, types.DeleteDataProtectionImpactAssessmentOutput{
DeletedDataProtectionImpactAssessmentID: input.ID,
}, nil
}
func (r *Resolver) ListStatementsOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListStatementsOfApplicabilityInput) (*mcp.CallToolResult, types.ListStatementsOfApplicabilityOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionStatementOfApplicabilityList)
if err != nil {
return nil, types.ListStatementsOfApplicabilityOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.StatementOfApplicabilityOrderField]{
Field: coredata.StatementOfApplicabilityOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.StatementOfApplicabilityOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
pg, err := prb.StatementsOfApplicability.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
return nil, types.ListStatementsOfApplicabilityOutput{}, fmt.Errorf("failed to list statements of applicability: %w", err)
}
return nil, types.NewListStatementsOfApplicabilityOutput(pg), nil
}
func (r *Resolver) GetStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetStatementOfApplicabilityInput) (*mcp.CallToolResult, types.GetStatementOfApplicabilityOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionStatementOfApplicabilityGet)
if err != nil {
return nil, types.GetStatementOfApplicabilityOutput{}, err
}
prb := r.proboSvc
soa, err := prb.StatementsOfApplicability.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetStatementOfApplicabilityOutput{}, fmt.Errorf("failed to get statement of applicability: %w", err)
}
return nil, types.GetStatementOfApplicabilityOutput{
StatementOfApplicability: types.NewStatementOfApplicability(soa),
}, nil
}
func (r *Resolver) AddStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddStatementOfApplicabilityInput) (*mcp.CallToolResult, types.AddStatementOfApplicabilityOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionStatementOfApplicabilityCreate)
if err != nil {
return nil, types.AddStatementOfApplicabilityOutput{}, err
}
svc := r.proboSvc
soa, err := svc.StatementsOfApplicability.Create(ctx, scope, probo.CreateStatementOfApplicabilityRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
})
if err != nil {
return nil, types.AddStatementOfApplicabilityOutput{}, fmt.Errorf("failed to create statement of applicability: %w", err)
}
return nil, types.AddStatementOfApplicabilityOutput{
StatementOfApplicability: types.NewStatementOfApplicability(soa),
}, nil
}
func (r *Resolver) UpdateStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateStatementOfApplicabilityInput) (*mcp.CallToolResult, types.UpdateStatementOfApplicabilityOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionStatementOfApplicabilityUpdate)
if err != nil {
return nil, types.UpdateStatementOfApplicabilityOutput{}, err
}
svc := r.proboSvc
soa, err := svc.StatementsOfApplicability.Update(ctx, scope, probo.UpdateStatementOfApplicabilityRequest{
StatementOfApplicabilityID: input.ID,
Name: input.Name,
})
if err != nil {
return nil, types.UpdateStatementOfApplicabilityOutput{}, fmt.Errorf("failed to update statement of applicability: %w", err)
}
return nil, types.UpdateStatementOfApplicabilityOutput{
StatementOfApplicability: types.NewStatementOfApplicability(soa),
}, nil
}
func (r *Resolver) DeleteStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteStatementOfApplicabilityInput) (*mcp.CallToolResult, types.DeleteStatementOfApplicabilityOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionStatementOfApplicabilityDelete)
if err != nil {
return nil, types.DeleteStatementOfApplicabilityOutput{}, err
}
svc := r.proboSvc
err = svc.StatementsOfApplicability.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteStatementOfApplicabilityOutput{}, fmt.Errorf("failed to delete statement of applicability: %w", err)
}
return nil, types.DeleteStatementOfApplicabilityOutput{
DeletedStatementOfApplicabilityID: input.ID,
}, nil
}
func (r *Resolver) ListApplicabilityStatementsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListApplicabilityStatementsInput) (*mcp.CallToolResult, types.ListApplicabilityStatementsOutput, error) {
scope, err := r.Authorize(ctx, input.StatementOfApplicabilityID, probo.ActionApplicabilityStatementList)
if err != nil {
return nil, types.ListApplicabilityStatementsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ApplicabilityStatementOrderField]{
Field: coredata.ApplicabilityStatementOrderFieldControlSectionTitle,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ApplicabilityStatementOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
pg, err := prb.StatementsOfApplicability.ListApplicabilityStatements(ctx, scope, input.StatementOfApplicabilityID, cursor)
if err != nil {
return nil, types.ListApplicabilityStatementsOutput{}, fmt.Errorf("failed to list applicability statements: %w", err)
}
return nil, types.NewListApplicabilityStatementsOutput(pg), nil
}
func (r *Resolver) GetApplicabilityStatementTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetApplicabilityStatementInput) (*mcp.CallToolResult, types.GetApplicabilityStatementOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionApplicabilityStatementGet)
if err != nil {
return nil, types.GetApplicabilityStatementOutput{}, err
}
prb := r.proboSvc
stmt, err := prb.StatementsOfApplicability.GetApplicabilityStatement(ctx, scope, input.ID)
if err != nil {
return nil, types.GetApplicabilityStatementOutput{}, fmt.Errorf("failed to get applicability statement: %w", err)
}
return nil, types.GetApplicabilityStatementOutput{
ApplicabilityStatement: types.NewApplicabilityStatement(stmt),
}, nil
}
func (r *Resolver) AddApplicabilityStatementTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddApplicabilityStatementInput) (*mcp.CallToolResult, types.AddApplicabilityStatementOutput, error) {
scope, err := r.Authorize(ctx, input.StatementOfApplicabilityID, probo.ActionApplicabilityStatementCreate)
if err != nil {
return nil, types.AddApplicabilityStatementOutput{}, err
}
svc := r.proboSvc
stmt, err := svc.StatementsOfApplicability.CreateApplicabilityStatement(
ctx, scope,
input.StatementOfApplicabilityID,
input.ControlID,
input.Applicability,
input.Justification,
)
if err != nil {
return nil, types.AddApplicabilityStatementOutput{}, fmt.Errorf("failed to create applicability statement: %w", err)
}
return nil, types.AddApplicabilityStatementOutput{
ApplicabilityStatement: types.NewApplicabilityStatement(stmt),
}, nil
}
func (r *Resolver) UpdateApplicabilityStatementTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateApplicabilityStatementInput) (*mcp.CallToolResult, types.UpdateApplicabilityStatementOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionApplicabilityStatementUpdate)
if err != nil {
return nil, types.UpdateApplicabilityStatementOutput{}, err
}
svc := r.proboSvc
stmt, err := svc.StatementsOfApplicability.UpdateApplicabilityStatement(
ctx, scope,
input.ID,
input.Applicability,
input.Justification,
)
if err != nil {
return nil, types.UpdateApplicabilityStatementOutput{}, fmt.Errorf("failed to update applicability statement: %w", err)
}
return nil, types.UpdateApplicabilityStatementOutput{
ApplicabilityStatement: types.NewApplicabilityStatement(stmt),
}, nil
}
func (r *Resolver) DeleteApplicabilityStatementTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteApplicabilityStatementInput) (*mcp.CallToolResult, types.DeleteApplicabilityStatementOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionApplicabilityStatementDelete)
if err != nil {
return nil, types.DeleteApplicabilityStatementOutput{}, err
}
svc := r.proboSvc
err = svc.StatementsOfApplicability.DeleteApplicabilityStatement(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteApplicabilityStatementOutput{}, fmt.Errorf("failed to delete applicability statement: %w", err)
}
return nil, types.DeleteApplicabilityStatementOutput{
DeletedApplicabilityStatementID: input.ID,
}, nil
}
// ListThirdPartyRiskAssessmentsTool handles the listThirdPartyRiskAssessments tool
// List all risk assessments for a thirdParty
func (r *Resolver) ListThirdPartyRiskAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartyRiskAssessmentsInput) (*mcp.CallToolResult, types.ListThirdPartyRiskAssessmentsOutput, error) {
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyRiskAssessmentList)
if err != nil {
return nil, types.ListThirdPartyRiskAssessmentsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ThirdPartyRiskAssessmentOrderField]{
Field: coredata.ThirdPartyRiskAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ThirdPartyRiskAssessmentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.ThirdParties.ListRiskAssessments(ctx, scope, input.ThirdPartyID, cursor)
if err != nil {
return nil, types.ListThirdPartyRiskAssessmentsOutput{}, fmt.Errorf("cannot list thirdParty risk assessments: %w", err)
}
return nil, types.NewListThirdPartyRiskAssessmentsOutput(p), nil
}
// AddThirdPartyRiskAssessmentTool handles the addThirdPartyRiskAssessment tool
// Add a new risk assessment for a thirdParty
func (r *Resolver) AddThirdPartyRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddThirdPartyRiskAssessmentInput) (*mcp.CallToolResult, types.AddThirdPartyRiskAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyRiskAssessmentCreate)
if err != nil {
return nil, types.AddThirdPartyRiskAssessmentOutput{}, err
}
prb := r.proboSvc
assessment, err := prb.ThirdParties.CreateRiskAssessment(
ctx, scope,
probo.CreateThirdPartyRiskAssessmentRequest{
ThirdPartyID: input.ThirdPartyID,
ExpiresAt: input.ExpiresAt,
DataSensitivity: input.DataSensitivity,
BusinessImpact: input.BusinessImpact,
Notes: input.Notes,
},
)
if err != nil {
return nil, types.AddThirdPartyRiskAssessmentOutput{}, fmt.Errorf("failed to create thirdParty risk assessment: %w", err)
}
return nil, types.NewAddThirdPartyRiskAssessmentOutput(assessment), nil
}
func (r *Resolver) DeleteThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteThirdPartyInput) (*mcp.CallToolResult, types.DeleteThirdPartyOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyDelete)
if err != nil {
return nil, types.DeleteThirdPartyOutput{}, err
}
svc := r.proboSvc
err = svc.ThirdParties.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteThirdPartyOutput{}, fmt.Errorf("failed to delete thirdParty: %w", err)
}
return nil, types.DeleteThirdPartyOutput{
DeletedThirdPartyID: input.ID,
}, nil
}
func (r *Resolver) DeleteFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteFindingInput) (*mcp.CallToolResult, types.DeleteFindingOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionFindingDelete)
if err != nil {
return nil, types.DeleteFindingOutput{}, err
}
svc := r.proboSvc
err = svc.Findings.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteFindingOutput{}, fmt.Errorf("cannot delete finding: %w", err)
}
return nil, types.DeleteFindingOutput{
DeletedFindingID: input.ID,
}, nil
}
func (r *Resolver) LinkFindingAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkFindingAuditInput) (*mcp.CallToolResult, types.LinkFindingAuditOutput, error) {
scope, err := r.Authorize(ctx, input.FindingID, probo.ActionFindingAuditMappingCreate)
if err != nil {
return nil, types.LinkFindingAuditOutput{}, err
}
svc := r.proboSvc
finding, audit, err := svc.Findings.CreateAuditMapping(ctx, scope, input.FindingID, input.AuditID, input.ReferenceID)
if err != nil {
return nil, types.LinkFindingAuditOutput{}, fmt.Errorf("cannot link finding to audit: %w", err)
}
return nil, types.LinkFindingAuditOutput{
Finding: types.NewFinding(finding),
Audit: types.NewAudit(audit, nil),
}, nil
}
func (r *Resolver) UnlinkFindingAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkFindingAuditInput) (*mcp.CallToolResult, types.UnlinkFindingAuditOutput, error) {
scope, err := r.Authorize(ctx, input.FindingID, probo.ActionFindingAuditMappingDelete)
if err != nil {
return nil, types.UnlinkFindingAuditOutput{}, err
}
svc := r.proboSvc
finding, audit, err := svc.Findings.DeleteAuditMapping(ctx, scope, input.FindingID, input.AuditID)
if err != nil {
return nil, types.UnlinkFindingAuditOutput{}, fmt.Errorf("cannot unlink finding from audit: %w", err)
}
return nil, types.UnlinkFindingAuditOutput{
DeletedFindingID: finding.ID,
DeletedAuditID: audit.ID,
}, nil
}
func (r *Resolver) ListFindingAuditsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListFindingAuditsInput) (*mcp.CallToolResult, types.ListFindingAuditsOutput, error) {
scope, err := r.Authorize(ctx, input.FindingID, probo.ActionFindingGet)
if err != nil {
return nil, types.ListFindingAuditsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
Field: coredata.AuditOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
auditPage, err := prb.Audits.ListForFindingID(ctx, scope, input.FindingID, cursor)
if err != nil {
return nil, types.ListFindingAuditsOutput{}, fmt.Errorf("cannot list finding audits: %w", err)
}
return nil, types.NewListFindingAuditsOutput(auditPage), nil
}
// ListAccessReviewCampaignsTool handles the listAccessReviewCampaigns tool
// List access review campaigns for an organization
func (r *Resolver) ListAccessReviewCampaignsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessReviewCampaignsInput) (*mcp.CallToolResult, types.ListAccessReviewCampaignsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, accessreview.ActionCampaignList)
if err != nil {
return nil, types.ListAccessReviewCampaignsOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.AccessReviewCampaignOrderField]{
Field: coredata.AccessReviewCampaignOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessReviewCampaignOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.accessReview.ListCampaignsForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list access review campaigns: %w", err))
}
return nil, types.NewListAccessReviewCampaignsOutput(p), nil
}
// ListAccessEntriesTool handles the listAccessEntries tool
// List access entries for a campaign or campaign source with optional filters
func (r *Resolver) ListAccessEntriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessEntriesInput) (*mcp.CallToolResult, types.ListAccessEntriesOutput, error) {
if input.AccessReviewCampaignSourceID == nil && input.CampaignID == nil {
return nil, types.ListAccessEntriesOutput{}, fmt.Errorf("campaign_id or access_review_campaign_source_id is required")
}
var (
scope *coredata.Scope
campaignID gid.GID
sourceID *gid.GID
err error
)
if input.AccessReviewCampaignSourceID != nil {
scope, err = r.Authorize(ctx, *input.AccessReviewCampaignSourceID, accessreview.ActionEntryList)
if err != nil {
return nil, types.ListAccessEntriesOutput{}, err
}
campaignSource, err := r.accessReview.GetCampaignSource(ctx, scope, *input.AccessReviewCampaignSourceID)
if err != nil {
panic(fmt.Errorf("cannot get campaign source: %w", err))
}
campaignID = campaignSource.AccessReviewCampaignID
sourceID = input.AccessReviewCampaignSourceID
} else {
scope, err = r.Authorize(ctx, *input.CampaignID, accessreview.ActionEntryList)
if err != nil {
return nil, types.ListAccessEntriesOutput{}, err
}
campaignID = *input.CampaignID
}
pageOrderBy := page.OrderBy[coredata.AccessReviewEntryOrderField]{
Field: coredata.AccessReviewEntryOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessReviewEntryOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
var filter *coredata.AccessReviewEntryFilter
if input.Filter != nil {
filter = &coredata.AccessReviewEntryFilter{
Decision: input.Filter.Decision,
Flag: input.Filter.Flag,
IncrementalTag: input.Filter.IncrementalTag,
IsAdmin: input.Filter.IsAdmin,
Active: input.Filter.Active,
AuthMethod: input.Filter.AuthMethod,
AccountType: input.Filter.AccountType,
}
}
var p *page.Page[*coredata.AccessReviewEntry, coredata.AccessReviewEntryOrderField]
if sourceID != nil {
p, err = r.accessReview.ListEntriesForCampaignIDAndSourceID(
ctx,
scope,
campaignID,
*sourceID,
cursor,
filter,
)
if err != nil {
panic(fmt.Errorf("cannot list access entries: %w", err))
}
} else {
p, err = r.accessReview.ListEntriesForCampaignID(ctx, scope, campaignID, cursor, filter)
if err != nil {
panic(fmt.Errorf("cannot list access entries: %w", err))
}
}
return nil, types.NewListAccessEntriesOutput(p), nil
}
// GetAccessReviewStatisticsTool handles the getAccessReviewCampaignStatistics tool
// Get statistics for an access review campaign
func (r *Resolver) GetAccessReviewStatisticsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAccessReviewStatisticsInput) (*mcp.CallToolResult, types.GetAccessReviewStatisticsOutput, error) {
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignGet)
if err != nil {
return nil, types.GetAccessReviewStatisticsOutput{}, err
}
stats, err := r.accessReview.CampaignStatistics(ctx, scope, input.CampaignID)
if err != nil {
panic(fmt.Errorf("cannot get campaign statistics: %w", err))
}
return nil, types.GetAccessReviewStatisticsOutput{
Statistics: types.NewAccessReviewStatistics(stats),
}, nil
}
// RecordAccessReviewEntryDecisionTool handles the recordAccessEntryDecision tool
// Record a decision on an access entry
func (r *Resolver) RecordAccessReviewEntryDecisionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RecordAccessReviewEntryDecisionInput) (*mcp.CallToolResult, types.RecordAccessReviewEntryDecisionOutput, error) {
scope, err := r.Authorize(ctx, input.AccessReviewEntryID, accessreview.ActionEntryDecide)
if err != nil {
return nil, types.RecordAccessReviewEntryDecisionOutput{}, err
}
entry, err := r.accessReview.RecordDecision(
ctx,
scope,
accessreview.RecordAccessReviewEntryDecisionRequest{
EntryID: input.AccessReviewEntryID,
Decision: input.Decision,
DecisionNote: input.DecisionNote,
DecidedByID: &authn.IdentityFromContext(ctx).ID,
},
)
if err != nil {
return nil, types.RecordAccessReviewEntryDecisionOutput{}, fmt.Errorf("cannot record decision: %w", err)
}
return nil, types.RecordAccessReviewEntryDecisionOutput{
AccessEntry: types.NewAccessReviewEntry(entry),
}, nil
}
// RecordAccessReviewEntryDecisionsTool handles the recordAccessEntryDecisions tool
// Record decisions on multiple access entries in a single batch
func (r *Resolver) RecordAccessReviewEntryDecisionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RecordAccessReviewEntryDecisionsInput) (*mcp.CallToolResult, types.RecordAccessReviewEntryDecisionsOutput, error) {
if len(input.Decisions) == 0 {
return nil, types.RecordAccessReviewEntryDecisionsOutput{
AccessReviewEntries: []*types.AccessReviewEntry{},
}, nil
}
const maxBatchSize = 100
if len(input.Decisions) > maxBatchSize {
return nil, types.RecordAccessReviewEntryDecisionsOutput{}, fmt.Errorf("cannot record decisions: batch size %d exceeds maximum of %d", len(input.Decisions), maxBatchSize)
}
// Authorize each entry individually to prevent cross-org bypass.
for _, d := range input.Decisions {
if _, err := r.Authorize(ctx, d.AccessReviewEntryID, accessreview.ActionEntryDecide); err != nil {
return nil, types.RecordAccessReviewEntryDecisionsOutput{}, err
}
}
scope := coredata.NewScopeFromObjectID(input.Decisions[0].AccessReviewEntryID)
identity := authn.IdentityFromContext(ctx)
if identity == nil {
return nil, types.RecordAccessReviewEntryDecisionsOutput{}, fmt.Errorf("no identity in context")
}
decidedByID := &identity.ID
decisions := make([]accessreview.RecordAccessReviewEntryDecisionRequest, len(input.Decisions))
for i, d := range input.Decisions {
decisions[i] = accessreview.RecordAccessReviewEntryDecisionRequest{
EntryID: d.AccessReviewEntryID,
Decision: d.Decision,
DecisionNote: d.DecisionNote,
DecidedByID: decidedByID,
}
}
entries, err := r.accessReview.RecordDecisions(ctx, scope, decisions)
if err != nil {
return nil, types.RecordAccessReviewEntryDecisionsOutput{}, fmt.Errorf("cannot record decisions: %w", err)
}
accessEntries := make([]*types.AccessReviewEntry, len(entries))
for i, e := range entries {
accessEntries[i] = types.NewAccessReviewEntry(e)
}
return nil, types.RecordAccessReviewEntryDecisionsOutput{
AccessReviewEntries: accessEntries,
}, nil
}
// CloseAccessReviewCampaignTool handles the closeAccessReviewCampaign tool
// Close an access review campaign
func (r *Resolver) CloseAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CloseAccessReviewCampaignInput) (*mcp.CallToolResult, types.CloseAccessReviewCampaignOutput, error) {
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignClose)
if err != nil {
return nil, types.CloseAccessReviewCampaignOutput{}, err
}
campaign, err := r.accessReview.CloseCampaign(ctx, scope, input.CampaignID)
if err != nil {
return nil, types.CloseAccessReviewCampaignOutput{}, fmt.Errorf("cannot close campaign: %w", err)
}
return nil, types.CloseAccessReviewCampaignOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// ListAccessReviewSourcesTool handles the listAccessSources tool
// List access sources for an organization
func (r *Resolver) ListAccessReviewSourcesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessReviewSourcesInput) (*mcp.CallToolResult, types.ListAccessReviewSourcesOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, accessreview.ActionSourceList)
if err != nil {
return nil, types.ListAccessReviewSourcesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.AccessReviewSourceOrderField]{
Field: coredata.AccessReviewSourceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessReviewSourceOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.accessReview.ListSourcesForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list access sources: %w", err))
}
return nil, types.NewListAccessReviewSourcesOutput(p), nil
}
// CreateAccessReviewSourceTool handles the createAccessSource tool
// Create a new access source for an organization
func (r *Resolver) CreateAccessReviewSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateAccessReviewSourceInput) (*mcp.CallToolResult, types.CreateAccessReviewSourceOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, accessreview.ActionSourceCreate)
if err != nil {
return nil, types.CreateAccessReviewSourceOutput{}, err
}
source, err := r.accessReview.CreateSource(ctx, scope, accessreview.CreateAccessReviewSourceRequest{
OrganizationID: input.OrganizationID,
ConnectorID: input.ConnectorID,
Name: input.Name,
CsvData: input.CsvData,
})
if err != nil {
return nil, types.CreateAccessReviewSourceOutput{}, fmt.Errorf("cannot create access source: %w", err)
}
return nil, types.CreateAccessReviewSourceOutput{
AccessReviewSource: types.NewAccessReviewSource(source),
}, nil
}
// UpdateAccessReviewSourceTool handles the updateAccessSource tool
// Update an existing access source
func (r *Resolver) UpdateAccessReviewSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAccessReviewSourceInput) (*mcp.CallToolResult, types.UpdateAccessReviewSourceOutput, error) {
scope, err := r.Authorize(ctx, input.AccessReviewSourceID, accessreview.ActionSourceUpdate)
if err != nil {
return nil, types.UpdateAccessReviewSourceOutput{}, err
}
updateReq := accessreview.UpdateAccessReviewSourceRequest{
AccessReviewSourceID: input.AccessReviewSourceID,
}
if input.Name != nil {
updateReq.Name = &input.Name
}
if rawConnectorID := UnwrapOmittable(input.ConnectorID); rawConnectorID != nil {
if *rawConnectorID != nil {
id, err := gid.ParseGID(**rawConnectorID)
if err != nil {
return nil, types.UpdateAccessReviewSourceOutput{}, fmt.Errorf("cannot parse connector_id: %w", err)
}
idPtr := &id
updateReq.ConnectorID = &idPtr
} else {
var nilGID *gid.GID
updateReq.ConnectorID = &nilGID
}
}
if rawCsvData := UnwrapOmittable(input.CsvData); rawCsvData != nil {
updateReq.CsvData = rawCsvData
}
source, err := r.accessReview.UpdateSource(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateAccessReviewSourceOutput{}, fmt.Errorf("cannot update access source: %w", err)
}
return nil, types.UpdateAccessReviewSourceOutput{
AccessReviewSource: types.NewAccessReviewSource(source),
}, nil
}
// DeleteAccessReviewSourceTool handles the deleteAccessSource tool
// Delete an access source
func (r *Resolver) DeleteAccessReviewSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAccessReviewSourceInput) (*mcp.CallToolResult, types.DeleteAccessReviewSourceOutput, error) {
scope, err := r.Authorize(ctx, input.AccessReviewSourceID, accessreview.ActionSourceDelete)
if err != nil {
return nil, types.DeleteAccessReviewSourceOutput{}, err
}
if err := r.accessReview.DeleteSource(ctx, scope, input.AccessReviewSourceID); err != nil {
return nil, types.DeleteAccessReviewSourceOutput{}, fmt.Errorf("cannot delete access source: %w", err)
}
return nil, types.DeleteAccessReviewSourceOutput{
DeletedAccessReviewSourceID: input.AccessReviewSourceID,
}, nil
}
// CreateAccessReviewCampaignTool handles the createAccessReviewCampaign tool
// Create a new access review campaign for an organization
func (r *Resolver) CreateAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateAccessReviewCampaignInput) (*mcp.CallToolResult, types.CreateAccessReviewCampaignOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, accessreview.ActionCampaignCreate)
if err != nil {
return nil, types.CreateAccessReviewCampaignOutput{}, err
}
var description string
if input.Description != nil {
description = *input.Description
}
campaign, err := r.accessReview.CreateCampaign(ctx, scope, accessreview.CreateAccessReviewCampaignRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: description,
AccessReviewSourceIDs: input.AccessReviewSourceIds,
})
if err != nil {
return nil, types.CreateAccessReviewCampaignOutput{}, fmt.Errorf("cannot create access review campaign: %w", err)
}
return nil, types.CreateAccessReviewCampaignOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// UpdateAccessReviewCampaignTool handles the updateAccessReviewCampaign tool
// Update an existing access review campaign
func (r *Resolver) UpdateAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAccessReviewCampaignInput) (*mcp.CallToolResult, types.UpdateAccessReviewCampaignOutput, error) {
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignUpdate)
if err != nil {
return nil, types.UpdateAccessReviewCampaignOutput{}, err
}
updateReq := accessreview.UpdateAccessReviewCampaignRequest{
CampaignID: input.CampaignID,
}
if input.Name != nil {
updateReq.Name = &input.Name
}
if input.Description != nil {
updateReq.Description = &input.Description
}
campaign, err := r.accessReview.UpdateCampaign(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateAccessReviewCampaignOutput{}, fmt.Errorf("cannot update access review campaign: %w", err)
}
return nil, types.UpdateAccessReviewCampaignOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// DeleteAccessReviewCampaignTool handles the deleteAccessReviewCampaign tool
// Delete an access review campaign
func (r *Resolver) DeleteAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAccessReviewCampaignInput) (*mcp.CallToolResult, types.DeleteAccessReviewCampaignOutput, error) {
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignDelete)
if err != nil {
return nil, types.DeleteAccessReviewCampaignOutput{}, err
}
if err := r.accessReview.DeleteCampaign(ctx, scope, input.CampaignID); err != nil {
return nil, types.DeleteAccessReviewCampaignOutput{}, fmt.Errorf("cannot delete access review campaign: %w", err)
}
return nil, types.DeleteAccessReviewCampaignOutput{
DeletedCampaignID: input.CampaignID,
}, nil
}
// StartAccessReviewCampaignTool handles the startAccessReviewCampaign tool
// Start an access review campaign
func (r *Resolver) StartAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.StartAccessReviewCampaignInput) (*mcp.CallToolResult, types.StartAccessReviewCampaignOutput, error) {
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignStart)
if err != nil {
return nil, types.StartAccessReviewCampaignOutput{}, err
}
campaign, err := r.accessReview.StartCampaign(ctx, scope, input.CampaignID)
if err != nil {
return nil, types.StartAccessReviewCampaignOutput{}, fmt.Errorf("cannot start access review campaign: %w", err)
}
return nil, types.StartAccessReviewCampaignOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// CancelAccessReviewCampaignTool handles the cancelAccessReviewCampaign tool
// Cancel an in-progress access review campaign
func (r *Resolver) CancelAccessReviewCampaignTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CancelAccessReviewCampaignInput) (*mcp.CallToolResult, types.CancelAccessReviewCampaignOutput, error) {
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignCancel)
if err != nil {
return nil, types.CancelAccessReviewCampaignOutput{}, err
}
campaign, err := r.accessReview.CancelCampaign(ctx, scope, input.CampaignID)
if err != nil {
return nil, types.CancelAccessReviewCampaignOutput{}, fmt.Errorf("cannot cancel access review campaign: %w", err)
}
return nil, types.CancelAccessReviewCampaignOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// AddAccessReviewCampaignSourceTool handles the addAccessReviewCampaignScopeSource tool
// Add an access source to an access review campaign's scope
func (r *Resolver) AddAccessReviewCampaignSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAccessReviewCampaignSourceInput) (*mcp.CallToolResult, types.AddAccessReviewCampaignSourceOutput, error) {
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignAddSource)
if err != nil {
return nil, types.AddAccessReviewCampaignSourceOutput{}, err
}
campaign, err := r.accessReview.AddCampaignSource(ctx, scope, accessreview.AddCampaignSourceRequest{
CampaignID: input.CampaignID,
AccessReviewSourceID: input.AccessReviewSourceID,
})
if err != nil {
return nil, types.AddAccessReviewCampaignSourceOutput{}, fmt.Errorf("cannot add scope source to access review campaign: %w", err)
}
return nil, types.AddAccessReviewCampaignSourceOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// RemoveAccessReviewCampaignSourceTool handles the removeAccessReviewCampaignScopeSource tool
// Remove an access source from an access review campaign's scope
func (r *Resolver) RemoveAccessReviewCampaignSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RemoveAccessReviewCampaignSourceInput) (*mcp.CallToolResult, types.RemoveAccessReviewCampaignSourceOutput, error) {
scope, err := r.Authorize(ctx, input.CampaignID, accessreview.ActionCampaignRemoveSource)
if err != nil {
return nil, types.RemoveAccessReviewCampaignSourceOutput{}, err
}
campaign, err := r.accessReview.RemoveCampaignSource(ctx, scope, accessreview.RemoveCampaignSourceRequest{
CampaignID: input.CampaignID,
AccessReviewSourceID: input.AccessReviewSourceID,
})
if err != nil {
return nil, types.RemoveAccessReviewCampaignSourceOutput{}, fmt.Errorf("cannot remove scope source from access review campaign: %w", err)
}
return nil, types.RemoveAccessReviewCampaignSourceOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// FlagAccessReviewEntryTool handles the flagAccessEntry tool
// Flag an access entry during review
func (r *Resolver) FlagAccessReviewEntryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.FlagAccessReviewEntryInput) (*mcp.CallToolResult, types.FlagAccessReviewEntryOutput, error) {
scope, err := r.Authorize(ctx, input.AccessReviewEntryID, accessreview.ActionEntryFlag)
if err != nil {
return nil, types.FlagAccessReviewEntryOutput{}, err
}
entry, err := r.accessReview.FlagEntry(ctx, scope, accessreview.FlagAccessReviewEntryRequest{
EntryID: input.AccessReviewEntryID,
Flags: input.Flags,
FlagReasons: input.FlagReasons,
})
if err != nil {
return nil, types.FlagAccessReviewEntryOutput{}, fmt.Errorf("cannot flag access entry: %w", err)
}
return nil, types.FlagAccessReviewEntryOutput{
AccessEntry: types.NewAccessReviewEntry(entry),
}, nil
}
func (r *Resolver) GetAuditReportUrlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAuditReportUrlInput) (*mcp.CallToolResult, types.GetAuditReportUrlOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionReportGetReportUrl)
if err != nil {
return nil, types.GetAuditReportUrlOutput{}, err
}
prb := r.proboSvc
url, err := prb.Audits.GenerateReportURL(ctx, scope, input.ID, 15*time.Minute)
if err != nil {
return nil, types.GetAuditReportUrlOutput{}, fmt.Errorf("cannot generate audit report URL: %w", err)
}
return nil, types.GetAuditReportUrlOutput{
URL: *url,
}, nil
}
func (r *Resolver) ArchiveDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ArchiveDocumentInput) (*mcp.CallToolResult, types.ArchiveDocumentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentArchive)
if err != nil {
return nil, types.ArchiveDocumentOutput{}, err
}
svc := r.proboSvc
document, err := svc.Documents.Archive(ctx, scope, input.ID)
if err != nil {
return nil, types.ArchiveDocumentOutput{}, fmt.Errorf("cannot archive document: %w", err)
}
return nil, types.ArchiveDocumentOutput{
Document: types.NewDocument(document),
}, nil
}
func (r *Resolver) UnarchiveDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnarchiveDocumentInput) (*mcp.CallToolResult, types.UnarchiveDocumentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentUnarchive)
if err != nil {
return nil, types.UnarchiveDocumentOutput{}, err
}
svc := r.proboSvc
document, err := svc.Documents.Unarchive(ctx, scope, input.ID)
if err != nil {
return nil, types.UnarchiveDocumentOutput{}, fmt.Errorf("cannot unarchive document: %w", err)
}
return nil, types.UnarchiveDocumentOutput{
Document: types.NewDocument(document),
}, nil
}
func (r *Resolver) GetOrganizationContextTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetOrganizationContextInput) (*mcp.CallToolResult, types.GetOrganizationContextOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionOrganizationContextGet)
if err != nil {
return nil, types.GetOrganizationContextOutput{}, err
}
prb := r.proboSvc
orgContext, err := prb.Organizations.GetContext(ctx, scope, input.OrganizationID)
if err != nil {
return nil, types.GetOrganizationContextOutput{}, fmt.Errorf("cannot get organization context: %w", err)
}
return nil, types.GetOrganizationContextOutput{
OrganizationContext: types.NewOrganizationContext(orgContext),
}, nil
}
func (r *Resolver) UpdateOrganizationContextTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateOrganizationContextInput) (*mcp.CallToolResult, types.UpdateOrganizationContextOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionOrganizationContextUpdate)
if err != nil {
return nil, types.UpdateOrganizationContextOutput{}, err
}
prb := r.proboSvc
orgContext, err := prb.Organizations.UpdateContext(
ctx, scope,
probo.UpdateOrganizationContextRequest{
OrganizationID: input.OrganizationID,
Product: &input.Product,
Architecture: &input.Architecture,
Team: &input.Team,
Processes: &input.Processes,
Customers: &input.Customers,
},
)
if err != nil {
return nil, types.UpdateOrganizationContextOutput{}, fmt.Errorf("cannot update organization context: %w", err)
}
return nil, types.UpdateOrganizationContextOutput{
OrganizationContext: types.NewOrganizationContext(orgContext),
}, nil
}
func (r *Resolver) GetAuditLogEntryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAuditLogEntryInput) (*mcp.CallToolResult, types.GetAuditLogEntryOutput, error) {
if _, err := r.Authorize(ctx, input.ID, iam.ActionAuditLogEntryGet); err != nil {
return nil, types.GetAuditLogEntryOutput{}, err
}
entry, err := r.iamSvc.OrganizationService.GetAuditLogEntry(ctx, input.ID)
if err != nil {
panic(fmt.Errorf("cannot get audit log entry: %w", err))
}
return nil, types.GetAuditLogEntryOutput{
AuditLogEntry: types.NewAuditLogEntry(entry),
}, nil
}
func (r *Resolver) ListAuditLogEntriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAuditLogEntriesInput) (*mcp.CallToolResult, types.ListAuditLogEntriesOutput, error) {
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionAuditLogEntryList); err != nil {
return nil, types.ListAuditLogEntriesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: coredata.AuditLogEntryOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
filter := coredata.NewAuditLogEntryFilter()
if input.Filter != nil {
if input.Filter.Action != nil {
filter.WithAction(*input.Filter.Action)
}
if input.Filter.ActorID != nil {
filter.WithActorID(*input.Filter.ActorID)
}
if input.Filter.ResourceType != nil {
filter.WithResourceType(*input.Filter.ResourceType)
}
if input.Filter.ResourceID != nil {
filter.WithResourceID(*input.Filter.ResourceID)
}
}
p, err := r.iamSvc.OrganizationService.ListAuditLogEntries(ctx, input.OrganizationID, cursor, filter)
if err != nil {
panic(fmt.Errorf("cannot list audit log entries: %w", err))
}
return nil, types.NewListAuditLogEntriesOutput(p), nil
}
func (r *Resolver) ListMeasureDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureDocumentsInput) (*mcp.CallToolResult, types.ListMeasureDocumentsOutput, error) {
scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureGet)
if err != nil {
return nil, types.ListMeasureDocumentsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
docPage, err := prb.Documents.ListForMeasureID(ctx, scope, input.MeasureID, cursor, coredata.NewDocumentFilter(nil))
if err != nil {
return nil, types.ListMeasureDocumentsOutput{}, fmt.Errorf("failed to list measure documents: %w", err)
}
return nil, types.NewListMeasureDocumentsOutput(docPage), nil
}
func (r *Resolver) VoidDocumentVersionApprovalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.VoidDocumentVersionApprovalInput) (*mcp.CallToolResult, types.VoidDocumentVersionApprovalOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionVoidApproval)
if err != nil {
return nil, types.VoidDocumentVersionApprovalOutput{}, err
}
svc := r.proboSvc
_, documentVersion, err := svc.DocumentApprovals.VoidApproval(ctx, scope, input.DocumentVersionID)
if err != nil {
panic(fmt.Errorf("cannot void document version approval: %w", err))
}
return nil, types.VoidDocumentVersionApprovalOutput{
DocumentVersion: types.NewDocumentVersion(documentVersion),
}, nil
}
func (r *Resolver) DeleteDocumentDraftTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDocumentDraftInput) (*mcp.CallToolResult, types.DeleteDocumentDraftOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentDeleteDraft)
if err != nil {
return nil, types.DeleteDocumentDraftOutput{}, err
}
svc := r.proboSvc
document, err := svc.Documents.DeleteDraft(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteDocumentDraftOutput{}, fmt.Errorf("cannot delete document draft: %w", err)
}
return nil, types.DeleteDocumentDraftOutput{
Document: types.NewDocument(document),
}, nil
}
func (r *Resolver) PublishStatementOfApplicabilityTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishStatementOfApplicabilityInput) (*mcp.CallToolResult, types.PublishStatementOfApplicabilityOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionStatementOfApplicabilityPublish)
if err != nil {
return nil, types.PublishStatementOfApplicabilityOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishStatementOfApplicability(ctx, scope, input.ID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishStatementOfApplicabilityOutput{}, fmt.Errorf("cannot publish statement of applicability: %w", err)
}
return nil, types.PublishStatementOfApplicabilityOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) ListWebhookSubscriptionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListWebhookSubscriptionsInput) (*mcp.CallToolResult, types.ListWebhookSubscriptionsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionWebhookSubscriptionList)
if err != nil {
return nil, types.ListWebhookSubscriptionsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.WebhookSubscriptionOrderField]{
Field: coredata.WebhookSubscriptionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.WebhookSubscriptionOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.WebhookSubscriptions.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list webhook subscriptions: %w", err))
}
return nil, types.NewListWebhookSubscriptionsOutput(page), nil
}
func (r *Resolver) GetWebhookSubscriptionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetWebhookSubscriptionInput) (*mcp.CallToolResult, types.GetWebhookSubscriptionOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionWebhookSubscriptionGet)
if err != nil {
return nil, types.GetWebhookSubscriptionOutput{}, err
}
prb := r.proboSvc
subscription, err := prb.WebhookSubscriptions.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetWebhookSubscriptionOutput{}, fmt.Errorf("failed to get webhook subscription: %w", err)
}
return nil, types.GetWebhookSubscriptionOutput{
WebhookSubscription: types.NewWebhookSubscription(subscription),
}, nil
}
func (r *Resolver) CreateWebhookSubscriptionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateWebhookSubscriptionInput) (*mcp.CallToolResult, types.CreateWebhookSubscriptionOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionWebhookSubscriptionCreate)
if err != nil {
return nil, types.CreateWebhookSubscriptionOutput{}, err
}
prb := r.proboSvc
subscription, err := prb.WebhookSubscriptions.Create(
ctx, scope,
probo.CreateWebhookSubscriptionRequest{
OrganizationID: input.OrganizationID,
EndpointURL: input.EndpointURL,
SelectedEvents: input.SelectedEvents,
},
)
if err != nil {
return nil, types.CreateWebhookSubscriptionOutput{}, fmt.Errorf("failed to create webhook subscription: %w", err)
}
return nil, types.CreateWebhookSubscriptionOutput{
WebhookSubscription: types.NewWebhookSubscription(subscription),
}, nil
}
func (r *Resolver) UpdateWebhookSubscriptionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateWebhookSubscriptionInput) (*mcp.CallToolResult, types.UpdateWebhookSubscriptionOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionWebhookSubscriptionUpdate)
if err != nil {
return nil, types.UpdateWebhookSubscriptionOutput{}, err
}
prb := r.proboSvc
subscription, err := prb.WebhookSubscriptions.Update(
ctx, scope,
probo.UpdateWebhookSubscriptionRequest{
WebhookSubscriptionID: input.ID,
EndpointURL: input.EndpointURL,
SelectedEvents: input.SelectedEvents,
},
)
if err != nil {
return nil, types.UpdateWebhookSubscriptionOutput{}, fmt.Errorf("failed to update webhook subscription: %w", err)
}
return nil, types.UpdateWebhookSubscriptionOutput{
WebhookSubscription: types.NewWebhookSubscription(subscription),
}, nil
}
func (r *Resolver) DeleteWebhookSubscriptionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteWebhookSubscriptionInput) (*mcp.CallToolResult, types.DeleteWebhookSubscriptionOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionWebhookSubscriptionDelete)
if err != nil {
return nil, types.DeleteWebhookSubscriptionOutput{}, err
}
prb := r.proboSvc
err = prb.WebhookSubscriptions.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteWebhookSubscriptionOutput{}, fmt.Errorf("failed to delete webhook subscription: %w", err)
}
return nil, types.DeleteWebhookSubscriptionOutput{
DeletedWebhookSubscriptionID: input.ID,
}, nil
}
func (r *Resolver) ListWebhookEventsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListWebhookEventsInput) (*mcp.CallToolResult, types.ListWebhookEventsOutput, error) {
scope, err := r.Authorize(ctx, input.WebhookSubscriptionID, probo.ActionWebhookSubscriptionGet)
if err != nil {
return nil, types.ListWebhookEventsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.WebhookEventOrderField]{
Field: coredata.WebhookEventOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.WebhookEventOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.WebhookSubscriptions.ListEventsForSubscriptionID(ctx, scope, input.WebhookSubscriptionID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list webhook events: %w", err))
}
return nil, types.NewListWebhookEventsOutput(page), nil
}
func (r *Resolver) ListDocumentVersionApprovalQuorumsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionApprovalQuorumsInput) (*mcp.CallToolResult, types.ListDocumentVersionApprovalQuorumsOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionApprovalList)
if err != nil {
return nil, types.ListDocumentVersionApprovalQuorumsOutput{}, err
}
svc := r.proboSvc
pageOrderBy := page.OrderBy[coredata.DocumentVersionApprovalQuorumOrderField]{
Field: coredata.DocumentVersionApprovalQuorumOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentVersionApprovalQuorumOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := svc.DocumentApprovals.ListQuorums(ctx, scope, input.DocumentVersionID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list approval quorums: %w", err))
}
return nil, types.NewListDocumentVersionApprovalQuorumsOutput(p), nil
}
func (r *Resolver) GetDocumentVersionApprovalQuorumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionApprovalQuorumInput) (*mcp.CallToolResult, types.GetDocumentVersionApprovalQuorumOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
if err != nil {
return nil, types.GetDocumentVersionApprovalQuorumOutput{}, err
}
svc := r.proboSvc
quorum, err := svc.DocumentApprovals.GetQuorum(ctx, scope, input.ID)
if err != nil {
panic(fmt.Errorf("cannot get approval quorum: %w", err))
}
return nil, types.GetDocumentVersionApprovalQuorumOutput{
ApprovalQuorum: types.NewDocumentVersionApprovalQuorum(quorum),
}, nil
}
func (r *Resolver) ListDocumentVersionApprovalDecisionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionApprovalDecisionsInput) (*mcp.CallToolResult, types.ListDocumentVersionApprovalDecisionsOutput, error) {
scope, err := r.Authorize(ctx, input.QuorumID, probo.ActionDocumentVersionApprovalList)
if err != nil {
return nil, types.ListDocumentVersionApprovalDecisionsOutput{}, err
}
svc := r.proboSvc
pageOrderBy := page.OrderBy[coredata.DocumentVersionApprovalDecisionOrderField]{
Field: coredata.DocumentVersionApprovalDecisionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentVersionApprovalDecisionOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
var states []coredata.DocumentVersionApprovalDecisionState
if input.Filter != nil {
states = input.Filter.States
}
filter := coredata.NewDocumentVersionApprovalDecisionFilter(states)
p, err := svc.DocumentApprovals.ListDecisions(ctx, scope, input.QuorumID, cursor, filter)
if err != nil {
panic(fmt.Errorf("cannot list approval decisions: %w", err))
}
return nil, types.NewListDocumentVersionApprovalDecisionsOutput(p), nil
}
func (r *Resolver) GetDocumentVersionApprovalDecisionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionApprovalDecisionInput) (*mcp.CallToolResult, types.GetDocumentVersionApprovalDecisionOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
if err != nil {
return nil, types.GetDocumentVersionApprovalDecisionOutput{}, err
}
svc := r.proboSvc
decision, err := svc.DocumentApprovals.GetDecision(ctx, scope, input.ID)
if err != nil {
panic(fmt.Errorf("cannot get approval decision: %w", err))
}
return nil, types.GetDocumentVersionApprovalDecisionOutput{
ApprovalDecision: types.NewDocumentVersionApprovalDecision(decision),
}, nil
}
func (r *Resolver) PublishDataListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishDataListInput) (*mcp.CallToolResult, types.PublishDataListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDatumPublish)
if err != nil {
return nil, types.PublishDataListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishDataList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishDataListOutput{}, fmt.Errorf("cannot publish data list: %w", err)
}
return nil, types.PublishDataListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) PublishAssetListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishAssetListInput) (*mcp.CallToolResult, types.PublishAssetListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionAssetPublish)
if err != nil {
return nil, types.PublishAssetListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishAssetList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishAssetListOutput{}, fmt.Errorf("cannot publish asset list: %w", err)
}
return nil, types.PublishAssetListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
// ListThirdPartyContactsTool handles the listThirdPartyContacts tool
// List all contacts for a thirdParty
func (r *Resolver) ListThirdPartyContactsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartyContactsInput) (*mcp.CallToolResult, types.ListThirdPartyContactsOutput, error) {
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyContactList)
if err != nil {
return nil, types.ListThirdPartyContactsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ThirdPartyContactOrderField]{
Field: coredata.ThirdPartyContactOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ThirdPartyContactOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.ThirdPartyContacts.List(ctx, scope, input.ThirdPartyID, cursor)
if err != nil {
return nil, types.ListThirdPartyContactsOutput{}, fmt.Errorf("cannot list thirdParty contacts: %w", err)
}
return nil, types.NewListThirdPartyContactsOutput(p), nil
}
// AddThirdPartyContactTool handles the addThirdPartyContact tool
// Add a new contact to a thirdParty
func (r *Resolver) AddThirdPartyContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddThirdPartyContactInput) (*mcp.CallToolResult, types.AddThirdPartyContactOutput, error) {
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyContactCreate)
if err != nil {
return nil, types.AddThirdPartyContactOutput{}, err
}
prb := r.proboSvc
emailAddr, err := mail.ParseAddr(input.Email)
if err != nil {
return nil, types.AddThirdPartyContactOutput{}, fmt.Errorf("invalid email address: %w", err)
}
thirdPartyContact, err := prb.ThirdPartyContacts.Create(ctx, scope, probo.CreateThirdPartyContactRequest{
ThirdPartyID: input.ThirdPartyID,
FullName: &input.FullName,
Email: &emailAddr,
Phone: &input.Phone,
Role: &input.Role,
})
if err != nil {
return nil, types.AddThirdPartyContactOutput{}, fmt.Errorf("cannot create thirdParty contact: %w", err)
}
return nil, types.AddThirdPartyContactOutput{
ThirdPartyContact: types.NewThirdPartyContact(thirdPartyContact),
}, nil
}
// UpdateThirdPartyContactTool handles the updateThirdPartyContact tool
// Update an existing thirdParty contact
func (r *Resolver) UpdateThirdPartyContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateThirdPartyContactInput) (*mcp.CallToolResult, types.UpdateThirdPartyContactOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyContactUpdate)
if err != nil {
return nil, types.UpdateThirdPartyContactOutput{}, err
}
prb := r.proboSvc
updateReq := probo.UpdateThirdPartyContactRequest{
ID: input.ID,
}
if input.FullName != nil {
updateReq.FullName = &input.FullName
}
if input.Email != nil {
emailAddr, err := mail.ParseAddr(*input.Email)
if err != nil {
return nil, types.UpdateThirdPartyContactOutput{}, fmt.Errorf("invalid email address: %w", err)
}
emailPtr := &emailAddr
updateReq.Email = &emailPtr
}
if input.Phone != nil {
updateReq.Phone = &input.Phone
}
if input.Role != nil {
updateReq.Role = &input.Role
}
thirdPartyContact, err := prb.ThirdPartyContacts.Update(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateThirdPartyContactOutput{}, fmt.Errorf("cannot update thirdParty contact: %w", err)
}
return nil, types.UpdateThirdPartyContactOutput{
ThirdPartyContact: types.NewThirdPartyContact(thirdPartyContact),
}, nil
}
// DeleteThirdPartyContactTool handles the deleteThirdPartyContact tool
// Delete a thirdParty contact
func (r *Resolver) DeleteThirdPartyContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteThirdPartyContactInput) (*mcp.CallToolResult, types.DeleteThirdPartyContactOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyContactDelete)
if err != nil {
return nil, types.DeleteThirdPartyContactOutput{}, err
}
prb := r.proboSvc
err = prb.ThirdPartyContacts.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteThirdPartyContactOutput{}, fmt.Errorf("cannot delete thirdParty contact: %w", err)
}
return nil, types.DeleteThirdPartyContactOutput{
DeletedThirdPartyContactID: input.ID,
}, nil
}
// ListThirdPartyServicesTool handles the listThirdPartyServices tool
// List all services for a thirdParty
func (r *Resolver) ListThirdPartyServicesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartyServicesInput) (*mcp.CallToolResult, types.ListThirdPartyServicesOutput, error) {
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyServiceList)
if err != nil {
return nil, types.ListThirdPartyServicesOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.ThirdPartyServiceOrderField]{
Field: coredata.ThirdPartyServiceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ThirdPartyServiceOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.ThirdPartyServices.List(ctx, scope, input.ThirdPartyID, cursor)
if err != nil {
return nil, types.ListThirdPartyServicesOutput{}, fmt.Errorf("cannot list thirdParty services: %w", err)
}
return nil, types.NewListThirdPartyServicesOutput(p), nil
}
// AddThirdPartyServiceTool handles the addThirdPartyService tool
// Add a new service to a thirdParty
func (r *Resolver) AddThirdPartyServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddThirdPartyServiceInput) (*mcp.CallToolResult, types.AddThirdPartyServiceOutput, error) {
scope, err := r.Authorize(ctx, input.ThirdPartyID, probo.ActionThirdPartyServiceCreate)
if err != nil {
return nil, types.AddThirdPartyServiceOutput{}, err
}
prb := r.proboSvc
thirdPartyService, err := prb.ThirdPartyServices.Create(ctx, scope, probo.CreateThirdPartyServiceRequest{
ThirdPartyID: input.ThirdPartyID,
Name: input.Name,
Description: input.Description,
})
if err != nil {
return nil, types.AddThirdPartyServiceOutput{}, fmt.Errorf("cannot create thirdParty service: %w", err)
}
return nil, types.AddThirdPartyServiceOutput{
ThirdPartyService: types.NewThirdPartyService(thirdPartyService),
}, nil
}
// UpdateThirdPartyServiceTool handles the updateThirdPartyService tool
// Update an existing thirdParty service
func (r *Resolver) UpdateThirdPartyServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateThirdPartyServiceInput) (*mcp.CallToolResult, types.UpdateThirdPartyServiceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyServiceUpdate)
if err != nil {
return nil, types.UpdateThirdPartyServiceOutput{}, err
}
prb := r.proboSvc
updateReq := probo.UpdateThirdPartyServiceRequest{
ID: input.ID,
}
if input.Name != nil {
updateReq.Name = input.Name
}
if input.Description != nil {
updateReq.Description = &input.Description
}
thirdPartyService, err := prb.ThirdPartyServices.Update(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateThirdPartyServiceOutput{}, fmt.Errorf("cannot update thirdParty service: %w", err)
}
return nil, types.UpdateThirdPartyServiceOutput{
ThirdPartyService: types.NewThirdPartyService(thirdPartyService),
}, nil
}
// DeleteThirdPartyServiceTool handles the deleteThirdPartyService tool
// Delete a thirdParty service
func (r *Resolver) DeleteThirdPartyServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteThirdPartyServiceInput) (*mcp.CallToolResult, types.DeleteThirdPartyServiceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyServiceDelete)
if err != nil {
return nil, types.DeleteThirdPartyServiceOutput{}, err
}
prb := r.proboSvc
err = prb.ThirdPartyServices.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteThirdPartyServiceOutput{}, fmt.Errorf("cannot delete thirdParty service: %w", err)
}
return nil, types.DeleteThirdPartyServiceOutput{
DeletedThirdPartyServiceID: input.ID,
}, nil
}
func (r *Resolver) DeleteAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAssetInput) (*mcp.CallToolResult, types.DeleteAssetOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionAssetDelete)
if err != nil {
return nil, types.DeleteAssetOutput{}, err
}
svc := r.proboSvc
err = svc.Assets.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteAssetOutput{}, fmt.Errorf("failed to delete asset: %w", err)
}
return nil, types.DeleteAssetOutput{
DeletedAssetID: input.ID,
}, nil
}
func (r *Resolver) DeleteDatumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDatumInput) (*mcp.CallToolResult, types.DeleteDatumOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionDatumDelete)
if err != nil {
return nil, types.DeleteDatumOutput{}, err
}
svc := r.proboSvc
err = svc.Data.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteDatumOutput{}, fmt.Errorf("failed to delete datum: %w", err)
}
return nil, types.DeleteDatumOutput{
DeletedDatumID: input.ID,
}, nil
}
func (r *Resolver) DeleteObligationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteObligationInput) (*mcp.CallToolResult, types.DeleteObligationOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionObligationDelete)
if err != nil {
return nil, types.DeleteObligationOutput{}, err
}
svc := r.proboSvc
err = svc.Obligations.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteObligationOutput{}, fmt.Errorf("failed to delete obligation: %w", err)
}
return nil, types.DeleteObligationOutput{
DeletedObligationID: input.ID,
}, nil
}
func (r *Resolver) DeleteAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAuditInput) (*mcp.CallToolResult, types.DeleteAuditOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionAuditDelete)
if err != nil {
return nil, types.DeleteAuditOutput{}, err
}
svc := r.proboSvc
err = svc.Audits.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteAuditOutput{}, fmt.Errorf("failed to delete audit: %w", err)
}
return nil, types.DeleteAuditOutput{
DeletedAuditID: input.ID,
}, nil
}
func (r *Resolver) ListRightsRequestsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRightsRequestsInput) (*mcp.CallToolResult, types.ListRightsRequestsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRightsRequestList)
if err != nil {
return nil, types.ListRightsRequestsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.RightsRequestOrderField]{
Field: coredata.RightsRequestOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RightsRequestOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.RightsRequests.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization rights requests: %w", err))
}
return nil, types.NewListRightsRequestsOutput(page), nil
}
func (r *Resolver) GetRightsRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRightsRequestInput) (*mcp.CallToolResult, types.GetRightsRequestOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRightsRequestGet)
if err != nil {
return nil, types.GetRightsRequestOutput{}, err
}
prb := r.proboSvc
rightsRequest, err := prb.RightsRequests.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRightsRequestOutput{}, fmt.Errorf("failed to get rights request: %w", err)
}
return nil, types.GetRightsRequestOutput{
RightsRequest: types.NewRightsRequest(rightsRequest),
}, nil
}
func (r *Resolver) AddRightsRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRightsRequestInput) (*mcp.CallToolResult, types.AddRightsRequestOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRightsRequestCreate)
if err != nil {
return nil, types.AddRightsRequestOutput{}, err
}
svc := r.proboSvc
rightsRequest, err := svc.RightsRequests.Create(
ctx, scope,
&probo.CreateRightsRequestRequest{
OrganizationID: input.OrganizationID,
RequestType: &input.RequestType,
RequestState: &input.RequestState,
DataSubject: &input.DataSubject,
Contact: input.Contact,
Details: input.Details,
Deadline: input.Deadline,
ActionTaken: input.ActionTaken,
},
)
if err != nil {
return nil, types.AddRightsRequestOutput{}, fmt.Errorf("failed to create rights request: %w", err)
}
return nil, types.AddRightsRequestOutput{
RightsRequest: types.NewRightsRequest(rightsRequest),
}, nil
}
func (r *Resolver) UpdateRightsRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRightsRequestInput) (*mcp.CallToolResult, types.UpdateRightsRequestOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRightsRequestUpdate)
if err != nil {
return nil, types.UpdateRightsRequestOutput{}, err
}
svc := r.proboSvc
var dataSubject **string
if input.DataSubject != nil {
dataSubject = &input.DataSubject
}
rightsRequest, err := svc.RightsRequests.Update(
ctx, scope,
&probo.UpdateRightsRequestRequest{
ID: input.ID,
RequestType: input.RequestType,
RequestState: input.RequestState,
DataSubject: dataSubject,
Contact: UnwrapOmittable(input.Contact),
Details: UnwrapOmittable(input.Details),
Deadline: UnwrapOmittable(input.Deadline),
ActionTaken: UnwrapOmittable(input.ActionTaken),
},
)
if err != nil {
return nil, types.UpdateRightsRequestOutput{}, fmt.Errorf("failed to update rights request: %w", err)
}
return nil, types.UpdateRightsRequestOutput{
RightsRequest: types.NewRightsRequest(rightsRequest),
}, nil
}
func (r *Resolver) DeleteRightsRequestTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRightsRequestInput) (*mcp.CallToolResult, types.DeleteRightsRequestOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRightsRequestDelete)
if err != nil {
return nil, types.DeleteRightsRequestOutput{}, err
}
svc := r.proboSvc
err = svc.RightsRequests.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteRightsRequestOutput{}, fmt.Errorf("failed to delete rights request: %w", err)
}
return nil, types.DeleteRightsRequestOutput{
DeletedRightsRequestID: input.ID,
}, nil
}
// GetTrustCenterTool handles the getTrustCenter tool
// Get the trust center for an organization
func (r *Resolver) GetTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrustCenterInput) (*mcp.CallToolResult, types.GetTrustCenterOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, complianceportal.ActionCompliancePortalGet)
if err != nil {
return nil, types.GetTrustCenterOutput{}, err
}
prb := r.management
trustCenter, err := prb.GetByOrganizationID(ctx, scope, input.OrganizationID)
if err != nil {
return nil, types.GetTrustCenterOutput{}, fmt.Errorf("cannot get trust center: %w", err)
}
tc := types.NewTrustCenter(trustCenter)
if trustCenter.LogoFileID != nil {
logo, err := r.loadFile(ctx, scope, *trustCenter.LogoFileID)
if err != nil {
return nil, types.GetTrustCenterOutput{}, err
}
tc.Logo = logo
}
if trustCenter.DarkLogoFileID != nil {
darkLogo, err := r.loadFile(ctx, scope, *trustCenter.DarkLogoFileID)
if err != nil {
return nil, types.GetTrustCenterOutput{}, err
}
tc.DarkLogo = darkLogo
}
if trustCenter.NonDisclosureAgreementFileID != nil {
nda, err := r.loadFile(ctx, scope, *trustCenter.NonDisclosureAgreementFileID)
if err != nil {
return nil, types.GetTrustCenterOutput{}, err
}
tc.Nda = nda
}
return nil, types.GetTrustCenterOutput{TrustCenter: tc}, nil
}
// UpdateTrustCenterTool handles the updateTrustCenter tool
// Update the trust center settings
func (r *Resolver) UpdateTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterInput) (*mcp.CallToolResult, types.UpdateTrustCenterOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalUpdate)
if err != nil {
return nil, types.UpdateTrustCenterOutput{}, err
}
prb := r.management
updateReq := &management.UpdateRequest{
ID: input.TrustCenterID,
}
if active := UnwrapOmittable(input.Active); active != nil {
updateReq.Active = *active
}
if sei := UnwrapOmittable(input.SearchEngineIndexing); sei != nil {
updateReq.SearchEngineIndexing = *sei
}
updateReq.Description = UnwrapOmittable(input.Description)
updateReq.WebsiteURL = UnwrapOmittable(input.WebsiteURL)
updateReq.Email = UnwrapOmittable(input.Email)
updateReq.HeadquarterAddress = UnwrapOmittable(input.HeadquarterAddress)
trustCenter, _, err := prb.Update(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateTrustCenterOutput{}, fmt.Errorf("cannot update trust center: %w", err)
}
return nil, types.UpdateTrustCenterOutput{TrustCenter: types.NewTrustCenter(trustCenter)}, nil
}
// ListTrustCenterReferencesTool handles the listTrustCenterReferences tool
// List all references for a trust center
func (r *Resolver) ListTrustCenterReferencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterReferencesInput) (*mcp.CallToolResult, types.ListTrustCenterReferencesOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalReferenceList)
if err != nil {
return nil, types.ListTrustCenterReferencesOutput{}, err
}
prb := r.management
pageOrderBy := page.OrderBy[coredata.TrustCenterReferenceOrderField]{
Field: coredata.TrustCenterReferenceOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterReferenceOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.ListReferences(ctx, scope, input.TrustCenterID, cursor)
if err != nil {
return nil, types.ListTrustCenterReferencesOutput{}, fmt.Errorf("cannot list trust center references: %w", err)
}
refs := make([]*types.TrustCenterReference, 0, len(p.Data))
for _, reference := range p.Data {
ref := types.NewTrustCenterReference(reference)
logo, err := r.loadFile(ctx, scope, reference.LogoFileID)
if err != nil {
return nil, types.ListTrustCenterReferencesOutput{}, err
}
ref.Logo = logo
refs = append(refs, ref)
}
return nil, types.NewListTrustCenterReferencesOutput(refs, p), nil
}
// AddTrustCenterReferenceTool handles the addTrustCenterReference tool
// Add a new reference to the trust center
func (r *Resolver) AddTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrustCenterReferenceInput) (*mcp.CallToolResult, types.AddTrustCenterReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCompliancePortalReferenceCreate)
if err != nil {
return nil, types.AddTrustCenterReferenceOutput{}, err
}
prb := r.management
var websiteURL string
if input.WebsiteURL != nil {
websiteURL = *input.WebsiteURL
}
reference, err := prb.CreateReference(
ctx, scope,
&management.CreateReferenceRequest{
TrustCenterID: input.TrustCenterID,
Name: input.Name,
Description: input.Description,
WebsiteURL: websiteURL,
},
)
if err != nil {
return nil, types.AddTrustCenterReferenceOutput{}, fmt.Errorf("cannot add trust center reference: %w", err)
}
return nil, types.AddTrustCenterReferenceOutput{TrustCenterReference: types.NewTrustCenterReference(reference)}, nil
}
// UpdateTrustCenterReferenceTool handles the updateTrustCenterReference tool
// Update a trust center reference
func (r *Resolver) UpdateTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterReferenceInput) (*mcp.CallToolResult, types.UpdateTrustCenterReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionCompliancePortalReferenceUpdate)
if err != nil {
return nil, types.UpdateTrustCenterReferenceOutput{}, err
}
prb := r.management
updateRefReq := &management.UpdateReferenceRequest{
ID: input.ID,
Description: UnwrapOmittable(input.Description),
}
if name := UnwrapOmittable(input.Name); name != nil {
updateRefReq.Name = *name
}
if websiteURL := UnwrapOmittable(input.WebsiteURL); websiteURL != nil {
updateRefReq.WebsiteURL = *websiteURL
}
if rank := UnwrapOmittable(input.Rank); rank != nil {
updateRefReq.Rank = *rank
}
reference, err := prb.UpdateReference(ctx, scope, updateRefReq)
if err != nil {
return nil, types.UpdateTrustCenterReferenceOutput{}, fmt.Errorf("cannot update trust center reference: %w", err)
}
return nil, types.UpdateTrustCenterReferenceOutput{TrustCenterReference: types.NewTrustCenterReference(reference)}, nil
}
// DeleteTrustCenterReferenceTool handles the deleteTrustCenterReference tool
// Delete a trust center reference
func (r *Resolver) DeleteTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterReferenceInput) (*mcp.CallToolResult, types.DeleteTrustCenterReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionCompliancePortalReferenceDelete)
if err != nil {
return nil, types.DeleteTrustCenterReferenceOutput{}, err
}
prb := r.management
err = prb.DeleteReference(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteTrustCenterReferenceOutput{}, fmt.Errorf("cannot delete trust center reference: %w", err)
}
return nil, types.DeleteTrustCenterReferenceOutput{DeletedTrustCenterReferenceID: input.ID}, nil
}
// ListTrustCenterFilesTool handles the listTrustCenterFiles tool
// List all files for the trust center
func (r *Resolver) ListTrustCenterFilesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterFilesInput) (*mcp.CallToolResult, types.ListTrustCenterFilesOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, complianceportal.ActionCompliancePortalFileList)
if err != nil {
return nil, types.ListTrustCenterFilesOutput{}, err
}
prb := r.management
pageOrderBy := page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: coredata.TrustCenterFileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
filter := coredata.NewTrustCenterFileFilter()
p, err := prb.ListFilesForOrganizationID(ctx, scope, input.OrganizationID, cursor, filter)
if err != nil {
return nil, types.ListTrustCenterFilesOutput{}, fmt.Errorf("cannot list trust center files: %w", err)
}
files := make([]*types.TrustCenterFile, 0, len(p.Data))
for _, f := range p.Data {
file, err := r.loadFile(ctx, scope, f.FileID)
if err != nil {
return nil, types.ListTrustCenterFilesOutput{}, err
}
files = append(files, types.NewTrustCenterFile(f, file))
}
return nil, types.NewListTrustCenterFilesOutput(files, p), nil
}
// DeleteTrustCenterFileTool handles the deleteTrustCenterFile tool
// Delete a trust center file
func (r *Resolver) DeleteTrustCenterFileTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterFileInput) (*mcp.CallToolResult, types.DeleteTrustCenterFileOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionCompliancePortalFileDelete)
if err != nil {
return nil, types.DeleteTrustCenterFileOutput{}, err
}
prb := r.management
err = prb.DeleteFile(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteTrustCenterFileOutput{}, fmt.Errorf("cannot delete trust center file: %w", err)
}
return nil, types.DeleteTrustCenterFileOutput{DeletedTrustCenterFileID: input.ID}, nil
}
// ListComplianceCustomLinksTool handles the listComplianceCustomLinks tool
// List all custom links for a trust center
func (r *Resolver) ListComplianceCustomLinksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListComplianceCustomLinksInput) (*mcp.CallToolResult, types.ListComplianceCustomLinksOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionComplianceCustomLinkList)
if err != nil {
return nil, types.ListComplianceCustomLinksOutput{}, err
}
prb := r.management
pageOrderBy := page.OrderBy[coredata.ComplianceCustomLinkOrderField]{
Field: coredata.ComplianceCustomLinkOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ComplianceCustomLinkOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.ListCustomLinks(ctx, scope, input.TrustCenterID, cursor)
if err != nil {
return nil, types.ListComplianceCustomLinksOutput{}, fmt.Errorf("cannot list compliance custom links: %w", err)
}
return nil, types.NewListComplianceCustomLinksOutput(p), nil
}
// AddComplianceCustomLinkTool handles the addComplianceCustomLink tool
// Add a new custom link to the trust center
func (r *Resolver) AddComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddComplianceCustomLinkInput) (*mcp.CallToolResult, types.AddComplianceCustomLinkOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionComplianceCustomLinkCreate)
if err != nil {
return nil, types.AddComplianceCustomLinkOutput{}, err
}
prb := r.management
item, err := prb.CreateCustomLink(
ctx, scope,
&management.CreateCustomLinkRequest{
TrustCenterID: input.TrustCenterID,
Name: input.Name,
URL: input.URL,
},
)
if err != nil {
return nil, types.AddComplianceCustomLinkOutput{}, fmt.Errorf("cannot add compliance custom link: %w", err)
}
return nil, types.AddComplianceCustomLinkOutput{ComplianceCustomLink: types.NewComplianceCustomLink(item)}, nil
}
// UpdateComplianceCustomLinkTool handles the updateComplianceCustomLink tool
// Update a compliance custom link
func (r *Resolver) UpdateComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateComplianceCustomLinkInput) (*mcp.CallToolResult, types.UpdateComplianceCustomLinkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionComplianceCustomLinkUpdate)
if err != nil {
return nil, types.UpdateComplianceCustomLinkOutput{}, err
}
prb := r.management
updateURLReq := &management.UpdateCustomLinkRequest{
ID: input.ID,
}
if name := UnwrapOmittable(input.Name); name != nil && *name != nil {
updateURLReq.Name = **name
}
if u := UnwrapOmittable(input.URL); u != nil && *u != nil {
updateURLReq.URL = **u
}
if rank := UnwrapOmittable(input.Rank); rank != nil {
updateURLReq.Rank = *rank
}
item, err := prb.UpdateCustomLink(ctx, scope, updateURLReq)
if err != nil {
return nil, types.UpdateComplianceCustomLinkOutput{}, fmt.Errorf("cannot update compliance custom link: %w", err)
}
return nil, types.UpdateComplianceCustomLinkOutput{ComplianceCustomLink: types.NewComplianceCustomLink(item)}, nil
}
// DeleteComplianceCustomLinkTool handles the deleteComplianceCustomLink tool
// Delete a compliance custom link
func (r *Resolver) DeleteComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteComplianceCustomLinkInput) (*mcp.CallToolResult, types.DeleteComplianceCustomLinkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, complianceportal.ActionComplianceCustomLinkDelete)
if err != nil {
return nil, types.DeleteComplianceCustomLinkOutput{}, err
}
prb := r.management
err = prb.DeleteCustomLink(
ctx, scope,
&management.DeleteCustomLinkRequest{
ID: input.ID,
},
)
if err != nil {
return nil, types.DeleteComplianceCustomLinkOutput{}, fmt.Errorf("cannot delete compliance custom link: %w", err)
}
return nil, types.DeleteComplianceCustomLinkOutput{DeletedComplianceCustomLinkID: input.ID}, nil
}
// CreateCustomDomainTool handles the createCustomDomain tool
// Create a custom domain for a compliance page
func (r *Resolver) CreateCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateCustomDomainInput) (*mcp.CallToolResult, types.CreateCustomDomainOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCustomDomainCreate)
if err != nil {
return nil, types.CreateCustomDomainOutput{}, err
}
domain, err := r.management.AddCustomDomain(
ctx, scope,
input.TrustCenterID,
input.Domain,
)
if err != nil {
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot create custom domain: %w", err)
}
cert, err := r.management.GetCertificate(ctx, scope, domain)
if err != nil {
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot load certificate: %w", err)
}
return nil, types.CreateCustomDomainOutput{CustomDomain: types.NewCustomDomain(domain, cert)}, nil
}
// DeleteCustomDomainTool handles the deleteCustomDomain tool
// Delete the custom domain of a compliance page
func (r *Resolver) DeleteCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCustomDomainInput) (*mcp.CallToolResult, types.DeleteCustomDomainOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, complianceportal.ActionCustomDomainDelete)
if err != nil {
return nil, types.DeleteCustomDomainOutput{}, err
}
domain, err := r.management.GetCustomDomain(ctx, scope, input.TrustCenterID)
if err != nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot get custom domain: %w", err)
}
if domain == nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("compliance page has no custom domain")
}
cert, err := r.management.GetCertificate(ctx, scope, domain)
if err != nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot load certificate: %w", err)
}
deletedDomain := types.NewCustomDomain(domain, cert)
if err := r.management.RemoveCustomDomain(ctx, scope, domain.ID); err != nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot delete custom domain: %w", err)
}
return nil, types.DeleteCustomDomainOutput{DeletedCustomDomain: deletedDomain}, nil
}
func (r *Resolver) VetThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.VetThirdPartyInput) (*mcp.CallToolResult, types.VetThirdPartyOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyVet)
if err != nil {
return nil, types.VetThirdPartyOutput{}, err
}
svc := r.thirdPartySvc
thirdParty, err := svc.Vet(
ctx, scope,
thirdparty.VetRequest{
ID: input.ID,
WebsiteURL: input.WebsiteURL,
Procedure: input.Procedure,
},
)
if err != nil {
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
return nil, types.VetThirdPartyOutput{}, validationErrors
}
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("resource not found")
}
if errors.Is(err, thirdparty.ErrVettingDisabled) {
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("vetting is not configured")
}
if errors.Is(err, thirdparty.ErrVettingInProgress) {
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("vetting is already in progress")
}
r.logger.ErrorCtx(ctx, "cannot vet thirdParty", log.Error(err))
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("internal server error")
}
return nil, types.VetThirdPartyOutput{
ThirdParty: types.NewThirdParty(thirdParty),
}, nil
}
func (r *Resolver) PublishFindingListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishFindingListInput) (*mcp.CallToolResult, types.PublishFindingListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionFindingPublish)
if err != nil {
return nil, types.PublishFindingListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishFindingList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishFindingListOutput{}, fmt.Errorf("cannot publish finding list: %w", err)
}
return nil, types.PublishFindingListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) PublishObligationListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishObligationListInput) (*mcp.CallToolResult, types.PublishObligationListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionObligationPublish)
if err != nil {
return nil, types.PublishObligationListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishObligationList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishObligationListOutput{}, fmt.Errorf("cannot publish obligation list: %w", err)
}
return nil, types.PublishObligationListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) PublishProcessingActivityListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishProcessingActivityListInput) (*mcp.CallToolResult, types.PublishProcessingActivityListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionProcessingActivityPublish)
if err != nil {
return nil, types.PublishProcessingActivityListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishProcessingActivityList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishProcessingActivityListOutput{}, fmt.Errorf("cannot publish processing activity list: %w", err)
}
return nil, types.PublishProcessingActivityListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) PublishDataProtectionImpactAssessmentListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishDataProtectionImpactAssessmentListInput) (*mcp.CallToolResult, types.PublishDataProtectionImpactAssessmentListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionDataProtectionImpactAssessmentPublish)
if err != nil {
return nil, types.PublishDataProtectionImpactAssessmentListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishDataProtectionImpactAssessmentList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishDataProtectionImpactAssessmentListOutput{}, fmt.Errorf("cannot publish DPIA list: %w", err)
}
return nil, types.PublishDataProtectionImpactAssessmentListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) PublishTransferImpactAssessmentListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishTransferImpactAssessmentListInput) (*mcp.CallToolResult, types.PublishTransferImpactAssessmentListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionTransferImpactAssessmentPublish)
if err != nil {
return nil, types.PublishTransferImpactAssessmentListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishTransferImpactAssessmentList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishTransferImpactAssessmentListOutput{}, fmt.Errorf("cannot publish TIA list: %w", err)
}
return nil, types.PublishTransferImpactAssessmentListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) PublishThirdPartyListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishThirdPartyListInput) (*mcp.CallToolResult, types.PublishThirdPartyListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyPublish)
if err != nil {
return nil, types.PublishThirdPartyListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishThirdPartyList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishThirdPartyListOutput{}, fmt.Errorf("cannot publish thirdParty list: %w", err)
}
return nil, types.PublishThirdPartyListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) ListCookieBannersTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieBannersInput) (*mcp.CallToolResult, types.ListCookieBannersOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionCookieBannerList)
if err != nil {
return nil, types.ListCookieBannersOutput{}, err
}
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieBannerOrderField]{Field: coredata.CookieBannerOrderFieldCreatedAt, Direction: page.OrderDirectionDesc})
banners, err := r.cookieBanner.ListCookieBannersForOrganization(ctx, scope, input.OrganizationID, cursor, coredata.NewCookieBannerFilter(nil))
if err != nil {
panic(fmt.Errorf("cannot list cookie banners: %w", err))
}
p := page.NewPage(banners, cursor)
return nil, types.NewListCookieBannersOutput(p), nil
}
func (r *Resolver) GetCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieBannerInput) (*mcp.CallToolResult, types.GetCookieBannerOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerGet)
if err != nil {
return nil, types.GetCookieBannerOutput{}, err
}
banner, err := r.cookieBanner.GetCookieBanner(ctx, scope, input.ID)
if err != nil {
return nil, types.GetCookieBannerOutput{}, fmt.Errorf("cannot get cookie banner: %w", err)
}
return nil, types.GetCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
}
func (r *Resolver) AddCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCookieBannerInput) (*mcp.CallToolResult, types.AddCookieBannerOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionCookieBannerCreate)
if err != nil {
return nil, types.AddCookieBannerOutput{}, err
}
banner, err := r.cookieBanner.CreateCookieBanner(ctx, scope, cookiebanner.CreateCookieBannerRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Origin: input.Origin,
PrivacyPolicyURL: input.PrivacyPolicyURL,
CookiePolicyURL: input.CookiePolicyURL,
ConsentExpiryDays: input.ConsentExpiryDays,
})
if err != nil {
return nil, types.AddCookieBannerOutput{}, fmt.Errorf("cannot create cookie banner: %w", err)
}
return nil, types.AddCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
}
func (r *Resolver) UpdateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCookieBannerInput) (*mcp.CallToolResult, types.UpdateCookieBannerOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerUpdate)
if err != nil {
return nil, types.UpdateCookieBannerOutput{}, err
}
updateReq := cookiebanner.UpdateCookieBannerRequest{CookieBannerID: input.ID}
if v := UnwrapOmittable(input.Name); v != nil && *v != nil {
updateReq.Name = *v
}
if v := UnwrapOmittable(input.PrivacyPolicyURL); v != nil && *v != nil {
updateReq.PrivacyPolicyURL = *v
}
if v := UnwrapOmittable(input.CookiePolicyURL); v != nil && *v != nil {
updateReq.CookiePolicyURL = *v
}
if v := UnwrapOmittable(input.ConsentExpiryDays); v != nil && *v != nil {
updateReq.ConsentExpiryDays = *v
}
if v := UnwrapOmittable(input.DefaultLanguage); v != nil && *v != nil {
updateReq.DefaultLanguage = *v
}
banner, err := r.cookieBanner.UpdateCookieBanner(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateCookieBannerOutput{}, fmt.Errorf("cannot update cookie banner: %w", err)
}
return nil, types.UpdateCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
}
func (r *Resolver) DeleteCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCookieBannerInput) (*mcp.CallToolResult, types.DeleteCookieBannerOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerDelete)
if err != nil {
return nil, types.DeleteCookieBannerOutput{}, err
}
if err := r.cookieBanner.DeleteCookieBanner(ctx, scope, input.ID); err != nil {
return nil, types.DeleteCookieBannerOutput{}, fmt.Errorf("cannot delete cookie banner: %w", err)
}
return nil, types.DeleteCookieBannerOutput{DeletedID: input.ID}, nil
}
func (r *Resolver) ActivateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ActivateCookieBannerInput) (*mcp.CallToolResult, types.ActivateCookieBannerOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerActivate)
if err != nil {
return nil, types.ActivateCookieBannerOutput{}, err
}
banner, err := r.cookieBanner.ActivateCookieBanner(ctx, scope, input.ID)
if err != nil {
return nil, types.ActivateCookieBannerOutput{}, fmt.Errorf("cannot activate cookie banner: %w", err)
}
return nil, types.ActivateCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
}
func (r *Resolver) DeactivateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeactivateCookieBannerInput) (*mcp.CallToolResult, types.DeactivateCookieBannerOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerDeactivate)
if err != nil {
return nil, types.DeactivateCookieBannerOutput{}, err
}
banner, err := r.cookieBanner.DeactivateCookieBanner(ctx, scope, input.ID)
if err != nil {
return nil, types.DeactivateCookieBannerOutput{}, fmt.Errorf("cannot deactivate cookie banner: %w", err)
}
return nil, types.DeactivateCookieBannerOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
}
func (r *Resolver) ListCookieCategoriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieCategoriesInput) (*mcp.CallToolResult, types.ListCookieCategoriesOutput, error) {
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryList)
if err != nil {
return nil, types.ListCookieCategoriesOutput{}, err
}
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieCategoryOrderField]{Field: coredata.CookieCategoryOrderFieldRank, Direction: page.OrderDirectionAsc})
categories, err := r.cookieBanner.ListCategoriesForBanner(ctx, scope, input.CookieBannerID, cursor, coredata.NewCookieCategoryFilter(new(coredata.CookieCategoryKindUncategorised)))
if err != nil {
panic(fmt.Errorf("cannot list cookie categories: %w", err))
}
p := page.NewPage(categories, cursor)
return nil, types.NewListCookieCategoriesOutput(p), nil
}
func (r *Resolver) GetCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieCategoryInput) (*mcp.CallToolResult, types.GetCookieCategoryOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryGet)
if err != nil {
return nil, types.GetCookieCategoryOutput{}, err
}
category, err := r.cookieBanner.GetCookieCategory(ctx, scope, input.ID)
if err != nil {
return nil, types.GetCookieCategoryOutput{}, fmt.Errorf("cannot get cookie category: %w", err)
}
return nil, types.GetCookieCategoryOutput{CookieCategory: types.NewCookieCategory(category)}, nil
}
func (r *Resolver) AddCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCookieCategoryInput) (*mcp.CallToolResult, types.AddCookieCategoryOutput, error) {
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryCreate)
if err != nil {
return nil, types.AddCookieCategoryOutput{}, err
}
category, err := r.cookieBanner.CreateCookieCategory(ctx, scope, cookiebanner.CreateCookieCategoryRequest{
CookieBannerID: input.CookieBannerID,
Name: input.Name,
Slug: input.Slug,
Description: input.Description,
Rank: input.Rank,
})
if err != nil {
return nil, types.AddCookieCategoryOutput{}, fmt.Errorf("cannot create cookie category: %w", err)
}
return nil, types.AddCookieCategoryOutput{CookieCategory: types.NewCookieCategory(category)}, nil
}
func (r *Resolver) UpdateCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCookieCategoryInput) (*mcp.CallToolResult, types.UpdateCookieCategoryOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryUpdate)
if err != nil {
return nil, types.UpdateCookieCategoryOutput{}, err
}
updateReq := cookiebanner.UpdateCookieCategoryRequest{CookieCategoryID: input.ID}
if v := UnwrapOmittable(input.Name); v != nil && *v != nil {
updateReq.Name = *v
}
if v := UnwrapOmittable(input.Slug); v != nil && *v != nil {
updateReq.Slug = *v
}
if v := UnwrapOmittable(input.Description); v != nil && *v != nil {
updateReq.Description = *v
}
category, err := r.cookieBanner.UpdateCookieCategory(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateCookieCategoryOutput{}, fmt.Errorf("cannot update cookie category: %w", err)
}
return nil, types.UpdateCookieCategoryOutput{CookieCategory: types.NewCookieCategory(category)}, nil
}
func (r *Resolver) DeleteCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCookieCategoryInput) (*mcp.CallToolResult, types.DeleteCookieCategoryOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryDelete)
if err != nil {
return nil, types.DeleteCookieCategoryOutput{}, err
}
if err := r.cookieBanner.DeleteCookieCategory(ctx, scope, input.ID); err != nil {
return nil, types.DeleteCookieCategoryOutput{}, fmt.Errorf("cannot delete cookie category: %w", err)
}
return nil, types.DeleteCookieCategoryOutput{DeletedID: input.ID}, nil
}
func (r *Resolver) ReorderCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ReorderCookieCategoryInput) (*mcp.CallToolResult, types.ReorderCookieCategoryOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryUpdate)
if err != nil {
return nil, types.ReorderCookieCategoryOutput{}, err
}
_, err = r.cookieBanner.ReorderCookieCategory(ctx, scope, cookiebanner.ReorderCookieCategoryRequest{
CookieCategoryID: input.ID,
Rank: input.Rank,
})
if err != nil {
return nil, types.ReorderCookieCategoryOutput{}, fmt.Errorf("cannot reorder cookie category: %w", err)
}
category, err := r.cookieBanner.GetCookieCategory(ctx, scope, input.ID)
if err != nil {
return nil, types.ReorderCookieCategoryOutput{}, fmt.Errorf("cannot get cookie category: %w", err)
}
return nil, types.ReorderCookieCategoryOutput{CookieCategory: types.NewCookieCategory(category)}, nil
}
func (r *Resolver) ListTrackerPatternsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrackerPatternsInput) (*mcp.CallToolResult, types.ListTrackerPatternsOutput, error) {
scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternList)
if err != nil {
return nil, types.ListTrackerPatternsOutput{}, err
}
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.TrackerPatternOrderField]{Field: coredata.TrackerPatternOrderFieldCreatedAt, Direction: page.OrderDirectionAsc})
patterns, err := r.cookieBanner.ListTrackerPatternsForCategory(ctx, scope, input.CookieCategoryID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list tracker patterns: %w", err))
}
p := page.NewPage(patterns, cursor)
return nil, types.NewListTrackerPatternsOutput(p), nil
}
func (r *Resolver) GetTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrackerPatternInput) (*mcp.CallToolResult, types.GetTrackerPatternOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternGet)
if err != nil {
return nil, types.GetTrackerPatternOutput{}, err
}
pattern, err := r.cookieBanner.GetTrackerPattern(ctx, scope, input.ID)
if err != nil {
return nil, types.GetTrackerPatternOutput{}, fmt.Errorf("cannot get tracker pattern: %w", err)
}
return nil, types.GetTrackerPatternOutput{TrackerPattern: types.NewTrackerPattern(pattern)}, nil
}
func (r *Resolver) AddTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrackerPatternInput) (*mcp.CallToolResult, types.AddTrackerPatternOutput, error) {
scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternCreate)
if err != nil {
return nil, types.AddTrackerPatternOutput{}, err
}
pattern, err := r.cookieBanner.CreateTrackerPattern(ctx, scope, cookiebanner.CreateTrackerPatternRequest{
CookieCategoryID: input.CookieCategoryID,
TrackerType: coredata.TrackerType(input.TrackerType),
Pattern: input.Pattern,
MatchType: coredata.TrackerPatternMatchType(input.MatchType),
DisplayName: input.DisplayName,
MaxAgeSeconds: input.MaxAgeSeconds,
Description: input.Description,
})
if err != nil {
return nil, types.AddTrackerPatternOutput{}, fmt.Errorf("cannot create tracker pattern: %w", err)
}
return nil, types.AddTrackerPatternOutput{TrackerPattern: types.NewTrackerPattern(pattern)}, nil
}
func (r *Resolver) UpdateTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrackerPatternInput) (*mcp.CallToolResult, types.UpdateTrackerPatternOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternUpdate)
if err != nil {
return nil, types.UpdateTrackerPatternOutput{}, err
}
updateReq := cookiebanner.UpdateTrackerPatternRequest{TrackerPatternID: input.ID}
if input.MaxAgeSeconds.IsSet() {
val, _ := input.MaxAgeSeconds.Value()
updateReq.MaxAgeSeconds = &val
}
if v := UnwrapOmittable(input.Description); v != nil && *v != nil {
updateReq.Description = *v
}
if v := UnwrapOmittable(input.Excluded); v != nil && *v != nil {
updateReq.Excluded = *v
}
pattern, err := r.cookieBanner.UpdateTrackerPattern(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateTrackerPatternOutput{}, fmt.Errorf("cannot update tracker pattern: %w", err)
}
return nil, types.UpdateTrackerPatternOutput{TrackerPattern: types.NewTrackerPattern(pattern)}, nil
}
func (r *Resolver) DeleteTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrackerPatternInput) (*mcp.CallToolResult, types.DeleteTrackerPatternOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternDelete)
if err != nil {
return nil, types.DeleteTrackerPatternOutput{}, err
}
if err := r.cookieBanner.DeleteTrackerPattern(ctx, scope, input.ID); err != nil {
return nil, types.DeleteTrackerPatternOutput{}, fmt.Errorf("cannot delete tracker pattern: %w", err)
}
return nil, types.DeleteTrackerPatternOutput{DeletedID: input.ID}, nil
}
func (r *Resolver) MoveTrackerPatternToCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.MoveTrackerPatternToCategoryInput) (*mcp.CallToolResult, types.MoveTrackerPatternToCategoryOutput, error) {
scope, err := r.Authorize(ctx, input.TrackerPatternID, probo.ActionTrackerPatternUpdate)
if err != nil {
return nil, types.MoveTrackerPatternToCategoryOutput{}, err
}
if _, err := r.Authorize(ctx, input.TargetCookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
return nil, types.MoveTrackerPatternToCategoryOutput{}, err
}
result, err := r.cookieBanner.MoveTrackerPatternToCategory(ctx, scope, cookiebanner.MoveTrackerPatternToCategoryRequest{
TrackerPatternID: input.TrackerPatternID,
TargetCookieCategoryID: input.TargetCookieCategoryID,
})
if err != nil {
return nil, types.MoveTrackerPatternToCategoryOutput{}, fmt.Errorf("cannot move tracker pattern: %w", err)
}
return nil, types.MoveTrackerPatternToCategoryOutput{TrackerPattern: types.NewTrackerPattern(result.TrackerPattern)}, nil
}
func (r *Resolver) PublishCookieBannerVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishCookieBannerVersionInput) (*mcp.CallToolResult, types.PublishCookieBannerVersionOutput, error) {
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionPublish)
if err != nil {
return nil, types.PublishCookieBannerVersionOutput{}, err
}
version, err := r.cookieBanner.PublishCookieBannerVersion(ctx, scope, input.CookieBannerID)
if err != nil {
return nil, types.PublishCookieBannerVersionOutput{}, fmt.Errorf("cannot publish cookie banner version: %w", err)
}
return nil, types.PublishCookieBannerVersionOutput{CookieBannerVersion: types.NewCookieBannerVersion(version)}, nil
}
func (r *Resolver) RegenerateCookieBannerTrackerPolicyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RegenerateCookieBannerTrackerPolicyInput) (*mcp.CallToolResult, types.RegenerateCookieBannerTrackerPolicyOutput, error) {
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerRegeneratePolicy)
if err != nil {
return nil, types.RegenerateCookieBannerTrackerPolicyOutput{}, err
}
banner, err := r.cookieBanner.RegenerateTrackerPolicy(ctx, scope, input.CookieBannerID)
if err != nil {
return nil, types.RegenerateCookieBannerTrackerPolicyOutput{}, fmt.Errorf("cannot regenerate cookie banner tracker policy: %w", err)
}
return nil, types.RegenerateCookieBannerTrackerPolicyOutput{CookieBanner: types.NewCookieBanner(banner)}, nil
}
func (r *Resolver) ListCookieBannerVersionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieBannerVersionsInput) (*mcp.CallToolResult, types.ListCookieBannerVersionsOutput, error) {
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionList)
if err != nil {
return nil, types.ListCookieBannerVersionsOutput{}, err
}
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieBannerVersionOrderField]{Field: coredata.CookieBannerVersionOrderFieldCreatedAt, Direction: page.OrderDirectionDesc})
versions, err := r.cookieBanner.ListCookieBannerVersionsForBanner(ctx, scope, input.CookieBannerID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list cookie banner versions: %w", err))
}
p := page.NewPage(versions, cursor)
return nil, types.NewListCookieBannerVersionsOutput(p), nil
}
func (r *Resolver) UpsertCookieBannerTranslationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpsertCookieBannerTranslationInput) (*mcp.CallToolResult, types.UpsertCookieBannerTranslationOutput, error) {
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerUpdate)
if err != nil {
return nil, types.UpsertCookieBannerTranslationOutput{}, err
}
translation, err := r.cookieBanner.UpsertCookieBannerTranslation(ctx, scope, cookiebanner.UpsertCookieBannerTranslationRequest{
CookieBannerID: input.CookieBannerID,
Language: input.Language,
Translations: json.RawMessage(input.Translations),
})
if err != nil {
return nil, types.UpsertCookieBannerTranslationOutput{}, fmt.Errorf("cannot upsert cookie banner translation: %w", err)
}
return nil, types.UpsertCookieBannerTranslationOutput{CookieBannerTranslation: types.NewCookieBannerTranslation(translation)}, nil
}
func (r *Resolver) ListCookieConsentRecordsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieConsentRecordsInput) (*mcp.CallToolResult, types.ListCookieConsentRecordsOutput, error) {
scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieConsentRecordList)
if err != nil {
return nil, types.ListCookieConsentRecordsOutput{}, err
}
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieConsentRecordOrderField]{Field: coredata.CookieConsentRecordOrderFieldCreatedAt, Direction: page.OrderDirectionDesc})
var action *coredata.CookieConsentAction
if input.Action != nil {
a := coredata.CookieConsentAction(*input.Action)
action = &a
}
filter := coredata.NewCookieConsentRecordFilter(action, input.VisitorID, input.Version)
records, err := r.cookieBanner.ListCookieConsentRecordsForBanner(ctx, scope, input.CookieBannerID, cursor, filter)
if err != nil {
panic(fmt.Errorf("cannot list cookie consent records: %w", err))
}
p := page.NewPage(records, cursor)
return nil, types.NewListCookieConsentRecordsOutput(p), nil
}
func (r *Resolver) GetCookieConsentRecordTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieConsentRecordInput) (*mcp.CallToolResult, types.GetCookieConsentRecordOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieConsentRecordList)
if err != nil {
return nil, types.GetCookieConsentRecordOutput{}, err
}
record, err := r.cookieBanner.GetCookieConsentRecord(ctx, scope, input.ID)
if err != nil {
return nil, types.GetCookieConsentRecordOutput{}, fmt.Errorf("cannot get cookie consent record: %w", err)
}
return nil, types.GetCookieConsentRecordOutput{CookieConsentRecord: types.NewCookieConsentRecord(record)}, nil
}
func (r *Resolver) PublishRiskListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishRiskListInput) (*mcp.CallToolResult, types.PublishRiskListOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskPublish)
if err != nil {
return nil, types.PublishRiskListOutput{}, err
}
svc := r.proboSvc
document, documentVersion, err := svc.GeneratedDocuments.PublishRiskList(ctx, scope, input.OrganizationID, input.ApproverIds, input.Minor)
if err != nil {
return nil, types.PublishRiskListOutput{}, fmt.Errorf("cannot publish risk list: %w", err)
}
return nil, types.PublishRiskListOutput{
DocumentID: document.ID,
DocumentVersionID: documentVersion.ID,
}, nil
}
func (r *Resolver) GetSCIMConfigurationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetSCIMConfigurationInput) (*mcp.CallToolResult, types.GetSCIMConfigurationOutput, error) {
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionSCIMConfigurationGet); err != nil {
return nil, types.GetSCIMConfigurationOutput{}, err
}
config, err := r.iamSvc.OrganizationService.GetSCIMConfiguration(ctx, input.OrganizationID)
if err != nil {
if _, ok := errors.AsType[*iam.ErrNoSCIMConfigurationFound](err); ok {
return nil, types.GetSCIMConfigurationOutput{}, fmt.Errorf("SCIM configuration not found")
}
panic(fmt.Errorf("cannot get SCIM configuration: %w", err))
}
return nil, types.GetSCIMConfigurationOutput{ScimConfiguration: types.NewSCIMConfiguration(config)}, nil
}
func (r *Resolver) CreateSCIMConfigurationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateSCIMConfigurationInput) (*mcp.CallToolResult, types.CreateSCIMConfigurationOutput, error) {
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionSCIMConfigurationCreate); err != nil {
return nil, types.CreateSCIMConfigurationOutput{}, err
}
config, token, err := r.iamSvc.OrganizationService.CreateSCIMConfiguration(ctx, input.OrganizationID)
if err != nil {
return nil, types.CreateSCIMConfigurationOutput{}, fmt.Errorf("cannot create SCIM configuration: %w", err)
}
output := types.CreateSCIMConfigurationOutput{
ScimConfiguration: types.NewSCIMConfiguration(config),
Token: token,
}
if input.ConnectorID != nil {
bridge, err := r.iamSvc.OrganizationService.CreateSCIMBridge(ctx, input.OrganizationID, config.ID, *input.ConnectorID)
if err != nil {
return nil, types.CreateSCIMConfigurationOutput{}, fmt.Errorf("cannot create SCIM bridge: %w", err)
}
output.ScimBridge = types.NewSCIMBridge(bridge)
}
return nil, output, nil
}
func (r *Resolver) DeleteSCIMConfigurationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteSCIMConfigurationInput) (*mcp.CallToolResult, types.DeleteSCIMConfigurationOutput, error) {
if _, err := r.Authorize(ctx, input.OrganizationID, iam.ActionSCIMConfigurationDelete); err != nil {
return nil, types.DeleteSCIMConfigurationOutput{}, err
}
err := r.iamSvc.OrganizationService.DeleteSCIMConfiguration(ctx, input.OrganizationID, input.ScimConfigurationID)
if err != nil {
return nil, types.DeleteSCIMConfigurationOutput{}, fmt.Errorf("cannot delete SCIM configuration: %w", err)
}
return nil, types.DeleteSCIMConfigurationOutput{DeletedScimConfigurationID: input.ScimConfigurationID}, nil
}
func (r *Resolver) RegenerateSCIMTokenTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RegenerateSCIMTokenInput) (*mcp.CallToolResult, types.RegenerateSCIMTokenOutput, error) {
if _, err := r.Authorize(ctx, input.ScimConfigurationID, iam.ActionSCIMConfigurationUpdate); err != nil {
return nil, types.RegenerateSCIMTokenOutput{}, err
}
config, token, err := r.iamSvc.OrganizationService.RegenerateSCIMToken(ctx, input.OrganizationID, input.ScimConfigurationID)
if err != nil {
return nil, types.RegenerateSCIMTokenOutput{}, fmt.Errorf("cannot regenerate SCIM token: %w", err)
}
return nil, types.RegenerateSCIMTokenOutput{
ScimConfiguration: types.NewSCIMConfiguration(config),
Token: token,
}, nil
}
func (r *Resolver) GetSCIMBridgeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetSCIMBridgeInput) (*mcp.CallToolResult, types.GetSCIMBridgeOutput, error) {
if _, err := r.Authorize(ctx, input.ID, iam.ActionSCIMBridgeGet); err != nil {
return nil, types.GetSCIMBridgeOutput{}, err
}
bridge, err := r.iamSvc.OrganizationService.GetSCIMBridgeByID(ctx, input.ID)
if err != nil {
if _, ok := errors.AsType[*iam.ErrSCIMBridgeNotFound](err); ok {
return nil, types.GetSCIMBridgeOutput{}, fmt.Errorf("SCIM bridge %s not found", input.ID)
}
panic(fmt.Errorf("cannot get SCIM bridge: %w", err))
}
return nil, types.GetSCIMBridgeOutput{ScimBridge: types.NewSCIMBridge(bridge)}, nil
}
func (r *Resolver) UpdateSCIMBridgeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateSCIMBridgeInput) (*mcp.CallToolResult, types.UpdateSCIMBridgeOutput, error) {
if _, err := r.Authorize(ctx, input.ScimBridgeID, iam.ActionSCIMBridgeUpdate); err != nil {
return nil, types.UpdateSCIMBridgeOutput{}, err
}
bridge, err := r.iamSvc.OrganizationService.UpdateSCIMBridge(ctx, input.OrganizationID, input.ScimBridgeID, input.ExcludedUserNames)
if err != nil {
return nil, types.UpdateSCIMBridgeOutput{}, fmt.Errorf("cannot update SCIM bridge: %w", err)
}
return nil, types.UpdateSCIMBridgeOutput{ScimBridge: types.NewSCIMBridge(bridge)}, nil
}
func (r *Resolver) ListSCIMEventsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListSCIMEventsInput) (*mcp.CallToolResult, types.ListSCIMEventsOutput, error) {
if _, err := r.Authorize(ctx, input.ScimConfigurationID, iam.ActionSCIMEventList); err != nil {
return nil, types.ListSCIMEventsOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.SCIMEventOrderField]{
Field: coredata.SCIMEventOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.SCIMEventOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.iamSvc.OrganizationService.ListSCIMEventsByConfigID(ctx, input.ScimConfigurationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list SCIM events: %w", err))
}
return nil, types.NewListSCIMEventsOutput(p), nil
}
func (r *Resolver) PublishDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishDocumentInput) (*mcp.CallToolResult, types.PublishDocumentOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentID, probo.ActionDocumentVersionPublish)
if err != nil {
return nil, types.PublishDocumentOutput{}, err
}
svc := r.proboSvc
result, err := svc.Documents.PublishVersionWithDefaultApprovers(ctx, scope, probo.PublishDocumentRequest{
DocumentID: input.DocumentID,
Minor: input.Minor,
Changelog: input.Changelog,
})
if err != nil {
panic(fmt.Errorf("cannot publish document: %w", err))
}
output := types.PublishDocumentOutput{
Document: types.NewDocument(result.Document),
DocumentVersion: types.NewDocumentVersion(result.Version),
}
if result.Quorum != nil {
output.ApprovalQuorum = types.NewDocumentVersionApprovalQuorum(result.Quorum)
}
return nil, output, nil
}
func (r *Resolver) ListTrackerResourcesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrackerResourcesInput) (*mcp.CallToolResult, types.ListTrackerResourcesOutput, error) {
scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceList)
if err != nil {
return nil, types.ListTrackerResourcesOutput{}, err
}
cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.TrackerResourceOrderField]{Field: coredata.TrackerResourceOrderFieldCreatedAt, Direction: page.OrderDirectionAsc})
resources, err := r.cookieBanner.ListTrackerResourcesForCategory(ctx, scope, input.CookieCategoryID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list tracker resources: %w", err))
}
p := page.NewPage(resources, cursor)
return nil, types.NewListTrackerResourcesOutput(p), nil
}
func (r *Resolver) GetTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrackerResourceInput) (*mcp.CallToolResult, types.GetTrackerResourceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceGet)
if err != nil {
return nil, types.GetTrackerResourceOutput{}, err
}
resource, err := r.cookieBanner.GetTrackerResource(ctx, scope, input.ID)
if err != nil {
return nil, types.GetTrackerResourceOutput{}, fmt.Errorf("cannot get tracker resource: %w", err)
}
return nil, types.GetTrackerResourceOutput{TrackerResource: types.NewTrackerResource(resource)}, nil
}
func (r *Resolver) AddTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrackerResourceInput) (*mcp.CallToolResult, types.AddTrackerResourceOutput, error) {
scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceCreate)
if err != nil {
return nil, types.AddTrackerResourceOutput{}, err
}
description := ""
if input.Description != nil {
description = *input.Description
}
resource, err := r.cookieBanner.CreateTrackerResource(ctx, scope, cookiebanner.CreateTrackerResourceRequest{
CookieCategoryID: input.CookieCategoryID,
ResourceType: coredata.TrackerResourceType(input.ResourceType),
Origin: input.Origin,
Path: input.Path,
DisplayName: input.DisplayName,
Description: description,
})
if err != nil {
return nil, types.AddTrackerResourceOutput{}, fmt.Errorf("cannot create tracker resource: %w", err)
}
return nil, types.AddTrackerResourceOutput{TrackerResource: types.NewTrackerResource(resource)}, nil
}
func (r *Resolver) UpdateTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrackerResourceInput) (*mcp.CallToolResult, types.UpdateTrackerResourceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceUpdate)
if err != nil {
return nil, types.UpdateTrackerResourceOutput{}, err
}
updateReq := cookiebanner.UpdateTrackerResourceRequest{TrackerResourceID: input.ID}
if v := UnwrapOmittable(input.DisplayName); v != nil && *v != nil {
updateReq.DisplayName = *v
}
if v := UnwrapOmittable(input.Description); v != nil && *v != nil {
updateReq.Description = *v
}
if v := UnwrapOmittable(input.Excluded); v != nil && *v != nil {
updateReq.Excluded = *v
}
resource, err := r.cookieBanner.UpdateTrackerResource(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateTrackerResourceOutput{}, fmt.Errorf("cannot update tracker resource: %w", err)
}
return nil, types.UpdateTrackerResourceOutput{TrackerResource: types.NewTrackerResource(resource)}, nil
}
func (r *Resolver) DeleteTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrackerResourceInput) (*mcp.CallToolResult, types.DeleteTrackerResourceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceDelete)
if err != nil {
return nil, types.DeleteTrackerResourceOutput{}, err
}
if err := r.cookieBanner.DeleteTrackerResource(ctx, scope, input.ID); err != nil {
return nil, types.DeleteTrackerResourceOutput{}, fmt.Errorf("cannot delete tracker resource: %w", err)
}
return nil, types.DeleteTrackerResourceOutput{DeletedID: input.ID}, nil
}
func (r *Resolver) MoveTrackerResourceToCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.MoveTrackerResourceToCategoryInput) (*mcp.CallToolResult, types.MoveTrackerResourceToCategoryOutput, error) {
scope, err := r.Authorize(ctx, input.TrackerResourceID, probo.ActionTrackerResourceUpdate)
if err != nil {
return nil, types.MoveTrackerResourceToCategoryOutput{}, err
}
if _, err := r.Authorize(ctx, input.TargetCookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
return nil, types.MoveTrackerResourceToCategoryOutput{}, err
}
result, err := r.cookieBanner.MoveTrackerResourceToCategory(ctx, scope, cookiebanner.MoveTrackerResourceToCategoryRequest{
TrackerResourceID: input.TrackerResourceID,
TargetCookieCategoryID: input.TargetCookieCategoryID,
})
if err != nil {
return nil, types.MoveTrackerResourceToCategoryOutput{}, fmt.Errorf("cannot move tracker resource: %w", err)
}
return nil, types.MoveTrackerResourceToCategoryOutput{TrackerResource: types.NewTrackerResource(result.TrackerResource)}, nil
}
func (r *Resolver) ListChildThirdPartiesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListChildThirdPartiesInput) (*mcp.CallToolResult, types.ListChildThirdPartiesOutput, error) {
scope, err := r.Authorize(ctx, input.ParentThirdPartyID, probo.ActionThirdPartyRelationList)
if err != nil {
return nil, types.ListChildThirdPartiesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.ThirdPartyOrderField]{
Field: coredata.ThirdPartyOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ThirdPartyOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := r.proboSvc.ThirdParties.ListForParentThirdPartyID(ctx, scope, input.ParentThirdPartyID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list child third parties: %w", err))
}
return nil, types.NewListChildThirdPartiesOutput(page), nil
}
func (r *Resolver) ListRiskAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentsInput) (*mcp.CallToolResult, types.ListRiskAssessmentsOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskAssessmentList)
if err != nil {
return nil, types.ListRiskAssessmentsOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.RiskAssessmentOrderField]{
Field: coredata.RiskAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.riskManagement.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list risk assessments: %w", err))
}
return nil, types.NewListRiskAssessmentsOutput(p), nil
}
func (r *Resolver) GetRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentInput) (*mcp.CallToolResult, types.GetRiskAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentGet)
if err != nil {
return nil, types.GetRiskAssessmentOutput{}, err
}
ra, err := r.riskManagement.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskAssessmentOutput{}, fmt.Errorf("failed to get risk assessment: %w", err)
}
return nil, types.GetRiskAssessmentOutput{
RiskAssessment: types.NewRiskAssessment(ra),
}, nil
}
func (r *Resolver) AddRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentInput) (*mcp.CallToolResult, types.AddRiskAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskAssessmentCreate)
if err != nil {
return nil, types.AddRiskAssessmentOutput{}, err
}
ra, err := r.riskManagement.Create(ctx, scope, riskmanagement.CreateRiskAssessmentRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
})
if err != nil {
return nil, types.AddRiskAssessmentOutput{}, fmt.Errorf("failed to create risk assessment: %w", err)
}
return nil, types.AddRiskAssessmentOutput{
RiskAssessment: types.NewRiskAssessment(ra),
}, nil
}
func (r *Resolver) UpdateRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentUpdate)
if err != nil {
return nil, types.UpdateRiskAssessmentOutput{}, err
}
ra, err := r.riskManagement.Update(ctx, scope, riskmanagement.UpdateRiskAssessmentRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
})
if err != nil {
return nil, types.UpdateRiskAssessmentOutput{}, fmt.Errorf("failed to update risk assessment: %w", err)
}
return nil, types.UpdateRiskAssessmentOutput{
RiskAssessment: types.NewRiskAssessment(ra),
}, nil
}
func (r *Resolver) DeleteRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentDelete)
if err != nil {
return nil, types.DeleteRiskAssessmentOutput{}, err
}
if err := r.riskManagement.Delete(ctx, scope, input.ID); err != nil {
return nil, types.DeleteRiskAssessmentOutput{}, fmt.Errorf("failed to delete risk assessment: %w", err)
}
return nil, types.DeleteRiskAssessmentOutput{
DeletedRiskAssessmentID: input.ID,
}, nil
}
func (r *Resolver) ListRiskAssessmentScopesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentScopesInput) (*mcp.CallToolResult, types.ListRiskAssessmentScopesOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentID, probo.ActionRiskAssessmentScopeList)
if err != nil {
return nil, types.ListRiskAssessmentScopesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.RiskAssessmentScopeOrderField]{
Field: coredata.RiskAssessmentScopeOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentScopeOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.riskManagement.ListScopesForRiskAssessmentID(ctx, scope, input.RiskAssessmentID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list risk assessment scopes: %w", err))
}
return nil, types.NewListRiskAssessmentScopesOutput(p), nil
}
func (r *Resolver) GetRiskAssessmentScopeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentScopeInput) (*mcp.CallToolResult, types.GetRiskAssessmentScopeOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScopeGet)
if err != nil {
return nil, types.GetRiskAssessmentScopeOutput{}, err
}
s, err := r.riskManagement.GetScope(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskAssessmentScopeOutput{}, fmt.Errorf("failed to get risk assessment scope: %w", err)
}
return nil, types.GetRiskAssessmentScopeOutput{
RiskAssessmentScope: types.NewRiskAssessmentScope(s),
}, nil
}
func (r *Resolver) AddRiskAssessmentScopeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentScopeInput) (*mcp.CallToolResult, types.AddRiskAssessmentScopeOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentID, probo.ActionRiskAssessmentScopeCreate)
if err != nil {
return nil, types.AddRiskAssessmentScopeOutput{}, err
}
s, err := r.riskManagement.CreateScope(ctx, scope, riskmanagement.CreateRiskAssessmentScopeRequest{
RiskAssessmentID: input.RiskAssessmentID,
Name: input.Name,
})
if err != nil {
return nil, types.AddRiskAssessmentScopeOutput{}, fmt.Errorf("failed to create risk assessment scope: %w", err)
}
return nil, types.AddRiskAssessmentScopeOutput{
RiskAssessmentScope: types.NewRiskAssessmentScope(s),
}, nil
}
func (r *Resolver) UpdateRiskAssessmentScopeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentScopeInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentScopeOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScopeUpdate)
if err != nil {
return nil, types.UpdateRiskAssessmentScopeOutput{}, err
}
s, err := r.riskManagement.UpdateScope(ctx, scope, riskmanagement.UpdateRiskAssessmentScopeRequest{
ID: input.ID,
Name: input.Name,
})
if err != nil {
return nil, types.UpdateRiskAssessmentScopeOutput{}, fmt.Errorf("failed to update risk assessment scope: %w", err)
}
return nil, types.UpdateRiskAssessmentScopeOutput{
RiskAssessmentScope: types.NewRiskAssessmentScope(s),
}, nil
}
func (r *Resolver) DeleteRiskAssessmentScopeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentScopeInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentScopeOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScopeDelete)
if err != nil {
return nil, types.DeleteRiskAssessmentScopeOutput{}, err
}
if err := r.riskManagement.DeleteScope(ctx, scope, input.ID); err != nil {
return nil, types.DeleteRiskAssessmentScopeOutput{}, fmt.Errorf("failed to delete risk assessment scope: %w", err)
}
return nil, types.DeleteRiskAssessmentScopeOutput{
DeletedRiskAssessmentScopeID: input.ID,
}, nil
}
func (r *Resolver) ListRiskAssessmentNodesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentNodesInput) (*mcp.CallToolResult, types.ListRiskAssessmentNodesOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentNodeList)
if err != nil {
return nil, types.ListRiskAssessmentNodesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.RiskAssessmentNodeOrderField]{
Field: coredata.RiskAssessmentNodeOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentNodeOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.riskManagement.ListNodesForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list risk assessment nodes: %w", err))
}
return nil, types.NewListRiskAssessmentNodesOutput(p), nil
}
func (r *Resolver) GetRiskAssessmentNodeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentNodeInput) (*mcp.CallToolResult, types.GetRiskAssessmentNodeOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentNodeGet)
if err != nil {
return nil, types.GetRiskAssessmentNodeOutput{}, err
}
n, err := r.riskManagement.GetNode(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskAssessmentNodeOutput{}, fmt.Errorf("failed to get risk assessment node: %w", err)
}
return nil, types.GetRiskAssessmentNodeOutput{
RiskAssessmentNode: types.NewRiskAssessmentNode(n),
}, nil
}
func (r *Resolver) AddRiskAssessmentNodeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentNodeInput) (*mcp.CallToolResult, types.AddRiskAssessmentNodeOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentNodeCreate)
if err != nil {
return nil, types.AddRiskAssessmentNodeOutput{}, err
}
n, err := r.riskManagement.CreateNode(ctx, scope, riskmanagement.CreateRiskAssessmentNodeRequest{
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
BoundaryID: input.BoundaryID,
NodeType: input.NodeType,
Name: input.Name,
})
if err != nil {
return nil, types.AddRiskAssessmentNodeOutput{}, fmt.Errorf("failed to create risk assessment node: %w", err)
}
return nil, types.AddRiskAssessmentNodeOutput{
RiskAssessmentNode: types.NewRiskAssessmentNode(n),
}, nil
}
func (r *Resolver) UpdateRiskAssessmentNodeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentNodeInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentNodeOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentNodeUpdate)
if err != nil {
return nil, types.UpdateRiskAssessmentNodeOutput{}, err
}
var boundaryID **gid.GID
if input.BoundaryID != nil {
boundaryID = &input.BoundaryID
}
n, err := r.riskManagement.UpdateNode(ctx, scope, riskmanagement.UpdateRiskAssessmentNodeRequest{
ID: input.ID,
BoundaryID: boundaryID,
NodeType: input.NodeType,
Name: input.Name,
})
if err != nil {
return nil, types.UpdateRiskAssessmentNodeOutput{}, fmt.Errorf("failed to update risk assessment node: %w", err)
}
return nil, types.UpdateRiskAssessmentNodeOutput{
RiskAssessmentNode: types.NewRiskAssessmentNode(n),
}, nil
}
func (r *Resolver) DeleteRiskAssessmentNodeTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentNodeInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentNodeOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentNodeDelete)
if err != nil {
return nil, types.DeleteRiskAssessmentNodeOutput{}, err
}
if err := r.riskManagement.DeleteNode(ctx, scope, input.ID); err != nil {
return nil, types.DeleteRiskAssessmentNodeOutput{}, fmt.Errorf("failed to delete risk assessment node: %w", err)
}
return nil, types.DeleteRiskAssessmentNodeOutput{
DeletedRiskAssessmentNodeID: input.ID,
}, nil
}
func (r *Resolver) ListRiskAssessmentProcessesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentProcessesInput) (*mcp.CallToolResult, types.ListRiskAssessmentProcessesOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentProcessList)
if err != nil {
return nil, types.ListRiskAssessmentProcessesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.RiskAssessmentProcessOrderField]{
Field: coredata.RiskAssessmentProcessOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentProcessOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.riskManagement.ListProcessesForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list risk assessment processes: %w", err))
}
return nil, types.NewListRiskAssessmentProcessesOutput(p), nil
}
func (r *Resolver) GetRiskAssessmentProcessTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentProcessInput) (*mcp.CallToolResult, types.GetRiskAssessmentProcessOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentProcessGet)
if err != nil {
return nil, types.GetRiskAssessmentProcessOutput{}, err
}
p, err := r.riskManagement.GetProcess(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskAssessmentProcessOutput{}, fmt.Errorf("failed to get risk assessment process: %w", err)
}
return nil, types.GetRiskAssessmentProcessOutput{
RiskAssessmentProcess: types.NewRiskAssessmentProcess(p),
}, nil
}
func (r *Resolver) AddRiskAssessmentProcessTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentProcessInput) (*mcp.CallToolResult, types.AddRiskAssessmentProcessOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentProcessCreate)
if err != nil {
return nil, types.AddRiskAssessmentProcessOutput{}, err
}
p, err := r.riskManagement.CreateProcess(ctx, scope, riskmanagement.CreateRiskAssessmentProcessRequest{
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
SourceNodeID: input.SourceNodeID,
TargetNodeID: input.TargetNodeID,
Name: input.Name,
})
if err != nil {
return nil, types.AddRiskAssessmentProcessOutput{}, fmt.Errorf("failed to create risk assessment process: %w", err)
}
return nil, types.AddRiskAssessmentProcessOutput{
RiskAssessmentProcess: types.NewRiskAssessmentProcess(p),
}, nil
}
func (r *Resolver) UpdateRiskAssessmentProcessTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentProcessInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentProcessOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentProcessUpdate)
if err != nil {
return nil, types.UpdateRiskAssessmentProcessOutput{}, err
}
p, err := r.riskManagement.UpdateProcess(ctx, scope, riskmanagement.UpdateRiskAssessmentProcessRequest{
ID: input.ID,
SourceNodeID: input.SourceNodeID,
TargetNodeID: input.TargetNodeID,
Name: input.Name,
})
if err != nil {
return nil, types.UpdateRiskAssessmentProcessOutput{}, fmt.Errorf("failed to update risk assessment process: %w", err)
}
return nil, types.UpdateRiskAssessmentProcessOutput{
RiskAssessmentProcess: types.NewRiskAssessmentProcess(p),
}, nil
}
func (r *Resolver) DeleteRiskAssessmentProcessTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentProcessInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentProcessOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentProcessDelete)
if err != nil {
return nil, types.DeleteRiskAssessmentProcessOutput{}, err
}
if err := r.riskManagement.DeleteProcess(ctx, scope, input.ID); err != nil {
return nil, types.DeleteRiskAssessmentProcessOutput{}, fmt.Errorf("failed to delete risk assessment process: %w", err)
}
return nil, types.DeleteRiskAssessmentProcessOutput{
DeletedRiskAssessmentProcessID: input.ID,
}, nil
}
func (r *Resolver) ListRiskAssessmentThreatsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentThreatsInput) (*mcp.CallToolResult, types.ListRiskAssessmentThreatsOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentThreatList)
if err != nil {
return nil, types.ListRiskAssessmentThreatsOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.RiskAssessmentThreatOrderField]{
Field: coredata.RiskAssessmentThreatOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentThreatOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.riskManagement.ListThreatsForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list risk assessment threats: %w", err))
}
return nil, types.NewListRiskAssessmentThreatsOutput(p), nil
}
func (r *Resolver) GetRiskAssessmentThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentThreatInput) (*mcp.CallToolResult, types.GetRiskAssessmentThreatOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentThreatGet)
if err != nil {
return nil, types.GetRiskAssessmentThreatOutput{}, err
}
t, err := r.riskManagement.GetThreat(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskAssessmentThreatOutput{}, fmt.Errorf("failed to get risk assessment threat: %w", err)
}
return nil, types.GetRiskAssessmentThreatOutput{
RiskAssessmentThreat: types.NewRiskAssessmentThreat(t),
}, nil
}
func (r *Resolver) AddRiskAssessmentThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentThreatInput) (*mcp.CallToolResult, types.AddRiskAssessmentThreatOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentThreatCreate)
if err != nil {
return nil, types.AddRiskAssessmentThreatOutput{}, err
}
t, err := r.riskManagement.CreateThreat(ctx, scope, riskmanagement.CreateRiskAssessmentThreatRequest{
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
ProcessID: input.ProcessID,
Name: input.Name,
Category: input.Category,
})
if err != nil {
return nil, types.AddRiskAssessmentThreatOutput{}, fmt.Errorf("failed to create risk assessment threat: %w", err)
}
return nil, types.AddRiskAssessmentThreatOutput{
RiskAssessmentThreat: types.NewRiskAssessmentThreat(t),
}, nil
}
func (r *Resolver) UpdateRiskAssessmentThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentThreatInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentThreatOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentThreatUpdate)
if err != nil {
return nil, types.UpdateRiskAssessmentThreatOutput{}, err
}
t, err := r.riskManagement.UpdateThreat(ctx, scope, riskmanagement.UpdateRiskAssessmentThreatRequest{
ID: input.ID,
ProcessID: input.ProcessID,
Name: input.Name,
Category: input.Category,
})
if err != nil {
return nil, types.UpdateRiskAssessmentThreatOutput{}, fmt.Errorf("failed to update risk assessment threat: %w", err)
}
return nil, types.UpdateRiskAssessmentThreatOutput{
RiskAssessmentThreat: types.NewRiskAssessmentThreat(t),
}, nil
}
func (r *Resolver) DeleteRiskAssessmentThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentThreatInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentThreatOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentThreatDelete)
if err != nil {
return nil, types.DeleteRiskAssessmentThreatOutput{}, err
}
if err := r.riskManagement.DeleteThreat(ctx, scope, input.ID); err != nil {
return nil, types.DeleteRiskAssessmentThreatOutput{}, fmt.Errorf("failed to delete risk assessment threat: %w", err)
}
return nil, types.DeleteRiskAssessmentThreatOutput{
DeletedRiskAssessmentThreatID: input.ID,
}, nil
}
func (r *Resolver) ListRiskAssessmentScenariosTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentScenariosInput) (*mcp.CallToolResult, types.ListRiskAssessmentScenariosOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentScenarioList)
if err != nil {
return nil, types.ListRiskAssessmentScenariosOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.RiskAssessmentScenarioOrderField]{
Field: coredata.RiskAssessmentScenarioOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentScenarioOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.riskManagement.ListScenariosForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list risk assessment scenarios: %w", err))
}
return nil, types.NewListRiskAssessmentScenariosOutput(p), nil
}
func (r *Resolver) GetRiskAssessmentScenarioTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentScenarioInput) (*mcp.CallToolResult, types.GetRiskAssessmentScenarioOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScenarioGet)
if err != nil {
return nil, types.GetRiskAssessmentScenarioOutput{}, err
}
s, err := r.riskManagement.GetScenario(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskAssessmentScenarioOutput{}, fmt.Errorf("failed to get risk assessment scenario: %w", err)
}
return nil, types.GetRiskAssessmentScenarioOutput{
RiskAssessmentScenario: types.NewRiskAssessmentScenario(s),
}, nil
}
func (r *Resolver) AddRiskAssessmentScenarioTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentScenarioInput) (*mcp.CallToolResult, types.AddRiskAssessmentScenarioOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentScenarioCreate)
if err != nil {
return nil, types.AddRiskAssessmentScenarioOutput{}, err
}
s, err := r.riskManagement.CreateScenario(ctx, scope, riskmanagement.CreateRiskAssessmentScenarioRequest{
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
Name: input.Name,
Description: input.Description,
})
if err != nil {
return nil, types.AddRiskAssessmentScenarioOutput{}, fmt.Errorf("failed to create risk assessment scenario: %w", err)
}
return nil, types.AddRiskAssessmentScenarioOutput{
RiskAssessmentScenario: types.NewRiskAssessmentScenario(s),
}, nil
}
func (r *Resolver) UpdateRiskAssessmentScenarioTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentScenarioInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentScenarioOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScenarioUpdate)
if err != nil {
return nil, types.UpdateRiskAssessmentScenarioOutput{}, err
}
s, err := r.riskManagement.UpdateScenario(ctx, scope, riskmanagement.UpdateRiskAssessmentScenarioRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
})
if err != nil {
return nil, types.UpdateRiskAssessmentScenarioOutput{}, fmt.Errorf("failed to update risk assessment scenario: %w", err)
}
return nil, types.UpdateRiskAssessmentScenarioOutput{
RiskAssessmentScenario: types.NewRiskAssessmentScenario(s),
}, nil
}
func (r *Resolver) DeleteRiskAssessmentScenarioTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentScenarioInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentScenarioOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScenarioDelete)
if err != nil {
return nil, types.DeleteRiskAssessmentScenarioOutput{}, err
}
if err := r.riskManagement.DeleteScenario(ctx, scope, input.ID); err != nil {
return nil, types.DeleteRiskAssessmentScenarioOutput{}, fmt.Errorf("failed to delete risk assessment scenario: %w", err)
}
return nil, types.DeleteRiskAssessmentScenarioOutput{
DeletedRiskAssessmentScenarioID: input.ID,
}, nil
}
func (r *Resolver) LinkRiskAssessmentScenarioThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkRiskAssessmentScenarioThreatInput) (*mcp.CallToolResult, types.LinkRiskAssessmentScenarioThreatOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScenarioID, probo.ActionRiskAssessmentScenarioThreatLink)
if err != nil {
return nil, types.LinkRiskAssessmentScenarioThreatOutput{}, err
}
err = r.riskManagement.LinkScenarioThreat(ctx, scope, riskmanagement.LinkRiskAssessmentScenarioThreatRequest{
RiskAssessmentScenarioID: input.RiskAssessmentScenarioID,
ThreatID: input.ThreatID,
})
if err != nil {
return nil, types.LinkRiskAssessmentScenarioThreatOutput{}, fmt.Errorf("failed to link scenario threat: %w", err)
}
return nil, types.LinkRiskAssessmentScenarioThreatOutput{}, nil
}
func (r *Resolver) UnlinkRiskAssessmentScenarioThreatTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkRiskAssessmentScenarioThreatInput) (*mcp.CallToolResult, types.UnlinkRiskAssessmentScenarioThreatOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScenarioID, probo.ActionRiskAssessmentScenarioThreatUnlink)
if err != nil {
return nil, types.UnlinkRiskAssessmentScenarioThreatOutput{}, err
}
if err := r.riskManagement.UnlinkScenarioThreat(
ctx,
scope,
riskmanagement.UnlinkRiskAssessmentScenarioThreatRequest{
RiskAssessmentScenarioID: input.RiskAssessmentScenarioID,
ThreatID: input.ThreatID,
},
); err != nil {
return nil, types.UnlinkRiskAssessmentScenarioThreatOutput{}, fmt.Errorf("failed to unlink scenario threat: %w", err)
}
return nil, types.UnlinkRiskAssessmentScenarioThreatOutput{}, nil
}
func (r *Resolver) LinkRiskAssessmentScenarioRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkRiskAssessmentScenarioRiskInput) (*mcp.CallToolResult, types.LinkRiskAssessmentScenarioRiskOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScenarioID, probo.ActionRiskAssessmentScenarioRiskLink)
if err != nil {
return nil, types.LinkRiskAssessmentScenarioRiskOutput{}, err
}
if err := r.riskManagement.LinkScenarioRisk(
ctx,
scope,
riskmanagement.LinkRiskAssessmentScenarioRiskRequest{
RiskAssessmentScenarioID: input.RiskAssessmentScenarioID,
RiskID: input.RiskID,
},
); err != nil {
return nil, types.LinkRiskAssessmentScenarioRiskOutput{}, fmt.Errorf("failed to link scenario risk: %w", err)
}
return nil, types.LinkRiskAssessmentScenarioRiskOutput{}, nil
}
func (r *Resolver) UnlinkRiskAssessmentScenarioRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkRiskAssessmentScenarioRiskInput) (*mcp.CallToolResult, types.UnlinkRiskAssessmentScenarioRiskOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScenarioID, probo.ActionRiskAssessmentScenarioRiskUnlink)
if err != nil {
return nil, types.UnlinkRiskAssessmentScenarioRiskOutput{}, err
}
if err := r.riskManagement.UnlinkScenarioRisk(
ctx,
scope,
riskmanagement.UnlinkRiskAssessmentScenarioRiskRequest{
RiskAssessmentScenarioID: input.RiskAssessmentScenarioID,
RiskID: input.RiskID,
},
); err != nil {
return nil, types.UnlinkRiskAssessmentScenarioRiskOutput{}, fmt.Errorf("failed to unlink scenario risk: %w", err)
}
return nil, types.UnlinkRiskAssessmentScenarioRiskOutput{}, nil
}
func (r *Resolver) GetRiskAssessmentScopeMermaidChartTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentScopeMermaidChartInput) (*mcp.CallToolResult, types.GetRiskAssessmentScopeMermaidChartOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentScopeGet)
if err != nil {
return nil, types.GetRiskAssessmentScopeMermaidChartOutput{}, err
}
chart, err := r.riskManagement.BuildScopeMermaidChart(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskAssessmentScopeMermaidChartOutput{}, fmt.Errorf("failed to build mermaid chart: %w", err)
}
return nil, types.GetRiskAssessmentScopeMermaidChartOutput{
MermaidChart: chart,
}, nil
}
func (r *Resolver) ListRiskAssessmentBoundariesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskAssessmentBoundariesInput) (*mcp.CallToolResult, types.ListRiskAssessmentBoundariesOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentBoundaryList)
if err != nil {
return nil, types.ListRiskAssessmentBoundariesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.RiskAssessmentBoundaryOrderField]{
Field: coredata.RiskAssessmentBoundaryOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskAssessmentBoundaryOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.riskManagement.ListBoundariesForScopeID(ctx, scope, input.RiskAssessmentScopeID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list risk assessment boundaries: %w", err))
}
return nil, types.NewListRiskAssessmentBoundariesOutput(p), nil
}
func (r *Resolver) GetRiskAssessmentBoundaryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskAssessmentBoundaryInput) (*mcp.CallToolResult, types.GetRiskAssessmentBoundaryOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentBoundaryGet)
if err != nil {
return nil, types.GetRiskAssessmentBoundaryOutput{}, err
}
b, err := r.riskManagement.GetBoundary(ctx, scope, input.ID)
if err != nil {
return nil, types.GetRiskAssessmentBoundaryOutput{}, fmt.Errorf("failed to get risk assessment boundary: %w", err)
}
return nil, types.GetRiskAssessmentBoundaryOutput{
RiskAssessmentBoundary: types.NewRiskAssessmentBoundary(b),
}, nil
}
func (r *Resolver) AddRiskAssessmentBoundaryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskAssessmentBoundaryInput) (*mcp.CallToolResult, types.AddRiskAssessmentBoundaryOutput, error) {
scope, err := r.Authorize(ctx, input.RiskAssessmentScopeID, probo.ActionRiskAssessmentBoundaryCreate)
if err != nil {
return nil, types.AddRiskAssessmentBoundaryOutput{}, err
}
b, err := r.riskManagement.CreateBoundary(ctx, scope, riskmanagement.CreateRiskAssessmentBoundaryRequest{
RiskAssessmentScopeID: input.RiskAssessmentScopeID,
ParentBoundaryID: input.ParentBoundaryID,
Name: input.Name,
})
if err != nil {
return nil, types.AddRiskAssessmentBoundaryOutput{}, fmt.Errorf("failed to create risk assessment boundary: %w", err)
}
return nil, types.AddRiskAssessmentBoundaryOutput{
RiskAssessmentBoundary: types.NewRiskAssessmentBoundary(b),
}, nil
}
func (r *Resolver) UpdateRiskAssessmentBoundaryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateRiskAssessmentBoundaryInput) (*mcp.CallToolResult, types.UpdateRiskAssessmentBoundaryOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentBoundaryUpdate)
if err != nil {
return nil, types.UpdateRiskAssessmentBoundaryOutput{}, err
}
var parentBoundaryID **gid.GID
if input.ParentBoundaryID != nil {
parentBoundaryID = &input.ParentBoundaryID
}
b, err := r.riskManagement.UpdateBoundary(ctx, scope, riskmanagement.UpdateRiskAssessmentBoundaryRequest{
ID: input.ID,
ParentBoundaryID: parentBoundaryID,
Name: input.Name,
})
if err != nil {
return nil, types.UpdateRiskAssessmentBoundaryOutput{}, fmt.Errorf("failed to update risk assessment boundary: %w", err)
}
return nil, types.UpdateRiskAssessmentBoundaryOutput{
RiskAssessmentBoundary: types.NewRiskAssessmentBoundary(b),
}, nil
}
func (r *Resolver) DeleteRiskAssessmentBoundaryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteRiskAssessmentBoundaryInput) (*mcp.CallToolResult, types.DeleteRiskAssessmentBoundaryOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionRiskAssessmentBoundaryDelete)
if err != nil {
return nil, types.DeleteRiskAssessmentBoundaryOutput{}, err
}
if err := r.riskManagement.DeleteBoundary(ctx, scope, input.ID); err != nil {
return nil, types.DeleteRiskAssessmentBoundaryOutput{}, fmt.Errorf("failed to delete risk assessment boundary: %w", err)
}
return nil, types.DeleteRiskAssessmentBoundaryOutput{
DeletedRiskAssessmentBoundaryID: input.ID,
}, nil
}
func (r *Resolver) SetResourceAliasTool(ctx context.Context, req *mcp.CallToolRequest, input *types.SetResourceAliasInput) (*mcp.CallToolResult, types.SetResourceAliasOutput, error) {
scope, err := r.Authorize(ctx, input.ResourceID, resourcealias.ActionAliasSet)
if err != nil {
return nil, types.SetResourceAliasOutput{}, err
}
alias, err := r.resourceAlias.Create(
ctx,
scope,
resourcealias.CreateRequest{
ResourceID: input.ResourceID,
Alias: input.Alias,
},
)
if err != nil {
return nil, types.SetResourceAliasOutput{}, fmt.Errorf("cannot set resource alias: %w", err)
}
return nil, types.SetResourceAliasOutput{
ResourceAlias: types.NewResourceAlias(input.ResourceID, alias),
}, nil
}
func (r *Resolver) RemoveResourceAliasTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RemoveResourceAliasInput) (*mcp.CallToolResult, types.RemoveResourceAliasOutput, error) {
scope, err := r.Authorize(ctx, input.ResourceID, resourcealias.ActionAliasRemove)
if err != nil {
return nil, types.RemoveResourceAliasOutput{}, err
}
err = r.resourceAlias.Remove(ctx, scope, input.ResourceID)
if err != nil {
return nil, types.RemoveResourceAliasOutput{}, fmt.Errorf("cannot remove resource alias: %w", err)
}
return nil, types.RemoveResourceAliasOutput{
DeletedResourceID: input.ResourceID,
}, nil
}
// ListCommitmentGroupsTool handles the listCommitmentGroups tool
// List all commitment groups for a trust center
func (r *Resolver) ListCommitmentGroupsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCommitmentGroupsInput) (*mcp.CallToolResult, types.ListCommitmentGroupsOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, probo.ActionCompliancePortalCommitmentGroupList)
if err != nil {
return nil, types.ListCommitmentGroupsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]{
Field: coredata.CompliancePortalCommitmentGroupOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.CompliancePortalCommitmentGroupOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.CompliancePortalCommitmentGroups.ListForTrustCenterID(ctx, scope, input.TrustCenterID, cursor)
if err != nil {
return nil, types.ListCommitmentGroupsOutput{}, fmt.Errorf("cannot list commitment groups: %w", err)
}
return nil, types.NewListCommitmentGroupsOutput(p), nil
}
// AddCommitmentGroupTool handles the addCommitmentGroup tool
// Add a new commitment group to a trust center
func (r *Resolver) AddCommitmentGroupTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCommitmentGroupInput) (*mcp.CallToolResult, types.AddCommitmentGroupOutput, error) {
scope, err := r.Authorize(ctx, input.TrustCenterID, probo.ActionCompliancePortalCommitmentGroupCreate)
if err != nil {
return nil, types.AddCommitmentGroupOutput{}, err
}
prb := r.proboSvc
group, err := prb.CompliancePortalCommitmentGroups.Create(
ctx, scope,
&probo.CreateCompliancePortalCommitmentGroupRequest{
TrustCenterID: input.TrustCenterID,
Title: input.Title,
Description: input.Description,
},
)
if err != nil {
return nil, types.AddCommitmentGroupOutput{}, fmt.Errorf("cannot add commitment group: %w", err)
}
return nil, types.AddCommitmentGroupOutput{CommitmentGroup: types.NewCommitmentGroup(group)}, nil
}
// UpdateCommitmentGroupTool handles the updateCommitmentGroup tool
// Update an existing commitment group
func (r *Resolver) UpdateCommitmentGroupTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCommitmentGroupInput) (*mcp.CallToolResult, types.UpdateCommitmentGroupOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCompliancePortalCommitmentGroupUpdate)
if err != nil {
return nil, types.UpdateCommitmentGroupOutput{}, err
}
prb := r.proboSvc
updateReq := &probo.UpdateCompliancePortalCommitmentGroupRequest{
ID: input.ID,
}
if title := UnwrapOmittable(input.Title); title != nil {
updateReq.Title = *title
}
if description := UnwrapOmittable(input.Description); description != nil {
updateReq.Description = *description
}
if rank := UnwrapOmittable(input.Rank); rank != nil {
updateReq.Rank = *rank
}
group, err := prb.CompliancePortalCommitmentGroups.Update(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateCommitmentGroupOutput{}, fmt.Errorf("cannot update commitment group: %w", err)
}
return nil, types.UpdateCommitmentGroupOutput{CommitmentGroup: types.NewCommitmentGroup(group)}, nil
}
// DeleteCommitmentGroupTool handles the deleteCommitmentGroup tool
// Delete a commitment group
func (r *Resolver) DeleteCommitmentGroupTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCommitmentGroupInput) (*mcp.CallToolResult, types.DeleteCommitmentGroupOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCompliancePortalCommitmentGroupDelete)
if err != nil {
return nil, types.DeleteCommitmentGroupOutput{}, err
}
prb := r.proboSvc
err = prb.CompliancePortalCommitmentGroups.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteCommitmentGroupOutput{}, fmt.Errorf("cannot delete commitment group: %w", err)
}
return nil, types.DeleteCommitmentGroupOutput{DeletedCommitmentGroupID: input.ID}, nil
}
// ListCommitmentsTool handles the listCommitments tool
// List all commitments in a commitment group
func (r *Resolver) ListCommitmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCommitmentsInput) (*mcp.CallToolResult, types.ListCommitmentsOutput, error) {
scope, err := r.Authorize(ctx, input.GroupID, probo.ActionCompliancePortalCommitmentList)
if err != nil {
return nil, types.ListCommitmentsOutput{}, err
}
prb := r.proboSvc
pageOrderBy := page.OrderBy[coredata.CompliancePortalCommitmentOrderField]{
Field: coredata.CompliancePortalCommitmentOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.CompliancePortalCommitmentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.CompliancePortalCommitments.ListForGroupID(ctx, scope, input.GroupID, cursor)
if err != nil {
return nil, types.ListCommitmentsOutput{}, fmt.Errorf("cannot list commitments: %w", err)
}
return nil, types.NewListCommitmentsOutput(p), nil
}
// AddCommitmentTool handles the addCommitment tool
// Add a new commitment to a commitment group
func (r *Resolver) AddCommitmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCommitmentInput) (*mcp.CallToolResult, types.AddCommitmentOutput, error) {
scope, err := r.Authorize(ctx, input.GroupID, probo.ActionCompliancePortalCommitmentCreate)
if err != nil {
return nil, types.AddCommitmentOutput{}, err
}
prb := r.proboSvc
commitment, err := prb.CompliancePortalCommitments.Create(
ctx, scope,
&probo.CreateCompliancePortalCommitmentRequest{
GroupID: input.GroupID,
Icon: input.Icon,
Eyebrow: input.Eyebrow,
Title: input.Title,
Description: input.Description,
},
)
if err != nil {
return nil, types.AddCommitmentOutput{}, fmt.Errorf("cannot add commitment: %w", err)
}
return nil, types.AddCommitmentOutput{Commitment: types.NewCommitment(commitment)}, nil
}
// UpdateCommitmentTool handles the updateCommitment tool
// Update an existing commitment
func (r *Resolver) UpdateCommitmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCommitmentInput) (*mcp.CallToolResult, types.UpdateCommitmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCompliancePortalCommitmentUpdate)
if err != nil {
return nil, types.UpdateCommitmentOutput{}, err
}
prb := r.proboSvc
updateReq := &probo.UpdateCompliancePortalCommitmentRequest{
ID: input.ID,
}
if icon := UnwrapOmittable(input.Icon); icon != nil {
updateReq.Icon = *icon
}
if eyebrow := UnwrapOmittable(input.Eyebrow); eyebrow != nil {
updateReq.Eyebrow = *eyebrow
}
if title := UnwrapOmittable(input.Title); title != nil {
updateReq.Title = *title
}
if description := UnwrapOmittable(input.Description); description != nil {
updateReq.Description = *description
}
if rank := UnwrapOmittable(input.Rank); rank != nil {
updateReq.Rank = *rank
}
commitment, err := prb.CompliancePortalCommitments.Update(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateCommitmentOutput{}, fmt.Errorf("cannot update commitment: %w", err)
}
return nil, types.UpdateCommitmentOutput{Commitment: types.NewCommitment(commitment)}, nil
}
// DeleteCommitmentTool handles the deleteCommitment tool
// Delete a commitment
func (r *Resolver) DeleteCommitmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCommitmentInput) (*mcp.CallToolResult, types.DeleteCommitmentOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionCompliancePortalCommitmentDelete)
if err != nil {
return nil, types.DeleteCommitmentOutput{}, err
}
prb := r.proboSvc
err = prb.CompliancePortalCommitments.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteCommitmentOutput{}, fmt.Errorf("cannot delete commitment: %w", err)
}
return nil, types.DeleteCommitmentOutput{DeletedCommitmentID: input.ID}, nil
}