v2.1.0 – Strange New Worlds
Qbix Server v2.1.0 — Strange New Worlds
v2.0 was a mesh-networked runtime. v2.1 makes it production-ready: every major PHP framework runs unmodified, the control panel manages apps end-to-end, mobile apps can be built and distributed for iOS and Android from the panel, and nine security audit passes harden the entire stack.
The mesh layer is still there — every v2.0 feature works unchanged. v2.1 adds the framework compat layer, a rebuilt control panel, mobile build scaffolding, and a significant number of security fixes.
Framework Compatibility
The compat source transform now handles output buffer protection, SAPI detection, and 27 shimmed PHP functions. Frameworks like Laravel, Symfony, WordPress, Drupal, CakePHP, Yii, and Mezzio run out of the box — no code changes, no plugins, no extensions.
# Drop a Laravel app in and go
php qbixserver.php --root=my-laravel-app/public --port=8080Source Transform
The rewriter intercepts calls that would break under Qbix's execution model:
ob_end_flush(),ob_end_clean(),ob_get_clean(),ob_get_level()are shimmed so frameworks that drain output buffers in a loop don't infinite-loop against Qbix's protected buffer.php_sapi_name()returns'cli-server'instead of'cli'. ThePHP_SAPIconstant is replaced via a context-aware constant engine that skips qualified references likeSomeClass::PHP_SAPI.- All shimmed calls are emitted fully qualified (
\Q_WebServer_Compat::_header(...)) so they resolve correctly inside namespaced framework code. The v2.0 rewriter omitted the leading backslash, which broke every Symfony, Laravel, and Drupal response.
13 Framework Presets
Built-in presets for Laravel, Symfony, WordPress, Drupal, CakePHP, CodeIgniter, Yii, Mezzio, Slim, Joomla, Magento, Nextcloud, and ownCloud. Each preset sets the front controller, upload limits, memory limits, and session settings appropriate for the framework.
12 Boot Adapters
Boot adapters automatically detect and bootstrap each framework. A Custom adapter allows user-specified boot callables.
Performance
Benchmarked against PHP's built-in development server:
| Framework | php -S | Qbix Server | Speedup |
|---|---|---|---|
| Laravel | 190 req/s | 653 req/s | 3.4× |
| Drupal | 404 req/s | 1,636 req/s | 4.0× |
| CakePHP | 905 req/s | 1,790 req/s | 2.0× |
| Mezzio | 1,580 req/s | 2,337 req/s | 1.5× |
See BENCHMARKS.md for full methodology.
Control Panel
App Management
Create, delete, start, stop, and configure apps from the panel. Domain assignment, SSL cert provisioning, and framework detection are integrated into the app creation flow. The panel also manages WordPress and Drupal plugin/module installation through their respective CLIs.
Cache Clearing
Append ?Q.clearCache to any URL to clear all caches — opcode, static file, precompression, and image — for that app. During development this replaces the cycle of clearing APC, restarting workers, and purging the image cache separately.
Script Modules
The panel's JavaScript is organized into modules with a loader, replacing the inline scripts that grew to several thousand lines in v2.0. The module system loads only the code needed for the active tab.
Mobile Build and Distribution
The control panel can scaffold, build, and package native iOS and Android apps.
Scaffolding
Click Prepare with a platform selected and the panel generates a complete native project:
- iOS: Swift source files +
project.ymlfor xcodegen.PhpBridge.swiftstarts PHP viaposix_spawn,TransportManager.swifthandles BLE/MC/LAN,BackgroundKeepAlive.swiftmaintains the silent audio session. - Android: Kotlin source files + Gradle (Kotlin DSL).
PhpBridge.ktextracts the binary from APK assets and runs it viaProcessBuilder,TransportManager.kthandles BLE/LAN,QbixServerService.ktruns the Foreground Service.
Both include the GATT service UUIDs, chunking protocol, and mesh handshake integration.
Building
Click Build and the panel runs xcodebuild or ./gradlew assembleRelease. CI produces qbixserver-ios-arm64 and qbixserver-android-arm64 micro binaries via static-php-cli, with Android NDK cross-compilation.
Distribution
iOS apps are archived and uploaded to App Store Connect via the Xcode Organizer or xcodebuild -exportArchive. TestFlight handles beta distribution (25 internal testers without review, 10,000 external testers with review). Ad Hoc provisioning supports direct distribution to up to 100 registered devices.
Android apps are signed with a release keystore and uploaded to the Google Play Console as an AAB. The Play Console offers internal (100 testers, no review), closed (invite-only), and open testing tracks before production. Signed APKs can also be distributed directly for sideloading or alternative stores.
See mobile/iOS.md and mobile/Android.md for full walkthroughs.
Security Hardening
Nine audit passes reviewed Panel.php (~7,000 lines), TransportManager.swift (~860 lines), and TransportManager.kt (~680 lines). Each pass found progressively fewer issues — 7, then 3, then 1 — confirming convergence.
XSS Prevention
All innerHTML assignments in the Nearby tab now escape API-returned data through escHtml(). Previously, a peer could set its mesh name to <img onerror=...> and have it rendered unsanitized in the control panel. Fixed in: mesh identity display, routing table rows, peer connection status, script selector options, attestation labels, and attestation signer fields.
Path Traversal
basename() is applied to directory names from user input in apiQbixNpm, apiFrameworkPkgDownload, and framework package endpoints. Without this, a target value of ../../etc could traverse outside the expected directory.
Shell Injection
escapeshellarg() is applied to all user-supplied paths passed to shell commands. This covers the WordPress CLI path (wp) and Drupal CLI path (drush) in six locations across apiFrameworkPackages, apiFrameworkPkgAction, and apiFrameworkRun. A crafted CLI path like /usr/bin/wp; rm -rf / would previously execute the injected command.
Authentication
apiChangePassword and apiLogout now check the Authorization: Bearer header in addition to X-Panel-Token and cookies, matching the existing checkAuth logic. API clients authenticating via Bearer header could previously not change their password or log out — the token lookup returned empty and the operation silently failed or invalidated the wrong session.
BLE SSRF
Both the iOS and Android TransportManagers now reject BLE-received HTTP request paths that don't start with /. Without this check, a crafted BLE request could use the path as a userinfo@host trick — the HTTP client would interpret user:pass@evil.com/path as a request to evil.com — turning the local server into an open proxy reachable over Bluetooth.
// iOS fix
guard parsed.path.hasPrefix("/") else {
sendBLEResponse("HTTP/1.1 400 Bad Request\r\n..."
.data(using: .utf8)!, to: central)
return
}// Android fix
if (!path.startsWith("/")) return@submitMultipeerConnectivity Peer Identity
The iOS TransportManager now uses the peer's actual mesh_id from the ECDH handshake when relaying MultipeerConnectivity messages to PHP, instead of the MC displayName. The MC display name is an arbitrary string set by the remote device; the mesh_id is the cryptographic identity established during the handshake. Using the display name meant the PHP server couldn't match MC messages to the correct peer, breaking message routing for any peer whose display name didn't happen to match its mesh ID.
Documentation
| Doc | What's new |
|---|---|
| FRAMEWORKS.md | All 13 frameworks with presets, adapters, benchmarks |
| BENCHMARKS.md | Framework benchmark section |
| mobile/README.md | Transport layer, GATT protocol, platform requirements |
| mobile/iOS.md | Signing, TestFlight, App Store, Ad Hoc distribution |
| mobile/Android.md | Keystore, Play Store, testing tracks, direct APK |
| README.md | Expanded Mobile section with build/distribute overview |
Upgrading from v2.0
No breaking changes. All v2.0 configuration, APIs, and mesh behavior are preserved. The framework compat layer activates only when serving a framework that needs it. The security fixes apply automatically.