Skip to content

Commit 527d999

Browse files
amosttAygentic
andauthored
docs(api): update AYG-70 entity docs after merge (#8)
* feat(api): add Entity CRUD REST endpoints with auth and pagination [AYG-70] Add 5 thin route handlers (POST/GET/GET/{id}/PATCH/{id}/DELETE/{id}) for the Entity resource at /api/v1/entities. All endpoints require Clerk JWT authentication via PrincipalDep and delegate business logic to entity_service. Pagination validated at route layer via Query constraints (offset>=0, limit 1-100). Includes 22 integration tests covering CRUD lifecycle, auth enforcement, ownership isolation (404 not 403), validation errors, and pagination boundary rejection. Files: - CREATE backend/app/api/routes/entities.py (5 route handlers) - MODIFY backend/app/api/main.py (register entities router) - CREATE backend/tests/integration/test_entities.py (22 tests) Fixes AYG-70 Related to AYG-64 🤖 Generated by Aygentic Co-Authored-By: Aygentic <noreply@aygentic.com> * docs(api): activate entity endpoint docs and test registry updates [AYG-70] --------- Co-authored-by: Aygentic <noreply@aygentic.com>
1 parent 4140280 commit 527d999

3 files changed

Lines changed: 37 additions & 13 deletions

File tree

docs/api/endpoints/entities.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
title: "Entities API"
33
doc-type: reference
4-
status: planned
4+
status: active
55
version: "0.1.0"
66
base-url: "/api/v1"
77
last-updated: 2026-02-28
8-
updated-by: "api-docs-writer (AYG-69)"
8+
updated-by: "api-docs-writer (AYG-70)"
99
related-code:
1010
- backend/app/models/entity.py
1111
- backend/app/services/entity_service.py
@@ -15,12 +15,12 @@ related-docs:
1515
- docs/api/overview.md
1616
- docs/architecture/overview.md
1717
- docs/data/models.md
18-
tags: [api, rest, entities, planned]
18+
tags: [api, rest, entities]
1919
---
2020

2121
# Entities API
2222

23-
> **Planned — implementation in AYG-70.** The service layer and data models for this resource are complete (AYG-69). Route handlers have not yet been registered. This document is pre-scaffolded from the service contract so that consumer teams can review the interface before implementation begins. All details are derived directly from `backend/app/models/entity.py` and `backend/app/services/entity_service.py`.
23+
> **Active as of AYG-70.** The entity route handlers are registered and live under `/api/v1/entities`. All five CRUD operations are implemented and tested.
2424
2525
## Overview
2626

@@ -30,12 +30,12 @@ The entities router will provide full CRUD operations for the `Entity` resource.
3030
**Authentication:** Clerk JWT Bearer token — required for all endpoints
3131
**Tag:** `entities`
3232

33-
> **AYG-70 note:** Routes are implemented in AYG-70. The service functions `create_entity`, `get_entity`, `list_entities`, `update_entity`, and `delete_entity` in `backend/app/services/entity_service.py` define the exact behaviour documented here. See [API Overview — Authentication](../overview.md#authentication) for the full Clerk auth flow. All error responses use the [unified error shape](../overview.md#standard-error-responses).
33+
The service functions `create_entity`, `get_entity`, `list_entities`, `update_entity`, and `delete_entity` in `backend/app/services/entity_service.py` define the exact behaviour documented here. See [API Overview — Authentication](../overview.md#authentication) for the full Clerk auth flow. All error responses use the [unified error shape](../overview.md#standard-error-responses).
3434

3535
## Quick Start
3636

3737
```bash
38-
# List your entities (once AYG-70 is merged)
38+
# List your entities
3939
curl -X GET "http://localhost:8000/api/v1/entities" \
4040
-H "Authorization: Bearer <clerk_jwt>"
4141
```

docs/api/overview.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
title: "API Overview"
33
doc-type: reference
4-
status: draft
4+
status: active
55
version: "1.3.0"
66
base-url: "/api/v1"
77
last-updated: 2026-02-28
8-
updated-by: "api-docs-writer (AYG-69)"
8+
updated-by: "api-docs-writer (AYG-70)"
99
related-code:
1010
- backend/app/main.py
1111
- backend/app/api/main.py
@@ -137,7 +137,7 @@ Non-superusers can only access items they own. Accessing another user's item ret
137137

138138
### Entities
139139

140-
> **Planned (AYG-70):** The entity service layer and Supabase-backed data models are complete (AYG-69). Route handlers are not yet registered. The full API contract is pre-scaffolded in [Entities](endpoints/entities.md).
140+
> **Active (AYG-70):** Entity CRUD endpoints are implemented and registered at `/api/v1/entities`. See [Entities API](endpoints/entities.md) for full documentation.
141141
142142
All entity endpoints are scoped to the authenticated caller — `owner_id` isolation is enforced at the service layer, so users can only access their own records.
143143

@@ -404,13 +404,14 @@ CORS allowed origins are controlled by two configuration values:
404404
- [Login & Authentication](endpoints/login.md)
405405
- [Users](endpoints/users.md)
406406
- [Items](endpoints/items.md)
407-
- [Entities](endpoints/entities.md) *(Planned — routes in AYG-70; service layer complete in AYG-69)*
407+
- [Entities](endpoints/entities.md)
408408
- [Utils](endpoints/utils.md)
409409

410410
## Changelog
411411

412412
| Version | Date | Change |
413413
|---------|------|--------|
414+
| 1.4.0 | 2026-02-28 | AYG-70: Entity CRUD route handlers registered; all five endpoints live |
414415
| 1.3.0 | 2026-02-28 | AYG-69: Entity resource forward-reference added; service layer complete, routes planned for AYG-70 |
415416
| 1.2.0 | 2026-02-28 | AYG-68: Operational endpoints (`/healthz`, `/readyz`, `/version`) added at root level; Utils `/health-check/` marked as legacy |
416417
| 1.1.0 | 2026-02-27 | AYG-65: Auth updated to Clerk JWT; unified error response shape documented; `PaginatedResponse[T]` and `offset`/`limit` pagination params documented |

docs/testing/test-registry.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: "Test Registry"
33
doc-type: reference
44
status: draft
55
last-updated: 2026-02-28
6-
updated-by: "architecture-docs-writer"
6+
updated-by: "api-docs-writer (AYG-70)"
77
related-code:
88
- "backend/tests/**/*.py"
99
- "frontend/tests/**/*.spec.ts"
@@ -18,7 +18,7 @@ tags: [testing, quality, registry]
1818

1919
| Module | Unit | Integration | E2E | Total |
2020
|--------|------|-------------|-----|-------|
21-
| backend/api/routes | 0 | 64 | 0 | 64 |
21+
| backend/api/routes | 0 | 82 | 0 | 82 |
2222
| backend/core/config | 13 | 0 | 0 | 13 |
2323
| backend/core/errors | 20 | 0 | 0 | 20 |
2424
| backend/core/logging | 6 | 0 | 0 | 6 |
@@ -35,7 +35,7 @@ tags: [testing, quality, registry]
3535
| frontend/user-settings | 0 | 0 | 14 | 14 |
3636
| frontend/sign-up | 0 | 0 | 11 | 11 |
3737
| frontend/reset-password | 0 | 0 | 6 | 6 |
38-
| **Total** | **114** | **64** | **61** | **239** |
38+
| **Total** | **114** | **82** | **61** | **257** |
3939

4040
> Unit tests in `backend/tests/unit/` can run without database env vars. The conftest guard pattern in that directory skips DB-dependent fixtures automatically.
4141
@@ -131,6 +131,29 @@ tags: [testing, quality, registry]
131131
| test_response_schema_exact (version) | Response has exactly five expected fields | integration | passing |
132132
| test_no_auth_required (version) | Succeeds without Authorization header | integration | passing |
133133

134+
#### Backend — Integration: Entities (`backend/tests/integration/test_entities.py`)
135+
136+
| Test | Description |
137+
|------|-------------|
138+
| `TestCreateEntity::test_create_returns_201_with_entity` | POST /entities returns 201 with created entity body |
139+
| `TestCreateEntity::test_create_sets_owner_id_from_principal` | owner_id set from JWT principal, not request body |
140+
| `TestCreateEntity::test_create_missing_title_returns_422` | Missing required title field returns 422 |
141+
| `TestCreateEntity::test_create_invalid_json_returns_422_with_details` | Empty title string returns 422 with details array |
142+
| `TestListEntities::test_list_returns_200_with_data_and_count` | GET /entities returns 200 with data array and count |
143+
| `TestListEntities::test_list_uses_default_pagination` | Default pagination uses offset=0, limit=20 (range 0-19) |
144+
| `TestListEntities::test_list_rejects_limit_over_100` | limit=200 rejected with 422 via Query constraint |
145+
| `TestListEntities::test_list_rejects_negative_offset` | Negative offset rejected with 422 via Query constraint |
146+
| `TestListEntities::test_list_respects_custom_offset_and_limit` | Custom offset and limit forwarded correctly to service |
147+
| `TestGetEntity::test_get_returns_200_for_owned_entity` | GET /entities/{id} returns 200 with entity data |
148+
| `TestGetEntity::test_get_nonexistent_returns_404` | Non-existent UUID returns 404 with ENTITY_NOT_FOUND code |
149+
| `TestGetEntity::test_get_non_owned_returns_404` | Non-owned entity returns 404 (not 403) for isolation |
150+
| `TestUpdateEntity::test_patch_updates_provided_fields_only` | PATCH updates only provided fields, leaves others unchanged |
151+
| `TestUpdateEntity::test_patch_nonexistent_returns_404` | PATCH non-existent entity returns 404 with ENTITY_NOT_FOUND |
152+
| `TestUpdateEntity::test_patch_empty_body_returns_current_entity` | Empty PATCH body is a no-op returning current entity |
153+
| `TestDeleteEntity::test_delete_returns_204` | DELETE returns 204 No Content with empty body |
154+
| `TestDeleteEntity::test_delete_nonexistent_returns_404` | DELETE non-existent entity returns 404 with ENTITY_NOT_FOUND |
155+
| `TestAuth::test_no_auth_returns_401` | All 5 entity endpoints return 401 without authentication |
156+
134157
### Backend — Unit: Config (`backend/tests/unit/test_config.py`)
135158

136159
| Test Name | Description | Type | Status |

0 commit comments

Comments
 (0)