feat(compliance): add content compliance detection across tenant, ops, and clients

Implements the Revision 8/9 compliance design: tenant + ops backends, ops-web
content-safety pages, admin-web editor/publish gate integration, desktop publish
block surfacing, and supporting migrations / shared types / config plumbing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-05 20:48:14 +08:00
parent 81577b6154
commit 745cdd79cf
73 changed files with 12747 additions and 1892 deletions
@@ -10,25 +10,30 @@ import (
)
type DesktopPublishJob struct {
DesktopID uuid.UUID
TenantID int64
WorkspaceID int64
CreatedByUserID int64
Title string
ContentRef []byte
ScheduledAt *time.Time
CreatedAt time.Time
UpdatedAt time.Time
DesktopID uuid.UUID
TenantID int64
WorkspaceID int64
CreatedByUserID int64
Title string
ContentRef []byte
ScheduledAt *time.Time
ArticleID *int64
ArticleVersionID *int64
Status string
CreatedAt time.Time
UpdatedAt time.Time
}
type CreateDesktopPublishJobParams struct {
DesktopID uuid.UUID
TenantID int64
WorkspaceID int64
CreatedByUserID int64
Title string
ContentRef []byte
ScheduledAt *time.Time
DesktopID uuid.UUID
TenantID int64
WorkspaceID int64
CreatedByUserID int64
Title string
ContentRef []byte
ScheduledAt *time.Time
ArticleID *int64
ArticleVersionID *int64
}
type DesktopTask struct {
@@ -136,13 +141,15 @@ func NewDesktopTaskRepository(db generated.DBTX) DesktopTaskRepository {
func (r *desktopTaskRepository) CreatePublishJob(ctx context.Context, params CreateDesktopPublishJobParams) (*DesktopPublishJob, error) {
row, err := r.q.CreateDesktopPublishJob(ctx, generated.CreateDesktopPublishJobParams{
DesktopID: pgUUID(params.DesktopID),
TenantID: params.TenantID,
WorkspaceID: params.WorkspaceID,
CreatedByUserID: params.CreatedByUserID,
Title: params.Title,
ContentRef: params.ContentRef,
ScheduledAt: pgTimestamp(params.ScheduledAt),
DesktopID: pgUUID(params.DesktopID),
TenantID: params.TenantID,
WorkspaceID: params.WorkspaceID,
CreatedByUserID: params.CreatedByUserID,
Title: params.Title,
ContentRef: params.ContentRef,
ScheduledAt: pgTimestamp(params.ScheduledAt),
ArticleID: pgInt8(params.ArticleID),
ArticleVersionID: pgInt8(params.ArticleVersionID),
})
if err != nil {
return nil, err
@@ -314,15 +321,18 @@ func (r *desktopTaskRepository) FinishAttempt(ctx context.Context, params Finish
func desktopPublishJobFromGenerated(row generated.DesktopPublishJob) *DesktopPublishJob {
return &DesktopPublishJob{
DesktopID: uuidFromPG(row.DesktopID),
TenantID: row.TenantID,
WorkspaceID: row.WorkspaceID,
CreatedByUserID: row.CreatedByUserID,
Title: row.Title,
ContentRef: row.ContentRef,
ScheduledAt: optionalTime(row.ScheduledAt),
CreatedAt: timeFromTimestamp(row.CreatedAt),
UpdatedAt: timeFromTimestamp(row.UpdatedAt),
DesktopID: uuidFromPG(row.DesktopID),
TenantID: row.TenantID,
WorkspaceID: row.WorkspaceID,
CreatedByUserID: row.CreatedByUserID,
Title: row.Title,
ContentRef: row.ContentRef,
ScheduledAt: optionalTime(row.ScheduledAt),
ArticleID: nullableInt64(row.ArticleID),
ArticleVersionID: nullableInt64(row.ArticleVersionID),
Status: row.Status,
CreatedAt: timeFromTimestamp(row.CreatedAt),
UpdatedAt: timeFromTimestamp(row.UpdatedAt),
}
}