Symptom
DefaultProductCode's actual behavior is split, and doesn't match what its own UI text/docs described (a generic "fallback when no template code is set"):
- New enrollments: never consulted.
Models/EnrollmentParams.cs's ProductCode getter falls back only to a built-in default keyed by product name, never to _config.DefaultProductCode. Client/CERTInextClient.cs's BuildOrderRequestFromLegacyEnrollRequest has ProductCode = request.ProfileId ?? _config.DefaultProductCode ?? string.Empty, but request.ProfileId is never null (worst case ""), so that fallback is unreachable.
- Renewals: consulted unconditionally.
RenewCertificateAsync (CERTInextClient.cs:820) sets ProductCode = _config.DefaultProductCode ?? string.Empty with no other fallback — the code comment notes "we don't have the product code from TrackOrder." This ignores the template's ProductCode/ProfileId entirely for renewals. If DefaultProductCode is left unset (its default is "", not null), every renewal is submitted with an empty product code.
How this was found
Found during a docsource freshness review (2026-08-13). Originally filed (incorrectly) as "dead code with no effect anywhere" — a follow-up verification pass caught that the renewal path does use it, unconditionally. Docs (docsource/configuration.md) have been corrected to describe the actual split behavior.
Severity
Medium — for any deployment that renews certificates and hasn't set DefaultProductCode, renewals may be going out with an empty product code today. Worth checking whether this has caused silent renewal failures.
Fix
Not fixed here. Options: make the renewal path respect the template's ProductCode/ProfileId (probably the right fix, if that information is available to the renewal call), or at minimum validate DefaultProductCode is set before attempting a renewal and fail clearly instead of submitting an empty code.
Files
CERTInext/Client/CERTInextClient.cs:820 (RenewCertificateAsync)
CERTInext/Models/EnrollmentParams.cs (ProductCode getter — new-enrollment path, unaffected)
docsource/configuration.md
Symptom
DefaultProductCode's actual behavior is split, and doesn't match what its own UI text/docs described (a generic "fallback when no template code is set"):Models/EnrollmentParams.cs'sProductCodegetter falls back only to a built-in default keyed by product name, never to_config.DefaultProductCode.Client/CERTInextClient.cs'sBuildOrderRequestFromLegacyEnrollRequesthasProductCode = request.ProfileId ?? _config.DefaultProductCode ?? string.Empty, butrequest.ProfileIdis never null (worst case""), so that fallback is unreachable.RenewCertificateAsync(CERTInextClient.cs:820) setsProductCode = _config.DefaultProductCode ?? string.Emptywith no other fallback — the code comment notes "we don't have the product code from TrackOrder." This ignores the template'sProductCode/ProfileIdentirely for renewals. IfDefaultProductCodeis left unset (its default is"", not null), every renewal is submitted with an empty product code.How this was found
Found during a docsource freshness review (2026-08-13). Originally filed (incorrectly) as "dead code with no effect anywhere" — a follow-up verification pass caught that the renewal path does use it, unconditionally. Docs (
docsource/configuration.md) have been corrected to describe the actual split behavior.Severity
Medium — for any deployment that renews certificates and hasn't set
DefaultProductCode, renewals may be going out with an empty product code today. Worth checking whether this has caused silent renewal failures.Fix
Not fixed here. Options: make the renewal path respect the template's
ProductCode/ProfileId(probably the right fix, if that information is available to the renewal call), or at minimum validateDefaultProductCodeis set before attempting a renewal and fail clearly instead of submitting an empty code.Files
CERTInext/Client/CERTInextClient.cs:820(RenewCertificateAsync)CERTInext/Models/EnrollmentParams.cs(ProductCodegetter — new-enrollment path, unaffected)docsource/configuration.md