begin_nested() auto-flushes on entry which triggers the INSERT before
the savepoint is active. Move sess.add() inside the savepoint block
and split into update vs insert paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Blog app now registers SqlFederationService (was stub/no-op)
- sync_single_page emits post.published/updated events for pages
- Updated shared submodule: fix sign_request in AP delivery handler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ghost /pages/ endpoint may not include "page": true in the response.
Explicitly set it so _upsert_post correctly marks is_page=true.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ghost has separate /posts/ and /pages/ endpoints. All admin functions
(get_post_for_edit, update_post, update_post_settings, sync) were
hardcoded to /posts/, causing 404s when editing pages. Now checks
is_page from post_data and uses the correct endpoint.
Also uses sync_single_page (not sync_single_post) after page saves
to prevent IntegrityError from mismatched fetch/upsert paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Register StubFederationService in services/__init__.py
- Add federation to CI sibling list
- Add federation URL to app-config.yaml
- Update shared submodule with federation models/contracts/services
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Delete coop_api.py (dead internal API endpoint)
- Replace cross-app calendar imports with shared service calls
- Update shared submodule
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The blog app's local templates/_types/post/_nav.html was shadowing
the shared version due to ChoiceLoader priority. Updated local copy
to use container_nav_widgets while keeping the blog-specific admin
cog link. Removed debug logging from context processor.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace explicit calendar/market service calls in post routes, auth
routes, and listing cards with widget-driven iteration. Zero cross-domain
imports remain in blog bp layer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New GET /auth/tickets/ and /auth/bookings/ routes with HTMX support.
Update shared submodule with TicketDTO, service methods, nav links,
and panel templates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Market CRUD in blog now delegates to services.market.create_marketplace()
and soft_delete_marketplace() instead of importing MarketPlace directly.
Adds TODO comments on Calendar imports in admin routes (deferred to
admin UI rework). Updates shared submodule.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The glue layer's models (MenuNode, ContainerRelation), services
(navigation, relationships), and event handlers have been absorbed
into shared/. The glue submodule caused duplicate SQLAlchemy table
registration for 'menu_nodes'.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace direct Calendar, MarketPlace, and Post model queries with typed
service calls (services.blog, services.calendar, services.market,
services.cart). Blog registers all 4 services via domain_services_fn
with has() guards for composable deployment.
Key changes:
- app.py: use domain_services_fn instead of inline service registration
- admin routes: MarketPlace queries → services.market.marketplaces_for_container()
- entry_associations: CalendarEntryPost → services.calendar.entry_ids_for_content()
- markets service: Post query → services.blog.get_post_by_id/slug()
- posts_data, post routes: use calendar/market/cart services
- menu_items: glue imports → shared imports
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Context processor now sums product count + calendar_count from the
cart API, so the cart badge shows the correct total on all pages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace all imports from cart.models, market.models, events.models
with shared.models equivalents
- Convert blog/models/ghost_content.py to re-export stub
- Update shared + glue submodule pointers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These were duplicates of files in shared/browser/templates/ and
silently prevented shared updates from taking effect (as happened
with the auth nav orders link fix). 8 blog-specific overrides with
genuine differences are kept.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The orders link was using links.link macro which adds hx-get, causing
htmx:invalidPath because cart.rose-ash.com is cross-origin. Use a
plain <a> tag for this cross-domain link instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract inline email body into separate Jinja2 templates
(_email/magic_link.html and .txt) with a styled sign-in
button and fallback plain-text link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
List specific model imports, glue services, internal APIs, and
domain events that blog code actually references.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>