# Task 014: Assets And Media Library Development description: Implement asset specifications, generated or uploaded asset records, object-storage file handling, approval/rejection, replacement, and a media library view. ## Implementation Details - Backend endpoints: - `POST /api/articles/{article_id}/assets/generate-specs` - `GET /api/articles/{article_id}/assets` - `PATCH /api/articles/{article_id}/assets/{asset_id}` - `POST /api/articles/{article_id}/assets/{asset_id}/approve` - Upload/replacement endpoint for asset files. - Asset types: - Hero image. - Inline diagram. - Table. - Flowchart. - Comparison matrix. - Architecture diagram. - Inline image. - Asset record fields: - Title. - Type. - Prompt or diagram/table code. - File URL/object key. - Alt text. - Caption. - Status. - Linked section/article. - Frontend: - Asset review page. - Media library. - Replacement upload. - Approval/rejection controls. ## Public Interface - Editor reviews generated asset specs. - Editor approves, rejects, or replaces assets. - Approved assets are included in draft/publish bundle. ## Acceptance Criteria - [x] TDD pre-requirement: before implementation, write one failing public API test for approving an asset and seeing it become available to the article; proceed one asset behavior at a time and record evidence in `Result`. - [x] Asset specs are generated and linked to article or section. - [x] File uploads store objects in object storage and persist object keys. - [x] Asset approval writes workflow event. - [x] Rejected assets are excluded from publish bundle. - [x] Replacement preserves audit history. - [x] Media library lists article assets with status, type, title, preview/file link, alt text, and caption. - [x] Draft preview uses approved asset references where available. ## Verification - Run asset API tests. - Run object-storage upload integration tests. - Run frontend media library tests. - Run smoke flow approving and replacing an asset. ## Result - Status: Implementation completed, acceptance criteria closed. - TDD plan: 1. Keep RED pre-requirement test that calls approve API and asserts asset visibility in article context. 2. Expand integration tests to cover full assets lifecycle: specs generation, upload, approve/reject, replacement audit, and draft-facing inclusion/exclusion behavior. 3. Implement API contracts + persistence + routes + object storage integration. 4. Add frontend media library model/UI and draft preview asset reference resolution. - Red evidence: - Initial pre-requirement failure: `POST /api/articles/{article_id}/assets/{asset_id}/approve` returned `404 Not Found`. - During implementation hardening: transient runtime bug `NameError: name 'approved' is not defined` in `approve_asset` (fixed), confirmed by rerun to green. - Green evidence: - Backend assets suite now green with 7 integration tests, including: - specs linked to sections, - upload persists `object_key` and writes object file, - approval writes workflow event, - rejected asset excluded from assembled draft publish-facing data, - replacement keeps full audit history. - Draft assembly and parallel production suites remain green after assets integration. - Frontend media-library model tests and typecheck are green. - Refactor notes: - Added dedicated assets application module and routes. - Extended object storage adapter with `put_bytes`. - Added persistent `asset_revisions` history table and API-visible history payload. - Updated shared OpenAPI contracts and generated TS types. - Verification output: - `PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_assets_media_library_public_api.py` - `Ran 7 tests ... OK` - `PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_draft_assembly_public_api.py` - `Ran 5 tests ... OK` - `PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_parallel_production_public_api.py` - `Ran 6 tests ... OK` - `node apps/frontend/tests/article_assets.model.test.mjs` - `OK` (exit code `0`) - `node apps/frontend/tests/draft_editor.model.test.mjs` - `OK` (exit code `0`) - `pnpm --dir apps/frontend typecheck` - `tsc --noEmit` completed successfully.