- README rewritten for the real Next.js + Payload + Postgres stack (old one described the dead static prototype) - Logo + 4 live screenshots (home, articles, post, subscription) - Arabic flow explanations with mermaid diagrams: visitor journey, content pipeline, request path - Architecture table, quick start, API reference, security summary, deploy commands - AGENT.md: orientation for future AI agents (data model, trust rules, rate limits, routes, env, deploy, house rules) - GLOSSARY.md and docs/adr committed (linked from README)
26 lines
1.6 KiB
Markdown
26 lines
1.6 KiB
Markdown
# ADR 0002 — Moderated comments with server-forced author
|
|
|
|
Date: 2026-10-03
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
Comments are user-generated content on a public site. Risks: identity spoofing (a request forging `author`), spam (no gate), and orphaned identity data (nested user lookups through restrictive read access). QA-D04 required a real backend for comments.
|
|
|
|
## Decision
|
|
|
|
- Comments default to `status: 'pending'`; only `approved` are publicly visible. The read access rule returns `{ status: { equals: 'approved' } }` for non-admins.
|
|
- The author is forced server-side on create, twice: a `beforeChange` hook on the collection and the custom route — REST-created comments can never spoof identity.
|
|
- `authorName` is denormalized at submit time (snapshot of `fullName`, else «عضو») to avoid nested user-read access issues when rendering; the email is never exposed.
|
|
- Approval/rejection is admin-only, done in the Payload admin panel. Authors cannot edit or delete their comments (moderated model).
|
|
- Authors see their own pending comments rendered on the post page tagged «قيد المراجعة» (via `overrideAccess` query filtered to their own author id), so a submitted comment does not "vanish".
|
|
|
|
## Tests for a real ADR
|
|
|
|
- **Hard to reverse**: the display-name snapshot and status lifecycle are visible in every rendered comment and in the DB.
|
|
- **Surprising**: forcing author in two places (hook + route) and `overrideAccess` for the pending query are non-obvious.
|
|
- **Real trade-off**: moderation latency for users vs. spam safety; denormalization vs. live join through restricted user reads.
|