# API Contract Workflow

**Single Source of Truth: Backend OpenAPI Specification**

---

## Overview

This project uses **OpenAPI-driven development** where the backend C# API is the authoritative source for API contracts. The frontend Flutter app automatically generates type-safe Dart code from the OpenAPI specification.

---

## Architecture

```
Backend (C#)                    Frontend (Flutter/Dart)
─────────────                   ───────────────────────

Controllers with                api-schema.json
XML docs          ──────────►   (copied from backend)
                                       │
docs/openapi.json                      │
(auto-generated)  ──────────►          │
                                       ▼
                                lib/api/generated/
                                (auto-generated types)
                                       │
                                       ▼
                                lib/api/client.dart
                                (CQRS API client)
                                       │
                                       ▼
                                lib/api/endpoints/
                                (endpoint extensions)
```

---

## Backend Responsibilities

### 1. XML Documentation
All controllers and DTOs must have complete XML documentation:

```csharp
/// <summary>Gets paginated users with filtering</summary>
/// <param name="page">Page number (1-based)</param>
/// <response code="200">Returns paginated user list</response>
/// <response code="401">Unauthorized</response>
[HttpGet]
[ProducesResponseType(typeof(PagedResult<UserDto>), 200)]
[ProducesResponseType(401)]
public async Task<IActionResult> GetUsers([FromQuery] int page = 1) { }
```

### 2. OpenAPI Export
Backend generates `docs/openapi.json`:

```bash
cd backend
dotnet run --project Codex.Api &
sleep 5
curl https://localhost:7108/swagger/v1/swagger.json > docs/openapi.json
pkill -f "Codex.Api"
```

### 3. Schema Distribution
Frontend copies `docs/openapi.json` to `api-schema.json`:

```bash
cp ../backend/docs/openapi.json ./api-schema.json
```

---

## Frontend Responsibilities

### 1. Install Dependencies
OpenAPI generator packages are in `pubspec.yaml`:

```yaml
dependencies:
  http: ^1.2.2
  json_annotation: ^4.9.0

dev_dependencies:
  build_runner: ^2.4.14
  json_serializable: ^6.9.2
  openapi_generator_annotations: ^5.0.1
```

### 2. Code Generation
Generate Dart types from OpenAPI spec:

```bash
flutter pub run build_runner build --delete-conflicting-outputs
```

### 3. Generated Output
Code is generated to `lib/api/generated/`:

- ✅ **DO NOT EDIT** - These files are auto-generated
- ✅ **DO NOT COMMIT** - Listed in `.gitignore`
- ✅ **REGENERATE** on every API schema update

### 4. Manual Code (Stable)
These files are **manually maintained**:

- `lib/api/client.dart` - CQRS client framework
- `lib/api/types.dart` - Core types (Result, ApiError, pagination)
- `lib/api/endpoints/*.dart` - Endpoint-specific extensions

---

## Workflow: Making API Changes

### Backend Developer Flow

1. **Update C# code** with XML documentation
2. **Run API** to regenerate Swagger
3. **Export OpenAPI spec**:
   ```bash
   curl https://localhost:7108/swagger/v1/swagger.json > docs/openapi.json
   ```
4. **Commit** `docs/openapi.json` to git
5. **Notify frontend** that API contract changed

### Frontend Developer Flow

1. **Pull latest** backend changes
2. **Copy schema**:
   ```bash
   cp ../backend/docs/openapi.json ./api-schema.json
   ```
3. **Regenerate types**:
   ```bash
   flutter pub run build_runner build --delete-conflicting-outputs
   ```
4. **Update endpoint code** if needed (new queries/commands)
5. **Test** with new types

---

## Type Safety Guarantees

### Strict Typing Rules
All generated code follows project strict typing standards:

- ✅ No `dynamic` types
- ✅ No `any` types
- ✅ Explicit type annotations everywhere
- ✅ Null safety enforced

### Example: Generated Query

Backend defines:
```csharp
public record HealthQuery();
```

Frontend generates:
```dart
class HealthQuery {
  const HealthQuery();

  Map<String, Object?> toJson() => {};

  factory HealthQuery.fromJson(Map<String, Object?> json) =>
    const HealthQuery();
}
```

---

## Error Handling

### Backend Contract
Backend returns structured errors:

```json
{
  "message": "Validation failed",
  "statusCode": 422,
  "details": "Email is required"
}
```

### Frontend Handling
Client wraps all responses in `Result<T>`:

```dart
final result = await client.executeQuery<UserDto>(
  endpoint: 'users/123',
  query: const GetUserQuery(),
  fromJson: UserDto.fromJson,
);

result.when(
  success: (user) => print('Got user: ${user.name}'),
  error: (error) => print('Error: ${error.message}'),
);
```

---

## File Structure

```
Console/
├── api-schema.json              # Copied from backend (DO NOT EDIT)
├── build.yaml                   # Code generation config
├── lib/api/
│   ├── client.dart              # CQRS client (manual)
│   ├── types.dart               # Core types (manual)
│   ├── generated/               # Auto-generated (git-ignored)
│   │   └── .gitkeep
│   └── endpoints/
│       └── health_endpoint.dart # Endpoint extensions (manual)
└── .claude-docs/
    └── api-contract-workflow.md # This file
```

---

## Benefits

### For Backend
- ✅ Single source of truth (C# code with XML docs)
- ✅ Type-safe APIs enforced by compiler
- ✅ Swagger UI for testing
- ✅ Automatic client generation

### For Frontend
- ✅ Type-safe API calls (no runtime errors)
- ✅ Auto-completion in IDE
- ✅ Compile-time validation
- ✅ No manual type definitions
- ✅ Always in sync with backend

### For Team
- ✅ Clear contract boundaries
- ✅ Breaking changes caught early
- ✅ No API drift
- ✅ Shared understanding via OpenAPI spec

---

## Troubleshooting

### "Generated code has type errors"
**Solution:** Backend may have incomplete XML docs or invalid schema. Ask backend team to validate `openapi.json`.

### "Types don't match backend"
**Solution:** Regenerate frontend types:
```bash
cp ../backend/docs/openapi.json ./api-schema.json
flutter pub run build_runner build --delete-conflicting-outputs
```

### "Build runner fails"
**Solution:** Clean and rebuild:
```bash
flutter clean
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs
```

---

## References

- **OpenAPI Spec:** `api-schema.json`
- **Backend Docs:** `../backend/docs/ARCHITECTURE.md`
- **Strict Typing:** `.claude-docs/strict-typing.md`
- **Response Protocol:** `.claude-docs/response-protocol.md`
