V4 implemented. Some tweaking left, but it is working

This commit is contained in:
Jim Lancaster
2026-08-11 12:07:19 -05:00
parent ccf2c78ff4
commit 0ace10269f
19 changed files with 1379 additions and 79 deletions
+219
View File
@@ -0,0 +1,219 @@
# API Questions & Answers
## Question
```
what is v4_documents.py?
```
## Response
v4_documents.py is the new additive V4 API router I added in Phase 4.
What it does:
- Defines V4 endpoints under /api/v4 for registry-driven document/relationship workflows.
- Exposes read endpoints for catalogs:
- GET /api/v4/document-types
- GET /api/v4/person-roles
- Exposes write endpoints for code-or-id updates:
- PUT /api/v4/documents/{document_id}/type
- POST /api/v4/documents/{document_id}/people
- PATCH /api/v4/document-people/{document_person_id}
- DELETE /api/v4/document-people/{document_person_id}
- Uses DocumentService methods as the backend (no direct DB access in the route layer).
- Returns typed request/response models for backward-compatible, additive API evolution.
It is registered in app.py, so it is live when the app starts.
If you want, I can walk endpoint-by-endpoint with examples of request/response payloads.
---
## Question
```
Please do
```
## Response
Absolutely. Here is a quick endpoint-by-endpoint walkthrough of v4_documents.py, with practical request/response examples.
**What This Router Is**
- Prefix: /api/v4
- Purpose: additive V4 contract for:
1. Registry catalogs (document types, person roles)
2. Role-aware document-person linking
3. Code-or-id document type assignment
- It delegates to DocumentService and does not access DB sessions directly in route handlers.
**Dependency Wiring**
- Route dependency: get_document_service in v4_documents.py
- Behavior:
1. Uses app.state.services.documents when running in the app lifecycle
2. Falls back to a direct DocumentService() instance if needed (useful in isolated tests)
**1) List Document Types**
- Endpoint: GET /api/v4/document-types
- Query param: active_only=true by default
- Backing service call: list_document_types(active_only=...)
- Response shape:
[
{
"id": "uuid",
"code": "letter",
"label": "Letter",
"is_active": true,
"sort_order": 0
}
]
**2) List Person Roles**
- Endpoint: GET /api/v4/person-roles
- Query param: active_only=true by default
- Backing service call: list_person_roles(active_only=...)
- Response shape:
[
{
"id": "uuid",
"code": "author",
"label": "Author",
"is_active": true
}
]
**3) Set Document Type (By Id Or Code)**
- Endpoint: PUT /api/v4/documents/{document_id}/type
- Body options:
1. document_type_id
2. document_type_code
- Rule: provide one selector, not both
- Example request:
{
"document_type_code": "record"
}
- Example response:
{
"document_id": "uuid",
"document_type_id": "uuid",
"document_type_code": "record"
}
**4) List Document-Person Links For A Document**
- Endpoint: GET /api/v4/documents/{document_id}/people
- Backing service call: list_document_people(document_id=...)
- Example response:
{
"document_id": "uuid",
"links": [
{
"id": "uuid",
"document_id": "uuid",
"person_id": "uuid",
"role_id": "uuid",
"role_code": "author",
"person_name": "Zenna Cochran"
}
]
}
**5) Add A Document-Person Link**
- Endpoint: POST /api/v4/documents/{document_id}/people
- Body fields:
1. person_id required
2. role_id optional
3. role_code optional
- If duplicate document/person/role link is attempted, returns conflict envelope via shared error handlers.
- Example request:
{
"person_id": "uuid",
"role_code": "mentioned"
}
- Example success response:
{
"id": "uuid",
"document_id": "uuid",
"person_id": "uuid",
"role_id": "uuid",
"role_code": "mentioned",
"person_name": "Ada Lovelace"
}
**6) Update Link Role**
- Endpoint: PATCH /api/v4/document-people/{document_person_id}
- Body options:
1. role_id
2. role_code
- Rule: provide one selector, not both
- Example request:
{
"role_code": "recipient"
}
- Example response:
{
"id": "uuid",
"document_id": "uuid",
"person_id": "uuid",
"role_id": "uuid",
"role_code": "recipient",
"person_name": "Ada Lovelace"
}
**7) Delete Link**
- Endpoint: DELETE /api/v4/document-people/{document_person_id}
- Response: HTTP 204 No Content
**Error Behavior**
- Uses shared registration in errors.py
- So AppError categories map to consistent envelope + status codes:
1. validation_error -> 400
2. not_found_error -> 404
3. conflict_error -> 409
4. internal_unexpected_error -> 500
**Where It Gets Mounted**
- Included in app factory at app.py
- That makes all /api/v4 endpoints available during normal app startup.
If you want, next I can generate a compact curl-style smoke checklist for all 7 endpoints so you can test them in under 2 minutes.
---
## Question
```
Should there be one of these for people, jobs, and sources too?
```
## Response
Short answer: yes, but not all at once.
Given your V4 scope, the strongest split is:
1. Keep v4_documents.py for document-centric workflows
This file already owns:
- document type catalog/use
- document-person role links
- document-level relationship mutations
2. Add a V4 people router next
Recommended new file:
- src/transcription/api/v4_people.py
Why:
- You likely need person-centric queries and updates that are not naturally document-scoped
- It keeps API boundaries clearer as UI grows
3. Do not rush a separate jobs/sources V4 router unless contracts are diverging
For now, jobs and sources are still tightly tied to the existing transcription pipeline behavior. A new v4_jobs or v4_sources router is useful only when you need genuinely new contract shape, such as:
- job lifecycle contract changes
- source revision/audit contract changes
- new pagination/filtering semantics incompatible with current endpoints
Practical rule of thumb:
1. New router if the domain has new V4 semantics and independent lifecycle
2. Keep existing router if only additive fields are needed
Suggested target structure:
1. v4_documents.py
2. src/transcription/api/v4_people.py
3. optional later: src/transcription/api/v4_jobs.py
4. optional later: src/transcription/api/v4_sources.py
If you want, I can scaffold v4_people next with additive endpoints that mirror your current service capabilities and keep error envelope behavior consistent.