Remove deprecated SOA code

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-02-17 13:55:56 +01:00
parent e9263fb42f
commit 40e4db9278
50 changed files with 285 additions and 2669 deletions

View File

@@ -30,17 +30,15 @@ import (
type (
Control struct {
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
SectionTitle string `db:"section_title"`
FrameworkID gid.GID `db:"framework_id"`
Name string `db:"name"`
Description *string `db:"description"`
Status ControlStatus `db:"status"`
ExclusionJustification *string `db:"exclusion_justification"`
BestPractice bool `db:"best_practice"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
SectionTitle string `db:"section_title"`
FrameworkID gid.GID `db:"framework_id"`
Name string `db:"name"`
Description *string `db:"description"`
BestPractice bool `db:"best_practice"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
Controls []*Control
@@ -132,8 +130,6 @@ WITH ctrl AS (
c.tenant_id,
c.name,
c.description,
c.status,
c.exclusion_justification,
c.best_practice,
c.created_at,
c.updated_at,
@@ -152,8 +148,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -245,8 +239,6 @@ WITH ctrl AS (
c.tenant_id,
c.name,
c.description,
c.status,
c.exclusion_justification,
c.best_practice,
c.created_at,
c.updated_at,
@@ -265,8 +257,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -364,8 +354,6 @@ WITH ctrl AS (
c.tenant_id,
c.name,
c.description,
c.status,
c.exclusion_justification,
c.best_practice,
c.created_at,
c.updated_at,
@@ -390,8 +378,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -471,8 +457,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -567,8 +551,6 @@ WITH ctrl AS (
c.tenant_id,
c.name,
c.description,
c.status,
c.exclusion_justification,
c.best_practice,
c.created_at,
c.updated_at,
@@ -587,8 +569,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -635,8 +615,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -685,8 +663,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -739,8 +715,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -783,8 +757,6 @@ INSERT INTO
section_title,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -797,8 +769,6 @@ VALUES (
@section_title,
@name,
@description,
@status,
@exclusion_justification,
@best_practice,
@created_at,
@updated_at
@@ -806,18 +776,16 @@ VALUES (
`
args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(),
"control_id": c.ID,
"organization_id": c.OrganizationID,
"framework_id": c.FrameworkID,
"section_title": c.SectionTitle,
"name": c.Name,
"description": c.Description,
"status": c.Status,
"exclusion_justification": c.ExclusionJustification,
"best_practice": c.BestPractice,
"created_at": c.CreatedAt,
"updated_at": c.UpdatedAt,
"tenant_id": scope.GetTenantID(),
"control_id": c.ID,
"organization_id": c.OrganizationID,
"framework_id": c.FrameworkID,
"section_title": c.SectionTitle,
"name": c.Name,
"description": c.Description,
"best_practice": c.BestPractice,
"created_at": c.CreatedAt,
"updated_at": c.UpdatedAt,
}
_, err := conn.Exec(ctx, q, args)
@@ -866,8 +834,6 @@ UPDATE controls SET
name = @name,
description = @description,
section_title = @section_title,
status = @status,
exclusion_justification = @exclusion_justification,
best_practice = @best_practice,
updated_at = @updated_at
WHERE %s
@@ -876,14 +842,12 @@ WHERE %s
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"control_id": c.ID,
"name": c.Name,
"description": c.Description,
"section_title": c.SectionTitle,
"status": c.Status,
"exclusion_justification": c.ExclusionJustification,
"best_practice": c.BestPractice,
"updated_at": c.UpdatedAt,
"control_id": c.ID,
"name": c.Name,
"description": c.Description,
"section_title": c.SectionTitle,
"best_practice": c.BestPractice,
"updated_at": c.UpdatedAt,
}
maps.Copy(args, scope.SQLArguments())
@@ -963,8 +927,6 @@ WITH ctrl AS (
c.tenant_id,
c.name,
c.description,
c.status,
c.exclusion_justification,
c.best_practice,
c.created_at,
c.updated_at,
@@ -983,8 +945,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at
@@ -1077,8 +1037,6 @@ WITH ctrl AS (
c.tenant_id,
c.name,
c.description,
c.status,
c.exclusion_justification,
c.best_practice,
c.created_at,
c.updated_at,
@@ -1097,8 +1055,6 @@ SELECT
organization_id,
name,
description,
status,
exclusion_justification,
best_practice,
created_at,
updated_at

View File

@@ -1,59 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package coredata
import (
"database/sql/driver"
"fmt"
)
type ControlStatus string
const (
ControlStatusIncluded ControlStatus = "INCLUDED"
ControlStatusExcluded ControlStatus = "EXCLUDED"
)
func ControlStatuses() []ControlStatus {
return []ControlStatus{
ControlStatusIncluded,
ControlStatusExcluded,
}
}
func (cs ControlStatus) String() string {
return string(cs)
}
func (cs *ControlStatus) Scan(value interface{}) error {
switch v := value.(type) {
case string:
switch v {
case "INCLUDED":
*cs = ControlStatusIncluded
case "EXCLUDED":
*cs = ControlStatusExcluded
default:
return fmt.Errorf("invalid ControlStatus value: %q", v)
}
default:
return fmt.Errorf("unsupported type for ControlStatus: %T", value)
}
return nil
}
func (cs ControlStatus) Value() (driver.Value, error) {
return cs.String(), nil
}

View File

@@ -88,7 +88,7 @@ func (states DocumentVersionSignatureStates) Value() (driver.Value, error) {
if i > 0 {
result.WriteString(",")
}
result.WriteString(fmt.Sprintf("%q", state.String()))
fmt.Fprintf(&result, "%q", state.String())
}
result.WriteString("}")
return result.String(), nil

View File

@@ -21,7 +21,7 @@ import (
)
type (
InvitationStatus string
InvitationStatus string
InvitationStatuses []InvitationStatus
)
@@ -74,7 +74,7 @@ func (statuses InvitationStatuses) Value() (driver.Value, error) {
if i > 0 {
result.WriteString(",")
}
result.WriteString(fmt.Sprintf("%q", status.String()))
fmt.Fprintf(&result, "%q", status.String())
}
result.WriteString("}")
return result.String(), nil

View File

@@ -0,0 +1,6 @@
ALTER TABLE controls ALTER COLUMN status DROP NOT NULL;
-- TODO: drop columns and type once all code references are fully removed
-- ALTER TABLE controls DROP COLUMN status;
-- ALTER TABLE controls DROP COLUMN exclusion_justification;
-- DROP TYPE control_status;

View File

@@ -105,8 +105,7 @@ const (
ActionFrameworkCreate = "core:framework:create"
ActionFrameworkUpdate = "core:framework:update"
ActionFrameworkDelete = "core:framework:delete"
ActionFrameworkStateOfApplicabilityGenerate = "core:framework:generate-state-of-applicability"
ActionFrameworkExport = "core:framework:export"
ActionFrameworkExport = "core:framework:export"
ActionFrameworkImport = "core:framework:import"
// Control actions

View File

@@ -32,24 +32,20 @@ type (
}
CreateControlRequest struct {
ID gid.GID
FrameworkID gid.GID
Name string
Description *string
SectionTitle string
Status *coredata.ControlStatus
ExclusionJustification *string
BestPractice bool
ID gid.GID
FrameworkID gid.GID
Name string
Description *string
SectionTitle string
BestPractice bool
}
UpdateControlRequest struct {
ID gid.GID
Name *string
Description **string
SectionTitle *string
Status *coredata.ControlStatus
ExclusionJustification *string
BestPractice *bool
ID gid.GID
Name *string
Description **string
SectionTitle *string
BestPractice *bool
}
)
@@ -60,8 +56,6 @@ func (ccr *CreateControlRequest) Validate() error {
v.Check(ccr.Name, "name", validator.Required(), validator.SafeTextNoNewLine(TitleMaxLength))
v.Check(ccr.Description, "description", validator.Required(), validator.SafeText(ContentMaxLength))
v.Check(ccr.SectionTitle, "section_title", validator.Required(), validator.SafeTextNoNewLine(TitleMaxLength))
v.Check(ccr.Status, "status", validator.Required(), validator.OneOfSlice(coredata.ControlStatuses()))
v.Check(ccr.ExclusionJustification, "exclusion_justification", validator.SafeText(TitleMaxLength))
return v.Error()
}
@@ -73,8 +67,6 @@ func (ucr *UpdateControlRequest) Validate() error {
v.Check(ucr.Name, "name", validator.SafeTextNoNewLine(TitleMaxLength))
v.Check(ucr.Description, "description", validator.SafeText(ContentMaxLength))
v.Check(ucr.SectionTitle, "section_title", validator.SafeTextNoNewLine(TitleMaxLength))
v.Check(ucr.Status, "status", validator.OneOfSlice(coredata.ControlStatuses()))
v.Check(ucr.ExclusionJustification, "exclusion_justification", validator.SafeText(TitleMaxLength))
return v.Error()
}
@@ -839,16 +831,14 @@ func (s ControlService) Create(
framework := &coredata.Framework{}
control := &coredata.Control{
ID: gid.New(s.svc.scope.GetTenantID(), coredata.ControlEntityType),
FrameworkID: req.FrameworkID,
Name: req.Name,
Description: req.Description,
SectionTitle: req.SectionTitle,
Status: *req.Status,
ExclusionJustification: req.ExclusionJustification,
BestPractice: req.BestPractice,
CreatedAt: now,
UpdatedAt: now,
ID: gid.New(s.svc.scope.GetTenantID(), coredata.ControlEntityType),
FrameworkID: req.FrameworkID,
Name: req.Name,
Description: req.Description,
SectionTitle: req.SectionTitle,
BestPractice: req.BestPractice,
CreatedAt: now,
UpdatedAt: now,
}
err := s.svc.pg.WithTx(
@@ -921,14 +911,6 @@ func (s ControlService) Update(
control.SectionTitle = *req.SectionTitle
}
if req.Status != nil {
control.Status = *req.Status
}
if req.ExclusionJustification != nil {
control.ExclusionJustification = req.ExclusionJustification
}
if req.BestPractice != nil {
control.BestPractice = *req.BestPractice
}

View File

@@ -36,12 +36,10 @@ import (
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/slug"
"go.probo.inc/probo/pkg/soagen"
"go.probo.inc/probo/pkg/validator"
)
const (
maxStateOfApplicabilityLimit = 10_000
frameworkExportEmailExpiresIn = 24 * time.Hour
)
@@ -584,7 +582,6 @@ func (s FrameworkService) Import(
SectionTitle: control.ID,
Name: control.Name,
Description: &description,
Status: coredata.ControlStatusIncluded,
BestPractice: bestPractice,
CreatedAt: now,
UpdatedAt: now,
@@ -605,182 +602,6 @@ func (s FrameworkService) Import(
return framework, nil
}
func (s FrameworkService) StateOfApplicability(ctx context.Context, frameworkID gid.GID) ([]byte, error) {
rows := []soagen.SOARowData{}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
framework := &coredata.Framework{}
if err := framework.LoadByID(ctx, conn, s.svc.scope, frameworkID); err != nil {
return fmt.Errorf("cannot load framework: %w", err)
}
controls := coredata.Controls{}
err := controls.LoadByFrameworkID(
ctx,
conn,
s.svc.scope,
frameworkID,
page.NewCursor(
maxStateOfApplicabilityLimit,
nil,
page.Head,
page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldSectionTitle,
Direction: page.OrderDirectionAsc,
},
),
coredata.NewControlFilter(nil),
)
if err != nil {
return fmt.Errorf("cannot load controls: %w", err)
}
for _, control := range controls {
exclusionJustification := ""
if control.Status == coredata.ControlStatusExcluded {
if control.ExclusionJustification == nil {
return fmt.Errorf("exclusion justification is required for excluded controls")
}
exclusionJustification = *control.ExclusionJustification
}
applicability := soagen.NewApplicability("Yes", true)
if control.Status == coredata.ControlStatusExcluded {
applicability = soagen.NewApplicability("No", false)
}
bestPractice := ref.Ref(true)
if control.Status == coredata.ControlStatusExcluded {
bestPractice = ref.Ref(false)
}
row := soagen.SOARowData{
SectionTitle: control.SectionTitle,
ControlName: control.Name,
Applicability: applicability,
ExclusionJustification: exclusionJustification,
Regulatory: ref.Ref(false),
Contractual: ref.Ref(false),
BestPractice: bestPractice,
RiskAssessment: ref.Ref(false),
SecurityMeasures: []string{},
}
if control.Status == coredata.ControlStatusExcluded {
rows = append(rows, row)
continue
}
measures := coredata.Measures{}
err = measures.LoadByControlID(
ctx,
conn,
s.svc.scope,
control.ID,
page.NewCursor(
maxStateOfApplicabilityLimit,
nil,
page.Head,
page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc,
},
),
coredata.NewMeasureFilter(nil, nil),
)
if err != nil {
return fmt.Errorf("cannot load measures: %w", err)
}
for _, measure := range measures {
risks := coredata.Risks{}
var nilSnapshotID *gid.GID = nil
risksCount, err := risks.CountByMeasureID(
ctx,
conn,
s.svc.scope,
measure.ID,
coredata.NewRiskFilter(nil, &nilSnapshotID),
)
if err != nil {
return fmt.Errorf("cannot count risks: %w", err)
}
if risksCount > 0 {
row.RiskAssessment = ref.Ref(true)
}
row.SecurityMeasures = append(row.SecurityMeasures, measure.Name)
}
documents := coredata.Documents{}
err = documents.LoadByControlID(
ctx,
conn,
s.svc.scope,
control.ID,
page.NewCursor(
0,
nil,
page.Head,
page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc,
},
),
coredata.NewDocumentFilter(nil),
)
if err != nil {
return fmt.Errorf("cannot load documents: %w", err)
}
for _, document := range documents {
risks := coredata.Risks{}
var nilSnapshotID *gid.GID = nil
risksCount, err := risks.CountByDocumentID(
ctx,
conn,
s.svc.scope,
document.ID,
coredata.NewRiskFilter(nil, &nilSnapshotID),
)
if err != nil {
return fmt.Errorf("cannot count risks: %w", err)
}
if risksCount > 0 {
row.RiskAssessment = ref.Ref(true)
}
row.SecurityMeasures = append(row.SecurityMeasures, document.Title)
}
rows = append(rows, row)
}
return nil
},
)
if err != nil {
return nil, err
}
output, err := soagen.GenerateExcel(
soagen.SOAData{
Rows: rows,
},
)
if err != nil {
return nil, fmt.Errorf("cannot generate Excel file: %w", err)
}
return output, nil
}
func (s FrameworkService) SendExportEmail(
ctx context.Context,
fileID gid.GID,

View File

@@ -1030,14 +1030,6 @@ enum DataClassification
)
}
enum ControlStatus
@goModel(model: "go.probo.inc/probo/pkg/coredata.ControlStatus") {
INCLUDED
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ControlStatusIncluded")
EXCLUDED
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ControlStatusExcluded")
}
enum AuditOrderField
@goModel(model: "go.probo.inc/probo/pkg/coredata.AuditOrderField") {
CREATED_AT
@@ -2051,8 +2043,6 @@ type Control implements Node {
sectionTitle: String!
name: String!
description: String
status: ControlStatus!
exclusionJustification: String
bestPractice: Boolean!
regulatory: Boolean! @goField(forceResolver: true)
contractual: Boolean! @goField(forceResolver: true)
@@ -3287,9 +3277,6 @@ type Mutation {
updateFramework(input: UpdateFrameworkInput!): UpdateFrameworkPayload!
importFramework(input: ImportFrameworkInput!): ImportFrameworkPayload!
deleteFramework(input: DeleteFrameworkInput!): DeleteFrameworkPayload!
generateFrameworkStateOfApplicability(
input: GenerateFrameworkStateOfApplicabilityInput!
): GenerateFrameworkStateOfApplicabilityPayload!
exportFramework(input: ExportFrameworkInput!): ExportFrameworkPayload!
# Control mutations
createControl(input: CreateControlInput!): CreateControlPayload!
@@ -3576,14 +3563,6 @@ type Mutation {
}
# Input Types
input GenerateFrameworkStateOfApplicabilityInput {
frameworkId: ID!
}
type GenerateFrameworkStateOfApplicabilityPayload {
data: String!
}
input UpdateOrganizationContextInput {
organizationId: ID!
summary: String @goField(omittable: true)
@@ -4146,8 +4125,6 @@ input CreateControlInput {
sectionTitle: String!
name: String!
description: String
status: ControlStatus!
exclusionJustification: String
bestPractice: Boolean!
}
@@ -4156,8 +4133,6 @@ input UpdateControlInput {
sectionTitle: String
name: String
description: String @goField(omittable: true)
status: ControlStatus
exclusionJustification: String
bestPractice: Boolean
}

View File

@@ -258,26 +258,24 @@ type ComplexityRoot struct {
}
Control struct {
Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) int
BestPractice func(childComplexity int) int
Contractual func(childComplexity int) int
CreatedAt func(childComplexity int) int
Description func(childComplexity int) int
Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) int
ExclusionJustification func(childComplexity int) int
Framework func(childComplexity int) int
ID func(childComplexity int) int
Measures func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) int
Name func(childComplexity int) int
Obligations func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ObligationOrderBy, filter *types.ObligationFilter) int
Organization func(childComplexity int) int
Permission func(childComplexity int, action string) int
Regulatory func(childComplexity int) int
RiskAssessment func(childComplexity int) int
SectionTitle func(childComplexity int) int
Snapshots func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SnapshotOrderBy) int
Status func(childComplexity int) int
UpdatedAt func(childComplexity int) int
Audits func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) int
BestPractice func(childComplexity int) int
Contractual func(childComplexity int) int
CreatedAt func(childComplexity int) int
Description func(childComplexity int) int
Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) int
Framework func(childComplexity int) int
ID func(childComplexity int) int
Measures func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) int
Name func(childComplexity int) int
Obligations func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ObligationOrderBy, filter *types.ObligationFilter) int
Organization func(childComplexity int) int
Permission func(childComplexity int, action string) int
Regulatory func(childComplexity int) int
RiskAssessment func(childComplexity int) int
SectionTitle func(childComplexity int) int
Snapshots func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SnapshotOrderBy) int
UpdatedAt func(childComplexity int) int
}
ControlConnection struct {
@@ -873,10 +871,6 @@ type ComplexityRoot struct {
Changelog func(childComplexity int) int
}
GenerateFrameworkStateOfApplicabilityPayload struct {
Data func(childComplexity int) int
}
GetTrustCenterFilePayload struct {
TrustCenterFile func(childComplexity int) int
}
@@ -1034,7 +1028,6 @@ type ComplexityRoot struct {
ExportStateOfApplicabilityPDF func(childComplexity int, input types.ExportStateOfApplicabilityPDFInput) int
ExportTransferImpactAssessmentsPDF func(childComplexity int, input types.ExportTransferImpactAssessmentsPDFInput) int
GenerateDocumentChangelog func(childComplexity int, input types.GenerateDocumentChangelogInput) int
GenerateFrameworkStateOfApplicability func(childComplexity int, input types.GenerateFrameworkStateOfApplicabilityInput) int
GetTrustCenterFile func(childComplexity int, input types.GetTrustCenterFileInput) int
ImportFramework func(childComplexity int, input types.ImportFrameworkInput) int
ImportMeasure func(childComplexity int, input types.ImportMeasureInput) int
@@ -2164,7 +2157,6 @@ type MutationResolver interface {
UpdateFramework(ctx context.Context, input types.UpdateFrameworkInput) (*types.UpdateFrameworkPayload, error)
ImportFramework(ctx context.Context, input types.ImportFrameworkInput) (*types.ImportFrameworkPayload, error)
DeleteFramework(ctx context.Context, input types.DeleteFrameworkInput) (*types.DeleteFrameworkPayload, error)
GenerateFrameworkStateOfApplicability(ctx context.Context, input types.GenerateFrameworkStateOfApplicabilityInput) (*types.GenerateFrameworkStateOfApplicabilityPayload, error)
ExportFramework(ctx context.Context, input types.ExportFrameworkInput) (*types.ExportFrameworkPayload, error)
CreateControl(ctx context.Context, input types.CreateControlInput) (*types.CreateControlPayload, error)
UpdateControl(ctx context.Context, input types.UpdateControlInput) (*types.UpdateControlPayload, error)
@@ -3104,12 +3096,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Control.Documents(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.DocumentOrderBy), args["filter"].(*types.DocumentFilter)), true
case "Control.exclusionJustification":
if e.complexity.Control.ExclusionJustification == nil {
break
}
return e.complexity.Control.ExclusionJustification(childComplexity), true
case "Control.framework":
if e.complexity.Control.Framework == nil {
break
@@ -3196,12 +3182,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Control.Snapshots(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.SnapshotOrderBy)), true
case "Control.status":
if e.complexity.Control.Status == nil {
break
}
return e.complexity.Control.Status(childComplexity), true
case "Control.updatedAt":
if e.complexity.Control.UpdatedAt == nil {
break
@@ -4887,13 +4867,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.GenerateDocumentChangelogPayload.Changelog(childComplexity), true
case "GenerateFrameworkStateOfApplicabilityPayload.data":
if e.complexity.GenerateFrameworkStateOfApplicabilityPayload.Data == nil {
break
}
return e.complexity.GenerateFrameworkStateOfApplicabilityPayload.Data(childComplexity), true
case "GetTrustCenterFilePayload.trustCenterFile":
if e.complexity.GetTrustCenterFilePayload.TrustCenterFile == nil {
break
@@ -6182,17 +6155,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Mutation.GenerateDocumentChangelog(childComplexity, args["input"].(types.GenerateDocumentChangelogInput)), true
case "Mutation.generateFrameworkStateOfApplicability":
if e.complexity.Mutation.GenerateFrameworkStateOfApplicability == nil {
break
}
args, err := ec.field_Mutation_generateFrameworkStateOfApplicability_args(ctx, rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.GenerateFrameworkStateOfApplicability(childComplexity, args["input"].(types.GenerateFrameworkStateOfApplicabilityInput)), true
case "Mutation.getTrustCenterFile":
if e.complexity.Mutation.GetTrustCenterFile == nil {
break
@@ -10419,7 +10381,6 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputExportTransferImpactAssessmentsPDFInput,
ec.unmarshalInputFrameworkOrder,
ec.unmarshalInputGenerateDocumentChangelogInput,
ec.unmarshalInputGenerateFrameworkStateOfApplicabilityInput,
ec.unmarshalInputGetTrustCenterFileInput,
ec.unmarshalInputImportFrameworkInput,
ec.unmarshalInputImportMeasureInput,
@@ -11627,14 +11588,6 @@ enum DataClassification
)
}
enum ControlStatus
@goModel(model: "go.probo.inc/probo/pkg/coredata.ControlStatus") {
INCLUDED
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ControlStatusIncluded")
EXCLUDED
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ControlStatusExcluded")
}
enum AuditOrderField
@goModel(model: "go.probo.inc/probo/pkg/coredata.AuditOrderField") {
CREATED_AT
@@ -12648,8 +12601,6 @@ type Control implements Node {
sectionTitle: String!
name: String!
description: String
status: ControlStatus!
exclusionJustification: String
bestPractice: Boolean!
regulatory: Boolean! @goField(forceResolver: true)
contractual: Boolean! @goField(forceResolver: true)
@@ -13884,9 +13835,6 @@ type Mutation {
updateFramework(input: UpdateFrameworkInput!): UpdateFrameworkPayload!
importFramework(input: ImportFrameworkInput!): ImportFrameworkPayload!
deleteFramework(input: DeleteFrameworkInput!): DeleteFrameworkPayload!
generateFrameworkStateOfApplicability(
input: GenerateFrameworkStateOfApplicabilityInput!
): GenerateFrameworkStateOfApplicabilityPayload!
exportFramework(input: ExportFrameworkInput!): ExportFrameworkPayload!
# Control mutations
createControl(input: CreateControlInput!): CreateControlPayload!
@@ -14173,14 +14121,6 @@ type Mutation {
}
# Input Types
input GenerateFrameworkStateOfApplicabilityInput {
frameworkId: ID!
}
type GenerateFrameworkStateOfApplicabilityPayload {
data: String!
}
input UpdateOrganizationContextInput {
organizationId: ID!
summary: String @goField(omittable: true)
@@ -14743,8 +14683,6 @@ input CreateControlInput {
sectionTitle: String!
name: String!
description: String
status: ControlStatus!
exclusionJustification: String
bestPractice: Boolean!
}
@@ -14753,8 +14691,6 @@ input UpdateControlInput {
sectionTitle: String
name: String
description: String @goField(omittable: true)
status: ControlStatus
exclusionJustification: String
bestPractice: Boolean
}
@@ -17835,17 +17771,6 @@ func (ec *executionContext) field_Mutation_generateDocumentChangelog_args(ctx co
return args, nil
}
func (ec *executionContext) field_Mutation_generateFrameworkStateOfApplicability_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNGenerateFrameworkStateOfApplicabilityInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityInput)
if err != nil {
return nil, err
}
args["input"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_getTrustCenterFile_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -20211,10 +20136,6 @@ func (ec *executionContext) fieldContext_ApplicabilityStatement_control(_ contex
return ec.fieldContext_Control_name(ctx, field)
case "description":
return ec.fieldContext_Control_description(ctx, field)
case "status":
return ec.fieldContext_Control_status(ctx, field)
case "exclusionJustification":
return ec.fieldContext_Control_exclusionJustification(ctx, field)
case "bestPractice":
return ec.fieldContext_Control_bestPractice(ctx, field)
case "regulatory":
@@ -23225,64 +23146,6 @@ func (ec *executionContext) fieldContext_Control_description(_ context.Context,
return fc, nil
}
func (ec *executionContext) _Control_status(ctx context.Context, field graphql.CollectedField, obj *types.Control) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_Control_status,
func(ctx context.Context) (any, error) {
return obj.Status, nil
},
nil,
ec.marshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus,
true,
true,
)
}
func (ec *executionContext) fieldContext_Control_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Control",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type ControlStatus does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Control_exclusionJustification(ctx context.Context, field graphql.CollectedField, obj *types.Control) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_Control_exclusionJustification,
func(ctx context.Context) (any, error) {
return obj.ExclusionJustification, nil
},
nil,
ec.marshalOString2ᚖstring,
true,
false,
)
}
func (ec *executionContext) fieldContext_Control_exclusionJustification(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Control",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type String does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Control_bestPractice(ctx context.Context, field graphql.CollectedField, obj *types.Control) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -23960,10 +23823,6 @@ func (ec *executionContext) fieldContext_ControlEdge_node(_ context.Context, fie
return ec.fieldContext_Control_name(ctx, field)
case "description":
return ec.fieldContext_Control_description(ctx, field)
case "status":
return ec.fieldContext_Control_status(ctx, field)
case "exclusionJustification":
return ec.fieldContext_Control_exclusionJustification(ctx, field)
case "bestPractice":
return ec.fieldContext_Control_bestPractice(ctx, field)
case "regulatory":
@@ -32598,35 +32457,6 @@ func (ec *executionContext) fieldContext_GenerateDocumentChangelogPayload_change
return fc, nil
}
func (ec *executionContext) _GenerateFrameworkStateOfApplicabilityPayload_data(ctx context.Context, field graphql.CollectedField, obj *types.GenerateFrameworkStateOfApplicabilityPayload) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_GenerateFrameworkStateOfApplicabilityPayload_data,
func(ctx context.Context) (any, error) {
return obj.Data, nil
},
nil,
ec.marshalNString2string,
true,
true,
)
}
func (ec *executionContext) fieldContext_GenerateFrameworkStateOfApplicabilityPayload_data(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "GenerateFrameworkStateOfApplicabilityPayload",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type String does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _GetTrustCenterFilePayload_trustCenterFile(ctx context.Context, field graphql.CollectedField, obj *types.GetTrustCenterFilePayload) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -35189,51 +35019,6 @@ func (ec *executionContext) fieldContext_Mutation_deleteFramework(ctx context.Co
return fc, nil
}
func (ec *executionContext) _Mutation_generateFrameworkStateOfApplicability(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_Mutation_generateFrameworkStateOfApplicability,
func(ctx context.Context) (any, error) {
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.Mutation().GenerateFrameworkStateOfApplicability(ctx, fc.Args["input"].(types.GenerateFrameworkStateOfApplicabilityInput))
},
nil,
ec.marshalNGenerateFrameworkStateOfApplicabilityPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityPayload,
true,
true,
)
}
func (ec *executionContext) fieldContext_Mutation_generateFrameworkStateOfApplicability(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Mutation",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "data":
return ec.fieldContext_GenerateFrameworkStateOfApplicabilityPayload_data(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type GenerateFrameworkStateOfApplicabilityPayload", field.Name)
},
}
defer func() {
if r := recover(); r != nil {
err = ec.Recover(ctx, r)
ec.Error(ctx, err)
}
}()
ctx = graphql.WithFieldContext(ctx, fc)
if fc.Args, err = ec.field_Mutation_generateFrameworkStateOfApplicability_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
return fc, nil
}
func (ec *executionContext) _Mutation_exportFramework(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -53944,10 +53729,6 @@ func (ec *executionContext) fieldContext_UpdateControlPayload_control(_ context.
return ec.fieldContext_Control_name(ctx, field)
case "description":
return ec.fieldContext_Control_description(ctx, field)
case "status":
return ec.fieldContext_Control_status(ctx, field)
case "exclusionJustification":
return ec.fieldContext_Control_exclusionJustification(ctx, field)
case "bestPractice":
return ec.fieldContext_Control_bestPractice(ctx, field)
case "regulatory":
@@ -63141,7 +62922,7 @@ func (ec *executionContext) unmarshalInputCreateControlInput(ctx context.Context
asMap[k] = v
}
fieldsInOrder := [...]string{"frameworkId", "sectionTitle", "name", "description", "status", "exclusionJustification", "bestPractice"}
fieldsInOrder := [...]string{"frameworkId", "sectionTitle", "name", "description", "bestPractice"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
@@ -63176,20 +62957,6 @@ func (ec *executionContext) unmarshalInputCreateControlInput(ctx context.Context
return it, err
}
it.Description = data
case "status":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
data, err := ec.unmarshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx, v)
if err != nil {
return it, err
}
it.Status = data
case "exclusionJustification":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("exclusionJustification"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.ExclusionJustification = data
case "bestPractice":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("bestPractice"))
data, err := ec.unmarshalNBoolean2bool(ctx, v)
@@ -66924,33 +66691,6 @@ func (ec *executionContext) unmarshalInputGenerateDocumentChangelogInput(ctx con
return it, nil
}
func (ec *executionContext) unmarshalInputGenerateFrameworkStateOfApplicabilityInput(ctx context.Context, obj any) (types.GenerateFrameworkStateOfApplicabilityInput, error) {
var it types.GenerateFrameworkStateOfApplicabilityInput
asMap := map[string]any{}
for k, v := range obj.(map[string]any) {
asMap[k] = v
}
fieldsInOrder := [...]string{"frameworkId"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
continue
}
switch k {
case "frameworkId":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("frameworkId"))
data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
if err != nil {
return it, err
}
it.FrameworkID = data
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputGetTrustCenterFileInput(ctx context.Context, obj any) (types.GetTrustCenterFileInput, error) {
var it types.GetTrustCenterFileInput
asMap := map[string]any{}
@@ -68231,7 +67971,7 @@ func (ec *executionContext) unmarshalInputUpdateControlInput(ctx context.Context
asMap[k] = v
}
fieldsInOrder := [...]string{"id", "sectionTitle", "name", "description", "status", "exclusionJustification", "bestPractice"}
fieldsInOrder := [...]string{"id", "sectionTitle", "name", "description", "bestPractice"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
@@ -68266,20 +68006,6 @@ func (ec *executionContext) unmarshalInputUpdateControlInput(ctx context.Context
return it, err
}
it.Description = graphql.OmittableOf(data)
case "status":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
data, err := ec.unmarshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx, v)
if err != nil {
return it, err
}
it.Status = data
case "exclusionJustification":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("exclusionJustification"))
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
it.ExclusionJustification = data
case "bestPractice":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("bestPractice"))
data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v)
@@ -72533,13 +72259,6 @@ func (ec *executionContext) _Control(ctx context.Context, sel ast.SelectionSet,
}
case "description":
out.Values[i] = ec._Control_description(ctx, field, obj)
case "status":
out.Values[i] = ec._Control_status(ctx, field, obj)
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "exclusionJustification":
out.Values[i] = ec._Control_exclusionJustification(ctx, field, obj)
case "bestPractice":
out.Values[i] = ec._Control_bestPractice(ctx, field, obj)
if out.Values[i] == graphql.Null {
@@ -79243,45 +78962,6 @@ func (ec *executionContext) _GenerateDocumentChangelogPayload(ctx context.Contex
return out
}
var generateFrameworkStateOfApplicabilityPayloadImplementors = []string{"GenerateFrameworkStateOfApplicabilityPayload"}
func (ec *executionContext) _GenerateFrameworkStateOfApplicabilityPayload(ctx context.Context, sel ast.SelectionSet, obj *types.GenerateFrameworkStateOfApplicabilityPayload) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, generateFrameworkStateOfApplicabilityPayloadImplementors)
out := graphql.NewFieldSet(fields)
deferred := make(map[string]*graphql.FieldSet)
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("GenerateFrameworkStateOfApplicabilityPayload")
case "data":
out.Values[i] = ec._GenerateFrameworkStateOfApplicabilityPayload_data(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch(ctx)
if out.Invalids > 0 {
return graphql.Null
}
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
for label, dfs := range deferred {
ec.processDeferredGroup(graphql.DeferredGroup{
Label: label,
Path: graphql.GetPath(ctx),
FieldSet: dfs,
Context: ctx,
})
}
return out
}
var getTrustCenterFilePayloadImplementors = []string{"GetTrustCenterFilePayload"}
func (ec *executionContext) _GetTrustCenterFilePayload(ctx context.Context, sel ast.SelectionSet, obj *types.GetTrustCenterFilePayload) graphql.Marshaler {
@@ -80277,13 +79957,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "generateFrameworkStateOfApplicability":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_generateFrameworkStateOfApplicability(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "exportFramework":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_exportFramework(ctx, field)
@@ -93049,34 +92722,6 @@ var (
}
)
func (ec *executionContext) unmarshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx context.Context, v any) (coredata.ControlStatus, error) {
tmp, err := graphql.UnmarshalString(v)
res := unmarshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus[tmp]
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx context.Context, sel ast.SelectionSet, v coredata.ControlStatus) graphql.Marshaler {
_ = sel
res := graphql.MarshalString(marshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus[v])
if res == graphql.Null {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
}
}
return res
}
var (
unmarshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus = map[string]coredata.ControlStatus{
"INCLUDED": coredata.ControlStatusIncluded,
"EXCLUDED": coredata.ControlStatusExcluded,
}
marshalNControlStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus = map[coredata.ControlStatus]string{
coredata.ControlStatusIncluded: "INCLUDED",
coredata.ControlStatusExcluded: "EXCLUDED",
}
)
func (ec *executionContext) unmarshalNCountryCode2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐCountryCode(ctx context.Context, v any) (coredata.CountryCode, error) {
tmp, err := graphql.UnmarshalString(v)
res := unmarshalNCountryCode2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐCountryCode[tmp]
@@ -96474,25 +96119,6 @@ func (ec *executionContext) marshalNGenerateDocumentChangelogPayload2ᚖgoᚗpro
return ec._GenerateDocumentChangelogPayload(ctx, sel, v)
}
func (ec *executionContext) unmarshalNGenerateFrameworkStateOfApplicabilityInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityInput(ctx context.Context, v any) (types.GenerateFrameworkStateOfApplicabilityInput, error) {
res, err := ec.unmarshalInputGenerateFrameworkStateOfApplicabilityInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNGenerateFrameworkStateOfApplicabilityPayload2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityPayload(ctx context.Context, sel ast.SelectionSet, v types.GenerateFrameworkStateOfApplicabilityPayload) graphql.Marshaler {
return ec._GenerateFrameworkStateOfApplicabilityPayload(ctx, sel, &v)
}
func (ec *executionContext) marshalNGenerateFrameworkStateOfApplicabilityPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGenerateFrameworkStateOfApplicabilityPayload(ctx context.Context, sel ast.SelectionSet, v *types.GenerateFrameworkStateOfApplicabilityPayload) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
}
return graphql.Null
}
return ec._GenerateFrameworkStateOfApplicabilityPayload(ctx, sel, v)
}
func (ec *executionContext) unmarshalNGetTrustCenterFileInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐGetTrustCenterFileInput(ctx context.Context, v any) (types.GetTrustCenterFileInput, error) {
res, err := ec.unmarshalInputGetTrustCenterFileInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
@@ -101595,36 +101221,6 @@ func (ec *executionContext) unmarshalOControlOrder2ᚖgoᚗproboᚗincᚋprobo
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) unmarshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx context.Context, v any) (*coredata.ControlStatus, error) {
if v == nil {
return nil, nil
}
tmp, err := graphql.UnmarshalString(v)
res := unmarshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus[tmp]
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus(ctx context.Context, sel ast.SelectionSet, v *coredata.ControlStatus) graphql.Marshaler {
if v == nil {
return graphql.Null
}
_ = sel
_ = ctx
res := graphql.MarshalString(marshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus[*v])
return res
}
var (
unmarshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus = map[string]coredata.ControlStatus{
"INCLUDED": coredata.ControlStatusIncluded,
"EXCLUDED": coredata.ControlStatusExcluded,
}
marshalOControlStatus2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐControlStatus = map[coredata.ControlStatus]string{
coredata.ControlStatusIncluded: "INCLUDED",
coredata.ControlStatusExcluded: "EXCLUDED",
}
)
func (ec *executionContext) unmarshalOCountryCode2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐCountryCodeᚄ(ctx context.Context, v any) ([]coredata.CountryCode, error) {
if v == nil {
return nil, nil

View File

@@ -57,13 +57,11 @@ func NewControl(control *coredata.Control) *Control {
Framework: &Framework{
ID: control.FrameworkID,
},
SectionTitle: control.SectionTitle,
Name: control.Name,
Description: control.Description,
Status: control.Status,
ExclusionJustification: control.ExclusionJustification,
BestPractice: control.BestPractice,
CreatedAt: control.CreatedAt,
UpdatedAt: control.UpdatedAt,
SectionTitle: control.SectionTitle,
Name: control.Name,
Description: control.Description,
BestPractice: control.BestPractice,
CreatedAt: control.CreatedAt,
UpdatedAt: control.UpdatedAt,
}
}

View File

@@ -179,26 +179,24 @@ type ContinualImprovementFilter struct {
}
type Control struct {
ID gid.GID `json:"id"`
Organization *Organization `json:"organization,omitempty"`
SectionTitle string `json:"sectionTitle"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
Status coredata.ControlStatus `json:"status"`
ExclusionJustification *string `json:"exclusionJustification,omitempty"`
BestPractice bool `json:"bestPractice"`
Regulatory bool `json:"regulatory"`
Contractual bool `json:"contractual"`
RiskAssessment bool `json:"riskAssessment"`
Framework *Framework `json:"framework"`
Measures *MeasureConnection `json:"measures"`
Documents *DocumentConnection `json:"documents"`
Audits *AuditConnection `json:"audits"`
Obligations *ObligationConnection `json:"obligations"`
Snapshots *SnapshotConnection `json:"snapshots"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Permission bool `json:"permission"`
ID gid.GID `json:"id"`
Organization *Organization `json:"organization,omitempty"`
SectionTitle string `json:"sectionTitle"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
BestPractice bool `json:"bestPractice"`
Regulatory bool `json:"regulatory"`
Contractual bool `json:"contractual"`
RiskAssessment bool `json:"riskAssessment"`
Framework *Framework `json:"framework"`
Measures *MeasureConnection `json:"measures"`
Documents *DocumentConnection `json:"documents"`
Audits *AuditConnection `json:"audits"`
Obligations *ObligationConnection `json:"obligations"`
Snapshots *SnapshotConnection `json:"snapshots"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Permission bool `json:"permission"`
}
func (Control) IsNode() {}
@@ -288,13 +286,11 @@ type CreateControlDocumentMappingPayload struct {
}
type CreateControlInput struct {
FrameworkID gid.GID `json:"frameworkId"`
SectionTitle string `json:"sectionTitle"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
Status coredata.ControlStatus `json:"status"`
ExclusionJustification *string `json:"exclusionJustification,omitempty"`
BestPractice bool `json:"bestPractice"`
FrameworkID gid.GID `json:"frameworkId"`
SectionTitle string `json:"sectionTitle"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
BestPractice bool `json:"bestPractice"`
}
type CreateControlMeasureMappingInput struct {
@@ -1334,14 +1330,6 @@ type GenerateDocumentChangelogPayload struct {
Changelog string `json:"changelog"`
}
type GenerateFrameworkStateOfApplicabilityInput struct {
FrameworkID gid.GID `json:"frameworkId"`
}
type GenerateFrameworkStateOfApplicabilityPayload struct {
Data string `json:"data"`
}
type GetTrustCenterFileInput struct {
ID gid.GID `json:"id"`
}
@@ -1994,13 +1982,11 @@ type UpdateContinualImprovementPayload struct {
}
type UpdateControlInput struct {
ID gid.GID `json:"id"`
SectionTitle *string `json:"sectionTitle,omitempty"`
Name *string `json:"name,omitempty"`
Description graphql.Omittable[*string] `json:"description,omitempty"`
Status *coredata.ControlStatus `json:"status,omitempty"`
ExclusionJustification *string `json:"exclusionJustification,omitempty"`
BestPractice *bool `json:"bestPractice,omitempty"`
ID gid.GID `json:"id"`
SectionTitle *string `json:"sectionTitle,omitempty"`
Name *string `json:"name,omitempty"`
Description graphql.Omittable[*string] `json:"description,omitempty"`
BestPractice *bool `json:"bestPractice,omitempty"`
}
type UpdateControlPayload struct {

View File

@@ -2511,28 +2511,6 @@ func (r *mutationResolver) DeleteFramework(ctx context.Context, input types.Dele
}, nil
}
// GenerateFrameworkStateOfApplicability is the resolver for the generateFrameworkStateOfApplicability field.
func (r *mutationResolver) GenerateFrameworkStateOfApplicability(ctx context.Context, input types.GenerateFrameworkStateOfApplicabilityInput) (*types.GenerateFrameworkStateOfApplicabilityPayload, error) {
if err := r.authorize(ctx, input.FrameworkID, probo.ActionFrameworkStateOfApplicabilityGenerate); err != nil {
return nil, err
}
prb := r.ProboService(ctx, input.FrameworkID.TenantID())
soa, err := prb.Frameworks.StateOfApplicability(ctx, input.FrameworkID)
if err != nil {
// TODO no panic use gqlutils.InternalError
panic(fmt.Errorf("cannot generate framework SOA: %w", err))
}
return &types.GenerateFrameworkStateOfApplicabilityPayload{
Data: fmt.Sprintf(
"data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,%s",
base64.StdEncoding.EncodeToString(soa),
),
}, nil
}
// ExportFramework is the resolver for the exportFramework field.
func (r *mutationResolver) ExportFramework(ctx context.Context, input types.ExportFrameworkInput) (*types.ExportFrameworkPayload, error) {
if err := r.authorize(ctx, input.FrameworkID, probo.ActionFrameworkExport); err != nil {
@@ -2569,13 +2547,11 @@ func (r *mutationResolver) CreateControl(ctx context.Context, input types.Create
control, err := prb.Controls.Create(
ctx,
probo.CreateControlRequest{
FrameworkID: input.FrameworkID,
Name: input.Name,
Description: input.Description,
SectionTitle: input.SectionTitle,
Status: &input.Status,
ExclusionJustification: input.ExclusionJustification,
BestPractice: input.BestPractice,
FrameworkID: input.FrameworkID,
Name: input.Name,
Description: input.Description,
SectionTitle: input.SectionTitle,
BestPractice: input.BestPractice,
},
)
if err != nil {
@@ -2603,13 +2579,11 @@ func (r *mutationResolver) UpdateControl(ctx context.Context, input types.Update
control, err := prb.Controls.Update(
ctx,
probo.UpdateControlRequest{
ID: input.ID,
Name: input.Name,
Description: gqlutils.UnwrapOmittable(input.Description),
SectionTitle: input.SectionTitle,
Status: input.Status,
ExclusionJustification: input.ExclusionJustification,
BestPractice: input.BestPractice,
ID: input.ID,
Name: input.Name,
Description: gqlutils.UnwrapOmittable(input.Description),
SectionTitle: input.SectionTitle,
BestPractice: input.BestPractice,
},
)

View File

@@ -1182,12 +1182,10 @@ func (r *Resolver) AddControlTool(ctx context.Context, req *mcp.CallToolRequest,
control, err := svc.Controls.Create(
ctx,
probo.CreateControlRequest{
FrameworkID: input.FrameworkID,
Name: input.Name,
Description: input.Description,
SectionTitle: input.SectionTitle,
Status: input.Status,
ExclusionJustification: input.ExclusionJustification,
FrameworkID: input.FrameworkID,
Name: input.Name,
Description: input.Description,
SectionTitle: input.SectionTitle,
},
)
if err != nil {
@@ -1207,12 +1205,10 @@ func (r *Resolver) UpdateControlTool(ctx context.Context, req *mcp.CallToolReque
control, err := svc.Controls.Update(
ctx,
probo.UpdateControlRequest{
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
SectionTitle: input.SectionTitle,
Status: input.Status,
ExclusionJustification: input.ExclusionJustification,
ID: input.ID,
Name: input.Name,
Description: UnwrapOmittable(input.Description),
SectionTitle: input.SectionTitle,
},
)
if err != nil {

View File

@@ -2758,13 +2758,6 @@ components:
audit:
$ref: "#/components/schemas/Audit"
ControlStatus:
type: string
enum:
- INCLUDED
- EXCLUDED
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.ControlStatus
ControlOrderField:
type: string
enum:
@@ -2793,7 +2786,6 @@ components:
- framework_id
- section_title
- name
- status
- created_at
- updated_at
properties:
@@ -2817,14 +2809,6 @@ components:
- string
- "null"
description: Control description
status:
$ref: "#/components/schemas/ControlStatus"
description: Control status
exclusion_justification:
type:
- string
- "null"
description: Exclusion justification
created_at:
type: string
format: date-time
@@ -2914,12 +2898,6 @@ components:
description:
type: string
description: Control description
status:
$ref: "#/components/schemas/ControlStatus"
description: Control status
exclusion_justification:
type: string
description: Exclusion justification
AddControlOutput:
type: object
@@ -2947,16 +2925,6 @@ components:
type: ["string", "null"]
description: Control description
go.probo.inc/mcpgen/omittable: true
status:
anyOf:
- $ref: "#/components/schemas/ControlStatus"
description: Control status
- type: "null"
description: No status
description: Control status
exclusion_justification:
type: string
description: Exclusion justification
UpdateControlOutput:
type: object

View File

@@ -20,16 +20,14 @@ import (
func NewControl(c *coredata.Control) *Control {
return &Control{
ID: c.ID,
OrganizationID: c.OrganizationID,
SectionTitle: c.SectionTitle,
FrameworkID: c.FrameworkID,
Name: c.Name,
Description: c.Description,
Status: c.Status,
ExclusionJustification: c.ExclusionJustification,
CreatedAt: c.CreatedAt,
UpdatedAt: c.UpdatedAt,
ID: c.ID,
OrganizationID: c.OrganizationID,
SectionTitle: c.SectionTitle,
FrameworkID: c.FrameworkID,
Name: c.Name,
Description: c.Description,
CreatedAt: c.CreatedAt,
UpdatedAt: c.UpdatedAt,
}
}

View File

@@ -21,8 +21,8 @@ var (
AddAuditToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"audit":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"description":"Audit name"},"organization_id":{"type":"string","format":"string"},"state":{"type":"string","enum":["NOT_STARTED","IN_PROGRESS","COMPLETED","REJECTED","OUTDATED"]},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"valid_from":{"description":"Valid from date","format":"date-time"},"valid_until":{"description":"Valid until date","format":"date-time"}},"required":["id","organization_id","framework_id","state","trust_center_visibility","created_at","updated_at"]}},"required":["audit"]}`)
AddContinualImprovementToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"type":"string","description":"Description"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"description":"Priority","anyOf":[{"type":"string","enum":["LOW","MEDIUM","HIGH"]},{"type":"null","description":"No priority"}]},"reference_id":{"type":"string","description":"Reference ID"},"source":{"type":"string","description":"Source"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},{"type":"null","description":"No status"}]},"target_date":{"type":"string","description":"Target date","format":"date-time"}},"required":["organization_id","reference_id","owner_id"]}`)
AddContinualImprovementToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"continual_improvement":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Description"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"reference_id":{"type":"string","description":"Reference ID"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"target_date":{"description":"Target date","format":"date-time"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","reference_id","owner_id","status","priority","created_at","updated_at"]}},"required":["continual_improvement"]}`)
AddControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"type":"string","description":"Control description"},"exclusion_justification":{"type":"string","description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]}},"required":["organization_id","framework_id","section_title","name"]}`)
AddControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"required":["control"]}`)
AddControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"type":"string","description":"Control description"},"framework_id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"}},"required":["organization_id","framework_id","section_title","name"]}`)
AddControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","created_at","updated_at"]}},"required":["control"]}`)
AddDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"vendor_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Vendor IDs"}},"required":["organization_id","name","data_classification","owner_id"]}`)
AddDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
AddDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"content":{"type":"string","description":"Document content"},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"organization_id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]}},"required":["organization_id","title","content","approver_ids","classification","document_type"]}`)
@@ -54,11 +54,11 @@ var (
DeleteDraftDocumentVersionToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"document_version_id":{"type":"string","format":"string"}},"required":["document_version_id"]}`)
DeleteDraftDocumentVersionToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_document_version_id":{"type":"string","format":"string"}},"required":["deleted_document_version_id"]}`)
DeleteMeetingToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
DeleteTaskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
DeleteTaskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_task_id":{"type":"string","format":"string"}},"required":["deleted_task_id"]}`)
DeleteMeetingToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_meeting_id":{"type":"string","format":"string"}},"required":["deleted_meeting_id"]}`)
DeleteRiskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
DeleteRiskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_risk_id":{"type":"string","format":"string"}},"required":["deleted_risk_id"]}`)
DeleteTaskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
DeleteTaskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"deleted_task_id":{"type":"string","format":"string"}},"required":["deleted_task_id"]}`)
GetAssetToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
GetAssetToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"asset":{"type":"object","properties":{"amount":{"type":"integer","description":"Asset amount"},"asset_type":{"type":"string","enum":["PHYSICAL","VIRTUAL"]},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_types_stored":{"type":"string","description":"Data types stored"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Asset name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","amount","owner_id","asset_type","data_types_stored","created_at","updated_at"]}},"required":["asset"]}`)
GetAuditToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
@@ -66,7 +66,7 @@ var (
GetContinualImprovementToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
GetContinualImprovementToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"continual_improvement":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Description"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"reference_id":{"type":"string","description":"Reference ID"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"target_date":{"description":"Target date","format":"date-time"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","reference_id","owner_id","status","priority","created_at","updated_at"]}},"required":["continual_improvement"]}`)
GetControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
GetControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"required":["control"]}`)
GetControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","created_at","updated_at"]}},"required":["control"]}`)
GetDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
GetDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
GetDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"id":{"type":"string","format":"string"}},"required":["id"]}`)
@@ -108,7 +108,7 @@ var (
ListContinualImprovementsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","REFERENCE_ID","TARGET_DATE","STATUS","PRIORITY"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
ListContinualImprovementsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"continual_improvements":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Description"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"reference_id":{"type":"string","description":"Reference ID"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"target_date":{"description":"Target date","format":"date-time"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","reference_id","owner_id","status","priority","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["continual_improvements"]}`)
ListControlsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"query":{"type":"string","description":"Search query"}}},"framework_id":{"type":"string","format":"string"},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","SECTION_TITLE"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
ListControlsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"controls":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["controls"]}`)
ListControlsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"controls":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["controls"]}`)
ListDataToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","NAME","DATA_CLASSIFICATION"]}},"required":["field","direction"]},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}},"required":["organization_id"]}`)
ListDataToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"next_cursor":{"type":"string","format":"string"}},"required":["data"]}`)
ListDocumentVersionSignaturesToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"cursor":{"type":"string","format":"string"},"document_version_id":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"active_contract":{"type":"boolean","description":"Signatory contract status"},"states":{"type":"array","items":{"type":"string","enum":["REQUESTED","SIGNED"]},"description":"Signature states"}}},"order_by":{"type":"object","properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","SIGNED_AT"]}},"required":["field","direction"]},"size":{"type":"integer","description":"Page size"}},"required":["document_version_id"]}`)
@@ -163,8 +163,8 @@ var (
UpdateAuditToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"audit":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"description":"Audit name"},"organization_id":{"type":"string","format":"string"},"state":{"type":"string","enum":["NOT_STARTED","IN_PROGRESS","COMPLETED","REJECTED","OUTDATED"]},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"},"valid_from":{"description":"Valid from date","format":"date-time"},"valid_until":{"description":"Valid until date","format":"date-time"}},"required":["id","organization_id","framework_id","state","trust_center_visibility","created_at","updated_at"]}},"required":["audit"]}`)
UpdateContinualImprovementToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"description":"Description"},"id":{"type":"string","format":"string"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"priority":{"description":"Priority","anyOf":[{"type":"string","enum":["LOW","MEDIUM","HIGH"]},{"type":"null","description":"No priority"}]},"reference_id":{"type":"string","description":"Reference ID"},"source":{"description":"Source"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},{"type":"null","description":"No status"}]},"target_date":{"description":"Target date","format":"date-time"}},"required":["id"]}`)
UpdateContinualImprovementToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"continual_improvement":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Description"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH"]},"reference_id":{"type":"string","description":"Reference ID"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"target_date":{"description":"Target date","format":"date-time"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","reference_id","owner_id","status","priority","created_at","updated_at"]}},"required":["continual_improvement"]}`)
UpdateControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"description":"Control description"},"exclusion_justification":{"type":"string","description":"Exclusion justification"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"section_title":{"type":"string","description":"Section title"},"status":{"description":"Control status","anyOf":[{"type":"string","enum":["INCLUDED","EXCLUDED"]},{"type":"null","description":"No status"}]}},"required":["id"]}`)
UpdateControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"exclusion_justification":{"description":"Exclusion justification"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"status":{"type":"string","enum":["INCLUDED","EXCLUDED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","status","created_at","updated_at"]}},"required":["control"]}`)
UpdateControlToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"description":{"description":"Control description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"section_title":{"type":"string","description":"Section title"}},"required":["id"]}`)
UpdateControlToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"control":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Control description"},"framework_id":{"type":"string","format":"string"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Control name"},"organization_id":{"type":"string","format":"string"},"section_title":{"type":"string","description":"Section title"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","framework_id","section_title","name","created_at","updated_at"]}},"required":["control"]}`)
UpdateDatumToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"vendor_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Vendor IDs"}},"required":["id"]}`)
UpdateDatumToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"datum":{"type":"object","properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"data_classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Datum name"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}},"required":["id","organization_id","name","data_classification","owner_id","created_at","updated_at"]}},"required":["datum"]}`)
UpdateDocumentToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"approver_ids":{"type":"array","items":{"type":"string","format":"string"},"description":"Approver IDs"},"classification":{"type":"string","enum":["PUBLIC","INTERNAL","CONFIDENTIAL","SECRET"]},"document_type":{"type":"string","enum":["OTHER","ISMS","POLICY","PROCEDURE"]},"id":{"type":"string","format":"string"},"title":{"type":"string","description":"Document title"},"trust_center_visibility":{"type":"string","enum":["NONE","PRIVATE","PUBLIC"]}},"required":["id"]}`)
@@ -564,8 +564,6 @@ type AddContinualImprovementOutput struct {
type AddControlInput struct {
// Control description
Description *string `json:"description,omitempty"`
// Exclusion justification
ExclusionJustification *string `json:"exclusion_justification,omitempty"`
// Framework ID
FrameworkID gid.GID `json:"framework_id"`
// Control name
@@ -574,8 +572,6 @@ type AddControlInput struct {
OrganizationID gid.GID `json:"organization_id"`
// Section title
SectionTitle string `json:"section_title"`
// Control status
Status *coredata.ControlStatus `json:"status,omitempty"`
}
// AddControlOutput represents the schema
@@ -975,8 +971,6 @@ type Control struct {
CreatedAt time.Time `json:"created_at"`
// Control description
Description *string `json:"description,omitempty"`
// Exclusion justification
ExclusionJustification *string `json:"exclusion_justification,omitempty"`
// Framework ID
FrameworkID gid.GID `json:"framework_id"`
// Control ID
@@ -987,8 +981,6 @@ type Control struct {
OrganizationID gid.GID `json:"organization_id"`
// Section title
SectionTitle string `json:"section_title"`
// Control status
Status coredata.ControlStatus `json:"status"`
// Update timestamp
UpdatedAt time.Time `json:"updated_at"`
}
@@ -1088,6 +1080,18 @@ type DeleteRiskOutput struct {
DeletedRiskID gid.GID `json:"deleted_risk_id"`
}
// DeleteTaskInput represents the schema
type DeleteTaskInput struct {
// Task ID
ID gid.GID `json:"id"`
}
// DeleteTaskOutput represents the schema
type DeleteTaskOutput struct {
// Deleted task ID
DeletedTaskID gid.GID `json:"deleted_task_id"`
}
// Document represents the schema
type Document struct {
// Approver IDs
@@ -2171,18 +2175,6 @@ type UnassignTaskOutput struct {
Task *Task `json:"task"`
}
// DeleteTaskInput represents the schema
type DeleteTaskInput struct {
// Task ID
ID gid.GID `json:"id"`
}
// DeleteTaskOutput represents the schema
type DeleteTaskOutput struct {
// Deleted task ID
DeletedTaskID gid.GID `json:"deleted_task_id"`
}
// UnlinkControlAuditInput represents the schema
type UnlinkControlAuditInput struct {
// Audit ID
@@ -2304,16 +2296,12 @@ type UpdateContinualImprovementOutput struct {
type UpdateControlInput struct {
// Control description
Description mcp.Omittable[*string] `json:"description,omitempty"`
// Exclusion justification
ExclusionJustification *string `json:"exclusion_justification,omitempty"`
// Control ID
ID gid.GID `json:"id"`
// Control name
Name *string `json:"name,omitempty"`
// Section title
SectionTitle *string `json:"section_title,omitempty"`
// Control status
Status *coredata.ControlStatus `json:"status,omitempty"`
}
// UpdateControlOutput represents the schema

View File

@@ -1,56 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package soagen
import "github.com/xuri/excelize/v2"
type Applicability struct {
Value string
IsApplicable bool
}
func NewApplicability(value string, isApplicable bool) Applicability {
return Applicability{
Value: value,
IsApplicable: isApplicable,
}
}
func (a Applicability) String() string {
return a.Value
}
func (a Applicability) MarshalExcel() ExcelValue {
color := "FFB6C1" // Light red for not applicable
if a.IsApplicable {
color = "90EE90" // Light green for applicable
}
return ExcelValue{
Value: a.Value,
Style: &excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{Type: "pattern", Color: []string{color}, Pattern: 1},
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
},
Validation: []string{"Yes", "No"},
Width: 12,
}
}

View File

@@ -1,28 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package soagen
import "github.com/xuri/excelize/v2"
type ExcelValue struct {
Value interface{}
Style *excelize.Style
Validation []string
Width float64
}
type ExcelMarshaler interface {
MarshalExcel() ExcelValue
}

View File

@@ -1,101 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package soagen
type FieldConfiguration struct {
Field string
Columns []string
FilterColumns []string // Specific columns that should have filters (subset of Columns)
Width []float64 // Width for each column
DefaultWidth float64 // Default width if not specified
HasFilter bool // Whether to enable auto-filter
}
var (
soaFieldConfigs = []FieldConfiguration{
{
Field: "SectionTitle",
Columns: []string{"A"},
FilterColumns: []string{},
Width: []float64{12},
DefaultWidth: 12,
HasFilter: false,
},
{
Field: "ControlName",
Columns: []string{"B"},
FilterColumns: []string{},
Width: []float64{35},
DefaultWidth: 35,
HasFilter: false,
},
{
Field: "Applicability",
Columns: []string{"C"},
FilterColumns: []string{"C"},
Width: []float64{12},
DefaultWidth: 12,
HasFilter: true,
},
{
Field: "ExclusionJustification",
Columns: []string{"D"},
FilterColumns: []string{},
Width: []float64{25},
DefaultWidth: 25,
HasFilter: false,
},
{
Field: "Regulatory",
Columns: []string{"E"},
FilterColumns: []string{},
Width: []float64{12},
DefaultWidth: 12,
HasFilter: false,
},
{
Field: "Contractual",
Columns: []string{"F"},
FilterColumns: []string{},
Width: []float64{12},
DefaultWidth: 12,
HasFilter: false,
},
{
Field: "BestPractice",
Columns: []string{"G"},
FilterColumns: []string{},
Width: []float64{12},
DefaultWidth: 12,
HasFilter: false,
},
{
Field: "RiskAssessment",
Columns: []string{"H"},
FilterColumns: []string{},
Width: []float64{12},
DefaultWidth: 12,
HasFilter: false,
},
{
Field: "SecurityMeasures",
Columns: []string{"I"},
FilterColumns: []string{},
Width: []float64{40},
DefaultWidth: 40,
HasFilter: false,
},
}
)

View File

@@ -1,319 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package soagen
import (
"fmt"
"strings"
"github.com/xuri/excelize/v2"
)
func GenerateSOAExcel(data SOAData) ([]byte, error) {
f := excelize.NewFile()
defer func() { _ = f.Close() }()
sheetName := "State of Applicability"
_, err := f.NewSheet(sheetName)
if err != nil {
return nil, fmt.Errorf("cannot create sheet: %w", err)
}
if err := f.DeleteSheet("Sheet1"); err != nil {
return nil, fmt.Errorf("cannot delete sheet: %w", err)
}
if err := setupSOAHeader(f, sheetName); err != nil {
return nil, fmt.Errorf("cannot setup Excel header: %w", err)
}
if err := populateSOAData(f, sheetName, data.Rows); err != nil {
return nil, fmt.Errorf("cannot populate Excel data: %w", err)
}
if err := applySOAFinalFormatting(f, sheetName, len(data.Rows)); err != nil {
return nil, fmt.Errorf("cannot apply final formatting: %w", err)
}
buf, err := f.WriteToBuffer()
if err != nil {
return nil, fmt.Errorf("cannot write Excel file to buffer: %w", err)
}
return buf.Bytes(), nil
}
func setupSOAHeader(f *excelize.File, sheetName string) error {
headerStyle, err := f.NewStyle(getHeaderStyle())
if err != nil {
return err
}
cellStyle, err := f.NewStyle(getCellStyle())
if err != nil {
return err
}
return applyHeaderLayout(f, sheetName, getSOAHeaderLayout(), headerStyle, cellStyle)
}
func populateSOAData(f *excelize.File, sheetName string, rows []SOARowData) error {
dataStartRow := 8
for i, rowData := range rows {
isFirstRow := i == 0
filterColumns, err := writeSOARow(f, sheetName, dataStartRow+i, rowData, isFirstRow)
if err != nil {
return fmt.Errorf("cannot write row %d: %w", dataStartRow+i, err)
}
if isFirstRow && len(filterColumns) > 0 {
if err := applySOAAutoFilter(f, sheetName, filterColumns); err != nil {
return fmt.Errorf("cannot apply auto filter: %w", err)
}
}
}
return nil
}
func writeSOARow(f *excelize.File, sheetName string, row int, data SOARowData, isFirstRow bool) ([]string, error) {
var allFilterColumns []string
fields := []struct {
name string
value interface{}
}{
{"SectionTitle", data.SectionTitle},
{"ControlName", data.ControlName},
{"Applicability", data.Applicability},
{"Regulatory", data.Regulatory},
{"Contractual", data.Contractual},
{"BestPractice", data.BestPractice},
{"RiskAssessment", data.RiskAssessment},
{"ExclusionJustification", data.ExclusionJustification},
{"SecurityMeasures", data.SecurityMeasures},
}
for _, field := range fields {
fieldConfig := getSOAFieldConfig(field.name)
if fieldConfig == nil {
continue
}
filterColumns, err := processField(f, sheetName, row, field.value, *fieldConfig, isFirstRow)
if err != nil {
return nil, fmt.Errorf("cannot write field %s: %w", field.name, err)
}
allFilterColumns = append(allFilterColumns, filterColumns...)
}
return allFilterColumns, nil
}
func getSOAFieldConfig(fieldName string) *FieldConfiguration {
for _, config := range soaFieldConfigs {
if config.Field == fieldName {
return &config
}
}
return nil
}
func applySOAAutoFilter(f *excelize.File, sheetName string, filterColumns []string) error {
if len(filterColumns) == 0 {
return nil
}
firstCol, lastCol := filterColumns[0], filterColumns[0]
for _, col := range filterColumns {
if col < firstCol {
firstCol = col
}
if col > lastCol {
lastCol = col
}
}
filterRange := fmt.Sprintf("%s7:%s1000", firstCol, lastCol)
return f.AutoFilter(sheetName, filterRange, []excelize.AutoFilterOptions{})
}
func applySOAFinalFormatting(f *excelize.File, sheetName string, dataRowCount int) error {
if dataRowCount > 0 {
headerRowHeight := 30.0
_ = f.SetRowHeight(sheetName, 6, headerRowHeight)
_ = f.SetRowHeight(sheetName, 7, headerRowHeight)
return f.SetPanes(sheetName, &excelize.Panes{
Freeze: true,
XSplit: 0,
YSplit: 7,
TopLeftCell: "A8",
})
}
return nil
}
func processField(f *excelize.File, sheetName string, row int, value interface{}, config FieldConfiguration, isFirstRow bool) ([]string, error) {
switch v := value.(type) {
case ExcelMarshaler:
marshaler := v
excelValue := marshaler.MarshalExcel()
styleID, err := createCellStyle(f, excelValue.Style)
if err != nil {
return nil, err
}
return writeSingleColumnField(f, sheetName, row, excelValue, &config, styleID, isFirstRow)
case string:
if len(config.Columns) == 0 {
return []string{}, nil
}
col := config.Columns[0]
cellRef := fmt.Sprintf("%s%d", col, row)
if err := f.SetCellValue(sheetName, cellRef, v); err != nil {
return nil, fmt.Errorf("cannot set cell value: %w", err)
}
textStyleID, err := createCellStyle(f, getTextStyle())
if err != nil {
return nil, fmt.Errorf("cannot create text style: %w", err)
}
if err := f.SetCellStyle(sheetName, cellRef, cellRef, textStyleID); err != nil {
return nil, fmt.Errorf("cannot set cell style: %w", err)
}
if isFirstRow {
width := config.DefaultWidth
if len(config.Width) > 0 {
width = config.Width[0]
}
if err := f.SetColWidth(sheetName, col, col, width); err != nil {
return nil, fmt.Errorf("cannot set column width: %w", err)
}
}
if config.HasFilter {
if len(config.FilterColumns) > 0 {
return config.FilterColumns, nil
}
return []string{col}, nil
}
return []string{}, nil
case []string:
var formattedLines []string
for _, item := range v {
lines := strings.Split(item, "\n")
for _, line := range lines {
if strings.TrimSpace(line) != "" {
formattedLines = append(formattedLines, "• "+strings.TrimSpace(line))
}
}
}
joinedValue := strings.Join(formattedLines, "\n")
if len(config.Columns) == 0 {
return []string{}, nil
}
col := config.Columns[0]
cellRef := fmt.Sprintf("%s%d", col, row)
if err := f.SetCellValue(sheetName, cellRef, joinedValue); err != nil {
return nil, fmt.Errorf("cannot set cell value: %w", err)
}
textStyleID, err := createCellStyle(f, getTextStyle())
if err != nil {
return nil, fmt.Errorf("cannot create text style: %w", err)
}
if err := f.SetCellStyle(sheetName, cellRef, cellRef, textStyleID); err != nil {
return nil, fmt.Errorf("cannot set cell style: %w", err)
}
if isFirstRow {
width := config.DefaultWidth
if len(config.Width) > 0 {
width = config.Width[0]
}
if err := f.SetColWidth(sheetName, col, col, width); err != nil {
return nil, fmt.Errorf("cannot set column width: %w", err)
}
}
if config.HasFilter {
if len(config.FilterColumns) > 0 {
return config.FilterColumns, nil
}
return []string{col}, nil
}
return []string{}, nil
case *bool:
yesNoValue := boolToYesNo(v)
excelValue := yesNoValue.MarshalExcel()
styleID, err := createCellStyle(f, excelValue.Style)
if err != nil {
return nil, err
}
return writeSingleColumnField(f, sheetName, row, excelValue, &config, styleID, isFirstRow)
default:
return nil, fmt.Errorf("no handler found for field type: %T", value)
}
}
func GenerateExcel(data SOAData) ([]byte, error) {
return GenerateSOAExcel(data)
}
func writeSingleColumnField(f *excelize.File, sheetName string, row int, excelValue ExcelValue, colDef *FieldConfiguration, styleID int, isFirstRow bool) ([]string, error) {
if len(colDef.Columns) == 0 {
return []string{}, nil
}
col := colDef.Columns[0]
cellRef := fmt.Sprintf("%s%d", col, row)
_ = f.SetCellValue(sheetName, cellRef, excelValue.Value)
_ = f.SetCellStyle(sheetName, cellRef, cellRef, styleID)
if isFirstRow {
if err := applyDataValidation(f, sheetName, col, row, excelValue.Validation); err != nil {
return nil, err
}
if err := setColumnWidth(f, sheetName, col, excelValue.Width); err != nil {
return nil, err
}
}
if colDef.HasFilter {
if len(colDef.FilterColumns) > 0 {
return colDef.FilterColumns, nil
}
return []string{col}, nil
}
return []string{}, nil
}

View File

@@ -1,134 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package soagen
import (
"fmt"
"time"
"github.com/xuri/excelize/v2"
)
type HeaderCell struct {
Cell string
Value string
Style string // "header" or "cell"
}
type MergedCell struct {
StartCell string
EndCell string
}
type HeaderLayout struct {
InfoHeader []HeaderCell
InfoData []HeaderCell
MainHeader []HeaderCell
SubHeader []HeaderCell
Merges []MergedCell
}
func getSOAHeaderLayout() HeaderLayout {
return HeaderLayout{
InfoHeader: []HeaderCell{
{"A2", "Version", "header"},
{"C2", "Date", "header"},
{"D2", "Comment", "header"},
{"E2", "Author", "header"},
{"F2", "Approver", "header"},
},
InfoData: []HeaderCell{
{"A3", "1.0", "cell"},
{"C3", time.Now().Format("01/02/2006"), "cell"},
{"D3", "Initial SoA", "cell"},
{"E3", "System Admin", "cell"},
{"F3", "Security Manager", "cell"},
},
MainHeader: []HeaderCell{
{"A6", "Control", "header"},
{"B6", "Control name", "header"},
{"C6", "Applicability", "header"},
{"D6", "Justification for exclusion", "header"},
{"E6", "Justification for inclusion", "header"},
{"F6", "Justification for inclusion", "header"},
{"G6", "Justification for inclusion", "header"},
{"H6", "Justification for inclusion", "header"},
{"I6", "List of security measure or policy", "header"},
},
SubHeader: []HeaderCell{
{"A7", "Control", "header"},
{"B7", "Control name", "header"},
{"C7", "Applicability", "header"},
{"D7", "Justification for exclusion", "header"},
{"E7", "Regulatory", "header"},
{"F7", "Contractual", "header"},
{"G7", "Best practice", "header"},
{"H7", "Risk assessment", "header"},
{"I7", "List of security measure or policy", "header"},
},
Merges: []MergedCell{
{"A6", "A7"},
{"B6", "B7"},
{"C6", "C7"},
{"D6", "D7"},
{"E6", "H6"},
{"I6", "I7"},
},
}
}
func applyHeaderLayout(f *excelize.File, sheetName string, layout HeaderLayout, headerStyle, cellStyle int) error {
if err := applyCells(f, sheetName, layout.InfoHeader, headerStyle, cellStyle); err != nil {
return err
}
if err := applyCells(f, sheetName, layout.InfoData, headerStyle, cellStyle); err != nil {
return err
}
if err := applyCells(f, sheetName, layout.MainHeader, headerStyle, cellStyle); err != nil {
return err
}
if err := applyCells(f, sheetName, layout.SubHeader, headerStyle, cellStyle); err != nil {
return err
}
for _, merge := range layout.Merges {
if err := f.MergeCell(sheetName, merge.StartCell, merge.EndCell); err != nil {
return err
}
}
return nil
}
func applyCells(f *excelize.File, sheetName string, cells []HeaderCell, headerStyle, cellStyle int) error {
for _, cell := range cells {
if err := f.SetCellValue(sheetName, cell.Cell, cell.Value); err != nil {
return fmt.Errorf("cannot set cell value: %w", err)
}
style := cellStyle
if cell.Style == "header" {
style = headerStyle
}
if err := f.SetCellStyle(sheetName, cell.Cell, cell.Cell, style); err != nil {
return fmt.Errorf("cannot set cell style: %w", err)
}
}
return nil
}

View File

@@ -1,33 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package soagen
// SOARowData represents a single row in the State of Applicability Excel
type SOARowData struct {
SectionTitle string
ControlName string
Applicability Applicability
Regulatory *bool
Contractual *bool
BestPractice *bool
RiskAssessment *bool
ExclusionJustification string
SecurityMeasures []string
}
// SOAData contains all the data needed for State of Applicability generation
type SOAData struct {
Rows []SOARowData
}

View File

@@ -1,95 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package soagen
import (
"fmt"
"github.com/xuri/excelize/v2"
)
// getTextStyle returns the standard text style for string fields
func getTextStyle() *excelize.Style {
return &excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "#000000", Style: 1},
{Type: "top", Color: "#000000", Style: 1},
{Type: "bottom", Color: "#000000", Style: 1},
{Type: "right", Color: "#000000", Style: 1},
},
Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center", WrapText: true},
}
}
// getHeaderStyle returns the standard header style
func getHeaderStyle() *excelize.Style {
return &excelize.Style{
Font: &excelize.Font{Bold: true, Size: 10, Color: "#000000"},
Fill: excelize.Fill{Type: "pattern", Color: []string{"#D9D9D9"}, Pattern: 1},
Border: []excelize.Border{
{Type: "left", Color: "#000000", Style: 1},
{Type: "top", Color: "#000000", Style: 1},
{Type: "bottom", Color: "#000000", Style: 1},
{Type: "right", Color: "#000000", Style: 1},
},
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
}
}
// getCellStyle returns the standard cell style
func getCellStyle() *excelize.Style {
return &excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "#000000", Style: 1},
{Type: "top", Color: "#000000", Style: 1},
{Type: "bottom", Color: "#000000", Style: 1},
{Type: "right", Color: "#000000", Style: 1},
},
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
}
}
func createCellStyle(f *excelize.File, style *excelize.Style) (int, error) {
styleID, err := f.NewStyle(style)
if err != nil {
return 0, fmt.Errorf("cannot create style: %w", err)
}
return styleID, nil
}
func applyDataValidation(f *excelize.File, sheetName, col string, row int, validation []string) error {
if len(validation) == 0 {
return nil
}
dv := excelize.NewDataValidation(true)
dv.Sqref = fmt.Sprintf("%s%d:%s1000", col, row, col) // Apply to reasonable range
_ = dv.SetDropList(validation)
dv.SetError(excelize.DataValidationErrorStyleStop, "Invalid Input", "Please select from the dropdown list.")
if err := f.AddDataValidation(sheetName, dv); err != nil {
return fmt.Errorf("cannot add data validation: %w", err)
}
return nil
}
func setColumnWidth(f *excelize.File, sheetName, col string, width float64) error {
if width > 0 {
if err := f.SetColWidth(sheetName, col, col, width); err != nil {
return fmt.Errorf("cannot set column width: %w", err)
}
}
return nil
}

View File

@@ -1,60 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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.
package soagen
import "github.com/xuri/excelize/v2"
// YesNo represents a YES/NO/Empty value
type YesNo string
const (
Yes YesNo = "YES"
No YesNo = "NO"
Empty YesNo = ""
)
// String returns the string representation of YesNo
func (yn YesNo) String() string {
return string(yn)
}
// MarshalExcel implements ExcelMarshaler for YesNo
func (yn YesNo) MarshalExcel() ExcelValue {
return ExcelValue{
Value: yn.String(),
Style: &excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "#000000", Style: 1},
{Type: "top", Color: "#000000", Style: 1},
{Type: "bottom", Color: "#000000", Style: 1},
{Type: "right", Color: "#000000", Style: 1},
},
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
},
Validation: []string{string(Yes), string(No), string(Empty)},
Width: 12,
}
}
// boolToYesNo converts *bool to YesNo type for Excel output
func boolToYesNo(b *bool) YesNo {
if b == nil {
return Empty
}
if *b {
return Yes
}
return No
}

View File

@@ -154,8 +154,7 @@ func TestValidationErrors_Methods(t *testing.T) {
first := errors.First()
if first == nil {
t.Fatal("expected first error")
}
if first.Field != "email" {
} else if first.Field != "email" {
t.Errorf("expected first field to be 'email', got '%s'", first.Field)
}
})

View File

@@ -40,8 +40,7 @@ func TestMinItems(t *testing.T) {
err := MinItems(2)(&items)
if err == nil {
t.Fatal("expected validation error")
}
if err.Code != ErrorCodeOutOfRange {
} else if err.Code != ErrorCodeOutOfRange {
t.Errorf("expected error code %s, got %s", ErrorCodeOutOfRange, err.Code)
}
})
@@ -85,8 +84,7 @@ func TestMaxItems(t *testing.T) {
err := MaxItems(2)(&items)
if err == nil {
t.Fatal("expected validation error")
}
if err.Code != ErrorCodeOutOfRange {
} else if err.Code != ErrorCodeOutOfRange {
t.Errorf("expected error code %s, got %s", ErrorCodeOutOfRange, err.Code)
}
})
@@ -114,8 +112,7 @@ func TestUniqueItems(t *testing.T) {
err := UniqueItems()(&items)
if err == nil {
t.Fatal("expected validation error")
}
if err.Code != ErrorCodeInvalidFormat {
} else if err.Code != ErrorCodeInvalidFormat {
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
}
})
@@ -157,12 +154,13 @@ func TestUniqueItems(t *testing.T) {
err := UniqueItems()(&items)
if err == nil {
t.Fatal("expected validation error for non-comparable type")
}
if err.Code != ErrorCodeInvalidFormat {
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
}
if err.Message != "cannot validate uniqueness for non-comparable types" {
t.Errorf("unexpected error message: %s", err.Message)
} else {
if err.Code != ErrorCodeInvalidFormat {
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
}
if err.Message != "cannot validate uniqueness for non-comparable types" {
t.Errorf("unexpected error message: %s", err.Message)
}
}
})
@@ -171,8 +169,7 @@ func TestUniqueItems(t *testing.T) {
err := UniqueItems()(&items)
if err == nil {
t.Fatal("expected validation error for non-comparable type")
}
if err.Code != ErrorCodeInvalidFormat {
} else if err.Code != ErrorCodeInvalidFormat {
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
}
})
@@ -185,8 +182,7 @@ func TestUniqueItems(t *testing.T) {
err := UniqueItems()(&items)
if err == nil {
t.Fatal("expected validation error for non-comparable type")
}
if err.Code != ErrorCodeInvalidFormat {
} else if err.Code != ErrorCodeInvalidFormat {
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
}
})
@@ -212,8 +208,7 @@ func TestUniqueItems(t *testing.T) {
err := UniqueItems()(&items)
if err == nil {
t.Fatal("expected validation error for duplicate comparable structs")
}
if err.Code != ErrorCodeInvalidFormat {
} else if err.Code != ErrorCodeInvalidFormat {
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
}
})

View File

@@ -103,8 +103,7 @@ func TestRequired(t *testing.T) {
err := Required()(&str)
if err == nil {
t.Fatal("expected validation error")
}
if err.Code != ErrorCodeRequired {
} else if err.Code != ErrorCodeRequired {
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
}
})
@@ -193,8 +192,7 @@ func TestRequired(t *testing.T) {
err := Required()(slice)
if err == nil {
t.Fatal("expected validation error for empty []string slice")
}
if err.Code != ErrorCodeRequired {
} else if err.Code != ErrorCodeRequired {
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
}
})
@@ -212,8 +210,7 @@ func TestRequired(t *testing.T) {
err := Required()(slice)
if err == nil {
t.Fatal("expected validation error for empty []int slice")
}
if err.Code != ErrorCodeRequired {
} else if err.Code != ErrorCodeRequired {
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
}
})
@@ -234,8 +231,7 @@ func TestRequired(t *testing.T) {
err := Required()(slice)
if err == nil {
t.Fatal("expected validation error for empty custom type slice")
}
if err.Code != ErrorCodeRequired {
} else if err.Code != ErrorCodeRequired {
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
}
})