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>
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>