ImpulseCore
Module manifest & registration
How each Impulse module declares itself to Core. The manifest is read at activation time; nothing else needs to be configured by hand.
1. One JSON file per module
Section titled “1. One JSON file per module”Every Impulse module ships a small manifest named impulse_module.json — at modules/servers/{slug}/impulse_module.json for modules with a server module, or modules/addons/{slug}/impulse_module.json for addon-only modules. Core reads it when the module is activated or upgraded. The file is plain JSON — not PHP — so a syntax error in module code can never prevent Core from reading the module’s identity.
An excerpt from ImpulseDB Postgres’s manifest (values change from release to release):
{ "slug": "impulsepostgres", "display_name": "Managed PostgreSQL", "version": "1.10.5", "core_min_version": "1.61.13", "service_type": "database", "license_prefix": "IPGRES-", "addon_module_slug": "impulsepostgres_addon", "tables": [ "mod_impulsepostgres_settings", "mod_impulsepostgres_servers", "mod_impulsepostgres_plans", "mod_impulsepostgres_services" ], "cron_tasks": [ {"name": "provision", "cadence": "2min"}, {"name": "usage", "cadence": "hourly"}, {"name": "alert_detection", "cadence": "hourly"}, {"name": "pg_upgrade", "cadence": "5min"} ], "hooks_consumed": [], "security": { "collector": "ImpulsePostgres\\Security\\Collector", "actuator": "ImpulsePostgres\\Security\\Actuator" }, "cve_products": [ "cpe:2.3:a:postgresql:postgresql" ], "licensing": { "key_prefixes": {"licensed": "IPGRES-", "dev": "IPGRESDEV-"}, "tier_features": { "free": [], "licensed": ["dedicated_provision", "replicas", "backups", "maintenance", "ip_allowlist", "custom_domain"], "dev": ["dedicated_provision", "replicas", "backups", "maintenance", "ip_allowlist", "custom_domain"] } }, "admin_proxy": { "table": "mod_impulsepostgres_servers", "health_path": "/health", "secret_encrypted": true }}2. What each field does
Section titled “2. What each field does”| Field | Purpose |
|---|---|
slug |
Stable internal identifier: lowercase letters, digits and underscores. Used as the table prefix (mod_{slug}_*) and the server module’s directory name. Required. |
display_name |
Human-facing name shown in Core’s Modules tab and status surfaces. Must be unique per install. Required. |
version |
Module version (semver). Core records it as the module’s installed version. Required. |
core_min_version |
Minimum ImpulseCore version this module needs. Core refuses to activate the module if it is older, and holds a newer release of an active module until Core is updated. |
service_type |
What kind of service the module sells: for the current modules, one of storage | database | cache | secrets | auth | search | hosting | compute | notifications (core is reserved for ImpulseCore). Drives grouping and icons in cross-module UI. Required. |
addon_module_slug |
The module’s WHMCS addon directory (for example impulsepostgres_addon). Core looks for the module’s hook, cron, lifecycle and security classes under it. |
license_prefix |
The module’s license-key prefix. |
licensing |
Opts the module into Core-managed licensing: key_prefixes maps each tier to its key prefix, tier_features lists what each tier unlocks, and optional dev_tier_limits caps a developer key’s usage. Keys are pasted in Core’s Modules & Licensing → Licenses tab. |
tables |
Lists the module’s own tables. Informational. |
cron_tasks |
Tasks the module wants Core’s cron runner to dispatch. Each task has a name (matched to a handler class in the module’s lib/Cron/ directory) and a cadence: 1min, 2min, 5min, 15min, hourly, daily or weekly. |
hooks_consumed |
Informational list of Core events the module handles. Core installs hook subscriptions from the handler classes it finds in the module’s lib/Hooks/ directory, not from this list. |
security |
Optional. Class names for the Security & Maintenance Collector and Actuator. Core finds these classes in the module’s lib/Security/ directory, including the per-server variants; the manifest entries are belt-and-braces. |
cve_products |
Optional. NVD CPE 2.3 strings naming upstream products this module manages (e.g. PostgreSQL, RustFS, Meilisearch). Core’s daily NVD-by-CPE feed pulls direct-install CVEs for these products. |
admin_proxy |
Optional. Where the module keeps its servers and which health path Core’s 15-minute admin-proxy health check calls. |
| Other blocks | Optional: email (Email Delivery settings), email_templates (Email Center entries), engines (modules that run more than one engine, chosen per server), upstream (managed upstream products and versions), project (Projects participation). |
3. Activation flow
Section titled “3. Activation flow”When you click Activate on a module’s addon entry in WHMCS, the module’s activate hook calls ImpulseCore::registerModule() with the path to its manifest, then ImpulseCore::activateModule(). Core then:
- Reads the manifest from the module’s directory.
- Validates it: required fields present,
slugwell formed,versionsemver,service_typeknown, every cron task named once with a known cadence, and any optional block well formed. An invalid manifest is refused with a readable error. - Compares
core_min_versionagainst Core’s own version. If Core is older, the module is listed as registered but not active, Core refusesactivateModule()with “Module ‘…’ requires ImpulseCore >= X, but installed Core is Y. Update ImpulseCore before activating this module.” (shown in WHMCS’s activation message) and records amodule.activate.core_min_version_unmeterror in the audit log. - Inserts or updates the module’s row in
mod_impulsecore_modules(slug, display name, version, status, manifest). - Installs hook subscriptions in
mod_impulsecore_hook_subscriptionsfor the handler classes in the module’slib/Hooks/. - Inserts or updates the module’s
cron_tasksinmod_impulsecore_cron_tasks; a new task is due straight away. - Records the module’s lifecycle handler from
lib/Lifecycle/, seeds its default monitoring alert rules, and adds its email templates to the Email Center.
Security Collector and Actuator classes are found in the module’s lib/Security/ directory when the Security pipeline runs, and the daily NVD feed reads cve_products from every active module’s manifest.
The whole flow is idempotent — re-running activate updates the existing rows rather than duplicating them. A module upgrade re-registers its manifest the same way, so new cron tasks and hooks arrive with the release; your own changes, such as a disabled cron task, are kept. Modules & Licensing → Modules lists any module release that is waiting for a newer ImpulseCore.
4. How modules talk back to Core
Section titled “4. How modules talk back to Core”Modules call into a static facade for everything cross-cutting:
// Audit a state changeImpulseCore::log('impulseobjects', 'server.provisioned', [ 'service_id' => 1234, 'region' => 'us-central-dallas',], 'info');
// Render the customer Security tab on a service pageecho ImpulseCore::renderClientSecurityTab($serviceId);
// Check what the module's license unlocks (Core-managed licensing)$canReplicate = \ImpulseCore\License::hasFeature('impulseobjects', 'replication');
// Find the other services in the same project$siblings = ImpulseCore::getSiblings($serviceId);
// Record a Security event (writes to both audit_log AND security_events)ImpulseCore::recordSecurityEvent($serviceId, 'patch_succeeded', [ 'cve' => 'CVE-2024-XXXXX',]);5. What modules ride on Core for
Section titled “5. What modules ride on Core for”| Concern | What Core provides |
|---|---|
| Project membership | Logical grouping of related services (a Postgres DB + an object-storage bucket + a search instance) into a single customer-facing project. |
| Cross-service detection | “Connected” badge in the customer client area showing related services across modules. |
| Hook dispatch | Re-dispatches WHMCS hooks under canonical event names; modules subscribe by name and never touch WHMCS hook registration directly. |
| Cron runner | Single Core cron entry dispatches every module’s tasks. Every run is logged per task; missed runs surface in Operations → Cron. |
| Audit log | Cross-module audit trail with module, event, level, service / client / project ids, request id and structured context. Single search surface across all modules. |
| Licensing | Shared XML licensing client. Same caching, grace and domain-detection behaviour for every licensed module. |
| Lifecycle | Suspension and termination grace windows, customer warning emails, and the purge at the end. |
| Security & Maintenance | CVE feeds, scheduled patching, pre-patch snapshots, customer maintenance windows. |
| Connection-string contributor | Unified .env exporter with secret masking. |