-
Notifications
You must be signed in to change notification settings - Fork 0
Home
A single-tenant, self-hosted field-service dispatch platform — customers, jobs & work-orders, estimates, invoicing, scheduling/dispatch. FastAPI backend, Vue 3 SPA, Postgres + Redis + Celery.
- Getting Started — run an instance with Docker in ~5 minutes.
Operating
- Getting Started — install & first login.
-
Configuration Reference — what every
.envgroup does. - Architecture — services, data model, request flow.
- Backup & Restore — dumps, restores, drills.
- Updating — upgrade safely (snapshot → migrate → health-gate).
Plugins
- Using Plugins — operators: installing/enabling third-party modules.
- Authoring Plugins — developers: building a plugin.
Conventions
-
Role & Nav Naming Conventions — how roles are spelled/stored (canonical long form in
users.role) and how nav visibility is decided. Read before touching role strings or adding a nav module.
GDX supports third-party modules (plugins): full-stack extensions an operator installs into their own instance, each with its own backend and its own (server-rendered) UI. Architecture & rationale: ADR-013.
Plugins are ordinary pip packages that register under the gdx.modules
entry-point group. They run inside a dedicated plugin-host container
(isolated from the core app — the VS Code "Extension Host" model), which the core
app proxies to at /api/plugins/*, forwarding the authenticated principal.
Plugins ship no browser JavaScript: their UI is declared as a JSON manifest
the host renders. Operators vet what they install; there is no central registry or
signing.
| Step | What | Status |
|---|---|---|
| 1 |
gdx.plugin_api foundation — manifest, discovery, version gate |
✅ |
| 2 |
PluginBase + forwarded-identity context, require_module
|
✅ |
| 3 |
plugin-host container + core /api/plugins/* proxy |
✅ verified live E2E |
| 4 | UI-manifest schema + Vue host renderer (vitest) | ✅ |
| 5 |
plugin_registry + in-app install / reconcile |
✅ verified live |
| 6 | Reference gdx-plugin-example plugin |
✅ verified live |
Verified on a live docker stack: authenticated user → core proxy →
plugin-host → the example plugin's own (migrated) table; module gating (403 before
grant, 200 after), tenant isolation, the catalog + UI manifest, and in-app install
via the registry → reconcile (pip-install into a /plugins volume → discover).
34 automated tests pass (30 backend pytest + 4 frontend vitest).
-
Auto-restart on install isn't built. Registering a plugin records intent;
applying it currently needs a manual
plugin-hostrestart. The docker-socket "supervisor" that restarts plugin-host from the app is future work. -
Migrations use
PluginBase.metadata.create_all(idempotent table creation), not yet a per-plugin Alembic branch — fine until a plugin needs schema changes. - The UI renderer is unit-tested (vitest) but not yet wired into a route/nav and not browser-E2E'd on the live stack.
- The
/pluginsvolume must be writable by the plugin-host runtime user (ops).