# Project Context ## Purpose A Laravel-based hosting backend API that manages user portfolios and static site deployments. The system allows users to: - Register and authenticate via OAuth 2.0 (Passport) - Create and manage multiple portfolios with custom domains - Upload static site files (HTML/CSS/JS) - Deploy sites to Kubernetes infrastructure - Retrieve portfolio information via public endpoints ## Tech Stack - **Language**: PHP 8.2 - **Framework**: Laravel 12 - **Authentication**: Laravel Passport (OAuth 2.0 tokens) - **Database**: MySQL (production), SQLite (development) - **Cache/Session**: Database-backed - **Queue System**: Database-backed - **Container**: Docker with Alpine Linux - **Orchestration**: Kubernetes (k3s) - **CI/CD**: Gitea Actions (tag-driven deployment) - **Package Manager**: Composer - **Testing**: PHPUnit 11.5.3 - **Code Formatting**: Laravel Pint ## Project Conventions ### Code Style - **PSR-4 Autoloading**: All classes use appropriate namespaces (App\Http\Controllers, App\Models, App\Jobs, etc.) - **Naming Conventions**: - Controllers: Plural resource names (PortfolioController, AuthController) - Models: Singular (User, Portfolio) - Methods: camelCase (getPortfolioName, getStoragePath) - Database Tables: Plural (portfolios, users) - **Response Format**: All API responses use ApiResponse helper with consistent structure: ```json { "success": true/false, "message": "Human-readable message", "data": {...} } ``` - **Code Organization**: Separation of concerns with Models, Controllers, Services, Jobs, Policies, and Helpers - **Documentation**: PHPDoc comments on public methods ### Architecture Patterns - **MVC Pattern**: Models (Eloquent ORM), Controllers (HTTP handlers), Views (API responses) - **Authorization**: Laravel Policies (PortfolioPolicy) for centralized authorization logic - **Service Layer**: Business logic extracted into Services (PortfolioUploadService) - **Job Queue**: Background jobs for long-running operations (DeployStaticSiteJob) - **Dependency Injection**: Constructor injection used throughout (services, repositories) - **RESTful API**: Follows REST conventions for resource endpoints (/portfolios, /portfolios/{id}) ### Testing Strategy - **Framework**: PHPUnit with Laravel's test helpers - **Test Organization**: - Feature tests: Integration tests for HTTP endpoints (/tests/Feature/) - Unit tests: Isolated unit tests (/tests/Unit/) - **Test Database**: In-memory SQLite for fast test execution - **Test Running**: `composer test` clears config cache and runs PHPUnit - **Coverage**: Code coverage reports include /app directory - **Test Optimization**: BCRYPT_ROUNDS set to 4 for faster password hashing in tests ### Git Workflow - **Main Branch**: Primary development branch is 'main' - **Deployment Strategy**: Tag-based deployments - Tags matching `PRE_ALPHA*` trigger alpha deployment to `hosting-alpha` namespace - Tags matching `PROD*` trigger production deployment to `hosting` namespace - **Commit Convention**: Follow conventional commits for clarity - **CI/CD**: Gitea Actions workflows automatically build, push to registry, and deploy on tags ## Domain Context ### Portfolio Management - Each user can have multiple portfolios (hasMany relationship) - Portfolios have domain, path, active status, and deployment tracking - Active status controls whether uploads are allowed (verified through PortfolioPolicy) ### Deployment Process 1. User uploads ZIP file containing site files 2. Files stored at `portfolios/{name}/{id}/index.html` 3. Deploy job dispatched to queue 4. Artisan command runs Ansible playbook for infrastructure deployment 5. Site becomes accessible at configured domain ### Authentication - OAuth 2.0 token-based (Laravel Passport) - Users create personal access tokens for API requests - Token stored in Authorization header: `Bearer {token}` ## Important Constraints - **File Upload Limit**: 10MB max file size per upload - **Activation Required**: Portfolio must be marked as active (paid) to allow uploads - **Active Field**: Represents subscription/payment status (controls upload/deploy access) - **Authorization**: Only portfolio owner can view/update/delete/deploy - **Rate Limiting**: Handled by deployment job (prevents simultaneous deploys) - **Database-Backed Queue**: Tasks persist in database (no external queue service) ## External Dependencies - **Kubernetes (k3s)**: Container orchestration platform - **Docker Registry**: For storing built container images - **Ansible**: Infrastructure provisioning and deployment orchestration - **Nginx**: Web server configuration for deployed sites - **Supervisor**: Process manager for application workers - **Git**: Version control (Gitea) ## Recent Code Cleaning & Refactoring (Q1 2025) ### Applied DRY Principles 1. **AuthController**: Refactored to use ApiResponse helper consistently (eliminates duplicate response formatting) 2. **Portfolio Attributes**: Created model methods (getPortfolioName, getPortfolioDomain, getStoragePath) to reduce controller code duplication 3. **API Responses**: Standardized all responses through ApiResponse helper ### Applied KISS Principles 1. **Removed Unused Code**: Deleted empty StaticSiteController and unused routes 2. **Removed Debug Routes**: Cleaned up test routes (/ping, /pute) 3. **Authorization Refactor**: Replaced manual authorization checks with Laravel Policies for cleaner, maintainable authorization 4. **Service Layer**: Extracted file upload logic into PortfolioUploadService for better separation of concerns ### Code Quality Improvements - Authorization logic centralized in PortfolioPolicy - File upload responsibility separated into dedicated service - Consistent API response formatting across all endpoints - Removed unnecessary getAttribute() calls (using direct property access) - Eliminated manual validation duplication