Commit Graph

82 Commits

Author SHA1 Message Date
giles
16df62e2c4 Sign-in button → account app, clear old shared cookie
- 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>
2026-02-23 10:56:56 +00:00
giles
ea35e040e7 Fix OAuth authorize URL: include /auth prefix
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>
2026-02-23 10:25:46 +00:00
giles
46f44f6171 OAuth SSO infrastructure + account app support
- OAuthCode model + migration for authorization code flow
- OAuth client blueprint (auto-registered for non-federation apps)
- Per-app first-party session cookies (fixes Safari ITP)
- /oauth/authorize endpoint support in URL helpers
- account_url() helper + Jinja global
- Templates: federation_url('/auth/...') → account_url('/...')
- Widget registry: account page links use account_url

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:55:27 +00:00
giles
326b380135 Fix root top-bar account link to point to federation
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>
2026-02-23 09:07:38 +00:00
giles
ea8e7da9d4 Move account page URLs from blog to federation
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>
2026-02-23 09:00:44 +00:00
giles
bd18d0befc Route auth to federation: login_url default, logout URL, federation_url global
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:41:18 +00:00
giles
5bed4a6c78 Update README: coop_url → blog_url
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:35:16 +00:00
giles
798087de9a Rename coop to blog throughout codebase
- coop_url() → blog_url(), AUTH_APP default → "blog"
- Session cookie: coop_session → blog_session
- Config keys: coop_root/coop_title → market_root/market_title
- All Jinja templates: coop_url → blog_url, coop_title → market_title
- Template blocks: coop-child-header → blog-child-header

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:32:46 +00:00
giles
cc22b21b18 Rename coop.rose-ash.com to blog.rose-ash.com in comment
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:27:54 +00:00
giles
f085d4a8d0 Add search_actors to FederationService for paginated actor search
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>
2026-02-23 08:18:43 +00:00
giles
b16ba34b40 Add list_marketplaces to MarketService protocol, impl, and stub
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>
2026-02-22 23:29:14 +00:00
giles
16e4d3aa57 Make upcoming_entries_for_container work without container filter
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>
2026-02-22 23:04:55 +00:00
giles
6e438dbfdc Add upcoming_entries_for_container to CalendarService
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>
2026-02-22 22:28:18 +00:00
giles
7316dc6eac Add 'updated' timestamp to Update activity objects for Mastodon
Mastodon requires an updated field to process post edits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:41:18 +00:00
giles
a3a41dbefd Allow repeated Update activities for post edits
The dedup guard was blocking legitimate edits after the first Update.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:36:15 +00:00
giles
30b5a1438b Change AP_DOMAIN default to federation.rose-ash.com
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:12:28 +00:00
giles
0e89dbee55 Make origin_app migration idempotent
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 20:59:19 +00:00
giles
86ccfd25c5 Add origin_app to APActivity — apps only process their own activities
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>
2026-02-22 20:57:46 +00:00
giles
b42f5d63db Add debug logging to EventProcessor and activity handler registry
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>
2026-02-22 20:49:37 +00:00
giles
2e48760b38 Fix AP re-publish: use versioned object IDs after Delete
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>
2026-02-22 19:59:48 +00:00
giles
9cdd2195df Restore all 33 deleted shared templates
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>
2026-02-22 19:26:48 +00:00
giles
46f6ca4a0f Remove dead code: domain_event.py + 39 overridden templates
- 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>
2026-02-22 18:09:02 +00:00
giles
7de4a2e40e Remove dead shared _cart.html template
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>
2026-02-22 18:05:17 +00:00
giles
1c1ab3576f Pass cart_sid through login URL for cross-app cart adoption
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>
2026-02-22 17:46:08 +00:00
giles
07aa2e2be9 Fix cart sign-in button: use plain link instead of HTMX
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>
2026-02-22 17:37:16 +00:00
giles
2e9db11925 Unify domain_events + ap_activities into AP-shaped event bus
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>
2026-02-22 16:19:29 +00:00
giles
d697709f60 Tech debt cleanup: fix session.py, remove stale references, update docs
- db/session.py: fix indentation (2→4 space), pool_size=0 (unlimited),
  remove "ned to look at this" typo
- Remove glue.models from alembic env.py import list
- Update shared __init__.py, menu_item.py docstring, calendar_impl.py,
  handlers/__init__.py to remove glue terminology
- Remove federation_handlers.py tombstone file
- Remove TODO comments (replace with explanatory comments)
- Rewrite README.md to reflect current architecture
- Update anchoring.py TODO to plain comment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:11:31 +00:00
giles
04f7c5e85c Add fediverse social features: followers/following lists, actor timelines
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>
2026-02-22 13:41:58 +00:00
giles
eec750a699 Fix AP object id: must be on actor's domain (Mastodon origin check)
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>
2026-02-22 08:52:56 +00:00
giles
fd163b577f Inline federation publication + fix AP delivery
- Replace async federation_handlers with inline try_publish() at write sites
- Fix ap_delivery_handler: urlparse for signature path/host, @context array
  with security vocab, Delete/Tombstone object handling
- Fix federation_impl: @context array for IPFS, .limit(1) + upsert follower

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 08:24:29 +00:00
giles
3bde451ce9 Inline federation publication, remove async handlers
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>
2026-02-22 07:54:14 +00:00
giles
798fe56165 Fix MultipleResultsFound crash in get_activity_for_source
- 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>
2026-02-21 23:49:19 +00:00
giles
18410c4b16 Add unpublish (Delete) support + improve object IDs
- 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>
2026-02-21 23:26:56 +00:00
giles
a28add8640 Add WARNING-level logging to federation publish handler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:13:00 +00:00
giles
68941b97f6 Fix sign_request call in AP delivery handler
Parse inbox URL into path+host instead of passing url= which doesn't exist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:52:30 +00:00
giles
1d83a339b6 Upsert followers in add_follower to prevent IntegrityError
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:43:20 +00:00
giles
24432cd52a Page-aware labels in blog_new template
- "Post title"→"Page title", "Create Post"→"Create Page" when is_page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:31:58 +00:00
giles
9a1a4996bc Use "Page" labels instead of "Post" when editing pages
- 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>
2026-02-21 22:13:50 +00:00
giles
1832c53980 Skip blog chrome (like, tags, authors, excerpt) for pages
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>
2026-02-21 22:10:39 +00:00
giles
9db739e56d Fix adopt_entries_for_user deleting confirmed bookings on login
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>
2026-02-21 21:19:42 +00:00
giles
dd7a99e8b7 Add federation event handlers, AP delivery, and anchoring
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>
2026-02-21 15:57:31 +00:00
giles
8850a0106a Add federation/ActivityPub models, contracts, and services
Phase 0+1 of ActivityPub integration:
- 6 ORM models (ActorProfile, APActivity, APFollower, APInboxItem, APAnchor, IPFSPin)
- FederationService protocol + SqlFederationService implementation + stub
- 4 DTOs (ActorProfileDTO, APActivityDTO, APFollowerDTO, APAnchorDTO)
- Registry slot for federation service
- Alembic migration for federation tables
- IPFS async client (httpx-based)
- HTTP Signatures (RSA-2048 sign/verify)
- login_url() now uses AUTH_APP env var for flexible auth routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:10:08 +00:00
giles
7abef48cf2 Add count param to cart mini macro for explicit override
When the macro is imported without context ({% from ... import mini %}),
template variables like cart_count aren't visible. The new count param
allows callers to pass it explicitly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:42:58 +00:00
giles
1f8fb521b2 Add ticket +/- quantity support to shared contracts and services
- Add ticket_type_id field to TicketDTO for grouping
- Add adjust_ticket_quantity to CalendarService protocol + SQL impl
- Add stub for adjust_ticket_quantity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 08:53:04 +00:00
giles
e83df2f742 Decoupling audit cleanup: fix protocol gaps, remove dead APIs
- Add search_posts, entry_ids_for_content, visible_entries_for_period
  to protocols and stubs
- Delete internal_api.py and factory cleanup hook (zero callers)
- Convert utils.py to utils/ package with calendar_helpers module
- Remove deleted_at check from calendar_view template (service filters)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:58:07 +00:00
giles
7ee8638d6e Add ticket-to-cart integration
Reserved tickets now flow through the cart and checkout pipeline:
- TicketDTO gains price, entry_id, order_id, calendar_container_id
- CartSummaryDTO gains ticket_count, ticket_total
- 6 new CalendarService methods for ticket lifecycle
- cart_summary includes tickets; login adoption migrates tickets
- New _ticket_items.html template for checkout return page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:32:30 +00:00
giles
71729ffb28 Remove debug comment from post nav template
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 19:57:07 +00:00
giles
8b6be6da96 Add template debug comment for widget nav
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 19:32:43 +00:00
giles
7882644731 Add widget registry for universal UI decoupling
Introduces a widget system where domains register UI fragments into
named slots (container_nav, container_card, account_page, account_link).
Host apps iterate widgets generically without naming any domain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:04:13 +00:00
giles
dfc324b1be Add tickets & bookings to account page
Add TicketDTO, user_tickets/user_bookings to CalendarService protocol
and SqlCalendarService implementation, plus nav links and panel
templates for the auth account sub-pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:06:21 +00:00