Skip to content

Bundled modules

simple_module_python ships with eleven first-party modules. Each is a regular Python package — same shape as a module you'd write yourself — registered through the simple_module entry point and discovered at boot. They are independent: install only what you need.

ModuleDepends onWhat it provides
authTiny public surface (UserContext, AuthProvider, get_current_user, require_permission) other modules import, plus the provider-agnostic AuthMiddleware and principal-resolver chain. The actual login/session logic lives in an auth-provider module (users or keycloak).
usersauthEmail + password auth, OAuth/OIDC (Google, GitHub, Microsoft/Entra ID, generic OIDC), sessions, roles, invites, password reset, email verification, admin UI, mailer backends, smpy users create-admin.
keycloakauth, settingsAlternative auth provider: Keycloak OIDC single sign-on.
permissionsauth, usersRole / direct-grant assignment store + admin UI; RequiresPermission dependency that honours both forms.
settingsDB-backed key/value store with system / tenant / user precedence; per-module pydantic settings registration; hot reload; smpy settings CLI.
feature_flagsRuntime feature toggles with system + tenant overrides.
file_storagesettingsPluggable file storage (filesystem, S3-compatible) with upload validation, presigned URLs, browse/download/delete UI.
brandingsettings, file_storageAdmin-configurable app identity — app name, logo, favicon and primary colour — pushed to every page via Inertia shared props.
background_tasksusersCelery + Redis workers, persistent task history, retry, stuck-task sweep, live worker dashboard.
audit_logusersAutomatic field-level audit trail for SQLModel entities, with an admin UI to browse change history.
dashboardusersAuthenticated landing page with system overview (user counts, module list, health checks).
site_locksettings, authOptional site-wide shared-password gate for staging / pre-launch sites. Off by default.

How modules are wired in

Every module declares an entry point in its pyproject.toml:

toml
[project.entry-points.simple_module]
users = "users.module:UsersModule"

At boot, simple_module_core.discovery.discover_modules() loads them, sorts them topologically by ModuleMeta.depends_on, and the host invokes their lifecycle hooks in order — see discovery and lifecycle hooks.

What each page covers

  • ModuleMeta — exact name, route_prefix, view_prefix, depends_on.
  • Routes — REST (/api/...) + Inertia view (/...) endpoints, with the permission each requires.
  • Public contracts — DTOs and protocols other modules import from <module>/contracts/.
  • Models — SQLModel tables the module owns.
  • Settings — DB-backed and bootstrap (SM_*) fields.
  • Permissions / menu / events / tasks / CLI — anything the module registers or exposes.
  • Inertia pages — what's under pages/*.tsx.

If a section isn't applicable to a given module, the page omits it.

Disabling a bundled module

Set SM_MODULES_ENABLED to a comma-separated allow-list; only those modules load. Useful when you don't need (say) background_tasks and don't want to run Redis:

bash
SM_MODULES_ENABLED=users,permissions,settings,dashboard

Don't drop users unless you've replaced authentication with a different module — most other bundled modules rely on it for request.state.user.

Next steps

Released under the MIT License.