This repository is a reference architecture showcase extracted from a real, production system. It focuses on architectural decisions, boundaries, and operational patterns — not on business-specific logic or a ready-to-deploy plugin.
The full system context, constraints, and outcomes are described in the corresponding case study: 👉 https://rocketdeploy.dev/en/case-studies/ops-layer-for-woocommerce
- This plugin is an admin extension for a CMS-driven commerce site, designed to coordinate internal operational workflows with role-aware access.
- It provides operator-facing screens, API endpoints, and document generation helpers to support day-to-day operational tasks in a controlled environment.
- This document intentionally omits business rules, pricing logic, customer data, and any domain-sensitive workflows.
- Plugin bootstrap file (root PHP entry point): registers hooks, loads modules, and defines version/constants.
- Admin menu and settings module: wires configuration screens and persists options.
- Admin dashboard module: aggregates counts for dashboards and widgets.
- Operator REST controller: exposes endpoints for list views and action-based transitions.
- Install/upgrade module: manages schema setup and role/capability changes.
- Document generation module: renders templates and produces PDFs or similar artifacts.
- Template layer (admin + documents): declarative views that receive sanitized data.
- Asset bundles (admin UI): front-end code for panels and widgets.
+--------------------------+ +-----------------------------+ +-----------------------------+
| CMS Integration Layer | ----> | Core / Application Layer | ----> | Infrastructure / Adapters |
| - hooks & admin menus | | - workflow services | | - CMS DB (entities/meta) |
| - REST controllers | | - validation / policy | | - object storage (optional) |
| - templates & assets | | - document generation | | - third-party libraries |
+--------------------------+ +-----------------------------+ +-----------------------------+
- CMS integration layer adapts platform hooks, admin screens, and API requests into internal actions.
- Core/application layer hosts reusable workflow logic and shared validations with minimal I/O.
- Infrastructure/adapters encapsulate storage, external integrations, and library-specific concerns.
- Boundary rule: Only the CMS integration layer may call platform APIs (hooks, option storage, entity APIs).
- Boundary rule: Core/application code must remain framework-agnostic and operate on plain data structures.
- Boundary rule: Infrastructure/adapters can call external libraries and storage APIs, but should not contain business rules.
- Enforcement today: Boundaries are enforced by file placement and call patterns (controllers call services; services call helpers/adapters).
- Known coupling: Some helper utilities still call platform functions directly, creating lightweight coupling that should be isolated over time.
- Plugin bootstrap: Defines constants, loads modules, and registers hooks/activation logic.
- Shared helpers: Cross-cutting utilities for sanitization, formatting, and common data shaping.
- Admin layer: Menus, settings, dashboards, and access bridge for admin-only workflows.
- Operator panels: REST controllers and request handlers for operator actions and list views.
- Order/admin UI extensions: List columns, bulk actions, and metabox UI enhancements.
- Document pipeline: Data shaping, template rendering, and PDF generation via libraries.
- Object storage adapter (optional): Request signing and storage integration for artifacts.
- Templates: Admin and document templates, with data passed in from controllers/services.
- Assets: Admin UI JavaScript/CSS bundles for panels and widgets.
- Localization: Translation catalog for user-facing strings.
-
Operator panel data fetch
- Trigger: API endpoint invoked by admin UI.
- Validation/auth: Permission callback validates role/capability and sanitizes query params.
- Core use-case invoked: Query summaries and lists based on current workflow state.
- Side effects: None (read-only), optional lightweight caching.
- Observability: Consistent error responses and platform logging where enabled.
- Evidence:
- Operator REST controller for list endpoints.
- Admin dashboard aggregation module.
-
State transition action
- Trigger: API endpoint for an action (e.g., confirm/undo/mark) invoked by an operator panel.
- Validation/auth: Capability checks plus input validation and idempotency guards.
- Core use-case invoked: Apply state transition and record an operator event.
- Side effects: Updates entity meta/state and appends to an internal event log table.
- Observability: Errors handled via structured API responses; events stored for audit trails.
- Evidence:
- Operator REST controller for action endpoints.
- Operator events logging module.
-
Document generation
- Trigger: Admin post action from an admin screen or bulk action.
- Validation/auth: Nonce and capability checks before generating files.
- Core use-case invoked: Render HTML template and generate a document artifact.
- Side effects: Stores generated artifacts and updates metadata flags when applicable.
- Observability: Errors surfaced to admin UI; optional adapter logging.
- Evidence:
- Admin post handler for document generation.
- Document rendering/generation module.
-
Dashboard counters
- Trigger: API endpoints backing dashboard widgets.
- Validation/auth: Role/capability checks plus minimal input validation.
- Core use-case invoked: Aggregate counts by status or workflow stage.
- Side effects: None; read-only queries.
- Observability: Standard API error response format.
- Evidence:
- Admin dashboard module.
- Shared query helper utilities.
-
Install/upgrade
- Trigger: Plugin activation or version check on load.
- Validation/auth: Activation hook (administrator context).
- Core use-case invoked: Create/upgrade event table and ensure role capabilities.
- Side effects: Writes to options and database schema.
- Observability: Follows platform upgrade routines; failures surface as admin notices.
- Evidence:
- Install/upgrade module for schema and role setup.
- Bootstrap file registering activation hooks.
- State is stored in CMS primitives: entity meta for per-entity state, options for configuration, and a custom event-history table.
- Event history is modeled as append-only records with columns for entity reference, actor reference, event type, optional metadata payload, and timestamps.
- State transitions are guarded by checks that prevent duplicates and enforce allowable transitions.
- Migration/upgrade logic is centralized in an install/upgrade module that evolves schema and capability sets.
- Error handling uses structured error objects and defensive checks; failures are surfaced to API clients or admin screens.
- Idempotency is achieved via state guards and explicit markers to prevent duplicate processing.
- Retry/backoff is minimal inside the plugin; external operations are designed to be re-invoked safely.
- Logging is conservative and routed through platform facilities or adapter-level logging.
- Authentication and authorization are delegated to platform roles/capabilities and API permission callbacks.
- Nonce validation is used for admin-post actions that mutate state.
- Example (generic): "Only users with the operation-management capability may call the action endpoint; otherwise the request is rejected."
- Secrets are stored in platform options and loaded only when integrations are enabled; values are never hard-coded.
- Input validation uses platform sanitizers and strict checks for identifiers, dates, and text fields.
- Decision: Keep the CMS as the primary adapter layer. Why: Leverages platform hooks, roles, and admin UI. Trade-off: Tighter coupling to the platform lifecycle. Risk: Harder to test core logic in isolation. Mitigation: Extract pure functions for validation and state mapping.
- Decision: Use API endpoints for operator panels. Why: Enables responsive UIs and decouples views from logic. Trade-off: Requires careful permission callbacks and request validation. Risk: Elevated attack surface for admin endpoints. Mitigation: Centralize permission checks and input sanitization.
- Decision: Record operator events in a dedicated table. Why: Provides a durable audit trail and efficient querying. Trade-off: Schema migrations must be maintained across versions. Risk: Drift between code and schema. Mitigation: Versioned migrations via install/upgrade module.
- Decision: Store workflow state in entity meta. Why: Aligns with existing entities without duplicating records. Trade-off: Meta-heavy queries can be less performant. Risk: Query performance degradation as data grows. Mitigation: Limit meta queries and add targeted indexes when needed.
- Decision: Bundle document libraries locally. Why: Ensures consistent rendering without external service dependencies. Trade-off: Larger plugin footprint. Risk: Library updates lag behind security fixes. Mitigation: Maintain a routine dependency review schedule.
- Decision: Provide optional object storage integration. Why: Allows offloading artifacts without hard dependency on external systems. Trade-off: Additional configuration complexity. Risk: Misconfiguration leading to failed uploads. Mitigation: Readiness checks and clear admin diagnostics.
- Decision: Implement role-based access for multiple operator panels. Why: Enforces least-privilege access by function. Trade-off: Capability maintenance on upgrades. Risk: Permission drift after updates. Mitigation: Re-apply capabilities during version checks.
- Decision: Centralize validation in shared helpers. Why: Consistent sanitization and normalization. Trade-off: Shared helpers may become a coupling point. Risk: Hidden dependencies across modules. Mitigation: Keep helpers stateless and narrowly scoped.
- Decision: Use a single event log schema for multiple actions. Why: Simplifies auditing and reporting. Trade-off: Requires flexible metadata storage. Risk: Overuse of unstructured payloads. Mitigation: Define stable metadata keys and document them.
- Decision: Provide admin-post flows for document generation. Why: Aligns with platform admin conventions. Trade-off: Less suitable for long-running tasks. Risk: Timeouts for large batches. Mitigation: Encourage batch sizing and surface warnings.
- Decision: Keep templates thin and data-driven. Why: Minimizes logic in views. Trade-off: More logic in controllers/services. Risk: Controller bloat. Mitigation: Split data shaping into small helper functions.
- Decision: Outside the CMS, use a service layer with dependency injection. Why: Improves testability and module boundaries. Trade-off: Additional setup complexity. Risk: Over-engineering for small deployments. Mitigation: Provide a minimal default container.
- Decision: Outside the CMS, store events in a dedicated analytics store. Why: Enables advanced querying and retention policies. Trade-off: Added infrastructure dependencies. Risk: Operational overhead. Mitigation: Provide a fallback in the primary database.
- Start with the plugin bootstrap to understand which modules are loaded and which hooks are registered.
- Trace API endpoints in operator panels and dashboard modules to see how requests map to core actions.
- Review the install/upgrade routines to understand database tables and capability management.
- Focus on how state changes are validated and recorded rather than the business-specific meaning of states.
- Note that domain-specific status labels, business rules, and operational procedures are intentionally omitted here.
- Modules to extract:
core/: workflow engine, validation, and event recording.adapters/: persistence adapter, logging adapter, storage adapter.api/: HTTP controllers with permission hooks.ui/: minimal admin UI and templates.docs/: architecture and usage notes.
- Responsibilities:
- Core defines domain-agnostic state transitions and event recording.
- Adapters map core interfaces to platform APIs and storage backends.
- API layer exposes endpoints with explicit permission checks and input validation.
- UI layer renders admin views and consumes API endpoints.
- Target folder structure (reference):
reference-plugin/
core/
workflows/
validation/
events/
adapters/
cms/
storage/
logging/
api/
controllers/
routes/
ui/
admin/
templates/
docs/
architecture.md
usage.md
If you’re dealing with a similar problem — complex operational workflows, CMS constraints, or systems that must work reliably beyond standard admin panels — feel free to reach out: