- All backend routers moved to /api/v1/ prefix
- Frontend BASE_URL updated to /api/v1
- Setup redirect middleware updated to redirect to /api/v1/setup
- Health router path fixed: prefix=/api/v1/health, @router.get('')
- conftest.py: set server_status=online for test fixture
- Created Docs/API_VERSIONING.md with deprecation policy
- Updated Docs/Backend-Development.md with versioning section
- Updated Instructions.md curl examples
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
125 lines
3.8 KiB
Markdown
125 lines
3.8 KiB
Markdown
# API Versioning Strategy
|
|
|
|
**Status:** Active — Current version: **v1**
|
|
|
|
All BanGUI API endpoints are versioned using URI path versioning (e.g., `/api/v1/`).
|
|
This document explains when and how to version endpoints, how deprecation works, and what guarantees consumers can rely on.
|
|
|
|
---
|
|
|
|
## 1. Version Lifecycle
|
|
|
|
| Stage | Meaning |
|
|
|-------|---------|
|
|
| **Current** | Active, receiving new features and bug fixes. |
|
|
| **Deprecated** | Still functional but marked for removal. Clients receive `Deprecation: true` and `Sunset: <date>` response headers. |
|
|
| **Removed** | Endpoint no longer exists. Clients must migrate to a newer version. |
|
|
|
|
---
|
|
|
|
## 2. URL Structure
|
|
|
|
```
|
|
/api/v{major}/<resource>/<path>
|
|
```
|
|
|
|
- **v1** — current version (2026-05-02)
|
|
- **v2** — reserved for future breaking changes
|
|
- **PATCH** versions (v1.1, v1.2) are **not** used; only **major** version bumps indicate breaking changes
|
|
- The OpenAPI schema is always available at `/api/openapi.json` regardless of version
|
|
|
|
---
|
|
|
|
## 3. What Triggers a Version Bump
|
|
|
|
A new major version is required when a **breaking change** must be introduced, including:
|
|
|
|
- Removing or renaming a field in a response model
|
|
- Changing the type of a request or response field
|
|
- Removing an endpoint entirely
|
|
- Changing authentication/authorization semantics
|
|
- Modifying the semantics of an existing operation
|
|
|
|
**Non-breaking changes** (backward-compatible):
|
|
|
|
- Adding new optional request fields
|
|
- Adding new response fields
|
|
- Adding new endpoints
|
|
- Fixing bugs that caused incorrect behavior
|
|
|
|
These do **not** require a version bump.
|
|
|
|
---
|
|
|
|
## 4. Deprecation Policy
|
|
|
|
When an endpoint is deprecated:
|
|
|
|
1. The endpoint **remains functional** for a minimum of **6 months** from the `Sunset` date
|
|
2. Response headers are added:
|
|
```
|
|
Deprecation: true
|
|
Sunset: <RFC-5322 date>
|
|
Link: <https://bangui.example.com/api/v2/...>; rel="successor-version"
|
|
```
|
|
3. The OpenAPI schema marks the endpoint with `deprecated: true`
|
|
4. Documentation is updated to show the endpoint as deprecated
|
|
|
|
---
|
|
|
|
## 5. Backend Development: Adding Versioned Endpoints
|
|
|
|
### New endpoints
|
|
|
|
All new endpoints are added to the **current** version (`/api/v1/`). Prefix your router:
|
|
|
|
```python
|
|
router = APIRouter(prefix="/api/v1/my-resource", tags=["My Resource"])
|
|
```
|
|
|
|
### Breaking changes requiring v2
|
|
|
|
1. Create a new router file (e.g., `routers/my_resource_v2.py`) with the v2 prefix:
|
|
```python
|
|
router = APIRouter(prefix="/api/v2/my-resource", tags=["My Resource"])
|
|
```
|
|
2. Copy or adapt the v1 handler logic as needed
|
|
3. Register the new router in `app/main.py`:
|
|
```python
|
|
app.include_router(my_resource_v2.router)
|
|
```
|
|
4. Add deprecation headers to the **old** v1 router by marking it deprecated in the OpenAPI spec
|
|
5. Update this document to reflect the new version lifecycle
|
|
|
|
### Keeping routers DRY
|
|
|
|
If v1 and v2 share logic, extract business logic into a **service layer function** and call it from both router handlers. Routers should only contain HTTP concerns (parameters, responses, status codes).
|
|
|
|
---
|
|
|
|
## 6. Frontend Development
|
|
|
|
The frontend always uses the current version's base URL:
|
|
|
|
```typescript
|
|
const BASE_URL: string = import.meta.env.VITE_API_URL ?? "/api/v1";
|
|
```
|
|
|
|
All endpoint paths in `frontend/src/api/endpoints.ts` are defined as relative paths (e.g., `/bans`, `/jails`) and are appended to `BASE_URL` at runtime.
|
|
|
|
---
|
|
|
|
## 7. OpenAPI / Documentation
|
|
|
|
- Swagger UI: `/api/docs`
|
|
- ReDoc: `/api/redoc`
|
|
- OpenAPI schema: `/api/openapi.json`
|
|
- Docs are **not** versioned; they always reflect the **current** (latest) API version
|
|
|
|
---
|
|
|
|
## 8. Version History
|
|
|
|
| Version | Status | Released | Sunset Date | Notes |
|
|
|---------|--------|---------|-------------|-------|
|
|
| v1 | **Current** | 2026-05-02 | — | Initial versioning; all endpoints moved from `/api/` to `/api/v1/` | |