This document provides guidance for AI agents working with the Cockpit codebase.
Cockpit is a headless CMS and content platform built on the Lime Framework. It provides a REST/GraphQL API for content management with support for MongoDB and SQLite backends.
- PHP 8.3+ backend with Vue 3 frontend
- Event-driven architecture using
$app->on()/$app->trigger() - Modular design with core modules in
/modulesand extensions in/addons - Multitenancy support via spaces (
:spaceURL prefix) - Unified storage abstraction supporting MongoDB and SQLite
/modules/ # Core system modules (App, Content, Assets, System, Finder)
/addons/ # Optional extensions
/lib/ # Core libraries (Lime, MongoHybrid, etc.)
/config/ # Configuration files, i18n, API routes
/storage/ # Data, cache, uploads (runtime)
- App - Authentication, ACL, admin UI, API infrastructure
- Content - Collections, Singletons, Trees content models
- Assets - File/image management
- System - Settings, locales, API keys
- Finder - File browser
npm run build # Build bundled CSS and JS assets
npm run watch # Watch for changes and rebuild
npm run build-bundle # Build app bundle using Rollupcomposer serve # Start dev server at localhost:8080./tower # List available CLI commands
./tower app:cache:flush # Flush app cacheNavigate to /install in browser for initial setup. Ensure /storage directory is writable.
The project uses EditorConfig. Key settings:
- Indentation: 4 spaces (PHP, JS, CSS)
- Line endings: LF
- Charset: UTF-8
- Trailing whitespace: Trimmed
- Final newline: Required
- Use namespace matching directory structure (e.g.,
namespace App\Helper) - Classes extend framework base classes (
\Lime\Helper,\Lime\App) - Use typed properties and return types (PHP 8.3+ features)
- Follow PSR-4 autoloading conventions
// Example class structure
namespace App\Helper;
class ExampleHelper extends \Lime\Helper {
public string $property = 'value';
public function methodName(array $data): mixed {
// Implementation
}
}ModuleName/
├── bootstrap.php # Module init and service registration
├── admin.php # Admin UI routes
├── api.php # API endpoints
├── cli.php # CLI commands (optional)
├── Controller/ # MVC controllers
├── Helper/ # Business logic
├── assets/ # Frontend assets
├── views/ # View templates
└── icon.svg # Module icon
- Use ES6+ syntax
- Global
Appobject for framework utilities - Vue 3 components in
assets/vue-components/ - KISS CSS framework for styling
- Use dot notation:
app.init,content.save,graphql.config - Prefix with module name for module-specific events
The project uses informal test scripts in /tests/ rather than a formal testing framework. Tests are PHP scripts that can be run directly.
# Run individual test scripts
php tests/test.php
php tests/expression.php
php tests/indexlite_smoke.php- Start the development server:
composer serve - Navigate to
localhost:8080/installfor fresh installation - Test API endpoints at
/api/* - Test GraphQL at
/api/gql
Use these authentication headers:
Cockpit-Token- User/API tokenAuthorization: Bearer <token>- JWTAPI-KEY- API key
// Via CLI or bootstrap
$app = Cockpit::instance();
$app->dataStorage->save('collection_name', [
'field' => 'value'
]);- Password hashing: Uses
password_verify()with bcrypt - Session security: Implements session fixation prevention via
regenerateId() - ACL system: Role-based access control via
Aclhelper - CSRF protection: Built-in CSRF token validation
- Always validate and sanitize user input before database operations
- Use typed parameters in API endpoints
- Escape output in views using appropriate helpers
- Use parameterized queries through MongoHybrid abstraction
- Never construct queries from raw user input
- Recent security updates block
$outand$mergeaggregation stages - Field names are sanitized in
toJsonPathto prevent injections
- API rate limiting available via
ApiRateLimiterhelper - Token-based authentication for API access
- JWT support for stateless authentication
- 2FA support via
TWFAhelper
- Validate file types and extensions
- Use Flysystem abstraction for file operations
- Store uploads outside web root when possible
- Sanitize filenames before storage
- Store sensitive config in
/config/config.php(not version controlled) - Use
.envfiles for environment-specific secrets - Change default
sec-keyin production - Never commit API keys or tokens
// Always check permissions
if (!$this->app->helper('acl')->isAllowed('permission', $role)) {
return $this->stop(403);
}
// Validate CSRF tokens
if (!$this->app->helper('csrf')->isValid('token_name', $token)) {
return $this->stop(403);
}- Read and understand (addons|modules)/*/README.md for detailed module documentation
- Follow existing patterns in the codebase
- Test changes with the development server
- Clear caches after configuration changes:
./tower app:routes:cache:clear
Adding an API endpoint:
Create file in config/api/:
endpoint.php- All methodsendpoint.get.php- GET onlyendpoint/[id].php- With route parameter
Adding a module:
- Create directory in
/addons/ - Add
bootstrap.phpfor initialization - Add
api.phpfor API routes - Add
admin.phpfor admin UI
Extending functionality: Use the event system:
$app->on('event.name', function($data) {
// Handle event
});- Enable debug mode in config:
'debug' => true - Check
/storage/cache/for cached data - Review error logs in PHP error log location
- Use
$app->trigger('error', [...])for error handling