Files
openapi-first/docs/wiki/04_design.md

88 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design — Guarantees, Startup Pipeline, and the Contract Model
This page is the architecture reference: the fail-fast startup surface, the guarantees that hold by construction, and the trade-offs baked into every decision.
---
## 🏗️ 1. The Startup Pipeline
Everything happens **once, eagerly, at construction time** — for the app at `OpenAPIFirstApp(...)`, for the client at `OpenAPIClient(...)`. There is no lazy loading, no deferred binding, no "it'll work on first request".
```text
openapi.yaml ──► loader.load_openapi
├─ parse (json/yaml by extension)
├─ validate (strict OpenAPI 3.x validator)
└─► dict ──▶ OpenAPISpecLoadError
OpenAPIFirstApp(openapi_path=..., routes_module=routes)
├─ 1. load + validate spec (loader)
├─ 2. parse securitySchemes (security)
├─ 3. make_security_dependencies (security)
├─ 4. bind_routes: every operationId ──► routes.<operationId>
│ └─ missing op / missing handler ──► MissingOperationHandler
└─► FastAPI app: routes registry + /openapi.json + Swagger UI
```
Client — same spec, same guarantees:
```text
OpenAPIClient(spec)
├─ require servers[]
├─ require paths
├─ one callable per operationId (client.<operationId>)
│ └─ missing / duplicate opId ──► OpenAPIClientError
└─► ready
```
---
## 📜 2. Guarantees That Hold by Construction
These are not conventions — they are enforced at startup or client construction:
1. **Every route is spec-declared.** Routes are registered *only* from `paths`; there is no decorator-driven or implicit routing.
2. **Every operation is handled.** Each `operationId` resolves to an exact handler name in `routes_module`; a missing one aborts bootstrap.
3. **Every operation has an `operationId`.** An operation without one cannot be bound and fails fast.
4. **Client and server use the same spec.** One document drives both sides, so they cannot drift.
5. **Auth is spec-driven.** `security` dependencies come from `securitySchemes` + per-operation `security`; no manual middleware.
6. **Spec is valid before use.** Invalid, malformed, or unloadable specs are rejected at load, not at first request.
### The startup "no half-states" property
Because binding, validation, and security resolution all run at construction, a booted app is a **provably-complete app**. If the contract is violated in any way, the process refuses to start — the failure is loud, immediate, and tells you exactly what to fix.
---
## 🧩 3. Component Responsibilities
| Module | Owns | Refuses to |
|--------|------|------------|
| `loader` | parse + validate the spec | modify or "fix" the spec |
| `app` | assemble FastAPI from spec + handlers | routing decisions, decorators |
| `binder` | `operationId` → handler mapping | infer handlers from paths |
| `client` | build one callable per `operationId` | guess URLs, deserialize implicitly |
| `security` | schemes → FastAPI `Depends` | manual middleware |
| `errors` | the error hierarchy | swallow failures |
| `codegen` | build-time model/routes generation | runtime codegen |
| `templates` | copyable scaffolds | production data stores |
**Rule of thumb for contributors:** keep modules coercive (they raise if the contract is wrong) and narrow (one responsibility each). Pydoclint + the test suite keep that contract honest.
---
## ⚖️ 4. Design Trade-offs (Accepted)
| Decision | Chosen because | What you give up |
|----------|----------------|------------------|
| Handlers are plain callables | Framework-agnostic, testable, grep-able | No decorator sugar |
| Fail-fast at startup | Drift caught in CI, not at 3am | Slightly heavier boot |
| Raw `httpx.Response` from client | No hidden deserialization/validation | You read `.json()` yourself |
| Build-time codegen | One-way generation, no runtime generator dep | Spec must already be spec-valid |
| Templates copy verbatim | Scaffold, not magic | Templates never updated in place |
---
## 🔗 Related
- [01 Overview](01_overview.md) · [02 Components](02_components.md) · [05 Security](05_security.md) · [06 Error Handling](06_error_handling.md) · [07 Testing](07_testing.md)