Files
content-factory/tasks/016-final-approval-gate.md

4.1 KiB

Task 016: Final Approval Gate

Development description: Implement the final review gate that prevents publishing until the editor has approved the exact draft version, assets, evidence state, metadata, and publishing settings.

Implementation Details

  • Backend endpoints:
    • POST /api/articles/{article_id}/final-approval
    • POST /api/articles/{article_id}/final-revision-request
  • Final approval checklist:
    • Plan followed.
    • Evidence reviewed.
    • No high-risk unsupported claims remain.
    • SEO metadata approved.
    • Images/assets approved.
    • Tables and diagrams approved.
    • Internal links approved.
    • Frontmatter fields selected.
    • Content path selected.
    • Author selected.
    • Publishing mode selected.
  • Approval records:
    • Actor.
    • Timestamp.
    • Exact draft version.
    • Selected publishing settings.
  • Revision request returns workflow to FINAL_REVISION_REQUIRED.

Public Interface

  • Editor sees final review checklist.
  • Editor cannot approve while hard blockers remain.
  • Approved article moves to PUBLISH_DRY_RUN_REQUIRED.

Acceptance Criteria

  • TDD pre-requirement: before implementation, write one failing behavior test proving high-risk unsupported claims block final approval; proceed one checklist behavior at a time and record evidence in Result.
  • Final approval requires an exact draft version.
  • High-risk unsupported claims block approval.
  • Missing required publishing settings block approval.
  • Unapproved required assets block approval.
  • Approval writes a workflow event with actor, timestamp, draft version, and publishing settings.
  • Revision request writes event and moves article to FINAL_REVISION_REQUIRED.
  • UI shows blockers and completed checklist items.

Verification

  • Run final approval API tests.
  • Run frontend final review tests.
  • Run smoke flow showing blocked and successful approval paths.

Result

  • Status: Done (TDD RED -> GREEN completed).

  • TDD progression:

    1. Pre-requirement RED test created for high-risk unsupported claims blocker.
    2. Implemented final approval gate service with checklist evaluation on assembled draft + evidence + assets + review state.
    3. Added public endpoints:
      • POST /api/articles/{article_id}/final-approval
      • POST /api/articles/{article_id}/final-revision-request
      • GET /api/articles/{article_id}/final-approval/checklist (for UI checklist visibility).
    4. Added workflow events:
      • FINAL_APPROVAL_GRANTED -> PUBLISH_DRY_RUN_REQUIRED
      • FINAL_REVISION_REQUESTED -> FINAL_REVISION_REQUIRED
    5. Added frontend final-approval feature (FSD) to show blockers/completed checklist items and invoke approval/revision endpoints.
  • Implemented behavior coverage:

    • Exact draft version is required and validated against latest immutable draft.
    • High-risk unsupported claims (claims + section scaffold history) block approval.
    • Missing required publishing settings (frontmatter, content_path, author, publishing_mode) block approval.
    • Unapproved required assets block approval.
    • Successful approval writes event payload with actor/timestamp/draft version/publishing settings and moves state to PUBLISH_DRY_RUN_REQUIRED.
    • Revision request writes event payload and moves state to FINAL_REVISION_REQUIRED.
    • UI renders checklist rows, blockers, and completed items.
  • Verification output:

    • PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_final_approval_gate_public_api.py -> OK (7 tests)
    • PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_seo_language_review_public_api.py -> OK (6 tests)
    • PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_assets_media_library_public_api.py -> OK (7 tests)
    • PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_draft_assembly_public_api.py -> OK (5 tests)
    • node apps/frontend/tests/final_approval.model.test.mjs -> OK
    • pnpm --dir apps/frontend typecheck -> OK