Today, any publish → !publish transition schedules atmosphere_delete_post, which removes the post's records from both Bluesky and standard.site. That treats every WordPress non-publish state — draft, private, pending, trash — identically: "the post is gone, remove the mirror."
That's defensible. It's also got a real footgun.
The problem
Bluesky engagement attaches to the specific record (AT-URI + CID). Likes, reposts, replies, and quote posts all point at that record. Delete the record, and that engagement is pointed at a tombstone. AT Protocol does let rkeys be reused after deletion, so a subsequent re-publish creates a fresh record cleanly — but it has zero engagement history.
Concrete: user publishes a post, picks up 50 likes and a few reposts. They notice a typo, click "Switch to Draft" to fix it, re-publish. The original record is gone. Fresh re-publish has zero interactions and there's no path to recover them.
Surprising, effectively undoable, and "fix a typo" is a normal flow.
Trade-off
- Strict mirror (current): anything out of public WordPress view should be out of public Bluesky too. Visibility treated consistently.
- Engagement preservation: most "unpublish" on WordPress is a temporary edit, not a permanent retraction. Distinguishing those preserves engagement, at the cost of a window where draft content's mirror is still live.
Possible directions
- Trash-only delete. Only
wp_trash_post / permanent delete trigger remote cleanup. Draft / private / pending leave the record alone. Pro: preserves engagement on the typo-fix flow. Con: a draft or private post still has a public Bluesky mirror.
- Pause on draft, delete on trash. Same outcome, framed as soft-pause vs. hard-delete.
- Filter/setting to opt in. Default stays as today; expose a hook for sites that want trash-only semantics.
- Status quo, document it. Current behavior is defensible if users understand "draft = delete." Probably weak if the footgun lands in practice.
Out of scope
This is not about the syncable-allowlist gate conflation — that's fixed in #38. Splitting the gate is a strict bug fix; this issue is the broader policy question raised during that PR review.
Background
Surfaced in @pfefferle's review of #38. The Mastodon-flavored concern there ("can't republish with the same ID") doesn't translate one-to-one — AT Protocol allows rkey reuse — but the engagement-loss problem is real and worth resolving on its own terms.
Today, any
publish → !publishtransition schedulesatmosphere_delete_post, which removes the post's records from both Bluesky and standard.site. That treats every WordPress non-publish state —draft,private,pending,trash— identically: "the post is gone, remove the mirror."That's defensible. It's also got a real footgun.
The problem
Bluesky engagement attaches to the specific record (AT-URI + CID). Likes, reposts, replies, and quote posts all point at that record. Delete the record, and that engagement is pointed at a tombstone. AT Protocol does let rkeys be reused after deletion, so a subsequent re-publish creates a fresh record cleanly — but it has zero engagement history.
Concrete: user publishes a post, picks up 50 likes and a few reposts. They notice a typo, click "Switch to Draft" to fix it, re-publish. The original record is gone. Fresh re-publish has zero interactions and there's no path to recover them.
Surprising, effectively undoable, and "fix a typo" is a normal flow.
Trade-off
Possible directions
wp_trash_post/ permanent delete trigger remote cleanup. Draft / private / pending leave the record alone. Pro: preserves engagement on the typo-fix flow. Con: a draft or private post still has a public Bluesky mirror.Out of scope
This is not about the syncable-allowlist gate conflation — that's fixed in #38. Splitting the gate is a strict bug fix; this issue is the broader policy question raised during that PR review.
Background
Surfaced in @pfefferle's review of #38. The Mastodon-flavored concern there ("can't republish with the same ID") doesn't translate one-to-one — AT Protocol allows rkey reuse — but the engagement-loss problem is real and worth resolving on its own terms.