Skip to content
This repository was archived by the owner on Aug 11, 2026. It is now read-only.
This repository was archived by the owner on Aug 11, 2026. It is now read-only.

Issue 2: Implement Blog Post Admin API and Lifecycle Actions #538

Description

@ahliweb

Parent Epic: #536
Depends on: #537

Objective

Implement tenant-scoped admin API for blog post CRUD and lifecycle actions.

Context

This issue builds on the blog_content schema and permission foundation. It must use existing AWCMS-Mini API, auth, tenant, RBAC/ABAC, idempotency, audit, and response patterns.

Scope

  • List posts
  • Create post
  • Read post detail
  • Update post
  • Soft-delete post
  • Submit post for review
  • Publish post
  • Schedule post
  • Archive post
  • Restore post
  • Purge post
  • Enforce auth, tenant context, RBAC/ABAC, idempotency, audit, and RLS

Out of Scope

  • Pages API
  • Taxonomy API
  • Public blog rendering
  • Admin UI
  • Template/widget/menu/ads implementation

Routes

GET    /api/v1/blog/posts
POST   /api/v1/blog/posts
GET    /api/v1/blog/posts/{id}
PATCH  /api/v1/blog/posts/{id}
DELETE /api/v1/blog/posts/{id}

POST   /api/v1/blog/posts/{id}/submit-review
POST   /api/v1/blog/posts/{id}/publish
POST   /api/v1/blog/posts/{id}/schedule
POST   /api/v1/blog/posts/{id}/archive
POST   /api/v1/blog/posts/{id}/restore
POST   /api/v1/blog/posts/{id}/purge

Permission Mapping

GET list/detail              -> blog_content.posts.read
POST create                  -> blog_content.posts.create
PATCH update                 -> blog_content.posts.update
DELETE soft-delete           -> blog_content.posts.delete
POST submit-review           -> blog_content.posts.update
POST publish                 -> blog_content.posts.publish
POST schedule                -> blog_content.posts.schedule
POST archive                 -> blog_content.posts.archive
POST restore                 -> blog_content.posts.restore
POST purge                   -> blog_content.posts.purge

ABAC Rules

Minimum rules:

  • Cross-tenant access must always be denied.
  • Author may edit own draft post if the post is not published.
  • Author may not publish unless granted blog_content.posts.publish.
  • Editor/Admin with permission may edit all tenant posts.
  • Restore and purge require explicit restore/purge permission.
  • Purge is forbidden for published content unless archived or soft-deleted first.

Idempotency Requirements

Require Idempotency-Key for:

POST /api/v1/blog/posts/{id}/publish
POST /api/v1/blog/posts/{id}/schedule
POST /api/v1/blog/posts/{id}/archive
POST /api/v1/blog/posts/{id}/restore
POST /api/v1/blog/posts/{id}/purge

Recommended for:

POST /api/v1/blog/posts
PATCH /api/v1/blog/posts/{id}

Audit Requirements

Record audit events for:

blog.post.created
blog.post.updated
blog.post.submitted_for_review
blog.post.published
blog.post.scheduled
blog.post.archived
blog.post.deleted
blog.post.restored
blog.post.purged

Audit attributes must use existing redaction patterns. Do not log raw tokens, emails, phone numbers, secrets, or sensitive identifiers.

Acceptance Criteria

  • All routes require authenticated session.
  • All routes require tenant context.
  • Existing tenant context helper is reused.
  • Existing ABAC/RBAC guard pattern is reused.
  • Default deny works when permission is absent.
  • Cross-tenant post access is denied.
  • Author can edit own draft only when allowed by ABAC.
  • Author cannot publish without publish permission.
  • Editor/Admin with permission can publish tenant posts.
  • Status transition rules are validated.
  • Slug uniqueness is enforced per tenant and locale.
  • Content is stored as structured JSON plus searchable plain text.
  • Unsafe HTML/script/embed content is rejected or sanitized.
  • Delete uses soft delete.
  • Restore requires explicit permission.
  • Purge requires explicit permission and audit.
  • High-risk actions require Idempotency-Key.
  • High-risk actions write audit events.
  • Error responses do not expose stack traces.
  • OpenAPI is updated.
  • Integration tests cover CRUD, ABAC, audit, idempotency, and RLS.

Validation Commands

bun run db:migrate
bun run api:spec:check
bun run test
bun run typecheck

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions