# Interface NetworkGuard

public interface NetworkGuard

Interception point for cross-cutting network policy: decorating outgoing requests, and vetting the TLS certificate chain before a request body is written.

At most one guard is installed per app, via `NetworkManager.setNetworkGuard(NetworkGuard)`, and the slot seals after the first call. `AppShield` is the intended consumer, but the interface is deliberately generic and carries no dependency on it.

##### This does not replace the per-request certificate hook

[ConnectionRequest#checkSSLCertificates(ConnectionRequest.SSLCertificate[])] remains the way an individual request pins for itself, and it still runs first and unchanged. The guard runs afterwards, so an app that already pins manually keeps working and simply gains a second, app-wide layer.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `afterResponse(ConnectionRequest request, int responseCode, String[] headers)`
  Called once the response code is known, including for failed requests.
  `void`
  `beforeRequest(ConnectionRequest request)`
  Called on the network thread immediately before the connection is opened, and again on each retry or redirect so a stale token is never reused.
  `void`
  `checkCertificates(ConnectionRequest request, ConnectionRequest.SSLCertificate[] certificates)`
  Vets the certificate chain, after the handshake and before any request body is written.
  `String[]`
  `interestingResponseHeaders()`
  Response header names this guard wants captured, or null for none.
  `boolean`
  `isCertificateCheckRequired(String url)`
  Whether this URL's certificate chain needs to be inspected, i.e.

- ## Method Details

  - ### beforeRequest

    void beforeRequest(ConnectionRequest request) throws IOException

    Called on the network thread immediately before the connection is opened, and again on each retry or redirect so a stale token is never reused.

    May block -- it is off the EDT and outside the network queue's lock. Add headers here. Throwing fails the request through the normal error path.

    Throws:
      `IOException`

  - ### isCertificateCheckRequired

    boolean isCertificateCheckRequired(String url)

    Whether this URL's certificate chain needs to be inspected, i.e. whether the host has pins.

    Must be fast and purely local. On iOS this is consulted from the TLS delegate thread while the handshake is held open.

    Returning true has a cost beyond the check itself: the framework asks the platform for the richer certificate details, including public-key digests, which it does not otherwise collect. Return false for hosts with no pins.

  - ### checkCertificates

    void checkCertificates(ConnectionRequest request, ConnectionRequest.SSLCertificate[] certificates) throws IOException

    Vets the certificate chain, after the handshake and before any request body is written.

    Throwing an `IOException` aborts the request and surfaces through the request's normal error handling, rather than completing it with an empty response.

    Must be local and non-blocking, for the same delegate-thread reason as `isCertificateCheckRequired(String)`. In particular it must not try to fetch a fresh pin set: use the last known one and let a mismatch stand.

    Throws:
      `IOException`

  - ### interestingResponseHeaders

    String[] interestingResponseHeaders()

    Response header names this guard wants captured, or null for none.

    Asked once per response, while the connection is still open. The framework does not retain arbitrary response headers, and by the time `afterResponse(ConnectionRequest, int, String[])` runs the connection has been closed -- so anything a guard needs to see has to be named here first.

  - ### afterResponse

    void afterResponse(ConnectionRequest request, int responseCode, String[] headers)

    Called once the response code is known, including for failed requests.

    This is how a token layer learns its token was refused -- a 401 or 403 from a protected host usually means the cached token should be discarded before the next attempt. Must not throw; exceptions here are logged and swallowed so a telemetry problem cannot fail a request that otherwise succeeded.

    Parameters:
      `headers` - values for the names returned by `interestingResponseHeaders()`, in the same order; an entry is null when the response did not carry that header