The Certificates facade
RoundlyConsulting\Certificates\Facades\Certificates is the recommended entry point. Its root is CertificatesManager, a container singleton, and every state-changing method runs through an action — so the facade, an injected manager and Certificates::fake() all see the same calls. A tour of the surface:
use RoundlyConsulting\Certificates\DataTransferObjects\IssueCertificateData;
use RoundlyConsulting\Certificates\Facades\Certificates;
// Issue
Certificates::issueIfMissing('app.example.com');
Certificates::issue(IssueCertificateData::make('app.example.com'));
// Lifecycle — a registry Certificate or a domain (its most recent row)
Certificates::renew('app.example.com');
Certificates::renewLater('app.example.com');
Certificates::revoke($certificate, 'key compromise');
Certificates::expire('app.example.com');
// The whole registry
Certificates::expiring(14); // Collection<int, Certificate>, soonest first
Certificates::renewDue(); // RenewalReport
Certificates::sync('kubernetes'); // int rows written
Certificates::prune(30); // int rows soft-deleted
// One domain — fluent issuance, reads and the same lifecycle verbs
Certificates::for('app.example.com')->using('acme')->issue();
Certificates::for('app.example.com')->renew();
// Reads, drivers and scoping
Certificates::find('app.example.com');
Certificates::statusReport('app.example.com', fresh: true);
Certificates::driver('acme');
Certificates::extend('vault', fn () => new VaultCertificateProvider());
Certificates::on('tenant')->renewDue();Issuance and lifecycle
Every lifecycle verb takes a registry Certificate or a domain, which resolves to its most recent row on the bound connection. An unknown domain, or a status that cannot make the move (renewing a revoked certificate, say), throws CertificateException — renewLater() included: it checks the status before it queues anything:
| Method | Returns | Purpose |
|---|---|---|
issue(IssueCertificateData $data) | Certificate | Provision and record from a DTO; throws ProvisioningInProgressException while another process provisions the same certificate. |
issueIfMissing(string $domain) | Certificate | The active registry record, or a new issuance. |
generate(string $domain) | bool | Provision — full lifecycle with a registry, straight through the provider without one; false while the certificate’s lock is held. |
renew(Certificate|string $certificate) | Certificate | Issued/Renewed/Failed → Renewed, now, through the certificate’s own driver. |
renewLater(Certificate|string $certificate) | Certificate | Check the status now, then queue RenewCertificateJob on renewal.queue. |
renewDue(?int $thresholdDays = null, bool $queue = false) | RenewalReport | Renew or queue everything expiring within the threshold (failed rows included); one failure never stops the rest. |
revoke(Certificate|string $certificate, ?string $reason = null) | Certificate | Issued/Renewed → Revoked, fires CertificateRevoked. Registry only — the CA is not contacted. |
expire(Certificate|string $certificate) | Certificate | Issued/Renewed → Expired, fires CertificateExpired. |
sync(?string $driver = null) | int | Pull a driver’s live certificates into the registry; returns rows written. |
prune(int $days = 30, CertificateStatus|string|null $status = null) | int | Soft-delete stale expired, failed and revoked rows — or exactly $status. |
The domain handle, reads and drivers
| Method | Returns | Purpose |
|---|---|---|
for(string|array $domain) | CertificateBuilder | The domain handle — fluent issuance, reads and the lifecycle verbs. |
find(string $domain, ?string $driver = null) | ?Certificate | Latest registry record for the domain. |
status(string $domain) | ?CertificateStatus | Registry status of the latest record. |
statusReport(string $domain, ?string $driver = null, bool $fresh = false) | ?CertificateStatusReport | Live, cache-aware status from the provider. |
expiring(?int $days = null, ?string $driver = null) | Collection<Certificate> | Issued, Renewed and Failed rows expiring within $days (default renewal.threshold_days), soonest first. |
get() | Collection<RemoteCertificate> | Certificates the default driver manages. |
exists(string $domain) | bool | Provider check on the default driver. |
monitorExpiry(Certificate $certificate, ?Model $notifiable = null) | PendingScheduledCheck | Schedule an alerts expiry monitor. |
driver(?string $name = null) | CertificateProvider | Resolve a provider (default when null). |
extend(string $driver, Closure $callback) | CertificatesManager | Register a custom driver on CertificateProviderManager. |
on(?string $connection) | CertificatesManager | Connection-bound clone for multi-tenant registries. |
certificateName(string $domain) | string | Deterministic, lowercase DNS-1123 certificate name (*. becomes wildcard-, at most 253 characters). |
fake() | CertificatesFake | Swap in the in-memory recording fake (see Testing). |
Certificates::for($domain) is a handle for one domain (or a SAN set led by its first domain): fluent issuance, reads, and renew(), renewLater(), revoke() and expire() on that domain’s row — see Fluent builder. With using($driver) it only ever touches that driver’s row.
The facade also exposes the fake-only seed(), failRenewalOf() and every assert* method once Certificates::fake() is active (see Testing). The manager is macroable, so your own methods show up on the facade too (see Extending).
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.