Files
thrilltrack-explorer/docs/moderation/SUBMISSION_PATTERNS.md
gpt-engineer-app[bot] 1a8395f0a0 Update documentation references
Update remaining documentation files to remove references to the old approval flow and feature flags.
2025-11-06 21:23:29 +00:00

262 lines
7.1 KiB
Markdown

# Submission Patterns & Guidelines
## Overview
This document outlines the patterns and best practices for working with submissions in the moderation queue system.
## Submission Types
### 1. Content Submissions (`content_submissions`)
**When to use:**
- Creating or updating parks, rides, companies, ride models
- Multi-item submissions with dependencies
- Submissions requiring moderator review before going live
**Data Flow:**
```
User Form → validateEntityData() → createSubmission()
→ content_submissions table
→ submission_items table (with dependencies)
→ Moderation Queue
→ Approval → process-selective-approval edge function (atomic transaction RPC)
→ Live entities created (all-or-nothing via PostgreSQL transaction)
```
**Example:**
```typescript
// Creating a park with operator dependency
const { success } = await createParkSubmission({
name: "Cedar Point",
park_type: "theme_park",
operator_id: "new_operator_123", // References another item in same submission
});
```
### 2. Photo Submissions (`photo_submissions`)
**When to use:**
- User uploading photos to existing entities
- Photos require moderation but entity already exists
**Data Flow:**
```
UppyPhotoSubmissionUpload
→ Cloudflare Direct Upload
→ photo_submissions + photo_submission_items tables
→ Moderation Queue
→ Approval → Photos linked to entity
```
**Key Requirements:**
- Must be linked to parent `content_submissions` for queue integration
- Caption and title sanitized (plain text only, no HTML)
- Maximum 10 photos per submission
### 3. Reviews (`reviews`)
**When to use:**
- User reviewing a park or ride
- Rating with optional text content
**Data Flow:**
```
ReviewForm
→ reviews table + content_submissions (NEW)
→ Moderation Queue
→ Approval → Review goes live
```
**Sanitization:**
- All review content is plain text (HTML stripped)
- Maximum 5000 characters
- Rating validation (0.5-5.0 scale)
## When to Use Each Table
### Use `content_submissions` when:
✅ Creating new entities (parks, rides, companies)
✅ Updating existing entities
✅ Submissions have multi-item dependencies
✅ Need moderator review before data goes live
### Use Specialized Tables when:
**Photos**: Entity exists, just adding media (`photo_submissions`)
**Reviews**: User feedback on existing entity (`reviews` + `content_submissions`)
**Technical Specs**: Belongs to specific entity (`ride_technical_specifications`)
## Validation Requirements
### All Submissions Must:
1. Pass Zod schema validation (`entityValidationSchemas.ts`)
2. Have proper slug generation (unique, URL-safe)
3. Include source URLs when applicable
4. Pass duplicate detection checks
### Entity-Specific Requirements:
**Parks:**
- Valid `park_type` enum
- Valid location data (country required)
- Opening date format validation
**Rides:**
- Must reference valid `park_id`
- Valid `ride_type` enum
- Opening date validation
**Companies:**
- Valid `company_type` enum
- Country code validation
- Founded year range check
## Dependency Resolution
### Dependency Types:
1. **Same-submission dependencies**: New park references new operator (both in queue)
2. **Existing entity dependencies**: New ride references existing park
3. **Multi-level dependencies**: Ride → Park → Operator → Owner (4 levels)
### Resolution Order:
Dependencies are resolved using topological sorting:
```
1. Load all items in submission
2. Build dependency graph
3. Sort topologically (parents before children)
4. Process in order
```
**Example:**
```
Submission contains:
- Item A: Operator (no dependencies)
- Item B: Park (depends on A)
- Item C: Ride (depends on B)
Processing order: A → B → C
```
## Best Practices
### DO:
✅ Use existing entities when possible (avoid duplicates)
✅ Provide source URLs for verifiability
✅ Write clear submission notes for moderators
✅ Validate data on client-side before submission
✅ Use type guards when working with `SubmissionItemData`
### DON'T:
❌ Store JSON blobs in SQL columns
❌ Skip validation to "speed up" submissions
❌ Create dependencies to non-existent entities
❌ Submit without source verification
❌ Bypass moderation queue (security risk)
## Adding New Submission Types
### Steps:
1. Create type definition in `src/types/moderation.ts`
2. Add type guard to `src/lib/moderation/typeGuards.ts`
3. Create validation schema in `src/lib/entityValidationSchemas.ts`
4. Add submission helper in `src/lib/entitySubmissionHelpers.ts`
5. Update `useModerationQueueManager` query to fetch new type
6. Create renderer component (optional, for complex UI)
7. Add tests for new type
### Example: Adding "Event" Submission Type
```typescript
// 1. Type definition (moderation.ts)
export interface EventItemData {
event_id?: string;
name: string;
park_id: string;
start_date: string;
end_date: string;
}
export type SubmissionItemData =
| ParkItemData
| RideItemData
| EventItemData; // Add here
// 2. Type guard (typeGuards.ts)
export function isEventItemData(data: SubmissionItemData): data is EventItemData {
return 'start_date' in data && 'end_date' in data;
}
// 3. Validation (entityValidationSchemas.ts)
const eventSchema = z.object({
name: z.string().min(1).max(200),
park_id: z.string().uuid(),
start_date: z.string().datetime(),
end_date: z.string().datetime(),
});
// 4. Submission helper (entitySubmissionHelpers.ts)
export async function createEventSubmission(eventData: EventFormData) {
// Validation, submission creation logic
}
// 5. Update queue query to include events
// (already handles all content_submissions)
// 6. Optional: Create EventSubmissionDisplay component
// 7. Add tests
```
## Migration Checklist
When migrating legacy code to this pattern:
- [ ] Remove direct database writes (use submission helpers)
- [ ] Add validation schemas
- [ ] Update to use `SubmissionItemData` types
- [ ] Add type guards where needed
- [ ] Test dependency resolution
- [ ] Verify sanitization is applied
- [ ] Update documentation
## Security Considerations
### Input Validation:
- **Server-side validation** is mandatory (Zod schemas)
- **Client-side validation** for UX only
- **Never trust user input** - always validate and sanitize
### Sanitization:
- HTML stripped from user text (use `rehype-sanitize`)
- URLs validated and optionally stripped
- File uploads validated (type, size, count)
- SQL injection prevented (Supabase parameterized queries)
### Access Control:
- Only moderators can approve/reject
- Users can only submit, not self-approve
- RLS policies enforce row-level security
- Lock system prevents concurrent modifications
## Troubleshooting
### Common Issues:
**"Dependency not found"**
→ Check if parent entity exists in database or in same submission
**"Validation failed"**
→ Check Zod schema, ensure all required fields present
**"Duplicate slug"**
→ Slug generation collided, system will auto-increment
**"Lock expired"**
→ Moderator must re-claim submission to continue
**"Permission denied"**
→ Check user role (must be moderator/admin)
## References
- See `ARCHITECTURE.md` for system design
- See `COMPONENTS.md` for UI component usage
- See `../IMPLEMENTATION_COMPLETE.md` for recent changes