Skip to content

Module Development Standard

Every business capability on this platform is a module. Modules are licensed via the marketplace catalog and authorized via Spatie permissions. They are not PHP packages or plugins.

Reference implementation: Leads

Guides

AudienceDocument
Engineersmodule-development-developer.md
Production / opsmodule-development-production.md
Documentationdocumentation-governance.md
Architecture freeze../architecture/platform-freeze.md
Module architecturemodule-architecture.md
Module dependenciesmodule-dependencies.md
Module licensingmodule-licensing.md
Notification contractsnotification-architecture-contract.md

Principles

  1. Consistency over abstraction — flat Laravel layout; register through existing catalog, permissions, middleware, nav, and settings.
  2. Licensing ≠ authorizationmodule:{slug} then can:{slug}.{action}.
  3. Mirror Leads — Tasks, Calendar, Communication Templates, Invoices, Inventory, Purchases, HR, Payroll, Accounting, Assets, Projects must follow the same licensing + permission + UI structure (Communication Templates is additionally a cross-cutting consumer pattern).
  4. No shortcuts — every module ships backend, frontend, tests, docs, and CHANGELOG in the same delivery (Documentation Governance).
  5. Migrate-only production — new default modules and permissions ship as data migrations; never production db:seed for catalog/RBAC.
  6. Self-contained modules — each module owns its migrations, models, services, routes, UI, permissions, settings, docs, and tests; communicate through contracts/services only. See Module Architecture.
  7. Declare dependencies — required vs optional; free vs billable. See Module Dependencies.
  8. Independent licensing — design every module so it can be included, free, or billable. See Module Licensing.

Cross-cutting patterns (Sprint 2+)

  • Dashboard widgets — register via DashboardWidgetService on GET /dashboard; gate by module entitlement, permission, and assignee scope (see Calendar calendar widget as the latest example).
  • Notifications — Follow the frozen Notification Architecture Contract: versioned payload, route descriptors, NotificationBatch aggregation, Reverb/Echo realtime, modular SPA registry. Due/overdue work uses crm:send-due-notifications. Retention: notifications:prune.
  • Assignee scoping — reuse ScopesToAssignee so users without {slug}.assign only see their own records.

Definition of Done

A module is complete only when:

  • [ ] Backend implementation complete (models, migrations, services, controllers, requests, resources, policies, events, notifications)
  • [ ] Frontend complete (pages, forms, tables, filters, dialogs/drawers, loading/empty/error states)
  • [ ] Permissions enforced (Spatie + UI gates)
  • [ ] Module licensing enforced (module: middleware + SPA nav)
  • [ ] Tenant isolation verified
  • [ ] Audit logging (PlatformAuditService) implemented
  • [ ] Activity logging (Spatie LogsActivity + domain timeline where applicable)
  • [ ] Notifications implemented where applicable
  • [ ] Pest tests pass (CRUD, authz, validation, tenant isolation, module gate)
  • [ ] Playwright suite passes (test:e2e:{slug})
  • [ ] Manual browser QA passes
  • [ ] Developer / User / Production guides updated in the same PR (Documentation Governance)
  • [ ] API + database docs updated
  • [ ] CHANGELOG updated
  • [ ] No console errors; no failed network requests; build passes
  • [ ] No platform refactor required before the next module

Official documentation for the SaleOS SaaS Platform.