MSFLib¶
MSFLib (pronounced "musflib") is a set of Python packages for building FastAPI backends. A small core package, msflib, supplies the shared plumbing: settings, base models, a CRUD action layer, an event bus, scope and policy primitives, database setup and seeding. On top of it sit optional feature modules such as accounts, authentication, workspaces, payments and AI infrastructure.
You write a normal FastAPI application, the host app. You install the packages you need, define your own models and routes next to the ones the modules provide, and mount the module routers where you want them. MSFLib does not run your app and does not own your FastAPI() instance.
What a module is¶
A module is a separately installable msflib-* package. Each one is a slice of the shared msflib namespace (for example msflib.auth or msflib.workspaces) and typically provides some mix of:
- Models: SQLModel tables and the Pydantic schemas that go with them.
- Actions: service-layer classes, usually
ModelActionsubclasses, that hold the database logic. - Routers: factory functions that build a FastAPI
APIRouterfrom the dependencies you hand them (session, identity, settings). - Dependencies: factories that return namespaces of FastAPI dependencies, such as "the current account".
- Settings: a settings class with its own namespace, mixed into your app's settings class (or composed as a nested field; see the authentication guide for a current limitation).
Modules are written to be wired, not configured by import side effects. A module's router factory asks you for the session and identity dependencies it needs, so the same module works with whatever auth and database layout your app already has. Modules depend on msflib and, in some cases, on each other (see the table below).
Package map¶
All packages live in one repository, msflib/fastapi. "Depends on" lists the direct msflib-* dependencies declared in each package's pyproject.toml; every package also depends on msflib itself.
| Package | Import | Purpose | Depends on |
|---|---|---|---|
msflib |
msflib |
Core: settings, base models, actions, event bus, scope and policy, DB setup, seeding, utilities | none |
msflib-auth |
msflib.auth |
Login, token issue and revocation, password reset, optional Google OAuth, identity dependency factories | none |
msflib-account |
msflib.account |
Accounts and profiles: registration, self-service and admin endpoints | none |
msflib-tenancy |
msflib.tenancy |
A minimal Tenant model and tenant resolution, the target for tenant_id foreign keys |
none |
msflib-workspaces |
msflib.workspaces |
Workspace lifecycle, ownership and membership | account, tenancy |
msflib-notifications |
msflib.notifications |
Account inbox and admin broadcast over in-app, email and SMS channels | account, tenancy |
msflib-workspace-notifications |
msflib.workspace_notifications |
Workspace-level notifications, including Discord channels | workspaces, notifications |
msflib-workspace-config |
msflib.workspace_config |
Tenant, workspace and user scoped configuration values and categories | tenancy |
msflib-payments |
msflib.payments |
Payment initiation and verification over Stripe and Paystack, payment queue | none |
msflib-ai-core |
msflib.ai_core |
Provider-agnostic LLM, embedding and vector-store factories, prompts, ingestion pipeline | tenancy |
msflib-ai-api |
msflib.ai_api |
HTTP endpoints for scoped retrieval and grounded Q&A on top of ai-core | account, ai-core, tenancy |
msflib-drivelink |
msflib.drivelink |
A Drive-style virtual filesystem | account |
msflib-ingestion |
msflib.ingestion |
Shared ingestion job model and Celery-backed queue with an operator API | tenancy |
msflib-documents |
msflib.documents |
Document upload, extraction, chunking, embedding and indexing | account, drivelink, ai-core, ingestion, tenancy |
msflib-knowledge |
msflib.knowledge |
Scoped knowledge model projected to graph and vector stores, with semantic queries | ai-core, documents, ingestion, tenancy |
msflib-conversation |
msflib.conversation |
Channels, threads, messages, membership and reactions | tenancy |
The import column is a namespace package: msflib is declared with pkgutil.extend_path, so all of these packages install into the same msflib directory tree. Check what a package's __init__ exports before relying on from msflib.x import y; several modules export nothing at the top level and expect you to import from submodules.
Picking what to install¶
Start from what your app has to do, then add the packages that provide it. Installing a package pulls in the msflib-* packages it depends on.
| If you need | Install |
|---|---|
| CRUD endpoints over your own models, settings, events, seeding | msflib only |
| User accounts and login | msflib-account and msflib-auth |
| Per-tenant isolation keys on your tables | msflib-tenancy |
| Teams or organisations that users join | msflib-workspaces (brings account and tenancy) |
| Settings that differ by tenant, workspace or user | msflib-workspace-config |
| In-app, email or SMS notifications | msflib-notifications, plus msflib-workspace-notifications for workspace-level ones |
| Taking payments | msflib-payments |
| LLM calls, embeddings, vector search | msflib-ai-core, plus msflib-ai-api for ready-made endpoints |
| Chat threads and channels | msflib-conversation |
| File storage with a folder tree | msflib-drivelink |
| Document ingestion and retrieval | msflib-documents and msflib-ingestion; add msflib-knowledge for the knowledge graph |
Some packages have optional extras (for example msflib-ai-core[openai,pgvector] or msflib-notifications[email]); each module page lists them. The core has one, migrations, which adds Alembic.
Known issue (#279)
The sms, email and discord extras of the notification packages currently add nothing: their dependencies (twilio, emails, discord-py) are already hard requirements of the core, so you do not need them. For msflib-workspace-notifications, avoid the sms and all extras: they require twilio ^8.0.0 while the core requires ^9.4.6, so the resolver cannot satisfy both.
Installing¶
Packages are installed from the git repository, one subdirectory per package. With Poetry:
[tool.poetry.dependencies]
msflib = { git = "https://github.com/msflib/fastapi.git", subdirectory = "core", rev = "core-v0.2.1" }
msflib-account = { git = "https://github.com/msflib/fastapi.git", subdirectory = "modules/account", rev = "account-v0.2.2" }
msflib-auth = { git = "https://github.com/msflib/fastapi.git", subdirectory = "modules/auth", rev = "auth-v0.2.2" }
Pin a release tag in rev. Tags are named <package directory>-v<version>, for example core-v0.2.1, account-v0.2.2 or workspace_config-v0.2.1, and each package is versioned independently. The versions above were current when this page was written; list the latest with:
git ls-remote --tags https://github.com/msflib/fastapi.git 'core-v*'
Do not use rev = "dev" (or @dev with pip) in anything you deploy. dev is the moving development head: it can change or break between installs. The Quick Start walks through the same installation for the core package.
Note
MSFLib 0.2.0 and later require Pydantic v2. If your app is still on Pydantic v1, use the 0.1.x tags.
Where to go next¶
- Quick Start: a four-page walk from an empty directory to a tested CRUD API on the core package.
- Modules: one page per package.
- Diving Deeper: mounting routes, overriding models, subclassing actions, authentication, long-running jobs.
- Concepts: tiered configuration, policy, scopes, the event bus, dependency injection and seeding.
- Contributing: working on MSFLib itself.