98 lines
4.3 KiB
Markdown
98 lines
4.3 KiB
Markdown
# 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.
|