/api/extensions and customer extension list now only return
is_active extensions, preventing deleted extensions from showing
in the dashboard and causing deploy errors with null versions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Every time the server starts (including after deploy), it syncs
the extension registry from Gitea before serving requests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MODULES was a static dict that got out of sync with Gitea repos —
LegalAssistance was missing, 5 deleted extensions were still listed.
Now MODULES loads from DB on startup with static fallback.
New POST /sync-registry endpoint scans espocrm-extensions org on Gitea,
adds new extensions, deactivates removed ones, and reloads MODULES.
INSTALL_ORDER is now computed dynamically via topological sort.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The platform stores API keys as base64-encoded Espo-Authorization,
not raw API keys. Send both headers so opcache-clear.php can validate.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add multi-tier opcache clearing after extension install:
- Tier 1: HTTP call to opcache-clear.php endpoint
- Tier 2: SSH + docker exec apachectl graceful
- Tier 3: Log warning
Add ssh_host, ssh_user, ssh_key, docker_container fields
to customers table for SSH fallback.
Fixes production issue where new PHP files weren't loaded
after extension upgrade due to stale opcache.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Was showing all historical deploys causing noise. Now uses DISTINCT ON
to get only the most recent deploy for each extension+customer pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New /health-check endpoint verifies:
- Gitea release integrity (manifest version matches tag)
- Duplicate ZIP assets in releases
- EspoCRM API reachability per customer
- Extension load status on each instance
- Stale deployments (logged ok but version not updated)
New n8n workflow runs at 07:00 & 19:00, combines health check
with drift sync, and posts combined report to Mattermost.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- When re-publishing, delete old ZIP assets before uploading new one
- Take last ZIP asset when duplicates exist in deploy flow
- Handle empty response body from DELETE API calls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ensures every sync call first fills in any missing extension
assignments, so new extensions are automatically available to
all customers without manual intervention.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Backend: sync_customer_extensions now sets installed_version=NULL when
extension is missing_on_server (previously only detected drift without
updating DB)
- Frontend: refresh button now calls /sync endpoint before reloading,
ensuring the dashboard reflects actual server state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds extension sync that queries each customer's EspoCRM to compare
actually-installed extensions with what the platform DB tracks.
Updates platform DB on version mismatches and reports drifts to Mattermost.
n8n workflow ID: NXxBHm3qhWL3yHza (daily at 07:00)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Sort extensions by install order (HebrewLanguage first, then deps)
- Grey out extensions with missing dependencies (show lock icon + "נדרש: X")
- Checkbox selection for batch install with progress indicator
- "בחר הכל" button to select all installable extensions
- Server returns dependencies + install_order in customer API
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>