33 — TestimonialModerationLog Model & Audit Workflow (Blueprint §5.10)
Cursor-ready plan for implementing immutable moderation audit logging, write contracts, query patterns, and compliance-safe retention.
33 — TestimonialModerationLog Model & Audit Workflow (Blueprint §5.10)
Section titled “33 — TestimonialModerationLog Model & Audit Workflow (Blueprint §5.10)”Source: 02-Implementation-Blueprint.md — §5.10 New model: TestimonialModerationLog.
This document is a build spec only. No code changes are implied until a task references this file.
Related: 10 (submission detail actions), 11 (published actions), 12 (moderation settings), 08 (security/compliance), 20 (schema baseline).
0) Goal (one sentence)
Section titled “0) Goal (one sentence)”Ensure every moderation or publication decision on testimonial content is captured in an immutable, tenant-scoped audit trail usable for support, compliance, and incident investigation.
1) Blueprint model recap
Section titled “1) Blueprint model recap”Blueprint fields:
id String @id @default(uuid())shopId String @map("shop_id")submissionId String @map("submission_id")action String// approve | reject | archive | unpublish | featurereason String? @db.TextactorType String @map("actor_type")// merchant | systemactorEmail String? @map("actor_email")createdAt DateTime @default(now()) @map("created_at")
Index:
@@index([submissionId, createdAt])
2) Scope
Section titled “2) Scope”In scope
Section titled “In scope”- Prisma model implementation and migration
- Write-path integration for all moderation actions
- Read/query usage for admin detail timeline
- Immutability guarantees (application-level)
Out of scope
Section titled “Out of scope”- Full legal retention policy beyond app-level defaults
- External SIEM export (optional future)
3) Action taxonomy (canonical)
Section titled “3) Action taxonomy (canonical)”Start with blueprint actions:
approverejectarchiveunpublishfeature
Recommended extensions (optional but useful):
publishunfeaturereopen(move rejected back to pending)auto_reject(system moderation rule)auto_approve_photo
If extensions are added, keep a central action constants list.
4) Write contract (where logs must be created)
Section titled “4) Write contract (where logs must be created)”Create one log row for each successful state-changing intent:
- Screen 6 detail actions (
approve,reject,flag,publish, etc.) - Screen 7 published management actions (
unpublish,feature, reorder-related if needed) - Screen 5 bulk moderation actions
- System actions from moderation automation (Screen 9 rules)
4.1 Transaction rule
Section titled “4.1 Transaction rule”State change and log insertion must be in the same DB transaction:
- If status update fails -> no log
- If log insert fails -> rollback state update
This prevents audit drift.
5) Actor rules
Section titled “5) Actor rules”5.1 actorType
Section titled “5.1 actorType”merchantfor admin UI actionssystemfor automatic rule-based actions
5.2 actorEmail
Section titled “5.2 actorEmail”- required for
merchantwhen available from session - nullable for
system
5.3 reason
Section titled “5.3 reason”- required for
reject(UI enforce + server enforce) - optional for others
6) Immutability standard
Section titled “6) Immutability standard”Treat this model as append-only:
- No update endpoint
- No delete endpoint
- No “edit reason” after insert
If correction needed:
- insert another log row with corrective action and reason.
This aligns with audit expectations from 08-security-compliance-and-privacy.md.
7) Query patterns
Section titled “7) Query patterns”7.1 Submission detail timeline
Section titled “7.1 Submission detail timeline”where: { submissionId, shopId }
orderBy: { createdAt: "desc" }
take: 20 (pagination optional)
7.2 Troubleshooting query
Section titled “7.2 Troubleshooting query”Filter by:
shopIdaction- date range
actorType
Optional admin support screen can be added later; not required now.
8) Privacy/compliance notes
Section titled “8) Privacy/compliance notes”reasoncan include free text; avoid storing raw customer PII when possible.- For GDPR customer redaction:
- do not break audit chain,
- but sanitize
reasonif it accidentally contains personal data (policy decision in08).
Do not expose moderation logs in storefront/public APIs.
9) Migration and index guidance
Section titled “9) Migration and index guidance”9.1 Schema migration
Section titled “9.1 Schema migration”Add model exactly with mapped snake_case columns.
9.2 Indexes
Section titled “9.2 Indexes”Required:
@@index([submissionId, createdAt])
Recommended:
@@index([shopId, createdAt])for support/reporting lookups.
10) Acceptance criteria
Section titled “10) Acceptance criteria”- Every moderation state mutation creates exactly one corresponding log row.
- Reject action cannot complete without reason and log.
- Bulk actions create one log row per submission id.
- Log rows are never edited/deleted by application code.
- Submission detail timeline displays logs in reverse chronological order.
11) Suggested implementation order (for Cursor)
Section titled “11) Suggested implementation order (for Cursor)”- Add Prisma model + migration.
- Add constants for action values and actor types.
- Implement helper
appendModerationLog(...). - Integrate helper in all relevant route actions.
- Add timeline section in Screen 6 detail loader/UI.
- Add tests for transaction integrity and required reject reason.
12) References
Section titled “12) References”02-Implementation-Blueprint.md— §5.1010-submission-detail-screen-6.md11-published-content-screen-7.md12-moderation-settings-screen-9.md08-security-compliance-and-privacy.md
13) Note on numbering
Section titled “13) Note on numbering”This folder already includes 05 through 32 plans. This file is 33-....