# Entity Submission Flow - CRITICAL SECURITY PATTERN

## The Sacred Flow

Every entity creation or edit MUST follow this exact flow:

```
1. User fills form
   ↓
2. Submission created → moderation queue
   ↓
3. Moderator reviews & approves
   ↓
4. Edge function writes to database (via service role)
   ↓
5. Versioning system captures change
   ↓
6. Public can view live entity
```

## ❌ NEVER DO THIS

```ts
// Direct database write - BYPASSES EVERYTHING!
await supabase.from('parks').insert(parkData);
await supabase.from('rides').update({ id: rideId }, rideData);

// Even if you're a moderator/admin:
if (isAdmin) {
  await supabase.from('parks').insert(parkData); // STILL WRONG!
}
```

**Why this is blocked:**
- RLS policies explicitly deny INSERT/UPDATE to authenticated users
- Only the service role (edge functions) can write
- Edge functions are ONLY triggered by moderation approval

## ✅ ALWAYS DO THIS

```ts
// Import the submission helpers
import { 
  submitParkCreation, 
  submitParkUpdate,
  submitRideCreation,
  submitRideUpdate 
} from '@/lib/entitySubmissionHelpers';

// For new entities:
const result = await submitParkCreation(parkData, user.id);

// For editing existing entities:
const result = await submitParkUpdate(parkId, parkData, user.id);
```

## For React Components

Use the enforced wrappers:

```tsx
import { enforceParkSubmissionFlow } from '@/lib/entityFormValidation';

// In your component:
const handleSubmit = enforceParkSubmissionFlow(isEditing, park?.id);

<ParkForm
  isEditing={isEditing}
  initialData={park}
  onSubmit={async (data) => {
    await handleSubmit(data, user!.id);
    toast({ title: "Submitted for review" });
  }}
/>
```

## Why This Matters

### Security
- Prevents spam and vandalism
- Rate-limits submissions via queue system
- Blocks malicious automated bots

### Quality
- Human review catches errors, duplicates, inappropriate content
- Maintains high data quality standards

### Accountability
- Full version history with user attribution
- Every change is tracked and auditable
- Can rollback any change

### Compliance
- Complete audit trail for legal/regulatory requirements
- User attribution for all content

## For Moderators/Admins

**Even moderators must follow the flow:**

1. Create/edit submission through normal UI
2. It goes to moderation queue
3. Review your own submission
4. Approve it

**Why?** 
- Ensures versioning captures the change
- Creates audit trail
- Prevents accidental mistakes

**Exception:**
Only emergency database fixes via SQL editor should bypass this. These should be:
- Extremely rare
- Documented in admin_audit_log
- Followed by manual version creation if needed

## Database Protection

### RLS Policies
The following tables have explicit denial policies:
- `parks` - INSERT/UPDATE blocked for authenticated users
- `rides` - INSERT/UPDATE blocked for authenticated users
- `companies` - INSERT/UPDATE blocked for authenticated users
- `ride_models` - INSERT/UPDATE blocked for authenticated users

### Service Role Access
Only these edge functions can write (they use service role):
- `process-selective-approval` - Applies approved submissions atomically (PostgreSQL transaction RPC)
- Direct SQL migrations (admin only)

### Versioning Triggers
All entity writes trigger `auto_create_entity_version()`:
- Captures full entity state
- Records user who made change
- Creates diff of what changed
- Logs to audit trail if user attribution missing

## Error Messages

If you see these errors, you're trying to bypass the flow:

```
Error: new row violates row-level security policy
```
→ You tried to INSERT/UPDATE directly. Use submission helpers.

```
Error: permission denied for table parks/rides/companies/ride_models
```
→ Same issue - use submission helpers.

## Testing the Flow

### Manual Test:
1. Create a new park through the UI
2. Check `content_submissions` table - should have new row
3. Check `submission_items` table - should have park data
4. Approve via moderation queue
5. Check `parks` table - entity should appear
6. Check `entity_versions` table - version should be created
7. Version should have correct `changed_by` user_id

### Automated Test:
```ts
// Test that direct writes are blocked
try {
  await supabase.from('parks').insert({ name: 'Test Park' });
  throw new Error('Expected RLS to block this');
} catch (error) {
  // Should get permission denied error
  expect(error.message).toContain('row-level security');
}

// Test that submission flow works
const result = await submitParkCreation(parkData, userId);
expect(result.submitted).toBe(true);
```

## Monitoring

### Dashboard Widgets
Check the admin dashboard for:
- **Suspicious Versions** - Versions without user attribution
- **Queue Backlog** - Submissions waiting too long
- **Flow Violations** - Any attempts to bypass the flow

### Audit Logs
```sql
-- Check for versions without user attribution
SELECT * FROM entity_versions 
WHERE changed_by IS NULL 
ORDER BY changed_at DESC;

-- Check for direct writes (should be none except migrations)
SELECT * FROM admin_audit_log 
WHERE action = 'version_without_user'
ORDER BY created_at DESC;
```

## Common Pitfalls

### ❌ "I'll just fix this one typo directly"
Even small fixes must go through the flow. Creates version history.

### ❌ "I'm an admin, I can bypass this"
No. Admins follow the flow. Prevents mistakes and maintains audit trail.

### ❌ "This is taking too long, I'll do it in SQL editor"
Only for emergencies. Document it. Create manual version if needed.

### ❌ "I'll bulk import via CSV"
Bulk imports should:
1. Create submissions programmatically
2. Auto-approve them if from trusted source
3. Still trigger versioning

## Questions?

**Q: What if I need to bulk import 1000 parks?**
A: Create submissions programmatically, set `status='approved'`, let edge function process them.

**Q: What if there's an emergency typo on homepage?**
A: Make the fix via submission → have another mod approve immediately. Takes <1 minute.

**Q: What if the moderation queue is broken?**
A: Fix the queue. Don't bypass the flow. That creates worse problems.

**Q: Can I use the service role key directly?**
A: Only in edge functions. Never in client-side code. Never for routine edits.

## Related Files

- `src/lib/entitySubmissionHelpers.ts` - Core submission functions
- `src/lib/entityFormValidation.ts` - Enforced wrappers
- `supabase/functions/process-selective-approval/index.ts` - Atomic transaction RPC approval processor
- `src/components/admin/*Form.tsx` - Form components using the flow
- `docs/ATOMIC_APPROVAL_TRANSACTIONS.md` - Atomic transaction RPC documentation

## Update History

- 2025-01-XX: Added explicit RLS denial policies
- 2025-01-XX: Added versioning for photos table
- 2025-01-XX: Added user attribution to edge function
- 2025-01-XX: Created this documentation
