This is the initial commit for the CODEX_ADK project, a full-stack AI agent management platform featuring: BACKEND (ASP.NET Core 8.0): - CQRS architecture with 6 commands and 7 queries - 16 API endpoints (all working and tested) - PostgreSQL database with 5 entities - AES-256 encryption for API keys - FluentValidation on all commands - Rate limiting and CORS configured - OpenAPI/Swagger documentation - Docker Compose setup (PostgreSQL + Ollama) FRONTEND (Flutter 3.x): - Dark theme with Svrnty branding - Collapsible sidebar navigation - CQRS API client with Result<T> error handling - Type-safe endpoints from OpenAPI schema - Multi-platform support (Web, iOS, Android, macOS, Linux, Windows) DOCUMENTATION: - Comprehensive API reference - Architecture documentation - Development guidelines for Claude Code - API integration guides - context-claude.md project overview Status: Backend ready (Grade A-), Frontend integration pending 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
275 lines
6.7 KiB
Markdown
275 lines
6.7 KiB
Markdown
# 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`
|