@framers/agentos 0.10.26 → 0.10.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,17 +22,20 @@
22
22
  *
23
23
  * ## Webhook verification: HMAC-SHA256 + nonce (v3 scheme)
24
24
  *
25
- * Plivo's v3 webhook signature scheme:
26
- *
27
- * 1. Plivo generates a random `nonce` and includes it in the
28
- * `X-Plivo-Signature-V3-Nonce` header.
29
- * 2. The signed data is: `{fullRequestURL}{nonce}` (concatenated, no separator).
30
- * 3. Compute `HMAC-SHA256(authToken, signedData)`.
31
- * 4. Base64-encode the HMAC digest.
32
- * 5. Compare the result with the `X-Plivo-Signature-V3` header.
33
- *
34
- * Note: Unlike Twilio's scheme, Plivo does NOT include the POST body in the
35
- * signed data -- only the URL and nonce. The nonce prevents replay attacks.
25
+ * Plivo's v3 signature covers the method, the URL, its query and the POST
26
+ * fields (see {@link computePlivoV3Signature}). The nonce arrives in
27
+ * `X-Plivo-Signature-V3-Nonce` and the signature in `X-Plivo-Signature-V3`
28
+ * (or `X-Plivo-Signature-Ma-V3`, signed with the main account's token), which
29
+ * may list several signatures separated by commas.
30
+ *
31
+ * Plivo's SDKs build the signed text differently in three places:
32
+ * plivo-python (`plivo/utils/signature_v3.py`) decodes the query one
33
+ * character per byte, writes JSON values with Python's `str()` and sorts by
34
+ * code point; plivo-node decodes the query as UTF-8, writes JSON values with
35
+ * `String()` and sorts by UTF-16 code unit. Plivo does not document which its
36
+ * servers match, so a signature over either text is accepted (see
37
+ * {@link PlivoCanonicalStyle}). For ASCII callbacks with string fields the two
38
+ * texts are the same.
36
39
  *
37
40
  * ## DTMF via `<GetDigits>` XML pattern
38
41
  *
@@ -78,6 +81,63 @@ export interface PlivoVoiceProviderConfig {
78
81
  */
79
82
  fetchImpl?: typeof fetch;
80
83
  }
84
+ /** A webhook field's value: one string, a repeated field's values, or a nested object. */
85
+ export type PlivoParamValue = string | string[] | PlivoParams;
86
+ /** Webhook fields by name, as {@link computePlivoV3Signature} signs them. */
87
+ export interface PlivoParams {
88
+ [key: string]: PlivoParamValue;
89
+ }
90
+ /**
91
+ * Which SDK's signed text to build.
92
+ *
93
+ * - `'python'`: as plivo-python 4.63 builds it on Python 3.12 and later. The
94
+ * query is decoded one character per byte (`caf%C3%A9` reads `café`), JSON
95
+ * values are written with `str()` (`True`, `None`, `1.0`, `1e-07`) and keys
96
+ * and repeated values are sorted by code point, as `sorted()` does.
97
+ * - `'js'`: JavaScript's text, which is plivo-node's for flat bodies of
98
+ * strings, numbers and booleans. The query is decoded as UTF-8, JSON values
99
+ * are written with `String()` (`true`, `null`, `1`, `1e-7`) and sorting is by
100
+ * UTF-16 code unit, JavaScript's default. plivo-node throws on a JSON null
101
+ * and writes a nested object as `[object Object]`; this style writes `null`
102
+ * and signs nested fields like plivo-python, so no field goes unsigned.
103
+ */
104
+ export type PlivoCanonicalStyle = 'python' | 'js';
105
+ /**
106
+ * Plivo's v3 webhook signature, computed as plivo-python
107
+ * (`plivo/utils/signature_v3.py`) computes it by default: base64 of
108
+ * HMAC-SHA256 with the auth token over `{base}.{nonce}`.
109
+ *
110
+ * - GET: `base` is the URL without its query, then `?` and the query as
111
+ * sorted `key=value` pairs when there is one.
112
+ * - POST: `base` is the URL without its query; when the body has fields, `?`,
113
+ * the sorted query (and `.` when there is a query), then every field as
114
+ * `key` + `value` sorted by key. With no fields it is the GET form.
115
+ *
116
+ * @param method - The request method (GET or POST).
117
+ * @param url - The full URL Plivo requested.
118
+ * @param nonce - The `X-Plivo-Signature-V3-Nonce` header.
119
+ * @param authToken - The (sub)account auth token.
120
+ * @param params - The POST fields as text; ignored for GET. A JSON body's
121
+ * values must already be written in `style` (as the provider's verifier
122
+ * writes them).
123
+ * @param style - Which SDK's text to build: how the query is decoded and how
124
+ * keys and repeated values are sorted (see {@link PlivoCanonicalStyle}).
125
+ * @returns The base64 signature.
126
+ * @throws RangeError when the fields sign to more than
127
+ * {@link MAX_PLIVO_SIGNED_FIELDS_LENGTH} characters.
128
+ */
129
+ export declare function computePlivoV3Signature(method: string, url: string, nonce: string, authToken: string, params?: PlivoParams, style?: PlivoCanonicalStyle): string;
130
+ /**
131
+ * A finite float as Python's repr writes it: the shortest digits that read
132
+ * back to the same value (the digits JavaScript's toExponential() gives), in
133
+ * fixed notation with at least one fractional digit when the decimal point
134
+ * sits from 4 places left of the first digit up to 16 places right of it,
135
+ * otherwise as `d.ddde±XX`.
136
+ *
137
+ * @param value - The number.
138
+ * @returns Python's repr of the float.
139
+ */
140
+ export declare function pythonFloatRepr(value: number): string;
81
141
  /**
82
142
  * Plivo voice call provider.
83
143
  *
@@ -110,25 +170,22 @@ export declare class PlivoVoiceProvider implements IVoiceCallProvider {
110
170
  /**
111
171
  * Verify an incoming Plivo webhook request using HMAC-SHA256 (v3 scheme).
112
172
  *
113
- * ## Algorithm (step by step)
114
- *
115
- * 1. Extract the `X-Plivo-Signature-V3-Nonce` and `X-Plivo-Signature-V3` headers.
116
- * 2. Build the signed data string: `{fullRequestURL}{nonce}`.
117
- * Note: the POST body is NOT included in the signed data (unlike Twilio).
118
- * 3. Compute `HMAC-SHA256(authToken, signedData)`.
119
- * 4. Base64-encode the digest.
120
- * 5. Compare with the `X-Plivo-Signature-V3` header.
173
+ * Computes {@link computePlivoV3Signature} over the request's method, URL
174
+ * and fields (read by {@link readPlivoRequest}, as `parseWebhookEvent`
175
+ * reads them) in both SDKs' texts (see {@link PlivoCanonicalStyle}) and
176
+ * compares each in constant time with every signature listed in
177
+ * `X-Plivo-Signature-V3` and `X-Plivo-Signature-Ma-V3`.
121
178
  *
122
179
  * @param ctx - Raw webhook request context.
123
- * @returns Verification result with `valid: true` if the signature matches.
180
+ * @returns Verification result with `valid: true` if a signature matches.
124
181
  */
125
182
  verifyWebhook(ctx: WebhookContext): WebhookVerificationResult;
126
183
  /**
127
- * Parse a Plivo webhook body into normalized {@link NormalizedCallEvent}s.
184
+ * Parse a Plivo webhook into normalized {@link NormalizedCallEvent}s.
128
185
  *
129
- * Plivo sends most webhooks with URL-encoded bodies, but some callbacks
130
- * may arrive as JSON. This parser handles both formats by inspecting
131
- * whether the body starts with `{` (JSON) or not (form-encoded).
186
+ * Fields come from {@link readPlivoRequest} and {@link plivoEventFields},
187
+ * as the signature check reads them: a GET callback's query, otherwise the
188
+ * URL-encoded or JSON body.
132
189
  *
133
190
  * Plivo uses two naming conventions for the same fields:
134
191
  * - PascalCase (`CallUUID`, `CallStatus`, `Digits`) in URL callbacks.
@@ -1 +1 @@
1
- {"version":3,"file":"plivo.d.ts","sourceRoot":"","sources":["../../../../../src/io/channels/telephony/providers/plivo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAIH,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,cAAc,EACd,yBAAyB,EACzB,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAMrB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,kBAAmB,YAAW,kBAAkB;IAC3D,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IAEjC,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAElD,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC;;OAEG;gBACS,MAAM,EAAE,wBAAwB;IAW5C;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB;IAoB7D;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,kBAAkB;IAkE1D;;;;;;;;;OASG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0BzE;;;;;;;;OAQG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvD;;;;;;;OAOG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBlD"}
1
+ {"version":3,"file":"plivo.d.ts","sourceRoot":"","sources":["../../../../../src/io/channels/telephony/providers/plivo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAIH,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,cAAc,EACd,yBAAyB,EACzB,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAMrB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAMD,0FAA0F;AAC1F,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,WAAW,CAAC;AAE9D,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;CAChC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,IAAI,CAAC;AAgLlD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,WAAgB,EACxB,KAAK,GAAE,mBAA8B,GACpC,MAAM,CAWR;AAqSD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBrD;AAsDD;;;;;;;;;;;;;GAaG;AACH,qBAAa,kBAAmB,YAAW,kBAAkB;IAC3D,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IAEjC,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAElD,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC;;OAEG;gBACS,MAAM,EAAE,wBAAwB;IAW5C;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB;IA4C7D;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,kBAAkB;IA4D1D;;;;;;;;;OASG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0BzE;;;;;;;;OAQG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvD;;;;;;;OAOG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBlD"}