Files
rose-ash/shared
giles a759f4da3b
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
Add Freeze/Thaw page under CEK Machine with live demo
Documents and demonstrates serializable CEK state. Type an expression,
step to any point, click Freeze to see the frozen SX. Click Thaw to
resume from the frozen state and get the result.

- New page at /sx/(geography.(cek.freeze))
- Nav entry under CEK Machine
- Interactive island demo with step/run/freeze/thaw buttons
- Documentation: the idea, freeze format, thaw/resume, what it enables

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:31:34 +00:00
..

Shared

Shared infrastructure, models, contracts, services, and templates used by all five Rose Ash microservices (blog, market, cart, events, federation). Included as a git submodule in each app.

Structure

shared/
  db/
    base.py                 # SQLAlchemy declarative Base
    session.py              # Async session factory (get_session, register_db)
  models/                   # Canonical domain models
    user.py                 # User
    magic_link.py           # MagicLink (auth tokens)
    (domain_event.py removed — table dropped, see migration n4l2i8j0k1)
    kv.py                   # KeyValue (key-value store)
    menu_item.py            # MenuItem (deprecated — use MenuNode)
    menu_node.py            # MenuNode (navigation tree)
    container_relation.py   # ContainerRelation (parent-child content)
    ghost_membership_entities.py  # GhostNewsletter, UserNewsletter
    federation.py           # ActorProfile, APActivity, APFollower, APFollowing,
                            # RemoteActor, APRemotePost, APLocalPost,
                            # APInteraction, APNotification, APAnchor, IPFSPin
  contracts/
    dtos.py                 # Frozen dataclasses for cross-domain data transfer
    protocols.py            # Service protocols (Blog, Calendar, Market, Cart, Federation)
    widgets.py              # Widget types (NavWidget, CardWidget, AccountPageWidget)
  services/
    registry.py             # Typed singleton: services.blog, .calendar, .market, .cart, .federation
    blog_impl.py            # SqlBlogService
    calendar_impl.py        # SqlCalendarService
    market_impl.py          # SqlMarketService
    cart_impl.py            # SqlCartService
    federation_impl.py      # SqlFederationService
    federation_publish.py   # try_publish() — inline AP publication helper
    stubs.py                # No-op stubs for absent domains
    navigation.py           # get_navigation_tree()
    relationships.py        # attach_child, get_children, detach_child
    widget_registry.py      # Widget registry singleton
    widgets/                # Per-domain widget registration
  infrastructure/
    factory.py              # create_base_app() — Quart app factory
    cart_identity.py        # current_cart_identity() (user_id or session_id)
    cart_loader.py          # Cart data loader for context processors
    context.py              # Jinja2 context processors
    jinja_setup.py          # Jinja2 template environment setup
    urls.py                 # URL helpers (blog_url, market_url, etc.)
    user_loader.py          # Load current user from session
    http_utils.py           # HTTP utility functions
  events/
    bus.py                  # emit_activity(), register_activity_handler()
    processor.py            # EventProcessor (polls ap_activities, runs handlers)
    handlers/               # Shared activity handlers
      container_handlers.py #   Navigation rebuild on attach/detach
      login_handlers.py     #   Cart/entry adoption on login
      order_handlers.py     #   Order lifecycle events
      ap_delivery_handler.py #  AP activity delivery to follower inboxes (wildcard)
  utils/
    __init__.py
    calendar_helpers.py     # Calendar period/entry utilities
    http_signatures.py      # RSA keypair generation, HTTP signature signing/verification
    ipfs_client.py          # Async IPFS client (add_bytes, add_json, pin_cid)
    anchoring.py            # Merkle trees + OpenTimestamps Bitcoin anchoring
    webfinger.py            # WebFinger actor resolution
  browser/
    app/                    # Middleware, CSRF, errors, Redis caching, authz, filters
    templates/              # ~300 Jinja2 templates shared across all apps
  containers.py             # ContainerType, container_filter, content_filter helpers
  config.py                 # YAML config loader
  log_config/setup.py       # Logging configuration (JSON formatter)
  static/                   # Shared static assets (CSS, JS, images, FontAwesome)
  editor/                   # Koenig (Ghost) rich text editor build
  alembic/                  # Database migrations

Key Patterns

  • App factory: All apps call create_base_app() which sets up DB sessions, CSRF, error handling, event processing, logging, widget registration, and domain service wiring.
  • Service contracts: Cross-domain communication via typed Protocols + frozen DTO dataclasses. Apps call services.calendar.method(), never import models from other domains.
  • Service registry: Typed singleton (services.blog, .calendar, .market, .cart, .federation). Apps wire their own domain + stubs for others via register_domain_services().
  • Activity bus: emit_activity() writes to ap_activities table in the caller's transaction. EventProcessor polls pending activities and dispatches to registered handlers. Internal events use visibility="internal"; federation activities use visibility="public" and are delivered to follower inboxes by the wildcard delivery handler.
  • Widget registry: Domain services register widgets (nav, card, account); templates consume via widgets.container_nav, widgets.container_cards.
  • Cart identity: current_cart_identity() returns {"user_id": int|None, "session_id": str|None} from the request session.

Alembic Migrations

All apps share one PostgreSQL database. Migrations are managed here and run from the blog app's entrypoint (other apps skip migrations on startup).

alembic -c shared/alembic.ini upgrade head