Files
probo/pkg/server/api/mcp/v1/schema.resolvers.go
Sacha Al Himdani 6a4f124adb
Some checks failed
github / Analyze (go) (push) Has been cancelled
github / Analyze (actions) (push) Has been cancelled
github / Analyze (javascript-typescript) (push) Has been cancelled
make / build-apps (push) Has been cancelled
make / probod binary (darwin/amd64) (push) Has been cancelled
make / probod binary (freebsd/amd64) (push) Has been cancelled
make / probod binary (linux/amd64) (push) Has been cancelled
make / probod binary (openbsd/amd64) (push) Has been cancelled
make / probod binary (windows/amd64) (push) Has been cancelled
make / probod binary (darwin/arm64) (push) Has been cancelled
make / probod binary (freebsd/arm64) (push) Has been cancelled
make / probod binary (linux/arm64) (push) Has been cancelled
make / probod binary (openbsd/arm64) (push) Has been cancelled
make / probo-agent (darwin/amd64) (push) Has been cancelled
make / probo-agent (freebsd/amd64) (push) Has been cancelled
make / probo-agent (linux/amd64) (push) Has been cancelled
make / probo-agent (windows/amd64) (push) Has been cancelled
make / probo-agent (darwin/arm64) (push) Has been cancelled
make / probo-agent (freebsd/arm64) (push) Has been cancelled
make / probo-agent (linux/arm64) (push) Has been cancelled
make / probo-agent (windows/arm64) (push) Has been cancelled
make / docker (amd64) (push) Has been cancelled
make / docker (arm64) (push) Has been cancelled
make / snapshot-scan (push) Has been cancelled
make / build-probod (push) Has been cancelled
make / build-probo-agent (push) Has been cancelled
make / lint-go (push) Has been cancelled
make / lint-js (push) Has been cancelled
make / lint-swift (push) Has been cancelled
make / lint-shell (push) Has been cancelled
make / test (push) Has been cancelled
make / test-e2e (push) Has been cancelled
trufflehog / scan (push) Has been cancelled
Replace third-party owners with administrators
Migrate business and security owners into a shared administrators list across GraphQL, MCP, CLI, n8n, and the console.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-31 16:48:36 +02:00

8153 lines
301 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/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/itam"
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/mailman"
"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)
level := input.Level
if level == nil {
level = new(1)
}
thirdPartyFilter := coredata.NewThirdPartyFilter(nil, 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))
}
thirdPartyIDs := make([]gid.GID, len(page.Data))
for i, tp := range page.Data {
thirdPartyIDs[i] = tp.ID
}
administratorIDsByThirdPartyID, err := prb.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, thirdPartyIDs)
if err != nil {
return nil, types.ListThirdPartiesOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
}
return nil, types.NewListThirdPartiesOutput(page, administratorIDsByThirdPartyID), 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,
AdministratorIDs: input.AdministratorIds,
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, input.AdministratorIds), 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 administratorIDs *[]gid.GID
if input.AdministratorIds != nil {
administratorIDs = &input.AdministratorIds
}
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,
AdministratorIDs: administratorIDs,
StatusPageURL: statusPageURL,
TermsOfServiceURL: termsOfServiceURL,
SecurityPageURL: securityPageURL,
TrustPageURL: trustPageURL,
},
)
if err != nil {
return nil, types.UpdateThirdPartyOutput{}, fmt.Errorf("failed to update thirdParty: %w", err)
}
administratorIDsByThirdPartyID, err := svc.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, []gid.GID{thirdParty.ID})
if err != nil {
return nil, types.UpdateThirdPartyOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
}
return nil, types.NewUpdateThirdPartyOutput(thirdParty, administratorIDsByThirdPartyID[thirdParty.ID]), 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,
AuditStartDate: input.AuditStartDate,
AuditEndDate: input.AuditEndDate,
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,
AuditStartDate: input.AuditStartDate,
AuditEndDate: input.AuditEndDate,
State: input.State,
CompliancePortalVisibility: input.CompliancePortalVisibility,
},
)
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 compliancePortalVisibility *coredata.CompliancePortalVisibility
if input.CompliancePortalVisibility != nil {
compliancePortalVisibility = input.CompliancePortalVisibility
}
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,
CompliancePortalVisibility: compliancePortalVisibility,
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,
CompliancePortalVisibility: input.CompliancePortalVisibility,
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
profileStates []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.ProfileStates != nil {
profileStates = input.Filter.ProfileStates
}
}
signatureFilter := coredata.NewDocumentVersionSignatureFilter(signatureStates, activeContract, profileStates)
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 len(input.Filter.States) > 0 {
filter.WithStates(input.Filter.States...)
}
if input.Filter.Query != nil {
filter.WithQuery(input.Filter.Query)
}
if input.Filter.Role != nil {
filter.WithRole(*input.Filter.Role)
}
if input.Filter.Kind != nil {
kind := string(*input.Filter.Kind)
filter.WithKind(&kind)
}
}
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) DeactivateUserTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeactivateUserInput) (*mcp.CallToolResult, types.DeactivateUserOutput, error) {
scope, err := r.Authorize(ctx, input.ProfileID, iam.ActionMembershipProfileDeactivate)
if err != nil {
return nil, types.DeactivateUserOutput{}, err
}
err = r.iamSvc.OrganizationService.DeactivateUser(ctx, scope, input.OrganizationID, input.ProfileID)
if err != nil {
if _, ok := errors.AsType[*iam.ErrUserManagedBySCIM](err); ok {
return nil, types.DeactivateUserOutput{}, fmt.Errorf("user is managed by SCIM and cannot be deactivated: %w", err)
}
if _, ok := errors.AsType[*iam.ErrLastActiveOwner](err); ok {
return nil, types.DeactivateUserOutput{}, fmt.Errorf("cannot deactivate last active owner: %w", err)
}
return nil, types.DeactivateUserOutput{}, fmt.Errorf("deactivate user: %w", err)
}
return nil, types.DeactivateUserOutput{DeactivatedUserID: 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)
}
r.accessReview.AutoSelectDefaultOrganization(ctx, scope, source)
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
}
connectorSet := false
if rawConnectorID := UnwrapOmittable(input.ConnectorID); rawConnectorID != nil {
connectorSet = true
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)
}
// A connector was just (re)linked: default its org so the source is
// usable right away. Matches the GraphQL surface; skipped on name/CSV-only
// updates to avoid a needless provider round-trip.
if connectorSet {
r.accessReview.AutoSelectDefaultOrganization(ctx, scope, source)
}
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
}
// GetCompliancePortalTool handles the getCompliancePortal tool
// Get the compliance portal for an organization
func (r *Resolver) GetCompliancePortalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCompliancePortalInput) (*mcp.CallToolResult, types.GetCompliancePortalOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, management.ActionCompliancePortalGet)
if err != nil {
return nil, types.GetCompliancePortalOutput{}, err
}
prb := r.management
compliancePortal, err := prb.GetByOrganizationID(ctx, scope, input.OrganizationID)
if err != nil {
return nil, types.GetCompliancePortalOutput{}, fmt.Errorf("cannot get compliance portal: %w", err)
}
tc := types.NewCompliancePortal(compliancePortal)
if compliancePortal.LogoFileID != nil {
logo, err := r.loadFile(ctx, scope, *compliancePortal.LogoFileID)
if err != nil {
return nil, types.GetCompliancePortalOutput{}, err
}
tc.Logo = logo
}
if compliancePortal.DarkLogoFileID != nil {
darkLogo, err := r.loadFile(ctx, scope, *compliancePortal.DarkLogoFileID)
if err != nil {
return nil, types.GetCompliancePortalOutput{}, err
}
tc.DarkLogo = darkLogo
}
if compliancePortal.NonDisclosureAgreementFileID != nil {
nda, err := r.loadFile(ctx, scope, *compliancePortal.NonDisclosureAgreementFileID)
if err != nil {
return nil, types.GetCompliancePortalOutput{}, err
}
tc.Nda = nda
}
return nil, types.GetCompliancePortalOutput{CompliancePortal: tc}, nil
}
// UpdateCompliancePortalTool handles the updateCompliancePortal tool
// Update the compliance portal settings
func (r *Resolver) UpdateCompliancePortalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCompliancePortalInput) (*mcp.CallToolResult, types.UpdateCompliancePortalOutput, error) {
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionCompliancePortalUpdate)
if err != nil {
return nil, types.UpdateCompliancePortalOutput{}, err
}
prb := r.management
updateReq := &management.UpdateRequest{
ID: input.CompliancePortalID,
}
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)
if entityName := UnwrapOmittable(input.EntityName); entityName != nil {
updateReq.EntityName = *entityName
}
compliancePortal, _, err := prb.Update(ctx, scope, updateReq)
if err != nil {
return nil, types.UpdateCompliancePortalOutput{}, fmt.Errorf("cannot update compliance portal: %w", err)
}
return nil, types.UpdateCompliancePortalOutput{CompliancePortal: types.NewCompliancePortal(compliancePortal)}, nil
}
// ListCompliancePortalReferencesTool handles the listCompliancePortalReferences tool
// List all references for a compliance portal
func (r *Resolver) ListCompliancePortalReferencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCompliancePortalReferencesInput) (*mcp.CallToolResult, types.ListCompliancePortalReferencesOutput, error) {
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionCompliancePortalReferenceList)
if err != nil {
return nil, types.ListCompliancePortalReferencesOutput{}, err
}
prb := r.management
pageOrderBy := page.OrderBy[coredata.CompliancePortalReferenceOrderField]{
Field: coredata.CompliancePortalReferenceOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.CompliancePortalReferenceOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.ListReferences(ctx, scope, input.CompliancePortalID, cursor)
if err != nil {
return nil, types.ListCompliancePortalReferencesOutput{}, fmt.Errorf("cannot list compliance portal references: %w", err)
}
refs := make([]*types.CompliancePortalReference, 0, len(p.Data))
for _, reference := range p.Data {
ref := types.NewCompliancePortalReference(reference)
logo, err := r.loadFile(ctx, scope, reference.LogoFileID)
if err != nil {
return nil, types.ListCompliancePortalReferencesOutput{}, err
}
ref.Logo = logo
refs = append(refs, ref)
}
return nil, types.NewListCompliancePortalReferencesOutput(refs, p), nil
}
// AddCompliancePortalReferenceTool handles the addCompliancePortalReference tool
// Add a new reference to the compliance portal
func (r *Resolver) AddCompliancePortalReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCompliancePortalReferenceInput) (*mcp.CallToolResult, types.AddCompliancePortalReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionCompliancePortalReferenceCreate)
if err != nil {
return nil, types.AddCompliancePortalReferenceOutput{}, err
}
prb := r.management
var websiteURL string
if input.WebsiteURL != nil {
websiteURL = *input.WebsiteURL
}
reference, err := prb.CreateReference(
ctx, scope,
&management.CreateReferenceRequest{
CompliancePortalID: input.CompliancePortalID,
Name: input.Name,
Description: input.Description,
WebsiteURL: websiteURL,
},
)
if err != nil {
return nil, types.AddCompliancePortalReferenceOutput{}, fmt.Errorf("cannot add compliance portal reference: %w", err)
}
return nil, types.AddCompliancePortalReferenceOutput{CompliancePortalReference: types.NewCompliancePortalReference(reference)}, nil
}
// UpdateCompliancePortalReferenceTool handles the updateCompliancePortalReference tool
// Update a compliance portal reference
func (r *Resolver) UpdateCompliancePortalReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCompliancePortalReferenceInput) (*mcp.CallToolResult, types.UpdateCompliancePortalReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalReferenceUpdate)
if err != nil {
return nil, types.UpdateCompliancePortalReferenceOutput{}, 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.UpdateCompliancePortalReferenceOutput{}, fmt.Errorf("cannot update compliance portal reference: %w", err)
}
return nil, types.UpdateCompliancePortalReferenceOutput{CompliancePortalReference: types.NewCompliancePortalReference(reference)}, nil
}
// DeleteCompliancePortalReferenceTool handles the deleteCompliancePortalReference tool
// Delete a compliance portal reference
func (r *Resolver) DeleteCompliancePortalReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCompliancePortalReferenceInput) (*mcp.CallToolResult, types.DeleteCompliancePortalReferenceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalReferenceDelete)
if err != nil {
return nil, types.DeleteCompliancePortalReferenceOutput{}, err
}
prb := r.management
err = prb.DeleteReference(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteCompliancePortalReferenceOutput{}, fmt.Errorf("cannot delete compliance portal reference: %w", err)
}
return nil, types.DeleteCompliancePortalReferenceOutput{DeletedCompliancePortalReferenceID: input.ID}, nil
}
// ListCompliancePortalFilesTool handles the listCompliancePortalFiles tool
// List all files for the compliance portal
func (r *Resolver) ListCompliancePortalFilesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCompliancePortalFilesInput) (*mcp.CallToolResult, types.ListCompliancePortalFilesOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, management.ActionCompliancePortalFileList)
if err != nil {
return nil, types.ListCompliancePortalFilesOutput{}, err
}
prb := r.management
pageOrderBy := page.OrderBy[coredata.CompliancePortalFileOrderField]{
Field: coredata.CompliancePortalFileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.CompliancePortalFileOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
filter := coredata.NewCompliancePortalFileFilter()
p, err := prb.ListFilesForOrganizationID(ctx, scope, input.OrganizationID, cursor, filter)
if err != nil {
return nil, types.ListCompliancePortalFilesOutput{}, fmt.Errorf("cannot list compliance portal files: %w", err)
}
files := make([]*types.CompliancePortalFile, 0, len(p.Data))
for _, f := range p.Data {
file, err := r.loadFile(ctx, scope, f.FileID)
if err != nil {
return nil, types.ListCompliancePortalFilesOutput{}, err
}
files = append(files, types.NewCompliancePortalFile(f, file))
}
return nil, types.NewListCompliancePortalFilesOutput(files, p), nil
}
// DeleteCompliancePortalFileTool handles the deleteCompliancePortalFile tool
// Delete a compliance portal file
func (r *Resolver) DeleteCompliancePortalFileTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCompliancePortalFileInput) (*mcp.CallToolResult, types.DeleteCompliancePortalFileOutput, error) {
scope, err := r.Authorize(ctx, input.ID, management.ActionCompliancePortalFileDelete)
if err != nil {
return nil, types.DeleteCompliancePortalFileOutput{}, err
}
prb := r.management
err = prb.DeleteFile(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteCompliancePortalFileOutput{}, fmt.Errorf("cannot delete compliance portal file: %w", err)
}
return nil, types.DeleteCompliancePortalFileOutput{DeletedCompliancePortalFileID: input.ID}, nil
}
// ListComplianceCustomLinksTool handles the listComplianceCustomLinks tool
// List all custom links for a compliance portal
func (r *Resolver) ListComplianceCustomLinksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListComplianceCustomLinksInput) (*mcp.CallToolResult, types.ListComplianceCustomLinksOutput, error) {
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.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.CompliancePortalID, 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 compliance portal
func (r *Resolver) AddComplianceCustomLinkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddComplianceCustomLinkInput) (*mcp.CallToolResult, types.AddComplianceCustomLinkOutput, error) {
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionComplianceCustomLinkCreate)
if err != nil {
return nil, types.AddComplianceCustomLinkOutput{}, err
}
prb := r.management
item, err := prb.CreateCustomLink(
ctx, scope,
&management.CreateCustomLinkRequest{
CompliancePortalID: input.CompliancePortalID,
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, management.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, management.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.CompliancePortalID, management.ActionCustomDomainCreate)
if err != nil {
return nil, types.CreateCustomDomainOutput{}, err
}
domain, err := r.management.AddCustomDomain(
ctx, scope,
input.CompliancePortalID,
input.Domain,
)
if err != nil {
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot create custom domain: %w", err)
}
var cert *coredata.Certificate
if domain.CertificateID != nil {
cert, err = r.certManager.Get(ctx, scope, *domain.CertificateID)
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.CompliancePortalID, management.ActionCustomDomainDelete)
if err != nil {
return nil, types.DeleteCustomDomainOutput{}, err
}
compliancePage, err := r.management.Get(ctx, scope, input.CompliancePortalID)
if err != nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot load compliance page: %w", err)
}
if compliancePage.CustomDomainID == nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("compliance page has no custom domain")
}
domain, err := r.management.GetDomain(ctx, scope, *compliancePage.CustomDomainID)
if err != nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot get custom domain: %w", err)
}
var cert *coredata.Certificate
if domain.CertificateID != nil {
cert, err = r.certManager.Get(ctx, scope, *domain.CertificateID)
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")
}
administratorIDsByThirdPartyID, err := r.proboSvc.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, []gid.GID{thirdParty.ID})
if err != nil {
return nil, types.VetThirdPartyOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
}
return nil, types.VetThirdPartyOutput{
ThirdParty: types.NewThirdParty(thirdParty, administratorIDsByThirdPartyID[thirdParty.ID]),
}, 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))
}
thirdPartyIDs := make([]gid.GID, len(page.Data))
for i, tp := range page.Data {
thirdPartyIDs[i] = tp.ID
}
administratorIDsByThirdPartyID, err := r.proboSvc.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, thirdPartyIDs)
if err != nil {
return nil, types.ListChildThirdPartiesOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
}
return nil, types.NewListChildThirdPartiesOutput(page, administratorIDsByThirdPartyID), 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, management.ActionCompliancePortalCommitmentGroupList)
if err != nil {
return nil, types.ListCommitmentGroupsOutput{}, err
}
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 := r.management.ListCommitmentGroups(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, management.ActionCompliancePortalCommitmentGroupCreate)
if err != nil {
return nil, types.AddCommitmentGroupOutput{}, err
}
group, err := r.management.CreateCommitmentGroup(
ctx, scope,
&management.CreateCompliancePortalCommitmentGroupRequest{
CompliancePortalID: 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, management.ActionCompliancePortalCommitmentGroupUpdate)
if err != nil {
return nil, types.UpdateCommitmentGroupOutput{}, err
}
updateReq := &management.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 := r.management.UpdateCommitmentGroup(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, management.ActionCompliancePortalCommitmentGroupDelete)
if err != nil {
return nil, types.DeleteCommitmentGroupOutput{}, err
}
err = r.management.DeleteCommitmentGroup(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, management.ActionCompliancePortalCommitmentList)
if err != nil {
return nil, types.ListCommitmentsOutput{}, err
}
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 := r.management.ListCommitments(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, management.ActionCompliancePortalCommitmentCreate)
if err != nil {
return nil, types.AddCommitmentOutput{}, err
}
commitment, err := r.management.CreateCommitment(
ctx, scope,
&management.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, management.ActionCompliancePortalCommitmentUpdate)
if err != nil {
return nil, types.UpdateCommitmentOutput{}, err
}
updateReq := &management.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 := r.management.UpdateCommitment(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, management.ActionCompliancePortalCommitmentDelete)
if err != nil {
return nil, types.DeleteCommitmentOutput{}, err
}
err = r.management.DeleteCommitment(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
}
func (r *Resolver) RequestAuditLogExportTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RequestAuditLogExportInput) (*mcp.CallToolResult, types.RequestAuditLogExportOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, iam.ActionAuditLogExport)
if err != nil {
return nil, types.RequestAuditLogExportOutput{}, err
}
identity := authn.IdentityFromContext(ctx)
logExport, err := r.iamSvc.OrganizationService.RequestLogExport(
ctx,
scope,
iam.RequestLogExportRequest{
OrganizationID: input.OrganizationID,
Type: coredata.ExportJobTypeAuditLog,
FromTime: input.FromTime,
ToTime: input.ToTime,
RecipientEmail: identity.EmailAddress,
RecipientName: identity.FullName,
},
)
if err != nil {
if _, ok := errors.AsType[*iam.ErrInvalidLogExportTimeRange](err); ok {
return nil, types.RequestAuditLogExportOutput{}, err
}
return nil, types.RequestAuditLogExportOutput{}, fmt.Errorf("cannot request audit log export: %w", err)
}
return nil, types.RequestAuditLogExportOutput{
ExportJobID: logExport.ID,
}, nil
}
func (r *Resolver) RequestSCIMEventExportTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RequestSCIMEventExportInput) (*mcp.CallToolResult, types.RequestSCIMEventExportOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, iam.ActionSCIMEventExport)
if err != nil {
return nil, types.RequestSCIMEventExportOutput{}, err
}
identity := authn.IdentityFromContext(ctx)
logExport, err := r.iamSvc.OrganizationService.RequestLogExport(
ctx,
scope,
iam.RequestLogExportRequest{
OrganizationID: input.OrganizationID,
Type: coredata.ExportJobTypeSCIMEvent,
FromTime: input.FromTime,
ToTime: input.ToTime,
RecipientEmail: identity.EmailAddress,
RecipientName: identity.FullName,
},
)
if err != nil {
if _, ok := errors.AsType[*iam.ErrInvalidLogExportTimeRange](err); ok {
return nil, types.RequestSCIMEventExportOutput{}, err
}
return nil, types.RequestSCIMEventExportOutput{}, fmt.Errorf("cannot request SCIM event export: %w", err)
}
return nil, types.RequestSCIMEventExportOutput{
ExportJobID: logExport.ID,
}, nil
}
func (r *Resolver) ListDevicesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDevicesInput) (*mcp.CallToolResult, types.ListDevicesOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, itam.ActionDeviceList)
if err != nil {
return nil, types.ListDevicesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.DeviceOrderField]{
Field: coredata.DeviceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DeviceOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
size := input.Size
if size != nil && *size > maxDeviceListSize {
size = new(maxDeviceListSize)
}
cursor := types.NewCursor(size, input.Cursor, pageOrderBy)
devicePage, err := r.itamSvc.ListForOrganizationID(ctx, scope, input.OrganizationID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list devices", log.Error(err))
return nil, types.ListDevicesOutput{}, fmt.Errorf("internal server error")
}
includePostures := input.IncludePostures != nil && *input.IncludePostures
var postureScope *coredata.Scope
if includePostures && len(devicePage.Data) > 0 {
deviceIDs := make([]gid.GID, 0, len(devicePage.Data))
for _, d := range devicePage.Data {
deviceIDs = append(deviceIDs, d.ID)
}
postureScope, err = r.AuthorizeBatch(ctx, deviceIDs, itam.ActionDevicePostureList)
if err != nil {
return nil, types.ListDevicesOutput{}, err
}
}
posturesByDeviceID := make(map[gid.GID]coredata.DevicePostures, len(devicePage.Data))
for _, d := range devicePage.Data {
if postureScope == nil {
continue
}
postures, err := r.itamSvc.GetLatestPostures(ctx, postureScope, d.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot load latest device postures", log.Error(err))
return nil, types.ListDevicesOutput{}, fmt.Errorf("internal server error")
}
posturesByDeviceID[d.ID] = postures
}
return nil, types.NewListDevicesOutput(devicePage, posturesByDeviceID), nil
}
func (r *Resolver) GetDeviceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDeviceInput) (*mcp.CallToolResult, types.GetDeviceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, itam.ActionDeviceGet)
if err != nil {
return nil, types.GetDeviceOutput{}, err
}
device, err := r.itamSvc.GetDevice(ctx, scope, input.ID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, types.GetDeviceOutput{}, fmt.Errorf("resource not found")
}
r.logger.ErrorCtx(ctx, "cannot get device", log.Error(err))
return nil, types.GetDeviceOutput{}, fmt.Errorf("internal server error")
}
var postures coredata.DevicePostures
if input.IncludePostures != nil && *input.IncludePostures {
postureScope, err := r.Authorize(ctx, input.ID, itam.ActionDevicePostureList)
if err != nil {
return nil, types.GetDeviceOutput{}, err
}
postures, err = r.itamSvc.GetLatestPostures(ctx, postureScope, device.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot load latest device postures", log.Error(err))
return nil, types.GetDeviceOutput{}, fmt.Errorf("internal server error")
}
}
return nil, types.GetDeviceOutput{
Device: types.NewDevice(device, postures),
}, nil
}
func (r *Resolver) RevokeDeviceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RevokeDeviceInput) (*mcp.CallToolResult, types.RevokeDeviceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, itam.ActionDeviceRevoke)
if err != nil {
return nil, types.RevokeDeviceOutput{}, err
}
device, err := r.itamSvc.RevokeDevice(ctx, scope, input.ID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, types.RevokeDeviceOutput{}, fmt.Errorf("resource not found")
}
r.logger.ErrorCtx(ctx, "cannot revoke device", log.Error(err))
return nil, types.RevokeDeviceOutput{}, fmt.Errorf("internal server error")
}
return nil, types.RevokeDeviceOutput{
Device: types.NewDevice(device, nil),
}, nil
}
func (r *Resolver) DeleteDeviceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDeviceInput) (*mcp.CallToolResult, types.DeleteDeviceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, itam.ActionDeviceDelete)
if err != nil {
return nil, types.DeleteDeviceOutput{}, err
}
device, err := r.itamSvc.DeleteDevice(ctx, scope, input.ID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, types.DeleteDeviceOutput{}, fmt.Errorf("resource not found")
}
if errors.Is(err, itam.ErrDeviceNotDeletable) {
return nil, types.DeleteDeviceOutput{}, fmt.Errorf("device cannot be deleted")
}
r.logger.ErrorCtx(ctx, "cannot delete device", log.Error(err))
return nil, types.DeleteDeviceOutput{}, fmt.Errorf("internal server error")
}
return nil, types.DeleteDeviceOutput{
DeletedDeviceID: device.ID,
}, nil
}
func (r *Resolver) SetDeviceOwnerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.SetDeviceOwnerInput) (*mcp.CallToolResult, types.SetDeviceOwnerOutput, error) {
scope, err := r.Authorize(ctx, input.ID, itam.ActionDeviceAssignOwner)
if err != nil {
return nil, types.SetDeviceOwnerOutput{}, err
}
device, err := r.itamSvc.SetDeviceOwner(ctx, scope, input.ID, input.OwnerID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, types.SetDeviceOwnerOutput{}, fmt.Errorf("resource not found")
}
if errors.Is(err, itam.ErrInvalidOwnerProfile) {
return nil, types.SetDeviceOwnerOutput{}, fmt.Errorf("owner_id must reference a membership profile of the device organization")
}
r.logger.ErrorCtx(ctx, "cannot set device owner", log.Error(err))
return nil, types.SetDeviceOwnerOutput{}, fmt.Errorf("internal server error")
}
return nil, types.SetDeviceOwnerOutput{
Device: types.NewDevice(device, nil),
}, nil
}
func (r *Resolver) CreateDeviceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateDeviceInput) (*mcp.CallToolResult, types.CreateDeviceOutput, error) {
scope, err := r.Authorize(ctx, input.OrganizationID, itam.ActionDeviceCreate)
if err != nil {
return nil, types.CreateDeviceOutput{}, err
}
result, err := r.itamSvc.CreateDevice(
ctx,
scope,
itam.CreateDeviceRequest{
OrganizationID: input.OrganizationID,
OwnerID: input.OwnerID,
},
)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, types.CreateDeviceOutput{}, fmt.Errorf("resource not found")
}
if errors.Is(err, itam.ErrInvalidOwnerProfile) {
return nil, types.CreateDeviceOutput{}, fmt.Errorf("owner_id must reference a membership profile of the device organization")
}
r.logger.ErrorCtx(ctx, "cannot create device", log.Error(err))
return nil, types.CreateDeviceOutput{}, fmt.Errorf("internal server error")
}
urls, err := itam.BuildEnrollmentURLs(r.baseURL, result.EnrollmentToken)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot build enrollment URLs", log.Error(err))
return nil, types.CreateDeviceOutput{}, fmt.Errorf("internal server error")
}
return nil, types.CreateDeviceOutput{
Device: types.NewDevice(result.Device, nil),
EnrollmentToken: result.EnrollmentToken,
ServerURL: urls.ServerURL,
EnrollmentURL: urls.EnrollmentURL,
}, nil
}
func (r *Resolver) GetThirdPartyTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetThirdPartyInput) (*mcp.CallToolResult, types.GetThirdPartyOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyGet)
if err != nil {
return nil, types.GetThirdPartyOutput{}, err
}
thirdParty, err := r.proboSvc.ThirdParties.Get(ctx, scope, input.ID)
if err != nil {
return nil, types.GetThirdPartyOutput{}, fmt.Errorf("cannot get third party: %w", err)
}
administratorIDsByThirdPartyID, err := r.proboSvc.ThirdParties.MapAdministratorIDsForThirdPartyIDs(ctx, scope, []gid.GID{thirdParty.ID})
if err != nil {
return nil, types.GetThirdPartyOutput{}, fmt.Errorf("cannot load third party administrators: %w", err)
}
return nil, types.GetThirdPartyOutput{
ThirdParty: types.NewThirdParty(thirdParty, administratorIDsByThirdPartyID[thirdParty.ID]),
}, nil
}
func (r *Resolver) DeleteEvidenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteEvidenceInput) (*mcp.CallToolResult, types.DeleteEvidenceOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionEvidenceDelete)
if err != nil {
return nil, types.DeleteEvidenceOutput{}, err
}
err = r.proboSvc.Evidences.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteEvidenceOutput{}, fmt.Errorf("cannot delete evidence: %w", err)
}
return nil, types.DeleteEvidenceOutput{
DeletedEvidenceID: input.ID,
}, nil
}
func (r *Resolver) DeleteFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteFrameworkInput) (*mcp.CallToolResult, types.DeleteFrameworkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionFrameworkDelete)
if err != nil {
return nil, types.DeleteFrameworkOutput{}, err
}
err = r.proboSvc.Frameworks.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteFrameworkOutput{}, fmt.Errorf("cannot delete framework: %w", err)
}
return nil, types.DeleteFrameworkOutput{
DeletedFrameworkID: input.ID,
}, nil
}
func (r *Resolver) DeleteAuditReportTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAuditReportInput) (*mcp.CallToolResult, types.DeleteAuditReportOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionAuditReportDelete)
if err != nil {
return nil, types.DeleteAuditReportOutput{}, err
}
audit, err := r.proboSvc.Audits.DeleteReport(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteAuditReportOutput{}, fmt.Errorf("cannot delete audit report: %w", err)
}
return nil, types.DeleteAuditReportOutput{
Audit: types.NewAudit(audit, nil),
}, nil
}
func (r *Resolver) DeleteControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteControlInput) (*mcp.CallToolResult, types.DeleteControlOutput, error) {
scope, err := r.Authorize(ctx, input.ID, probo.ActionControlDelete)
if err != nil {
return nil, types.DeleteControlOutput{}, err
}
err = r.proboSvc.Controls.Delete(ctx, scope, input.ID)
if err != nil {
return nil, types.DeleteControlOutput{}, fmt.Errorf("cannot delete control: %w", err)
}
return nil, types.DeleteControlOutput{
DeletedControlID: input.ID,
}, nil
}
func (r *Resolver) ApproveDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ApproveDocumentVersionInput) (*mcp.CallToolResult, types.ApproveDocumentVersionOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionApprove)
if err != nil {
return nil, types.ApproveDocumentVersionOutput{}, err
}
identity := authn.IdentityFromContext(ctx)
signer := signerMetadataFromToolRequest(req)
decision, err := r.proboSvc.DocumentApprovals.Approve(
ctx,
scope,
probo.ApproveDocumentVersionRequest{
DocumentVersionID: input.DocumentVersionID,
IdentityID: identity.ID,
Comment: input.Comment,
SignerFullName: identity.FullName,
SignerEmail: identity.EmailAddress,
SignerIPAddr: signer.IPAddr,
SignerUA: signer.UA,
},
)
if err != nil {
return nil, types.ApproveDocumentVersionOutput{}, fmt.Errorf("cannot approve document version: %w", err)
}
return nil, types.ApproveDocumentVersionOutput{
DocumentVersionApprovalDecision: types.NewDocumentVersionApprovalDecision(decision),
}, nil
}
func (r *Resolver) RejectDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RejectDocumentVersionInput) (*mcp.CallToolResult, types.RejectDocumentVersionOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionReject)
if err != nil {
return nil, types.RejectDocumentVersionOutput{}, err
}
identity := authn.IdentityFromContext(ctx)
decision, err := r.proboSvc.DocumentApprovals.Reject(
ctx,
scope,
probo.RejectDocumentVersionRequest{
DocumentVersionID: input.DocumentVersionID,
IdentityID: identity.ID,
Comment: input.Comment,
},
)
if err != nil {
return nil, types.RejectDocumentVersionOutput{}, fmt.Errorf("cannot reject document version: %w", err)
}
return nil, types.RejectDocumentVersionOutput{
DocumentVersionApprovalDecision: types.NewDocumentVersionApprovalDecision(decision),
}, nil
}
func (r *Resolver) SignDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.SignDocumentInput) (*mcp.CallToolResult, types.SignDocumentOutput, error) {
scope, err := r.Authorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSign)
if err != nil {
return nil, types.SignDocumentOutput{}, err
}
identity := authn.IdentityFromContext(ctx)
signer := signerMetadataFromToolRequest(req)
signature, err := r.proboSvc.Documents.SignDocumentVersionByIdentity(
ctx,
scope,
probo.SignDocumentVersionRequest{
DocumentVersionID: input.DocumentVersionID,
IdentityID: identity.ID,
SignerFullName: identity.FullName,
SignerEmail: identity.EmailAddress,
SignerIPAddr: signer.IPAddr,
SignerUA: signer.UA,
},
)
if err != nil {
return nil, types.SignDocumentOutput{}, fmt.Errorf("cannot sign document: %w", err)
}
return nil, types.SignDocumentOutput{
DocumentVersionSignature: types.NewDocumentVersionSignature(signature),
}, nil
}
func (r *Resolver) GetMailingListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetMailingListInput) (*mcp.CallToolResult, types.GetMailingListOutput, error) {
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionMailingListSubscriberList)
if err != nil {
return nil, types.GetMailingListOutput{}, err
}
mailingList, err := r.management.GetMailingList(ctx, scope, input.CompliancePortalID)
if err != nil {
return nil, types.GetMailingListOutput{}, fmt.Errorf("cannot get mailing list: %w", err)
}
return nil, types.GetMailingListOutput{MailingList: types.NewMailingList(mailingList)}, nil
}
func (r *Resolver) UpdateMailingListTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMailingListInput) (*mcp.CallToolResult, types.UpdateMailingListOutput, error) {
if _, err := r.Authorize(ctx, input.ID, management.ActionMailingListUpdate); err != nil {
return nil, types.UpdateMailingListOutput{}, err
}
mailingList, err := r.mailman.UpdateMailingList(ctx, input.ID, input.ReplyTo)
if err != nil {
return nil, types.UpdateMailingListOutput{}, fmt.Errorf("cannot update mailing list: %w", err)
}
return nil, types.UpdateMailingListOutput{MailingList: types.NewMailingList(mailingList)}, nil
}
func (r *Resolver) ListMailingListSubscribersTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMailingListSubscribersInput) (*mcp.CallToolResult, types.ListMailingListSubscribersOutput, error) {
if _, err := r.Authorize(ctx, input.MailingListID, management.ActionMailingListSubscriberList); err != nil {
return nil, types.ListMailingListSubscribersOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.MailingListSubscriberOrderField]{
Field: coredata.MailingListSubscriberOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.MailingListSubscriberOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.mailman.ListSubscribers(ctx, input.MailingListID, cursor)
if err != nil {
return nil, types.ListMailingListSubscribersOutput{}, fmt.Errorf("cannot list mailing list subscribers: %w", err)
}
return nil, types.NewListMailingListSubscribersOutput(p), nil
}
func (r *Resolver) AddMailingListSubscriberTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddMailingListSubscriberInput) (*mcp.CallToolResult, types.AddMailingListSubscriberOutput, error) {
if _, err := r.Authorize(ctx, input.MailingListID, management.ActionMailingListSubscriberCreate); err != nil {
return nil, types.AddMailingListSubscriberOutput{}, err
}
subscriber, err := r.mailman.CreateSubscriber(
ctx,
&mailman.CreateSubscriberRequest{
MailingListID: input.MailingListID,
Email: input.Email,
FullName: input.FullName,
Confirmed: input.Confirmed != nil && *input.Confirmed,
},
)
if err != nil {
return nil, types.AddMailingListSubscriberOutput{}, fmt.Errorf("cannot add mailing list subscriber: %w", err)
}
return nil, types.AddMailingListSubscriberOutput{
MailingListSubscriber: types.NewMailingListSubscriber(subscriber),
}, nil
}
func (r *Resolver) DeleteMailingListSubscriberTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteMailingListSubscriberInput) (*mcp.CallToolResult, types.DeleteMailingListSubscriberOutput, error) {
if _, err := r.Authorize(ctx, input.ID, management.ActionMailingListSubscriberDelete); err != nil {
return nil, types.DeleteMailingListSubscriberOutput{}, err
}
if err := r.mailman.DeleteSubscriber(ctx, input.ID); err != nil {
return nil, types.DeleteMailingListSubscriberOutput{}, fmt.Errorf("cannot delete mailing list subscriber: %w", err)
}
return nil, types.DeleteMailingListSubscriberOutput{
DeletedMailingListSubscriberID: input.ID,
}, nil
}
func (r *Resolver) ListMailingListUpdatesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMailingListUpdatesInput) (*mcp.CallToolResult, types.ListMailingListUpdatesOutput, error) {
if _, err := r.Authorize(ctx, input.MailingListID, management.ActionMailingListUpdateList); err != nil {
return nil, types.ListMailingListUpdatesOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.MailingListUpdateOrderField]{
Field: coredata.MailingListUpdateOrderFieldUpdatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.MailingListUpdateOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.mailman.ListMailingListUpdates(ctx, input.MailingListID, cursor)
if err != nil {
return nil, types.ListMailingListUpdatesOutput{}, fmt.Errorf("cannot list mailing list updates: %w", err)
}
return nil, types.NewListMailingListUpdatesOutput(p), nil
}
func (r *Resolver) AddMailingListUpdateTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddMailingListUpdateInput) (*mcp.CallToolResult, types.AddMailingListUpdateOutput, error) {
if _, err := r.Authorize(ctx, input.MailingListID, management.ActionMailingListUpdateCreate); err != nil {
return nil, types.AddMailingListUpdateOutput{}, err
}
update, err := r.mailman.CreateMailingListUpdate(
ctx,
&mailman.CreateMailingListUpdateRequest{
MailingListID: input.MailingListID,
Title: input.Title,
Body: input.Body,
},
)
if err != nil {
return nil, types.AddMailingListUpdateOutput{}, fmt.Errorf("cannot add mailing list update: %w", err)
}
return nil, types.AddMailingListUpdateOutput{
MailingListUpdate: types.NewMailingListUpdate(update),
}, nil
}
func (r *Resolver) UpdateMailingListUpdateTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateMailingListUpdateInput) (*mcp.CallToolResult, types.UpdateMailingListUpdateOutput, error) {
if _, err := r.Authorize(ctx, input.ID, management.ActionMailingListUpdateUpdate); err != nil {
return nil, types.UpdateMailingListUpdateOutput{}, err
}
update, err := r.mailman.UpdateMailingListUpdate(
ctx,
&mailman.UpdateMailingListUpdateRequest{
ID: input.ID,
Title: input.Title,
Body: input.Body,
},
)
if err != nil {
return nil, types.UpdateMailingListUpdateOutput{}, fmt.Errorf("cannot update mailing list update: %w", err)
}
return nil, types.UpdateMailingListUpdateOutput{
MailingListUpdate: types.NewMailingListUpdate(update),
}, nil
}
func (r *Resolver) SendMailingListUpdateTool(ctx context.Context, req *mcp.CallToolRequest, input *types.SendMailingListUpdateInput) (*mcp.CallToolResult, types.SendMailingListUpdateOutput, error) {
if _, err := r.Authorize(ctx, input.ID, management.ActionMailingListUpdateUpdate); err != nil {
return nil, types.SendMailingListUpdateOutput{}, err
}
update, err := r.mailman.SendMailingListUpdate(ctx, input.ID)
if err != nil {
return nil, types.SendMailingListUpdateOutput{}, fmt.Errorf("cannot send mailing list update: %w", err)
}
return nil, types.SendMailingListUpdateOutput{
MailingListUpdate: types.NewMailingListUpdate(update),
}, nil
}
func (r *Resolver) DeleteMailingListUpdateTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteMailingListUpdateInput) (*mcp.CallToolResult, types.DeleteMailingListUpdateOutput, error) {
if _, err := r.Authorize(ctx, input.ID, management.ActionMailingListUpdateDelete); err != nil {
return nil, types.DeleteMailingListUpdateOutput{}, err
}
if err := r.mailman.DeleteMailingListUpdate(ctx, input.ID); err != nil {
return nil, types.DeleteMailingListUpdateOutput{}, fmt.Errorf("cannot delete mailing list update: %w", err)
}
return nil, types.DeleteMailingListUpdateOutput{
DeletedMailingListUpdateID: input.ID,
}, nil
}
func (r *Resolver) ListDetectedTrackersTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDetectedTrackersInput) (*mcp.CallToolResult, types.ListDetectedTrackersOutput, error) {
scope, err := r.Authorize(ctx, input.TrackerPatternID, probo.ActionTrackerPatternGet)
if err != nil {
return nil, types.ListDetectedTrackersOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.DetectedTrackerOrderField]{
Field: coredata.DetectedTrackerOrderFieldLastDetectedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.DetectedTrackerOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
trackers, err := r.cookieBanner.ListDetectedTrackersForPattern(ctx, scope, input.TrackerPatternID, cursor)
if err != nil {
return nil, types.ListDetectedTrackersOutput{}, fmt.Errorf("cannot list detected trackers: %w", err)
}
return nil, types.NewListDetectedTrackersOutput(page.NewPage(trackers, cursor)), nil
}
func (r *Resolver) ListCompliancePortalFrameworksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCompliancePortalFrameworksInput) (*mcp.CallToolResult, types.ListCompliancePortalFrameworksOutput, error) {
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionComplianceFrameworkList)
if err != nil {
return nil, types.ListCompliancePortalFrameworksOutput{}, err
}
pageOrderBy := page.OrderBy[coredata.ComplianceFrameworkOrderField]{
Field: coredata.ComplianceFrameworkOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ComplianceFrameworkOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.management.ListFrameworksWithHidden(ctx, scope, input.CompliancePortalID, cursor)
if err != nil {
return nil, types.ListCompliancePortalFrameworksOutput{}, fmt.Errorf("cannot list compliance portal frameworks: %w", err)
}
return nil, types.NewListCompliancePortalFrameworksOutput(p), nil
}
func (r *Resolver) AddCompliancePortalFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCompliancePortalFrameworkInput) (*mcp.CallToolResult, types.AddCompliancePortalFrameworkOutput, error) {
scope, err := r.Authorize(ctx, input.CompliancePortalID, management.ActionComplianceFrameworkCreate)
if err != nil {
return nil, types.AddCompliancePortalFrameworkOutput{}, err
}
framework, err := r.management.CreateFramework(
ctx,
scope,
&management.CreateFrameworkRequest{
CompliancePortalID: input.CompliancePortalID,
FrameworkID: input.FrameworkID,
},
)
if err != nil {
return nil, types.AddCompliancePortalFrameworkOutput{}, fmt.Errorf("cannot add compliance portal framework: %w", err)
}
return nil, types.AddCompliancePortalFrameworkOutput{
CompliancePortalFramework: types.NewCompliancePortalFramework(framework),
}, nil
}
func (r *Resolver) UpdateCompliancePortalFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCompliancePortalFrameworkInput) (*mcp.CallToolResult, types.UpdateCompliancePortalFrameworkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, management.ActionComplianceFrameworkUpdateRank)
if err != nil {
return nil, types.UpdateCompliancePortalFrameworkOutput{}, err
}
framework, err := r.management.UpdateFramework(
ctx,
scope,
&management.UpdateFrameworkRequest{
ID: input.ID,
Rank: input.Rank,
},
)
if err != nil {
return nil, types.UpdateCompliancePortalFrameworkOutput{}, fmt.Errorf("cannot update compliance portal framework: %w", err)
}
return nil, types.UpdateCompliancePortalFrameworkOutput{
CompliancePortalFramework: types.NewCompliancePortalFramework(framework),
}, nil
}
func (r *Resolver) DeleteCompliancePortalFrameworkTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCompliancePortalFrameworkInput) (*mcp.CallToolResult, types.DeleteCompliancePortalFrameworkOutput, error) {
scope, err := r.Authorize(ctx, input.ID, management.ActionComplianceFrameworkDelete)
if err != nil {
return nil, types.DeleteCompliancePortalFrameworkOutput{}, err
}
err = r.management.DeleteFramework(
ctx,
scope,
&management.DeleteFrameworkRequest{ID: input.ID},
)
if err != nil {
return nil, types.DeleteCompliancePortalFrameworkOutput{}, fmt.Errorf("cannot delete compliance portal framework: %w", err)
}
return nil, types.DeleteCompliancePortalFrameworkOutput{
DeletedCompliancePortalFrameworkID: input.ID,
}, nil
}