MultiFlexi Application Development¶
This guide explains how to create MultiFlexi applications that can be managed and executed by the MultiFlexi platform.
Overview¶
A MultiFlexi application consists of:
Application JSON definition - Describes the application, its configuration, and environment variables
Executable script(s) - The actual program that performs the work
Source code - Business logic implementation
Configuration files - composer.json, .env.example, etc.
Project Structure¶
A typical MultiFlexi application project should have the following structure:
your-application/
├── bin/
│ ├── app-command-1
│ └── app-command-2
├── src/
│ └── YourApplication.php
├── multiflexi/
│ ├── app-name-1.multiflexi.app.json
│ └── app-name-2.multiflexi.app.json
├── composer.json
├── .env.example
└── README.md
Application JSON Definition¶
The application definition is a JSON file that conforms to the MultiFlexi schema.
Schema Location¶
The schema is available at: https://raw.githubusercontent.com/VitexSoftware/php-vitexsoftware-multiflexi-core/refs/heads/main/multiflexi.app.schema.json
Basic Structure¶
{
"$schema": "https://raw.githubusercontent.com/VitexSoftware/php-vitexsoftware-multiflexi-core/refs/heads/main/multiflexi.app.schema.json",
"schemaVersion": "3.2.1",
"uuid": "unique-uuid-here",
"version": "1.0.0",
"name": {
"en": "Application Name",
"cs": "Název aplikace"
},
"description": {
"en": "Application description",
"cs": "Popis aplikace"
},
"tags": [
"Tag1",
"Tag2"
],
"homepage": "https://github.com/yourorg/your-app",
"executable": "command-name",
"environment": {
"ENV_VAR_NAME": {
"type": "string",
"description": {
"en": "Description",
"cs": "Popis"
},
"defval": "default_value",
"required": true,
"category": "API"
}
}
}
Required Fields¶
$schema - Reference to the MultiFlexi schema
schemaVersion - Current version is “3.2.1”
uuid - Unique identifier for your application (generate using uuidgen)
version - Application version (semantic versioning)
name - Localized application name (at least “en” and “cs”)
description - Localized description
tags - Array of tags for categorization
homepage - Project homepage URL
executable - Name of the command to execute
environment - Environment variable definitions
Defining Output Artifacts¶
If your application produces output files (reports, exports, documents),
declare them in the artifacts array. MultiFlexi will automatically collect
all matching files after each job execution.
Each artifact entry has these fields:
name (required) — Localized display name
path (required) — Regex pattern matched against filenames in the temp directory
type (required) — Type of artifact (e.g.
"file")description — Localized description
Example:
"artifacts": [
{
"name": {"en": "JSON Report", "cs": "JSON zpráva"},
"type": "file",
"path": ".*\\.json$",
"description": {
"en": "Output report in JSON format",
"cs": "Výstupní zpráva ve formátu JSON"
}
}
]
The path is a regex pattern. Common examples:
".*\.json$"— matches any.jsonfile"invoice_.*\.pdf$"— matches files likeinvoice_2025.pdf"report\.csv"— matches exactlyreport.csv
Note
The artifacts array replaces the older RESULT_FILE environment
variable approach for declaring output files. RESULT_FILE is still
supported for backward compatibility, but new applications should use
artifacts to declare all output files.
Environment Variable Types¶
Supported types:
string - Text value
password - Sensitive text (will be hidden in UI)
bool - Boolean value (true/false)
integer - Numeric value
set - Predefined set of options
Environment Variable Categories¶
API - API credentials and endpoints
Behavior - Application behavior settings
Security - Security-related settings
Other - Other configuration
Example Environment Variable¶
"ABRAFLEXI_URL": {
"type": "string",
"description": {
"en": "AbraFlexi Server URI",
"cs": "Adresa serveru AbraFlexi"
},
"defval": "https://demo.flexibee.eu:5434",
"required": true,
"category": "API"
}
Example with Set Type¶
"LANG": {
"type": "set",
"description": {
"en": "Locale for this application",
"cs": "Jazykové nastavení aplikace"
},
"defval": "cs_CZ",
"required": false,
"options": [
"cs_CZ",
"en_US"
],
"category": "Other"
}
Composer Configuration¶
Create a composer.json file to define dependencies:
{
"name": "yourorg/your-application",
"description": "Your application description",
"version": "1.0.0",
"type": "project",
"license": "MIT",
"authors": [
{
"name": "Your Name",
"email": "your.email@example.com"
}
],
"require": {
"php": ">=7.4",
"vitexsoftware/ease-core": "*",
"vitexsoftware/multiflexi-core": "*"
},
"autoload": {
"psr-4": {
"YourNamespace\\": "src/"
}
},
"minimum-stability": "stable",
"prefer-stable": true
}
Executable Scripts¶
Create executable scripts in the bin/ directory.
Example (bin/your-command):
#!/bin/bash
php -f /usr/share/your-application/YourScript.php -- $@
Make the script executable:
chmod +x bin/your-command
PHP Application Code¶
Create your application logic in the src/ directory.
Basic Structure¶
<?php
declare(strict_types=1);
namespace YourNamespace;
use Ease\Shared;
require_once '../vendor/autoload.php';
\define('EASE_APPNAME', 'YourApplication');
$exitcode = 0;
// Parse command line options
$options = getopt('o::e::', ['output::environment::']);
// Initialize configuration from environment
Shared::init(
[
'REQUIRED_VAR_1',
'REQUIRED_VAR_2',
'ABRAFLEXI_URL',
'ABRAFLEXI_LOGIN',
'ABRAFLEXI_PASSWORD',
],
\array_key_exists('environment', $options) ? $options['environment'] :
(\array_key_exists('e', $options) ? $options['e'] : '../.env'),
);
// Set output destination
$destination = \array_key_exists('output', $options) ?
$options['output'] : Shared::cfg('RESULT_FILE', 'php://stdout');
// Initialize localization if needed
\Ease\Locale::singleton(null, '../i18n', 'your-app');
// Your application logic here
$yourApp = new YourApplication();
if (Shared::cfg('APP_DEBUG', false)) {
$yourApp->logBanner();
}
$report = $yourApp->process();
// Generate MultiFlexi-compliant report
$multiFlexiReport = $yourApp->generateMultiFlexiReport(
$report,
'operation_type',
$exitcode
);
$written = file_put_contents(
$destination,
json_encode($multiFlexiReport, \JSON_PRETTY_PRINT)
);
$yourApp->addStatusMessage(
sprintf('MultiFlexi report saved to %s', $destination),
$written ? 'success' : 'error'
);
exit($exitcode);
Environment Configuration¶
Create a .env.example file with placeholder values:
# AbraFlexi Configuration
ABRAFLEXI_URL=https://demo.flexibee.eu:5434
ABRAFLEXI_LOGIN=winstrom
ABRAFLEXI_PASSWORD=placeholder_password
ABRAFLEXI_COMPANY=demo_company
# Application Configuration
EASE_LOGGER=console|syslog
RESULT_FILE=result.json
# Application Behavior
APP_DEBUG=false
Important: Do not include real passwords in .env.example
MultiFlexi Report Generation¶
All MultiFlexi applications must produce a JSON report that conforms to the MultiFlexi report schema.
Report Schema¶
The report schema is available at: https://raw.githubusercontent.com/VitexSoftware/php-vitexsoftware-multiflexi-core/refs/heads/main/schema/report.json
Required Fields¶
producer - Name of the script/application that generated the report (string)
status - Application execution result: “success”, “error”, or “warning” (string)
timestamp - Execution completion time in ISO8601 format (string)
Optional Fields¶
message - Human-readable message about the execution result (string)
artifacts - Artifacts produced by the application, keys correspond to names in ‘produces’ section (object)
metrics - Additional execution metrics with numeric or string values (object)
Report Structure¶
{
"producer": "YourApplicationName",
"status": "success",
"timestamp": "2025-01-21T17:45:00+01:00",
"message": "Processing completed successfully",
"artifacts": {
"invoices": [
"/path/to/invoice1.pdf",
"https://example.com/invoice/123"
]
},
"metrics": {
"processed_count": 42,
"created_count": 38,
"skipped_count": 4,
"total_amount": 15000.50,
"exit_code": 0
}
}
Generating Reports in PHP¶
Here’s a complete example of generating a compliant report:
<?php
// Track metrics during processing
$processedCount = 0;
$successCount = 0;
$errorCount = 0;
$exitcode = 0;
// Your application logic here
// ...
// Determine overall status
$hasErrors = false;
$hasWarnings = false;
// Check status messages for errors/warnings
foreach ($yourApp->getStatusMessages() as $message) {
if (isset($message['type'])) {
if ($message['type'] === 'error') {
$hasErrors = true;
$exitcode = 1;
}
if ($message['type'] === 'warning') {
$hasWarnings = true;
}
}
}
// Set status based on errors and warnings
if ($hasErrors) {
$status = 'error';
$message = 'Processing completed with errors';
} elseif ($hasWarnings) {
$status = 'warning';
$message = sprintf(
'Processed %d items with %d warnings',
$processedCount,
$warningCount
);
} else {
$status = 'success';
$message = sprintf(
'Successfully processed %d items',
$successCount
);
}
// Build the report
$report = [
'producer' => 'YourApplicationName',
'status' => $status,
'timestamp' => date('c'), // ISO8601 format
'message' => $message,
'metrics' => [
'processed_count' => $processedCount,
'success_count' => $successCount,
'error_count' => $errorCount,
'exit_code' => $exitcode,
],
];
// Optionally add artifacts if your app produces files/URLs
if (!empty($createdFiles)) {
$report['artifacts'] = [
'documents' => $createdFiles,
];
}
// Write report to destination
$written = file_put_contents(
$destination,
json_encode($report, \JSON_PRETTY_PRINT)
);
exit($exitcode);
Complete Report Example¶
Here’s a real-world example from the BlockNet application:
$report = [
'producer' => 'BlockNet',
'status' => 'warning',
'timestamp' => '2025-01-21T17:45:00+01:00',
'message' => 'Blocked 15 clients with ODPOJEN label. Skipped 2 VIP and 1 NODISCONNECT clients.',
'metrics' => [
'total_disconnected_customers' => 18,
'clients_blocked' => 15,
'vip_skipped' => 2,
'no_disconnect_skipped' => 1,
'exit_code' => 0,
],
];
Status Determination Guidelines¶
success - All operations completed without errors or warnings
warning - Operations completed but with non-critical issues (e.g., skipped items)
error - Critical errors occurred, operations may have failed
Best Practices for Reports¶
Always include producer - Use a consistent, descriptive name for your application
Use ISO8601 timestamps - Use
date('c')in PHP for proper formattingProvide clear messages - Make messages human-readable and informative
Include relevant metrics - Add metrics that help understand what happened
Match exit codes - Include exit_code in metrics and use it with exit()
Document artifacts - If your app produces files/URLs, list them in artifacts
Be consistent - Use the same metric names across similar applications
Validating Application JSON¶
Use the multiflexi-cli tool to validate your application JSON:
multiflexi-cli application validate-json --file multiflexi/your-app.multiflexi.app.json
Successful validation will output:
JSON is valid
Common Environment Variables¶
AbraFlexi Integration¶
For applications that integrate with AbraFlexi:
ABRAFLEXI_URL - AbraFlexi server URL
ABRAFLEXI_LOGIN - Username
ABRAFLEXI_PASSWORD - Password (type: password)
ABRAFLEXI_COMPANY - Company code
Logging and Output¶
EASE_LOGGER - Logger type (e.g., “console|syslog”)
RESULT_FILE - Output file path for results
APP_DEBUG - Debug mode flag (type: bool)
Localization¶
LANG - Application locale (e.g., “cs_CZ”, “en_US”)
Complete Example: ISP Tools¶
Here’s a complete example of a MultiFlexi application:
Directory Structure¶
isp-tools/
├── bin/
│ ├── blocknet
│ └── unblocknet
├── src/
│ ├── BlockNet.php
│ └── UnblockNet.php
├── multiflexi/
│ ├── blocknet.multiflexi.app.json
│ └── unblocknet.multiflexi.app.json
├── composer.json
├── .env.example
└── README.md
Application JSON (blocknet.multiflexi.app.json)¶
{
"$schema": "https://raw.githubusercontent.com/VitexSoftware/php-vitexsoftware-multiflexi-core/refs/heads/main/multiflexi.app.schema.json",
"schemaVersion": "3.2.1",
"uuid": "8f3c4a5e-9b2d-4e1f-a6d8-7c9e0f1a2b3c",
"version": "1.0.0",
"name": {
"en": "Block Internet Access",
"cs": "Zablokovat přístup k internetu"
},
"description": {
"en": "Block internet access for all clients with ODPOJEN label",
"cs": "Zablokuje internet všem klientům kteří mají štítek ODPOJEN"
},
"tags": [
"AbraFlexi",
"ISP",
"Network"
],
"homepage": "https://github.com/Spoje-NET/isp-tools",
"executable": "blocknet",
"environment": {
"ABRAFLEXI_COMPANY": {
"type": "string",
"description": {
"en": "AbraFlexi Company code",
"cs": "Kód společnosti v AbraFlexi"
},
"defval": "",
"required": true,
"category": "API"
},
"ABRAFLEXI_LOGIN": {
"type": "string",
"description": {
"en": "AbraFlexi Login",
"cs": "Přihlašovací jméno do AbraFlexi"
},
"defval": "",
"required": true,
"category": "API"
},
"ABRAFLEXI_PASSWORD": {
"type": "password",
"description": {
"en": "AbraFlexi password",
"cs": "Heslo do AbraFlexi"
},
"defval": "",
"required": true,
"category": "API"
},
"ABRAFLEXI_URL": {
"type": "string",
"description": {
"en": "AbraFlexi Server URI",
"cs": "Adresa serveru AbraFlexi"
},
"defval": "https://demo.flexibee.eu:5434",
"required": true,
"category": "API"
},
"RESULT_FILE": {
"type": "string",
"description": {
"en": "Write output json data to",
"cs": "Zapsat výstupní json data do"
},
"defval": "blocknet_result.json",
"required": false,
"category": "Other"
},
"EASE_LOGGER": {
"type": "string",
"description": {
"en": "Write log messages using",
"cs": "Způsob zápisu logovacích zpráv"
},
"defval": "console|syslog",
"required": false,
"category": "Behavior"
}
},
"artifacts": [
{
"name": {"en": "Block Report", "cs": "Zpráva o blokování"},
"type": "file",
"path": "blocknet_.*\\.json$",
"description": {
"en": "JSON report of blocked clients",
"cs": "JSON zpráva o zablokovaných klientech"
}
}
]
}
Executable Script (bin/blocknet)¶
#!/bin/bash
php -f /usr/share/isp-tools/BlockNet.php -- $@
Best Practices¶
Use Unique UUIDs - Generate unique UUIDs for each application using
uuidgenProvide Localization - Include at least English (“en”) and Czech (“cs”) translations
Use Semantic Versioning - Follow semver for the version field
Validate Before Commit - Always validate JSON files before committing
Secure Passwords - Mark password fields with
"type": "password"Document Environment Variables - Provide clear descriptions for all variables
Use Standard Categories - Stick to standard categories (API, Behavior, Security, Other)
Generate MultiFlexi Reports - Output JSON reports compatible with MultiFlexi
Support Command Line Options - Accept
-efor environment file and-ofor outputHandle Exit Codes - Return appropriate exit codes (0 for success)
Testing Your Application¶
Validate the JSON definition:
multiflexi-cli application validate-json --file multiflexi/your-app.multiflexi.app.jsonInstall dependencies:
composer installCreate a test environment file:
cp .env.example .env # Edit .env with test credentials
Run the application:
bin/your-command
Deployment¶
For production deployment:
Package your application (Debian package, Docker image, etc.)
Install to standard locations (
/usr/share/your-app/for code)Place executables in
/usr/bin/or/usr/local/bin/Register with MultiFlexi using the JSON definition
Configure environment variables through MultiFlexi UI
For AI Assistants¶
When creating MultiFlexi applications:
Always validate JSON - Use
multiflexi-cli application validate-json --fileFollow the structure - Use the standard directory layout
Check existing applications - Look at examples in ~/Projects for patterns
Generate unique UUIDs - Never reuse UUIDs from other applications
Include both languages - Provide “en” and “cs” translations for all user-facing text
Mark sensitive data - Use
"type": "password"for credentialsGenerate compliant reports - All applications must produce reports following the schema at https://raw.githubusercontent.com/VitexSoftware/php-vitexsoftware-multiflexi-core/refs/heads/main/schema/report.json
Include required report fields - Always include producer, status, and timestamp in reports
Validate before finishing - Always confirm JSON validity as the final step
Update documentation - Include README.md with usage instructions
Report Generation Checklist for AI¶
When generating reports in MultiFlexi applications:
Include
'producer' => 'ApplicationName'with the application nameSet
'status'to “success”, “error”, or “warning” based on execution resultUse
'timestamp' => date('c')for ISO8601 formatAdd a human-readable
'message'describing what happenedInclude
'metrics'object with relevant counters and the exit_codeOptionally add
'artifacts'for produced files/URLsWrite report using
json_encode($report, \JSON_PRETTY_PRINT)Exit with appropriate exit code: 0 for success, non-zero for errors
Troubleshooting¶
JSON Validation Fails¶
Check that all required fields are present
Verify JSON syntax (commas, brackets, quotes)
Ensure schemaVersion is “3.2.1”
Confirm UUID is unique and properly formatted
Application Doesn’t Execute¶
Verify executable permissions (
chmod +x)Check shebang line in script (
#!/bin/bash)Ensure PHP file path is correct
Verify all dependencies are installed
Environment Variables Not Loaded¶
Check
.envfile exists and is readableVerify variable names match JSON definition
Ensure
Shared::init()includes all required variablesCheck for typos in variable names
Resources¶
Application Schema: https://raw.githubusercontent.com/VitexSoftware/php-vitexsoftware-multiflexi-core/refs/heads/main/multiflexi.app.schema.json
Report Schema: https://raw.githubusercontent.com/VitexSoftware/php-vitexsoftware-multiflexi-core/refs/heads/main/schema/report.json
Example applications: ~/Projects/VitexSoftware/, ~/Projects/SpojeNet/
MultiFlexi CLI: Required version 2.2.0 or newer