Coolify builds with --no-cache, so intl (C++) recompiles from source every
deploy (~180s single-threaded) and overran the build timeout (exit 255).
Compile across all cores via MAKEFLAGS=-j$(nproc) to cut it several-fold.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Coolify-doc-driven production hardening of the deploy stack:
- run the whole stack as non-root www-data; nginx on 8080 (non-privileged),
pid in /tmp, user directive dropped (Coolify routes to any port)
- docker/healthcheck.sh: hit real /health route via PHP (not just port probe)
- split OPcache config into docker/php/opcache.ini
- graceful shutdown: supervisord stopsignal/stopwaitsecs + worker stop_grace_period
- APCu intentionally not added (Symfony cache uses redis)
- DEPLOY.md: 8080 port, non-root, resource-limit guidance
Verified on linux/amd64: non-root uid=82, /health 200, migrations run,
worker process healthcheck OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
worker-async crashed in a loop with 'No transport supports Messenger DSN
redis://...' because symfony/redis-messenger was never installed — 10x restart
killed the whole stack. Add the package (v7.4.8).
Also harden healthchecks:
- app: hit the real /health route via PHP get_headers (verifies app boots and
serves, not just that port 80 is open)
- workers: confirm the messenger:consume process is alive via busybox ps
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Coolify build host intermittently gets HTTP 400 from codeload.github.com on
Composer dist downloads. Bump COMPOSER_HTTP_RETRIES, wrap the install in a
5x retry loop, and on final attempt fall back to --prefer-source (git clone,
different endpoint than dist zips).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Symfony Dotenv::bootEnv() hard-requires a .env file even in prod. The repo's
.env holds dev secrets and is gitignored, so Coolify's clone ships none and the
app fatals with 'Unable to read /app/.env'. Write a minimal APP_ENV=prod .env
at build if one wasn't copied; all real values still come from the compose
environment (clear_env=no), which Dotenv never overwrites.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pecl install redis and install-php-extensions both fail on the Coolify build
host with 'No releases available for package pecl.php.net/redis' — that host
cannot reach the pecl registry. Build phpredis 6.1.0 from its GitHub source
tarball instead (github.com is reachable); pdo_mysql/intl/opcache stay as
bundled docker-php-ext-install (no network).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Added Dockerfile for multi-stage build including PHP, Node.js, and Nginx.
- Created docker-compose.coolify.yaml for service orchestration with app, workers, MariaDB, and Redis.
- Introduced entrypoint.sh for initialization tasks like JWT key generation and database migrations.
- Configured Nginx with default.conf for handling requests and routing to PHP-FPM.
- Added php.ini with production settings and opcache configuration.
- Set up supervisord.conf to manage PHP-FPM and Nginx processes.
- Created frontend-domains.json for managing allowed frontend domains.
- Added gen-cors-env.php script to generate CORS environment variables from frontend domains.
- Updated framework.yaml to configure trusted proxies and headers.
- Created .dockerignore to exclude unnecessary files from the Docker context.
- Added .env.coolify.example for environment variable configuration.
- Documented deployment steps and troubleshooting in coolify.md.
- Created a new JSON file for the representation API documentation, including nodes and edges that describe the API structure and relationships.
- Added another JSON file for the ApiIrService class, detailing its methods, imports, and relationships with other components.
- Added a new column `national_code_verified` to the `users` table.
- Normalized the `bank_account` field in the `representations` table from a single object to an array of IBANs with a default `verified` status of false.
feat(ApiIrService): implement identity verification client for api.ir
- Created `ApiIrService` to handle identity verification via api.ir.
- Implemented methods for matching national code with mobile and IBAN with national code and birth date.
- Added error handling and logging for external API requests.
- Added domain guard in CommissionService to ensure commission is calculated only when the appointment is booked under the same representation as the doctor.
- Updated RepresentationController to filter statistics by representation, ensuring accurate data is shown for each representative.
- Introduced new endpoints for the representation dashboard to provide summary statistics, doctor performance, and financial reports.
- Created new pages for RepresentationFinance and RepresentationSettlement to display financial data and allow for settlement requests.
- Added migration to include booking_representation_id in appointments for tracking the representative under which the appointment was booked.
- Added new configuration keys for appointment and upgrade commissions, tax settings, and SMS panel fee in SiteConfigController and SiteConfigRepository.
- Introduced CommissionService to handle commission calculations for appointments and subscriptions, including tax deductions and SMS fees.
- Created FinancialBreakdown entity and repository to log financial transactions.
- Updated PaymentController to process commissions upon successful payments for appointments and subscriptions.
- Developed FinancialReportPage in the admin panel to display financial breakdowns and summaries.
- Added database migration for the new financial_breakdowns table.
- Updated NewSessionPage to calculate patient share based on insurance coverage rules.
- Refactored billing calculations to utilize new patientShareOf function for service items.
- Enhanced API documentation to reflect changes in service coverage structure.
- Implemented ServiceInsuranceModal for managing insurance coverage per service.
- Added UI components for displaying and editing insurance coverage details.
- Removed obsolete toggle switch styles and adjusted CSS for new components.
- Ensured backend endpoints support both service_item_id and service_item_uuid for flexibility.
Wrap InsurancePricingPage and ClaimsPage in <FeatureGate feature="insurance">
so direct-URL access is blocked without an active subscription that enables
the feature. Add feature: "insurance" to the sidebar links (doctor/clinic/
secretary sections) so the menu items hide when the plan lacks it.
Make AdminSubscriptionPage feature controls dynamic: derive the plan feature
checkboxes from FEATURE_LABELS (now including "insurance") and switch the Zod
schema to z.record, so adding a feature only touches the label map.
No backend/migration change: plan.features is free-form JSON; existing plans
default to insurance:false and admins enable it per plan.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>