---
estimated_steps: 39
estimated_files: 3
skills_used: []
---

# T02: Add version API endpoints, schemas, and integration tests

Add Pydantic schemas for version responses, API endpoints for version list and version detail, extend TechniquePageDetail with version_count, and write integration tests covering the full flow.

## Failure Modes

| Dependency | On error | On timeout | On malformed response |
|------------|----------|-----------|----------------------|
| PostgreSQL query | SQLAlchemy raises → FastAPI returns 500 | N/A (local) | N/A |
| Missing technique slug | Return 404 with clear message | N/A | N/A |
| Missing version number | Return 404 with clear message | N/A | N/A |

## Negative Tests

- **Malformed inputs**: GET /techniques/nonexistent-slug/versions → 404; GET /techniques/{slug}/versions/999 → 404
- **Boundary conditions**: Technique with zero versions → empty list response; version_count = 0 on fresh page

## Steps

1. Add Pydantic schemas to `backend/schemas.py`:
   - `TechniquePageVersionSummary`: version_number (int), created_at (datetime), pipeline_metadata (dict | None)
   - `TechniquePageVersionDetail`: version_number (int), content_snapshot (dict), pipeline_metadata (dict | None), created_at (datetime)
   - `TechniquePageVersionListResponse`: items (list[TechniquePageVersionSummary]), total (int)
   - Add `version_count: int = 0` field to `TechniquePageDetail`

2. Add endpoints to `backend/routers/techniques.py`:
   - `GET /{slug}/versions` — query TechniquePageVersion rows for the page, ordered by version_number DESC. Return TechniquePageVersionListResponse. 404 if slug not found.
   - `GET /{slug}/versions/{version_number}` — return single TechniquePageVersionDetail. 404 if slug or version not found.

3. Modify the existing `get_technique` endpoint to include `version_count` by counting TechniquePageVersion rows for the page.

4. Write integration tests in `backend/tests/test_public_api.py`:
   - Test version list returns empty for page with no versions
   - Test version list returns versions after inserting a TechniquePageVersion row directly
   - Test version detail returns correct content_snapshot
   - Test version detail 404 for nonexistent version number
   - Test technique detail includes version_count field
   - Test versions endpoint 404 for nonexistent slug

5. Run all existing tests to confirm no regressions.

## Must-Haves

- [ ] TechniquePageVersionSummary, TechniquePageVersionDetail, TechniquePageVersionListResponse schemas
- [ ] version_count field on TechniquePageDetail
- [ ] GET /{slug}/versions endpoint returns version list sorted by version_number desc
- [ ] GET /{slug}/versions/{version_number} endpoint returns full content snapshot
- [ ] 404 responses for missing slug or version number
- [ ] Integration tests pass for all version endpoints
- [ ] All existing tests still pass

## Verification

- `cd backend && python -m pytest tests/test_public_api.py -v` — all tests pass including new version tests
- `cd backend && python -m pytest tests/ -v` — full test suite passes (no regressions)

## Inputs

- ``backend/models.py` — TechniquePageVersion model created in T01`
- ``backend/schemas.py` — existing TechniquePageDetail schema to extend with version_count`
- ``backend/routers/techniques.py` — existing technique detail endpoint to modify and add version endpoints`
- ``backend/tests/test_public_api.py` — existing test file with seed helpers and test patterns to follow`
- ``backend/tests/conftest.py` — test fixtures (db_engine, client) for async integration tests`

## Expected Output

- ``backend/schemas.py` — TechniquePageVersionSummary, TechniquePageVersionDetail, TechniquePageVersionListResponse schemas added; version_count field added to TechniquePageDetail`
- ``backend/routers/techniques.py` — GET /{slug}/versions and GET /{slug}/versions/{version_number} endpoints added; get_technique modified to include version_count`
- ``backend/tests/test_public_api.py` — integration tests for version list, version detail, version_count on technique detail, and 404 cases`

## Verification

cd backend && python -m pytest tests/test_public_api.py -v && python -m pytest tests/ -v --timeout=60
