sso_hint on .rose-ash.com was blocked by Safari ITP — the exact
problem we're solving. Replaced with redirect chain: account logout
chains through each client app's /auth/sso-clear to clear all
first-party sessions without any cross-domain cookies.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When account logs out and deletes sso_hint, client apps now detect
the missing cookie and clear their local session on next request.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All client apps (including federation) now redirect to account for OAuth.
Factory excludes account from OAuth client blueprint registration.
SSO logout chains through account instead of federation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Federation sets sso_hint=1 on .rose-ash.com after magic link login
- Client apps: before_request checks sso_hint, triggers silent OAuth
once per session (sso_checked flag prevents loops)
- Logout clears sso_hint cookie on all apps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Account's / requires login, so redirecting there after logout
triggers silent OAuth re-authentication. Blog home is safe.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Nav sign-in links point to account_url('/') instead of login_url()
- After-request hook clears old blog_session cookie on .rose-ash.com
(prevents collision with new per-app first-party cookies)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The federation auth blueprint is mounted at /auth, so the authorize
endpoint is /auth/oauth/authorize, not /oauth/authorize.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The logged-in user links in _full_user.html (desktop + mobile)
still used blog_url — now they use federation_url to match
the account page migration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auth templates and widget nav links now point to
federation_url instead of blog_url, co-locating the
account UI with the auth system in the federation app.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fuzzy ILIKE search across remote actors and local profiles, with
WebFinger resolution for @user@domain queries. Supports page-based
pagination for infinite scroll.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Paginated query for market listings — supports optional container filtering
and returns (dtos, has_more) for infinite scroll.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When container_type/container_id are None, returns all upcoming
confirmed entries across all calendars (for global event listings).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New paginated query for upcoming confirmed entries across all calendars
belonging to a container (page). Used by the events page summary view.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each app's EventProcessor now filters by origin_app so apps don't steal
each other's pending activities. emit_activity() and publish_activity()
auto-detect the app name from Quart's current_app.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Logs which handlers are registered at startup and which handlers are
found/called when processing each activity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After Delete + re-Create, Mastodon tombstones the old object ID and
ignores new Creates with the same ID. Now appends /v2, /v3 etc. so
remote servers treat re-publishes as fresh posts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Templates were incorrectly identified as dead code because individual
apps override them, but other apps still depend on the shared versions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Delete shared/models/domain_event.py (table dropped, model orphaned)
- Delete 39 shared templates that are overridden by app-local copies:
- 8 blog overrides (blog/_action_buttons, post/_meta, etc.)
- 27 events overrides (calendar/*, day/*, entry/*, post_entries/*)
- 4 market overrides (market/index, browse/_oob_elements, etc.)
These shared copies were never served — Quart loads app-level
templates first, so the app-local versions always win.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The cart app has its own override with ticket support. The shared
copy was never used and would only cause confusion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When login_url() is called from a different app (e.g. cart), the
anonymous cart_sid is in that app's session cookie. Pass it as a
query parameter so the auth app can store it and use it for adoption.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The login URL is cross-origin (blog app), so hx-get can't load it
into the current page. Use a regular <a href> for cross-app navigation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All cross-service events now flow through ap_activities with a unified
EventProcessor. Internal events use visibility="internal"; federation
activities use visibility="public" and get delivered by a wildcard handler.
- Add processing columns to APActivity (process_state, actor_uri, etc.)
- New emit_activity() / register_activity_handler() API
- EventProcessor polls ap_activities instead of domain_events
- Rewrite all handlers to accept APActivity
- Migrate all 7 emit_event call sites to emit_activity
- publish_activity() sets process_state=pending directly (no emit_event bridge)
- Migration to drop domain_events table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds get_followers_paginated and get_actor_timeline to FederationService
protocol + SQL implementation + stubs. Includes accumulated federation
changes: models, DTOs, delivery handler, webfinger, inline publishing,
widget nav templates, and migration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mastodon verifies the object id domain matches the actor domain.
Using the post URL (coop.rose-ash.com) as object id caused silent
rejection. Now always uses {activity_id}/object on federation domain.
Also adds to/cc on object for visibility determination.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Federation activities are now created at write time via try_publish()
instead of relying on async event handlers. Fixes race condition where
multiple EventProcessors could consume post.published events in apps
that couldn't meaningfully process them.
AP delivery (federation.activity_created → inbox POST) stays async.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use .scalars().first() + LIMIT 1 instead of scalar_one_or_none()
which crashes when multiple activities exist for the same source
- Allow re-Create after Delete (re-publish after unpublish)
- Add missing on_post_unpublished handler to root shared copy
- Sync add_follower upsert fix to root shared
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- on_post_unpublished handler sends Delete/Tombstone activity
- Create/Update objects use post URL as id (for Delete reference)
- Delete objects use Tombstone type
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Edit: placeholder "Page title..." vs "Post title..."
- Settings: slug placeholder, featured checkbox, custom template
all say "page" when is_page is true
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pages are container/landing pages, not blog posts. Hide the like
button, tags/authors bar, and excerpt when post.is_page is true.
Feature image and content still render for both.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The adoption logic soft-deleted ALL user entries before adopting
anonymous session entries. This nuked confirmed/ordered bookings
every time the user logged in. Add state="pending" filter so only
stale pending entries are cleared.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 3-5 of ActivityPub integration:
- Federation handlers: post.published, calendar_entry.created, product.listed
→ publish_activity() for AP outbox
- AP delivery handler: federation.activity_created → sign + POST to follower
inboxes with HTTP Signatures
- IPFS storage wired into publish_activity() (best-effort)
- Anchoring utility: merkle trees + OpenTimestamps Bitcoin timestamping
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>