# Write Flow Update (Mutation Pattern)

This document updates the write flow section of WEBSITE_CONTRACT.md to use the Mutation pattern.

## Write Flow (Strict)

All writes MUST enter through **Next.js Server Actions**.

### Forbidden

- client components performing write HTTP requests
- client components calling API clients for mutations

### Allowed

- client submits intent (FormData, button action)
- server action performs UX validation
- **server action calls a Mutation** (not Services directly)
- Mutation creates infrastructure and calls Service
- Service orchestrates API calls and business logic

### Server Actions must use Mutations

```typescript
// ❌ WRONG - Direct service usage
'use server';
import { AdminService } from '@/lib/services/admin/AdminService';

export async function updateUserStatus(userId: string, status: string) {
  const service = new AdminService(...);
  await service.updateUserStatus(userId, status); // ❌ Should use mutation
}
```

```typescript
// ✅ CORRECT - Mutation usage
'use server';
import { AdminUserMutation } from '@/lib/mutations/admin/AdminUserMutation';
import { revalidatePath } from 'next/cache';

export async function updateUserStatus(userId: string, status: string) {
  const mutation = new AdminUserMutation();
  const result = await mutation.updateUserStatus(userId, status);
  
  if (result.isErr()) {
    console.error('updateUserStatus failed:', result.getError());
    throw new Error('Failed to update user status');
  }
  
  revalidatePath('/admin/users');
}
```

### Mutation Pattern

```typescript
// lib/mutations/admin/AdminUserMutation.ts
import { Result, ResultFactory } from '@/lib/contracts/Result';

export class AdminUserMutation {
  private service: AdminService;
  
  constructor() {
    // Manual DI for serverless
    const logger = new ConsoleLogger();
    const errorReporter = new EnhancedErrorReporter(logger, {
      showUserNotifications: true,
      logToConsole: true,
      reportToExternal: process.env.NODE_ENV === 'production',
    });
    const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001';
    const apiClient = new AdminApiClient(baseUrl, errorReporter, logger);
    this.service = new AdminService(apiClient);
  }
  
  async updateUserStatus(userId: string, status: string): Promise<Result<void, string>> {
    try {
      await this.service.updateUserStatus(userId, status);
      return ResultFactory.ok(undefined);
    } catch (error) {
      return ResultFactory.error('UPDATE_USER_STATUS_FAILED');
    }
  }
}
```

### Flow

1. **Server Action** (thin wrapper) - handles framework concerns (revalidation, redirects)
2. **Mutation** (framework-agnostic) - creates infrastructure, calls service
3. **Service** (business logic) - orchestrates API calls
4. **API Client** (infrastructure) - makes HTTP requests
5. **Result** - type-safe error handling

### Rationale

- **Framework independence**: Mutations can be tested without Next.js
- **Consistency**: Mirrors PageQuery pattern for reads/writes
- **Type-safe errors**: Result pattern eliminates exceptions
- **Migration ease**: Can switch frameworks without rewriting business logic
- **Testability**: Can unit test mutations in isolation
- **Reusability**: Can be called from other contexts (cron jobs, etc.)

### Comparison with PageQueries

| Aspect | PageQuery | Mutation |
|--------|-----------|----------|
| Purpose | Read data | Write data |
| Location | `lib/page-queries/` | `lib/mutations/` |
| Framework | Called from RSC | Called from Server Actions |
| Infrastructure | Manual DI | Manual DI |
| Returns | `Result<ApiDto, string>` | `Result<void, string>` |
| Revalidation | N/A | Server Action handles it |

### See Also

- [`MUTATIONS.md`](MUTATIONS.md) - Full mutation pattern documentation
- [`SERVICES.md`](SERVICES.md) - Service layer documentation
- [`WEBSITE_CONTRACT.md`](WEBSITE_CONTRACT.md) - Main contract