diff --git a/e2e/console/access_review_test.go b/e2e/console/access_review_test.go index 11eb65274..42f65cbf8 100644 --- a/e2e/console/access_review_test.go +++ b/e2e/console/access_review_test.go @@ -349,50 +349,6 @@ func TestAccessReviewCampaign_Create(t *testing.T) { assert.Len(t, node.CampaignSources, 2) }) - t.Run("with framework controls", func(t *testing.T) { - t.Parallel() - - const query = ` - mutation($input: CreateAccessReviewCampaignInput!) { - createAccessReviewCampaign(input: $input) { - accessReviewCampaignEdge { - node { - id - name - frameworkControls - } - } - } - } - ` - - var result struct { - CreateAccessReviewCampaign struct { - AccessReviewCampaignEdge struct { - Node struct { - ID string `json:"id"` - Name string `json:"name"` - FrameworkControls []string `json:"frameworkControls"` - } `json:"node"` - } `json:"accessReviewCampaignEdge"` - } `json:"createAccessReviewCampaign"` - } - - err := owner.Execute(query, map[string]any{ - "input": map[string]any{ - "organizationId": orgID, - "name": "SOC2 Campaign", - "frameworkControls": []string{"CC6.1", "CC6.2"}, - }, - }, &result) - require.NoError(t, err) - - node := result.CreateAccessReviewCampaign.AccessReviewCampaignEdge.Node - assert.NotEmpty(t, node.ID) - assert.Equal(t, "SOC2 Campaign", node.Name) - assert.Contains(t, node.FrameworkControls, "CC6.1") - assert.Contains(t, node.FrameworkControls, "CC6.2") - }) } func TestAccessReviewCampaign_Update(t *testing.T) { diff --git a/pkg/accessreview/campaign_service.go b/pkg/accessreview/campaign_service.go index 336b92f34..ec337bc25 100644 --- a/pkg/accessreview/campaign_service.go +++ b/pkg/accessreview/campaign_service.go @@ -36,14 +36,13 @@ func (s *Service) CreateCampaign( now := time.Now() campaign := &coredata.AccessReviewCampaign{ - ID: gid.New(scope.GetTenantID(), coredata.AccessReviewCampaignEntityType), - OrganizationID: req.OrganizationID, - Name: req.Name, - Description: req.Description, - Status: coredata.AccessReviewCampaignStatusDraft, - FrameworkControls: req.FrameworkControls, - CreatedAt: now, - UpdatedAt: now, + ID: gid.New(scope.GetTenantID(), coredata.AccessReviewCampaignEntityType), + OrganizationID: req.OrganizationID, + Name: req.Name, + Description: req.Description, + Status: coredata.AccessReviewCampaignStatusDraft, + CreatedAt: now, + UpdatedAt: now, } err := s.pg.WithTx( @@ -160,10 +159,6 @@ func (s *Service) UpdateCampaign( campaign.Description = **req.Description } - if req.FrameworkControls != nil { - campaign.FrameworkControls = *req.FrameworkControls - } - campaign.UpdatedAt = time.Now() if err := campaign.Update(ctx, conn, scope); err != nil { diff --git a/pkg/accessreview/campaign_types.go b/pkg/accessreview/campaign_types.go index 0dab93b8d..2239de4e7 100644 --- a/pkg/accessreview/campaign_types.go +++ b/pkg/accessreview/campaign_types.go @@ -27,15 +27,13 @@ type ( OrganizationID gid.GID Name string Description string - FrameworkControls []string AccessReviewSourceIDs []gid.GID } UpdateAccessReviewCampaignRequest struct { - CampaignID gid.GID - Name **string - Description **string - FrameworkControls *[]string + CampaignID gid.GID + Name **string + Description **string } AddCampaignSourceRequest struct { diff --git a/pkg/cmd/access-review/campaign/update/update.go b/pkg/cmd/access-review/campaign/update/update.go index 12195e525..276c94464 100644 --- a/pkg/cmd/access-review/campaign/update/update.go +++ b/pkg/cmd/access-review/campaign/update/update.go @@ -47,10 +47,9 @@ type updateResponse struct { func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command { var ( - flagName string - flagDescription string - flagFrameworkControl []string - flagOutput *string + flagName string + flagDescription string + flagOutput *string ) cmd := &cobra.Command{ @@ -92,10 +91,6 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command { input["description"] = flagDescription } - if cmd.Flags().Changed("framework-control") { - input["frameworkControls"] = flagFrameworkControl - } - data, err := client.Do( updateMutation, map[string]any{"input": input}, @@ -125,12 +120,6 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command { cmd.Flags().StringVar(&flagName, "name", "", "Campaign name") cmd.Flags().StringVar(&flagDescription, "description", "", "Campaign description") - cmd.Flags().StringSliceVar( - &flagFrameworkControl, - "framework-control", - nil, - "Framework control IDs (can be repeated)", - ) flagOutput = cmdutil.AddOutputFlag(cmd) return cmd diff --git a/pkg/coredata/access_review_campaign.go b/pkg/coredata/access_review_campaign.go index dfba62c19..f2e85b02b 100644 --- a/pkg/coredata/access_review_campaign.go +++ b/pkg/coredata/access_review_campaign.go @@ -30,16 +30,15 @@ import ( type ( AccessReviewCampaign struct { - ID gid.GID `db:"id"` - OrganizationID gid.GID `db:"organization_id"` - Name string `db:"name"` - Description string `db:"description"` - Status AccessReviewCampaignStatus `db:"status"` - StartedAt *time.Time `db:"started_at"` - CompletedAt *time.Time `db:"completed_at"` - FrameworkControls []string `db:"framework_controls"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ID gid.GID `db:"id"` + OrganizationID gid.GID `db:"organization_id"` + Name string `db:"name"` + Description string `db:"description"` + Status AccessReviewCampaignStatus `db:"status"` + StartedAt *time.Time `db:"started_at"` + CompletedAt *time.Time `db:"completed_at"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` } AccessReviewCampaigns []*AccessReviewCampaign @@ -136,7 +135,6 @@ SELECT status, started_at, completed_at, - framework_controls, created_at, updated_at FROM @@ -186,7 +184,6 @@ INSERT INTO status, started_at, completed_at, - framework_controls, created_at, updated_at ) @@ -199,24 +196,22 @@ VALUES ( @status, @started_at, @completed_at, - @framework_controls, @created_at, @updated_at ); ` args := pgx.StrictNamedArgs{ - "id": c.ID, - "tenant_id": scope.GetTenantID(), - "organization_id": c.OrganizationID, - "name": c.Name, - "description": c.Description, - "status": c.Status, - "started_at": c.StartedAt, - "completed_at": c.CompletedAt, - "framework_controls": c.FrameworkControls, - "created_at": c.CreatedAt, - "updated_at": c.UpdatedAt, + "id": c.ID, + "tenant_id": scope.GetTenantID(), + "organization_id": c.OrganizationID, + "name": c.Name, + "description": c.Description, + "status": c.Status, + "started_at": c.StartedAt, + "completed_at": c.CompletedAt, + "created_at": c.CreatedAt, + "updated_at": c.UpdatedAt, } _, err := conn.Exec(ctx, q, args) @@ -240,7 +235,6 @@ SET status = @status, started_at = @started_at, completed_at = @completed_at, - framework_controls = @framework_controls, updated_at = @updated_at WHERE %s @@ -249,14 +243,13 @@ WHERE q = fmt.Sprintf(q, scope.SQLFragment()) args := pgx.StrictNamedArgs{ - "id": c.ID, - "name": c.Name, - "description": c.Description, - "status": c.Status, - "started_at": c.StartedAt, - "completed_at": c.CompletedAt, - "framework_controls": c.FrameworkControls, - "updated_at": c.UpdatedAt, + "id": c.ID, + "name": c.Name, + "description": c.Description, + "status": c.Status, + "started_at": c.StartedAt, + "completed_at": c.CompletedAt, + "updated_at": c.UpdatedAt, } maps.Copy(args, scope.SQLArguments()) @@ -310,7 +303,6 @@ SELECT status, started_at, completed_at, - framework_controls, created_at, updated_at FROM @@ -382,7 +374,6 @@ SELECT status, started_at, completed_at, - framework_controls, created_at, updated_at FROM diff --git a/pkg/coredata/migrations/20260630T092731Z.sql b/pkg/coredata/migrations/20260630T092731Z.sql new file mode 100644 index 000000000..398d1ba5c --- /dev/null +++ b/pkg/coredata/migrations/20260630T092731Z.sql @@ -0,0 +1,16 @@ +-- Copyright (c) 2026 Probo Inc . +-- +-- Permission to use, copy, modify, and/or distribute this software for any +-- purpose with or without fee is hereby granted, provided that the above +-- copyright notice and this permission notice appear in all copies. +-- +-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +-- PERFORMANCE OF THIS SOFTWARE. + +ALTER TABLE access_review_campaigns + DROP COLUMN framework_controls; diff --git a/pkg/server/api/console/v1/access_review_campaign_resolvers.go b/pkg/server/api/console/v1/access_review_campaign_resolvers.go index ee4bb1a71..5daa1c407 100644 --- a/pkg/server/api/console/v1/access_review_campaign_resolvers.go +++ b/pkg/server/api/console/v1/access_review_campaign_resolvers.go @@ -736,7 +736,6 @@ func (r *mutationResolver) CreateAccessReviewCampaign(ctx context.Context, input OrganizationID: input.OrganizationID, Name: input.Name, Description: description, - FrameworkControls: input.FrameworkControls, AccessReviewSourceIDs: input.AccessReviewSourceIds, }, ) @@ -762,10 +761,9 @@ func (r *mutationResolver) UpdateAccessReviewCampaign(ctx context.Context, input ctx, scope, accessreview.UpdateAccessReviewCampaignRequest{ - CampaignID: input.AccessReviewCampaignID, - Name: gqlutils.UnwrapOmittable(input.Name), - Description: gqlutils.UnwrapOmittable(input.Description), - FrameworkControls: gqlutils.UnwrapOmittable(input.FrameworkControls), + CampaignID: input.AccessReviewCampaignID, + Name: gqlutils.UnwrapOmittable(input.Name), + Description: gqlutils.UnwrapOmittable(input.Description), }, ) if err != nil { diff --git a/pkg/server/api/console/v1/graphql/access_review_campaign.graphql b/pkg/server/api/console/v1/graphql/access_review_campaign.graphql index 65c49ad87..38b7a7ff8 100644 --- a/pkg/server/api/console/v1/graphql/access_review_campaign.graphql +++ b/pkg/server/api/console/v1/graphql/access_review_campaign.graphql @@ -349,7 +349,6 @@ type AccessReviewCampaign implements Node { status: AccessReviewCampaignStatus! startedAt: Datetime completedAt: Datetime - frameworkControls: [String!] createdAt: Datetime! updatedAt: Datetime! @@ -578,7 +577,6 @@ input CreateAccessReviewCampaignInput { organizationId: ID! name: String! description: String - frameworkControls: [String!] accessReviewSourceIds: [ID!] } @@ -590,7 +588,6 @@ input UpdateAccessReviewCampaignInput { accessReviewCampaignId: ID! name: String @goField(omittable: true) description: String @goField(omittable: true) - frameworkControls: [String!] @goField(omittable: true) } type UpdateAccessReviewCampaignPayload { diff --git a/pkg/server/api/console/v1/types/access_review.go b/pkg/server/api/console/v1/types/access_review.go index ef49d6a94..078a2538d 100644 --- a/pkg/server/api/console/v1/types/access_review.go +++ b/pkg/server/api/console/v1/types/access_review.go @@ -215,14 +215,13 @@ func NewAccessReviewCampaign(c *coredata.AccessReviewCampaign) *AccessReviewCamp Organization: &Organization{ ID: c.OrganizationID, }, - Name: c.Name, - Description: c.Description, - Status: c.Status, - StartedAt: c.StartedAt, - CompletedAt: c.CompletedAt, - FrameworkControls: c.FrameworkControls, - CreatedAt: c.CreatedAt, - UpdatedAt: c.UpdatedAt, + Name: c.Name, + Description: c.Description, + Status: c.Status, + StartedAt: c.StartedAt, + CompletedAt: c.CompletedAt, + CreatedAt: c.CreatedAt, + UpdatedAt: c.UpdatedAt, } return campaign diff --git a/pkg/server/api/mcp/v1/schema.resolvers.go b/pkg/server/api/mcp/v1/schema.resolvers.go index f8b96ef60..1afa93592 100644 --- a/pkg/server/api/mcp/v1/schema.resolvers.go +++ b/pkg/server/api/mcp/v1/schema.resolvers.go @@ -3752,7 +3752,6 @@ func (r *Resolver) CreateAccessReviewCampaignTool(ctx context.Context, req *mcp. OrganizationID: input.OrganizationID, Name: input.Name, Description: description, - FrameworkControls: input.FrameworkControls, AccessReviewSourceIDs: input.AccessReviewSourceIds, }) if err != nil { @@ -3784,22 +3783,6 @@ func (r *Resolver) UpdateAccessReviewCampaignTool(ctx context.Context, req *mcp. updateReq.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.UpdateCampaign(ctx, scope, updateReq) if err != nil { return nil, types.UpdateAccessReviewCampaignOutput{}, fmt.Errorf("cannot update access review campaign: %w", err) diff --git a/pkg/server/api/mcp/v1/specification.yaml b/pkg/server/api/mcp/v1/specification.yaml index a1054cc1b..94d7660e3 100644 --- a/pkg/server/api/mcp/v1/specification.yaml +++ b/pkg/server/api/mcp/v1/specification.yaml @@ -7644,11 +7644,6 @@ components: - "null" format: date-time description: Campaign completion time - framework_controls: - type: array - items: - type: string - description: Framework controls created_at: type: string format: date-time @@ -8187,11 +8182,6 @@ components: description: type: string description: Campaign description - framework_controls: - type: array - items: - type: string - description: Framework control references access_review_source_ids: type: array items: @@ -8220,15 +8210,6 @@ components: description: type: string description: New campaign description - framework_controls: - type: - - array - - "null" - items: - type: string - go.probo.inc/mcpgen/omittable: true - description: Framework control references (set to null to clear) - UpdateAccessReviewCampaignMCPOutput: type: object required: diff --git a/pkg/server/api/mcp/v1/types/access_review.go b/pkg/server/api/mcp/v1/types/access_review.go index 02e9dd708..362396d48 100644 --- a/pkg/server/api/mcp/v1/types/access_review.go +++ b/pkg/server/api/mcp/v1/types/access_review.go @@ -54,16 +54,15 @@ func NewListAccessReviewSourcesOutput( func NewAccessReviewCampaign(c *coredata.AccessReviewCampaign) *AccessReviewCampaign { return &AccessReviewCampaign{ - ID: c.ID, - OrganizationID: c.OrganizationID, - Name: c.Name, - Description: &c.Description, - Status: c.Status, - StartedAt: c.StartedAt, - CompletedAt: c.CompletedAt, - FrameworkControls: c.FrameworkControls, - CreatedAt: c.CreatedAt, - UpdatedAt: c.UpdatedAt, + ID: c.ID, + OrganizationID: c.OrganizationID, + Name: c.Name, + Description: &c.Description, + Status: c.Status, + StartedAt: c.StartedAt, + CompletedAt: c.CompletedAt, + CreatedAt: c.CreatedAt, + UpdatedAt: c.UpdatedAt, } }