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:
Sacha Al Himdani
2026-04-10 13:38:42 +02:00
parent 53edc5ba26
commit c635492f75
74 changed files with 3509 additions and 1595 deletions

View File

@@ -30,20 +30,21 @@ import (
type (
DocumentVersion struct {
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
DocumentID gid.GID `db:"document_id"`
Title string `db:"title"`
Major int `db:"major"`
Minor int `db:"minor"`
Classification DocumentClassification `db:"classification"`
DocumentType DocumentType `db:"document_type"`
Content string `db:"content"`
Changelog string `db:"changelog"`
Status DocumentVersionStatus `db:"status"`
PublishedAt *time.Time `db:"published_at"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
DocumentID gid.GID `db:"document_id"`
Title string `db:"title"`
Major int `db:"major"`
Minor int `db:"minor"`
Classification DocumentClassification `db:"classification"`
DocumentType DocumentType `db:"document_type"`
Content string `db:"content"`
Changelog string `db:"changelog"`
Status DocumentVersionStatus `db:"status"`
Orientation DocumentVersionOrientation `db:"orientation"`
PublishedAt *time.Time `db:"published_at"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
DocumentVersions []*DocumentVersion
@@ -93,6 +94,7 @@ SELECT
content,
changelog,
status,
orientation,
published_at,
created_at,
updated_at
@@ -156,6 +158,7 @@ SELECT
content,
changelog,
status,
orientation,
published_at,
created_at,
updated_at
@@ -211,6 +214,8 @@ INSERT INTO document_versions (
content,
changelog,
status,
orientation,
published_at,
created_at,
updated_at
)
@@ -227,6 +232,8 @@ VALUES (
@content,
@changelog,
@status,
@orientation,
@published_at,
@created_at,
@updated_at
)
@@ -244,6 +251,8 @@ VALUES (
"content": dv.Content,
"changelog": dv.Changelog,
"status": dv.Status,
"orientation": dv.Orientation,
"published_at": dv.PublishedAt,
"created_at": dv.CreatedAt,
"updated_at": dv.UpdatedAt,
}
@@ -285,6 +294,7 @@ SELECT
content,
changelog,
status,
orientation,
published_at,
created_at,
updated_at
@@ -344,6 +354,7 @@ SELECT
content,
changelog,
status,
orientation,
published_at,
created_at,
updated_at
@@ -399,6 +410,7 @@ SELECT
content,
changelog,
status,
orientation,
published_at,
created_at,
updated_at
@@ -453,6 +465,7 @@ UPDATE document_versions SET
published_at = @published_at,
classification = @classification,
document_type = @document_type,
orientation = @orientation,
updated_at = @updated_at
WHERE %s
AND id = @document_version_id
@@ -471,6 +484,7 @@ WHERE %s
"published_at": dv.PublishedAt,
"classification": dv.Classification,
"document_type": dv.DocumentType,
"orientation": dv.Orientation,
"updated_at": dv.UpdatedAt,
}
maps.Copy(args, scope.SQLArguments())