From 6cd0b009ef11d06d324ea34eb6cdefb0e148606b Mon Sep 17 00:00:00 2001 From: Alireza Hassani Date: Wed, 26 Aug 2026 01:20:03 +0330 Subject: [PATCH] Call per-tenant dashboard SSL agent when issuing domain SSL. Issue SSL on one domain now passes tenantApex to the dashboards agent instead of renewing the shared multi-tenant cert. Co-authored-by: Cursor --- src/domain-admin/domain-admin.service.ts | 30 +++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/domain-admin/domain-admin.service.ts b/src/domain-admin/domain-admin.service.ts index 427e9d7..c2f0b3d 100644 --- a/src/domain-admin/domain-admin.service.ts +++ b/src/domain-admin/domain-admin.service.ts @@ -103,13 +103,15 @@ export class DomainAdminService { } /** Fire-and-forget or blocking call to the dashboards VPS ssl-sync agent. */ - private async callDashboardSslSync(opts: { wait: boolean }) { + private async callDashboardSslSync(opts: { wait: boolean; tenantApex?: string }) { const agentUrl = this.config.get('SSL_SYNC_AGENT_URL')?.trim(); const token = this.config.get('SSL_SYNC_AGENT_TOKEN')?.trim(); if (!agentUrl || !token) { throw new ServiceUnavailableException('SSL sync agent is not configured'); } + const tenantApex = opts.tenantApex?.trim().toLowerCase(); + let response: Response; try { response = await fetch(agentUrl, { @@ -118,7 +120,10 @@ export class DomainAdminService { 'Content-Type': 'application/json', 'X-SSL-Sync-Agent-Token': token, }, - body: JSON.stringify({ wait: opts.wait }), + body: JSON.stringify({ + wait: opts.wait, + ...(tenantApex ? { tenantApex } : {}), + }), }); } catch { throw new ServiceUnavailableException('Could not reach SSL sync agent'); @@ -368,30 +373,39 @@ export class DomainAdminService { if (!businessOk || !customerOk) { try { - await this.callDashboardSslSync({ wait: true }); + await this.callDashboardSslSync({ wait: true, tenantApex: apex }); businessOk = await probeTlsHost(businessHost); customerOk = await probeTlsHost(customerHost); if (!hosts.business.detail) { hosts.business = businessOk - ? { host: businessHost, status: 'issued', detail: 'Covered by dashboard cert' } + ? { + host: businessHost, + status: 'issued', + detail: 'Dashboard cert issued for this domain only', + } : { host: businessHost, status: 'failed', - detail: 'Dashboard SSL sync finished but probe still failed', + detail: 'Tenant dashboard SSL finished but probe still failed', }; } if (!hosts.customer.detail) { hosts.customer = customerOk - ? { host: customerHost, status: 'issued', detail: 'Covered by dashboard cert' } + ? { + host: customerHost, + status: 'issued', + detail: 'Dashboard cert issued for this domain only', + } : { host: customerHost, status: 'failed', - detail: 'Dashboard SSL sync finished but probe still failed', + detail: 'Tenant dashboard SSL finished but probe still failed', }; } } catch (err) { - const detail = err instanceof Error ? err.message : 'Dashboard SSL sync failed'; + const detail = + err instanceof Error ? err.message : 'Tenant dashboard SSL failed'; if (!businessOk) { hosts.business = { host: businessHost, status: 'failed', detail }; }