Architecture
Rupert is a modular Rails monolith. Platform data flows in through a sync engine, lands in source mirrors, and is then lifted into a canonical domain core that the whole ERP reads from.
The sync pipeline
Shopify / Square
│ (GraphQL / REST)
▼
SyncEngine.run! ─▶ CatalogSyncer ─▶ ShopifyProduct, ShopifyVariant, Location
│ LedgerImporter ─▶ LedgerEntry
│ SquareSyncer ─▶ SquareItem, SquareVariation
│ AlertGenerator ─▶ StockAlert
▼
CanonicalOrderImporter ─▶ Core::Order, Core::OrderLine, Core::Payment,
Core::Customer, Core::Fulfillment
▼
DataCache.bump! (invalidate dashboard / report caches)
The importer is idempotent — it upserts on (tenant_id, source, source_order_id) and replaces line items, payments, and fulfillments each run, so the canonical store stays in lock-step with the feeds.
Modular monolith
Extensions live under app/modules/<name>/ and register themselves in app/models/module_registry.rb, which drives both navigation and the permission gate. The canonical domain core lives in app/modules/core/ and is the single source of truth for the ERP.
Background jobs
Syncs and their follow-up work run through Solid Queue. A sync enqueues post-sync work (notifications, sales announcements) that is fire-and-forget, so a slow worker can never block the sync run itself.
SyncSchedulerJob— kicks off a sync for every active tenant (every 15 minutes in production)SyncJob— runs the engine, then enqueues notificationsBuzzNotifyJob— posts to the team's Buzz / Nostr channelBackupJob— scheduled database snapshots to Google Drive
Permissions
Access is role-based with three resolution layers, checked through User#can? and Pundit policy objects:
- Per-employee overrides (
user_permissions) — exact grants for one person - Per-role overrides (
role_permissions) — replaces the built-ins for a role - Built-in matrix (
User::ROLE_PERMISSIONS) — the frozen defaults
Key directories
web/app/modules/core/ canonical domain (Order, Customer, Payment, Fulfillment)
web/app/modules/<module>/ per-feature controllers + views + policies
web/app/services/ sync engine, importers, presenters, platform clients
web/app/models/ module registry, users, settings, feature flags
web/app/views/ Tailwind UI (design tokens in app/assets/tailwind/application.css)