TAP Content Safety database
Flagged Azure Content Safety results from the active shared endpoint are persisted to Core.log_ContentSafetyDetections. The older TAP batch/content-safety workflow table, TAP.log_ContentSafetyFindings, is retained as a legacy audit surface until production usage and retention needs are reviewed.
The active endpoint also keeps a short-lived SQL context buffer in Core.cache_ContentSafetyMessageContext. This buffer stores every content-safety request for a default two-hour window so the backend can preserve recent context when a message is flagged. Expired rows are removed by the health aggregator Azure Function timer contentSafetyContextRetentionTimer.
Table: Core.cache_ContentSafetyMessageContext
Purpose: Ephemeral rolling context buffer for active content-safety sessions. This table is not a durable audit record.
Key columns
Identification & Correlation:
ContextMessageId— Stable unique identifier for the buffered rowSessionId,MessageId,RequestId— Conversation/request IDs returned by the endpointCorrelationId,RoutePath,TenantId,UserId,Project,Source— Request and ownership metadata
Buffered Content:
TextContent,TextHashSha256,TextLength— Submitted text plus search/dedupe metadataImageInputsJson— Image URL/label plus binary/base64 size and SHA-256 summaries. Raw image bytes are not stored.AuditContextJson,RequestContextJson— Caller/runtime metadata
Retention:
CreatedAtUtc,ExpiresAtUtc— Default expiry is two hoursIX_cache_ContentSafetyMessageContext_Sessionsupports flagged snapshot lookupIX_cache_ContentSafetyMessageContext_ExpiresAtUtcsupports purge batches
Cleanup
apps/health-aggregator registers contentSafetyContextRetentionTimer, defaulting to CONTENT_SAFETY_CONTEXT_PURGE_SCHEDULE=0 */10 * * * *. The timer calls Core.usp_PurgeExpiredContentSafetyContext with CONTENT_SAFETY_CONTEXT_PURGE_BATCH_SIZE, defaulting to 5000 rows.
Table: Core.log_ContentSafetyDetections
Purpose: Flagged-only audit trail for active content-safety detections. Safe/non-flagged requests are not stored.
Key columns
Identification & Correlation:
DetectionId— Stable unique identifier for the detection rowConversationId,MessageId,ThreadId,SessionId— Caller-provided conversation/message contextUserId,TenantId,Project,Source— Caller-provided ownership and source contextRequestId,CorrelationId,RoutePath,EnvironmentName— Runtime/request correlation
Moderation Outcome:
Flagged— Always1; the table has a check constraint to prevent safe-result rowsThreshold,AuthMode,CategoriesJson— Moderation configuration and auth modeTextMaxSeverity,ImageMaxSeverity, per-category severity columns, and flagged booleansBlocklistNamesJson,BlocklistHitCount,BlocklistHitsJson,HaltOnBlocklistHit
Preserved Context:
TextContent,TextHashSha256,TextLength— Submitted text and search/dedupe metadataImageInputsJson— Image URL/label plus binary/base64 size and SHA-256 summaries. Raw image bytes are not stored.AuditContextJson,RequestContextJson,TextResponseJson,ImageResponsesJson,FullResponseJsonContextSnapshotJson,ContextMessageCount,ContextWindowStartedAtUtc,ContextWindowEndedAtUtc,ContextRetentionHours— Available context copied fromCore.cache_ContentSafetyMessageContextwhen a message is flagged
Review & Retention:
ReviewStatus,ReviewedAtUtc,ReviewedBy,Disposition,ReviewNotesCreatedAtUtc,ExpiresAtUtc
Legacy table: TAP.log_ContentSafetyFindings
TAP.log_ContentSafetyFindings belongs to the retired TAP batch/content-safety workflow surface. It is not the active persistence target for /other/tools/azure-content-safety.
Purpose: Detailed Azure Content Safety moderation findings per post. Stores text severity, image severity, blocklist hits, and raw response payloads.
Schema Diagram
Key columns
Identification & Correlation:
ID— Primary key (BIGINT, identity)PostTaggingResultId— FK tolog_PostTaggingResults.ID(nullable)JobId— Links tolog_BatchTaggingJobs.JobIdPostId— TAP post identifier
Overall Outcome:
Flagged— Boolean indicating whether content was flagged for moderationThreshold— Configured severity threshold (0-7)AuthMode— Authentication method used ('managed-identity'or'api-key')
Text Analysis Results:
TextAnalyzed— Whether text was analyzedTextContent— Text that was analyzed (NVARCHAR(MAX))TextMaxSeverity— Max severity across all text categoriesTextHateSeverity,TextSelfHarmSeverity,TextSexualSeverity,TextViolenceSeverity— Per-category severity levelsTextFlagged— Whether text exceeded threshold
Image Analysis Results:
ImageAnalyzed— Whether image(s) were analyzedImageUrl— URL of analyzed imageImageLabel— Image identifier (e.g.,'post-12345')ImageMaxSeverity— Max severity across all image categoriesImageHateSeverity,ImageSelfHarmSeverity,ImageSexualSeverity,ImageViolenceSeverity— Per-category severity levelsImageFlagged— Whether image exceeded threshold
Blocklist Results:
BlocklistChecked— Whether blocklists were checkedBlocklistNames— Comma-separated list of blocklist names checkedBlocklistHitCount— Number of blocklist hits detectedBlocklistHitsJson— JSON array of blocklist hit detailsHaltOnBlocklistHit— Configuration: whether blocklist hit should halt processing
Raw Responses (Audit/Debug):
Notes— Human-readable notes from moderationTextResponseJson— Full Azure Content Safety text analysis responseImageResponseJson— Full Azure Content Safety image analysis responseFullResponseJson— Complete response payload
Timing:
AnalysisStartedAt,AnalysisCompletedAt— Analysis timestampsAnalysisDurationMs— Duration in millisecondsCreatedAt— Record creation timestamp
Common queries
Finding flagged posts
SELECT PostId, Flagged, TextMaxSeverity, ImageMaxSeverity, BlocklistHitCount, CreatedAt
FROM TAP.log_ContentSafetyFindings
WHERE Flagged = 1
ORDER BY CreatedAt DESC;
Get content safety results for a specific job
SELECT
f.PostId,
f.Flagged,
f.TextMaxSeverity,
f.ImageMaxSeverity,
f.BlocklistHitCount,
f.Notes,
f.CreatedAt
FROM TAP.log_ContentSafetyFindings f
WHERE f.JobId = @jobId
ORDER BY f.CreatedAt DESC;
Find posts with blocklist hits
SELECT
PostId,
BlocklistNames,
BlocklistHitCount,
BlocklistHitsJson,
Notes,
CreatedAt
FROM TAP.log_ContentSafetyFindings
WHERE BlocklistHitCount > 0
ORDER BY CreatedAt DESC;
Correlate content safety findings with tagging results
SELECT
ptr.PostId,
ptr.Caption,
ptr.GeneratedTagsJson,
csf.Flagged,
csf.TextMaxSeverity,
csf.ImageMaxSeverity,
csf.Notes
FROM TAP.log_PostTaggingResults ptr
LEFT JOIN TAP.log_ContentSafetyFindings csf ON csf.PostTaggingResultId = ptr.ID
WHERE ptr.JobId = @jobId
ORDER BY ptr.CreatedAt DESC;
Get severity distribution for recent posts
SELECT
CASE
WHEN TextMaxSeverity IS NULL THEN 'Not Analyzed'
WHEN TextMaxSeverity = 0 THEN 'Safe (0)'
WHEN TextMaxSeverity <= 2 THEN 'Low (1-2)'
WHEN TextMaxSeverity <= 4 THEN 'Medium (3-4)'
ELSE 'High (5-7)'
END AS SeverityRange,
COUNT(*) AS PostCount
FROM TAP.log_ContentSafetyFindings
WHERE CreatedAt >= DATEADD(day, -7, SYSUTCDATETIME())
GROUP BY CASE
WHEN TextMaxSeverity IS NULL THEN 'Not Analyzed'
WHEN TextMaxSeverity = 0 THEN 'Safe (0)'
WHEN TextMaxSeverity <= 2 THEN 'Low (1-2)'
WHEN TextMaxSeverity <= 4 THEN 'Medium (3-4)'
ELSE 'High (5-7)'
END
ORDER BY PostCount DESC;
Troubleshooting
- Many posts flagged unexpectedly: Check the threshold configuration and blocklist settings in your Azure Content Safety resource. Review
packages/platform-runtime/src/tools/azure-content-safety.tsfor threshold defaults. - Missing content safety entries: Verify that
AZURE_CONTENT_SAFETY_ENDPOINTis configured and that the App Service Managed Identity hasCognitive Services Userrole on the Content Safety resource. - Authentication failures: Check
AuthModecolumn - prefer'managed-identity'over'api-key'. Ensure the Managed Identity is properly assigned in Azure. - High analysis duration: Check
AnalysisDurationMs- if consistently high, investigate network latency or Azure Content Safety service performance. - Debugging specific posts: Use
FullResponseJsonto see the complete Azure Content Safety API response for detailed diagnostics.
Related tables
TAP.log_BatchTaggingJobs— Parent job recordsTAP.log_PostTaggingResults— Per-post tagging results (caption, tags, status)
Code references
- Content Safety tool:
src/mastra/tools/azure-content-safety.ts - Context buffer:
src/mastra/tools/content-safety-context-store.ts - Retention timer:
apps/health-aggregator/src/timer-trigger.ts - Runtime note: active TAP tagging suggestions do not currently write new content-safety rows; this table belongs to the legacy batch/content-safety workflow surface.
- DDL:
db/sqlproj/Mastra.Platform.TapDb/model/Tables/TAP.log_ContentSafetyFindings.sql