# Regulatory Headers

> STIR/SHAKEN, P-Asserted-Identity, and PIDF-LO geolocation.

The ClutchCall gateway can decorate every outbound SIP INVITE with the
regulatory headers required to interoperate with US/EU PSTN carriers.
None of this is exposed as an SDK option — it's configured on the trunk
([`AddTrunk`](/admin/trunks)) and applied automatically for calls on
that trunk.

## STIR/SHAKEN

The gateway signs outbound calls with a PASSporT JWT (RFC 8224 / 8225)
and attaches it as an `Identity` header. A typical signed INVITE looks
like:

```
INVITE sip:+15551234567@carrier.example;user=phone SIP/2.0
From: "ACME Support" <sip:+18005550100@clutchcall.dev>;tag=…
To: <sip:+15551234567@carrier.example>
Identity: eyJhbGciOiJFUzI1NiIsInR5cCI6InBhc3Nwb3J0Iiwic
 HBjIjoic2hha2VuIiwieDV1IjoiaHR0cHM6Ly9jZXJ0LmV4YW1wbG
 UvY2VydHMvc3RpL3RuIn0.eyJhdHRlc3QiOiJBIiwiZGVzdCI6eyJ0
 biI6WyIxNTU1MTIzNDU2NyJdfSwiaWF0IjoxNzM0MDAwMDAwLCJvcm
 lnIjp7InRuIjoiMTgwMDU1NTAxMDAifSwib3JpZ2lkIjoiYWNtZS0
 yMDI2LTA0In0.<sig>;info=<https://cert.clutchcall.dev/sti.pem>;alg=ES256;ppt=shaken
```

The PASSporT `attest` value is the trunk's configured **attestation
level**:

| Attest | Meaning                                                          |
| ------ | ---------------------------------------------------------------- |
| `A`    | Full attestation — caller has a verified relationship with the calling number. |
| `B`    | Partial attestation — caller is known but the number isn't directly verified. |
| `C`    | Gateway attestation — call is being routed but origin is unverified. |

Set the per-trunk default through `AddTrunk` extras (or, for tenants on
shared infrastructure, the gateway's deployment config). The signing
certificate (`x5u` URL) is sourced from the gateway's `cert_path` —
rotate it via [`ReloadCertificates`](/admin/certificates).

Inbound SIP INVITEs are validated symmetrically: the `Identity` header
is checked against the published `x5u` cert, and the result surfaces in
the `CallEvent.status` string (`STIR_VERIFIED`, `STIR_FAILED`,
`STIR_MISSING`).

## P-Asserted-Identity (PANI)

For carrier interconnects that prefer PANI over STIR, the gateway also
emits an [RFC 3325](https://datatracker.ietf.org/doc/html/rfc3325)
`P-Asserted-Identity` header carrying the verified caller-id:

```
P-Asserted-Identity: <sip:+18005550100@clutchcall.dev>
Privacy: none
```

PANI is mutually exclusive with `Privacy: id`; the gateway will switch
automatically if the SDK's `OriginateRequest` flags the call as
caller-id-restricted.

## PIDF-LO geolocation

For E911-style emergency routing, the gateway can attach a Presence
Information Data Format — Location Object (RFC 4119, RFC 5491) as a
SIP body part. Configure it on the trunk:

```yaml
# trunk extras (set via AddTrunk extras field or platform config)
geolocation:
  default_civic_address:
    country: US
    region:  CA
    city:    San Francisco
    street:  1 Market Street
    postal:  94105
  geo_priv_routing: emergency
```

The resulting `multipart/mixed` INVITE body:

```
--boundary
Content-Type: application/sdp

v=0
o=… …
s=…
…

--boundary
Content-Type: application/pidf+xml

<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
          xmlns:gp="urn:ietf:params:xml:ns:pidf:geopriv10"
          xmlns:cl="urn:ietf:params:xml:ns:pidf:geopriv10:civicAddr">
  <tuple id="loc">
    <status>
      <gp:geopriv>
        <gp:location-info>
          <cl:civicAddress>
            <cl:country>US</cl:country>
            <cl:A1>CA</cl:A1>
            <cl:A3>San Francisco</cl:A3>
            <cl:A6>Market Street</cl:A6>
            <cl:HNO>1</cl:HNO>
            <cl:PC>94105</cl:PC>
          </cl:civicAddress>
        </gp:location-info>
        <gp:usage-rules>
          <gp:retransmission-allowed>no</gp:retransmission-allowed>
          <gp:retention-expires>2026-04-26T12:00:00Z</gp:retention-expires>
        </gp:usage-rules>
      </gp:geopriv>
    </status>
    <timestamp>2026-04-26T11:00:00Z</timestamp>
  </tuple>
</presence>

--boundary--
```

A SIP `Geolocation` header points at the `cid:` of the PIDF-LO part,
plus `Geolocation-Routing: yes` for emergency-routing carriers.

## Per-call overrides

The standard `OriginateRequest` does not carry any of these fields —
that's deliberate, since regulated metadata shouldn't be set ad-hoc by
SDK callers. If you need to override the trunk default for a single
call (e.g. a softphone roaming to a different civic address), use
`ExecuteDialplan` with action `ANSWER` and supply the override via
`app_args` as a JSON blob:

```json
{
  "geolocation": {
    "civic_address": {
      "country": "US",
      "region":  "NY",
      "city":    "New York",
      "street":  "350 Fifth Avenue",
      "postal":  "10118"
    }
  }
}
```

The gateway picks this up before the INVITE leaves the wire.

## Disabling

For lab / development environments where regulatory headers cause noise
in test SBCs, set `regulatory.enabled: false` in the gateway config.
**Do not disable in production** — most carriers will silently degrade
calls without a valid `Identity` header (lower attestation, displayed
as "Spam Likely" on receiving handsets).
