Files
growup-crm/GEMINI.md
2026-02-02 15:31:15 -03:00

34 KiB

Growup Pro - Krayin CRM Whitelabel Multi-tenant

Project Overview

Growup Pro is a whitelabel implementation of Krayin Laravel CRM with multi-tenancy support. The platform allows multiple companies/organizations to use the same CRM instance with complete data isolation through subdomain-based tenancy.

CURRENT STATUS: DEBUGGING PHASE

  • Multi-tenancy implementation: Installed but encountering issues.
  • Issue 1: localhost not recognized as central domain (TenantCouldNotBeIdentifiedOnDomainException).
  • Issue 2: Tenant instances (tenant1.localhost) load but missing CSS (Asset 404).
  • Goal: Fix central domain detection and static asset serving for tenants.

Key Differentiators from Krayin

  • Rebranding: Complete visual overhaul with Growup Pro branding
  • Multi-tenancy: Isolated environments per client organization
  • Localization: Full Portuguese (pt-BR) translation
  • White-label ready: Easy customization per tenant

Tech Stack

  • Framework: Laravel (check composer.json for exact version)
  • Base CRM: Krayin Laravel CRM
  • Database: MySQL/PostgreSQL
  • Multi-tenancy Package: Tenancy for Laravel (v3)
  • Frontend: Blade templates with Alpine.js (Krayin default)
  • PHP Version: 8.1+
  • Containerization: Docker with Docker Compose
  • Orchestration: Docker Swarm
  • Management: Portainer
  • CI/CD: Gitea Actions (GitHub Actions compatible)
  • Error Tracking: Sentry for Laravel
  • Code Quality: PHPStan (static analysis) + Laravel Pint (code formatter)
  • CDN: Cloudflare (caching and DDoS protection) - PRODUCTION ONLY

Project Structure

.
├── .gitea/
│   └── workflows/       # Gitea Actions CI/CD pipelines
│       ├── deploy.yml           # Production deployment
│       ├── deploy-staging.yml   # Staging environment deployment
│       └── tests.yml            # Automated testing pipeline
├── .husky/              # Git hooks (pre-commit, pre-push)
├── Makefile             # Common development commands
├── app/
│   ├── Models/          # Eloquent models (tenant-scoped)
│   ├── Http/
│   │   ├── Controllers/ # Application controllers
│   │   └── Middleware/  # Custom middleware (tenant identification)
│   └── Providers/       # Service providers
├── config/
│   └── tenancy.php      # Tenancy for Laravel configuration
├── database/
│   ├── migrations/      # Database migrations
│   │   ├── tenant/      # Tenant-specific migrations
│   │   └── landlord/    # Central database migrations
│   └── seeders/         # Seeders for tenants and central data
│       ├── DemoTenantSeeder.php    # Creates demo tenants for testing
│       └── ProductionSeeder.php    # Production data seeding
├── docker/
│   ├── Dockerfile       # Application container definition
│   ├── docker-compose.yml # Local development orchestration
│   └── docker-compose.prod.yml # Production stack definition
├── packages/            # Krayin core packages
│   └── Webkul/
│       └── ...
├── public/
│   └── assets/          # Growup Pro assets (logos, images)
├── resources/
│   ├── lang/
│   │   └── pt_BR/       # Portuguese translations
│   └── views/           # Blade templates (Growup Pro customized)
└── routes/
    ├── web.php          # Central app routes
    ├── tenant.php       # Tenant-specific routes
    ├── admin.php        # Admin dashboard routes (tenant management)
    └── api.php          # API routes

Multi-tenancy Configuration

Package: Tenancy for Laravel

We use Tenancy for Laravel v3 for robust multi-tenant architecture with automatic database switching and tenant identification.

Tenant Identification Strategy

  • Method: Subdomain-based identification
  • Domain: growuppro.com.br
  • Pattern: {tenant}.growuppro.com.br
  • Examples:
    • empresa1.growuppro.com.br → Tenant: empresa1
    • empresa2.growuppro.com.br → Tenant: empresa2
    • demo.growuppro.com.br → Tenant: demo

Data Isolation

  • Approach: Separate database per tenant (recommended by Tenancy for Laravel)
  • Database naming: tenant_{tenant_id} (e.g., tenant_empresa1)
  • Central database: growuppro_central (stores tenant metadata, domains, users)
  • Automatic tenant context switching via middleware
  • Models automatically scoped to current tenant

Tenant Features

Each tenant has isolated:

  • Data: Leads, contacts, deals, products, activities
  • Users: Separate user base with roles/permissions
  • Settings: Email configuration, notifications, workflows
  • Customization: Optional CSS overrides, email templates

Branding & Localization

Growup Pro Visual Identity

  • Application Name: Growup Pro (replacing all Krayin mentions)
  • Logo: Custom Growup Pro logo in all interfaces
  • Color Scheme: [Define primary/secondary colors when ready]
  • Typography: [Define font family when ready]
  • UI/UX: Modern, clean interface aligned with Growup Pro brand

Translation (pt-BR)

  • All user-facing text translated to Portuguese (Brazil)
  • Language files in resources/lang/pt_BR/
  • Default locale: pt_BR (set in config/app.php)
  • Maintain translation keys for easy updates
  • Include tenant-customizable text snippets

Customization Locations

  1. Logo: public/assets/images/logo.png (central) and tenant-specific storage
  2. Translations: resources/lang/pt_BR/
  3. Views: resources/views/ (customized Krayin templates)
  4. Styles: public/assets/css/custom.css (Growup Pro overrides)
  5. Config: config/growuppro.php (application-specific settings)

Docker & Deployment Architecture

Container Strategy

The application runs in Docker containers orchestrated by Docker Swarm and managed through Portainer.

Docker Compose Structure

  • Development: docker-compose.yml (local development with hot-reload)
  • Production: docker-compose.prod.yml (optimized for Swarm deployment)

Services

Typical stack includes:

  • app: PHP-FPM application container (Growup Pro)
  • nginx-proxy-manager: Nginx Proxy Manager for reverse proxy, SSL, and domain management (managed via Portainer)
  • database: MySQL/PostgreSQL (central + tenants)
  • redis: Session and cache storage
  • queue: Laravel queue worker for background jobs
  • scheduler: Laravel scheduler (cron jobs)

Image Management

  • Registry: GitHub Container Registry (GHCR)
  • Image naming: ghcr.io/cauefaleiros/growup-pro:latest
  • Tagging strategy: Git commit SHA and semantic versioning
  • Tags: latest (production), dev (development), v{version} (releases)

CI/CD Pipeline with Gitea Actions

About Gitea Actions

Gitea Actions (available since Gitea 1.19) is a built-in CI/CD solution similar and mostly compatible with GitHub Actions. It uses the same YAML workflow format and is compatible with most GitHub Actions marketplace plugins.

Key Components:

  • Gitea Server: Hosts repositories and triggers workflows
  • act_runner: Standalone runner program (written in Go) that executes jobs, based on a fork of nektos/act
  • Workflows: YAML files stored in .gitea/workflows/ directory (compatible with GitHub Actions syntax)

Compatibility:

  • Same YAML syntax as GitHub Actions
  • Can use most actions from GitHub marketplace (e.g., actions/checkout@v4, actions/setup-node@v4)
  • Workflows are portable between GitHub and Gitea with minimal changes

Deployment Flow

Developer pushes code to GitHub
         ↓
GitHub Actions workflow triggered
         ↓
1. Run tests (PHPUnit, Pest)
2. Build Docker image
3. Tag image with commit SHA
         ↓
Push image to GitHub Container Registry (GHCR)
         ↓
Call Portainer API (webhook or direct API)
         ↓
Portainer updates Docker Stack definition
         ↓
Docker Swarm pulls new image
         ↓
Swarm performs rolling update (zero-downtime)
         ↓
Health checks verify deployment
         ↓
Old containers removed

GitHub Actions Workflow

Location: .github/workflows/deploy.yml

Key steps:

  1. Checkout code
  2. Setup PHP & dependencies (Composer install)
  3. Run code quality checks (PHPStan, Pint)
  4. Run tests (PHPUnit/Pest - ensure code quality)
  5. Build Docker image with build args
  6. Login to GHCR using GitHub token
  7. Push image with appropriate tags
  8. Trigger Portainer via API to update stack
  9. Verify deployment (health check endpoint)
  10. Notify team (Slack/Discord webhook on success/failure)

Environment Variables

Managed through:

  • GitHub Secrets: Sensitive data (API keys, tokens, Sentry DSN)
  • Portainer: Stack environment variables
  • Docker Swarm Secrets: Database credentials, API keys

Portainer Integration

  • Portainer URL: https://148.230.76.122:9443
  • API Endpoint: https://148.230.76.122:9443/api
  • Authentication: API token (stored in GitHub Secrets)
  • Stack Management: Update existing stack with new image tag
  • Webhooks: Optional webhook for automated redeploy
  • Nginx Proxy Manager: Managed through Portainer for SSL certificates and domain routing

Coding Conventions

Models

All tenant-scoped models automatically inherit tenant context through Tenancy for Laravel:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Lead extends Model
{
    // Tenancy for Laravel handles scoping automatically
    // No manual trait needed for tenant models
    
    protected $fillable = ['title', 'value', 'status'];
}

Central Models

Models that exist in the central database (tenant metadata, etc.):

<?php

namespace App\Models;

use Stancl\Tenancy\Database\Models\Tenant as BaseTenant;

class Tenant extends BaseTenant
{
    // Custom tenant attributes
    protected $fillable = [
        'id', 'company_name', 'subdomain', 'logo_url', 'primary_color'
    ];
}

Controllers

  • Follow Krayin's controller structure
  • Tenant context is automatic (no manual checking needed)
  • Use dependency injection and repository pattern
  • Keep business logic in Service classes

Migrations

Tenancy for Laravel separates migrations:

// database/migrations/tenant/2024_xx_xx_create_leads_table.php
Schema::create('leads', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->decimal('value', 10, 2);
    // No tenant_id needed - separate databases per tenant
    $table->timestamps();
});

// database/migrations/2024_xx_xx_create_tenants_table.php (central)
Schema::create('tenants', function (Blueprint $table) {
    $table->string('id')->primary();
    $table->string('company_name');
    $table->string('subdomain')->unique();
    $table->timestamps();
});

Routes

// routes/tenant.php - Runs in tenant context
Route::middleware(['tenant'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
    Route::resource('leads', LeadController::class);
});

// routes/web.php - Central app (tenant selection, etc.)
Route::get('/', [HomeController::class, 'index']);
Route::post('/register-tenant', [TenantController::class, 'register']);

Important Files to Know

Configuration

  • config/app.php - Application configuration (locale: pt_BR)
  • config/tenancy.php - Tenancy for Laravel settings
  • config/growuppro.php - Custom Growup Pro configuration
  • app/Http/Kernel.php - Middleware registration

Krayin Core

  • packages/Webkul/ - Krayin core packages (never modify directly)
  • Extend functionality through Laravel's standard practices (service providers, custom packages)

Docker & Deployment

  • docker/Dockerfile - Application container definition
  • docker-compose.yml - Local development environment
  • docker-compose.prod.yml - Production stack for Swarm
  • .github/workflows/deploy.yml - CI/CD pipeline

Branding

  • public/assets/images/logo.png - Growup Pro logo
  • resources/lang/pt_BR/ - Portuguese translations
  • resources/views/layouts/app.blade.php - Main layout (branded)

CRITICAL: Krayin Authentication Issues (MUST RESOLVE BEFORE MULTI-TENANCY)

IMPORTANT: Multi-tenancy implementation is ON HOLD until we stabilize Krayin's base authentication system. We have experienced critical login issues that must be resolved first.

Known Authentication Problems

Problem 1: Error 419 - CSRF Token Mismatch

Symptoms:

  • User enters credentials
  • Form submission returns 419 error
  • Login fails even with correct credentials

Possible Causes:

  • Session driver misconfiguration (file vs redis vs database)
  • Session cookie not being set properly
  • Domain/subdomain mismatch in session configuration
  • APP_URL mismatch with actual access URL
  • CSRF token expiration (session timeout too short)
  • Reverse proxy stripping session cookies

Debug Steps:

# Check current session driver
grep SESSION_DRIVER .env

# Clear all caches
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

# Check session files (if using file driver)
ls -la storage/framework/sessions/

# Test session configuration
php artisan tinker
>>> session()->put('test', 'value');
>>> session()->get('test');  # Should return 'value'

Potential Fixes:

  1. Ensure APP_URL matches access URL exactly:

    # If accessing via localhost:8000
    APP_URL=http://localhost:8000
    
    # If accessing via IP
    APP_URL=http://192.168.1.100:8000
    
  2. Check session configuration (config/session.php):

    'domain' => env('SESSION_DOMAIN', null),  // Should match your domain
    'secure' => env('SESSION_SECURE_COOKIE', false),  // false for HTTP, true for HTTPS
    'same_site' => 'lax',  // Not 'strict' - can cause issues
    
  3. Verify CSRF middleware is present in app/Http/Kernel.php:

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,  // THIS IS CRITICAL
            // ...
        ],
    ];
    
  4. Check CSRF exceptions (if login route needs to be excluded):

    // app/Http/Middleware/VerifyCsrfToken.php
    protected $except = [
        // Add routes here ONLY as last resort
    ];
    

Problem 2: Tenant Database Connection Issues

Symptoms:

  • Login attempt fails silently
  • Database connection errors in logs
  • Can't authenticate against tenant-specific users table

Possible Causes:

  • Tenant database doesn't exist yet
  • Database migrations not run on tenant database
  • Wrong database being queried (central vs tenant)
  • Tenant context not initialized before authentication attempt

Debug Steps:

# List all databases
php artisan tinker
>>> DB::select('SHOW DATABASES');

# Check which database Laravel is connected to
>>> DB::connection()->getDatabaseName();

# Verify users table exists in tenant DB
>>> Schema::connection('tenant')->hasTable('users');

Critical Notes for Multi-tenancy:

  • Authentication MUST work in single-tenant (non-multi-tenant) mode FIRST
  • Only after stable authentication should we add tenant context switching
  • Tenant middleware should NOT interfere with session/CSRF handling

Problem 3: Infinite Login Redirect Loop (CRITICAL - UNRESOLVED)

Symptoms:

  • User enters valid credentials
  • Form submits successfully (no 419 error)
  • Page redirects back to login page
  • User is never authenticated
  • Dashboard never loads
  • No error messages displayed

This is the MOST CRITICAL issue and must be debugged thoroughly.

Possible Causes:

  1. Session not persisting after authentication:

    • Session written but immediately destroyed
    • Session driver issue (file permissions, Redis connection)
    • Session ID regeneration failing
  2. Authentication middleware misconfigured:

    • Auth middleware blocking authenticated users
    • Wrong guard being checked
    • Middleware order issues in Kernel.php
  3. Redirect logic broken:

    • redirectTo property in LoginController pointing to login route
    • Intended destination not being preserved
    • Route name/path mismatch
  4. Auth guard misconfigured:

    • Wrong guard specified in config/auth.php
    • Provider not finding users correctly
    • User model relationship issues
  5. Cookie domain/path mismatch:

    • Session cookie being set but not read back
    • Domain attribute too restrictive
    • Path attribute incorrect

Detailed Debug Steps:

# 1. Enable query logging to see what's happening
# Add to AppServiceProvider boot():
DB::listen(function ($query) {
    Log::info('Query: ' . $query->sql . ' - Bindings: ' . json_encode($query->bindings));
});

# 2. Add extensive logging to login process
# In LoginController or wherever authentication happens:
Log::info('Login attempt for: ' . request()->email);
Log::info('Session ID before auth: ' . session()->getId());

# After Auth::attempt():
Log::info('Auth attempt result: ' . (Auth::check() ? 'success' : 'failed'));
Log::info('Session ID after auth: ' . session()->getId());
Log::info('Authenticated user: ' . (Auth::user() ? Auth::user()->id : 'none'));

# 3. Check session files directly
# If using file driver:
tail -f storage/logs/laravel.log &
# Make login attempt
# Check if session file is created and contains auth data:
cat storage/framework/sessions/*

# 4. Test authentication in Tinker
php artisan tinker
>>> $user = User::first();
>>> Auth::login($user);
>>> Auth::check();  # Should return true
>>> session()->all();  # Check session data
>>> session()->save();  # Manually save session

Configuration Files to Check:

  1. config/auth.php

    'defaults' => [
        'guard' => 'web',  // Verify this matches your usage
        'passwords' => 'users',
    ],
    
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
    ],
    
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,  // Verify model path
        ],
    ],
    
  2. config/session.php

    'driver' => env('SESSION_DRIVER', 'file'),
    'lifetime' => env('SESSION_LIFETIME', 120),
    'expire_on_close' => false,
    'encrypt' => false,
    'files' => storage_path('framework/sessions'),
    'connection' => env('SESSION_CONNECTION', null),
    'table' => 'sessions',
    'store' => env('SESSION_STORE', null),
    'lottery' => [2, 100],
    'cookie' => env('SESSION_COOKIE', Str::slug(env('APP_NAME', 'laravel'), '_').'_session'),
    'path' => '/',
    'domain' => env('SESSION_DOMAIN', null),  // Should be NULL for localhost
    'secure' => env('SESSION_SECURE_COOKIE', false),  // FALSE for HTTP
    'http_only' => true,
    'same_site' => 'lax',  // NOT 'strict'
    
  3. Verify LoginController redirect logic:

    // Typical Laravel LoginController
    protected $redirectTo = '/dashboard';  // NOT '/login'!
    
    // Or method:
    protected function redirectTo() {
        return '/dashboard';  // Verify this route exists and is accessible
    }
    
    // Check authenticated() method isn't causing issues:
    protected function authenticated(Request $request, $user) {
        // Should NOT return redirect to login
        Log::info('User authenticated: ' . $user->id);
    }
    
  4. Check middleware in routes:

    // routes/web.php
    Route::middleware(['auth'])->group(function () {
        Route::get('/dashboard', [DashboardController::class, 'index']);
    });
    
    // Verify 'auth' middleware is defined in Kernel.php
    // and uses the correct guard
    

Testing Methodology:

  1. Isolate the problem:

    # Create a minimal test route
    Route::get('/test-auth', function () {
        Auth::login(User::first());
        return [
            'authenticated' => Auth::check(),
            'user_id' => Auth::id(),
            'session_id' => session()->getId(),
            'session_data' => session()->all(),
        ];
    });
    
  2. Test session persistence separately:

    Route::get('/test-session-write', function () {
        session(['test_key' => 'test_value_' . time()]);
        return 'Session written: ' . session('test_key');
    });
    
    Route::get('/test-session-read', function () {
        return 'Session read: ' . session('test_key', 'NOT FOUND');
    });
    
  3. Test authentication without redirect:

    Route::post('/test-login', function (Request $request) {
        $credentials = $request->only('email', 'password');
    
        if (Auth::attempt($credentials)) {
            return [
                'status' => 'success',
                'user' => Auth::user()->only(['id', 'email']),
                'session_id' => session()->getId(),
            ];
        }
    
        return ['status' => 'failed'];
    });
    

Critical Checklist Before Multi-tenancy:

  • Session driver works correctly (can write and read session data)
  • CSRF protection works (no 419 errors)
  • Auth::attempt() returns true for valid credentials
  • Auth::check() returns true immediately after Auth::attempt()
  • Session persists across requests (test with simple session()->put/get)
  • User can access protected routes after authentication
  • No infinite redirect loops
  • Login process completes in browser devtools Network tab (check for redirect chains)
  • Session cookie is set and sent back with subsequent requests (check devtools Application/Storage)

DO NOT proceed with multi-tenancy until ALL checklist items pass.

Debugging Tools

# Enable debug mode
APP_DEBUG=true

# Tail logs in real-time
tail -f storage/logs/laravel.log

# Check Redis connection (if using Redis sessions)
redis-cli ping

# Check MySQL connection
php artisan tinker
>>> DB::connection()->getPdo();

# Dump session driver configuration
php artisan tinker
>>> config('session.driver');
>>> config('session.files');
>>> config('session.connection');

# Test file permissions
ls -la storage/framework/sessions/
# Should be writable by web server user

Next Steps After Resolving Authentication

  1. Document the exact fix that resolved the issue
  2. Create test cases to prevent regression
  3. Only then begin multi-tenancy implementation
  4. Add monitoring/logging to detect authentication issues early

Development Workflow

Development Environments

The project uses multiple environments for safe deployment:

  1. Local Development (localhost)

    • Docker Compose for local stack
    • Hot reload enabled
    • Debug mode on
  2. Staging Environment (staging.growuppro.com.br)

    • Production-like environment
    • Deployed from staging branch
    • Used for testing before production
    • Same infrastructure as production
  3. Production Environment (growuppro.com.br)

    • Live environment
    • Deployed from main branch
    • Zero-downtime deployments

Local Development

  1. Clone repository
  2. Copy .env.example to .env and configure
  3. Run docker-compose up -d
  4. Access: http://localhost or configured local domain
  5. Create test tenants: php artisan tenants:create

Making Changes

  1. Never modify Krayin core - extend via Laravel patterns
  2. Test with multiple tenants - always verify isolation
  3. Follow PSR-12 coding standards (enforced by Pint)
  4. Run quality checks before committing:
    make lint        # Run PHPStan + Pint
    make test        # Run test suite
    
  5. Write tests for new features (PHPUnit/Pest)
  6. Update translations when adding UI text
  7. Document breaking changes in pull requests
  8. Use pre-commit hooks to catch issues early

Testing Strategy

  • Unit Tests: Core business logic, services
  • Feature Tests: Tenant isolation, API endpoints
  • Browser Tests: Multi-tenant user flows (Dusk)
  • Database Tests: Migration rollback/forward
  • Test with at least 2-3 active tenants
  • CI/CD Integration: All tests run automatically on push
  • Coverage Goal: Minimum 70% code coverage

Deployment Process

  1. Create feature branch from main
  2. Develop and test locally
  3. Push to staging branch for staging deployment
  4. Test on staging environment (staging.growuppro.com.br)
  5. Create Pull Request to main (after PR approval)
  6. Merge to main - GitHub Actions runs automatically
  7. Monitor deployment in Portainer
  8. Verify health checks pass
  9. Test critical flows on production
  10. Sentry monitors for runtime errors

Common Tasks

Quick Development Commands (Makefile)

make dev              # Start local development environment
make prod             # Start production-like local environment
make test             # Run test suite
make lint             # Run PHPStan + Pint checks
make fix              # Auto-fix code style issues
make deploy-staging   # Deploy to staging
make deploy-prod      # Deploy to production
make logs             # Show application logs
make shell            # Enter application container shell
make db-fresh         # Fresh database with seeders
make tenant-create    # Create a new demo tenant

Creating a tenant-scoped feature

  1. Create migration in database/migrations/tenant/
  2. Run migrations: php artisan tenants:migrate
  3. Create model (no special traits needed)
  4. Add routes in routes/tenant.php
  5. Build controller with tenant-aware logic

Adding a new translation

  1. Edit resources/lang/pt_BR/{file}.php
  2. Add translation key and Portuguese text
  3. Use in Blade: {{ __('messages.welcome') }}
  4. Test across different tenant contexts

Customizing tenant branding

  1. Store settings in Tenant model (JSON or relations)
  2. Load in middleware or service provider
  3. Pass to views via view composer
  4. Cache for performance: tenant()->cache('branding')

Updating Docker image

  1. Modify docker/Dockerfile as needed
  2. Test locally: make build or docker-compose build app
  3. Push changes to GitHub
  4. CI/CD handles the rest automatically

Creating demo tenants for testing

# Using artisan command
php artisan tenants:seed

# Or via Makefile
make tenant-create

# Specify tenant details
php artisan tenants:create \
  --domain=demo.growuppro.com.br \
  --name="Empresa Demo" \
  --email=admin@demo.com

Managing code quality

# Run static analysis
./vendor/bin/phpstan analyse

# Check code style
./vendor/bin/pint --test

# Auto-fix code style
./vendor/bin/pint

# Or use Makefile shortcuts
make lint  # Check only
make fix   # Auto-fix

Setting up pre-commit hooks

# Install Husky (or similar)
npm install --save-dev husky

# Initialize hooks
npx husky init

# Add pre-commit hook
echo "make lint && make test" > .husky/pre-commit
chmod +x .husky/pre-commit

Environment Variables

Required Variables

# Application
APP_NAME="Growup Pro"
APP_ENV=production
APP_KEY=base64:...
APP_URL=https://growuppro.com.br
APP_LOCALE=pt_BR
APP_DEBUG=false

# Database (Central)
DB_CONNECTION=mysql
DB_HOST=database
DB_PORT=3306
DB_DATABASE=growuppro_central
DB_USERNAME=growuppro
DB_PASSWORD=secure_password

# Tenancy
TENANCY_DATABASE_PREFIX=tenant_
CENTRAL_DOMAINS=growuppro.com.br

# Redis
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

# Cache & Queue
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis

# Sentry (Error Tracking)
SENTRY_LARAVEL_DSN=https://xxx@sentry.io/xxx
SENTRY_TRACES_SAMPLE_RATE=0.2
SENTRY_PROFILES_SAMPLE_RATE=0.2

# Gitea Container Registry (or GitHub Container Registry as fallback)
REGISTRY_URL=gitea.yourdomain.com
REGISTRY_USERNAME=cauefaleiros
REGISTRY_PASSWORD=...  # Or use token

# GitHub Container Registry (GHCR) - if using as fallback
GHCR_TOKEN=ghp_...
GHCR_USERNAME=cauefaleiros
GHCR_IMAGE=ghcr.io/cauefaleiros/growup-pro

# Portainer
PORTAINER_URL=https://148.230.76.122:9443
PORTAINER_API_TOKEN=ptr_...
PORTAINER_STACK_ID=...

# Cloudflare (Optional - for API integration)
CLOUDFLARE_API_TOKEN=...
CLOUDFLARE_ZONE_ID=...

Admin Dashboard for Tenant Management

The platform includes a comprehensive admin dashboard for managing tenants and monitoring platform health.

Dashboard Features

Tenant Management:

  • View all active tenants with key metrics
  • Create/edit/delete tenant accounts
  • Suspend or activate tenant access
  • View tenant resource usage (storage, bandwidth, users)
  • Manage tenant subscriptions and billing

Analytics & Monitoring:

  • Total active tenants count
  • Growth metrics (new tenants per month)
  • Resource utilization per tenant
  • Most active tenants (by usage)
  • Revenue tracking (if applicable)
  • System health overview

Tenant Details View:

  • Company information and contact details
  • Subdomain and custom domain settings
  • User count and activity logs
  • Storage usage and database size
  • Last login and activity timestamps
  • Custom branding settings (logo, colors)

Bulk Operations:

  • Bulk tenant creation via CSV import
  • Batch notifications to multiple tenants
  • Mass configuration updates
  • Export tenant data for reporting

System Settings:

  • Default tenant configurations
  • Resource limits and quotas
  • Email templates for tenant communications
  • Feature flags management
  • Maintenance mode per tenant

Access Control

  • Admin dashboard accessible only to super admins
  • Route: /admin (protected by SuperAdmin middleware)
  • Audit logs for all admin actions
  • Two-factor authentication required

Implementation Notes

  • Built with Filament Admin Panel (recommended) or custom Blade views
  • Real-time updates using Livewire
  • Caching for performance (tenant list, metrics)
  • API endpoints for programmatic access
  • Webhooks for tenant lifecycle events (created, suspended, deleted)

Notes for Gemini AI Assistant

Context Awareness

  • This is Growup Pro, not Krayin - always use correct branding
  • All text should be in Portuguese (pt-BR) when user-facing
  • Consider tenant context in all suggestions
  • Respect Docker/Swarm constraints in infrastructure suggestions

Code Suggestions

  • Prefer extending over modifying Krayin core
  • Ensure tenant isolation in all data operations
  • Follow Tenancy for Laravel best practices
  • Include proper error handling (tenant not found, DB connection issues)
  • Suggest Docker-compatible solutions (env vars, volumes, etc.)
  • Always consider Sentry error tracking when suggesting error handling
  • Recommend testable code (dependency injection, mockable services)
  • Suggest code quality improvements when reviewing code (PHPStan compliance)

Infrastructure Suggestions

  • Consider Docker Swarm constraints (secrets, configs, networks)
  • Suggest zero-downtime deployment strategies
  • Include health checks in Docker configurations
  • Recommend scalable solutions (horizontal scaling, load balancing)

Translation Reminders

  • Always provide Portuguese translations for new strings
  • Check existing translation files before adding new keys
  • Maintain consistent terminology across the application

Quality Assurance & Best Practices

Code Quality Tools

The project enforces code quality through automated tools:

PHPStan (Static Analysis):

  • Level 5 minimum (configurable in phpstan.neon)
  • Catches type errors, undefined variables, incorrect method calls
  • Runs on every commit (pre-commit hook)
  • Must pass before deployment

Laravel Pint (Code Formatter):

  • PSR-12 coding standard enforcement
  • Automatic code formatting
  • Consistent code style across the team
  • Can auto-fix issues: ./vendor/bin/pint

Pre-commit Hooks:

  • Automatically run before every commit
  • Prevents committing code that doesn't pass quality checks
  • Fast feedback loop for developers
  • Configured via Husky or similar

Error Tracking with Sentry

Setup:

composer require sentry/sentry-laravel
php artisan sentry:publish --dsn

Features:

  • Real-time error notifications
  • Complete stack traces with context
  • User tracking (which tenant experienced the error)
  • Performance monitoring
  • Release tracking (know which deployment introduced bugs)

Configuration:

// config/sentry.php
'dsn' => env('SENTRY_LARAVEL_DSN'),
'environment' => env('APP_ENV'),
'traces_sample_rate' => 0.2, // 20% of requests
'profiles_sample_rate' => 0.2,

Tenant Context: Always include tenant information in Sentry reports:

\Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
    $scope->setTag('tenant_id', tenant('id'));
    $scope->setContext('tenant', [
        'name' => tenant('name'),
        'domain' => tenant('domain'),
    ]);
});

Testing Standards

  • Coverage minimum: 70% code coverage
  • Test pyramid: More unit tests, fewer integration/feature tests
  • Tenant isolation tests: Critical - must verify data doesn't leak
  • Performance tests: Ensure queries are optimized (N+1 detection)
  • CI enforcement: All tests must pass before merge

Resources & Documentation

Project Specific

Infrastructure

CI/CD

Laravel & PHP


Project: Growup Pro
Base: Krayin Laravel CRM (Whitelabel)
Current Phase: Initial setup - multi-tenancy integration and Docker infrastructure
Domain: growuppro.com.br
Language: Portuguese (pt-BR)
Deployment: Docker Swarm + Portainer + GitHub Actions CI/CD