Skip to content

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/.