Skip to content

Resync bundled backends + switch photo-post AT projector onto atmosphere_post_embed#164

Merged
kraftbj merged 5 commits into
trunkfrom
update/bundled-resync-and-atmosphere-post-embed-DOTCOM-17143
May 20, 2026
Merged

Resync bundled backends + switch photo-post AT projector onto atmosphere_post_embed#164
kraftbj merged 5 commits into
trunkfrom
update/bundled-resync-and-atmosphere-post-embed-DOTCOM-17143

Conversation

@kraftbj
Copy link
Copy Markdown
Contributor

@kraftbj kraftbj commented May 20, 2026

Refs DOTCOM-17143.

Resyncs both bundled backends to current upstream trunk and refactors Photo_Post_Atmosphere onto the focused embed seam introduced upstream by wordpress-atmosphere PR 72.

Upstream SHAs

  • wordpress-activitypub trunk → 31cdcd0a (Add blurhash term to JSON-LD context)
  • wordpress-atmosphere trunk → 2a0383a (Re-sync publication on theme and site-URL changes)

Notable upstream changes brought in

Atmosphere:

  • atmosphere_post_embed filter + Post::upload_image_blob() / Post::get_attachment_aspect_ratio() helpers (wordpress-atmosphere PR 72) — the surface the second commit targets. Post::upload_thumbnail() remains as a back-compat alias for Publication / Document callers.
  • Re-sync publication on theme / site-URL changes (PR 76) and publication link tag for standard.site discovery (PR 75).
  • Publishing classifier, publication URI staleness, and handle-button hang fixes after the 1.0.0 cut (PR 74).
  • Atmosphere 1.0.0 release (PR 73). The bundled copy still reports ATMOSPHERE_VERSION = 'unreleased' because we vendor trunk, not the release tag.

ActivityPub:

  • toot:blurhash declared in the JSON-LD context (PR 3327). Pairs with FOSSE's own Blurhash injection so the field validates against Mastodon's schema without a FOSSE-side @context shim.
  • SWICG basic-profile conformance improvements for C2S (PR 3328) and supporting OAuth scope / token refactors.
  • Tombstone migration and post-types helper changes.

Photo-post projector refactor

The previous shape (PR 156) deliberately targeted the shipped Atmosphere surface — atmosphere_transform_bsky_post plus Post::upload_thumbnail() — so the photo-post AT federation worked the moment that PR landed, with or without PR 72 upstream. The class docblock called out the cleaner two-line switchover for when PR 72 made it into the bundled copy. That's this commit.

Three filter callbacks now do the work:

Filter Role
atmosphere_is_short_form_post Force the short-form path for photo posts. Unchanged.
atmosphere_post_embed (new) Build app.bsky.embed.images from up to 4 uploaded blob refs. All upload / overflow / featured-image-bail logic lives here.
atmosphere_transform_bsky_post (slimmed) Rewrite the record's text and re-extract facets. Now gated on record.embed.$type === 'app.bsky.embed.images' so a fully-failed upload pass leaves Atmosphere's default short-form text in place.

Other cleanups:

  • upload_blob() calls Post::upload_image_blob() (the documented successor). Functional behavior unchanged.
  • get_aspect_ratio() delegates to Post::get_attachment_aspect_ratio() so every downstream image-embed consumer reads dimensions the same way (including the is_numeric() sanitation that helper applies — protects against a unit-suffixed string like "1600px" propagating as a misleading integer).

Failure-mode posture (unchanged from PR 156)

  • Featured-image upload failure → embed filter returns input unchanged (null for short-form). Atmosphere ships text-only. A gallery missing its hero shot is worse than no gallery.
  • Non-featured upload failure → drop that attachment, log, keep going.
  • Every upload failed → embed filter returns input unchanged; if the post body is also empty, log so the silent "user federated literally nothing" outcome surfaces.
  • Filter / upload exceptions caught per-attachment so one misbehaving listener can't crater the federation event.
  • Synchronous blob uploads bounded by fosse_photo_post_atmosphere_upload_budget_seconds (default 30s).

Tests

  • 28 photo-post tests pass (the existing 26 plus 2 new ones covering the embed-filter contract directly: non-short-form strategy pass-through and non-WP_Post second-arg pass-through).
  • The apply_transform_filter() helper now simulates Atmosphere's full composition order — run atmosphere_post_embed, attach result, then run atmosphere_transform_bsky_post — so the embed-attached → text-rewritten chain is exercised end-to-end the way shipped Atmosphere does it inside Post::transform().

Known regressions from the bundled resync

Three OAuth callback tests in Admin\Bluesky_ProviderTest started failing with the Atmosphere resync (not introduced by the photo-post refactor):

  • test_handle_oauth_callback_success_emits_success_notice
  • test_handle_oauth_callback_warns_when_connection_not_persisted
  • test_handle_oauth_callback_warns_when_sync_publication_fails

Atmosphere's OAuth client was substantially rewritten upstream (~1000 lines changed in includes/oauth/class-client.php). The FOSSE-side stubs in fake_atmosphere_oauth_environment() / intercept_token_endpoint_success() need to be refreshed against the new request flow. Filing as a separate follow-up so this resync isn't held up — flagging here so it isn't a surprise on the next test run.

The pre-existing BlurhashTest and Blurhash_CLITest failures on trunk are unchanged by this PR.

Testing instructions

  • composer test-php -- --filter Photo_Post_Atmosphere — 28/28 pass.
  • composer lint-php -- src/class-photo-post-atmosphere.php tests/php/Photo_Post_AtmosphereTest.php — clean.
  • Manual: publish a WP post with post format = Image and a single image + caption. Confirm the federated Bluesky record carries embed.$type === "app.bsky.embed.images" (Flashes / Pinksky render it as a native image post; web bsky.app shows it inline). Toggle off Photo_Post::is_photo_post() via the fosse_is_photo_post filter and confirm the record reverts to embed.$type === "app.bsky.embed.external" (today's default link card).

kraftbj added 3 commits May 20, 2026 14:21
Refreshes bundled/activitypub/ and bundled/atmosphere/ via
tools/sync-bundled.sh.

Upstream SHAs:
- wordpress-activitypub trunk -> 31cdcd0a
- wordpress-atmosphere  trunk -> 2a0383a

Notable Atmosphere changes brought in:
- atmosphere_post_embed filter plus Post::upload_image_blob() /
  Post::get_attachment_aspect_ratio() helpers (PR 72). The next
  commit refactors Photo_Post_Atmosphere onto this surface.
  Post::upload_thumbnail() remains as a back-compat alias.
- Re-sync publication on theme / site-URL changes (PR 76) and
  publication link tag for standard.site discovery (PR 75).
- Publishing classifier, publication URI staleness, and handle
  button hang fixes after the 1.0.0 release cut (PR 74).
- Atmosphere 1.0.0 release (PR 73). The bundled copy still reports
  ATMOSPHERE_VERSION = 'unreleased' because the vendored tree is
  trunk, not a tagged release.

Notable ActivityPub changes brought in:
- toot:blurhash declared in the JSON-LD context (PR 3327). Pairs
  with FOSSE's Blurhash injection so the field validates against
  Mastodon's schema.
- SWICG basic-profile conformance improvements for C2S (PR 3328)
  and supporting OAuth scope / token refactors.
- Tombstone migration and post-types helper changes.

Known regressions from this resync (not introduced by FOSSE code):
- 3 Admin\Bluesky_ProviderTest::test_handle_oauth_callback_*
  cases now fail. Atmosphere's OAuth client was substantially
  rewritten; the fosse-side stubs in fake_atmosphere_oauth_environment()
  need to be updated to match the new request flow. Tracking
  separately so this resync isn't held up.
wordpress-atmosphere PR 72 added a focused atmosphere_post_embed
filter for swapping the embed attached to a Bluesky post record,
plus a renamed Post::upload_image_blob() (with upload_thumbnail() as
a backward-compatible alias) and a public
Post::get_attachment_aspect_ratio() helper that centralizes
metadata-driven aspectRatio resolution. With the previous commit
resyncing the bundled copy, the projector can target that focused
seam instead of leaning on the wider atmosphere_transform_bsky_post
for embed work.

The refactor splits the projector across two filters:

  - atmosphere_post_embed (new) - builds the
    app.bsky.embed.images envelope. All upload / overflow /
    featured-image-bail logic lives here. When uploads fail
    (featured image, all attachments, or budget exhaustion) the
    filter returns the input embed unchanged so Atmosphere
    cleanly ships short-form text with no embed.

  - atmosphere_transform_bsky_post (existing, slimmed) - rewrites
    the record's text and re-extracts facets. Now gated on
    record.embed.$type === 'app.bsky.embed.images' so a fully-
    failed upload pass leaves Atmosphere's default short-form text
    in place; rewriting to a caption-only string when no images
    actually shipped would strip useful body content.

atmosphere_is_short_form_post stays put - still the right seam to
force the short-form path for photo posts.

Other changes:

  - upload_blob() now calls Post::upload_image_blob() (the
    documented successor name). Functional behavior unchanged.
  - get_aspect_ratio() now delegates to
    Post::get_attachment_aspect_ratio() so every downstream
    image-embed consumer reads dimensions the same way (including
    the unit-suffix sanitation that helper applies).

Tests:

  - apply_transform_filter() helper now simulates Atmosphere's
    full composition: run atmosphere_post_embed first, attach the
    result onto the record, then run atmosphere_transform_bsky_post.
    Mirrors the call order inside shipped Post::transform().
  - 2 new tests cover the new embed-filter contract directly:
    pass-through for non-short-form strategies and pass-through on
    a non-WP_Post second arg.
  - Existing 26 tests pass unchanged - the helper transparently
    adds the new filter to the round-trip.

Refs DOTCOM-17143.
@kraftbj kraftbj marked this pull request as ready for review May 20, 2026 19:49
Copilot AI review requested due to automatic review settings May 20, 2026 19:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR resyncs the vendored ActivityPub and ATmosphere backends to newer upstream trunk SHAs, and updates FOSSE’s Photo_Post_Atmosphere projector to use ATmosphere’s newer atmosphere_post_embed seam for emitting app.bsky.embed.images on Bluesky.

Changes:

  • Resync bundled activitypub and atmosphere plugins to newer upstream revisions (includes substantial OAuth, publishing, and cleanup changes).
  • Refactor Photo_Post_Atmosphere to build the image embed via atmosphere_post_embed, and gate caption/facet rewriting on the images embed actually being attached.
  • Update/extend tests to simulate ATmosphere’s composition order and to accommodate upstream OAuth transient shape changes.

Reviewed changes

Copilot reviewed 35 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/class-photo-post-atmosphere.php Switches photo-post projection to build embeds via atmosphere_post_embed and rewrites text/facets only when an images embed is present.
tests/php/Photo_Post_AtmosphereTest.php Updates helper pipeline to run atmosphere_post_embed before atmosphere_transform_bsky_post; adds defensive embed-filter tests.
tests/php/Admin/Onboarding_WizardTest.php Seeds atmosphere_identity to avoid warnings when testing corrupted connection shapes after upstream identity split.
tests/php/Admin/Bluesky_ProviderTest.php Updates OAuth test fixtures to match upstream’s encrypted DPoP JWK transient format.
bundled/atmosphere/vendor/composer/installed.php Vendored upstream resync metadata (reference SHA update).
bundled/atmosphere/uninstall.php Vendored upstream resync: expanded uninstall cleanup (options/meta/transients) and broader scheduled-hook clearing.
bundled/atmosphere/readme.txt Vendored upstream resync: readme updates including 1.0.0 changelog content.
bundled/atmosphere/includes/wp-admin/class-admin.php Vendored upstream resync: admin UX + OAuth redirect hardening + metadata filter validation.
bundled/atmosphere/includes/transformer/class-tid.php Vendored upstream resync: persisted monotonic TID floor + safer clock id seeding.
bundled/atmosphere/includes/transformer/class-publication.php Vendored upstream resync: validates transform filter return type before use.
bundled/atmosphere/includes/transformer/class-post.php Vendored upstream resync: adds atmosphere_post_embed seam, redaction support, and stronger filter-return validation.
bundled/atmosphere/includes/transformer/class-facet.php Vendored upstream resync: safer mention resolution and handle validation.
bundled/atmosphere/includes/transformer/class-document.php Vendored upstream resync: redaction support, DID provenance meta, and safer filter handling.
bundled/atmosphere/includes/transformer/class-comment.php Vendored upstream resync: redaction guard and safer filter handling.
bundled/atmosphere/includes/transformer/class-base.php Vendored upstream resync: central redaction predicate for transformers.
bundled/atmosphere/includes/oauth/class-resolver.php Vendored upstream resync: wp_safe_remote_* usage, SSRF/url validation, and DID-doc hardening.
bundled/atmosphere/includes/oauth/class-nonce-storage.php Vendored upstream resync: nonce keying includes DID.
bundled/atmosphere/includes/oauth/class-dpop.php Vendored upstream resync: adds exp to DPoP proof payload.
bundled/atmosphere/includes/oauth/class-client.php Vendored upstream resync: encrypted transient storage, refresh locking, revocation worker, and rate limiting.
bundled/atmosphere/includes/functions.php Vendored upstream resync: identity split helpers + publishability predicates + expanded cron hook management.
bundled/atmosphere/includes/class-reaction-sync.php Vendored upstream resync: moderation pipeline for imported reactions and safer post lookup.
bundled/atmosphere/includes/class-publisher.php Vendored upstream resync: publishability gating + reconcile cleanup paths + deterministic comment ordering.
bundled/atmosphere/includes/class-handle.php Vendored upstream resync: handle update timeout and identity/connection sync behavior.
bundled/atmosphere/includes/class-backfill.php Vendored upstream resync: uses publishability predicate and excludes password-protected posts.
bundled/atmosphere/includes/class-atmosphere.php Vendored upstream resync: publication link tag, visibility cleanup migration, and broader lifecycle hardening.
bundled/atmosphere/includes/class-api.php Vendored upstream resync: uses wp_safe_remote_request and hardens JSON decode.
bundled/atmosphere/atmosphere.php Vendored upstream resync: version bump and deactivation hook cleanup semantics.
bundled/activitypub/includes/rest/oauth/class-token-controller.php Vendored upstream resync: adds Retry-After header on 429 error responses.
bundled/activitypub/includes/rest/oauth/class-clients-controller.php Vendored upstream resync: standardized 429 responses with Retry-After.
bundled/activitypub/includes/rest/oauth/class-authorization-controller.php Vendored upstream resync: standardized 429 responses with Retry-After.
bundled/activitypub/includes/oauth/class-token.php Vendored upstream resync: exposes activitypub_actor_id alongside IndieAuth me.
bundled/activitypub/includes/oauth/class-server.php Vendored upstream resync: advertises supported scopes via Scope::supported().
bundled/activitypub/includes/oauth/class-scope.php Vendored upstream resync: normalizes/advertises Basic Profile canonical scope aliases.
bundled/activitypub/includes/activity/class-base-object.php Vendored upstream resync: adds blurhash terms to JSON-LD context.
bundled/activitypub/includes/activity/class-activity.php Vendored upstream resync: adds blurhash term mapping.
bundled/activitypub/composer.json Vendored upstream resync: dev dependency bump.
Comments suppressed due to low confidence (1)

src/class-photo-post-atmosphere.php:223

  • $attempted is used to enforce the 4-image cap, but it’s incremented on failed uploads too. If a post has >4 candidate attachments and one of the early (non-featured) uploads fails, the loop will treat later attachments as overflow and stop trying to fill the remaining slots, potentially emitting fewer than MAX_IMAGES even though more successful uploads were available. Consider tracking the cap based on the number of successfully attached images (e.g., separate counters for scanned vs attached) so non-featured failures don’t reduce the final image count.

@kraftbj kraftbj merged commit a0f4321 into trunk May 20, 2026
13 checks passed
@kraftbj kraftbj deleted the update/bundled-resync-and-atmosphere-post-embed-DOTCOM-17143 branch May 20, 2026 20: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.

2 participants