# mTLS gate — `@suaveplan/api-auth-bearer-static` _(no submodules)_ ## Purpose The mTLS gate enforces an optional second factor on individual token table entries. When operators mark an entry with `mtlsRequired: true`, the resolver MUST refuse to surface the entry's Principal unless the host listener attached a verified peer certificate to the inbound request via `request.tls.peerCertificate`. This guards the highest-privilege service tokens (e.g. internal admin API) against credential leakage — the bearer token alone is necessary but no longer sufficient. The adapter does NOT establish TLS itself. The host listener (Bun's TLS-enabled server, Node's `https`, a Cloudflare-Worker TLS terminator ahead of the worker, etc.) is responsible for completing the TLS handshake and surfacing the verified subject as `request.tls.peerCertificate`. This module just inspects what was attached. ## Features - Pure function — no I/O, no state. - Defensive — accepts any `Request`-shaped input even when the `tls` field was not attached (returns `undefined`). - Treats `peerCertificate: null` identically to absent. - `mtlsRequired === false` short-circuits without inspecting the request. ## Usage: Basic ```ts import { checkMtlsGate } from "@suaveplan/api-auth-bearer-static/mtls"; const request = new Request("https://example/test"); const allowed = checkMtlsGate(request, true); // allowed === false — no peerCertificate attached ``` ## Usage: Advanced ```ts import { checkMtlsGate, extractPeerCertificate, } from "@suaveplan/api-auth-bearer-static/mtls"; // Host listener pattern — wrap the inbound request before handing off to // the auth chain. const withTls = Object.assign(request, { tls: { peerCertificate: parsedX509Subject }, }); const cert = extractPeerCertificate(withTls); // cert === parsedX509Subject const allowed = checkMtlsGate(withTls, true); // allowed === true ``` ## API Reference - `interface RequestTlsInfo { peerCertificate?: unknown }` - `extractPeerCertificate(request: Request): unknown | undefined` - `checkMtlsGate(request: Request, mtlsRequired: boolean): boolean` ## Implementation Notes The `Request` Web type has no standardised `tls` field. Both Node's undici-based `Request` and Bun's polyfill ignore unknown properties on construction, so the host pattern is to attach `tls` as a plain property after the Request is built (or to wrap it in a Proxy / subclass). The extractor reads through that property with a single defensive type cast and returns `undefined` for any shape that does not satisfy the `{ peerCertificate: }` invariant. The opaque certificate itself is not parsed here — that is the host's job, and a future `api-auth-mtls` adapter (out of scope for Stage 4) will own subject extraction.