/** How the broker serves its client port. Every `serverConfig` render must state one explicitly. */ export type BrokerTransport = { readonly kind: "plaintext"; } | { readonly kind: "tls-required"; readonly certFile: string; readonly keyFile: string; }; export type TlsRequired = Extract; /** What a validated cert/key pair turned out to be. Returned so callers can log or compare it — * notably the rotation path, which must prove the SERVED leaf matches the file on disk. */ export interface TlsMaterial { readonly notBefore: Date; readonly notAfter: Date; /** Colon-separated uppercase SHA-256 of the DER, exactly as `X509Certificate.fingerprint256` * and `tls.PeerCertificate.fingerprint256` render it, so the two are directly comparable. */ readonly fingerprint256: string; readonly subject: string; } /** Thrown for every rejected cert/key pair. A distinct type so callers can surface a * CERTIFICATE cause to the operator rather than a generic "broker unreachable" — a TLS failure * reported as unreachability invites exactly the wrong remedy. */ export declare class TlsMaterialError extends Error { constructor(message: string); } export declare function validateTlsMaterial(t: TlsRequired, opts?: { dialHost?: string; now?: Date; }): TlsMaterial; /** What the broker is actually serving right now, read off the wire. */ export interface ServedCert { readonly fingerprint256: string; readonly validTo: string; readonly subject: string; } /** * Open a real NATS STARTTLS connection and report the leaf certificate the broker is SERVING. * * This is the only honest proof that a rotation took effect. Renewing the files on disk does not * reload nats-server: the reference deployment renews its Let's Encrypt material on a timer and * the broker process has gone on serving the previous certificate for weeks, because nothing * signalled it. Comparing file mtimes, or trusting that a reload command exited zero, would both * have reported success there. Only reading back what the listener presents catches it. * * `rejectUnauthorized` is false on purpose: this call answers "which certificate is being served", * not "do I trust it". The caller compares the returned fingerprint to the file it intended to * install, which is a stronger and more specific check than chain validation. */ export declare function probeServedCert(opts: { host: string; port: number; /** SNI/verification name, when it differs from the dial host. */ servername?: string; timeoutMs?: number; }): Promise; /** * Assert that the broker is serving exactly the certificate in `expected`. This is the rotation * gate: validate the new pair, install it, signal the broker, then call this. A mismatch means the * reload did not take, and the caller must fail loud and leave the previous listener in place — * never fall back to plaintext. */ export declare function assertServedCertMatches(expected: TlsMaterial, where: { host: string; port: number; servername?: string; timeoutMs?: number; }): Promise; //# sourceMappingURL=broker-tls.d.ts.map