En vous promenant sur Beamreactor, nous stockons votre IP 48h pour des raisons de sécurité.

Leitor de Markdown

Base de conhecimento › BEAMREACTOR_CMDB

Beamreactor Cmdb

BeamReactor – CMDB (Configuration Management & Message Bus) #

Version: 1.0

Date: 2026.03.24

Audience: Core developers, plugin developers, system integrators

Scope: Inter-component communication, component registry, owner management

1. Overview

The CMDB is BeamReactor's backbone for inter-component communication. It provides:

  • A message bus for plugins, LLMs, load balancers, and services to exchange data
  • A component registry to declare and track what's running
  • An owner system for multi-tenant and federated deployments
  • Polling (flag-based) and push (handler callback) delivery modes
FileRole
lib/cmdb/CMDB.class.phpCore class — all static methods
lib/cmdb/cmdb.sqlSchema: 4 tables

Namespace: Beamreactor\CMDB\CMDB

2. Tables

TablePurpose
cmdb_ownersOwners: sites, clients, organisations
cmdb_registryDeclared components with dual ownership
cmdb_messagesMessage bus (the queue)
cmdb_subscriptionsWho listens to what

Installation #

php
use Beamreactor\CMDB\CMDB;

CMDB::install();  // Runs cmdb.sql — idempotent (CREATE IF NOT EXISTS)

3. Owners

Owners represent the entities that control components. A component has two optional owners:

RoleFieldMeaning
Businessbusiness_owner_idClient, contract holder, project sponsor
Technicaltechnical_owner_idOps team, sysadmin, DevOps

Owner Types #

TypeUsage
localThis BeamReactor instance
remoteExternal site / federated node
clientEnd customer / tenant
orgOrganisation / department
systemSystem-level (cron, scheduler)

Creating Owners #

php
// Business owner (a client)
$client_id = CMDB::createOwner('client', 'acme-corp', 'ACME Corporation',
    'https://acme.example.com/api',  // remote endpoint
    'admin@acme.com',
    ['contract' => 'PRO-2026', 'sla' => '99.9%'],  // metadata
    3  // trust level (high)
);

// Technical owner (ops team)
$ops_id = CMDB::createOwner('local', 'devops-team', 'DevOps Team');

Owner Methods #

MethodReturnsDescription
createOwner($type, $name, ...)int|falseCreate or update an owner (upsert)
getOwner(int $id)array|falseGet owner by ID (decodes metadata JSON)
findOwner($type, $name)array|falseFind owner by type + name
listOwners(?$type, ?$status)arrayList owners with optional filters
setOwnerStatus($id, $status)intChange status: active, suspended, revoked, pending
getOwnedComponents($id, $role)arrayList components for an owner (business/technical/any)

Inter-Site Authentication #

Owners can hold an API key for remote authentication:

php
// Generate and set (store the plain key, only the hash is saved)
$api_key = bin2hex(random_bytes(32));
CMDB::setOwnerApiKey($owner_id, $api_key);

// Verify later
if (CMDB::verifyOwnerApiKey($owner_id, $incoming_key))
{
    // Authenticated
}

Keys are hashed with Argon2ID. The plain key is never stored.

Trust Levels #

LevelMeaning
1Maximum trust (internal core)
3High trust (known partner)
5Standard (default)
7Low trust (new/unverified)
9Minimal trust (sandboxed)

4. Registry

Every component (plugin, LLM, service, load balancer) should register itself on startup.

Registering a Component #

php
CMDB::register(
    'plugin',                          // type
    'xchange',                         // name
    '1.0.0',                           // version
    'Marketplace plugin',              // description
    ['trading', 'rating', 'messaging'],// capabilities
    ['max_photos' => 5],              // config
    $client_id,                        // business owner
    $ops_id                            // technical owner
);

Component Types #

TypeUsage
pluginBeamReactor plugin
llmLLM connector (Aegis, GPT...)
lbLoad balancer instance
serviceBackground service, daemon
coreBeamReactor core component

Registry Methods #

MethodReturnsDescription
register($type, $name, ...)int|falseRegister component (upsert)
getComponent($type, $name)array|falseGet component with owner info (JOIN)
listComponents(?$type, ?$status)arrayList with optional filters
hasCapability($type, $name, $cap)boolCheck if component declares a capability
setStatus($type, $name, $status)intUpdate status
heartbeat($type, $name)intUpdate last_heartbeat timestamp
getStaleComponents($minutes)arrayFind components with no heartbeat since N minutes

Component Identifier Format #

Components are referenced as type:name strings throughout the message bus:

php
$id = CMDB::componentId('plugin', 'xchange');  // "plugin:xchange"
$parts = CMDB::parseComponentId($id);           // ['type' => 'plugin', 'name' => 'xchange']

5. Messages

The message bus uses a simple queue with flags and priorities.

Sending a Message #

php
CMDB::send(
    'plugin:xchange',       // source
    'plugin:messaging',     // target
    'xchange.first_contact',// channel
    [                        // payload (JSON)
        'buyer_id'   => 42,
        'seller_id'  => 7,
        'product_id' => 123,
        'message'    => 'Interested in your item'
    ],
    'notify',               // action (optional)
    CMDB::PRIORITY_NORMAL,  // priority (optional, default 5)
    3600,                   // TTL in seconds (optional, null = permanent)
    42                      // user_id (optional)
);

Request/Response Pattern #

For tracked exchanges with automatic correlation:

php
// Sender: create a request
$req = CMDB::request('plugin:xchange', 'plugin:messaging', 'xchange.first_contact', [
    'buyer_id' => 42,
    'seller_id' => 7,
]);
// $req = ['message_id' => 15, 'correlation_id' => 'a3f8...']

// Receiver: reply to it
CMDB::reply($req['message_id'], ['status' => 'conversation_opened']);

// Sender: check for responses
$responses = CMDB::getResponses($req['correlation_id'], 'plugin:xchange');

Polling (Receiver Side) #

php
// Get all pending messages
$messages = CMDB::poll('plugin:messaging');

// Filter by channel pattern
$messages = CMDB::poll('plugin:messaging', 'xchange.%');

// Quick checks
if (CMDB::hasPending('plugin:messaging'))
{
    $count = CMDB::countPending('plugin:messaging');
}

poll() automatically marks messages as READ and sets status to delivered.

Priority Constants #

ConstantValueUse
PRIORITY_CRITICAL1System failure, security alert
PRIORITY_HIGH3Needs prompt attention
PRIORITY_NORMAL5Default
PRIORITY_LOW7Background / informational
PRIORITY_IDLE9Cleanup, analytics

Messages are delivered in priority order (1 first), then by creation date.

6. Flags

Old-school bitfield system for message state tracking.

Flag Constants #

ConstantValueMeaning
FLAG_READ1Message has been seen
FLAG_ACK2Receiver acknowledged
FLAG_PROCESSED4Action completed
FLAG_ERROR8Processing failed
FLAG_EXPIRED16TTL exceeded

Usage #

php
// Set a flag
CMDB::setFlag($message_id, CMDB::FLAG_READ);

// Set multiple flags at once
CMDB::setFlag($message_id, CMDB::FLAG_ACK | CMDB::FLAG_PROCESSED);

// Clear a flag
CMDB::clearFlag($message_id, CMDB::FLAG_ERROR);

// Check flags (on a fetched message)
if (CMDB::hasFlag($msg['flags'], CMDB::FLAG_ACK))
{
    // Already acknowledged
}

// Shorthand: acknowledge = ACK + PROCESSED + status update
CMDB::acknowledge($message_id);

// Shorthand: mark as failed with error info
CMDB::fail($message_id, 'Connection timeout to remote API');

7. Subscriptions

Components can subscribe to message channels for push or poll delivery.

Subscribing #

php
// Poll mode (default) — component fetches messages with poll()
CMDB::subscribe('plugin:messaging', 'xchange.*');

// Push mode — handler is called immediately when a matching message arrives
CMDB::subscribe('plugin:messaging', 'xchange.first_contact', 'push',
    'plugins/messaging/handlers/cmdb_push.handler.php'
);

// Both modes
CMDB::subscribe('plugin:monitoring', 'llm.*', 'both',
    'plugins/monitoring/handlers/cmdb_push.handler.php',
    null,  // source filter (null = all sources)
    3      // priority_min: only priority 1-3
);

Push Handlers #

Push handler files are included when a matching message is sent. They receive:

VariableTypeDescription
$cmdb_push_message_idintID of the message that triggered the push
$cmdb_push_subscriberstringSubscriber component ID
php
<?php
// plugins/messaging/handlers/cmdb_push.handler.php
use Beamreactor\CMDB\CMDB;

$msg = CMDB::getMessage($cmdb_push_message_id);

if ($msg && $msg['channel'] === 'xchange.first_contact')
{
    // Create internal conversation between buyer and seller
    $payload = $msg['payload'];
    // ... create_conversation($payload['buyer_id'], $payload['seller_id']);

    CMDB::acknowledge($cmdb_push_message_id);
}
?>

Channel Patterns #

Subscriptions support wildcard matching:

PatternMatches
xchange.*xchange.first_contact, xchange.rating, etc.
llm.healthOnly llm.health
*.errorxchange.error, llm.error, etc.

Subscription Methods #

MethodReturnsDescription
subscribe($subscriber, $pattern, ...)int|falseSubscribe (upsert)
unsubscribe($subscriber, $pattern)intRemove subscription
getSubscriptions($subscriber)arrayList active subscriptions

8. Maintenance

TTL Expiration #

Messages with a ttl have an expires_at computed at creation. Expired messages must be swept:

php
// Run periodically (cron / scheduler)
$expired = CMDB::expireMessages();

Purge Old Messages #

php
// Delete processed/expired/failed messages older than 30 days
$deleted = CMDB::purge(30);

Stale Component Detection #

php
// Components that haven't sent a heartbeat in 30 minutes
$stale = CMDB::getStaleComponents(30);

foreach ($stale as $component)
{
    CMDB::setStatus($component['component_type'], $component['component_name'], 'degraded');
}

9. Typical Plugin Integration

A plugin registers itself and subscribes during its initialization (conf/{name}.conf.php or autoload):

php
use Beamreactor\CMDB\CMDB;

// Register
CMDB::register('plugin', 'xchange', '1.0.0', 'Marketplace', ['trading', 'rating']);

// Subscribe to responses
CMDB::subscribe('plugin:xchange', 'xchange.*', 'push',
    'plugins/xchange/handlers/cmdb_push.handler.php'
);

// Heartbeat (if the plugin runs as a service)
CMDB::heartbeat('plugin', 'xchange');

Sending Inter-Plugin Messages #

php
// xchange triggers a messaging conversation
CMDB::send('plugin:xchange', 'plugin:messaging', 'xchange.first_contact', [
    'buyer_id'   => $buyer_id,
    'seller_id'  => $seller_id,
    'product_id' => $product_id,
    'subject'    => 'Interested in: ' . $product_title,
]);

Receiving Messages #

php
// In a handler or cron job
$messages = CMDB::poll('plugin:xchange', 'messaging.%');

foreach ($messages as $msg)
{
    // Process
    CMDB::acknowledge($msg['id']);
}

10. Migrations

The CMDB includes a full SQL migration system. Each component (plugin, lib, core) can have versioned SQL files that are tracked, checksummed, and never replayed.

File Convention #

text
plugins/xchange/sql/migrations/001_initial.sql
plugins/xchange/sql/migrations/002_add_trades_table.sql
plugins/xchange/sql/migrations/003_add_rating_index.sql
lib/cmdb/sql/migrations/001_initial.sql

Files must be named with a sortable prefix. They are executed in alphabetical order.

Optional Description Header #

Place a description in the first SQL comment line:

sql
-- Description: Add trades table and buyer/seller indexes
CREATE TABLE IF NOT EXISTS xchange_trades ( ... );

Running Migrations #

php
// Single component
$result = CMDB::migrate(
    'plugin',                                    // component type
    'xchange',                                   // component name
    'plugins/xchange/sql/migrations',            // migrations directory
    '1.2.0',                                     // current version (optional)
    'admin',                                     // who runs this
    'production'                                 // environment tag
);
// $result = ['applied' => 2, 'skipped' => 1, 'failed' => 0, 'errors' => []]

// All components at once (scans lib/*, plugins/*)
$results = CMDB::migrateAll('deploy-server', 'production');
// $results = ['plugin:xchange' => [...], 'lib:cmdb' => [...], ...]

Checking Status #

php
// What migrations have been applied?
$status = CMDB::getMigrationStatus('plugin', 'xchange');
// Returns: migration_id, version, status, description, statements_count,
//          execution_time_ms, applied_by, environment, batch, applied_at

// What's pending?
$pending = CMDB::getPendingMigrations('plugin', 'xchange', 'plugins/xchange/sql/migrations');
// Returns: ['003_add_rating_index.sql']

Integrity Check #

Detects if migration files were modified after being applied (checksum mismatch) or deleted:

php
$tampered = CMDB::verifyMigrationIntegrity();

foreach ($tampered as $t)
{
    echo $t['component'] . ' / ' . $t['file'] . ': ' . $t['issue'];
    // "plugin:xchange / 001_initial.sql: checksum_mismatch"
}

Behavior #

ScenarioBehavior
File already appliedSkipped (checksum verified)
New file foundExecuted in transaction, recorded
Statement failsTransaction rolled back, status = failed, migration stops
File modified after applyWarning in verifyMigrationIntegrity()
File deleted after applyReported as file_missing

Batch Numbers #

All migrations executed in a single migrate() or migrateAll() call share the same batch number. This allows easy rollback identification.

Integration with Deployment #

On devarea.beamreactor.com, after syncing PHP files:

php
// Auto-run all pending migrations
$results = CMDB::migrateAll('devarea-deploy', 'production');

foreach ($results as $component => $r)
{
    if ($r['failed'] > 0)
    {
        // Alert: migration failed for $component
        trigger_error("Migration failed: $component — " . implode(', ', $r['errors']));
    }
}

11. Architecture Diagram

text
                        ┌─────────────┐
                        │ cmdb_owners │
                        │ (sites,     │
                        │  clients)   │
                        └──────┬──────┘
                   business_owner_id │ technical_owner_id
                               │
┌──────────────┐       ┌──────┴──────┐       ┌───────────────────┐
│   Plugin A   │──send─▶│ cmdb_messages│◀─poll──│    Plugin B       │
│ (xchange)    │       │  (the bus)  │       │ (messaging)       │
└──────────────┘       └──────┬──────┘       └───────────────────┘
       │                      │                        ▲
       │               ┌──────┴──────┐                 │
       └──register────▶│cmdb_registry│    ┌────────────┴──────┐
                       │ (who exists)│    │cmdb_subscriptions │
                       └─────────────┘    │ (who listens)     │
                                          └───────────────────┘

11. Quick Reference

Most Used Methods #

php
// Owners
CMDB::createOwner($type, $name, $display, $url, $email, $meta, $trust);
CMDB::getOwnedComponents($owner_id, 'business');

// Registry
CMDB::register($type, $name, $version, $desc, $caps, $config, $biz_owner, $tech_owner);
CMDB::getComponent($type, $name);
CMDB::hasCapability($type, $name, 'rating');

// Messages
CMDB::send($source, $target, $channel, $payload, $action, $priority, $ttl);
CMDB::poll($target, $channel_filter);
CMDB::request($source, $target, $channel, $payload);
CMDB::reply($message_id, $payload);
CMDB::acknowledge($message_id);
CMDB::fail($message_id, $error);

// Subscriptions
CMDB::subscribe($subscriber, $pattern, 'push', $handler);
CMDB::unsubscribe($subscriber, $pattern);

// Maintenance
CMDB::expireMessages();
CMDB::purge(30);
CMDB::getStaleComponents(30);

// Migrations
CMDB::migrate($type, $name, $dir, $version, $who, $env);
CMDB::migrateAll($who, $env);
CMDB::getMigrationStatus($type, $name);
CMDB::getPendingMigrations($type, $name, $dir);
CMDB::verifyMigrationIntegrity();
de en es fr pt