Two issues fixed:
- Sessions with uid but no grant_token (legacy or corrupt) were not
validated at all, allowing a user to be logged in as whoever got
their old numeric user ID after a DB rebuild
- DB errors during grant verification silently kept stale sessions
alive; now treated as invalid to fail-safe
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each service (blog, market, cart, events, federation, account) now owns
its own database schema with independent Alembic migrations. Removes the
monolithic shared/alembic/ that ran all migrations against a single DB.
- Add per-service alembic.ini, env.py, and 0001_initial.py migrations
- Add shared/db/alembic_env.py helper with table-name filtering
- Fix cross-DB FK in blog/models/snippet.py (users lives in db_account)
- Fix cart_impl.py cross-DB queries: fetch products and market_places
via internal data endpoints instead of direct SQL joins
- Fix blog ghost_sync to fetch page_configs from cart via data endpoint
- Add products-by-ids and page-config-ensure data endpoints
- Update all entrypoint.sh to create own DB and run own migrations
- Cart now uses db_cart instead of db_market
- Add docker-compose.dev.yml, dev.sh for local development
- CI deploys both rose-ash swarm stack and rose-ash-dev compose stack
- Fix Quart namespace package crash (root_path in factory.py)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lightweight social pages (search, follow/unfollow, followers, following,
actor timeline) auto-registered for AP-enabled apps via shared blueprint.
Federation keeps the full social hub. Followers scoped per app_domain;
post cards show "View on Hub" link instead of interaction buttons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redis: per-app DB index (0-5) with shared auth DB 15 for SSO keys;
flushdb replaces flushall so deploys don't wipe cross-app auth state.
Postgres: drop 13 cross-domain FK constraints (migration v2t0p8q9r0),
remove dead ORM relationships, add explicit joins for 4 live ones.
Multi-engine sessions (account + federation) ready for per-domain DBs
via DATABASE_URL_ACCOUNT / DATABASE_URL_FEDERATION env vars.
All URLs initially point to the same appdb — zero behaviour change
until split-databases.sh is run to migrate data to per-domain DBs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_load_user runs before _check_auth_state, so g.user was already set
when the grant was found revoked. The session was cleared but g.user
stayed populated, causing the template to render the signed-in UI
for one request after logout. Now sets g.user = None alongside the
session clear.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delete shared/contracts/widgets.py, shared/services/widget_registry.py,
and shared/services/widgets/ (empty stubs). Remove register_all_widgets()
from factory and widgets Jinja global from jinja_setup. Zero consumers
remain — all cross-app UI composition now uses the fragment API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cart _cart.html: replace url_for('market.browse.product...') with
market_product_url() for links and cart_global.update_quantity for
quantity forms (market endpoints don't exist in cart app)
- Factory favicon route: use STATIC_DIR instead of relative "static"
(resolves to shared/static/ where favicon.ico actually lives)
- Cart context processor: fetch all 3 fragments (cart-mini, auth-menu,
nav-tree) concurrently, matching pattern in all other apps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Combines shared, blog, market, cart, events, federation, and account
into a single repository. Eliminates submodule sync, sibling model
copying at build time, and per-app CI orchestration.
Changes:
- Remove per-app .git, .gitmodules, .gitea, submodule shared/ dirs
- Remove stale sibling model copies from each app
- Update all 6 Dockerfiles for monorepo build context (root = .)
- Add build directives to docker-compose.yml
- Add single .gitea/workflows/ci.yml with change detection
- Add .dockerignore for monorepo build context
- Create __init__.py for federation and account (cross-app imports)