← Back to Table of Contents

5. Plugin Architecture

KMP uses CakePHP plugins to isolate optional or domain-specific behavior while sharing core identity, authorization, workflow, and tenant infrastructure. app/config/plugins.php is the source of truth for what is enabled and for first-party migration order.

Enabled first-party domains

Order Plugin Owns
1 Activities Activity definitions and member authorizations
2 Officers Departments, offices, officer assignments, rosters, and warrant integration
3 Awards Award catalog, recommendations, approval processes, feedback, bestowals, and court agendas
4 Waivers Gathering waiver requirements, uploads, attestations, compliance, and closure

Bootstrap and GitHubIssueSubmitter are enabled local utility plugins. Queue is the external background-job plugin. Other framework plugins in plugins.php provide authentication, authorization, migrations, auditing, soft deletion, image handling, and exports.

Template is disabled and incomplete. It is not a production-ready starter and should not be copied as the basis of a new plugin.

Shared contracts

Expected plugin shape

plugins/Feature/
├── config/Migrations/
├── src/
│   ├── Controller/
│   ├── Model/{Entity,Table}/
│   ├── Policy/
│   ├── Services/
│   ├── View/Cell/
│   ├── KMP/GridColumns/
│   └── FeaturePlugin.php
├── templates/
├── assets/                 # only when the plugin has frontend assets
└── tests/TestCase/

Namespaces and ownership stay inside the plugin. Plugin controllers extend the app controller base, tables/entities/policies extend the project bases, and migrations live in the plugin that owns the data.

Bootstrap responsibilities

A first-party plugin bootstrap class may:

Keep bootstrap work deterministic and inexpensive. Durable business processing belongs in a service or workflow, not in plugin bootstrap.

Multi-tenant rules

Plugin tables use the active tenant database. Plugin migrations and settings must be applied to every tenant through the platform lifecycle/migration tooling. Plugin code must not open a tenant connection from request data, read the platform registry directly, or add tenant_id columns to tenant-domain tables.

Queued jobs, scheduled workflows, cache entries, documents, and mail initiated by a plugin must retain tenant context. Cross-tenant fleet work belongs in platform services, which enter one tenant at a time.

UI and API integration

Do not modify core controllers/templates to insert plugin-specific UI. Register navigation and cells from the plugin, and preserve detail-tab ordering conventions. API routes remain plugin-owned and must use the app API base, resource policies/scopes, and generated OpenAPI merge path.

Plugin frontend assets are built by Vite. Stimulus controllers use window.Controllers; do not add Laravel Mix manifests or standalone unversioned scripts.

Verification

See Extending KMP for an implementation checklist.