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:
@@ -211,7 +211,9 @@ INSERT INTO desktop_publish_jobs (
|
||||
created_by_user_id,
|
||||
title,
|
||||
content_ref,
|
||||
scheduled_at
|
||||
scheduled_at,
|
||||
article_id,
|
||||
article_version_id
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
@@ -220,19 +222,23 @@ VALUES (
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7
|
||||
$7,
|
||||
$8,
|
||||
$9
|
||||
)
|
||||
RETURNING id, desktop_id, tenant_id, workspace_id, created_by_user_id, title, content_ref, scheduled_at, created_at, updated_at
|
||||
RETURNING id, desktop_id, tenant_id, workspace_id, created_by_user_id, title, content_ref, scheduled_at, created_at, updated_at, article_id, article_version_id, status, compliance_blocked_record_id, compliance_blocked_at, compliance_blocked_reason
|
||||
`
|
||||
|
||||
type CreateDesktopPublishJobParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
CreatedByUserID int64 `json:"created_by_user_id"`
|
||||
Title string `json:"title"`
|
||||
ContentRef []byte `json:"content_ref"`
|
||||
ScheduledAt pgtype.Timestamptz `json:"scheduled_at"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
CreatedByUserID int64 `json:"created_by_user_id"`
|
||||
Title string `json:"title"`
|
||||
ContentRef []byte `json:"content_ref"`
|
||||
ScheduledAt pgtype.Timestamptz `json:"scheduled_at"`
|
||||
ArticleID pgtype.Int8 `json:"article_id"`
|
||||
ArticleVersionID pgtype.Int8 `json:"article_version_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateDesktopPublishJob(ctx context.Context, arg CreateDesktopPublishJobParams) (DesktopPublishJob, error) {
|
||||
@@ -244,6 +250,8 @@ func (q *Queries) CreateDesktopPublishJob(ctx context.Context, arg CreateDesktop
|
||||
arg.Title,
|
||||
arg.ContentRef,
|
||||
arg.ScheduledAt,
|
||||
arg.ArticleID,
|
||||
arg.ArticleVersionID,
|
||||
)
|
||||
var i DesktopPublishJob
|
||||
err := row.Scan(
|
||||
@@ -257,6 +265,12 @@ func (q *Queries) CreateDesktopPublishJob(ctx context.Context, arg CreateDesktop
|
||||
&i.ScheduledAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ArticleID,
|
||||
&i.ArticleVersionID,
|
||||
&i.Status,
|
||||
&i.ComplianceBlockedRecordID,
|
||||
&i.ComplianceBlockedAt,
|
||||
&i.ComplianceBlockedReason,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -544,12 +558,18 @@ const leaseNextQueuedDesktopTask = `-- name: LeaseNextQueuedDesktopTask :one
|
||||
WITH candidate AS (
|
||||
SELECT dt.desktop_id
|
||||
FROM desktop_tasks AS dt
|
||||
LEFT JOIN desktop_publish_jobs AS j ON j.desktop_id = dt.job_id
|
||||
WHERE dt.target_client_id = $3
|
||||
AND dt.status = 'queued'
|
||||
AND (
|
||||
$4::text IS NULL
|
||||
OR dt.kind = $4::text
|
||||
)
|
||||
AND (
|
||||
dt.kind <> 'publish'
|
||||
OR j.desktop_id IS NULL
|
||||
OR j.status = 'queued'
|
||||
)
|
||||
ORDER BY dt.lane_weight DESC,
|
||||
dt.priority DESC,
|
||||
COALESCE(dt.enqueued_at, dt.created_at) ASC,
|
||||
|
||||
Reference in New Issue
Block a user