Skip to content

feat(blog): add revision history and rollback workflow for blog posts - #50

Merged
maydayv7 merged 7 commits into
devfrom
feature/blog-revision-history
Sep 5, 2026
Merged

feat(blog): add revision history and rollback workflow for blog posts#50
maydayv7 merged 7 commits into
devfrom
feature/blog-revision-history

Conversation

@RsbhThakur

@RsbhThakur RsbhThakur commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Closes #32.

Follows up on #28 and #39 to implement a complete Blog Revision History system. Published posts now maintain an immutable, chronological snapshot history of every version across direct admin edits, approved member revisions, and rollbacks. Both administrators and member authors can inspect visual diffs against live content or previous versions, and restore historical snapshots with strict RBAC guarantees.


Key Changes

1. Data Model & Storage Strategy

  • Dedicated Collection (BlogPostRevision):
    • Revisions are persisted in a separate BlogPostRevision collection rather than an unbounded subdocument array on BlogPost, preventing document bloat, fragmentation, and the 16MB BSON limit.
    • Stores full immutable snapshots: postId, slug, version, title, content, excerpt, coverImage, coverFocalPoint, tags, authors, editor, approvedBy, source ("initial_publish" | "admin_edit" | "approved_revision" | "rollback"), restoredFromVersion, changeSummary, and createdAt.
    • Compound unique index { postId: 1, version: -1 } guarantees atomic version sequences, with secondary indexes on { slug: 1, createdAt: -1 }.
  • Zero-Migration Backwards Compatibility:
    • recordRevisionSnapshot automatically synthesizes and seeds a Version 1 baseline snapshot for legacy published posts on their next edit, ensuring seamless upgrades with zero downtime or database backfills.

2. Mutation Integration & Snapshot Capture

  • Publication Lifecycle:
    • POST /api/admin/blog: Automatically records Version 1 when a post is created directly as published.
    • PATCH /api/admin/blog/[slug]: Records Version 1 when transitioning a draft to published, or increments the version snapshot on direct admin content changes.
    • POST /api/admin/blog/[slug]/revision: Records a version snapshot upon admin approval of a member edit, attributing the author as editor and the approving admin as approvedBy.
    • DELETE /api/admin/blog/[slug]: Cascades deletion to remove all associated historical snapshots when a post is permanently deleted.

3. API Endpoints & Role-Based Restores

  • Admin Revision Routes (/api/admin/blog/[slug]/revisions):
    • GET: Lists version summaries (omits heavy Markdown bodies) or retrieves a specific version's full content.
    • POST /api/admin/blog/[slug]/revisions/[version]/restore: Reverts the live post directly to an earlier snapshot, records a "rollback" snapshot in history, writes a fail-closed audit log, and invalidates the edge cache.
  • Member Author Revision Routes (/api/internal/blog/[slug]/revisions):
    • GET: Lists version summaries for posts authored by the requesting user (isBlogAuthor).
    • POST /api/internal/blog/[slug]/revisions/[version]/restore: Restores historical content into the staged draft (pendingRevision) without modifying live content, strictly preserving the review and approval safeguards introduced in PR feat(blog): allow members to edit published posts with approval workflow #39.

4. UI & Visual Diffing

  • Editor Toolbar Integration (BlogEditorToolbar):
    • Added a "Revision history" clock icon button next to the preview and save controls, active in both /admin/blog/[slug]/edit and /internal/blog/[slug]/edit.
  • Interactive Revision History Modal (RevisionHistoryModal):
    • Two-pane layout: Left pane renders a chronological timeline with version badges, relative timestamps, author/approver badges, and commit notes.
    • Multi-mode diff inspector: Compare selected version with Live (live), with Previous (vN-1), or view raw markdown.
    • Contextual restore actions: Tailored confirmation modals for admins ("Revert Live Post") and authors ("Load into Staged Draft").

@RsbhThakur
RsbhThakur force-pushed the feature/blog-revision-history branch 2 times, most recently from 144a4df to 3f5d040 Compare September 5, 2026 11:14
@RsbhThakur
RsbhThakur marked this pull request as ready for review September 5, 2026 11:23
@RsbhThakur RsbhThakur changed the title Feature/blog revision history feat(blog): add revision history and rollback workflow for blog posts Sep 5, 2026
@maydayv7

maydayv7 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor
  1. Always check permissions and other state within the API call (in src/app/api/internal/blog/[slug]/revisions/[version]/restore/route.ts) like so to prevent race conditions and ensure security. I've also mentioned this in your previous PR.
  2. Unpublishing and republishing loses history?
  3. Restore overwrites drafts awaiting review.

RsbhThakur and others added 5 commits September 6, 2026 01:54
…elpers

Add BlogPostRevision Mongoose schema to store historical snapshots of published blog posts. Implement recordRevisionSnapshot domain helper with version sequencing and legacy post fallback, along with unit tests.
… endpoints

Record revision snapshots on blog publish, direct admin edits, and revision approvals. Cascade delete revisions on post deletion. Add endpoints for admins and authors to list revision history and restore versions.
Generalize RevisionDiffViewer with custom labels. Add RevisionHistoryModal with timeline, diff comparison modes, and restore workflows. Connect revision history trigger to admin and member blog edit toolbars.
…n history

Cover initial publication, direct admin edits, revision approval, version listing and details, admin live restore, author draft restore, RBAC, and cascade deletion.
@RsbhThakur
RsbhThakur force-pushed the feature/blog-revision-history branch from 37c5497 to 8778fa9 Compare September 5, 2026 20:25
@RsbhThakur

Copy link
Copy Markdown
Contributor Author

Thanks for the review @maydayv7! Fixed all three points:

  1. Permission check: Moved the user and permission checks directly inside the database transaction so there's no risk of race conditions or state changes slipping through.
  2. Unpublish / republish history: Fixed this so taking a post down and republishing it keeps the full revision history intact instead of wiping the past versions.
  3. Protected pending reviews: Restoring an old version is now blocked if an author currently has changes submitted and waiting for admin review, so unreviewed work won't get accidentally overwritten.

Also added tests covering all three cases. Let me know if everything looks good to merge!

@maydayv7
maydayv7 merged commit 68d9631 into dev Sep 5, 2026
1 check passed
@maydayv7
maydayv7 deleted the feature/blog-revision-history branch September 5, 2026 21:30
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.

Blog Revision History

2 participants