Add Post_Types projector; pivot onboarding SDD to direct AP option writes#31
Add Post_Types projector; pivot onboarding SDD to direct AP option writes#31
Conversation
…ypes Projects AP's stored `activitypub_support_post_types` option into Atmosphere's `atmosphere_syncable_post_types` filter, so the post types a user ticks in AP's settings also federate to Bluesky without a second configuration step. One-way by design. Unlike `Object_Type` — which owns `fosse_object_type` because short-form-vs-WP-post-format is a FOSSE-specific discriminator — post-type selection has no FOSSE-specific semantics. It's exactly what AP already stores, so reusing AP's option avoids a second source of truth that would silently override AP's admin UI on read. The class docblock notes the asymmetry so the pattern isn't reflexively "fixed" later. Registered from fosse.php inside an `init` action with the same `class_exists` guard used for `Object_Type`, so a bare clone without vendor/ still loads the bundled backends without fataling. See DOTCOM-16875. Companion SDD notes at sdd/post-type-sync/.
Flips the "AP settings ownership" decision recorded in PR #25. Original plan was FOSSE-owned `fosse_ap_actor_mode` / `fosse_ap_support_post_types` options projected into AP via `pre_option_*` filters at read time. That silently overrides AP's admin UI — a user toggles a checkbox, FOSSE's filter returns something else on read, admin becomes a lie. The upstream PR thread on Automattic/wordpress-activitypub#3218 made the divergence concrete: `option_activitypub_support_post_types` already exists, which is what a `pre_option_*` projection would ride on, and that's precisely the silent-override mechanism. Single source of truth (AP's option) + direct writes from both surfaces is the clean fix. AP_Provider now writes `activitypub_actor_mode` and `activitypub_support_post_types` with `update_option()` and registers no `pre_option_*` filters. Cross-network post-type sync into Atmosphere is handled separately by `Automattic\Fosse\Post_Types` (DOTCOM-16875). See DOTCOM-16875.
There was a problem hiding this comment.
Pull request overview
Adds a new FOSSE “Post_Types” projector to make ActivityPub’s post-type allowlist the single source of truth and project it into Atmosphere, and updates the onboarding SDD to reflect the pivot away from fosse_ap_* option projection toward direct activitypub_* option writes.
Changes:
- Introduce
Automattic\Fosse\Post_Typesto feedactivitypub_support_post_typesintoatmosphere_syncable_post_types(with sane defaults / corruption handling). - Register the new projector from
fosse.phpalongside the existingObject_Typeregistration guard. - Update onboarding SDD docs (spec/plan/requirements/planned-decisions) and add a decision-trail note doc for the ownership pivot.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/class-post-types.php |
Adds the post-type projector that sources AP’s option and returns it for Atmosphere’s filter. |
fosse.php |
Registers the new projector on init behind a class_exists guard. |
tests/php/Post_TypesTest.php |
Adds unit tests for defaulting, passthrough, empty array behavior, and registration behavior. |
sdd/post-type-sync/notes.md |
Records the decision trail and implementation approach for the ownership pivot + projection. |
sdd/onboarding-setup-ux/spec.md |
Updates the spec from pre_option_* projection to direct writes to AP options + one-way AT projection. |
sdd/onboarding-setup-ux/requirements.md |
Revises the resolved “AP settings ownership” decision to direct activitypub_* writes. |
sdd/onboarding-setup-ux/planned-decisions.md |
Documents the superseded projection plan and the rationale for the direct-write pivot. |
sdd/onboarding-setup-ux/plan.md |
Updates implementation tasks to write activitypub_* directly and removes pre_option_* projection steps. |
|
@RCowles FYI on the SDD amendment. |
Without this, an Atmosphere-only site (no ActivityPub) gets its atmosphere_syncable_post_types filter overridden with an invented ['post'] default — the projector has no source of truth to project when AP isn't loaded.
…osse into post-type-sync-DOTCOM-16875
|
Converting to draft: Codex's adversarial review surfaced a high-severity rollback hazard in the downstream Atmosphere path (narrowing The projector in this PR is correct; the bug lives in Atmosphere and is fixed upstream at Automattic/wordpress-atmosphere#38 (split the publish-time and cleanup-time gates, three PHPUnit cases added). Parking this PR in draft until that lands. Follow-up work (bundled re-sync, FOSSE-side regression test, taking this PR out of draft) tracked at DOTCOM-16909. Decision trail captured in |
Fixes DOTCOM-16875
Summary
Two linked changes around the "who owns the AP option" question:
New
Automattic\Fosse\Post_Typesprojector (src/class-post-types.php) reads AP's storedactivitypub_support_post_typesand feeds it into Atmosphere'satmosphere_syncable_post_typesfilter. A user ticks a post type once in AP's settings; it federates to Mastodon and Bluesky. One-way, no FOSSE-owned option.Onboarding SDD amendment (
sdd/onboarding-setup-ux/). The merged spec (PR SDD: onboarding-setup-ux (requirements + spec + plan) #25) plannedfosse_ap_actor_mode/fosse_ap_support_post_typesoptions projected into AP viapre_option_*filters. Superseded by the direct-write approach: FOSSE's Setup page writes straight toactivitypub_actor_mode/activitypub_support_post_types. AP's admin screen keeps editing the same keys — single source of truth, no divergence.Why the pivot
Original plan for DOTCOM-16875 was a FOSSE-owned
fosse_syncable_post_typesoption projected into both AP and AT via filters, symmetric withObject_Type. Landed Automattic/wordpress-activitypub#3218 to add a dedicated AP filter for that.AP maintainer pushed back: the stock
option_activitypub_support_post_typesfilter already exists,add_post_type_support()covers adds, so a new filter isn't warranted. Fair point — and it made the core issue obvious. Any read-time projection (whether a dedicated filter or the stockoption_*/pre_option_*hooks) silently overrides AP's admin UI: user toggles a checkbox, projection returns something else, admin becomes a lie. Two sources of truth, worst version.New direction: AP's option is canonical. One-way projection into AT only. AP PR closed.
Divergence from the
Object_Typepattern is deliberate — noted in the class docblock. Object-type semantics are FOSSE-specific (force short-form everywhere vs defer); post-type selection is not — it's exactly what AP already stores. Same-shape data, reuse the store.Changes
src/class-post-types.php— new projector class. Readsactivitypub_support_post_types, returns it fromatmosphere_syncable_post_types. Falls back to['post']on missing/corrupted option.fosse.php— newinitaction that callsPost_Types::register()behind the sameclass_existsguard used forObject_Type.tests/php/Post_TypesTest.php— six tests: default on unset option, value returned when set, empty array preserved (don't resurrect federation the user disabled), upstream default discarded, non-array option falls back to default,register()idempotent.sdd/post-type-sync/notes.md— SDD fix record (problem, approach, tasks, decision trail).sdd/onboarding-setup-ux/*.md— spec / plan / requirements / planned-decisions amended.fosse_ap_*option plan replaced with directactivitypub_*writes.Test plan
composer run-script lint-phpcleancomposer run-script test-php— 19/19 pass (6 new)pnpm run format:checkcleanactivitypub_support_post_types, confirm Atmosphere sees['post']activitypub_support_post_typesto['post', 'page'], confirm Atmosphere's filter returns the same