Skip to content

Commit

Permalink
KZOO-46: Add Emergency Notification for E911 Compliance (#6443)
Browse files Browse the repository at this point in the history
This PR adds new functionality to help facilitate compliance with
Kari's Law and notification for when an emergency call is placed.

An email contact list can now be set on a phone numbers emergency
metadata.

Notification can now be achieved one of several ways:

* A new amqp event, `emergency_bridge` has been added to
`kapi_notifications` to trigger a teletype notification email when an
emergency call is placed.
* A new dedicated emergency bridge webhook can be configured

* Adds new text and html teletype templates
* Adds new teletype module to render template
* Template will distinguish between Emergency and test calls

* Creates a new amqp definition ing `kapi_notifications` for usage
when an emergency call is attempted.
* Publish callback as been added to `cb_notifications`
* Set emergency location data as well as user and device metadata

* Publishes `emergency_bridge` message when stepswitch determines an
emergency call is being attempted
* Adds a new test rules object a resource to define test patterns for
a resource to help differentiate between emergency and test calls.
  • Loading branch information
John White authored and jamesaimonetti committed May 4, 2020
1 parent d73820e commit 0e7e374
Show file tree
Hide file tree
Showing 30 changed files with 992 additions and 29 deletions.
2 changes: 2 additions & 0 deletions applications/crossbar/doc/phone_numbers.md
Expand Up @@ -39,6 +39,8 @@ Key | Description | Type | Default | Required | Support Level
`e911.locality` | The locality (city) where the number is in service | `string()` | | `true` |
`e911.location_id` | The e911 provisioning system internal id for this service address | `string()` | | `false` |
`e911.longitude` | The e911 provisioning system calculated service address longitude | `string()` | | `false` |
`e911.notification_contact_emails.[]` | | `string()` | | `false` |
`e911.notification_contact_emails` | A list of email addresses to receive notification when this number places an emergency call | `array(string())` | `[]` | `false` |
`e911.plus_four` | The extended zip/postal code where the number is in service | `string()` | | `false` |
`e911.postal_code` | The zip/postal code where the number is in service | `string()` | | `true` |
`e911.region` | The region (state) where the number is in service | `string(2)` | | `true` |
Expand Down
2 changes: 2 additions & 0 deletions applications/crossbar/doc/ref/phone_numbers.md
Expand Up @@ -27,6 +27,8 @@ Key | Description | Type | Default | Required | Support Level
`e911.locality` | The locality (city) where the number is in service | `string()` | | `true` |
`e911.location_id` | The e911 provisioning system internal id for this service address | `string()` | | `false` |
`e911.longitude` | The e911 provisioning system calculated service address longitude | `string()` | | `false` |
`e911.notification_contact_emails.[]` | | `string()` | | `false` |
`e911.notification_contact_emails` | A list of email addresses to receive notification when this number places an emergency call | `array(string())` | `[]` | `false` |
`e911.plus_four` | The extended zip/postal code where the number is in service | `string()` | | `false` |
`e911.postal_code` | The zip/postal code where the number is in service | `string()` | | `true` |
`e911.region` | The region (state) where the number is in service | `string(2)` | | `true` |
Expand Down
2 changes: 2 additions & 0 deletions applications/crossbar/doc/ref/resources.md
Expand Up @@ -77,6 +77,8 @@ Key | Description | Type | Default | Required | Support Level
`require_flags` | When set to true this resource is ignored if the request does not specify outbound flags | `boolean()` | | `false` |
`rules.[]` | | `string()` | | `false` |
`rules` | A list of regular expressions of which one must match for the rule to be eligible, they can optionally contain capture groups | `array(string())` | `[]` | `false` |
`rules_test.[]` | | `string()` | | `false` |
`rules_test` | A list of regular expressions of which if matched denotes a test rule | `array(string())` | `[]` | `false` |
`weight_cost` | A value between 0 and 100 that determines the order of resources when multiple can be used | `integer()` | `50` | `false` |

### custom_sip_headers
Expand Down
18 changes: 18 additions & 0 deletions applications/crossbar/doc/resources.md
Expand Up @@ -93,6 +93,8 @@ Key | Description | Type | Default | Required | Support Level
`require_flags` | When set to true this resource is ignored if the request does not specify outbound flags | `boolean()` | | `false` |
`rules.[]` | | `string()` | | `false` |
`rules` | A list of regular expressions of which one must match for the rule to be eligible, they can optionally contain capture groups | `array(string())` | `[]` | `false` |
`rules_test.[]` | | `string()` | | `false` |
`rules_test` | A list of regular expressions of which if matched denotes a test rule | `array(string())` | `[]` | `false` |
`weight_cost` | A value between 0 and 100 that determines the order of resources when multiple can be used | `integer()` | `50` | `false` |

### custom_sip_headers
Expand Down Expand Up @@ -191,6 +193,22 @@ Some upstream carriers require the From address' realm to be formatted. There ar
2. Set `"from_account_realm":true` to use the calling account's realm
3. Set `"realm":"{CUSTOM_REALM}"` on a per-gateway basis (not on the top-level resource)


## rules_test.[]

The `rules_test` object defines an array of regular expressions for test patterns of the given resource.

For example, if the resource handles emergency routes in North America:

```
"rules_test": [
"^\\+{0,1}(933)$"
],
```

defining `933` as a test route, will inform teletype this emergency call is a test and will be reflected as such in the notification.


## Fetch

> GET /v2/accounts/{ACCOUNT_ID}/resources
Expand Down
149 changes: 149 additions & 0 deletions applications/crossbar/priv/api/swagger.json
Expand Up @@ -19857,6 +19857,139 @@
],
"type": "object"
},
"kapi.notifications.emergency_bridge": {
"description": "AMQP API for notifications.emergency_bridge",
"properties": {
"Account-DB": {
"type": "string"
},
"Account-ID": {
"type": "string"
},
"Account-Name": {
"type": "string"
},
"Attachment-URL": {
"type": "string"
},
"Authorizing-ID": {
"type": "string"
},
"Bcc": {
"type": "string"
},
"Call-ID": {
"type": "string"
},
"Cc": {
"type": "string"
},
"Device-ID": {
"type": "string"
},
"Device-Name": {
"type": "string"
},
"Device-Owner-ID": {
"type": "string"
},
"Emergency-Address-City": {
"type": "string"
},
"Emergency-Address-Latitude": {
"type": "string"
},
"Emergency-Address-Longitude": {
"type": "string"
},
"Emergency-Address-Postal-Code": {
"type": "string"
},
"Emergency-Address-Region": {
"type": "string"
},
"Emergency-Address-Street-1": {
"type": "string"
},
"Emergency-Address-Street-2": {
"type": "string"
},
"Emergency-Caller-ID-Name": {
"type": "string"
},
"Emergency-Caller-ID-Number": {
"type": "string"
},
"Emergency-Notfication-Contact-Emails": {
"type": "string"
},
"Emergency-Test-Call": {
"type": "string"
},
"Emergency-To-DID": {
"type": "string"
},
"Event-Category": {
"enum": [
"notification"
],
"type": "string"
},
"Event-Name": {
"enum": [
"emergency_bridge"
],
"type": "string"
},
"From": {
"type": "string"
},
"HTML": {
"type": "string"
},
"Outbound-Caller-ID-Name": {
"type": "string"
},
"Outbound-Caller-ID-Number": {
"type": "string"
},
"Owner-ID": {
"type": "string"
},
"Preview": {
"type": "boolean"
},
"Realm": {
"type": "string"
},
"Reply-To": {
"type": "string"
},
"Subject": {
"type": "string"
},
"Text": {
"type": "string"
},
"To": {
"type": "string"
},
"User-Email": {
"type": "string"
},
"User-First-Name": {
"type": "string"
},
"User-Last-Name": {
"type": "string"
}
},
"required": [
"Account-ID",
"Call-ID"
],
"type": "object"
},
"kapi.notifications.first_occurrence": {
"description": "AMQP API for notifications.first_occurrence",
"properties": {
Expand Down Expand Up @@ -30212,6 +30345,14 @@
"description": "The e911 provisioning system calculated service address longitude",
"type": "string"
},
"notification_contact_emails": {
"default": [],
"description": "A list of email addresses to receive notification when this number places an emergency call",
"items": {
"type": "string"
},
"type": "array"
},
"plus_four": {
"description": "The extended zip/postal code where the number is in service",
"type": "string"
Expand Down Expand Up @@ -31868,6 +32009,14 @@
},
"type": "array"
},
"rules_test": {
"default": [],
"description": "A list of regular expressions of which if matched denotes a test rule",
"items": {
"type": "string"
},
"type": "array"
},
"weight_cost": {
"default": 50,
"description": "A value between 0 and 100 that determines the order of resources when multiple can be used",
Expand Down
@@ -0,0 +1,135 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"_id": "kapi.notifications.emergency_bridge",
"description": "AMQP API for notifications.emergency_bridge",
"properties": {
"Account-DB": {
"type": "string"
},
"Account-ID": {
"type": "string"
},
"Account-Name": {
"type": "string"
},
"Attachment-URL": {
"type": "string"
},
"Authorizing-ID": {
"type": "string"
},
"Bcc": {
"type": "string"
},
"Call-ID": {
"type": "string"
},
"Cc": {
"type": "string"
},
"Device-ID": {
"type": "string"
},
"Device-Name": {
"type": "string"
},
"Device-Owner-ID": {
"type": "string"
},
"Emergency-Address-City": {
"type": "string"
},
"Emergency-Address-Latitude": {
"type": "string"
},
"Emergency-Address-Longitude": {
"type": "string"
},
"Emergency-Address-Postal-Code": {
"type": "string"
},
"Emergency-Address-Region": {
"type": "string"
},
"Emergency-Address-Street-1": {
"type": "string"
},
"Emergency-Address-Street-2": {
"type": "string"
},
"Emergency-Caller-ID-Name": {
"type": "string"
},
"Emergency-Caller-ID-Number": {
"type": "string"
},
"Emergency-Notfication-Contact-Emails": {
"type": "string"
},
"Emergency-Test-Call": {
"type": "string"
},
"Emergency-To-DID": {
"type": "string"
},
"Event-Category": {
"enum": [
"notification"
],
"type": "string"
},
"Event-Name": {
"enum": [
"emergency_bridge"
],
"type": "string"
},
"From": {
"type": "string"
},
"HTML": {
"type": "string"
},
"Outbound-Caller-ID-Name": {
"type": "string"
},
"Outbound-Caller-ID-Number": {
"type": "string"
},
"Owner-ID": {
"type": "string"
},
"Preview": {
"type": "boolean"
},
"Realm": {
"type": "string"
},
"Reply-To": {
"type": "string"
},
"Subject": {
"type": "string"
},
"Text": {
"type": "string"
},
"To": {
"type": "string"
},
"User-Email": {
"type": "string"
},
"User-First-Name": {
"type": "string"
},
"User-Last-Name": {
"type": "string"
}
},
"required": [
"Account-ID",
"Call-ID"
],
"type": "object"
}
8 changes: 8 additions & 0 deletions applications/crossbar/priv/couchdb/schemas/phone_numbers.json
Expand Up @@ -89,6 +89,14 @@
"description": "The e911 provisioning system calculated service address longitude",
"type": "string"
},
"notification_contact_emails": {
"default": [],
"description": "A list of email addresses to receive notification when this number places an emergency call",
"items": {
"type": "string"
},
"type": "array"
},
"plus_four": {
"description": "The extended zip/postal code where the number is in service",
"type": "string"
Expand Down
8 changes: 8 additions & 0 deletions applications/crossbar/priv/couchdb/schemas/resources.json
Expand Up @@ -418,6 +418,14 @@
},
"type": "array"
},
"rules_test": {
"default": [],
"description": "A list of regular expressions of which if matched denotes a test rule",
"items": {
"type": "string"
},
"type": "array"
},
"weight_cost": {
"default": 50,
"description": "A value between 0 and 100 that determines the order of resources when multiple can be used",
Expand Down

0 comments on commit 0e7e374

Please sign in to comment.