Skip to content

feat(posts): soft-delete, archive, and restore lifecycle for posts - #69

Merged
aji70 merged 2 commits into
MyFanss:mainfrom
devoclan:feature/post-soft-delete-archive-restore
Jul 29, 2026
Merged

feat(posts): soft-delete, archive, and restore lifecycle for posts#69
aji70 merged 2 commits into
MyFanss:mainfrom
devoclan:feature/post-soft-delete-archive-restore

Conversation

@devoclan

Copy link
Copy Markdown
Contributor

closes #56

PR: Implement Post Soft-Delete, Archive, Restore & Tombstone Lifecycle

Overview

This PR aligns post deletion behavior with the platform's user lifecycle by replacing hard deletes with a soft-delete workflow. Deleted posts are now recoverable, excluded from public-facing content, accessible through an archive for creators, and support consistent tombstone semantics for existing engagement.

The implementation ensures that creators can safely manage their content without permanently removing data through the public API while maintaining predictable behavior across feeds, post retrieval, likes, and comments.


What Changed

Database & Schema**

  • Added deletedAt timestamp to the Post entity.
  • Added optional deletedById support for future auditability.
  • Created indexes to efficiently exclude soft-deleted posts from public queries.
  • Added migration to backfill existing posts with deletedAt = NULL.

API Endpoints**

Implemented the following lifecycle endpoints:

  • Soft Delete

    • DELETE /api/v1/creators/me/posts/:id
    • Marks a post as deleted by setting deletedAt
    • Returns 204 No Content
    • Idempotent (repeated deletes return 204)
  • Archive Listing

    • GET /api/v1/creators/me/posts/archived
    • Supports pagination (cursor/page and limit)
    • Returns only the authenticated creator's archived posts
  • Restore

    • POST /api/v1/creators/me/posts/:id/restore
    • Restores a soft-deleted post
    • Restored posts become visible again in public endpoints

Read Path Updates

Updated all public queries to automatically exclude soft-deleted posts, including:

  • Creator public posts
  • Feed endpoints
  • Single post retrieval

Engagement Behavior

Implemented consistent handling for deleted posts:

  • New likes and comments on deleted posts return 404
  • Existing engagement is hidden behind tombstone semantics where applicable
  • Public listings never expose soft-deleted content

Authorization

Access control has been updated to ensure:

  • Only the post owner can soft-delete a post
  • Only the post owner can restore a post
  • Attempts to restore another creator's post return 403/404
  • No creator-facing hard delete endpoint exists

Idempotency

Implemented predictable API behavior:

  • Deleting an already deleted post returns 204 No Content
  • Restoring a non-deleted post returns 409 Conflict (documented behavior)

Audit Logging

Added audit events for:

  • Post soft deletion
  • Post restoration

This provides traceability for lifecycle actions without exposing deleted content publicly.


Documentation

Added:

  • docs/post-lifecycle.md
  • Swagger documentation updates for new endpoints
  • Lifecycle behavior documentation covering archive, restore, engagement, and visibility rules

Testing

Added comprehensive test coverage including:

  • Soft-deleted posts are hidden from public endpoints
  • Archived posts appear in creator archive
  • Restored posts become publicly visible again
  • Likes/comments on deleted posts follow documented behavior
  • Non-owner cannot delete or restore posts
  • Idempotent delete behavior
  • Restore edge cases
  • Migration coverage
  • Entity/service unit tests
  • Existing hard-delete tests updated for soft-delete lifecycle

Total Coverage: ≥10 tests

Acceptance Criteria Checklist

  • No hard delete through creator API
  • Public read paths exclude soft-deleted posts
  • Archive endpoint implemented
  • Restore endpoint implemented
  • Audit events added
  • Database migration included
  • Swagger updated
  • Lifecycle documentation added
  • Test coverage (10+ tests)
  • CI passing

Out of Scope

  • Legal hold support
  • GDPR media binary purge
  • Permanent admin purge endpoint (retention policy documented instead)

devoclan and others added 2 commits July 29, 2026 19:23
Posts were hard-deleted while users were already soft-deleted. Aligns
posts with the same lifecycle: DELETE now soft-deletes (idempotent),
adds GET .../archived and POST .../:id/restore, filters deletedAt out
of every active-post read path (owner list, public/subscriber feed,
single-post lookup), and defines the engagement contract deleted posts
must uphold for future likes/comments via assertPostIsEngageable.
@aji70
aji70 merged commit 59ca0c0 into MyFanss:main Jul 29, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Post Soft-Delete, Archive, Restore & Tombstone Semantics (Hard)

2 participants