Files
probo/pkg/server/api/mcp/v1/schema.resolvers.go
Aurélien Sibiril 509d0c88b1 Add vendor assessment agent
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-24 08:43:14 +02:00

4786 lines
180 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"
"errors"
"fmt"
"time"
"github.com/modelcontextprotocol/go-sdk/mcp"
"go.probo.inc/probo/pkg/accessreview"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/mcp/v1/types"
)
// 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
}
// ListVendorsTool handles the listVendors tool
// List all vendors for the organization
func (r *Resolver) ListVendorsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListVendorsInput) (*mcp.CallToolResult, types.ListVendorsOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionVendorList)
prb := r.ProboService(ctx, input.OrganizationID)
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
Field: coredata.VendorOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
noSnapshot := (*gid.GID)(nil)
vendorFilter := coredata.NewVendorFilter(&noSnapshot, nil)
if input.Filter != nil {
vendorFilter = coredata.NewVendorFilter(&input.Filter.SnapshotID, nil)
}
page, err := prb.Vendors.ListForOrganizationID(ctx, input.OrganizationID, cursor, vendorFilter)
if err != nil {
panic(fmt.Errorf("cannot list organization vendors: %w", err))
}
return nil, types.NewListVendorsOutput(page), nil
}
// AddVendorTool handles the addVendor tool
// Add a new vendor to the organization
func (r *Resolver) AddVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddVendorInput) (*mcp.CallToolResult, types.AddVendorOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionVendorCreate)
svc := r.ProboService(ctx, input.OrganizationID)
var category *coredata.VendorCategory
if input.Category != nil {
cat := coredata.VendorCategory(*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)
}
}
vendor, err := svc.Vendors.Create(
ctx,
probo.CreateVendorRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Category: category,
HeadquarterAddress: input.HeadquarterAddress,
LegalName: input.LegalName,
WebsiteURL: input.WebsiteURL,
PrivacyPolicyURL: input.PrivacyPolicyURL,
ServiceLevelAgreementURL: input.ServiceLevelAgreementURL,
DataProcessingAgreementURL: input.DataProcessingAgreementURL,
BusinessAssociateAgreementURL: input.BusinessAssociateAgreementURL,
SubprocessorsListURL: input.SubprocessorsListURL,
Certifications: input.Certifications,
Countries: countries,
BusinessOwnerID: input.BusinessOwnerID,
SecurityOwnerID: input.SecurityOwnerID,
StatusPageURL: input.StatusPageURL,
TermsOfServiceURL: input.TermsOfServiceURL,
SecurityPageURL: input.SecurityPageURL,
TrustPageURL: input.TrustPageURL,
},
)
if err != nil {
return nil, types.AddVendorOutput{}, fmt.Errorf("failed to create vendor: %w", err)
}
return nil, types.NewAddVendorOutput(vendor), nil
}
// UpdateVendorTool handles the updateVendor tool
// Update an existing vendor
func (r *Resolver) UpdateVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateVendorInput) (*mcp.CallToolResult, types.UpdateVendorOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionVendorUpdate)
svc := r.ProboService(ctx, input.ID)
var description **string
if input.Description != nil {
description = &input.Description
}
var headquarterAddress **string
if input.HeadquarterAddress != nil {
headquarterAddress = &input.HeadquarterAddress
}
var legalName **string
if input.LegalName != nil {
legalName = &input.LegalName
}
var websiteURL **string
if input.WebsiteURL != nil {
websiteURL = &input.WebsiteURL
}
var privacyPolicyURL **string
if input.PrivacyPolicyURL != nil {
privacyPolicyURL = &input.PrivacyPolicyURL
}
var serviceLevelAgreementURL **string
if input.ServiceLevelAgreementURL != nil {
serviceLevelAgreementURL = &input.ServiceLevelAgreementURL
}
var dataProcessingAgreementURL **string
if input.DataProcessingAgreementURL != nil {
dataProcessingAgreementURL = &input.DataProcessingAgreementURL
}
var businessAssociateAgreementURL **string
if input.BusinessAssociateAgreementURL != nil {
businessAssociateAgreementURL = &input.BusinessAssociateAgreementURL
}
var subprocessorsListURL **string
if input.SubprocessorsListURL != nil {
subprocessorsListURL = &input.SubprocessorsListURL
}
var statusPageURL **string
if input.StatusPageURL != nil {
statusPageURL = &input.StatusPageURL
}
var termsOfServiceURL **string
if input.TermsOfServiceURL != nil {
termsOfServiceURL = &input.TermsOfServiceURL
}
var securityPageURL **string
if input.SecurityPageURL != nil {
securityPageURL = &input.SecurityPageURL
}
var trustPageURL **string
if input.TrustPageURL != nil {
trustPageURL = &input.TrustPageURL
}
var businessOwnerID **gid.GID
if input.BusinessOwnerID != nil {
businessOwnerID = &input.BusinessOwnerID
}
var securityOwnerID **gid.GID
if input.SecurityOwnerID != nil {
securityOwnerID = &input.SecurityOwnerID
}
var category *coredata.VendorCategory
if input.Category != nil {
cat := coredata.VendorCategory(*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)
}
}
vendor, err := svc.Vendors.Update(
ctx,
probo.UpdateVendorRequest{
ID: input.ID,
Name: input.Name,
Description: description,
Category: category,
HeadquarterAddress: headquarterAddress,
LegalName: legalName,
WebsiteURL: websiteURL,
PrivacyPolicyURL: privacyPolicyURL,
ServiceLevelAgreementURL: serviceLevelAgreementURL,
DataProcessingAgreementURL: dataProcessingAgreementURL,
BusinessAssociateAgreementURL: businessAssociateAgreementURL,
SubprocessorsListURL: subprocessorsListURL,
Certifications: input.Certifications,
Countries: countries,
BusinessOwnerID: businessOwnerID,
SecurityOwnerID: securityOwnerID,
StatusPageURL: statusPageURL,
TermsOfServiceURL: termsOfServiceURL,
SecurityPageURL: securityPageURL,
TrustPageURL: trustPageURL,
},
)
if err != nil {
return nil, types.UpdateVendorOutput{}, fmt.Errorf("failed to update vendor: %w", err)
}
return nil, types.NewUpdateVendorOutput(vendor), nil
}
func (r *Resolver) ListRisksTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRisksInput) (*mcp.CallToolResult, types.ListRisksOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionRiskList)
prb := r.ProboService(ctx, input.OrganizationID)
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)
noSnapshot := (*gid.GID)(nil)
riskFilter := coredata.NewRiskFilter(nil, &noSnapshot)
if input.Filter != nil {
riskFilter = coredata.NewRiskFilter(input.Filter.Query, &input.Filter.SnapshotID)
}
page, err := prb.Risks.ListForOrganizationID(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionRiskGet)
prb := r.ProboService(ctx, input.ID)
risk, err := prb.Risks.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionRiskCreate)
svc := r.ProboService(ctx, input.OrganizationID)
risk, err := svc.Risks.Create(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionRiskUpdate)
svc := r.ProboService(ctx, input.ID)
risk, err := svc.Risks.Update(
ctx,
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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionMeasureList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionMeasureGet)
prb := r.ProboService(ctx, input.ID)
measure, err := prb.Measures.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionMeasureCreate)
svc := r.ProboService(ctx, input.OrganizationID)
measure, err := svc.Measures.Create(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionMeasureUpdate)
svc := r.ProboService(ctx, input.ID)
measure, err := svc.Measures.Update(
ctx,
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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFrameworkList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionFrameworkGet)
prb := r.ProboService(ctx, input.ID)
framework, err := prb.Frameworks.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFrameworkCreate)
svc := r.ProboService(ctx, input.OrganizationID)
framework, err := svc.Frameworks.Create(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionFrameworkUpdate)
svc := r.ProboService(ctx, input.ID)
framework, err := svc.Frameworks.Update(
ctx,
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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAssetList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionAssetGet)
prb := r.ProboService(ctx, input.ID)
asset, err := prb.Assets.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAssetCreate)
svc := r.ProboService(ctx, input.OrganizationID)
asset, err := svc.Assets.Create(
ctx,
probo.CreateAssetRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Amount: input.Amount,
OwnerID: input.OwnerID,
AssetType: input.AssetType,
DataTypesStored: input.DataTypesStored,
VendorIDs: input.VendorIds,
},
)
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionAssetUpdate)
svc := r.ProboService(ctx, input.ID)
asset, err := svc.Assets.Update(
ctx,
probo.UpdateAssetRequest{
ID: input.ID,
Name: input.Name,
Amount: input.Amount,
OwnerID: input.OwnerID,
AssetType: input.AssetType,
DataTypesStored: input.DataTypesStored,
VendorIDs: input.VendorIds,
},
)
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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDatumList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDatumGet)
prb := r.ProboService(ctx, input.ID)
datum, err := prb.Data.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDatumCreate)
svc := r.ProboService(ctx, input.OrganizationID)
datum, err := svc.Data.Create(
ctx,
probo.CreateDatumRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
DataClassification: input.DataClassification,
OwnerID: input.OwnerID,
VendorIDs: input.VendorIds,
},
)
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDatumUpdate)
svc := r.ProboService(ctx, input.ID)
datum, err := svc.Data.Update(
ctx,
probo.UpdateDatumRequest{
ID: input.ID,
Name: input.Name,
DataClassification: input.DataClassification,
OwnerID: input.OwnerID,
VendorIDs: input.VendorIds,
},
)
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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFindingList)
prb := r.ProboService(ctx, input.OrganizationID)
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)
noSnapshot := (*gid.GID)(nil)
findingFilter := coredata.NewFindingFilter(&noSnapshot, nil, nil, nil, nil)
if input.Filter != nil {
findingFilter = coredata.NewFindingFilter(
&input.Filter.SnapshotID,
input.Filter.Kind,
input.Filter.Status,
input.Filter.Priority,
input.Filter.OwnerID,
)
}
page, err := prb.Findings.ListForOrganizationID(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionFindingGet)
prb := r.ProboService(ctx, input.ID)
finding, err := prb.Findings.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionFindingCreate)
svc := r.ProboService(ctx, input.OrganizationID)
finding, err := svc.Findings.Create(
ctx,
&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) {
r.MustAuthorize(ctx, input.ID, probo.ActionFindingUpdate)
svc := r.ProboService(ctx, input.ID)
finding, err := svc.Findings.Update(
ctx,
&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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionObligationList)
prb := r.ProboService(ctx, input.OrganizationID)
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)
noSnapshot := (*gid.GID)(nil)
obligationFilter := coredata.NewObligationFilter(&noSnapshot)
if input.Filter != nil {
obligationFilter = coredata.NewObligationFilter(&input.Filter.SnapshotID)
}
page, err := prb.Obligations.ListForOrganizationID(ctx, input.OrganizationID, cursor, obligationFilter)
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionObligationGet)
prb := r.ProboService(ctx, input.ID)
obligation, err := prb.Obligations.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionObligationCreate)
svc := r.ProboService(ctx, input.OrganizationID)
obligation, err := svc.Obligations.Create(
ctx,
&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) {
r.MustAuthorize(ctx, input.ID, probo.ActionObligationUpdate)
svc := r.ProboService(ctx, input.ID)
obligation, err := svc.Obligations.Update(
ctx,
&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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionProcessingActivityList)
prb := r.ProboService(ctx, input.OrganizationID)
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)
noSnapshot := (*gid.GID)(nil)
filter := coredata.NewProcessingActivityFilter(&noSnapshot)
if input.Filter != nil {
filter = coredata.NewProcessingActivityFilter(&input.Filter.SnapshotID)
}
page, err := prb.ProcessingActivities.ListForOrganizationID(ctx, input.OrganizationID, cursor, filter)
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionProcessingActivityGet)
prb := r.ProboService(ctx, input.ID)
processingActivity, err := prb.ProcessingActivities.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionProcessingActivityCreate)
svc := r.ProboService(ctx, input.OrganizationID)
processingActivity, err := svc.ProcessingActivities.Create(
ctx,
&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,
VendorIDs: input.VendorIds,
},
)
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionProcessingActivityUpdate)
svc := r.ProboService(ctx, input.ID)
var vendorIDs *[]gid.GID
if input.VendorIds != nil {
vendorIDs = &input.VendorIds
}
processingActivity, err := svc.ProcessingActivities.Update(
ctx,
&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),
VendorIDs: vendorIDs,
},
)
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionProcessingActivityDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.ProcessingActivities.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDataProtectionImpactAssessmentList)
prb := r.ProboService(ctx, input.OrganizationID)
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)
noSnapshot := (*gid.GID)(nil)
filter := coredata.NewDataProtectionImpactAssessmentFilter(&noSnapshot)
if input.Filter != nil {
filter = coredata.NewDataProtectionImpactAssessmentFilter(&input.Filter.SnapshotID)
}
page, err := prb.DataProtectionImpactAssessments.ListForOrganizationID(ctx, input.OrganizationID, cursor, filter)
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentGet)
prb := r.ProboService(ctx, input.ID)
dpia, err := prb.DataProtectionImpactAssessments.Get(ctx, 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) {
r.MustAuthorize(ctx, input.ProcessingActivityID, probo.ActionDataProtectionImpactAssessmentCreate)
svc := r.ProboService(ctx, input.ProcessingActivityID)
dpia, err := svc.DataProtectionImpactAssessments.Create(
ctx,
&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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentUpdate)
svc := r.ProboService(ctx, input.ID)
dpia, err := svc.DataProtectionImpactAssessments.Update(
ctx,
&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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTransferImpactAssessmentList)
prb := r.ProboService(ctx, input.OrganizationID)
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)
noSnapshot := (*gid.GID)(nil)
filter := coredata.NewTransferImpactAssessmentFilter(&noSnapshot)
if input.Filter != nil {
filter = coredata.NewTransferImpactAssessmentFilter(&input.Filter.SnapshotID)
}
page, err := prb.TransferImpactAssessments.ListForOrganizationID(ctx, input.OrganizationID, cursor, filter)
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionTransferImpactAssessmentGet)
prb := r.ProboService(ctx, input.ID)
tia, err := prb.TransferImpactAssessments.Get(ctx, 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) {
r.MustAuthorize(ctx, input.ProcessingActivityID, probo.ActionTransferImpactAssessmentCreate)
svc := r.ProboService(ctx, input.ProcessingActivityID)
tia, err := svc.TransferImpactAssessments.Create(
ctx,
&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) {
r.MustAuthorize(ctx, input.ID, probo.ActionTransferImpactAssessmentUpdate)
svc := r.ProboService(ctx, input.ID)
tia, err := svc.TransferImpactAssessments.Update(
ctx,
&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) {
r.MustAuthorize(ctx, input.ID, probo.ActionTransferImpactAssessmentDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.TransferImpactAssessments.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAuditList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionAuditGet)
prb := r.ProboService(ctx, input.ID)
audit, err := prb.Audits.Get(ctx, input.ID)
if err != nil {
return nil, types.GetAuditOutput{}, fmt.Errorf("cannot get audit: %w", err)
}
var report *coredata.Report
if audit.ReportID != nil {
report, err = prb.Reports.Get(ctx, *audit.ReportID)
if err != nil {
return nil, types.GetAuditOutput{}, fmt.Errorf("cannot get audit report: %w", err)
}
}
return nil, types.GetAuditOutput{
Audit: types.NewAudit(audit, report),
}, nil
}
func (r *Resolver) AddAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAuditInput) (*mcp.CallToolResult, types.AddAuditOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAuditCreate)
svc := r.ProboService(ctx, input.OrganizationID)
audit, err := svc.Audits.Create(
ctx,
&probo.CreateAuditRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
ValidFrom: input.ValidFrom,
ValidUntil: input.ValidUntil,
State: input.State,
FrameworkID: input.FrameworkID,
},
)
if err != nil {
return nil, types.AddAuditOutput{}, fmt.Errorf("failed to create audit: %w", err)
}
return nil, types.AddAuditOutput{
Audit: types.NewAudit(audit, nil),
}, nil
}
func (r *Resolver) UpdateAuditTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAuditInput) (*mcp.CallToolResult, types.UpdateAuditOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionAuditUpdate)
svc := r.ProboService(ctx, input.ID)
audit, err := svc.Audits.Update(
ctx,
&probo.UpdateAuditRequest{
ID: input.ID,
Name: UnwrapOmittable(input.Name),
ValidFrom: input.ValidFrom,
ValidUntil: input.ValidUntil,
State: input.State,
TrustCenterVisibility: input.TrustCenterVisibility,
},
)
if err != nil {
return nil, types.UpdateAuditOutput{}, fmt.Errorf("cannot update audit: %w", err)
}
var report *coredata.Report
if audit.ReportID != nil {
report, err = svc.Reports.Get(ctx, *audit.ReportID)
if err != nil {
return nil, types.UpdateAuditOutput{}, fmt.Errorf("cannot get audit report: %w", err)
}
}
return nil, types.UpdateAuditOutput{
Audit: types.NewAudit(audit, report),
}, nil
}
func (r *Resolver) ListControlsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlsInput) (*mcp.CallToolResult, types.ListControlsOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionControlList)
prb := r.ProboService(ctx, input.OrganizationID)
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]
var err error
if input.Filter != nil && input.Filter.FrameworkID != nil {
controlPage, err = prb.Controls.ListForFrameworkID(ctx, *input.Filter.FrameworkID, cursor, controlFilter)
} else {
controlPage, err = prb.Controls.ListForOrganizationID(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionControlGet)
prb := r.ProboService(ctx, input.ID)
control, err := prb.Controls.Get(ctx, 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) {
r.MustAuthorize(ctx, input.FrameworkID, probo.ActionControlCreate)
svc := r.ProboService(ctx, input.FrameworkID)
control, err := svc.Controls.Create(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionControlUpdate)
svc := r.ProboService(ctx, input.ID)
var maturityLevel *coredata.ControlMaturityLevel
if input.MaturityLevel != nil {
v := coredata.ControlMaturityLevel(*input.MaturityLevel)
maturityLevel = &v
}
control, err := svc.Controls.Update(
ctx,
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.ProboService(ctx, input.ControlID)
switch input.ResourceID.EntityType() {
case coredata.MeasureEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlMeasureMappingCreate)
if _, _, err := svc.Controls.CreateMeasureMapping(ctx, input.ControlID, input.ResourceID); err != nil {
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to measure: %w", err)
}
case coredata.DocumentEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlDocumentMappingCreate)
if _, _, err := svc.Controls.CreateDocumentMapping(ctx, input.ControlID, input.ResourceID); err != nil {
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to document: %w", err)
}
case coredata.AuditEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlAuditMappingCreate)
if _, _, err := svc.Controls.CreateAuditMapping(ctx, input.ControlID, input.ResourceID); err != nil {
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to audit: %w", err)
}
case coredata.SnapshotEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlSnapshotMappingCreate)
if _, _, err := svc.Controls.CreateSnapshotMapping(ctx, input.ControlID, input.ResourceID); err != nil {
return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to snapshot: %w", err)
}
case coredata.ObligationEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlObligationMappingCreate)
if _, _, err := svc.Controls.CreateObligationMapping(ctx, 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.ProboService(ctx, input.ControlID)
switch input.ResourceID.EntityType() {
case coredata.MeasureEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlMeasureMappingDelete)
if _, _, err := svc.Controls.DeleteMeasureMapping(ctx, input.ControlID, input.ResourceID); err != nil {
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from measure: %w", err)
}
case coredata.DocumentEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlDocumentMappingDelete)
if _, _, err := svc.Controls.DeleteDocumentMapping(ctx, input.ControlID, input.ResourceID); err != nil {
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from document: %w", err)
}
case coredata.AuditEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlAuditMappingDelete)
if _, _, err := svc.Controls.DeleteAuditMapping(ctx, input.ControlID, input.ResourceID); err != nil {
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from audit: %w", err)
}
case coredata.SnapshotEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlSnapshotMappingDelete)
if _, _, err := svc.Controls.DeleteSnapshotMapping(ctx, input.ControlID, input.ResourceID); err != nil {
return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from snapshot: %w", err)
}
case coredata.ObligationEntityType:
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlObligationMappingDelete)
if _, _, err := svc.Controls.DeleteObligationMapping(ctx, 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) {
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
prb := r.ProboService(ctx, input.ControlID)
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, input.ControlID, cursor, coredata.NewObligationFilter(nil))
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) {
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
prb := r.ProboService(ctx, input.ControlID)
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, 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) {
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
prb := r.ProboService(ctx, input.ControlID)
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, 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) {
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
prb := r.ProboService(ctx, input.ControlID)
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, 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) ListControlSnapshotsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListControlSnapshotsInput) (*mcp.CallToolResult, types.ListControlSnapshotsOutput, error) {
r.MustAuthorize(ctx, input.ControlID, probo.ActionControlGet)
prb := r.ProboService(ctx, input.ControlID)
pageOrderBy := page.OrderBy[coredata.SnapshotOrderField]{
Field: coredata.SnapshotOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.SnapshotOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
snapshotPage, err := prb.Snapshots.ListForControlID(ctx, input.ControlID, cursor)
if err != nil {
return nil, types.ListControlSnapshotsOutput{}, fmt.Errorf("failed to list control snapshots: %w", err)
}
return nil, types.NewListControlSnapshotsOutput(snapshotPage), nil
}
func (r *Resolver) ListRiskObligationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListRiskObligationsInput) (*mcp.CallToolResult, types.ListRiskObligationsOutput, error) {
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskGet)
prb := r.ProboService(ctx, input.RiskID)
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, input.RiskID, cursor, coredata.NewObligationFilter(nil))
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.ProboService(ctx, input.RiskID)
switch input.ResourceID.EntityType() {
case coredata.DocumentEntityType:
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingCreate)
if _, _, err := svc.Risks.CreateDocumentMapping(ctx, input.RiskID, input.ResourceID); err != nil {
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to document: %w", err)
}
case coredata.MeasureEntityType:
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingCreate)
if _, _, err := svc.Risks.CreateMeasureMapping(ctx, input.RiskID, input.ResourceID); err != nil {
return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to measure: %w", err)
}
case coredata.ObligationEntityType:
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskObligationMappingCreate)
if _, _, err := svc.Risks.CreateObligationMapping(ctx, 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.ProboService(ctx, input.RiskID)
switch input.ResourceID.EntityType() {
case coredata.DocumentEntityType:
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingDelete)
if _, _, err := svc.Risks.DeleteDocumentMapping(ctx, input.RiskID, input.ResourceID); err != nil {
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from document: %w", err)
}
case coredata.MeasureEntityType:
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingDelete)
if _, _, err := svc.Risks.DeleteMeasureMapping(ctx, input.RiskID, input.ResourceID); err != nil {
return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from measure: %w", err)
}
case coredata.ObligationEntityType:
r.MustAuthorize(ctx, input.RiskID, probo.ActionRiskObligationMappingDelete)
if _, _, err := svc.Risks.DeleteObligationMapping(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTaskList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionTaskGet)
prb := r.ProboService(ctx, input.ID)
task, err := prb.Tasks.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTaskCreate)
svc := r.ProboService(ctx, input.OrganizationID)
priority := coredata.TaskPriorityMedium
if input.Priority != nil {
priority = *input.Priority
}
task, err := svc.Tasks.Create(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionTaskUpdate)
svc := r.ProboService(ctx, input.ID)
task, err := svc.Tasks.Update(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionTaskAssign)
svc := r.ProboService(ctx, input.ID)
task, err := svc.Tasks.Assign(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionTaskUnassign)
svc := r.ProboService(ctx, input.ID)
task, err := svc.Tasks.Unassign(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionTaskDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Tasks.Delete(ctx, 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) ListSnapshotsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListSnapshotsInput) (*mcp.CallToolResult, types.ListSnapshotsOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionSnapshotList)
prb := r.ProboService(ctx, input.OrganizationID)
pageOrderBy := page.OrderBy[coredata.SnapshotOrderField]{
Field: coredata.SnapshotOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.SnapshotOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
page, err := prb.Snapshots.ListForOrganizationID(ctx, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization snapshots: %w", err))
}
return nil, types.NewListSnapshotsOutput(page), nil
}
func (r *Resolver) GetSnapshotTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetSnapshotInput) (*mcp.CallToolResult, types.GetSnapshotOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionSnapshotGet)
prb := r.ProboService(ctx, input.ID)
snapshot, err := prb.Snapshots.Get(ctx, input.ID)
if err != nil {
return nil, types.GetSnapshotOutput{}, fmt.Errorf("failed to get snapshot: %w", err)
}
return nil, types.GetSnapshotOutput{
Snapshot: types.NewSnapshot(snapshot),
}, nil
}
func (r *Resolver) TakeSnapshotTool(ctx context.Context, req *mcp.CallToolRequest, input *types.TakeSnapshotInput) (*mcp.CallToolResult, types.TakeSnapshotOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionSnapshotCreate)
prb := r.ProboService(ctx, input.OrganizationID)
snapshot, err := prb.Snapshots.Create(
ctx,
&probo.CreateSnapshotRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
Type: input.Type,
},
)
if err != nil {
return nil, types.TakeSnapshotOutput{}, fmt.Errorf("failed to take snapshot: %w", err)
}
return nil, types.TakeSnapshotOutput{
Snapshot: types.NewSnapshot(snapshot),
}, nil
}
func (r *Resolver) ListDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentsInput) (*mcp.CallToolResult, types.ListDocumentsOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDocumentList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentGet)
prb := r.ProboService(ctx, input.ID)
document, err := prb.Documents.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDocumentCreate)
svc := r.ProboService(ctx, input.OrganizationID)
var trustCenterVisibility *coredata.TrustCenterVisibility
if input.TrustCenterVisibility != nil {
trustCenterVisibility = input.TrustCenterVisibility
}
contentJSON, err := markdownToProseMirrorJSON(input.Content)
if err != nil {
panic(fmt.Errorf("cannot convert markdown to prosemirror: %w", err))
}
document, documentVersion, err := svc.Documents.Create(
ctx,
probo.CreateDocumentRequest{
OrganizationID: input.OrganizationID,
Title: input.Title,
Content: contentJSON,
Classification: input.Classification,
DocumentType: input.DocumentType,
TrustCenterVisibility: trustCenterVisibility,
DefaultApproverIDs: input.DefaultApproverIds,
},
)
if err != nil {
panic(fmt.Errorf("cannot create document: %w", err))
}
return nil, types.NewAddDocumentOutput(document, documentVersion), nil
}
func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateDocumentInput) (*mcp.CallToolResult, types.UpdateDocumentOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentUpdate)
svc := r.ProboService(ctx, input.ID)
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,
probo.UpdateDocumentRequest{
DocumentID: input.ID,
Title: input.Title,
Content: content,
Classification: input.Classification,
DocumentType: input.DocumentType,
TrustCenterVisibility: input.TrustCenterVisibility,
DefaultApproverIDs: defaultApproverIDs,
},
)
if err != nil {
panic(fmt.Errorf("cannot update document: %w", err))
}
output := types.UpdateDocumentOutput{
Document: types.NewDocument(document),
}
if documentVersion != nil {
output.DocumentVersion = types.NewDocumentVersion(documentVersion)
}
return nil, output, nil
}
func (r *Resolver) ListDocumentVersionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionsInput) (*mcp.CallToolResult, types.ListDocumentVersionsOutput, error) {
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentVersionList)
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.ProboService(ctx, input.DocumentID)
versionFilter := coredata.NewDocumentVersionFilter()
if input.Filter != nil && len(input.Filter.Statuses) > 0 {
versionFilter = versionFilter.WithStatuses(input.Filter.Statuses...)
}
versionPage, err := svc.Documents.ListVersions(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionGet)
svc := r.ProboService(ctx, input.ID)
version, err := svc.Documents.GetVersion(ctx, 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) {
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSignatureList)
prb := r.ProboService(ctx, input.DocumentVersionID)
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
var activeContract *bool
if input.Filter != nil {
if input.Filter.States != nil {
signatureStates = input.Filter.States
}
if input.Filter.ActiveContract != nil {
activeContract = input.Filter.ActiveContract
}
}
signatureFilter := coredata.NewDocumentVersionSignatureFilter(signatureStates, activeContract)
page, err := prb.Documents.ListSignatures(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionSignatureGet)
prb := r.ProboService(ctx, input.ID)
signature, err := prb.Documents.GetVersionSignature(ctx, 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) {
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionSignatureRequest)
svc := r.ProboService(ctx, input.DocumentVersionID)
documentVersionSignature, err := svc.Documents.RequestSignature(
ctx,
probo.RequestSignatureRequest{
DocumentVersionID: input.DocumentVersionID,
Signatory: input.SignatoryID,
},
)
if err != nil {
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) {
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentDelete)
svc := r.ProboService(ctx, input.DocumentID)
err := svc.Documents.SoftDelete(ctx, 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) {
r.MustAuthorize(ctx, input.DocumentVersionSignatureID, probo.ActionDocumentVersionCancelSignature)
svc := r.ProboService(ctx, input.DocumentVersionSignatureID)
err := svc.Documents.CancelSignatureRequest(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionRiskDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Risks.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionMeasureDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Measures.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
prb := r.ProboService(ctx, input.MeasureID)
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, input.MeasureID, cursor, coredata.NewRiskFilter(nil, 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) {
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
prb := r.ProboService(ctx, input.MeasureID)
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, 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) {
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
prb := r.ProboService(ctx, input.MeasureID)
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, 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) {
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
prb := r.ProboService(ctx, input.MeasureID)
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, 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.ProboService(ctx, input.MeasureID)
switch input.ResourceID.EntityType() {
case coredata.ControlEntityType:
r.MustAuthorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingCreate)
if _, _, err := svc.Controls.CreateMeasureMapping(ctx, input.ResourceID, input.MeasureID); err != nil {
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to control: %w", err)
}
case coredata.RiskEntityType:
r.MustAuthorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingCreate)
if _, _, err := svc.Risks.CreateMeasureMapping(ctx, input.ResourceID, input.MeasureID); err != nil {
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to risk: %w", err)
}
case coredata.DocumentEntityType:
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingCreate)
if _, _, err := svc.Measures.CreateDocumentMapping(ctx, input.MeasureID, input.ResourceID); err != nil {
return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to document: %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.ProboService(ctx, input.MeasureID)
switch input.ResourceID.EntityType() {
case coredata.ControlEntityType:
r.MustAuthorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingDelete)
if _, _, err := svc.Controls.DeleteMeasureMapping(ctx, input.ResourceID, input.MeasureID); err != nil {
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from control: %w", err)
}
case coredata.RiskEntityType:
r.MustAuthorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingDelete)
if _, _, err := svc.Risks.DeleteMeasureMapping(ctx, input.ResourceID, input.MeasureID); err != nil {
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from risk: %w", err)
}
case coredata.DocumentEntityType:
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingDelete)
if _, _, err := svc.Measures.DeleteDocumentMapping(ctx, input.MeasureID, input.ResourceID); err != nil {
return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from document: %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) {
r.MustAuthorize(ctx, input.OrganizationID, iam.ActionMembershipProfileList)
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.ExcludeContractEnded).WithMembership()
}
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 {
var errNotFound *iam.ErrProfileNotFound
if errors.As(err, &errNotFound) {
return nil, types.GetUserOutput{}, fmt.Errorf("user not found: %w", err)
}
return nil, types.GetUserOutput{}, fmt.Errorf("get user: %w", err)
}
r.MustAuthorize(ctx, profile.OrganizationID, iam.ActionMembershipProfileGet)
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) {
r.MustAuthorize(ctx, input.OrganizationID, iam.ActionMembershipProfileCreate)
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, &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 {
var errAlreadyExists *iam.ErrUserAlreadyExists
if errors.As(err, &errAlreadyExists) {
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) {
r.MustAuthorize(ctx, input.ProfileID, iam.ActionInvitationCreate)
invitation, err := r.iamSvc.OrganizationService.InviteUser(ctx, &iam.CreateInvitationRequest{
OrganizationID: input.OrganizationID,
ProfileID: input.ProfileID,
})
if err != nil {
var errOrgNotFound *iam.ErrOrganizationNotFound
var errUserExists *iam.ErrUserAlreadyExists
if errors.As(err, &errOrgNotFound) {
return nil, types.InviteUserOutput{}, fmt.Errorf("organization not found: %w", err)
}
if errors.As(err, &errUserExists) {
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) {
r.MustAuthorize(ctx, input.ID, iam.ActionMembershipProfileUpdate)
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) {
r.MustAuthorize(ctx, input.MembershipID, iam.ActionMembershipUpdate)
if input.Role == coredata.MembershipRoleOwner {
r.MustAuthorize(ctx, input.MembershipID, iam.ActionMembershipRoleSetOwner)
}
membership, err := r.iamSvc.OrganizationService.UpdateMempership(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) {
r.MustAuthorize(ctx, input.ProfileID, iam.ActionMembershipProfileDelete)
err := r.iamSvc.OrganizationService.RemoveUser(ctx, input.OrganizationID, input.ProfileID)
if err != nil {
var errManagedBySCIM *iam.ErrUserManagedBySCIM
var errLastOwner *iam.ErrLastActiveOwner
if errors.As(err, &errManagedBySCIM) {
return nil, types.RemoveUserOutput{}, fmt.Errorf("user is managed by SCIM and cannot be removed: %w", err)
}
if errors.As(err, &errLastOwner) {
return nil, types.RemoveUserOutput{}, fmt.Errorf("cannot remove last active owner: %w", err)
}
return nil, types.RemoveUserOutput{}, fmt.Errorf("remove user: %w", err)
}
return nil, types.RemoveUserOutput{DeletedUserID: input.ProfileID}, nil
}
func (r *Resolver) DeleteDataProtectionImpactAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDataProtectionImpactAssessmentInput) (*mcp.CallToolResult, types.DeleteDataProtectionImpactAssessmentOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionDataProtectionImpactAssessmentDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.DataProtectionImpactAssessments.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionStatementOfApplicabilityList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionStatementOfApplicabilityGet)
prb := r.ProboService(ctx, input.ID)
soa, err := prb.StatementsOfApplicability.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionStatementOfApplicabilityCreate)
svc := r.ProboService(ctx, input.OrganizationID)
soa, err := svc.StatementsOfApplicability.Create(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionStatementOfApplicabilityUpdate)
svc := r.ProboService(ctx, input.ID)
soa, err := svc.StatementsOfApplicability.Update(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionStatementOfApplicabilityDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.StatementsOfApplicability.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.StatementOfApplicabilityID, probo.ActionApplicabilityStatementList)
prb := r.ProboService(ctx, input.StatementOfApplicabilityID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionApplicabilityStatementGet)
prb := r.ProboService(ctx, input.ID)
stmt, err := prb.StatementsOfApplicability.GetApplicabilityStatement(ctx, 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) {
r.MustAuthorize(ctx, input.StatementOfApplicabilityID, probo.ActionApplicabilityStatementCreate)
svc := r.ProboService(ctx, input.StatementOfApplicabilityID)
stmt, err := svc.StatementsOfApplicability.CreateApplicabilityStatement(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionApplicabilityStatementUpdate)
svc := r.ProboService(ctx, input.ID)
stmt, err := svc.StatementsOfApplicability.UpdateApplicabilityStatement(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionApplicabilityStatementDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.StatementsOfApplicability.DeleteApplicabilityStatement(ctx, 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
}
// ListVendorRiskAssessmentsTool handles the listVendorRiskAssessments tool
// List all risk assessments for a vendor
func (r *Resolver) ListVendorRiskAssessmentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListVendorRiskAssessmentsInput) (*mcp.CallToolResult, types.ListVendorRiskAssessmentsOutput, error) {
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorRiskAssessmentList)
prb := r.ProboService(ctx, input.VendorID)
pageOrderBy := page.OrderBy[coredata.VendorRiskAssessmentOrderField]{
Field: coredata.VendorRiskAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorRiskAssessmentOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.Vendors.ListRiskAssessments(ctx, input.VendorID, cursor)
if err != nil {
return nil, types.ListVendorRiskAssessmentsOutput{}, fmt.Errorf("cannot list vendor risk assessments: %w", err)
}
return nil, types.NewListVendorRiskAssessmentsOutput(p), nil
}
// AddVendorRiskAssessmentTool handles the addVendorRiskAssessment tool
// Add a new risk assessment for a vendor
func (r *Resolver) AddVendorRiskAssessmentTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddVendorRiskAssessmentInput) (*mcp.CallToolResult, types.AddVendorRiskAssessmentOutput, error) {
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorRiskAssessmentCreate)
prb := r.ProboService(ctx, input.VendorID)
assessment, err := prb.Vendors.CreateRiskAssessment(
ctx,
probo.CreateVendorRiskAssessmentRequest{
VendorID: input.VendorID,
ExpiresAt: input.ExpiresAt,
DataSensitivity: input.DataSensitivity,
BusinessImpact: input.BusinessImpact,
Notes: input.Notes,
},
)
if err != nil {
return nil, types.AddVendorRiskAssessmentOutput{}, fmt.Errorf("failed to create vendor risk assessment: %w", err)
}
return nil, types.NewAddVendorRiskAssessmentOutput(assessment), nil
}
func (r *Resolver) DeleteVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteVendorInput) (*mcp.CallToolResult, types.DeleteVendorOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionVendorDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Vendors.Delete(ctx, input.ID)
if err != nil {
return nil, types.DeleteVendorOutput{}, fmt.Errorf("failed to delete vendor: %w", err)
}
return nil, types.DeleteVendorOutput{
DeletedVendorID: input.ID,
}, nil
}
func (r *Resolver) DeleteFindingTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteFindingInput) (*mcp.CallToolResult, types.DeleteFindingOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionFindingDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Findings.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.FindingID, probo.ActionFindingAuditMappingCreate)
svc := r.ProboService(ctx, input.FindingID)
finding, audit, err := svc.Findings.CreateAuditMapping(ctx, 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) {
r.MustAuthorize(ctx, input.FindingID, probo.ActionFindingAuditMappingDelete)
svc := r.ProboService(ctx, input.FindingID)
finding, audit, err := svc.Findings.DeleteAuditMapping(ctx, 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) {
r.MustAuthorize(ctx, input.FindingID, probo.ActionFindingGet)
prb := r.ProboService(ctx, input.FindingID)
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, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAccessReviewCampaignList)
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
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.Campaigns(scope).ListForOrganizationID(ctx, 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 with optional filters
func (r *Resolver) ListAccessEntriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessEntriesInput) (*mcp.CallToolResult, types.ListAccessEntriesOutput, error) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessEntryList)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
pageOrderBy := page.OrderBy[coredata.AccessEntryOrderField]{
Field: coredata.AccessEntryOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessEntryOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
var filter *coredata.AccessEntryFilter
if input.Filter != nil {
filter = &coredata.AccessEntryFilter{
Decision: input.Filter.Decision,
Flag: input.Filter.Flag,
IncrementalTag: input.Filter.IncrementalTag,
IsAdmin: input.Filter.IsAdmin,
AuthMethod: input.Filter.AuthMethod,
}
}
var p *page.Page[*coredata.AccessEntry, coredata.AccessEntryOrderField]
if input.AccessSourceID != nil {
var err error
p, err = r.accessReview.Entries(scope).ListForCampaignIDAndSourceID(
ctx,
input.CampaignID,
*input.AccessSourceID,
cursor,
filter,
)
if err != nil {
panic(fmt.Errorf("cannot list access entries: %w", err))
}
} else {
var err error
p, err = r.accessReview.Entries(scope).ListForCampaignID(ctx, input.CampaignID, cursor, filter)
if err != nil {
panic(fmt.Errorf("cannot list access entries: %w", err))
}
}
return nil, types.NewListAccessEntriesOutput(p), nil
}
// GetAccessReviewCampaignStatisticsTool handles the getAccessReviewCampaignStatistics tool
// Get statistics for an access review campaign
func (r *Resolver) GetAccessReviewCampaignStatisticsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAccessReviewCampaignStatisticsInput) (*mcp.CallToolResult, types.GetAccessReviewCampaignStatisticsOutput, error) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignGet)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
stats, err := r.accessReview.Entries(scope).Statistics(ctx, input.CampaignID)
if err != nil {
panic(fmt.Errorf("cannot get campaign statistics: %w", err))
}
return nil, types.GetAccessReviewCampaignStatisticsOutput{
Statistics: types.NewAccessEntryStatistics(stats),
}, nil
}
// RecordAccessEntryDecisionTool handles the recordAccessEntryDecision tool
// Record a decision on an access entry
func (r *Resolver) RecordAccessEntryDecisionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RecordAccessEntryDecisionInput) (*mcp.CallToolResult, types.RecordAccessEntryDecisionOutput, error) {
r.MustAuthorize(ctx, input.AccessEntryID, probo.ActionAccessEntryDecide)
scope := coredata.NewScopeFromObjectID(input.AccessEntryID)
identity := authn.IdentityFromContext(ctx)
if identity == nil {
return nil, types.RecordAccessEntryDecisionOutput{}, fmt.Errorf("no identity in context")
}
decisionReq := accessreview.RecordAccessEntryDecisionRequest{
EntryID: input.AccessEntryID,
Decision: input.Decision,
DecisionNote: input.DecisionNote,
}
organizationID, err := r.accessReview.ResolveEntryOrganizationID(ctx, input.AccessEntryID)
if err == nil {
profile, err := r.iamSvc.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, organizationID)
if err == nil {
decisionReq.DecidedByID = &profile.ID
}
}
entry, err := r.accessReview.Entries(scope).RecordDecision(ctx, decisionReq)
if err != nil {
return nil, types.RecordAccessEntryDecisionOutput{}, fmt.Errorf("cannot record decision: %w", err)
}
return nil, types.RecordAccessEntryDecisionOutput{
AccessEntry: types.NewAccessEntry(entry),
}, nil
}
// RecordAccessEntryDecisionsTool handles the recordAccessEntryDecisions tool
// Record decisions on multiple access entries in a single batch
func (r *Resolver) RecordAccessEntryDecisionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RecordAccessEntryDecisionsInput) (*mcp.CallToolResult, types.RecordAccessEntryDecisionsOutput, error) {
if len(input.Decisions) == 0 {
return nil, types.RecordAccessEntryDecisionsOutput{
AccessEntries: []*types.AccessEntry{},
}, nil
}
const maxBatchSize = 100
if len(input.Decisions) > maxBatchSize {
return nil, types.RecordAccessEntryDecisionsOutput{}, 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 {
r.MustAuthorize(ctx, d.AccessEntryID, probo.ActionAccessEntryDecide)
}
scope := coredata.NewScopeFromObjectID(input.Decisions[0].AccessEntryID)
identity := authn.IdentityFromContext(ctx)
if identity == nil {
return nil, types.RecordAccessEntryDecisionsOutput{}, fmt.Errorf("no identity in context")
}
// Cache profile lookups per organization so we resolve the correct
// decidedByID for each entry even when a batch spans multiple orgs.
profileCache := make(map[gid.GID]*gid.GID)
decisions := make([]accessreview.RecordAccessEntryDecisionRequest, len(input.Decisions))
for i, d := range input.Decisions {
var decidedByID *gid.GID
organizationID, err := r.accessReview.ResolveEntryOrganizationID(ctx, d.AccessEntryID)
if err == nil {
if cached, ok := profileCache[organizationID]; ok {
decidedByID = cached
} else {
profile, err := r.iamSvc.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, organizationID)
if err == nil {
decidedByID = &profile.ID
}
profileCache[organizationID] = decidedByID
}
}
decisions[i] = accessreview.RecordAccessEntryDecisionRequest{
EntryID: d.AccessEntryID,
Decision: d.Decision,
DecisionNote: d.DecisionNote,
DecidedByID: decidedByID,
}
}
entries, err := r.accessReview.Entries(scope).RecordDecisions(ctx, decisions)
if err != nil {
return nil, types.RecordAccessEntryDecisionsOutput{}, fmt.Errorf("cannot record decisions: %w", err)
}
accessEntries := make([]*types.AccessEntry, len(entries))
for i, e := range entries {
accessEntries[i] = types.NewAccessEntry(e)
}
return nil, types.RecordAccessEntryDecisionsOutput{
AccessEntries: 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) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignClose)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
campaign, err := r.accessReview.Campaigns(scope).Close(ctx, 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
}
// ListAccessSourcesTool handles the listAccessSources tool
// List access sources for an organization
func (r *Resolver) ListAccessSourcesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListAccessSourcesInput) (*mcp.CallToolResult, types.ListAccessSourcesOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAccessSourceList)
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
pageOrderBy := page.OrderBy[coredata.AccessSourceOrderField]{
Field: coredata.AccessSourceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessSourceOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := r.accessReview.Sources(scope).ListForOrganizationID(ctx, input.OrganizationID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list access sources: %w", err))
}
return nil, types.NewListAccessSourcesOutput(p), nil
}
// CreateAccessSourceTool handles the createAccessSource tool
// Create a new access source for an organization
func (r *Resolver) CreateAccessSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateAccessSourceInput) (*mcp.CallToolResult, types.CreateAccessSourceOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAccessSourceCreate)
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
source, err := r.accessReview.Sources(scope).Create(ctx, accessreview.CreateAccessSourceRequest{
OrganizationID: input.OrganizationID,
ConnectorID: input.ConnectorID,
Name: input.Name,
Category: coredata.AccessSourceCategorySaaS,
CsvData: input.CsvData,
})
if err != nil {
return nil, types.CreateAccessSourceOutput{}, fmt.Errorf("cannot create access source: %w", err)
}
return nil, types.CreateAccessSourceOutput{
AccessSource: types.NewAccessSource(source),
}, nil
}
// UpdateAccessSourceTool handles the updateAccessSource tool
// Update an existing access source
func (r *Resolver) UpdateAccessSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateAccessSourceInput) (*mcp.CallToolResult, types.UpdateAccessSourceOutput, error) {
r.MustAuthorize(ctx, input.AccessSourceID, probo.ActionAccessSourceUpdate)
scope := coredata.NewScopeFromObjectID(input.AccessSourceID)
updateReq := accessreview.UpdateAccessSourceRequest{
AccessSourceID: input.AccessSourceID,
Name: input.Name,
}
if rawConnectorID := UnwrapOmittable(input.ConnectorID); rawConnectorID != nil {
if *rawConnectorID != nil {
id, err := gid.ParseGID(**rawConnectorID)
if err != nil {
return nil, types.UpdateAccessSourceOutput{}, 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.Sources(scope).Update(ctx, updateReq)
if err != nil {
return nil, types.UpdateAccessSourceOutput{}, fmt.Errorf("cannot update access source: %w", err)
}
return nil, types.UpdateAccessSourceOutput{
AccessSource: types.NewAccessSource(source),
}, nil
}
// DeleteAccessSourceTool handles the deleteAccessSource tool
// Delete an access source
func (r *Resolver) DeleteAccessSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAccessSourceInput) (*mcp.CallToolResult, types.DeleteAccessSourceOutput, error) {
r.MustAuthorize(ctx, input.AccessSourceID, probo.ActionAccessSourceDelete)
scope := coredata.NewScopeFromObjectID(input.AccessSourceID)
if err := r.accessReview.Sources(scope).Delete(ctx, input.AccessSourceID); err != nil {
return nil, types.DeleteAccessSourceOutput{}, fmt.Errorf("cannot delete access source: %w", err)
}
return nil, types.DeleteAccessSourceOutput{
DeletedAccessSourceID: input.AccessSourceID,
}, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAccessReviewCampaignCreate)
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
var description string
if input.Description != nil {
description = *input.Description
}
campaign, err := r.accessReview.Campaigns(scope).Create(ctx, accessreview.CreateAccessReviewCampaignRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: description,
FrameworkControls: input.FrameworkControls,
AccessSourceIDs: input.AccessSourceIds,
})
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) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignUpdate)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
updateReq := accessreview.UpdateAccessReviewCampaignRequest{
CampaignID: input.CampaignID,
Name: input.Name,
Description: input.Description,
}
if rawControls := UnwrapOmittable(input.FrameworkControls); rawControls != nil {
if *rawControls != nil {
controls := make([]string, 0, len(**rawControls))
for _, v := range **rawControls {
if s, ok := v.(string); ok {
controls = append(controls, s)
}
}
updateReq.FrameworkControls = &controls
} else {
empty := []string{}
updateReq.FrameworkControls = &empty
}
}
campaign, err := r.accessReview.Campaigns(scope).Update(ctx, 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) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignDelete)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
if err := r.accessReview.Campaigns(scope).Delete(ctx, 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) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignStart)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
campaign, err := r.accessReview.Campaigns(scope).Start(ctx, 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) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignCancel)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
campaign, err := r.accessReview.Campaigns(scope).Cancel(ctx, 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
}
// AddAccessReviewCampaignScopeSourceTool handles the addAccessReviewCampaignScopeSource tool
// Add an access source to an access review campaign's scope
func (r *Resolver) AddAccessReviewCampaignScopeSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddAccessReviewCampaignScopeSourceInput) (*mcp.CallToolResult, types.AddAccessReviewCampaignScopeSourceOutput, error) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignAddScopeSource)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
campaign, err := r.accessReview.Campaigns(scope).AddScopeSource(ctx, accessreview.AddCampaignScopeSourceRequest{
CampaignID: input.CampaignID,
AccessSourceID: input.AccessSourceID,
})
if err != nil {
return nil, types.AddAccessReviewCampaignScopeSourceOutput{}, fmt.Errorf("cannot add scope source to access review campaign: %w", err)
}
return nil, types.AddAccessReviewCampaignScopeSourceOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// RemoveAccessReviewCampaignScopeSourceTool handles the removeAccessReviewCampaignScopeSource tool
// Remove an access source from an access review campaign's scope
func (r *Resolver) RemoveAccessReviewCampaignScopeSourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RemoveAccessReviewCampaignScopeSourceInput) (*mcp.CallToolResult, types.RemoveAccessReviewCampaignScopeSourceOutput, error) {
r.MustAuthorize(ctx, input.CampaignID, probo.ActionAccessReviewCampaignRemoveScopeSource)
scope := coredata.NewScopeFromObjectID(input.CampaignID)
campaign, err := r.accessReview.Campaigns(scope).RemoveScopeSource(ctx, accessreview.RemoveCampaignScopeSourceRequest{
CampaignID: input.CampaignID,
AccessSourceID: input.AccessSourceID,
})
if err != nil {
return nil, types.RemoveAccessReviewCampaignScopeSourceOutput{}, fmt.Errorf("cannot remove scope source from access review campaign: %w", err)
}
return nil, types.RemoveAccessReviewCampaignScopeSourceOutput{
Campaign: types.NewAccessReviewCampaign(campaign),
}, nil
}
// FlagAccessEntryTool handles the flagAccessEntry tool
// Flag an access entry during review
func (r *Resolver) FlagAccessEntryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.FlagAccessEntryInput) (*mcp.CallToolResult, types.FlagAccessEntryOutput, error) {
r.MustAuthorize(ctx, input.AccessEntryID, probo.ActionAccessEntryFlag)
scope := coredata.NewScopeFromObjectID(input.AccessEntryID)
entry, err := r.accessReview.Entries(scope).FlagEntry(ctx, accessreview.FlagAccessEntryRequest{
EntryID: input.AccessEntryID,
Flags: input.Flags,
FlagReasons: input.FlagReasons,
})
if err != nil {
return nil, types.FlagAccessEntryOutput{}, fmt.Errorf("cannot flag access entry: %w", err)
}
return nil, types.FlagAccessEntryOutput{
AccessEntry: types.NewAccessEntry(entry),
}, nil
}
func (r *Resolver) GetAuditReportUrlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetAuditReportUrlInput) (*mcp.CallToolResult, types.GetAuditReportUrlOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionReportGetReportUrl)
prb := r.ProboService(ctx, input.ID)
url, err := prb.Audits.GenerateReportURL(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentArchive)
svc := r.ProboService(ctx, input.ID)
document, err := svc.Documents.Archive(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentUnarchive)
svc := r.ProboService(ctx, input.ID)
document, err := svc.Documents.Unarchive(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionOrganizationContextGet)
prb := r.ProboService(ctx, input.OrganizationID)
orgContext, err := prb.Organizations.GetContext(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionOrganizationContextUpdate)
prb := r.ProboService(ctx, input.OrganizationID)
orgContext, err := prb.Organizations.UpdateContext(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, iam.ActionAuditLogEntryGet)
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) {
r.MustAuthorize(ctx, input.OrganizationID, iam.ActionAuditLogEntryList)
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) RequestDocumentVersionApprovalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.RequestDocumentVersionApprovalInput) (*mcp.CallToolResult, types.RequestDocumentVersionApprovalOutput, error) {
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentVersionRequestApproval)
svc := r.ProboService(ctx, input.DocumentID)
quorum, err := svc.DocumentApprovals.RequestApproval(ctx, probo.RequestApprovalRequest{
DocumentID: input.DocumentID,
ApproverIDs: input.ApproverIds,
Changelog: input.Changelog,
})
if err != nil {
panic(fmt.Errorf("cannot request document version approval: %w", err))
}
documentVersion, err := svc.Documents.GetVersion(ctx, quorum.VersionID)
if err != nil {
panic(fmt.Errorf("cannot get document version: %w", err))
}
return nil, types.RequestDocumentVersionApprovalOutput{
DocumentVersion: types.NewDocumentVersion(documentVersion),
}, nil
}
func (r *Resolver) PublishMajorDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishMajorDocumentVersionInput) (*mcp.CallToolResult, types.PublishMajorDocumentVersionOutput, error) {
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentVersionPublish)
svc := r.ProboService(ctx, input.DocumentID)
user := authn.IdentityFromContext(ctx)
document, documentVersion, err := svc.Documents.PublishMajorVersion(
ctx,
input.DocumentID,
user.ID,
input.Changelog,
)
if err != nil {
panic(fmt.Errorf("cannot publish major document version: %w", err))
}
return nil, types.PublishMajorDocumentVersionOutput{
Document: types.NewDocument(document),
DocumentVersion: types.NewDocumentVersion(documentVersion),
}, nil
}
func (r *Resolver) PublishMinorDocumentVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishMinorDocumentVersionInput) (*mcp.CallToolResult, types.PublishMinorDocumentVersionOutput, error) {
r.MustAuthorize(ctx, input.DocumentID, probo.ActionDocumentVersionPublish)
svc := r.ProboService(ctx, input.DocumentID)
user := authn.IdentityFromContext(ctx)
document, documentVersion, err := svc.Documents.PublishMinorVersion(
ctx,
input.DocumentID,
user.ID,
input.Changelog,
)
if err != nil {
panic(fmt.Errorf("cannot publish minor document version: %w", err))
}
return nil, types.PublishMinorDocumentVersionOutput{
Document: types.NewDocument(document),
DocumentVersion: types.NewDocumentVersion(documentVersion),
}, nil
}
func (r *Resolver) ListMeasureDocumentsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListMeasureDocumentsInput) (*mcp.CallToolResult, types.ListMeasureDocumentsOutput, error) {
r.MustAuthorize(ctx, input.MeasureID, probo.ActionMeasureGet)
prb := r.ProboService(ctx, input.MeasureID)
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, 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) {
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionVoidApproval)
svc := r.ProboService(ctx, input.DocumentVersionID)
_, documentVersion, err := svc.DocumentApprovals.VoidApproval(ctx, 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) SendSigningNotificationsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.SendSigningNotificationsInput) (*mcp.CallToolResult, types.SendSigningNotificationsOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDocumentSendSigningNotifications)
svc := r.ProboService(ctx, input.OrganizationID)
err := svc.Documents.SendSigningNotifications(ctx, input.OrganizationID)
if err != nil {
panic(fmt.Errorf("cannot send signing notifications: %w", err))
}
return nil, types.SendSigningNotificationsOutput{
Success: true,
}, nil
}
func (r *Resolver) DeleteDocumentDraftTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteDocumentDraftInput) (*mcp.CallToolResult, types.DeleteDocumentDraftOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentDeleteDraft)
svc := r.ProboService(ctx, input.ID)
document, err := svc.Documents.DeleteDraft(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionStatementOfApplicabilityPublish)
svc := r.ProboService(ctx, input.ID)
document, documentVersion, err := svc.GeneratedDocuments.PublishStatementOfApplicability(ctx, input.ID, input.ApproverIds)
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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionWebhookSubscriptionList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionWebhookSubscriptionGet)
prb := r.ProboService(ctx, input.ID)
subscription, err := prb.WebhookSubscriptions.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionWebhookSubscriptionCreate)
prb := r.ProboService(ctx, input.OrganizationID)
subscription, err := prb.WebhookSubscriptions.Create(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionWebhookSubscriptionUpdate)
prb := r.ProboService(ctx, input.ID)
subscription, err := prb.WebhookSubscriptions.Update(
ctx,
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) {
r.MustAuthorize(ctx, input.ID, probo.ActionWebhookSubscriptionDelete)
prb := r.ProboService(ctx, input.ID)
err := prb.WebhookSubscriptions.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.WebhookSubscriptionID, probo.ActionWebhookSubscriptionGet)
prb := r.ProboService(ctx, input.WebhookSubscriptionID)
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, 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) {
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionApprovalList)
svc := r.ProboService(ctx, input.DocumentVersionID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
svc := r.ProboService(ctx, input.ID)
quorum, err := svc.DocumentApprovals.GetQuorum(ctx, 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) {
r.MustAuthorize(ctx, input.QuorumID, probo.ActionDocumentVersionApprovalList)
svc := r.ProboService(ctx, input.QuorumID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
svc := r.ProboService(ctx, input.ID)
decision, err := svc.DocumentApprovals.GetDecision(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionDatumPublish)
svc := r.ProboService(ctx, input.OrganizationID)
document, documentVersion, err := svc.GeneratedDocuments.PublishDataList(ctx, input.OrganizationID, input.ApproverIds)
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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionAssetPublish)
svc := r.ProboService(ctx, input.OrganizationID)
document, documentVersion, err := svc.GeneratedDocuments.PublishAssetList(ctx, input.OrganizationID, input.ApproverIds)
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
}
// ListVendorContactsTool handles the listVendorContacts tool
// List all contacts for a vendor
func (r *Resolver) ListVendorContactsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListVendorContactsInput) (*mcp.CallToolResult, types.ListVendorContactsOutput, error) {
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorContactList)
prb := r.ProboService(ctx, input.VendorID)
pageOrderBy := page.OrderBy[coredata.VendorContactOrderField]{
Field: coredata.VendorContactOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorContactOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.VendorContacts.List(ctx, input.VendorID, cursor)
if err != nil {
return nil, types.ListVendorContactsOutput{}, fmt.Errorf("cannot list vendor contacts: %w", err)
}
return nil, types.NewListVendorContactsOutput(p), nil
}
// AddVendorContactTool handles the addVendorContact tool
// Add a new contact to a vendor
func (r *Resolver) AddVendorContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddVendorContactInput) (*mcp.CallToolResult, types.AddVendorContactOutput, error) {
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorContactCreate)
prb := r.ProboService(ctx, input.VendorID)
emailAddr, err := mail.ParseAddr(input.Email)
if err != nil {
return nil, types.AddVendorContactOutput{}, fmt.Errorf("invalid email address: %w", err)
}
vendorContact, err := prb.VendorContacts.Create(ctx, probo.CreateVendorContactRequest{
VendorID: input.VendorID,
FullName: &input.FullName,
Email: &emailAddr,
Phone: &input.Phone,
Role: &input.Role,
})
if err != nil {
return nil, types.AddVendorContactOutput{}, fmt.Errorf("cannot create vendor contact: %w", err)
}
return nil, types.AddVendorContactOutput{
VendorContact: types.NewVendorContact(vendorContact),
}, nil
}
// UpdateVendorContactTool handles the updateVendorContact tool
// Update an existing vendor contact
func (r *Resolver) UpdateVendorContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateVendorContactInput) (*mcp.CallToolResult, types.UpdateVendorContactOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionVendorContactUpdate)
prb := r.ProboService(ctx, input.ID)
updateReq := probo.UpdateVendorContactRequest{
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.UpdateVendorContactOutput{}, 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
}
vendorContact, err := prb.VendorContacts.Update(ctx, updateReq)
if err != nil {
return nil, types.UpdateVendorContactOutput{}, fmt.Errorf("cannot update vendor contact: %w", err)
}
return nil, types.UpdateVendorContactOutput{
VendorContact: types.NewVendorContact(vendorContact),
}, nil
}
// DeleteVendorContactTool handles the deleteVendorContact tool
// Delete a vendor contact
func (r *Resolver) DeleteVendorContactTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteVendorContactInput) (*mcp.CallToolResult, types.DeleteVendorContactOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionVendorContactDelete)
prb := r.ProboService(ctx, input.ID)
err := prb.VendorContacts.Delete(ctx, input.ID)
if err != nil {
return nil, types.DeleteVendorContactOutput{}, fmt.Errorf("cannot delete vendor contact: %w", err)
}
return nil, types.DeleteVendorContactOutput{
DeletedVendorContactID: input.ID,
}, nil
}
// ListVendorServicesTool handles the listVendorServices tool
// List all services for a vendor
func (r *Resolver) ListVendorServicesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListVendorServicesInput) (*mcp.CallToolResult, types.ListVendorServicesOutput, error) {
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorServiceList)
prb := r.ProboService(ctx, input.VendorID)
pageOrderBy := page.OrderBy[coredata.VendorServiceOrderField]{
Field: coredata.VendorServiceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorServiceOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.VendorServices.List(ctx, input.VendorID, cursor)
if err != nil {
return nil, types.ListVendorServicesOutput{}, fmt.Errorf("cannot list vendor services: %w", err)
}
return nil, types.NewListVendorServicesOutput(p), nil
}
// AddVendorServiceTool handles the addVendorService tool
// Add a new service to a vendor
func (r *Resolver) AddVendorServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddVendorServiceInput) (*mcp.CallToolResult, types.AddVendorServiceOutput, error) {
r.MustAuthorize(ctx, input.VendorID, probo.ActionVendorServiceCreate)
prb := r.ProboService(ctx, input.VendorID)
vendorService, err := prb.VendorServices.Create(ctx, probo.CreateVendorServiceRequest{
VendorID: input.VendorID,
Name: input.Name,
Description: input.Description,
})
if err != nil {
return nil, types.AddVendorServiceOutput{}, fmt.Errorf("cannot create vendor service: %w", err)
}
return nil, types.AddVendorServiceOutput{
VendorService: types.NewVendorService(vendorService),
}, nil
}
// UpdateVendorServiceTool handles the updateVendorService tool
// Update an existing vendor service
func (r *Resolver) UpdateVendorServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateVendorServiceInput) (*mcp.CallToolResult, types.UpdateVendorServiceOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionVendorServiceUpdate)
prb := r.ProboService(ctx, input.ID)
updateReq := probo.UpdateVendorServiceRequest{
ID: input.ID,
}
if input.Name != nil {
updateReq.Name = input.Name
}
if input.Description != nil {
updateReq.Description = &input.Description
}
vendorService, err := prb.VendorServices.Update(ctx, updateReq)
if err != nil {
return nil, types.UpdateVendorServiceOutput{}, fmt.Errorf("cannot update vendor service: %w", err)
}
return nil, types.UpdateVendorServiceOutput{
VendorService: types.NewVendorService(vendorService),
}, nil
}
// DeleteVendorServiceTool handles the deleteVendorService tool
// Delete a vendor service
func (r *Resolver) DeleteVendorServiceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteVendorServiceInput) (*mcp.CallToolResult, types.DeleteVendorServiceOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionVendorServiceDelete)
prb := r.ProboService(ctx, input.ID)
err := prb.VendorServices.Delete(ctx, input.ID)
if err != nil {
return nil, types.DeleteVendorServiceOutput{}, fmt.Errorf("cannot delete vendor service: %w", err)
}
return nil, types.DeleteVendorServiceOutput{
DeletedVendorServiceID: input.ID,
}, nil
}
func (r *Resolver) DeleteAssetTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteAssetInput) (*mcp.CallToolResult, types.DeleteAssetOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionAssetDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Assets.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionDatumDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Data.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionObligationDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Obligations.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionAuditDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.Audits.Delete(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionRightsRequestList)
prb := r.ProboService(ctx, input.OrganizationID)
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, 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) {
r.MustAuthorize(ctx, input.ID, probo.ActionRightsRequestGet)
prb := r.ProboService(ctx, input.ID)
rightsRequest, err := prb.RightsRequests.Get(ctx, 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) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionRightsRequestCreate)
svc := r.ProboService(ctx, input.OrganizationID)
rightsRequest, err := svc.RightsRequests.Create(
ctx,
&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) {
r.MustAuthorize(ctx, input.ID, probo.ActionRightsRequestUpdate)
svc := r.ProboService(ctx, input.ID)
var dataSubject **string
if input.DataSubject != nil {
dataSubject = &input.DataSubject
}
rightsRequest, err := svc.RightsRequests.Update(
ctx,
&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) {
r.MustAuthorize(ctx, input.ID, probo.ActionRightsRequestDelete)
svc := r.ProboService(ctx, input.ID)
err := svc.RightsRequests.Delete(ctx, input.ID)
if err != nil {
return nil, types.DeleteRightsRequestOutput{}, fmt.Errorf("failed to delete rights request: %w", err)
}
return nil, types.DeleteRightsRequestOutput{
DeletedRightsRequestID: input.ID,
}, nil
}
// GetTrustCenterTool handles the getTrustCenter tool
// Get the trust center for an organization
func (r *Resolver) GetTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrustCenterInput) (*mcp.CallToolResult, types.GetTrustCenterOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTrustCenterGet)
prb := r.ProboService(ctx, input.OrganizationID)
trustCenter, err := prb.TrustCenters.GetByOrganizationID(ctx, input.OrganizationID)
if err != nil {
return nil, types.GetTrustCenterOutput{}, fmt.Errorf("cannot get trust center: %w", err)
}
tc := types.NewTrustCenter(trustCenter)
logoURL, err := prb.TrustCenters.GenerateLogoURL(ctx, trustCenter.ID, 1*time.Hour)
if err == nil {
tc.LogoFileURL = logoURL
}
darkLogoURL, err := prb.TrustCenters.GenerateDarkLogoURL(ctx, trustCenter.ID, 1*time.Hour)
if err == nil {
tc.DarkLogoFileURL = darkLogoURL
}
ndaFileURL, err := prb.TrustCenters.GenerateNDAFileURL(ctx, trustCenter.ID, 15*time.Minute)
if err == nil {
tc.NdaFileURL = ndaFileURL
}
return nil, types.GetTrustCenterOutput{TrustCenter: tc}, nil
}
// UpdateTrustCenterTool handles the updateTrustCenter tool
// Update the trust center settings
func (r *Resolver) UpdateTrustCenterTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterInput) (*mcp.CallToolResult, types.UpdateTrustCenterOutput, error) {
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionTrustCenterUpdate)
prb := r.ProboService(ctx, input.TrustCenterID)
updateReq := &probo.UpdateTrustCenterRequest{
ID: input.TrustCenterID,
}
if active := UnwrapOmittable(input.Active); active != nil {
updateReq.Active = *active
}
if sei := UnwrapOmittable(input.SearchEngineIndexing); sei != nil {
updateReq.SearchEngineIndexing = *sei
}
trustCenter, _, err := prb.TrustCenters.Update(ctx, updateReq)
if err != nil {
return nil, types.UpdateTrustCenterOutput{}, fmt.Errorf("cannot update trust center: %w", err)
}
return nil, types.UpdateTrustCenterOutput{TrustCenter: types.NewTrustCenter(trustCenter)}, nil
}
// ListTrustCenterReferencesTool handles the listTrustCenterReferences tool
// List all references for a trust center
func (r *Resolver) ListTrustCenterReferencesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterReferencesInput) (*mcp.CallToolResult, types.ListTrustCenterReferencesOutput, error) {
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionTrustCenterReferenceList)
prb := r.ProboService(ctx, input.TrustCenterID)
pageOrderBy := page.OrderBy[coredata.TrustCenterReferenceOrderField]{
Field: coredata.TrustCenterReferenceOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterReferenceOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.TrustCenterReferences.ListForTrustCenterID(ctx, input.TrustCenterID, cursor)
if err != nil {
return nil, types.ListTrustCenterReferencesOutput{}, fmt.Errorf("cannot list trust center references: %w", err)
}
return nil, types.NewListTrustCenterReferencesOutput(p), nil
}
// AddTrustCenterReferenceTool handles the addTrustCenterReference tool
// Add a new reference to the trust center
func (r *Resolver) AddTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrustCenterReferenceInput) (*mcp.CallToolResult, types.AddTrustCenterReferenceOutput, error) {
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionTrustCenterReferenceCreate)
prb := r.ProboService(ctx, input.TrustCenterID)
var websiteURL string
if input.WebsiteURL != nil {
websiteURL = *input.WebsiteURL
}
reference, err := prb.TrustCenterReferences.Create(
ctx,
&probo.CreateTrustCenterReferenceRequest{
TrustCenterID: input.TrustCenterID,
Name: input.Name,
Description: input.Description,
WebsiteURL: websiteURL,
},
)
if err != nil {
return nil, types.AddTrustCenterReferenceOutput{}, fmt.Errorf("cannot add trust center reference: %w", err)
}
return nil, types.AddTrustCenterReferenceOutput{TrustCenterReference: types.NewTrustCenterReference(reference)}, nil
}
// UpdateTrustCenterReferenceTool handles the updateTrustCenterReference tool
// Update a trust center reference
func (r *Resolver) UpdateTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrustCenterReferenceInput) (*mcp.CallToolResult, types.UpdateTrustCenterReferenceOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionTrustCenterReferenceUpdate)
prb := r.ProboService(ctx, input.ID)
updateRefReq := &probo.UpdateTrustCenterReferenceRequest{
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.TrustCenterReferences.Update(ctx, updateRefReq)
if err != nil {
return nil, types.UpdateTrustCenterReferenceOutput{}, fmt.Errorf("cannot update trust center reference: %w", err)
}
return nil, types.UpdateTrustCenterReferenceOutput{TrustCenterReference: types.NewTrustCenterReference(reference)}, nil
}
// DeleteTrustCenterReferenceTool handles the deleteTrustCenterReference tool
// Delete a trust center reference
func (r *Resolver) DeleteTrustCenterReferenceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterReferenceInput) (*mcp.CallToolResult, types.DeleteTrustCenterReferenceOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionTrustCenterReferenceDelete)
prb := r.ProboService(ctx, input.ID)
err := prb.TrustCenterReferences.Delete(ctx, input.ID)
if err != nil {
return nil, types.DeleteTrustCenterReferenceOutput{}, fmt.Errorf("cannot delete trust center reference: %w", err)
}
return nil, types.DeleteTrustCenterReferenceOutput{DeletedTrustCenterReferenceID: input.ID}, nil
}
// ListTrustCenterFilesTool handles the listTrustCenterFiles tool
// List all files for the trust center
func (r *Resolver) ListTrustCenterFilesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrustCenterFilesInput) (*mcp.CallToolResult, types.ListTrustCenterFilesOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionTrustCenterFileList)
prb := r.ProboService(ctx, input.OrganizationID)
pageOrderBy := page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: coredata.TrustCenterFileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
filter := coredata.NewTrustCenterFileFilter()
p, err := prb.TrustCenterFiles.ListForOrganizationID(ctx, input.OrganizationID, cursor, filter)
if err != nil {
return nil, types.ListTrustCenterFilesOutput{}, fmt.Errorf("cannot list trust center files: %w", err)
}
files := make([]*types.TrustCenterFile, 0, len(p.Data))
for _, f := range p.Data {
fileURL, err := prb.TrustCenterFiles.GenerateFileURL(ctx, f.ID, 1*time.Hour)
if err != nil {
return nil, types.ListTrustCenterFilesOutput{}, fmt.Errorf("cannot generate file URL: %w", err)
}
files = append(files, types.NewTrustCenterFile(f, fileURL))
}
return nil, types.NewListTrustCenterFilesOutput(files, p), nil
}
// DeleteTrustCenterFileTool handles the deleteTrustCenterFile tool
// Delete a trust center file
func (r *Resolver) DeleteTrustCenterFileTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteTrustCenterFileInput) (*mcp.CallToolResult, types.DeleteTrustCenterFileOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionTrustCenterFileDelete)
prb := r.ProboService(ctx, input.ID)
err := prb.TrustCenterFiles.Delete(ctx, input.ID)
if err != nil {
return nil, types.DeleteTrustCenterFileOutput{}, fmt.Errorf("cannot delete trust center file: %w", err)
}
return nil, types.DeleteTrustCenterFileOutput{DeletedTrustCenterFileID: input.ID}, nil
}
// ListComplianceExternalURLsTool handles the listComplianceExternalURLs tool
// List all external URLs for a trust center
func (r *Resolver) ListComplianceExternalURLsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListComplianceExternalURLsInput) (*mcp.CallToolResult, types.ListComplianceExternalURLsOutput, error) {
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionComplianceExternalURLList)
prb := r.ProboService(ctx, input.TrustCenterID)
pageOrderBy := page.OrderBy[coredata.ComplianceExternalURLOrderField]{
Field: coredata.ComplianceExternalURLOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
if input.OrderBy != nil {
pageOrderBy = page.OrderBy[coredata.ComplianceExternalURLOrderField]{
Field: input.OrderBy.Field,
Direction: input.OrderBy.Direction,
}
}
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
p, err := prb.ComplianceExternalURLs.List(ctx, input.TrustCenterID, cursor)
if err != nil {
return nil, types.ListComplianceExternalURLsOutput{}, fmt.Errorf("cannot list compliance external URLs: %w", err)
}
return nil, types.NewListComplianceExternalURLsOutput(p), nil
}
// AddComplianceExternalURLTool handles the addComplianceExternalURL tool
// Add a new external URL to the trust center
func (r *Resolver) AddComplianceExternalURLTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddComplianceExternalURLInput) (*mcp.CallToolResult, types.AddComplianceExternalURLOutput, error) {
r.MustAuthorize(ctx, input.TrustCenterID, probo.ActionComplianceExternalURLCreate)
prb := r.ProboService(ctx, input.TrustCenterID)
item, err := prb.ComplianceExternalURLs.Create(
ctx,
&probo.CreateComplianceExternalURLRequest{
TrustCenterID: input.TrustCenterID,
Name: input.Name,
URL: input.URL,
},
)
if err != nil {
return nil, types.AddComplianceExternalURLOutput{}, fmt.Errorf("cannot add compliance external URL: %w", err)
}
return nil, types.AddComplianceExternalURLOutput{ComplianceExternalURL: types.NewComplianceExternalURL(item)}, nil
}
// UpdateComplianceExternalURLTool handles the updateComplianceExternalURL tool
// Update a compliance external URL
func (r *Resolver) UpdateComplianceExternalURLTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateComplianceExternalURLInput) (*mcp.CallToolResult, types.UpdateComplianceExternalURLOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionComplianceExternalURLUpdate)
prb := r.ProboService(ctx, input.ID)
updateURLReq := &probo.UpdateComplianceExternalURLRequest{
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.ComplianceExternalURLs.Update(ctx, updateURLReq)
if err != nil {
return nil, types.UpdateComplianceExternalURLOutput{}, fmt.Errorf("cannot update compliance external URL: %w", err)
}
return nil, types.UpdateComplianceExternalURLOutput{ComplianceExternalURL: types.NewComplianceExternalURL(item)}, nil
}
// DeleteComplianceExternalURLTool handles the deleteComplianceExternalURL tool
// Delete a compliance external URL
func (r *Resolver) DeleteComplianceExternalURLTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteComplianceExternalURLInput) (*mcp.CallToolResult, types.DeleteComplianceExternalURLOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionComplianceExternalURLDelete)
prb := r.ProboService(ctx, input.ID)
err := prb.ComplianceExternalURLs.Delete(
ctx,
&probo.DeleteComplianceExternalURLRequest{
ID: input.ID,
},
)
if err != nil {
return nil, types.DeleteComplianceExternalURLOutput{}, fmt.Errorf("cannot delete compliance external URL: %w", err)
}
return nil, types.DeleteComplianceExternalURLOutput{DeletedComplianceExternalURLID: input.ID}, nil
}
// CreateCustomDomainTool handles the createCustomDomain tool
// Create a custom domain for the organization
func (r *Resolver) CreateCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.CreateCustomDomainInput) (*mcp.CallToolResult, types.CreateCustomDomainOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionCustomDomainCreate)
prb := r.ProboService(ctx, input.OrganizationID)
domain, err := prb.CustomDomains.CreateCustomDomain(
ctx,
probo.CreateCustomDomainRequest{
OrganizationID: input.OrganizationID,
Domain: input.Domain,
},
)
if err != nil {
return nil, types.CreateCustomDomainOutput{}, fmt.Errorf("cannot create custom domain: %w", err)
}
return nil, types.CreateCustomDomainOutput{CustomDomain: types.NewCustomDomain(domain)}, nil
}
// DeleteCustomDomainTool handles the deleteCustomDomain tool
// Delete the custom domain for the organization
func (r *Resolver) DeleteCustomDomainTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeleteCustomDomainInput) (*mcp.CallToolResult, types.DeleteCustomDomainOutput, error) {
r.MustAuthorize(ctx, input.OrganizationID, probo.ActionCustomDomainDelete)
prb := r.ProboService(ctx, input.OrganizationID)
domain, err := prb.CustomDomains.GetOrganizationCustomDomain(ctx, input.OrganizationID)
if err != nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot get custom domain: %w", err)
}
if domain == nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("organization has no custom domain")
}
deletedDomain := types.NewCustomDomain(domain)
if err := prb.CustomDomains.DeleteCustomDomain(ctx, input.OrganizationID); err != nil {
return nil, types.DeleteCustomDomainOutput{}, fmt.Errorf("cannot delete custom domain: %w", err)
}
return nil, types.DeleteCustomDomainOutput{DeletedCustomDomain: deletedDomain}, nil
}
func (r *Resolver) AssessVendorTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AssessVendorInput) (*mcp.CallToolResult, types.AssessVendorOutput, error) {
r.MustAuthorize(ctx, input.ID, probo.ActionVendorAssess)
svc := r.ProboService(ctx, input.ID)
result, err := svc.Vendors.Assess(
ctx,
probo.AssessVendorRequest{
ID: input.ID,
WebsiteURL: input.WebsiteURL,
Procedure: input.Procedure,
},
)
if err != nil {
return nil, types.AssessVendorOutput{}, fmt.Errorf("cannot assess vendor: %w", err)
}
return nil, types.NewAssessVendorOutput(result), nil
}