SOA as document: replace export with publish workflow
Statements of Applicability are no longer exported as one-off PDFs. Instead, each SOA owns a persistent document that accumulates versions over time, following the same publish/approve lifecycle as authored documents. Publishing without approvers publishes immediately; publishing with approvers creates a draft pending approval via the existing quorum system. SOAs can also store default approvers that are pre-populated in the publish dialog. The SOA is removed from the snapshot system — applicability statements are now queried directly (snapshot_id IS NULL) rather than through snapshot copies. A standalone migration script (cmd/migrate-soa-snapshots-to-documents) converts existing SOA snapshots into documents with proper ProseMirror content, preserving version history and approval decisions. Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -33,6 +33,11 @@ type (
|
||||
}
|
||||
|
||||
ControlObligations []*ControlObligation
|
||||
|
||||
ControlObligationType struct {
|
||||
ControlID gid.GID `db:"control_id"`
|
||||
ObligationType ObligationType `db:"obligation_type"`
|
||||
}
|
||||
)
|
||||
|
||||
func (co ControlObligation) Upsert(
|
||||
@@ -137,3 +142,48 @@ WHERE %s
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func LoadObligationTypesByControlIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
scope Scoper,
|
||||
controlIDs []gid.GID,
|
||||
) ([]ControlObligationType, error) {
|
||||
q := `
|
||||
WITH control_obls AS (
|
||||
SELECT DISTINCT
|
||||
co.control_id,
|
||||
o.type AS obligation_type,
|
||||
o.tenant_id
|
||||
FROM
|
||||
controls_obligations co
|
||||
INNER JOIN
|
||||
obligations o ON co.obligation_id = o.id
|
||||
WHERE
|
||||
co.control_id = ANY(@control_ids)
|
||||
)
|
||||
SELECT
|
||||
control_id,
|
||||
obligation_type
|
||||
FROM
|
||||
control_obls
|
||||
WHERE
|
||||
%s;
|
||||
`
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"control_ids": controlIDs}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot load obligation types by control IDs: %w", err)
|
||||
}
|
||||
|
||||
result, err := pgx.CollectRows(rows, pgx.RowToStructByName[ControlObligationType])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot collect control obligation types: %w", err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user