diff --git a/.github/changelog/add-content-mentions b/.github/changelog/add-content-mentions deleted file mode 100644 index 2cda5d48..00000000 --- a/.github/changelog/add-content-mentions +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -Mention a Bluesky account with @handle.tld in your post: the mention now links to their profile on your site, and they are notified on Bluesky even on longer posts. diff --git a/.github/changelog/add-custom-bluesky-text b/.github/changelog/add-custom-bluesky-text deleted file mode 100644 index 46233b5f..00000000 --- a/.github/changelog/add-custom-bluesky-text +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -The editor's Bluesky panel now has a custom text field: write your own message for Bluesky and it is posted with a link back to your post, instead of the automatically composed text. diff --git a/.github/changelog/add-filterable-appview-host b/.github/changelog/add-filterable-appview-host deleted file mode 100644 index a9b2a41e..00000000 --- a/.github/changelog/add-filterable-appview-host +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -Add filters so links to Bluesky can point at an alternative AT Protocol appview, including ones hosted on a subdomain or subpath. diff --git a/.github/changelog/add-per-post-share-toggle b/.github/changelog/add-per-post-share-toggle deleted file mode 100644 index 3c8813b4..00000000 --- a/.github/changelog/add-per-post-share-toggle +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -The editor's Bluesky panel now has a switch to turn sharing on or off for an individual post; switching it off after a post was shared removes it from Bluesky. diff --git a/.github/changelog/add-pre-publish-panel b/.github/changelog/add-pre-publish-panel deleted file mode 100644 index 5550bd11..00000000 --- a/.github/changelog/add-pre-publish-panel +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -Before publishing, the editor now shows whether a post will be shared to Bluesky, how it will appear, and how its text measures against Bluesky’s character limit. diff --git a/.github/changelog/add-publish-retry-backoff b/.github/changelog/add-publish-retry-backoff deleted file mode 100644 index 6d77e899..00000000 --- a/.github/changelog/add-publish-retry-backoff +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -Failed attempts to share a post to Bluesky are now retried automatically for about twenty minutes, so a brief network or server hiccup no longer means the post silently never appears. diff --git a/.github/changelog/add-reactions-block b/.github/changelog/add-reactions-block deleted file mode 100644 index 9b2d216b..00000000 --- a/.github/changelog/add-reactions-block +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -Add an ATmosphere Reactions block that shows the Bluesky likes and reposts that your posts have received, as a facepile of avatars with a count. diff --git a/.github/changelog/add-surface-publish-errors b/.github/changelog/add-surface-publish-errors deleted file mode 100644 index 6221f24f..00000000 --- a/.github/changelog/add-surface-publish-errors +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -The editor now shows a notice when sharing a post to Bluesky fails, including whether it will be retried automatically or needs the post to be updated again. diff --git a/.github/changelog/add-typed-atproto-preview b/.github/changelog/add-typed-atproto-preview deleted file mode 100644 index 2046ae8e..00000000 --- a/.github/changelog/add-typed-atproto-preview +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -Preview AT Protocol output by record type, including an all-record view for comparing records in the current page context. diff --git a/.github/changelog/add-warn-no-post-types-selected b/.github/changelog/add-warn-no-post-types-selected deleted file mode 100644 index 8f96fc5d..00000000 --- a/.github/changelog/add-warn-no-post-types-selected +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: added - -The settings page now warns you when auto-publishing is on but no post types are selected, so nothing would be published. diff --git a/.github/changelog/fix-comment-link-facets b/.github/changelog/fix-comment-link-facets deleted file mode 100644 index f8413684..00000000 --- a/.github/changelog/fix-comment-link-facets +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Links in Bluesky replies now keep their full web address when imported as comments, instead of showing a shortened, unclickable preview. diff --git a/.github/changelog/fix-comment-quote-embed b/.github/changelog/fix-comment-quote-embed deleted file mode 100644 index f48383b6..00000000 --- a/.github/changelog/fix-comment-quote-embed +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Bluesky replies that quote another post now keep a link to the quoted post when imported as comments, instead of dropping it. diff --git a/.github/changelog/fix-decouple-post-delete b/.github/changelog/fix-decouple-post-delete deleted file mode 100644 index 5158eea3..00000000 --- a/.github/changelog/fix-decouple-post-delete +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Deleting a post now reliably removes it from Bluesky even when it has a large number of replies to clean up. diff --git a/.github/changelog/fix-grapheme-truncation b/.github/changelog/fix-grapheme-truncation deleted file mode 100644 index 9338b0cf..00000000 --- a/.github/changelog/fix-grapheme-truncation +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Emoji now count as a single character against Bluesky's 300-character limit, the same way Bluesky's own composer counts them. Posts with emoji are no longer trimmed earlier than necessary, and the editor's character count matches what you would see on Bluesky. diff --git a/.github/changelog/fix-preview-cache-headers b/.github/changelog/fix-preview-cache-headers deleted file mode 100644 index a3da78f5..00000000 --- a/.github/changelog/fix-preview-cache-headers +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Send private, no-cache headers on the record preview so a caching layer cannot store a logged-in preview and show it to other visitors. diff --git a/.github/changelog/fix-preview-front-end-extras b/.github/changelog/fix-preview-front-end-extras deleted file mode 100644 index 35138a3a..00000000 --- a/.github/changelog/fix-preview-front-end-extras +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -The AT Protocol record preview no longer shows sharing buttons or other theme and plugin extras that are not part of the published record. diff --git a/.github/changelog/fix-publication-basic-theme-type b/.github/changelog/fix-publication-basic-theme-type deleted file mode 100644 index 30443eca..00000000 --- a/.github/changelog/fix-publication-basic-theme-type +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Your site's theme colours now display correctly in enhanced link cards on Bluesky and other apps, instead of being dropped because the publication record failed validation. diff --git a/.github/changelog/fix-publication-self-heal b/.github/changelog/fix-publication-self-heal deleted file mode 100644 index fc962072..00000000 --- a/.github/changelog/fix-publication-self-heal +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Shared posts on Bluesky now keep your site's publication details up to date automatically when you publish, so Standard.site readers always see current information. diff --git a/.github/changelog/fix-reaction-sync-cpt-resolution b/.github/changelog/fix-reaction-sync-cpt-resolution deleted file mode 100644 index eaa7afe2..00000000 --- a/.github/changelog/fix-reaction-sync-cpt-resolution +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Import Bluesky likes, reposts, and replies on all your published content types. Previously these interactions were only brought back for standard posts, so likes and replies on pages and other content published to Bluesky were quietly missed. diff --git a/.github/changelog/fix-reaction-sync-oldest-first b/.github/changelog/fix-reaction-sync-oldest-first deleted file mode 100644 index 899f3312..00000000 --- a/.github/changelog/fix-reaction-sync-oldest-first +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Reliably import nested Bluesky replies. Reactions are now processed oldest-first within each sync, so a reply threads under its parent comment in the same run instead of being dropped when a whole thread arrives between syncs. diff --git a/.github/changelog/fix-short-form-inline-links b/.github/changelog/fix-short-form-inline-links deleted file mode 100644 index 3ed7f52c..00000000 --- a/.github/changelog/fix-short-form-inline-links +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Links inside short posts shared to Bluesky now stay clickable, instead of being flattened to plain text with the link dropped. diff --git a/.github/changelog/fix-short-form-overflow b/.github/changelog/fix-short-form-overflow deleted file mode 100644 index 1220a518..00000000 --- a/.github/changelog/fix-short-form-overflow +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Long posts without a title are now shared to Bluesky as a summary with a link back to the original, instead of being cut off mid-sentence with no way to reach the full post. diff --git a/.github/changelog/fix-standard-site-strong-ref-cids b/.github/changelog/fix-standard-site-strong-ref-cids deleted file mode 100644 index 2c8ca29e..00000000 --- a/.github/changelog/fix-standard-site-strong-ref-cids +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Kept standard.site document references in Bluesky posts pointing at the current document record and made discovery URLs resolve more consistently. diff --git a/.github/changelog/fix-unschedule-all-cron-events b/.github/changelog/fix-unschedule-all-cron-events deleted file mode 100644 index 8b870caf..00000000 --- a/.github/changelog/fix-unschedule-all-cron-events +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Disconnecting or deactivating now reliably removes all pending background tasks, so a task queued under a previous connection can no longer run against a newly connected account. diff --git a/.github/changelog/harden-atproto-http-redirects b/.github/changelog/harden-atproto-http-redirects deleted file mode 100644 index 7087fdae..00000000 --- a/.github/changelog/harden-atproto-http-redirects +++ /dev/null @@ -1,4 +0,0 @@ -Significance: patch -Type: fixed - -Hardened the security of connections to your Bluesky account. diff --git a/.github/changelog/raise-minimum-wordpress b/.github/changelog/raise-minimum-wordpress deleted file mode 100644 index b40d73d4..00000000 --- a/.github/changelog/raise-minimum-wordpress +++ /dev/null @@ -1,4 +0,0 @@ -Significance: major -Type: changed - -ATmosphere now requires WordPress 6.5 or later. diff --git a/.github/changelog/update-standard-site-compatibility b/.github/changelog/update-standard-site-compatibility deleted file mode 100644 index 6fc74189..00000000 --- a/.github/changelog/update-standard-site-compatibility +++ /dev/null @@ -1,4 +0,0 @@ -Significance: minor -Type: changed - -Standard.site records and OAuth permissions are now more compatible with current long-form publishing tools and discovery. diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dc09159..a5b0c653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.0] - 2026-07-08 +### Added +- Add an ATmosphere Reactions block that shows the Bluesky likes and reposts that your posts have received, as a facepile of avatars with a count. [#148] +- Add filters so links to Bluesky can point at an alternative AT Protocol appview, including ones hosted on a subdomain or subpath. [#159] +- Before publishing, the editor now shows whether a post will be shared to Bluesky, how it will appear, and how its text measures against Bluesky’s character limit. [#139] +- Failed attempts to share a post to Bluesky are now retried automatically for about twenty minutes, so a brief network or server hiccup no longer means the post silently never appears. [#182] +- Mention a Bluesky account with @handle.tld in your post: the mention now links to their profile on your site, and they are notified on Bluesky even on longer posts. [#165] +- Preview AT Protocol output by record type, including an all-record view for comparing records in the current page context. [#170] +- The editor's Bluesky panel now has a custom text field: write your own message for Bluesky and it is posted with a link back to your post, instead of the automatically composed text. [#152] +- The editor's Bluesky panel now has a switch to turn sharing on or off for an individual post; switching it off after a post was shared removes it from Bluesky. [#139] +- The editor now shows a notice when sharing a post to Bluesky fails, including whether it will be retried automatically or needs the post to be updated again. [#183] +- The settings page now warns you when auto-publishing is on but no post types are selected, so nothing would be published. [#174] + +### Changed +- ATmosphere now requires WordPress 6.5 or later. [#148] +- Standard.site records and OAuth permissions are now more compatible with current long-form publishing tools and discovery. [#167] + +### Fixed +- Bluesky replies that quote another post now keep a link to the quoted post when imported as comments, instead of dropping it. [#157] +- Deleting a post now reliably removes it from Bluesky even when it has a large number of replies to clean up. [#138] +- Disconnecting or deactivating now reliably removes all pending background tasks, so a task queued under a previous connection can no longer run against a newly connected account. [#182] +- Emoji now count as a single character against Bluesky's 300-character limit, the same way Bluesky's own composer counts them. Posts with emoji are no longer trimmed earlier than necessary, and the editor's character count matches what you would see on Bluesky. [#156] +- Hardened the security of connections to your Bluesky account. [#171] +- Import Bluesky likes, reposts, and replies on all your published content types. Previously these interactions were only brought back for standard posts, so likes and replies on pages and other content published to Bluesky were quietly missed. [#185] +- Kept standard.site document references in Bluesky posts pointing at the current document record and made discovery URLs resolve more consistently. +- Links in Bluesky replies now keep their full web address when imported as comments, instead of showing a shortened, unclickable preview. [#134] +- Links inside short posts shared to Bluesky now stay clickable, instead of being flattened to plain text with the link dropped. [#146] +- Long posts without a title are now shared to Bluesky as a summary with a link back to the original, instead of being cut off mid-sentence with no way to reach the full post. [#145] +- Reliably import nested Bluesky replies. Reactions are now processed oldest-first within each sync, so a reply threads under its parent comment in the same run instead of being dropped when a whole thread arrives between syncs. [#186] +- Send private, no-cache headers on the record preview so a caching layer cannot store a logged-in preview and show it to other visitors. [#187] +- Shared posts on Bluesky now keep your site's publication details up to date automatically when you publish, so Standard.site readers always see current information. [#167] +- The AT Protocol record preview no longer shows sharing buttons or other theme and plugin extras that are not part of the published record. [#170] +- Your site's theme colours now display correctly in enhanced link cards on Bluesky and other apps, instead of being dropped because the publication record failed validation. [#154] + ## [1.2.0] - 2026-06-15 ### Security - Hardened error logging so details from cryptographic failures are never written to the log. [#128] @@ -113,6 +147,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Remove a comment reply from Bluesky if the comment was deleted or unapproved while it was being published, instead of leaving an orphan reply behind. [#32] - Short posts under the long-form teaser-thread strategy no longer ship a redundant "continue reading" reply when the entire body already fits in a single Bluesky post. The link-back is preserved as a card on the same post. [#51] +[2.0.0]: https://github.com/Automattic/wordpress-atmosphere/compare/1.2.0...2.0.0 [1.2.0]: https://github.com/Automattic/wordpress-atmosphere/compare/1.1.1...1.2.0 [1.1.1]: https://github.com/Automattic/wordpress-atmosphere/compare/1.1.0...1.1.1 [1.1.0]: https://github.com/Automattic/wordpress-atmosphere/compare/1.0.0...1.1.0 diff --git a/atmosphere.php b/atmosphere.php index 780cc17a..eeda6346 100644 --- a/atmosphere.php +++ b/atmosphere.php @@ -3,7 +3,7 @@ * Plugin Name: ATmosphere * Plugin URI: https://github.com/pfefferle/atmosphere * Description: Publish WordPress posts to AT Protocol (Bluesky + standard.site) via native OAuth. - * Version: 1.2.0 + * Version: 2.0.0 * Author: Automattic * Author URI: https://automattic.com * License: GPL-2.0-or-later @@ -19,7 +19,7 @@ \defined( 'ABSPATH' ) || exit; -\define( 'ATMOSPHERE_VERSION', '1.2.0' ); +\define( 'ATMOSPHERE_VERSION', '2.0.0' ); \define( 'ATMOSPHERE_PLUGIN_DIR', \plugin_dir_path( __FILE__ ) ); \define( 'ATMOSPHERE_PLUGIN_URL', \plugin_dir_url( __FILE__ ) ); \define( 'ATMOSPHERE_PLUGIN_FILE', __FILE__ ); diff --git a/includes/class-atmosphere.php b/includes/class-atmosphere.php index d4e7cef2..4d36acf7 100644 --- a/includes/class-atmosphere.php +++ b/includes/class-atmosphere.php @@ -2015,7 +2015,7 @@ private static function maybe_schedule_publish_retry( string $hook, int $post_id * so the delay schedule and the attempt cap cannot contradict * each other). * - * @since unreleased + * @since 2.0.0 * * @param int[] $delays Retry delays in seconds. Default 60, 300, 900. */ diff --git a/includes/class-blocks.php b/includes/class-blocks.php index bea61bcd..10bd45a7 100644 --- a/includes/class-blocks.php +++ b/includes/class-blocks.php @@ -17,7 +17,7 @@ class Blocks { /** * Wire block registration on `init`. * - * @since unreleased + * @since 2.0.0 * * @return void */ @@ -32,7 +32,7 @@ public static function register(): void { * already renders the same Bluesky reactions (stored as WordPress * comments in the shared shape), so registering ours too would double up. * - * @since unreleased + * @since 2.0.0 * * @return void */ @@ -46,7 +46,7 @@ public static function register_blocks(): void { * already renders these reactions. Return true to force the block on * regardless, or false to suppress it. * - * @since unreleased + * @since 2.0.0 * * @param bool $register Whether to register the reactions block. */ @@ -65,7 +65,7 @@ public static function register_blocks(): void { * overlay/frame/close wiring binds to the modal store created by * `src/shared/modal`. * - * @since unreleased + * @since 2.0.0 * * @param array $args { * Optional. Modal arguments. diff --git a/includes/class-mention.php b/includes/class-mention.php index eecf68f0..951754ef 100644 --- a/includes/class-mention.php +++ b/includes/class-mention.php @@ -16,7 +16,7 @@ /** * Display-side mention linkifier. * - * @since unreleased + * @since 2.0.0 */ class Mention { @@ -111,7 +111,7 @@ public static function the_content( string $content ): string { * mention. Returns empty sets for empty or pathologically large content, * mirroring {@see self::the_content()}, which linkifies neither. * - * @since unreleased + * @since 2.0.0 * * @param string $content Rendered HTML. * @return array{linkable:array,protected:array} @@ -339,7 +339,7 @@ static function ( array $m ): string { * text — e.g. to gate on a cached existence check or an * allowlist of known accounts. * - * @since unreleased + * @since 2.0.0 * * @param bool $should_link Whether to link the handle. Default true. * @param string $handle The bare handle (no leading `@`). diff --git a/includes/functions.php b/includes/functions.php index 1d019f7d..215f5e53 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -72,7 +72,7 @@ function appview_url( string $path, array $context = array() ): string { * the Bluesky appview. To rewrite the path itself (e.g. a custom route), * use the {@see 'atmosphere_appview_url'} filter instead. * - * @since unreleased + * @since 2.0.0 * * @param string $host Default appview host ('bsky.app'). * @param string $path Path being built, e.g. 'profile/'. @@ -90,7 +90,7 @@ function appview_url( string $path, array $context = array() ): string { * route — by rebuilding it from the parts in $context. Return a complete * URL; it is escaped by the caller, not here. * - * @since unreleased + * @since 2.0.0 * * @param string $url Assembled URL, e.g. 'https://bsky.app/profile/'. * @param string $path Path that was appended, e.g. 'profile/'. @@ -670,7 +670,7 @@ function debug_log( string $message ): void { * status (including a 3xx the server would have redirected) is treated * as a failure. Centralizes that check for the OAuth and API callers. * - * @since unreleased + * @since 2.0.0 * * @param mixed $status HTTP status code (int, or '' when the request failed). * @return bool True for 200-299, false otherwise. diff --git a/includes/transformer/class-base.php b/includes/transformer/class-base.php index a5fd1c2f..da8ef99e 100644 --- a/includes/transformer/class-base.php +++ b/includes/transformer/class-base.php @@ -220,7 +220,7 @@ protected function is_post_redacted( \WP_Post $post ): bool { * inside) work from this HTML; callers that only need plain text go through * {@see self::render_post_content_plain()}, which strips tags from it. * - * @since unreleased + * @since 2.0.0 * * @param \WP_Post $post Post object. * @return string diff --git a/includes/transformer/class-comment.php b/includes/transformer/class-comment.php index 0ef27ab7..b2382c5d 100644 --- a/includes/transformer/class-comment.php +++ b/includes/transformer/class-comment.php @@ -109,7 +109,7 @@ public function transform(): array { * A site that trusts its (already moderated) commenters and wants their * mentions to notify can return true to opt back in. * - * @since unreleased + * @since 2.0.0 * * @param bool $resolve Whether to resolve comment mentions. Default false. * @param \WP_Comment $comment The comment being transformed. diff --git a/includes/transformer/class-document.php b/includes/transformer/class-document.php index f0ea0e14..7f1df2ed 100644 --- a/includes/transformer/class-document.php +++ b/includes/transformer/class-document.php @@ -167,7 +167,7 @@ public function transform(): array { * Return an array with a non-empty string `$type` field to add * the `links` field. Return null or an empty array to omit it. * - * @since unreleased + * @since 2.0.0 * * @param array|null $links Links union object, or null to omit. * @param \WP_Post $post WordPress post. @@ -187,7 +187,7 @@ public function transform(): array { * Return a com.atproto.label.defs#selfLabels object to add * content-warning labels. Return null or an empty array to omit it. * - * @since unreleased + * @since 2.0.0 * * @param array|null $labels Self-labels object, or null to omit. * @param \WP_Post $post WordPress post. @@ -208,7 +208,7 @@ public function transform(): array { * sanitized and capped to the lexicon's 100-grapheme limit. * Return null or an empty array to omit the field. * - * @since unreleased + * @since 2.0.0 * * @param array|null $contributors Contributor list, or null to omit. * @param \WP_Post $post WordPress post. diff --git a/includes/transformer/class-facet.php b/includes/transformer/class-facet.php index 58f84b0b..8882aa18 100644 --- a/includes/transformer/class-facet.php +++ b/includes/transformer/class-facet.php @@ -45,7 +45,7 @@ class Facet { * leading class so the Twitter-style dot-mention idiom * (`.@alice.bsky.social`) still resolves and links. * - * @since unreleased + * @since 2.0.0 * * @var string */ @@ -64,7 +64,7 @@ class Facet { * anyway; 20 is a generous headroom over any legitimate post while keeping * the egress bounded. Handles past the cap are ignored (and logged once). * - * @since unreleased + * @since 2.0.0 * * @var int */ @@ -179,7 +179,7 @@ public static function for_urls( string $text, array $urls ): array { * `wp_kses_post()` by the caller (as the reaction-sync path does), so * only the generated `href` attributes are escaped here. * - * @since unreleased + * @since 2.0.0 * * @param string $text Plain-text display string from the record. * @param array $facets Facet array from the record, as stored on the PDS. @@ -464,7 +464,7 @@ private static function mentions( string $text, ?array $blocked = null ): array * guaranteed to produce a `#mention` facet when it reaches a record's * `text`. Shares the regex and resolver used to build mention facets. * - * @since unreleased + * @since 2.0.0 * * @param string $text Plain text. * @return array Map of handle => DID. @@ -488,7 +488,7 @@ public static function resolve_handles( string $text ): array { * first-appearance order, drops handles that don't resolve, and applies the * same {@see self::MAX_RESOLVED_HANDLES} egress cap. * - * @since unreleased + * @since 2.0.0 * * @param string[] $handles Candidate handles (no leading `@`). * @return array Map of handle => DID. @@ -541,7 +541,7 @@ public static function resolve_handle_list( array $handles ): array { * `@alice.com` as already present inside `@alice.company` — and to size the * carry-over line in the DNS-free pre-publish preview. * - * @since unreleased + * @since 2.0.0 * * @param string $text Plain text. * @return array Set of lowercased handles present in the text. @@ -658,7 +658,7 @@ private static function resolve_mention( string $handle ): string { * return true to restore the pre-1.0 fallback and keep the mention * even through a transient resolver blip. * - * @since unreleased + * @since 2.0.0 * * @param bool $fallback Whether to fall back to `did:web:`. Default false. * @param string $handle The handle that failed to resolve. diff --git a/includes/transformer/class-preview.php b/includes/transformer/class-preview.php index d13f5321..d56e215e 100644 --- a/includes/transformer/class-preview.php +++ b/includes/transformer/class-preview.php @@ -213,7 +213,7 @@ private static function transformers( array $defaults, ?\WP_Post $post ): array * same way {@see \Atmosphere\Content_Parser\Registry::register()} * lets a registration override a default by NSID. * - * @since unreleased + * @since 2.0.0 * * @param Base[] $transformers Default transformers for the context. * @param \WP_Post|null $post Queried post, or null on the front page. diff --git a/includes/transformer/class-publication.php b/includes/transformer/class-publication.php index 3979d5e1..f8e9c283 100644 --- a/includes/transformer/class-publication.php +++ b/includes/transformer/class-publication.php @@ -129,7 +129,7 @@ public function transform(): array { * Return a com.atproto.label.defs#selfLabels object to add * content-warning labels. Return null or an empty array to omit it. * - * @since unreleased + * @since 2.0.0 * * @param array|null $labels Self-labels object, or null to omit. */ @@ -152,7 +152,7 @@ public function transform(): array { * the preference entirely and let downstream appviews apply their * own default. * - * @since unreleased + * @since 2.0.0 * * @param bool|null $show_in_discover Whether to show in discovery, or null to omit. */ diff --git a/package.json b/package.json index f7667ab0..e9b6b4ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,5 @@ { "name": "atmosphere", - "version": "1.0.0", "description": "Publish WordPress posts to AT Protocol (Bluesky + standard.site) via native OAuth.", "author": "Automattic", "license": "GPL-2.0-or-later", diff --git a/readme.txt b/readme.txt index 400b6370..f71ba9d3 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: at-protocol, bluesky, fediverse, atproto, crossposting Requires at least: 6.5 Tested up to: 7.0 Requires PHP: 8.2 -Stable tag: 1.2.0 +Stable tag: 2.0.0 License: GPL-2.0-or-later License URI: https://spdx.org/licenses/GPL-2.0-or-later.html @@ -91,118 +91,39 @@ Not at this time. ATmosphere is designed for a single WordPress site. On a Netwo == Changelog == -### 1.2.0 - 2026-06-15 -#### Security -- Hardened error logging so details from cryptographic failures are never written to the log. -- Hardened the Bluesky connect flow so a redirect interruption cannot loosen redirect safety checks for the rest of the request. -- Hardened the Bluesky server address checks to also catch unsafe addresses hidden behind URL encoding. - -#### Added -- Add a Content format setting so you can choose how your posts are saved for standard.site readers — rendered HTML, Markdown, Leaflet, or pckt. -- Add rich content support for standard.site documents using the Markpub format. -- A new `wp atmosphere backfill` WP-CLI command publishes your older posts to Bluesky in bulk from the command line. -- New settings let you stop importing Bluesky likes and reposts, or replies. - -#### Changed -- Keep diagnostic messages out of your site's error log unless WordPress debugging (WP_DEBUG) is turned on. - -#### Removed -- The "Start Backfill" button has moved from the settings page to WP-CLI. Run "wp atmosphere backfill" to sync existing posts. - -#### Fixed -- Accept Bluesky handles entered with a leading "@" — pasting "@alice.bsky.social" now connects just like "alice.bsky.social". -- Apply your auto-publish, post-type, and long-form preferences even when a post is published outside the WordPress admin (REST API, WP-CLI, or scheduled posts). -- Fix domain handle verification failing on some sites when using your site's domain as your Bluesky handle. -- Restore the cover image and Bluesky link preview thumbnail for posts whose featured image is served from a CDN, such as on WordPress.com sites. -- Send your site's theme colours to standard.site in the format the network expects so they show up on your publication page. -- Show a clear error instead of crashing when connecting on a server whose OpenSSL build cannot create the secure key Bluesky requires. -- Stop caches from holding on to a stale domain handle or publication link, so reconnecting or switching accounts takes effect right away. -- Trim very long site titles and taglines when syncing your publication so the record is always accepted by the network. - -### 1.1.1 - 2026-06-01 -#### Added -- Posts shared to Bluesky now link back to both the site's publication record and the per-post document record, so Bluesky shows your site source, profile, and richer document metadata alongside the link preview. - -#### Changed -- Likes and reposts synced from Bluesky now include a readable comment body ("… liked this!" / "… reposted this!") so they display sensibly in themes that render activity-feed comments. - -#### Fixed -- Aside, status, and other short-form posts now include their images when published to Bluesky. -- Fix a fatal error when saving the Bluesky handle on sites without auth keys defined in wp-config.php. -- Fix unexpected disconnections by refreshing the AT Protocol session more reliably. -- Preserve your AT Protocol identity when disconnecting so a custom domain handle (`example.com` instead of `alice.bsky.social`) can be used to reconnect later. Disconnect no longer wipes the verification endpoint that the handle resolver depends on, no longer auto-reverts the Bluesky handle back to its pre-domain value, and shows a clearer "disconnected" notice instead of a "session expired" warning. -- Refresh admin assets after updating, so the latest styles and scripts load correctly. -- Site names and descriptions containing characters like apostrophes or ampersands now publish correctly instead of showing raw HTML codes. -- Stop reinjecting replies into the moderation queue when the parent Bluesky message has been deleted or blocked. -- Your site icon now appears on your standard.site publication. - -### 1.1.0 - 2026-05-21 -#### Added -- Add `atmosphere_post_embed` filter so downstream code can swap the default external link card for a richer embed (`app.bsky.embed.images`, `app.bsky.embed.video`, …) or attach an embed to a short-form post that would otherwise ship with none. The filter accepts `null` (suppress) or an array with a non-empty string `$type` key; non-array, empty-array, or missing-`$type` returns are rejected with `_doing_it_wrong` and the pre-filter value is restored. `Post::upload_thumbnail()` becomes a backward-compatible alias for the new generic `Post::upload_image_blob()`; a new `Post::get_attachment_aspect_ratio()` helper exposes the pixel dimensions consumers need for `embed.images`. -- Advertise the site's standard.site publication record from the front page and from each published post via a new `` tag, alongside the existing document link. - -#### Changed -- Refresh the site's publication record when the site URL, the active theme, or the theme's colours change, so the published record always reflects the current site state. - -#### Fixed -- Fix posts not appearing on Bluesky after a frontend visit lazily stamped the post, restore standard.site verification after reconnecting to a different account, and let the "use my domain as my Bluesky handle" button complete reliably without timing out. -- Stop publishing replies to local-only WordPress comments to Bluesky. Previously such replies were demoted to a top-level reply on the post; they are now skipped so the Bluesky thread only mirrors comments whose ancestors are also on Bluesky. - -### 1.0.0 - 2026-05-20 -#### Security -- Harden OAuth and PDS HTTP request paths against SSRF, encrypt the temporary DPoP key used during connect, and validate URLs received from third-party servers before they are used or stored. -- Tighten DPoP proof lifetime when talking to the AT Protocol auth server and PDS, and harden the OAuth and PDS HTTP paths against malformed server responses. -- Tighten OAuth redirect handling, validate hook return values from third-party plugins, gate DNS lookups for @mentions, and clean up additional plugin data on uninstall. - +### 2.0.0 - 2026-07-08 #### Added -- Add extensible content parser support and a JSON preview endpoint for AT Protocol records. -- Add `atmosphere_publish_post_result` and `atmosphere_publish_comment_result` actions so subscribers can react to publish success or failure (e.g., for metrics and notifications) without observing internal state. -- Add `atmosphere_should_sync_reply` filter so consumers can suppress specific incoming replies before they become WordPress comments — primarily useful for teaser-thread publishers that don't want their own follow-up records re-ingested as self-replies. -- Automatically sync the publication record when the site name, tagline, or site icon changes. -- Choose how long-form posts publish to Bluesky from the ATmosphere settings page — link card (default), a single post combining body text with the permalink, or a two-post teaser thread. -- Choose which post types are published to AT Protocol from the ATmosphere settings page. Plugins and themes can also opt their custom post types in directly with `add_post_type_support( 'your_type', 'atmosphere' )`. -- Liftoff! ATmosphere has cleared the troposphere — version 1.0 is now generally available. -- Long-form posts can now be published to Bluesky as a short thread that points readers back to the full article. Sites can keep the existing single-post behavior, publish a shortened text version with a link, or use a two-post teaser thread. When a threaded post is edited, ATmosphere updates the existing Bluesky posts when possible so links and replies stay connected. If the publishing format changes, ATmosphere replaces the old Bluesky posts with new ones. -- Preserve the connection success notice after completing Bluesky setup, and let integrating plugins customize the OAuth callback destination. -- Publish replies from registered WordPress users to Bluesky as native replies, with edit and unapprove/delete synced back to the AT Protocol record. -- Request the identity:handle permission when connecting to Bluesky so handle changes can be kept in sync. -- Short-form posts (untitled or with a post format) now publish as native Bluesky posts instead of link cards, matching the ActivityPub plugin's Note discriminator. Added the `atmosphere_is_short_form_post` filter for downstream override. -- Sync Bluesky replies, likes, and reposts back as WordPress comments. -- Use your site domain as your Bluesky handle with one click from the ATmosphere settings page. -- Use your WordPress domain as your Bluesky handle with automatic domain verification. +- Add an ATmosphere Reactions block that shows the Bluesky likes and reposts that your posts have received, as a facepile of avatars with a count. +- Add filters so links to Bluesky can point at an alternative AT Protocol appview, including ones hosted on a subdomain or subpath. +- Before publishing, the editor now shows whether a post will be shared to Bluesky, how it will appear, and how its text measures against Bluesky’s character limit. +- Failed attempts to share a post to Bluesky are now retried automatically for about twenty minutes, so a brief network or server hiccup no longer means the post silently never appears. +- Mention a Bluesky account with @handle.tld in your post: the mention now links to their profile on your site, and they are notified on Bluesky even on longer posts. +- Preview AT Protocol output by record type, including an all-record view for comparing records in the current page context. +- The editor's Bluesky panel now has a custom text field: write your own message for Bluesky and it is posted with a link back to your post, instead of the automatically composed text. +- The editor's Bluesky panel now has a switch to turn sharing on or off for an individual post; switching it off after a post was shared removes it from Bluesky. +- The editor now shows a notice when sharing a post to Bluesky fails, including whether it will be retried automatically or needs the post to be updated again. +- The settings page now warns you when auto-publishing is on but no post types are selected, so nothing would be published. #### Changed -- Always use HTTPS for the AT Protocol OAuth callback URL, and keep encrypted connection tokens out of the always-loaded options cache. -- Improved Bluesky connection reliability and disconnect speed, fixed a rare duplicate-record issue when publishing simultaneously from multiple workers, and now respects your comment moderation and spam filter settings when importing Bluesky reactions and replies. -- Improve the development test setup so automated tests can run while another local WordPress environment is already using the default ports. -- Limit backfill to the 10 most recent unsynced posts to avoid overwhelming the server on large sites. -- Long-form teaser threads now use a 3-post default (hook, body chunk, "continue reading" reply with a link card), so the thread reliably surfaces on bsky.app profiles and the terminal post offers a clear path back to the WordPress article. -- Redesign the settings page to use the standard WordPress Settings API for a cleaner, more consistent admin experience. -- Replace third-party JWT library with native OpenSSL signing and add a custom class autoloader. +- ATmosphere now requires WordPress 6.5 or later. +- Standard.site records and OAuth permissions are now more compatible with current long-form publishing tools and discovery. #### Fixed -- Break up large cleanup batches when removing a post and its replies so deletion still completes on threads with many comments. -- Clear every plugin-owned scheduled event on deactivate and uninstall so leftover jobs don't linger after the plugin is removed. -- Clear queued sync events on disconnect, deactivation, and uninstall so leftover jobs cannot fire against a different connected account. -- Editing a WordPress post that was published before connecting to Bluesky no longer creates a new Bluesky post on save. Use the Backfill tool to sync existing posts on purpose. -- Fix auto-publish being disabled by default after saving settings. -- Fix PHPCS warnings about unprefixed global variables and hook names. -- Fix published posts being incorrectly deleted from Bluesky when editing. -- Fix restoring a trashed post not republishing it to Bluesky. -- Fix the settings page, meta box, and backfill actions not loading after the previous admin hook change. -- Keep your AT Protocol verification headers and publishing preferences in place when your session expires. Reconnect is required to resume publishing, but your settings no longer reset and standard.site verification keeps working. -- Move scheduled action hook registration into the standard plugin initialization flow. -- Preserve remote cleanup of already-synced posts when their post type is removed from the syncable allowlist. -- Preserve the OAuth connection when token refresh fails due to temporary server errors. -- Prevent concurrent token refreshes from racing each other and accidentally disconnecting the plugin. -- Prevent password-protected or otherwise non-public posts from being published to AT Protocol records, and remove existing records when public posts become protected. -- Remove a comment reply from Bluesky if the comment was deleted or unapproved while it was being published, instead of leaving an orphan reply behind. -- Short posts under the long-form teaser-thread strategy no longer ship a redundant "continue reading" reply when the entire body already fits in a single Bluesky post. The link-back is preserved as a card on the same post. - -[1.2.0]: https://github.com/Automattic/wordpress-atmosphere/compare/1.1.1...1.2.0 -[1.1.1]: https://github.com/Automattic/wordpress-atmosphere/compare/1.1.0...1.1.1 -[1.1.0]: https://github.com/Automattic/wordpress-atmosphere/compare/1.0.0...1.1.0 -[1.0.0]: https://github.com/Automattic/wordpress-atmosphere/releases +- Bluesky replies that quote another post now keep a link to the quoted post when imported as comments, instead of dropping it. +- Deleting a post now reliably removes it from Bluesky even when it has a large number of replies to clean up. +- Disconnecting or deactivating now reliably removes all pending background tasks, so a task queued under a previous connection can no longer run against a newly connected account. +- Emoji now count as a single character against Bluesky's 300-character limit, the same way Bluesky's own composer counts them. Posts with emoji are no longer trimmed earlier than necessary, and the editor's character count matches what you would see on Bluesky. +- Hardened the security of connections to your Bluesky account. +- Import Bluesky likes, reposts, and replies on all your published content types. Previously these interactions were only brought back for standard posts, so likes and replies on pages and other content published to Bluesky were quietly missed. +- Kept standard.site document references in Bluesky posts pointing at the current document record and made discovery URLs resolve more consistently. +- Links in Bluesky replies now keep their full web address when imported as comments, instead of showing a shortened, unclickable preview. +- Links inside short posts shared to Bluesky now stay clickable, instead of being flattened to plain text with the link dropped. +- Long posts without a title are now shared to Bluesky as a summary with a link back to the original, instead of being cut off mid-sentence with no way to reach the full post. +- Reliably import nested Bluesky replies. Reactions are now processed oldest-first within each sync, so a reply threads under its parent comment in the same run instead of being dropped when a whole thread arrives between syncs. +- Send private, no-cache headers on the record preview so a caching layer cannot store a logged-in preview and show it to other visitors. +- Shared posts on Bluesky now keep your site's publication details up to date automatically when you publish, so Standard.site readers always see current information. +- The AT Protocol record preview no longer shows sharing buttons or other theme and plugin extras that are not part of the published record. +- Your site's theme colours now display correctly in enhanced link cards on Bluesky and other apps, instead of being dropped because the publication record failed validation. See full Changelog on [GitHub](https://github.com/Automattic/wordpress-atmosphere/blob/trunk/CHANGELOG.md).