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
@@ -213,6 +213,10 @@ func (c *Client) PublishImageAssetTask(ctx context.Context, body []byte) error {
return c.publish(ctx, c.cfg.ImageAssetExchange, c.cfg.ImageAssetRoutingKey, body)
}
func (c *Client) PublishComplianceReviewTask(ctx context.Context, body []byte) error {
return c.publish(ctx, c.cfg.ComplianceReviewExchange, c.cfg.ComplianceReviewRoutingKey, body)
}
func (c *Client) publish(ctx context.Context, exchange, routingKey string, body []byte) error {
for attempt := 0; attempt < 2; attempt++ {
conn, ch, pooled, err := c.acquirePublishChannel()
@@ -303,6 +307,10 @@ func (c *Client) ConsumeImageAssetTask(consumerName string) (<-chan amqp.Deliver
return c.consume(consumerName, c.cfg.ImageAssetQueue)
}
func (c *Client) ConsumeComplianceReviewTask(consumerName string) (<-chan amqp.Delivery, *amqp.Channel, error) {
return c.consume(consumerName, c.cfg.ComplianceReviewQueue)
}
func (c *Client) consume(consumerName, queue string) (<-chan amqp.Delivery, *amqp.Channel, error) {
for attempt := 0; attempt < 2; attempt++ {
conn, ch, err := c.openChannel()
@@ -741,6 +749,18 @@ func (c *Client) ensureTopology(conn *amqp.Connection) error {
return err
}
if err := c.ensureWorkQueue(
ch,
c.cfg.ComplianceReviewExchange,
c.cfg.ComplianceReviewRoutingKey,
c.cfg.ComplianceReviewQueue,
c.cfg.ComplianceReviewDLX,
c.cfg.ComplianceReviewDLQ,
c.cfg.ComplianceReviewDLQRouteKey,
); err != nil {
return err
}
return nil
}