Harden cert provisioning failure and write-back

Rate limits no longer inflate ssl_retry_count into an instant FAILED
path. Centralize outcomes in decideProvisioningOutcome, keep ACME
order state on transient and rate-limit errors, bound each Process
tick with a timeout, and block on FOR UPDATE when persisting a
freshly issued certificate.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
Bryan Frimin
2026-07-22 09:59:00 +02:00
parent 397f548937
commit 9724a2ce50
13 changed files with 1375 additions and 328 deletions

View File

@@ -63,3 +63,34 @@ export const getCustomDomainStatusBadgeLabel = (
}
return __("Unknown");
};
const provisioningErrorMessages: Record<string, string> = {
DNS_CNAME: "DNS is not configured correctly yet. Check the CNAME record.",
DNS_CAA: "DNS CAA records do not allow our certificate authority.",
ACME_RATE_LIMITED:
"Certificate authority is temporarily rate-limiting. We will retry automatically.",
ACME_INVALID_ORDER:
"Domain ownership could not be verified. We will retry automatically.",
ACME_TEMPORARY:
"Certificate provisioning hit a temporary error. We will retry automatically.",
ACME_FAILED:
"Certificate provisioning failed. Contact support if this persists.",
};
export const getCertificateProvisioningErrorMessage = (
provisioningError: string | null | undefined,
__: (key: string) => string,
) => {
if (!provisioningError) {
return null;
}
const knownMessage = provisioningErrorMessages[provisioningError];
if (knownMessage) {
return __(knownMessage);
}
return __(
"Certificate provisioning failed. Contact support if this persists.",
);
};

View File

@@ -21,6 +21,7 @@
export { objectKeys, objectEntries, cleanFormData } from "./object";
export { sprintf, faviconUrl, slugify } from "./string";
export {
getCertificateProvisioningErrorMessage,
getCustomDomainStatusBadgeLabel,
getCustomDomainStatusBadgeVariant,
} from "./customDomain";