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>
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>
MenuNode and ContainerRelation now live in shared/models/ — importing
glue.models caused SQLAlchemy to see duplicate table definitions.
Also register the two new models in shared/models/__init__.py.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add typed service contracts (Protocols + frozen DTOs) in shared/contracts/
for cross-domain communication. Each domain exposes a service interface
(BlogService, CalendarService, MarketService, CartService) backed by SQL
implementations in shared/services/. A singleton registry with has() guards
enables composable startup — apps register their own domain service and
stubs for absent domains.
Absorbs glue layer: navigation, relationships, event handlers (login,
container, order) now live in shared/ with has()-guarded service calls.
Factory gains domain_services_fn parameter for per-app service registration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Templates: item.post.X → item.X (MenuNode has label/slug/feature_image directly)
- factory.py: add glue.models to import loop + register_glue_handlers() at startup
- alembic env.py: add glue.models to import loop
- New migration: container_relations + menu_nodes tables with backfill from existing data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cross-domain relationships like Product.order_items → OrderItem use
string references that SQLAlchemy resolves by class name lookup. All
model packages must be imported so every class is registered before
mapper configuration runs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
shared/logging/ shadows Python's stdlib logging module, causing a
circular import when any code does `import logging`. This breaks
both the entrypoint Redis flush and Hypercorn app loading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>