Appearance
System
The System app is the always-installed core of the Lubb platform — it is never listed for install/uninstall like a regular app because every site needs it. It covers your own account (profile), who else has access to this organization (users, roles, invitations), cross-tenant organization administration on the platform hub, the site-wide Settings screens (branding, email, roles, API keys, and more), the Apps Library that controls which apps a site runs, and — for platform staff only — the "Grids" browser over the grid engine's own configuration tables. Regular end users mostly touch their own profile and the Apps Library; the Users/Organizations/Roles/ Sites/App Store/Grids screens are gated to admins and platform superusers.
What you can do
- Profile — update your own name, email and password (
PUT /me), and view your current account details (GET /me). - Users — see everyone in the active organization (or, for a superuser on the portal, "all organizations" at once), edit a member's role, extension, or status, invite a new user by email, edit a user's login email/password, manage which roles a user holds (a user can hold more than one role at a time), and send or resend "set your password" login-details emails (with a required preview before every send) — unverified users get a verify-your-email link instead until they confirm.
- Organizations (superuser, cross-tenant) — the full list of every tenant/customer of record on the platform: edit name, slug, plan tier, contact details and status, upload an org icon, and suspend/activate one organization or a bulk selection.
- Roles (superuser) — see the built-in role catalog plus any custom roles added for the site, and cap a role to a specific allow-list of apps (Roles → per-app checkboxes); add or delete custom roles.
- Settings — the site-wide configuration screens under
/settings: Branding (logo/company name used across emails and the SPA theme), Site, Email (SMTP), API Keys, Payments, Accounting/Tax, Activation Email Templates, Number Porting, Display and Appearance. - Apps Library — browse the app catalog for the current site, see what's installed, install or uninstall an app, reorder the sidebar, tint an app's icon colour, and (superuser) toggle whether apps this site isn't entitled to run are shown at all.
- Sites (platform hub only) — one row per site on the platform: its plan, billing status, which commercial modules it's entitled to (drives what the Apps Library will let that site install), and its live host + installed-app count.
- App Store (platform hub only) — the hub's "desired state" record per site (which apps/menu structure/colours/order it should have), with a dry run to preview drift against the site's actual state and a Sync Now to apply it; can also mirror one site's menu structure onto another and turn on hourly auto-sync.
- Grids (superuser) — a read-mostly browser over the grid engine's own configuration: every grid's columns, buttons, and stat cards (all rebuilt from code on every backend restart, so edits here don't stick), plus users' saved column layouts, which are the one thing here you actually can delete.
Common tasks
Invite a new user to your organization Go to System → Users → "Invite user" (toolbar button). This opens the invite modal, which posts to the invitations API and emails the invitee a signup link; once they accept, a Membership row appears in this grid with their assigned role.
Change someone's role or suspend their access In System → Users, edit the row's Role or Status cell directly, or use the row's "Manage roles" button to add/remove individual roles without touching the others they hold. Demoting the last remaining top-level role holder (e.g. the only "owner") is blocked.
Install an app from the Apps Library Open System → App Library (
/apps), find the app card, and click Install. The install is scoped to the current site and is blocked if the site's plan (see Sites, on the hub) isn't entitled to that app. Uninstall works the same way from an installed app's card; the built-insystemapp itself can never be removed.Cap a role to a limited set of apps Go to System → Roles, pick the role, and check only the apps it should see. A role with no explicit allow-list keeps seeing every installed app (subject to its normal privilege tier); "admin" and "owner" can't be capped. This has no effect on portal sites, whose role catalog is fixed.
Adjust a grid's fields via Grid Registry The System → Grids page lists every grid on the platform (its
erp_modulesrow). Drilling into a grid's "Fields" shows its columns; most fields and buttons here are read-only because they're rebuilt from Python code on every restart — the actual place to hand-edit one field's display/form behaviour is the grid's own column-menu "Field Config" editor, which sets anis_customizedflag that protects that one field from being overwritten on the next reseed.Reclaim a saved layout that's no longer wanted In System → Grids, drill into a grid and open "Saved Layouts". Select the stale layout(s) and Delete — this is a hard delete (saved layouts have no soft-delete column), unlike almost everything else in the platform.
Data model
- Tenant — one row per organization/customer of record on the platform (name, slug, plan tier, status, contact info); the "Organizations" grid.
- Membership — a user's role within one tenant; a user can hold several rows (one per role). Backs the "Users" grid.
- User — the platform-wide account record (email, full name, extension, password, email-verified flag) joined onto Membership for display/edit.
- SitePlan — per-site plan/billing status and JSON list of entitled commercial modules; lives on the platform hub. Backs the "Sites" grid.
- SiteAppState — per-site desired app list, disabled apps, app order, app colours, menu-mirror source and auto-sync flag, plus the result of the last sync; lives on the hub. Backs the "App Store" grid.
- ErpModule — one row per grid (slug, model, sort order, access flags, create/edit/delete permissions, custom form layout).
- ErpModuleField — one row per grid column/form field, including the
is_customizedflag that protects a hand-edited field from the every-boot reseed. - ErpGridButton — one row per row/toolbar/header/bulk button on a grid, referencing its server-side handler by name.
- ErpModuleStat — one row per stat card shown above a grid.
- GridLayout — a user's (or the shared default) saved AG Grid column/filter state for one grid; the only one of these five tables never rebuilt from code.
Configuration & integrations
Per-app visibility is controlled by role-based access (role_app_access, managed under System → Roles, app/api/roles.py / app/core/apps.py):
- A built-in role with no configured allow-list is unaffected — it sees every app installed on the site, subject to the normal privilege tiers (viewer/admin/owner and friends).
- A role given an explicit allow-list is capped to exactly those app slugs.
adminandowneralways have full access and cannot be capped.- Custom roles (added via the Roles screen) default to capped to nothing until an admin explicitly grants apps, and are always a capped peer of the built-in "sales" role for privilege-tier purposes.
- Writes (create/delete role, change an allow-list) require a platform superuser and apply platform-wide, across every tenant on the site.
- Customer-portal sites have a fixed, non-extensible role catalog (superadmin/service_user) — the Roles screen's custom-role and per-app access editing is disabled there, since portal app-menu visibility is already driven by subscription/customer scope, not
role_app_access.
Site entitlements gate what the Apps Library will even let you install: SitePlan.entitled_modules (edited from the hub's Sites grid) determines which commercial modules a site is allowed to run, and the install endpoint in app/api/apps.py enforces that before adding an app.
API reference
Most of System is served by the generic grid engine (app/social/api/grid.py, mounted under /grid), so each grid below behaves like standard CRUD:
GET /grid— list grid configs the caller can see.GET /grid/{slug}/data— paginated rows for a grid (e.g.users,organizations,sites,app-store,grids,grid-fields,grid-buttons,grid-stats,grid-layouts).POST /grid/{slug}/PUT /grid/{slug}/{row_id}/DELETE /grid/{slug}/{row_id}— create/update/delete a row, where the grid allows it (most Grid Registry tables are read-only; onlygrid-layoutssupports a delete).POST /grid/{slug}/action/{key}— run a named row/bulk/toolbar button action (e.g. Users'send_login_details,send_verification; Sites' suspend/activate; App Store'sdry_run/sync_now).GET /grid/{slug}/stats— the stat cards above a grid.GET /grid/{slug}/layout/PUT/DELETE— a user's saved column layout for a grid.
Purpose-built endpoints outside the grid engine:
GET /me/PUT /me— read/update your own profile.GET /tenants/{tenant_id}/members— list an organization's memberships.PATCH /tenants/{tenant_id}/members/{membership_id}— edit a member's role/status.POST /tenants/{tenant_id}/members/{membership_id}/roles/DELETE .../roles/{role}— grant/revoke an individual role on a membership.PATCH /tenants/{tenant_id}/members/{membership_id}/credentials— change a member's login email/password.POST /invitations/accept,GET /invitations/{token},POST /tenants/{tenant_id}/invitations— the invite-a-user flow.GET /apps— the app catalog for the active site, annotated with install state.POST /apps/{slug}/install/POST /apps/{slug}/uninstall— install or remove an app from the current site.POST /apps/{slug}/colour— set an app's icon colour override.POST /apps/reorder— reorder the Apps Library / sidebar.POST /apps/show-not-allowed— toggle showing apps this site isn't entitled to install.GET /roles— the role catalog plus each role's app allow-list.POST /roles/DELETE /roles/{role}— add/remove a custom role.PUT /roles/{role}— set a role's app allow-list.