# AGENTS.md — Fleetbase ## Architecture - **Dual-stack monorepo:** Laravel 10 (PHP) backend + Ember.js 5.4 frontend + 12 Git submodules - **Docker services:** `application` (FrankenPHP/Caddy :8000), `httpd` (:80→8000), `console` (Nginx :4200), `socket` (SocketCluster :38000), `database` (MySQL 8.0 :3306), `cache` (Redis), `queue`, `scheduler` - **Console port 4200**, **API port 8000** — both must be free or mapped differently - **Packages:** Each `packages//` is a Git submodule; contains PHP (`composer.json` + `server/`) and/or Ember code (`addon/`, `app/`, `extension.json`) - **Core packages:** `core-api`, `ember-core`, `ember-ui`, `dev-engine` — framework layers all extensions depend on ## Prerequisites & Constraints - **PHP >= 8.0, <= 8.2.30** (strict upper bound — 8.3+ will break) - **Node.js >= 22** - **pnpm** is the JS package manager (not npm/yarn) — `pnpm@11.0.9` - **Composer** uses private registry at `https://registry.fleetbase.io` — authentication may be required for private packages - Git submodules must be initialized: `git submodule update --init --recursive` ## Commands ### Docker (most common) ```bash docker compose up -d # Start all services docker compose exec application bash # Shell into API container docker compose exec application php artisan … # Run artisan commands docker compose exec application bash -c "./deploy.sh" # Run deployment script ``` ### Backend (api/) ```bash cd api && composer install # Install PHP deps (uses fleetbase registry) cd api && php artisan … # Laravel artisan (run inside container or locally with DB access) cd api && php artisan test # Run PHPUnit tests cd api && ./vendor/bin/php-cs-fixer fix # Fix PHP style cd api && vendor/bin/phpstan analyse # Static analysis (in packages with phpstan.neon.dist) ``` ### Frontend (console/) ```bash cd console && pnpm install # Install JS deps cd console && pnpm start # Ember dev server (requires API + socket running) cd console && pnpm lint # ESLint + stylelint + template-lint cd console && pnpm test # Lint + ember test (QUnit via Testem) cd console && pnpm build # Production build → dist/ ``` ### Single test runs ```bash cd api && php artisan test --filter=MyTest # PHP: single test class cd api && php artisan test --filter=MyTest::testFoo # PHP: single test method cd console && pnpm test --filter='My test name' # Ember: filter by test name cd console && pnpm test --server # Ember: watch mode ``` ## Extensions (Custom Packages) Each extension is a Git submodule under `packages//` with this structure: ``` extension.json # Metadata (name, version, engine, api) composer.json # PHP dependencies (if has API) package.json # JS dependencies (if has Ember engine) server/ # PHP API code (PSR-4) addon/ # Ember engine files app/ # Ember app files ``` ### Scaffold a new extension ```bash flb scaffold # CLI wizard # Or manually: create packages// with extension.json, composer.json, package.json # Register it as submodule: git submodule add packages/ ``` ### Link local extensions for development ```bash node scripts/package-linker.mjs # Symlink all packages/ into api/ and console/ ``` ### Package registry flow ```bash flb register # One-time: create registry account flb verify -e -c # Verify email flb generate-token -e # Get auth token flb set-auth # Save token for installs flb install fleetbase/ # Install extension from registry ``` ## Production Deployment (VPS: 37.27.183.102) ``` SSH key: Config/fleet_key (chmod 600, OpenSSH RSA private key) SSH command: ssh -i Config/fleet_key root@37.27.183.102 ``` ### Key env vars for production (docker-compose.override.yml) - `ENVIRONMENT=production`, `APP_DEBUG=false` - `APP_KEY` — generate with `docker compose exec application bash -c "php artisan key:generate --show"` - `APP_URL`, `CONSOLE_HOST` — set to actual domain/IP - `SESSION_DOMAIN` — domain for session cookies - `SOCKETCLUSTER_OPTIONS` — restrict origins to production domains - `MAIL_*` — configure real mailer (not log driver) - `FILESYSTEM_DRIVER=s3` — S3 for file storage (not local disk) - `GOOGLE_MAPS_API_KEY`, `IPINFO_API_KEY`, `TWILIO_*` — for full feature set - `REGISTRY_HOST`, `REGISTRY_PREINSTALLED_EXTENSIONS` — extension registry config - `OSRM_HOST` — routing engine URL ### Production checklist 1. Copy repo to server, run `docker compose up -d` (with correct override) 2. Ensure ports 80/443/8000/4200/38000 are open in firewall 3. Set up SSL/reverse proxy (Caddyfile for API, Nginx for console) 4. Use external/managed MySQL in production (not bundled container) 5. S3 for file storage (not local disk) 6. Restrict `SOCKETCLUSTER_OPTIONS` origins ## Environment File Locations | Env | Notes | |-----|-------| | `docker-compose.override.yml` | **Primary** — env vars injected into all Docker services | | `api/.env` | Only needed for local PHP runs outside Docker | | `api/.env.example` | Template reference | | `console/environments/.env.development` | Ember dev env | | `console/environments/.env.production` | Ember prod env | ## Git Submodule Gotchas - Always `git submodule update --init --recursive` after clone - Submodules track specific commits — working on a package means committing inside `packages//` first, then updating the parent repo's submodule pointer - After `git pull` in parent, run `git submodule update --recursive` to sync submodules - Package linker script (`scripts/package-linker.mjs`) symlinks submodules into api/console/ for local dev — run it after changing module structure ## Linting (all layers) | Layer | Tool | Command | |-------|------|---------| | PHP | php-cs-fixer | `./vendor/bin/php-cs-fixer fix` (in api/ or package) | | PHP | PHPStan | `vendor/bin/phpstan analyse` (in packages with neon config) | | JS | ESLint + Prettier | `pnpm lint` (in console/) | | CSS | Stylelint | `pnpm lint:css` | | Templates | ember-template-lint | `pnpm lint:hbs` | | i18n | fleetbase-intl-lint | `pnpm lint:intl` | ## Conventions - Ember Octane edition — use Glimmer components (`@glimmer/component`), `