Update app READMEs for monorepo
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m56s

Remove stale submodule references, port numbers, and Running sections.
Add fragment composition details. Create READMEs for federation and account.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-24 20:13:00 +00:00
parent 796443c06d
commit e1f9c964f5
6 changed files with 135 additions and 135 deletions

36
account/README.md Normal file
View File

@@ -0,0 +1,36 @@
# Account App
User dashboard for the Rose Ash cooperative. Provides account management, newsletter preferences, and widget pages for tickets and bookings.
## Structure
```
app.py # Application factory (create_base_app + blueprints)
path_setup.py # Adds project root + app dir to sys.path
entrypoint.sh # Container entrypoint (Redis flush, start)
bp/
account/ # Dashboard, newsletters, widget pages (tickets, bookings)
auth/ # OAuth client routes + HTTP token exchange for non-coop clients
fragments/ # auth-menu fragment (sign-in button / user menu)
models/ # Re-export stubs pointing to shared/models/
services/ # register_domain_services() — wires all domains
templates/ # Account-specific templates (override shared/)
```
## Auth menu
Account serves the `auth-menu` fragment consumed by all other apps' headers. It renders either a sign-in button (anonymous) or the user's email with a dropdown (authenticated), for both desktop and mobile layouts.
## OAuth token exchange
`POST /auth/oauth/token` provides HTTP-based token exchange for non-coop OAuth clients (e.g., Artdag).
## Cross-domain communication
- `services.blog.*` — post queries for page context
- `services.calendar.*` — calendar/entry queries for bookings panel
- `services.cart.*` — cart summary + orders for tickets panel
## Fragments served
- **auth-menu** — sign-in button or user email menu (desktop + mobile)

View File

@@ -1,39 +1,26 @@
# Blog App (Coop) # Blog App (Coop)
Blog, authentication, and content management service for the Rose Ash cooperative platform. Handles Ghost CMS integration, user auth, and admin settings. Content management, Ghost CMS sync, navigation, and the prose editor for the Rose Ash cooperative platform. Runs database migrations on startup and serves as the primary content hub.
## Architecture
One of five Quart microservices sharing a single PostgreSQL database:
| App | Port | Domain |
|-----|------|--------|
| **blog (coop)** | 8000 | Auth, blog, admin, menus, snippets |
| market | 8001 | Product browsing, Suma scraping |
| cart | 8002 | Shopping cart, checkout, orders |
| events | 8003 | Calendars, bookings, tickets |
| federation | 8004 | ActivityPub, fediverse social |
## Structure ## Structure
``` ```
app.py # Application factory (create_base_app + blueprints) app.py # Application factory (create_base_app + blueprints)
path_setup.py # Adds project root + app dir to sys.path path_setup.py # Adds project root + app dir to sys.path
config/app-config.yaml # App URLs, feature flags, SumUp config entrypoint.sh # Container entrypoint (migrations, Redis flush, start)
models/ # Blog-domain models (+ re-export stubs for shared models) bp/
bp/ # Blueprints blog/ # Post listing, Ghost CMS sync, webhooks
auth/ # Magic link login, account, newsletters
blog/ # Post listing, Ghost CMS sync
post/ # Single post view and admin post/ # Single post view and admin
admin/ # Settings admin interface admin/ # Settings admin interface
menu_items/ # Navigation menu management menu_items/ # Navigation menu management
snippets/ # Reusable content snippets snippets/ # Reusable content snippets
templates/ # Jinja2 templates fragments/ # nav-tree fragment for cross-app navigation
models/ # Re-export stubs pointing to shared/models/
services/ # register_domain_services() — wires blog + calendar + market + cart services/ # register_domain_services() — wires blog + calendar + market + cart
shared/ # Submodule -> git.rose-ash.com/coop/shared.git templates/ # Blog-specific templates (override shared/)
``` ```
## Cross-Domain Communication ## Cross-domain communication
All inter-app communication uses typed service contracts (no HTTP APIs): All inter-app communication uses typed service contracts (no HTTP APIs):
@@ -41,20 +28,14 @@ All inter-app communication uses typed service contracts (no HTTP APIs):
- `services.market.*` — marketplace queries via MarketService protocol - `services.market.*` — marketplace queries via MarketService protocol
- `services.cart.*` — cart summary via CartService protocol - `services.cart.*` — cart summary via CartService protocol
- `services.federation.*` — AP publishing via FederationService protocol - `services.federation.*` — AP publishing via FederationService protocol
- `shared.services.navigation` — site navigation tree
## Domain Events ## Fragments served
- `auth/routes.py` emits `user.logged_in` via `shared.events.emit_event` - **nav-tree** — site navigation tree, fetched by all other apps
- Ghost sync emits `post.published` / `post.updated` for federation
## Running ## Fragments consumed
```bash - **cart-mini** (from cart) — cart icon + badge
export DATABASE_URL_ASYNC=postgresql+asyncpg://user:pass@localhost/coop - **auth-menu** (from account) — sign-in / user menu
export REDIS_URL=redis://localhost:6379/0 - **container-nav** (from events, market) — sidebar widgets
export SECRET_KEY=your-secret-key - **container-cards** (from events) — event cards on listing pages
alembic -c shared/alembic.ini upgrade head
hypercorn app:app --bind 0.0.0.0:8000
```

View File

@@ -1,26 +1,13 @@
# Cart App # Cart App
Shopping cart, checkout, and order management service for the Rose Ash cooperative. Shopping cart, checkout, and order management service for the Rose Ash cooperative. Integrates with SumUp for payment processing.
## Architecture
One of five Quart microservices sharing a single PostgreSQL database:
| App | Port | Domain |
|-----|------|--------|
| blog (coop) | 8000 | Auth, blog, admin, menus, snippets |
| market | 8001 | Product browsing, Suma scraping |
| **cart** | 8002 | Shopping cart, checkout, orders |
| events | 8003 | Calendars, bookings, tickets |
| federation | 8004 | ActivityPub, fediverse social |
## Structure ## Structure
``` ```
app.py # Application factory (create_base_app + blueprints) app.py # Application factory (create_base_app + blueprints)
path_setup.py # Adds project root + app dir to sys.path path_setup.py # Adds project root + app dir to sys.path
config/app-config.yaml # App URLs, SumUp config entrypoint.sh # Container entrypoint (Redis flush, start)
models/ # Cart-domain models (Order, OrderItem, PageConfig)
bp/ bp/
cart/ # Cart blueprint cart/ # Cart blueprint
global_routes.py # Add to cart, checkout, webhooks, return page global_routes.py # Add to cart, checkout, webhooks, return page
@@ -37,40 +24,33 @@ bp/
clear_cart_for_order.py # Soft-delete cart after checkout clear_cart_for_order.py # Soft-delete cart after checkout
order/ # Single order detail view order/ # Single order detail view
orders/ # Order listing view orders/ # Order listing view
fragments/ # cart-mini fragment, account-nav-item fragment
models/ # Re-export stubs (Order, OrderItem, PageConfig)
services/ # register_domain_services() — wires cart + calendar + market services/ # register_domain_services() — wires cart + calendar + market
shared/ # Submodule -> git.rose-ash.com/coop/shared.git templates/ # Cart-specific templates (override shared/)
``` ```
## Cross-Domain Communication ## Cart identity
Cart items are keyed by `user_id` (logged in) or `session_id` (anonymous). On login, anonymous cart items are adopted to the user's account.
## Cross-domain communication
- `services.calendar.*` — claim/confirm entries for orders, adopt on login - `services.calendar.*` — claim/confirm entries for orders, adopt on login
- `services.market.*` — marketplace queries for page-scoped carts - `services.market.*` — marketplace queries for page-scoped carts
- `services.blog.*` — post lookup for page context - `services.blog.*` — post lookup for page context
- `shared.services.navigation` — site navigation tree
## Domain Events ## Fragments served
- `checkout.py` emits `order.created` via `shared.events.emit_event` - **cart-mini** — cart icon + badge count
- `check_sumup_status.py` emits `order.paid` via `shared.events.emit_event` - **account-nav-item** — orders link for account nav
## Checkout Flow ## Checkout flow
```
1. User clicks "Checkout" 1. User clicks "Checkout"
2. create_order_from_cart() creates Order + OrderItems 2. `create_order_from_cart()` creates Order + OrderItems
3. services.calendar.claim_entries_for_order() marks entries as "ordered" 3. `services.calendar.claim_entries_for_order()` marks entries as "ordered"
4. emit: order.created event 4. Emits `Create` / `rose:Order` activity
5. SumUp hosted checkout created, user redirected 5. SumUp hosted checkout created, user redirected
6. SumUp webhook / return page triggers check_sumup_status() 6. SumUp webhook / return page triggers `check_sumup_status()`
7. If PAID: services.calendar.confirm_entries_for_order(), emit: order.paid 7. If PAID: `services.calendar.confirm_entries_for_order()`, emits `rose:OrderPaid`
```
## Running
```bash
export DATABASE_URL_ASYNC=postgresql+asyncpg://user:pass@localhost/coop
export REDIS_URL=redis://localhost:6379/0
export SECRET_KEY=your-secret-key
hypercorn app:app --bind 0.0.0.0:8002
```

View File

@@ -2,28 +2,13 @@
Calendar and event booking service for the Rose Ash cooperative platform. Manages calendars, time slots, calendar entries (bookings), tickets, and ticket types. Calendar and event booking service for the Rose Ash cooperative platform. Manages calendars, time slots, calendar entries (bookings), tickets, and ticket types.
## Architecture
One of five Quart microservices sharing a single PostgreSQL database:
| App | Port | Domain |
|-----|------|--------|
| blog (coop) | 8000 | Auth, blog, admin, menus, snippets |
| market | 8001 | Product browsing, Suma scraping |
| cart | 8002 | Shopping cart, checkout, orders |
| **events** | 8003 | Calendars, bookings, tickets |
| federation | 8004 | ActivityPub, fediverse social |
## Structure ## Structure
``` ```
app.py # Application factory (create_base_app + blueprints) app.py # Application factory (create_base_app + blueprints)
path_setup.py # Adds project root + app dir to sys.path path_setup.py # Adds project root + app dir to sys.path
config/app-config.yaml # App URLs, feature flags entrypoint.sh # Container entrypoint (Redis flush, start)
models/ # Events-domain models bp/
calendars.py # Calendar, CalendarEntry, CalendarSlot,
# TicketType, Ticket, CalendarEntryPost
bp/ # Blueprints
calendars/ # Calendar listing calendars/ # Calendar listing
calendar/ # Single calendar view and admin calendar/ # Single calendar view and admin
calendar_entries/ # Calendar entries listing calendar_entries/ # Calendar entries listing
@@ -37,18 +22,20 @@ bp/ # Blueprints
ticket_admin/ # Ticket administration ticket_admin/ # Ticket administration
markets/ # Page-scoped marketplace views markets/ # Page-scoped marketplace views
payments/ # Payment-related views payments/ # Payment-related views
fragments/ # container-nav, container-cards fragments
models/ # Re-export stubs (Calendar, CalendarEntry, Ticket, etc.)
services/ # register_domain_services() — wires calendar + market + cart services/ # register_domain_services() — wires calendar + market + cart
shared/ # Submodule -> git.rose-ash.com/coop/shared.git templates/ # Events-specific templates (override shared/)
``` ```
## Models ## Models
All events-domain models live in `models/calendars.py`: All events-domain models live in `shared/models/`:
| Model | Description | | Model | Description |
|-------|-------------| |-------|-------------|
| **Calendar** | Container for entries, scoped to a page via `container_type + container_id` | | **Calendar** | Container for entries, scoped to a page via `container_type + container_id` |
| **CalendarEntry** | A bookable event/time slot. Has `state` (pending/ordered/provisional), `cost`, ownership (`user_id`/`session_id`), and `order_id` (plain integer, no FK) | | **CalendarEntry** | A bookable event/time slot with state (pending/ordered/provisional) and cost |
| **CalendarSlot** | Recurring time bands (day-of-week + time range) within a calendar | | **CalendarSlot** | Recurring time bands (day-of-week + time range) within a calendar |
| **TicketType** | Named ticket categories with price and count | | **TicketType** | Named ticket categories with price and count |
| **Ticket** | Individual ticket with unique code, state, and `order_id` (plain integer, no FK) | | **Ticket** | Individual ticket with unique code, state, and `order_id` (plain integer, no FK) |
@@ -56,23 +43,13 @@ All events-domain models live in `models/calendars.py`:
`order_id` on CalendarEntry and Ticket is a plain integer column — no FK constraint to the orders table. The cart app writes these values via service calls, not directly. `order_id` on CalendarEntry and Ticket is a plain integer column — no FK constraint to the orders table. The cart app writes these values via service calls, not directly.
## Cross-Domain Communication ## Cross-domain communication
- `services.market.*` — marketplace queries for page views - `services.market.*` — marketplace queries for page views
- `services.cart.*` — cart summary for context processor - `services.cart.*` — cart summary for context processor
- `services.federation.*` — AP publishing for new entries - `services.federation.*` — AP publishing for new entries
- `shared.services.navigation` — site navigation tree
## Migrations ## Fragments served
This app does **not** run Alembic migrations on startup. Migrations are managed in the `shared/` submodule and run from the blog app's entrypoint. - **container-nav** — calendar entries + links for blog sidebar
- **container-cards** — event cards for blog listing pages
## Running
```bash
export DATABASE_URL_ASYNC=postgresql+asyncpg://user:pass@localhost/coop
export REDIS_URL=redis://localhost:6379/0
export SECRET_KEY=your-secret-key
hypercorn app:app --bind 0.0.0.0:8003
```

44
federation/README.md Normal file
View File

@@ -0,0 +1,44 @@
# Federation App
OAuth2 authorization server and ActivityPub social hub for the Rose Ash cooperative. Handles user authentication, fediverse federation, and social features (timeline, compose, follow, notifications).
## Structure
```
app.py # Application factory (create_base_app + blueprints)
path_setup.py # Adds project root + app dir to sys.path
entrypoint.sh # Container entrypoint (optional migrations, Redis flush, start)
bp/
auth/ # Login, magic link, logout, OAuth2 authorize endpoint
identity/ # Actor profile management
social/ # Timeline, compose, search, follow/unfollow,
# like/boost, notifications, following/followers lists
fragments/ # Fragment endpoints
models/ # Re-export stubs pointing to shared/models/
services/ # register_domain_services() — wires all domains
templates/ # Federation-specific templates (override shared/)
```
## OAuth2 SSO
Federation is the authorization server for all Rose Ash apps:
- `/oauth/authorize` — authorization endpoint (PKCE supported)
- Magic link login (passwordless email)
- All client apps auto-get `/auth/login`, `/auth/callback`, `/auth/logout` via `shared/infrastructure/oauth.py`
- Per-app first-party session cookies (Safari ITP compatible)
## ActivityPub
- Per-app actors: each app has its own AP actor (virtual projection of the same keypair)
- Actor endpoints: webfinger, actor profile, inbox, outbox, followers
- Social features: timeline, compose, search, follow/unfollow, like/boost, notifications
- Activities emitted to `ap_activities` table, processed by `EventProcessor`
- HTTP signatures + IPFS content addressing
## Cross-domain communication
- `services.blog.*` — post queries for content federation
- `services.calendar.*` — event queries
- `services.market.*` — product queries
- `services.cart.*` — cart summary for context processor

View File

@@ -2,41 +2,33 @@
Product browsing and marketplace service for the Rose Ash cooperative. Displays products scraped from Suma Wholesale. Product browsing and marketplace service for the Rose Ash cooperative. Displays products scraped from Suma Wholesale.
## Architecture
One of five Quart microservices sharing a single PostgreSQL database:
| App | Port | Domain |
|-----|------|--------|
| blog (coop) | 8000 | Auth, blog, admin, menus, snippets |
| **market** | 8001 | Product browsing, Suma scraping |
| cart | 8002 | Shopping cart, checkout, orders |
| events | 8003 | Calendars, bookings, tickets |
| federation | 8004 | ActivityPub, fediverse social |
## Structure ## Structure
``` ```
app.py # Application factory (create_base_app + blueprints) app.py # Application factory (create_base_app + blueprints)
path_setup.py # Adds project root + app dir to sys.path path_setup.py # Adds project root + app dir to sys.path
config/app-config.yaml # App URLs, feature flags entrypoint.sh # Container entrypoint (Redis flush, start)
models/ # Market-domain models (+ re-export stubs) bp/
bp/ # Blueprints
market/ # Market root, navigation, category listing market/ # Market root, navigation, category listing
browse/ # Product browsing with filters and infinite scroll browse/ # Product browsing with filters and infinite scroll
product/ # Product detail pages product/ # Product detail pages
cart/ # Page-scoped cart views cart/ # Page-scoped cart views
api/ # Product sync API (used by scraper) api/ # Product sync API (used by scraper)
fragments/ # container-nav fragment (market links)
scrape/ # Suma Wholesale scraper scrape/ # Suma Wholesale scraper
models/ # Re-export stubs pointing to shared/models/
services/ # register_domain_services() — wires market + cart services/ # register_domain_services() — wires market + cart
shared/ # Submodule -> git.rose-ash.com/coop/shared.git templates/ # Market-specific templates (override shared/)
``` ```
## Cross-Domain Communication ## Cross-domain communication
- `services.cart.*` — cart summary via CartService protocol - `services.cart.*` — cart summary via CartService protocol
- `services.federation.*` — AP publishing via FederationService protocol - `services.federation.*` — AP publishing via FederationService protocol
- `shared.services.navigation` — site navigation tree
## Fragments served
- **container-nav** — market navigation links for blog sidebar
## Scraping ## Scraping
@@ -44,13 +36,3 @@ shared/ # Submodule -> git.rose-ash.com/coop/shared.git
bash scrape.sh # Full Suma Wholesale catalogue bash scrape.sh # Full Suma Wholesale catalogue
bash scrape-test.sh # Limited test scrape bash scrape-test.sh # Limited test scrape
``` ```
## Running
```bash
export DATABASE_URL_ASYNC=postgresql+asyncpg://user:pass@localhost/coop
export REDIS_URL=redis://localhost:6379/0
export SECRET_KEY=your-secret-key
hypercorn app:app --bind 0.0.0.0:8001
```