Project Structure¶
Top-Level Layout¶
vectis/
├── backend/ # Python FastAPI application
│ ├── vectis/
│ │ ├── core/ # App factory, config, middleware, strategy, events, database
│ │ ├── modules/ # ~40 domain modules (see below)
│ │ ├── extensions/ # ~45 ext_* packages (payment, shipping, fraud, storage, email, AI, etc.)
│ │ ├── events/ # Redpanda producer/consumer, JSON Schema registry
│ │ └── worker.py # Temporal worker entry point
│ ├── alembic/ # Database migrations
│ ├── Dockerfile / Dockerfile.prod # Dev + multi-stage production images
│ └── tests/ # pytest test suite (~1,670 tests)
├── admin/ # SvelteKit admin dashboard
│ └── src/
│ ├── lib/ # Components, help JSON, Houdini ops ($lib/houdini/), houdiniClient.ts
│ └── routes/ # ~40 admin routes (incl. refund-approvals, workflow-faults, affiliates, packaging)
├── storefront/ # SvelteKit B2B/B2C storefront
│ └── src/
│ ├── lib/ # Components, i18n, format, Houdini ops ($lib/houdini/), houdiniClient.ts
│ └── routes/ # Product pages, cart, checkout, account, affiliates portal
├── infra/ # grafana dashboards, prometheus config, deployment scripts
├── migrator/ # WooCommerce → Vectis data migration CLI
├── docs/ # Internal runbooks: constitution, conventions, REDPANDA_TOPICS, DR_RUNBOOK, DEPLOYMENT_DIGITALOCEAN, CUSTOMER_ONBOARDING_PILOT, CACHING, EXTENSION_GUIDE
├── scripts/ # check_resolver_redefs.py, check_no_core_extension_imports.py, sync_admin_extensions.py, backup_postgres.sh, verify_backup_restore.py
├── docker-compose.yml # Full development environment (incl. Prometheus + Grafana)
├── docker-compose.prod.yml
└── Makefile # `make check` runs the full local gate (~25s)
Note
The public documentation site (this site) lives in a separate repo — vectiscommerce/vectis-commerce-docs — and deploys to Cloudflare Pages at docs.vectisb2b.com. Keep code and docs in lockstep via PRs across both repos.
Backend Module Structure¶
Every core module follows this layout:
vectis/modules/{name}/
├── __init__.py
├── models.py # SQLAlchemy ORM models
├── services.py # Business logic (service layer)
├── resolvers.py # Strawberry GraphQL resolvers
├── strategies.py # ABC strategy interfaces (if applicable)
└── workflows.py # Temporal workflows (if applicable)
Core Modules (38)¶
| Module | Description |
|---|---|
auth | Login, JWT, sessions, BFF, RBAC, channel resolution |
account | Account, Location, Employee, Address, CustomerGroup |
activity | Activity feed across entities |
ai | LLM provider integrations (chat, descriptions, assistants) |
approval | Registration rules, document upload |
audit | Immutable append-only log |
banner | Site-wide banners / announcements |
cart | Per-location carts, snapshots, pessimistic locking, coupons |
cms | Pages (JSONB blocks), navigation, media |
compliance | Regulatory checks (tobacco, age-restricted goods) |
fee | Configurable surcharges and fees |
fraud | Fraud holds, signals from risk extensions |
fulfillment | Multi-box shipments, multi-carrier, by_box + by_order modes |
geo | Geographic data model (country/region/county/city), IP geolocation |
gift_card | Virtual + physical, partial redemption |
inventory | Warehouses, stock levels, FIFO allocation |
marketing | Campaigns, email marketing integrations |
net_terms | Invoices, aging, credit holds |
notification | Templates, delivery log |
order | Configurable state machine, custom order numbers, dual-currency |
payment | Gateway strategies, eligibility, transactions, lifecycle (auth/capture/void/refund) |
platform | Cross-cutting platform settings |
pricing | 5-level hierarchy, volume tiers, multi-currency, exchange rates |
product | Product, Variant, Category, Brand |
promotion | Discount engine, BOGO, stacking, cart indexer |
quote | Quote lifecycle |
recurring | Subscription/recurring orders |
registration | B2B registration flow + document requirements |
reporting | Saved + scheduled reports |
rma | Line-level return approval, state machine |
sales | Rep assignment, commissions |
search | Meilisearch (admin) + Typesense (storefront) indexing, SSR search |
store_credit | Financial ledger, overdraft protection |
support_chat | Strategy ABCs only — J'AI now ships as the ext_jai_chat extension |
tags | Universal tagging system |
tax | Stage-sorted multi-strategy engine (sales tier 100, excise tier 200) |
tracking | Shipment tracking integrations |
product_label | Predicate-driven product labels with batch evaluation (Decided #228) |
refund_approval | Refund approval inbox + durable Temporal execution (OQ #27) |
affiliate | Affiliate program with multi-factor fraud guard (Decided #179) |
(Packaging + MMOQ live as columns + helpers inside the product and cart modules — no standalone packaging module. Workflow faults are an event domain, not a module — the schema is at events/schemas/workflow/fault_v1.json and faults persist to a workflow_faults table.)
Core Infrastructure (vectis/core/)¶
| File | Purpose |
|---|---|
app.py | FastAPI application factory, lifespan, GraphQL router |
config.py | Pydantic settings (env-based infrastructure config) |
database.py | SQLAlchemy engine, session factory, Base, MoneyColumn |
middleware.py | Channel resolution, auth, locale, currency context |
context.py | RequestContext dataclass threaded through every request |
strategy.py | StrategyResolver with channel-scoped extension filtering |
events/ | In-process EventBus + Redpanda producer/consumer |
graphql.py | Root Query and Mutation composing all module resolvers |
extension.py | ExtensionRegistry, ExtensionProtocol, ChannelExtension model |
security.py | JWT creation/validation, password hashing |
deps.py | Dependency injection helpers (get_session context manager) |
Extensions¶
Extensions are installed Python packages discovered via pyproject.toml entry points. The current set (40+) spans several categories:
| Category | Extensions |
|---|---|
| Payment | ext_authorize_net, ext_nmi, ext_ach, ext_manual_payment, ext_gift_cards |
| Shipping / carriers | ext_ups, ext_usps, ext_usps_flatrate, ext_fedex, ext_ontrac, ext_priority1, ext_goshippo, ext_shipstation, ext_shipstation_address, ext_package_protection |
| Tax / compliance | ext_excise_engine (replaces deprecated ext_exciseiq per Decided #225), ext_taxjar, ext_agechecker |
| Fraud / risk | ext_signifyd, ext_riskified, ext_radar, ext_ipqs, ext_maxmind |
| Storage | ext_minio, ext_s3, ext_digitalocean_spaces, ext_dropbox |
| Email / messaging | ext_elastic_email, ext_ses, ext_sns, ext_twilio, ext_omnisend |
| Address / maps | ext_smarty, ext_google_maps |
| Tracking / delivery | ext_aftership (now in the Fulfillment category) |
| AI providers | ext_chatgpt, ext_claude, ext_grok |
| Support | ext_jai_chat (promoted from core module, 2026-05) |
| Auth / e-sign | ext_keycloak, ext_docusign, ext_hellosign |
| Marketing / affiliates | ext_awin |
See backend/vectis/extensions/ for the authoritative list.
Admin Routes¶
| Route | Page |
|---|---|
/ | Dashboard |
/orders, /orders/[id] | Orders list and detail (with inventory-risk filter, external handoff state) |
/products, /products/[id], /products/new, /products/labels, /products/labels/[id], /products/labels/new | Product management + label CRUD |
/customers, /customers/[id], /customers/create | Customer management |
/pricing | Price lists |
/promotions | Discount rules |
/inventory | Stock levels |
/shipping | Shipping zones and methods |
/tax | Tax rates and strategies |
/cms | CMS pages |
/settings, /settings/packaging, /settings/compliance, … | Channel and system settings (~36 entries) |
/carts, /carts/new, /quotes, /recurring-orders | Cart/quote/subscription management |
/claims, /returns, /fraud, /pending-changes | Customer service workflows |
/refund-approvals | Refund approval inbox (OQ #27) |
/workflow-faults | Workflow fault inbox (Decided #200) |
/gift-cards, /store-credit, /store-credit/overdraft-drafts | Financial instruments |
/affiliates/approvals, /affiliates/payouts, /affiliates/rules | Affiliate program |
/lists, /lists/[id] | B2B saved order lists |
/marketing, /registrations, /reports | Marketing + admin ops |
/brands, /categories, /collections, /attributes, /traits, /tags, /quicklinks | Catalog support |
/excise-calculator | Tax tooling |
/extensions/<slug>/* | Extension-contributed routes mirrored from each extension's admin_pages/ (Decided #224) |
Channel context travels via the X-Channel-Slug header (Decided #164), not a URL prefix. Routes are flat. Full list: see admin/src/routes/.