- Shipped
- September 9, 2026 at 8:08 PM UTC
- Author
- Kamo
- Commit
- 678fee8
**No e-sign email had been leaving the cluster.** EmailService gates /api/email/templates/send on the cluster-wide internal-auth secret (mlos-internal-auth -> INTERNAL_AUTH_SECRET). EsignEmailClient presented esig.internal-auth-secret, which the ConfigMap wires to **************** — a different, equally real, equally mounted credential. Every invitation, every step-up OTP and all four lifecycle notices came back 403 Forbidden. Nothing was unset, so nothing looked misconfigured; the client caught the 403 and answered false; and createAndSend DISCARDED that boolean, so the envelope reached SENT, the sender was shown "Document sent for signature", and the recipient row sat at PENDING — which is also exactly what a delivered-but-unopened invitation looks like. Confirmed on envelope 50a8f4e0 (2026-09-09 19:25:54): delivered_at null, and one ERROR line in the pod naming the 403. The property was doing two unrelated jobs. INBOUND, esig.internal-auth-secret guards EsignInternalController, which APIService calls presenting the public-chat secret — repointing it would have fixed mail by breaking every programmatic e-sign call. So it is two properties now, the outbound one from the secret EmailService actually compares against, and the deployment mounts it. EsignEmailClient refuses to send at all with no credential rather than converting a config fault into an indistinguishable delivery failure, and createAndSend reports what it could not deliver instead of throwing away the answer. Not an exception: the envelope, its roster and its tokens are all correct and one click resends. **Signature Date.** A new signature_date field type, filled by the server from the signing instant — never by the browser, whose clock is settable and which is the one value a party has an incentive to misstate on a legal instrument. Rendered in the SIGNER's time zone and the ORGANIZATION's locale (09/09/2026 in en-US, 09.09.2026 in de-DE), because a signature given at 20:00 in Los Angeles is already the next day in UTC and 09/07 is two different days on two continents. Any value arriving on the wire for such a field is dropped before the completeness check reads it, and the field is never counted as a missing required one — whatever its flags say, since a required-and-not-readOnly one would park the signer on a box they are shown no control for with Finish disabled forever. The config ratchet reads k8s/configmap.yaml, not src/main/resources — the pod runs with **************** and a test pointed at the repo's resources copy would have stayed green through the whole outage.