@wildo-ai/external-connectors-models 1.1.11 → 1.1.13
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.
- package/dist/esm/companion-exports.d.ts.map +1 -1
- package/dist/esm/companion-exports.js.map +1 -1
- package/dist/esm/core/commons.external-connectors-models.schemas.d.ts +10 -0
- package/dist/esm/core/commons.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/core/commons.external-connectors-models.schemas.js +10 -0
- package/dist/esm/core/commons.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/core/oauth2.enums.d.ts.map +1 -1
- package/dist/esm/core/oauth2.enums.js.map +1 -1
- package/dist/esm/core/operation-classification.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/core/operation-classification.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/core/operations.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/core/operations.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/core/security.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/core/security.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.d.ts +20 -46
- package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.js +34 -5
- package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/billing.standard-interface.schemas.d.ts +56 -3
- package/dist/esm/protocols/billing.standard-interface.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/billing.standard-interface.schemas.js +15 -2
- package/dist/esm/protocols/billing.standard-interface.schemas.js.map +1 -1
- package/dist/esm/protocols/content-safety.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/content-safety.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/document-extraction.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/document-extraction.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/electronic-signature.external-connectors-models.schemas.d.ts +157 -0
- package/dist/esm/protocols/electronic-signature.external-connectors-models.schemas.d.ts.map +1 -0
- package/dist/esm/protocols/electronic-signature.external-connectors-models.schemas.js +134 -0
- package/dist/esm/protocols/electronic-signature.external-connectors-models.schemas.js.map +1 -0
- package/dist/esm/protocols/email-inbound.standard-interface.schemas.d.ts +85 -0
- package/dist/esm/protocols/email-inbound.standard-interface.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/email-inbound.standard-interface.schemas.js +46 -2
- package/dist/esm/protocols/email-inbound.standard-interface.schemas.js.map +1 -1
- package/dist/esm/protocols/email.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/email.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/email.standard-interface.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/email.standard-interface.schemas.js.map +1 -1
- package/dist/esm/protocols/embeddings.external-connectors-models.schemas.d.ts +49 -6
- package/dist/esm/protocols/embeddings.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/embeddings.external-connectors-models.schemas.js +89 -6
- package/dist/esm/protocols/embeddings.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/file-storage.standard-interface.d.ts +9 -2
- package/dist/esm/protocols/file-storage.standard-interface.d.ts.map +1 -1
- package/dist/esm/protocols/file-storage.standard-interface.js +6 -0
- package/dist/esm/protocols/file-storage.standard-interface.js.map +1 -1
- package/dist/esm/protocols/frontend.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/frontend.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/graphql-operations.external-connectors-models.schemas.d.ts +254 -0
- package/dist/esm/protocols/graphql-operations.external-connectors-models.schemas.d.ts.map +1 -0
- package/dist/esm/protocols/graphql-operations.external-connectors-models.schemas.js +480 -0
- package/dist/esm/protocols/graphql-operations.external-connectors-models.schemas.js.map +1 -0
- package/dist/esm/protocols/hooks-capability.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/hooks-capability.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/hooks.external-connectors-models.schemas.d.ts +95 -1
- package/dist/esm/protocols/hooks.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/hooks.external-connectors-models.schemas.js +110 -0
- package/dist/esm/protocols/hooks.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/image.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/image.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/llm.external-connectors-models.schemas.d.ts +95 -3
- package/dist/esm/protocols/llm.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/llm.external-connectors-models.schemas.js +147 -15
- package/dist/esm/protocols/llm.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/oauth2-provider-assurance.definitions.d.ts.map +1 -1
- package/dist/esm/protocols/oauth2-provider-assurance.definitions.js.map +1 -1
- package/dist/esm/protocols/oauth2-provider-assurance.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/oauth2-provider-assurance.schemas.js.map +1 -1
- package/dist/esm/protocols/oauth2.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/oauth2.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/provider-configuration-authoring.external-connectors-models.schemas.d.ts +52 -0
- package/dist/esm/protocols/provider-configuration-authoring.external-connectors-models.schemas.d.ts.map +1 -0
- package/dist/esm/protocols/provider-configuration-authoring.external-connectors-models.schemas.js +132 -0
- package/dist/esm/protocols/provider-configuration-authoring.external-connectors-models.schemas.js.map +1 -0
- package/dist/esm/protocols/provider-connection-parameters.external-connectors-models.d.ts +111 -0
- package/dist/esm/protocols/provider-connection-parameters.external-connectors-models.d.ts.map +1 -0
- package/dist/esm/protocols/provider-connection-parameters.external-connectors-models.js +203 -0
- package/dist/esm/protocols/provider-connection-parameters.external-connectors-models.js.map +1 -0
- package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.d.ts +6 -0
- package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.d.ts.map +1 -1
- package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.js +13 -7
- package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.js.map +1 -1
- package/dist/esm/protocols/provider-vendor-registration.external-connectors-models.d.ts +50 -0
- package/dist/esm/protocols/provider-vendor-registration.external-connectors-models.d.ts.map +1 -0
- package/dist/esm/protocols/provider-vendor-registration.external-connectors-models.js +30 -0
- package/dist/esm/protocols/provider-vendor-registration.external-connectors-models.js.map +1 -0
- package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.d.ts +730 -17
- package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.js +822 -20
- package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/service-account-token.external-connectors-models.schemas.d.ts +73 -0
- package/dist/esm/protocols/service-account-token.external-connectors-models.schemas.d.ts.map +1 -0
- package/dist/esm/protocols/service-account-token.external-connectors-models.schemas.js +82 -0
- package/dist/esm/protocols/service-account-token.external-connectors-models.schemas.js.map +1 -0
- package/dist/esm/protocols/sms.external-connectors-models.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/sms.external-connectors-models.schemas.js.map +1 -1
- package/dist/esm/protocols/sms.standard-interface.schemas.d.ts +79 -1
- package/dist/esm/protocols/sms.standard-interface.schemas.d.ts.map +1 -1
- package/dist/esm/protocols/sms.standard-interface.schemas.js +93 -0
- package/dist/esm/protocols/sms.standard-interface.schemas.js.map +1 -1
- package/dist/esm/protocols/subject-erasure-effect.standard-interface.d.ts.map +1 -1
- package/dist/esm/protocols/subject-erasure-effect.standard-interface.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/dist/esm/.native.tsbuildinfo +0 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An AI provider that authenticates with a SERVICE ACCOUNT rather than a static API key (#3425): the deployment holds
|
|
3
|
+
* the account's key, and the engine exchanges it for a short-lived bearer token at a token endpoint the contract
|
|
4
|
+
* declares. Google Vertex AI is the first: the enterprise route to Gemini authenticates only this way (its API-key
|
|
5
|
+
* "express mode" is a Preview limited to `@gmail.com` accounts).
|
|
6
|
+
*
|
|
7
|
+
* The token endpoint is a SECOND outbound host of the provider, so it is declared on the contract (`tokenUrl`,
|
|
8
|
+
* `tokenHosts`) and nothing else is ever sent the signed assertion: not a `token_uri` the key file names, not a host a
|
|
9
|
+
* caller supplies. That is why a service-account key in the plain API-key slot was rejected: it would have hidden the
|
|
10
|
+
* second host and a credential format the engine does not know inside a string handed to the vendor's SDK.
|
|
11
|
+
*/
|
|
12
|
+
import { ProviderClientAssertionSigningAlgorithm } from './rest-operations.external-connectors-models.schemas';
|
|
13
|
+
/**
|
|
14
|
+
* The format of the service-account key a {@link ProviderServiceAccountTokenGrant} reads from the arm's `apiKey` slot.
|
|
15
|
+
* Each format names where the key's issuer, private key and key id sit; a member joins with the vendor that needs it.
|
|
16
|
+
*/
|
|
17
|
+
export declare enum ProviderServiceAccountKeyFormat {
|
|
18
|
+
/**
|
|
19
|
+
* A Google Cloud service-account key file, as downloaded from the console: a JSON object whose `client_email` is the
|
|
20
|
+
* assertion's issuer, whose `private_key` is a PKCS#8 PEM, and whose `private_key_id` is the key id. Its `token_uri`
|
|
21
|
+
* is NOT read: the token endpoint is the contract's.
|
|
22
|
+
* spec-cite: Google Identity, "Using OAuth 2.0 for Server to Server Applications"
|
|
23
|
+
* (https://developers.google.com/identity/protocols/oauth2/service-account, fetched 2026-11-09) — `iss`: "The email
|
|
24
|
+
* address of the service account"; "You can find this value in the `client_email` field of your service account JSON
|
|
25
|
+
* file"; the key id "in the `private_key_id` field of your service account JSON file".
|
|
26
|
+
*/
|
|
27
|
+
GOOGLE_SERVICE_ACCOUNT_JSON = "google_service_account_json"
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The JWT-bearer grant (RFC 7523 §2.1) that turns a service-account key into a bearer token for an AI arm (#3425).
|
|
31
|
+
*
|
|
32
|
+
* The engine reads the key from the arm's `apiKey.secretRef` slot, signs an assertion (`iss` the account, `scope`, `aud`
|
|
33
|
+
* the token URL, `iat`, `exp`), posts `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=…` to
|
|
34
|
+
* `tokenUrl`, caches the token until a minute before it expires, and hands the TOKEN to the arm's `sdkFactory` as its
|
|
35
|
+
* first argument. The factory sends it as `Authorization: Bearer`; it never sees the key.
|
|
36
|
+
*
|
|
37
|
+
* spec-cite: RFC 7523 §2.1 — "The value of the "grant_type" is "urn:ietf:params:oauth:grant-type:jwt-bearer"."; Google
|
|
38
|
+
* Identity, "Using OAuth 2.0 for Server to Server Applications"
|
|
39
|
+
* (https://developers.google.com/identity/protocols/oauth2/service-account, fetched 2026-11-09) — "Algorithm is
|
|
40
|
+
* mandatory, and has only one value: `"alg": "RS256"`"; `scope`: "A space-delimited list of the permissions that the
|
|
41
|
+
* application requests"; `aud`: "When making an access token request this value is always
|
|
42
|
+
* `https://oauth2.googleapis.com/token`"; `exp`: "This value has a maximum of 1 hour after the issued time".
|
|
43
|
+
*/
|
|
44
|
+
export interface ProviderServiceAccountTokenGrant {
|
|
45
|
+
/** How the key in the `apiKey` slot is laid out. */
|
|
46
|
+
readonly keyFormat: ProviderServiceAccountKeyFormat;
|
|
47
|
+
/** The https token endpoint, which is also the assertion's audience. */
|
|
48
|
+
readonly tokenUrl: string;
|
|
49
|
+
/** The hosts the token endpoint may be on. The assertion is sent nowhere else. */
|
|
50
|
+
readonly tokenHosts: readonly string[];
|
|
51
|
+
/** The `scope` claim, space-delimited, as written. */
|
|
52
|
+
readonly scope: string;
|
|
53
|
+
/** The algorithm the account's key signs with. Google's is RS256 only. */
|
|
54
|
+
readonly algorithm: ProviderClientAssertionSigningAlgorithm;
|
|
55
|
+
/** Seconds until the assertion's `exp`; omitted, 300; at most 3600. */
|
|
56
|
+
readonly assertionLifetimeSeconds?: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A value a deployment parameter may hold (#3425): a project id, a region name. It is placed into the vendor's request
|
|
60
|
+
* path by the module (`/v1/projects/{project}/locations/{location}/…`), so nothing that can leave a path segment is
|
|
61
|
+
* admitted.
|
|
62
|
+
*/
|
|
63
|
+
export declare const PROVIDER_DEPLOYMENT_PARAMETER_VALUE_SHAPE: RegExp;
|
|
64
|
+
/**
|
|
65
|
+
* Why an AI arm's credential declaration cannot be honoured, or an empty list (#3425): the service-account grant
|
|
66
|
+
* (an https token URL on a declared DNS host, a scope, a known key format and algorithm, a bounded assertion lifetime)
|
|
67
|
+
* and the deployment parameters (named like identifiers, each read from a non-empty slot name).
|
|
68
|
+
*/
|
|
69
|
+
export declare function describeProviderAiCredentialDefects(arm: {
|
|
70
|
+
readonly serviceAccountToken?: ProviderServiceAccountTokenGrant;
|
|
71
|
+
readonly deploymentParameterEnvVarNames?: Readonly<Record<string, string>>;
|
|
72
|
+
}): string[];
|
|
73
|
+
//# sourceMappingURL=service-account-token.external-connectors-models.schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-account-token.external-connectors-models.schemas.d.ts","sourceRoot":"","sources":["../../../src/protocols/service-account-token.external-connectors-models.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,uCAAuC,EAAwF,MAAM,sDAAsD,CAAC;AAErM;;;GAGG;AACH,oBAAY,+BAA+B;IACzC;;;;;;;;OAQG;IACH,2BAA2B,gCAAgC;CAC5D;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,gCAAgC;IAC/C,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,+BAA+B,CAAC;IACpD,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kFAAkF;IAClF,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,uCAAuC,CAAC;IAC5D,uEAAuE;IACvE,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;CAC5C;AAED;;;;GAIG;AACH,eAAO,MAAM,yCAAyC,QAAuD,CAAC;AAK9G;;;;GAIG;AACH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE;IACvD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,gCAAgC,CAAC;IAChE,QAAQ,CAAC,8BAA8B,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC5E,GAAG,MAAM,EAAE,CA6BX"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An AI provider that authenticates with a SERVICE ACCOUNT rather than a static API key (#3425): the deployment holds
|
|
3
|
+
* the account's key, and the engine exchanges it for a short-lived bearer token at a token endpoint the contract
|
|
4
|
+
* declares. Google Vertex AI is the first: the enterprise route to Gemini authenticates only this way (its API-key
|
|
5
|
+
* "express mode" is a Preview limited to `@gmail.com` accounts).
|
|
6
|
+
*
|
|
7
|
+
* The token endpoint is a SECOND outbound host of the provider, so it is declared on the contract (`tokenUrl`,
|
|
8
|
+
* `tokenHosts`) and nothing else is ever sent the signed assertion: not a `token_uri` the key file names, not a host a
|
|
9
|
+
* caller supplies. That is why a service-account key in the plain API-key slot was rejected: it would have hidden the
|
|
10
|
+
* second host and a credential format the engine does not know inside a string handed to the vendor's SDK.
|
|
11
|
+
*/
|
|
12
|
+
import { ProviderClientAssertionSigningAlgorithm, PROVIDER_CLIENT_ASSERTION_MAXIMUM_LIFETIME_SECONDS, PROVIDER_OAUTH2_DNS_NAME_PATTERN } from './rest-operations.external-connectors-models.schemas.js';
|
|
13
|
+
/**
|
|
14
|
+
* The format of the service-account key a {@link ProviderServiceAccountTokenGrant} reads from the arm's `apiKey` slot.
|
|
15
|
+
* Each format names where the key's issuer, private key and key id sit; a member joins with the vendor that needs it.
|
|
16
|
+
*/
|
|
17
|
+
export var ProviderServiceAccountKeyFormat;
|
|
18
|
+
(function (ProviderServiceAccountKeyFormat) {
|
|
19
|
+
/**
|
|
20
|
+
* A Google Cloud service-account key file, as downloaded from the console: a JSON object whose `client_email` is the
|
|
21
|
+
* assertion's issuer, whose `private_key` is a PKCS#8 PEM, and whose `private_key_id` is the key id. Its `token_uri`
|
|
22
|
+
* is NOT read: the token endpoint is the contract's.
|
|
23
|
+
* spec-cite: Google Identity, "Using OAuth 2.0 for Server to Server Applications"
|
|
24
|
+
* (https://developers.google.com/identity/protocols/oauth2/service-account, fetched 2026-11-09) — `iss`: "The email
|
|
25
|
+
* address of the service account"; "You can find this value in the `client_email` field of your service account JSON
|
|
26
|
+
* file"; the key id "in the `private_key_id` field of your service account JSON file".
|
|
27
|
+
*/
|
|
28
|
+
ProviderServiceAccountKeyFormat["GOOGLE_SERVICE_ACCOUNT_JSON"] = "google_service_account_json";
|
|
29
|
+
})(ProviderServiceAccountKeyFormat || (ProviderServiceAccountKeyFormat = {}));
|
|
30
|
+
/**
|
|
31
|
+
* A value a deployment parameter may hold (#3425): a project id, a region name. It is placed into the vendor's request
|
|
32
|
+
* path by the module (`/v1/projects/{project}/locations/{location}/…`), so nothing that can leave a path segment is
|
|
33
|
+
* admitted.
|
|
34
|
+
*/
|
|
35
|
+
export const PROVIDER_DEPLOYMENT_PARAMETER_VALUE_SHAPE = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,126}[A-Za-z0-9])?$/;
|
|
36
|
+
/** A deployment parameter's name, as the module reads it from its factory context. */
|
|
37
|
+
const DEPLOYMENT_PARAMETER_NAME_SHAPE = /^[a-z][A-Za-z0-9]{0,31}$/;
|
|
38
|
+
/**
|
|
39
|
+
* Why an AI arm's credential declaration cannot be honoured, or an empty list (#3425): the service-account grant
|
|
40
|
+
* (an https token URL on a declared DNS host, a scope, a known key format and algorithm, a bounded assertion lifetime)
|
|
41
|
+
* and the deployment parameters (named like identifiers, each read from a non-empty slot name).
|
|
42
|
+
*/
|
|
43
|
+
export function describeProviderAiCredentialDefects(arm) {
|
|
44
|
+
const defects = [];
|
|
45
|
+
const grant = arm.serviceAccountToken;
|
|
46
|
+
if (grant !== undefined) {
|
|
47
|
+
const formats = Object.values(ProviderServiceAccountKeyFormat);
|
|
48
|
+
if (!formats.includes(grant.keyFormat))
|
|
49
|
+
defects.push(`serviceAccountToken.keyFormat ${JSON.stringify(grant.keyFormat)} is none of ${formats.join(', ')}`);
|
|
50
|
+
const algorithms = Object.values(ProviderClientAssertionSigningAlgorithm);
|
|
51
|
+
if (!algorithms.includes(grant.algorithm))
|
|
52
|
+
defects.push(`serviceAccountToken.algorithm ${JSON.stringify(grant.algorithm)} is none of ${algorithms.join(', ')}`);
|
|
53
|
+
const host = /^https:\/\/([^/:?#]+)(?::\d+)?\//.exec(grant.tokenUrl)?.[1]?.toLowerCase();
|
|
54
|
+
if (host === undefined)
|
|
55
|
+
defects.push(`serviceAccountToken.tokenUrl '${grant.tokenUrl}' is not an https URL with a path`);
|
|
56
|
+
if (/[{}]/.test(grant.tokenUrl))
|
|
57
|
+
defects.push(`serviceAccountToken.tokenUrl '${grant.tokenUrl}' carries a placeholder`);
|
|
58
|
+
if (grant.tokenHosts.length === 0)
|
|
59
|
+
defects.push('serviceAccountToken.tokenHosts admits no host');
|
|
60
|
+
for (const tokenHost of grant.tokenHosts) {
|
|
61
|
+
if (!PROVIDER_OAUTH2_DNS_NAME_PATTERN.test(tokenHost.toLowerCase()))
|
|
62
|
+
defects.push(`serviceAccountToken.tokenHosts names '${tokenHost}', which is not a DNS name`);
|
|
63
|
+
}
|
|
64
|
+
if (host !== undefined && !grant.tokenHosts.some((tokenHost) => tokenHost.toLowerCase() === host)) {
|
|
65
|
+
defects.push(`serviceAccountToken.tokenUrl is on '${host}', which tokenHosts does not admit`);
|
|
66
|
+
}
|
|
67
|
+
if (grant.scope.trim() === '')
|
|
68
|
+
defects.push('serviceAccountToken.scope is empty');
|
|
69
|
+
if (grant.assertionLifetimeSeconds !== undefined
|
|
70
|
+
&& !(Number.isInteger(grant.assertionLifetimeSeconds) && grant.assertionLifetimeSeconds > 0 && grant.assertionLifetimeSeconds <= PROVIDER_CLIENT_ASSERTION_MAXIMUM_LIFETIME_SECONDS)) {
|
|
71
|
+
defects.push(`serviceAccountToken.assertionLifetimeSeconds is not a whole number of seconds from 1 to ${PROVIDER_CLIENT_ASSERTION_MAXIMUM_LIFETIME_SECONDS}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const [name, envVarName] of Object.entries(arm.deploymentParameterEnvVarNames ?? {})) {
|
|
75
|
+
if (!DEPLOYMENT_PARAMETER_NAME_SHAPE.test(name))
|
|
76
|
+
defects.push(`deploymentParameterEnvVarNames names '${name}', which is not a parameter name`);
|
|
77
|
+
if (envVarName.trim() === '')
|
|
78
|
+
defects.push(`deploymentParameterEnvVarNames '${name}' names no slot`);
|
|
79
|
+
}
|
|
80
|
+
return defects;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=service-account-token.external-connectors-models.schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-account-token.external-connectors-models.schemas.js","sourceRoot":"","sources":["../../../src/protocols/service-account-token.external-connectors-models.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * An AI provider that authenticates with a SERVICE ACCOUNT rather than a static API key (#3425): the deployment holds\n * the account's key, and the engine exchanges it for a short-lived bearer token at a token endpoint the contract\n * declares. Google Vertex AI is the first: the enterprise route to Gemini authenticates only this way (its API-key\n * \"express mode\" is a Preview limited to `@gmail.com` accounts).\n *\n * The token endpoint is a SECOND outbound host of the provider, so it is declared on the contract (`tokenUrl`,\n * `tokenHosts`) and nothing else is ever sent the signed assertion: not a `token_uri` the key file names, not a host a\n * caller supplies. That is why a service-account key in the plain API-key slot was rejected: it would have hidden the\n * second host and a credential format the engine does not know inside a string handed to the vendor's SDK.\n */\n\nimport { ProviderClientAssertionSigningAlgorithm, PROVIDER_CLIENT_ASSERTION_MAXIMUM_LIFETIME_SECONDS, PROVIDER_OAUTH2_DNS_NAME_PATTERN } from './rest-operations.external-connectors-models.schemas';\n\n/**\n * The format of the service-account key a {@link ProviderServiceAccountTokenGrant} reads from the arm's `apiKey` slot.\n * Each format names where the key's issuer, private key and key id sit; a member joins with the vendor that needs it.\n */\nexport enum ProviderServiceAccountKeyFormat {\n /**\n * A Google Cloud service-account key file, as downloaded from the console: a JSON object whose `client_email` is the\n * assertion's issuer, whose `private_key` is a PKCS#8 PEM, and whose `private_key_id` is the key id. Its `token_uri`\n * is NOT read: the token endpoint is the contract's.\n * spec-cite: Google Identity, \"Using OAuth 2.0 for Server to Server Applications\"\n * (https://developers.google.com/identity/protocols/oauth2/service-account, fetched 2026-11-09) — `iss`: \"The email\n * address of the service account\"; \"You can find this value in the `client_email` field of your service account JSON\n * file\"; the key id \"in the `private_key_id` field of your service account JSON file\".\n */\n GOOGLE_SERVICE_ACCOUNT_JSON = 'google_service_account_json',\n}\n\n/**\n * The JWT-bearer grant (RFC 7523 §2.1) that turns a service-account key into a bearer token for an AI arm (#3425).\n *\n * The engine reads the key from the arm's `apiKey.secretRef` slot, signs an assertion (`iss` the account, `scope`, `aud`\n * the token URL, `iat`, `exp`), posts `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=…` to\n * `tokenUrl`, caches the token until a minute before it expires, and hands the TOKEN to the arm's `sdkFactory` as its\n * first argument. The factory sends it as `Authorization: Bearer`; it never sees the key.\n *\n * spec-cite: RFC 7523 §2.1 — \"The value of the \"grant_type\" is \"urn:ietf:params:oauth:grant-type:jwt-bearer\".\"; Google\n * Identity, \"Using OAuth 2.0 for Server to Server Applications\"\n * (https://developers.google.com/identity/protocols/oauth2/service-account, fetched 2026-11-09) — \"Algorithm is\n * mandatory, and has only one value: `\"alg\": \"RS256\"`\"; `scope`: \"A space-delimited list of the permissions that the\n * application requests\"; `aud`: \"When making an access token request this value is always\n * `https://oauth2.googleapis.com/token`\"; `exp`: \"This value has a maximum of 1 hour after the issued time\".\n */\nexport interface ProviderServiceAccountTokenGrant {\n /** How the key in the `apiKey` slot is laid out. */\n readonly keyFormat: ProviderServiceAccountKeyFormat;\n /** The https token endpoint, which is also the assertion's audience. */\n readonly tokenUrl: string;\n /** The hosts the token endpoint may be on. The assertion is sent nowhere else. */\n readonly tokenHosts: readonly string[];\n /** The `scope` claim, space-delimited, as written. */\n readonly scope: string;\n /** The algorithm the account's key signs with. Google's is RS256 only. */\n readonly algorithm: ProviderClientAssertionSigningAlgorithm;\n /** Seconds until the assertion's `exp`; omitted, 300; at most 3600. */\n readonly assertionLifetimeSeconds?: number;\n}\n\n/**\n * A value a deployment parameter may hold (#3425): a project id, a region name. It is placed into the vendor's request\n * path by the module (`/v1/projects/{project}/locations/{location}/…`), so nothing that can leave a path segment is\n * admitted.\n */\nexport const PROVIDER_DEPLOYMENT_PARAMETER_VALUE_SHAPE = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,126}[A-Za-z0-9])?$/;\n\n/** A deployment parameter's name, as the module reads it from its factory context. */\nconst DEPLOYMENT_PARAMETER_NAME_SHAPE = /^[a-z][A-Za-z0-9]{0,31}$/;\n\n/**\n * Why an AI arm's credential declaration cannot be honoured, or an empty list (#3425): the service-account grant\n * (an https token URL on a declared DNS host, a scope, a known key format and algorithm, a bounded assertion lifetime)\n * and the deployment parameters (named like identifiers, each read from a non-empty slot name).\n */\nexport function describeProviderAiCredentialDefects(arm: {\n readonly serviceAccountToken?: ProviderServiceAccountTokenGrant;\n readonly deploymentParameterEnvVarNames?: Readonly<Record<string, string>>;\n}): string[] {\n const defects: string[] = [];\n const grant = arm.serviceAccountToken;\n if (grant !== undefined) {\n const formats: readonly string[] = Object.values(ProviderServiceAccountKeyFormat);\n if (!formats.includes(grant.keyFormat)) defects.push(`serviceAccountToken.keyFormat ${JSON.stringify(grant.keyFormat)} is none of ${formats.join(', ')}`);\n const algorithms: readonly string[] = Object.values(ProviderClientAssertionSigningAlgorithm);\n if (!algorithms.includes(grant.algorithm)) defects.push(`serviceAccountToken.algorithm ${JSON.stringify(grant.algorithm)} is none of ${algorithms.join(', ')}`);\n const host = /^https:\\/\\/([^/:?#]+)(?::\\d+)?\\//.exec(grant.tokenUrl)?.[1]?.toLowerCase();\n if (host === undefined) defects.push(`serviceAccountToken.tokenUrl '${grant.tokenUrl}' is not an https URL with a path`);\n if (/[{}]/.test(grant.tokenUrl)) defects.push(`serviceAccountToken.tokenUrl '${grant.tokenUrl}' carries a placeholder`);\n if (grant.tokenHosts.length === 0) defects.push('serviceAccountToken.tokenHosts admits no host');\n for (const tokenHost of grant.tokenHosts) {\n if (!PROVIDER_OAUTH2_DNS_NAME_PATTERN.test(tokenHost.toLowerCase())) defects.push(`serviceAccountToken.tokenHosts names '${tokenHost}', which is not a DNS name`);\n }\n if (host !== undefined && !grant.tokenHosts.some((tokenHost) => tokenHost.toLowerCase() === host)) {\n defects.push(`serviceAccountToken.tokenUrl is on '${host}', which tokenHosts does not admit`);\n }\n if (grant.scope.trim() === '') defects.push('serviceAccountToken.scope is empty');\n if (grant.assertionLifetimeSeconds !== undefined\n && !(Number.isInteger(grant.assertionLifetimeSeconds) && grant.assertionLifetimeSeconds > 0 && grant.assertionLifetimeSeconds <= PROVIDER_CLIENT_ASSERTION_MAXIMUM_LIFETIME_SECONDS)) {\n defects.push(`serviceAccountToken.assertionLifetimeSeconds is not a whole number of seconds from 1 to ${PROVIDER_CLIENT_ASSERTION_MAXIMUM_LIFETIME_SECONDS}`);\n }\n }\n for (const [name, envVarName] of Object.entries(arm.deploymentParameterEnvVarNames ?? {})) {\n if (!DEPLOYMENT_PARAMETER_NAME_SHAPE.test(name)) defects.push(`deploymentParameterEnvVarNames names '${name}', which is not a parameter name`);\n if (envVarName.trim() === '') defects.push(`deploymentParameterEnvVarNames '${name}' names no slot`);\n }\n return defects;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sms.external-connectors-models.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"sms.external-connectors-models.schemas.d.ts","sourceRoot":"","sources":["../../../src/protocols/sms.external-connectors-models.schemas.ts"],"names":[],"mappings":"AAsBA;;GAEG;AACH,oBAAY,sBAAsB;IAChC,YAAY,iBAAiB;IAC7B,wBAAwB,6BAA6B;IACrD,iBAAiB,sBAAsB;CACxC;AAED;;GAEG;AACH,oBAAY,wBAAwB;IAClC,QAAQ,aAAa;IACrB,kBAAkB,0BAA0B;CAC7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sms.external-connectors-models.schemas.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"sms.external-connectors-models.schemas.js","sourceRoot":"","sources":["../../../src/protocols/sms.external-connectors-models.schemas.ts"],"names":[],"mappings":"AAKA,kEAAkE;AAClE,eAAe;AACf,WAAW;AACX,mEAAmE;AACnE,+DAA+D;AAC/D,EAAE;AACF,wBAAwB;AACxB,wEAAwE;AACxE,mDAAmD;AACnD,gEAAgE;AAChE,2DAA2D;AAC3D,kEAAkE;AAElE,kEAAkE;AAClE,qBAAqB;AACrB,kEAAkE;AAElE;;GAEG;AACH,MAAM,CAAN,IAAY,sBAIX;AAJD,WAAY,sBAAsB;IAChC,uDAA6B,CAAA;IAC7B,+EAAqD,CAAA;IACrD,iEAAuC,CAAA;AACzC,CAAC,EAJW,sBAAsB,KAAtB,sBAAsB,QAIjC;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,wBAGX;AAHD,WAAY,wBAAwB;IAClC,iDAAqB,CAAA;IACrB,wEAA4C,CAAA;AAC9C,CAAC,EAHW,wBAAwB,KAAxB,wBAAwB,QAGnC","sourcesContent":["import { z } from \"zod\";\nimport {\n ExternalProvider_ExchangeProtocol_Kind,\n } from \"../core/commons.external-connectors-models.schemas\";\n\n// ===============================================================\n// SMS Provider\n// --------\n// Integration with SMS service providers for sending transactional\n// SMS messages (OTP codes, phone verification, notifications).\n//\n// CONFIGURATION LEVELS:\n// - Profile (Provider-level): Fixed by the provider, cannot be changed.\n// Examples: API endpoints, capabilities, limits.\n// - Configuration (Consumer-level): User-configurable settings.\n// Examples: API keys, sender phone number, webhook URLs.\n// ===============================================================\n\n// ===============================================================\n// SMS Provider Enums\n// ===============================================================\n\n/**\n * SMS provider capabilities — what features the provider supports.\n */\nexport enum SMSProvider_Capability {\n SUPPORTS_OTP = \"supports_otp\",\n SUPPORTS_DELIVERY_STATUS = \"supports_delivery_status\",\n SUPPORTS_WEBHOOKS = \"supports_webhooks\",\n}\n\n/**\n * Standard SMS provider operation keys.\n */\nexport enum SMSProvider_OperationKey {\n SEND_SMS = \"sms.send\",\n GET_MESSAGE_STATUS = \"sms.message.getStatus\",\n}\n\n"]}
|
|
@@ -38,13 +38,26 @@ export declare enum SmsProviderCredentialShape {
|
|
|
38
38
|
* the value was `'account-sid-auth-token'` until 2026-09-09, which put one vendor's vocabulary
|
|
39
39
|
* on a contract every SMS provider has to speak.
|
|
40
40
|
*/
|
|
41
|
-
ACCOUNT_ID_AND_SECRET = "account-id-and-secret"
|
|
41
|
+
ACCOUNT_ID_AND_SECRET = "account-id-and-secret",
|
|
42
|
+
/**
|
|
43
|
+
* A single API key, sent as an OAuth 2.0 bearer token: `Authorization: Bearer <key>`. The whole secret is the key,
|
|
44
|
+
* so it carries no account identifier and supplies NO path token: a `sendEndpointPath` naming `{accountId}` is
|
|
45
|
+
* refused by the endpoint composition, as any unfilled token is.
|
|
46
|
+
* spec-cite: RFC 6750 §2.1 (Authorization Request Header Field) — `credentials = "Bearer" 1*SP b64token`.
|
|
47
|
+
*
|
|
48
|
+
* Telnyx's Messaging API v2 is this shape: its OpenAPI description declares `POST /messages` with `bearerAuth` as
|
|
49
|
+
* its only security scheme (#2518 wave 2).
|
|
50
|
+
* spec-cite: Telnyx OpenAPI spec3.json (https://raw.githubusercontent.com/team-telnyx/openapi/c2d3e38858220301d84e5269bc08164873702712/openapi/spec3.json,
|
|
51
|
+
* fetched 2026-11-06) — `POST /messages`, `security: [{ bearerAuth: [] }]`.
|
|
52
|
+
*/
|
|
53
|
+
API_KEY_BEARER = "api-key-bearer"
|
|
42
54
|
}
|
|
43
55
|
export declare const StandardSMS_SendRequestSchema: z.ZodObject<{
|
|
44
56
|
to: z.ZodString;
|
|
45
57
|
from: z.ZodOptional<z.ZodString>;
|
|
46
58
|
body: z.ZodString;
|
|
47
59
|
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
60
|
+
statusCallbackUrl: z.ZodOptional<z.ZodURL>;
|
|
48
61
|
}, z.core.$strip>;
|
|
49
62
|
export type StandardSMS_SendRequest = z.infer<typeof StandardSMS_SendRequestSchema>;
|
|
50
63
|
/**
|
|
@@ -77,6 +90,71 @@ export declare const StandardSMS_SendResponseSchema: z.ZodObject<{
|
|
|
77
90
|
status: z.ZodOptional<z.ZodEnum<typeof SmsDeliveryStatus>>;
|
|
78
91
|
}, z.core.$strip>;
|
|
79
92
|
export type StandardSMS_SendResponse = z.infer<typeof StandardSMS_SendResponseSchema>;
|
|
93
|
+
/**
|
|
94
|
+
* What a verified SMS provider notification reports. A vendor reports both through its webhooks, often to one URL:
|
|
95
|
+
* a change in an outbound message's delivery, and a message a person sent to one of the application's numbers.
|
|
96
|
+
*/
|
|
97
|
+
export declare enum SmsNotificationKind {
|
|
98
|
+
/** An outbound message moved: queued, handed to a carrier, delivered, or failed. */
|
|
99
|
+
DELIVERY_STATUS = "delivery_status",
|
|
100
|
+
/** A person texted one of the application's numbers. */
|
|
101
|
+
INBOUND_MESSAGE = "inbound_message"
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* A change to whether the application may text a number, read from a message the number sent: a STOP (the person
|
|
105
|
+
* withdrew) or a START (they took it back). The engine reads it from every inbound text by the carrier keywords
|
|
106
|
+
* (`classifySmsOptOutKeyword`, `@wildo-ai/saas-models`); some vendors also report their own reading (Twilio's
|
|
107
|
+
* `OptOutType`, under Advanced Opt-Out), which is a second opinion that can only widen an opt-out, never narrow one.
|
|
108
|
+
*/
|
|
109
|
+
export declare enum SmsOptOutChange {
|
|
110
|
+
/** The message withdraws permission to text the number. */
|
|
111
|
+
OPTED_OUT = "opted_out",
|
|
112
|
+
/** The message gives it back after an opt-out. */
|
|
113
|
+
OPTED_IN = "opted_in"
|
|
114
|
+
}
|
|
115
|
+
export declare const StandardSMS_DeliveryStatusNotificationSchema: z.ZodObject<{
|
|
116
|
+
kind: z.ZodLiteral<SmsNotificationKind.DELIVERY_STATUS>;
|
|
117
|
+
providerMessageId: z.ZodString;
|
|
118
|
+
status: z.ZodOptional<z.ZodEnum<typeof SmsDeliveryStatus>>;
|
|
119
|
+
providerStatus: z.ZodString;
|
|
120
|
+
errorCode: z.ZodOptional<z.ZodString>;
|
|
121
|
+
to: z.ZodOptional<z.ZodString>;
|
|
122
|
+
occurredAt: z.ZodOptional<z.ZodDate>;
|
|
123
|
+
}, z.core.$strip>;
|
|
124
|
+
export type StandardSMS_DeliveryStatusNotification = z.infer<typeof StandardSMS_DeliveryStatusNotificationSchema>;
|
|
125
|
+
export declare const StandardSMS_InboundMessageNotificationSchema: z.ZodObject<{
|
|
126
|
+
kind: z.ZodLiteral<SmsNotificationKind.INBOUND_MESSAGE>;
|
|
127
|
+
providerMessageId: z.ZodString;
|
|
128
|
+
from: z.ZodString;
|
|
129
|
+
to: z.ZodString;
|
|
130
|
+
text: z.ZodString;
|
|
131
|
+
reportedOptOutChange: z.ZodOptional<z.ZodEnum<typeof SmsOptOutChange>>;
|
|
132
|
+
occurredAt: z.ZodOptional<z.ZodDate>;
|
|
133
|
+
}, z.core.$strip>;
|
|
134
|
+
export type StandardSMS_InboundMessageNotification = z.infer<typeof StandardSMS_InboundMessageNotificationSchema>;
|
|
135
|
+
/**
|
|
136
|
+
* One verified SMS provider notification, projected onto vendor-neutral terms by the provider's `parseNotification`.
|
|
137
|
+
* The engine re-validates it, so a module that returns a malformed one fails the delivery, which retries and then dies
|
|
138
|
+
* where an operator can replay it.
|
|
139
|
+
*/
|
|
140
|
+
export declare const StandardSMS_NotificationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
141
|
+
kind: z.ZodLiteral<SmsNotificationKind.DELIVERY_STATUS>;
|
|
142
|
+
providerMessageId: z.ZodString;
|
|
143
|
+
status: z.ZodOptional<z.ZodEnum<typeof SmsDeliveryStatus>>;
|
|
144
|
+
providerStatus: z.ZodString;
|
|
145
|
+
errorCode: z.ZodOptional<z.ZodString>;
|
|
146
|
+
to: z.ZodOptional<z.ZodString>;
|
|
147
|
+
occurredAt: z.ZodOptional<z.ZodDate>;
|
|
148
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
149
|
+
kind: z.ZodLiteral<SmsNotificationKind.INBOUND_MESSAGE>;
|
|
150
|
+
providerMessageId: z.ZodString;
|
|
151
|
+
from: z.ZodString;
|
|
152
|
+
to: z.ZodString;
|
|
153
|
+
text: z.ZodString;
|
|
154
|
+
reportedOptOutChange: z.ZodOptional<z.ZodEnum<typeof SmsOptOutChange>>;
|
|
155
|
+
occurredAt: z.ZodOptional<z.ZodDate>;
|
|
156
|
+
}, z.core.$strip>], "kind">;
|
|
157
|
+
export type StandardSMS_Notification = z.infer<typeof StandardSMS_NotificationSchema>;
|
|
80
158
|
export declare const StandardSMS_ErrorSchema: z.ZodObject<{
|
|
81
159
|
code: z.ZodEnum<{
|
|
82
160
|
VALIDATION_ERROR: "VALIDATION_ERROR";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sms.standard-interface.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"sms.standard-interface.schemas.d.ts","sourceRoot":"","sources":["../../../src/protocols/sms.standard-interface.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmBxB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,oBAAY,0BAA0B;IACpC;;;;;;;;;;;;;OAaG;IACH,qBAAqB,0BAA0B;IAC/C;;;;;;;;;;OAUG;IACH,cAAc,mBAAmB;CAClC;AAMD,eAAO,MAAM,6BAA6B;;;;;;iBAuBxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAMpF;;;;;;;;;;;;;GAaG;AACH,oBAAY,iBAAiB;IAC3B,6DAA6D;IAC7D,MAAM,WAAW;IACjB,uDAAuD;IACvD,IAAI,SAAS;IACb,8CAA8C;IAC9C,SAAS,cAAc;IACvB,8FAA8F;IAC9F,MAAM,WAAW;CAClB;AAED,eAAO,MAAM,8BAA8B;;;;iBAMzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAMtF;;;GAGG;AACH,oBAAY,mBAAmB;IAC7B,oFAAoF;IACpF,eAAe,oBAAoB;IACnC,wDAAwD;IACxD,eAAe,oBAAoB;CACpC;AAED;;;;;GAKG;AACH,oBAAY,eAAe;IACzB,2DAA2D;IAC3D,SAAS,cAAc;IACvB,kDAAkD;IAClD,QAAQ,aAAa;CACtB;AAKD,eAAO,MAAM,4CAA4C;;;;;;;;iBAiBvD,CAAC;AACH,MAAM,MAAM,sCAAsC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4CAA4C,CAAC,CAAC;AAElH,eAAO,MAAM,4CAA4C;;;;;;;;iBAcvD,CAAC;AACH,MAAM,MAAM,sCAAsC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4CAA4C,CAAC,CAAC;AAElH;;;;GAIG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;2BAGzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAMtF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;iBAalC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
|
@@ -55,6 +55,18 @@ export var SmsProviderCredentialShape;
|
|
|
55
55
|
* on a contract every SMS provider has to speak.
|
|
56
56
|
*/
|
|
57
57
|
SmsProviderCredentialShape["ACCOUNT_ID_AND_SECRET"] = "account-id-and-secret";
|
|
58
|
+
/**
|
|
59
|
+
* A single API key, sent as an OAuth 2.0 bearer token: `Authorization: Bearer <key>`. The whole secret is the key,
|
|
60
|
+
* so it carries no account identifier and supplies NO path token: a `sendEndpointPath` naming `{accountId}` is
|
|
61
|
+
* refused by the endpoint composition, as any unfilled token is.
|
|
62
|
+
* spec-cite: RFC 6750 §2.1 (Authorization Request Header Field) — `credentials = "Bearer" 1*SP b64token`.
|
|
63
|
+
*
|
|
64
|
+
* Telnyx's Messaging API v2 is this shape: its OpenAPI description declares `POST /messages` with `bearerAuth` as
|
|
65
|
+
* its only security scheme (#2518 wave 2).
|
|
66
|
+
* spec-cite: Telnyx OpenAPI spec3.json (https://raw.githubusercontent.com/team-telnyx/openapi/c2d3e38858220301d84e5269bc08164873702712/openapi/spec3.json,
|
|
67
|
+
* fetched 2026-11-06) — `POST /messages`, `security: [{ bearerAuth: [] }]`.
|
|
68
|
+
*/
|
|
69
|
+
SmsProviderCredentialShape["API_KEY_BEARER"] = "api-key-bearer";
|
|
58
70
|
})(SmsProviderCredentialShape || (SmsProviderCredentialShape = {}));
|
|
59
71
|
// ===============================================================
|
|
60
72
|
// Standard SMS Send Request
|
|
@@ -68,6 +80,16 @@ export const StandardSMS_SendRequestSchema = z.object({
|
|
|
68
80
|
body: z.string().min(1).max(1600),
|
|
69
81
|
/** Metadata for correlation/tracking */
|
|
70
82
|
metadata: z.record(z.string(), z.string()).optional(),
|
|
83
|
+
/**
|
|
84
|
+
* Where the provider should report this message's delivery states (#3394): the engine's own endpoint for the
|
|
85
|
+
* provider's notifications, composed by the ENGINE from the application's public API URL, never by a provider module.
|
|
86
|
+
* Absent when the application serves no such endpoint (the notification half is undeclared or its endpoint is not
|
|
87
|
+
* enabled) or has no public URL; a provider then reports through whatever its account is configured with.
|
|
88
|
+
*
|
|
89
|
+
* A provider whose delivery reports go only where each send asks (Twilio, outside a Messaging Service) passes it on;
|
|
90
|
+
* one whose account-level webhook already carries every report (Telnyx's messaging profile) may ignore it.
|
|
91
|
+
*/
|
|
92
|
+
statusCallbackUrl: z.url().optional(),
|
|
71
93
|
});
|
|
72
94
|
// ===============================================================
|
|
73
95
|
// Standard SMS Send Response
|
|
@@ -105,6 +127,77 @@ export const StandardSMS_SendResponseSchema = z.object({
|
|
|
105
127
|
status: z.enum(SmsDeliveryStatus).optional(),
|
|
106
128
|
});
|
|
107
129
|
// ===============================================================
|
|
130
|
+
// Standard SMS Notification (#3394)
|
|
131
|
+
// ===============================================================
|
|
132
|
+
/**
|
|
133
|
+
* What a verified SMS provider notification reports. A vendor reports both through its webhooks, often to one URL:
|
|
134
|
+
* a change in an outbound message's delivery, and a message a person sent to one of the application's numbers.
|
|
135
|
+
*/
|
|
136
|
+
export var SmsNotificationKind;
|
|
137
|
+
(function (SmsNotificationKind) {
|
|
138
|
+
/** An outbound message moved: queued, handed to a carrier, delivered, or failed. */
|
|
139
|
+
SmsNotificationKind["DELIVERY_STATUS"] = "delivery_status";
|
|
140
|
+
/** A person texted one of the application's numbers. */
|
|
141
|
+
SmsNotificationKind["INBOUND_MESSAGE"] = "inbound_message";
|
|
142
|
+
})(SmsNotificationKind || (SmsNotificationKind = {}));
|
|
143
|
+
/**
|
|
144
|
+
* A change to whether the application may text a number, read from a message the number sent: a STOP (the person
|
|
145
|
+
* withdrew) or a START (they took it back). The engine reads it from every inbound text by the carrier keywords
|
|
146
|
+
* (`classifySmsOptOutKeyword`, `@wildo-ai/saas-models`); some vendors also report their own reading (Twilio's
|
|
147
|
+
* `OptOutType`, under Advanced Opt-Out), which is a second opinion that can only widen an opt-out, never narrow one.
|
|
148
|
+
*/
|
|
149
|
+
export var SmsOptOutChange;
|
|
150
|
+
(function (SmsOptOutChange) {
|
|
151
|
+
/** The message withdraws permission to text the number. */
|
|
152
|
+
SmsOptOutChange["OPTED_OUT"] = "opted_out";
|
|
153
|
+
/** The message gives it back after an opt-out. */
|
|
154
|
+
SmsOptOutChange["OPTED_IN"] = "opted_in";
|
|
155
|
+
})(SmsOptOutChange || (SmsOptOutChange = {}));
|
|
156
|
+
/** E.164: what the engine keys a number on. A provider that receives a number in any other form reports no event. */
|
|
157
|
+
const E164PhoneNumberSchema = z.string().regex(/^\+[1-9]\d{1,14}$/, { error: "Invalid phone number (E.164 format required)" });
|
|
158
|
+
export const StandardSMS_DeliveryStatusNotificationSchema = z.object({
|
|
159
|
+
kind: z.literal(SmsNotificationKind.DELIVERY_STATUS),
|
|
160
|
+
/** The provider's id for the outbound message: the `messageId` its send answered. */
|
|
161
|
+
providerMessageId: z.string().min(1).max(128),
|
|
162
|
+
/**
|
|
163
|
+
* The vendor's state projected onto the framework's. Absent when the vendor's state has no honest projection
|
|
164
|
+
* (Telnyx's `delivery_unconfirmed`), exactly as on the send response.
|
|
165
|
+
*/
|
|
166
|
+
status: z.enum(SmsDeliveryStatus).optional(),
|
|
167
|
+
/** The vendor's own word for the state, kept because the projection collapses several of them. */
|
|
168
|
+
providerStatus: z.string().min(1).max(64),
|
|
169
|
+
/** The vendor's error code on a failure, never its message (a message can quote the number). */
|
|
170
|
+
errorCode: z.string().min(1).max(64).optional(),
|
|
171
|
+
/** The recipient, when the vendor's report names it. */
|
|
172
|
+
to: E164PhoneNumberSchema.optional(),
|
|
173
|
+
/** When the vendor says the change happened. Absent when it does not say (Twilio): the engine uses the receipt instant. */
|
|
174
|
+
occurredAt: z.date().optional(),
|
|
175
|
+
});
|
|
176
|
+
export const StandardSMS_InboundMessageNotificationSchema = z.object({
|
|
177
|
+
kind: z.literal(SmsNotificationKind.INBOUND_MESSAGE),
|
|
178
|
+
/** The provider's id for the received message. */
|
|
179
|
+
providerMessageId: z.string().min(1).max(128),
|
|
180
|
+
/** The person who texted. */
|
|
181
|
+
from: E164PhoneNumberSchema,
|
|
182
|
+
/** The application's number or short code they texted. */
|
|
183
|
+
to: z.string().min(1).max(32),
|
|
184
|
+
/** What they wrote. A concatenated message arrives whole; 1,600 characters is the ten-segment ceiling vendors apply. */
|
|
185
|
+
text: z.string().max(1600),
|
|
186
|
+
/** The vendor's own reading of the message as an opt-out or opt-in, when it reports one. */
|
|
187
|
+
reportedOptOutChange: z.enum(SmsOptOutChange).optional(),
|
|
188
|
+
/** When the vendor received it. Absent when it does not say (Twilio): the engine uses the receipt instant. */
|
|
189
|
+
occurredAt: z.date().optional(),
|
|
190
|
+
});
|
|
191
|
+
/**
|
|
192
|
+
* One verified SMS provider notification, projected onto vendor-neutral terms by the provider's `parseNotification`.
|
|
193
|
+
* The engine re-validates it, so a module that returns a malformed one fails the delivery, which retries and then dies
|
|
194
|
+
* where an operator can replay it.
|
|
195
|
+
*/
|
|
196
|
+
export const StandardSMS_NotificationSchema = z.discriminatedUnion("kind", [
|
|
197
|
+
StandardSMS_DeliveryStatusNotificationSchema,
|
|
198
|
+
StandardSMS_InboundMessageNotificationSchema,
|
|
199
|
+
]);
|
|
200
|
+
// ===============================================================
|
|
108
201
|
// Standard SMS Error
|
|
109
202
|
// ===============================================================
|
|
110
203
|
export const StandardSMS_ErrorSchema = z.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sms.standard-interface.schemas.js","sourceRoot":"","sources":["../../../../src/protocols/sms.standard-interface.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,kEAAkE;AAClE,yBAAyB;AACzB,WAAW;AACX,qEAAqE;AACrE,sEAAsE;AACtE,+BAA+B;AAC/B,EAAE;AACF,qBAAqB;AACrB,qDAAqD;AACrD,6EAA6E;AAC7E,yEAAyE;AACzE,kEAAkE;AAElE,kEAAkE;AAClE,gCAAgC;AAChC,kEAAkE;AAElE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAN,IAAY,0BAgBX;AAhBD,WAAY,0BAA0B;IACpC;;;;;;;;;;;;;OAaG;IACH,6EAA+C,CAAA;AACjD,CAAC,EAhBW,0BAA0B,KAA1B,0BAA0B,QAgBrC;AAED,kEAAkE;AAClE,4BAA4B;AAC5B,kEAAkE;AAElE,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,6CAA6C;IAC7C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,8CAA8C,EAAE,CAAC;IAErG,qFAAqF;IACrF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAE3B,uBAAuB;IACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IAEjC,wCAAwC;IACxC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACtD,CAAC,CAAC;AAGH,kEAAkE;AAClE,6BAA6B;AAC7B,kEAAkE;AAElE;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAN,IAAY,iBASX;AATD,WAAY,iBAAiB;IAC3B,6DAA6D;IAC7D,sCAAiB,CAAA;IACjB,uDAAuD;IACvD,kCAAa,CAAA;IACb,8CAA8C;IAC9C,4CAAuB,CAAA;IACvB,8FAA8F;IAC9F,sCAAiB,CAAA;AACnB,CAAC,EATW,iBAAiB,KAAjB,iBAAiB,QAS5B;AAED,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,mCAAmC;IACnC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,+CAA+C;IAC/C,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC;AAGH,kEAAkE;AAClE,qBAAqB;AACrB,kEAAkE;AAElE,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;QACX,kBAAkB;QAClB,gBAAgB;QAChB,sBAAsB;QACtB,qBAAqB;QACrB,uBAAuB;QACvB,gBAAgB;QAChB,eAAe;KAChB,CAAC;IACF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC","sourcesContent":["import { z } from \"zod\";\n\n// ===============================================================\n// Standard SMS Interface\n// --------\n// This is the canonical interface that Wildo uses internally to send\n// SMS messages. The ETL layer transforms these standard requests into\n// provider-specific API calls.\n//\n// Design Principles:\n// 1. Provider-agnostic - works with any SMS provider\n// 2. Minimal surface area - focused on transactional SMS (OTP, verification)\n// 3. Extensible - new fields can be added without breaking existing code\n// ===============================================================\n\n// ===============================================================\n// SMS Provider Credential Shape\n// ===============================================================\n\n/**\n * How a `kind: SMS` provider's credential bundle is SHAPED, and therefore how the engine parses\n * the resolved secret and authenticates the send request.\n *\n * The engine owns this — not the provider — because parsing a bundle means touching the secret,\n * and a provider module's request builder is a pure function that must never see one. So the\n * contract DECLARES which shape it uses and the engine implements it, exactly as the email arm\n * declares `apiKey.scheme` and lets the engine compose the header.\n *\n * ## Why a single member, and why that is the point\n *\n * One shape has a declarer today. A member is added here only together with its parse-and-\n * authenticate branch in the SMS transport, and that branch is an exhaustive `switch` with a\n * `never` check — so a member added without an implementation fails COMPILATION rather than\n * shipping a provider the engine cannot authenticate. Equally, a second SMS provider whose\n * credential is shaped differently cannot name a member that does not exist: it is refused at\n * declaration time, which is the strongest available form of \"never silently handed Twilio's\".\n *\n * An `'api-key'` member stood here until 2026-09-09 and was pure declaration: no production\n * provider named it, no consumer read it, and no code implemented it — its only use anywhere was\n * one test fixture about an unrelated projection. It was removed rather than implemented, because\n * inventing a header shape for a provider that does not exist is inventing a contract nobody can\n * check.\n */\nexport enum SmsProviderCredentialShape {\n /**\n * A two-part bundle: a non-secret account IDENTIFIER and the secret that authenticates it.\n * The engine authenticates with HTTP Basic — `base64(accountId:secret)` — and makes the\n * account identifier available for substitution into the contract's `sendEndpointPath`.\n *\n * Basic credentials are carried in the `Authorization` header by definition, so the header name\n * is not a per-provider choice and is deliberately not declared.\n * spec-cite: RFC 7617 §2 (The 'Basic' HTTP Authentication Scheme) — the credentials are the\n * base64 of `user-id \":\" password`, transmitted in the `Authorization` header.\n *\n * Twilio's `AccountSid` + `AuthToken` is this shape. The name is deliberately NOT Twilio's:\n * the value was `'account-sid-auth-token'` until 2026-09-09, which put one vendor's vocabulary\n * on a contract every SMS provider has to speak.\n */\n ACCOUNT_ID_AND_SECRET = \"account-id-and-secret\",\n}\n\n// ===============================================================\n// Standard SMS Send Request\n// ===============================================================\n\nexport const StandardSMS_SendRequestSchema = z.object({\n /** Recipient phone number in E.164 format */\n to: z.string().regex(/^\\+?[1-9]\\d{1,14}$/, { error: \"Invalid phone number (E.164 format required)\" }),\n\n /** Sender phone number or short code (optional, uses provider default if not set) */\n from: z.string().optional(),\n\n /** SMS message body */\n body: z.string().min(1).max(1600),\n\n /** Metadata for correlation/tracking */\n metadata: z.record(z.string(), z.string()).optional(),\n});\nexport type StandardSMS_SendRequest = z.infer<typeof StandardSMS_SendRequestSchema>;\n\n// ===============================================================\n// Standard SMS Send Response\n// ===============================================================\n\n/**\n * The delivery states this framework recognises, and the vocabulary a provider's\n * `parseSendResponse` projects its vendor's own states onto.\n *\n * Named rather than left inline because a vendor's vocabulary is LARGER than this one and the\n * mapping between them is the interesting part. Twilio alone reports `accepted`, `scheduled`,\n * `sending`, `undelivered` and `canceled`, none of which is a member here — so the per-member\n * question \"which vendor states land on this one, and why\" needs somewhere to be answered, and an\n * inline `z.enum` has nowhere to put it.\n *\n * The four members are unchanged; this only gives them a home. `.optional()` on the field is what\n * says a provider may report NO state, which is the honest answer for a vendor state this\n * vocabulary does not cover — better than forcing a wrong one.\n */\nexport enum SmsDeliveryStatus {\n /** Accepted by the provider, not yet handed to a carrier. */\n QUEUED = \"queued\",\n /** Handed to a carrier; delivery not yet confirmed. */\n SENT = \"sent\",\n /** The carrier confirmed handset delivery. */\n DELIVERED = \"delivered\",\n /** Terminal failure, whether the provider rejected it or the carrier could not deliver it. */\n FAILED = \"failed\",\n}\n\nexport const StandardSMS_SendResponseSchema = z.object({\n success: z.boolean(),\n /** Provider-assigned message ID */\n messageId: z.string(),\n /** Delivery status if available immediately */\n status: z.enum(SmsDeliveryStatus).optional(),\n});\nexport type StandardSMS_SendResponse = z.infer<typeof StandardSMS_SendResponseSchema>;\n\n// ===============================================================\n// Standard SMS Error\n// ===============================================================\n\nexport const StandardSMS_ErrorSchema = z.object({\n code: z.enum([\n \"VALIDATION_ERROR\",\n \"PROVIDER_ERROR\",\n \"INVALID_PHONE_NUMBER\",\n \"RATE_LIMIT_EXCEEDED\",\n \"AUTHENTICATION_FAILED\",\n \"QUOTA_EXCEEDED\",\n \"UNKNOWN_ERROR\",\n ]),\n message: z.string(),\n provider: z.string().optional(),\n details: z.unknown().optional(),\n});\nexport type StandardSMS_Error = z.infer<typeof StandardSMS_ErrorSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"sms.standard-interface.schemas.js","sourceRoot":"","sources":["../../../src/protocols/sms.standard-interface.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\n// ===============================================================\n// Standard SMS Interface\n// --------\n// This is the canonical interface that Wildo uses internally to send\n// SMS messages. The ETL layer transforms these standard requests into\n// provider-specific API calls.\n//\n// Design Principles:\n// 1. Provider-agnostic - works with any SMS provider\n// 2. Minimal surface area - focused on transactional SMS (OTP, verification)\n// 3. Extensible - new fields can be added without breaking existing code\n// ===============================================================\n\n// ===============================================================\n// SMS Provider Credential Shape\n// ===============================================================\n\n/**\n * How a `kind: SMS` provider's credential bundle is SHAPED, and therefore how the engine parses\n * the resolved secret and authenticates the send request.\n *\n * The engine owns this — not the provider — because parsing a bundle means touching the secret,\n * and a provider module's request builder is a pure function that must never see one. So the\n * contract DECLARES which shape it uses and the engine implements it, exactly as the email arm\n * declares `apiKey.scheme` and lets the engine compose the header.\n *\n * ## Why a single member, and why that is the point\n *\n * One shape has a declarer today. A member is added here only together with its parse-and-\n * authenticate branch in the SMS transport, and that branch is an exhaustive `switch` with a\n * `never` check — so a member added without an implementation fails COMPILATION rather than\n * shipping a provider the engine cannot authenticate. Equally, a second SMS provider whose\n * credential is shaped differently cannot name a member that does not exist: it is refused at\n * declaration time, which is the strongest available form of \"never silently handed Twilio's\".\n *\n * An `'api-key'` member stood here until 2026-09-09 and was pure declaration: no production\n * provider named it, no consumer read it, and no code implemented it — its only use anywhere was\n * one test fixture about an unrelated projection. It was removed rather than implemented, because\n * inventing a header shape for a provider that does not exist is inventing a contract nobody can\n * check.\n */\nexport enum SmsProviderCredentialShape {\n /**\n * A two-part bundle: a non-secret account IDENTIFIER and the secret that authenticates it.\n * The engine authenticates with HTTP Basic — `base64(accountId:secret)` — and makes the\n * account identifier available for substitution into the contract's `sendEndpointPath`.\n *\n * Basic credentials are carried in the `Authorization` header by definition, so the header name\n * is not a per-provider choice and is deliberately not declared.\n * spec-cite: RFC 7617 §2 (The 'Basic' HTTP Authentication Scheme) — the credentials are the\n * base64 of `user-id \":\" password`, transmitted in the `Authorization` header.\n *\n * Twilio's `AccountSid` + `AuthToken` is this shape. The name is deliberately NOT Twilio's:\n * the value was `'account-sid-auth-token'` until 2026-09-09, which put one vendor's vocabulary\n * on a contract every SMS provider has to speak.\n */\n ACCOUNT_ID_AND_SECRET = \"account-id-and-secret\",\n /**\n * A single API key, sent as an OAuth 2.0 bearer token: `Authorization: Bearer <key>`. The whole secret is the key,\n * so it carries no account identifier and supplies NO path token: a `sendEndpointPath` naming `{accountId}` is\n * refused by the endpoint composition, as any unfilled token is.\n * spec-cite: RFC 6750 §2.1 (Authorization Request Header Field) — `credentials = \"Bearer\" 1*SP b64token`.\n *\n * Telnyx's Messaging API v2 is this shape: its OpenAPI description declares `POST /messages` with `bearerAuth` as\n * its only security scheme (#2518 wave 2).\n * spec-cite: Telnyx OpenAPI spec3.json (https://raw.githubusercontent.com/team-telnyx/openapi/c2d3e38858220301d84e5269bc08164873702712/openapi/spec3.json,\n * fetched 2026-11-06) — `POST /messages`, `security: [{ bearerAuth: [] }]`.\n */\n API_KEY_BEARER = \"api-key-bearer\",\n}\n\n// ===============================================================\n// Standard SMS Send Request\n// ===============================================================\n\nexport const StandardSMS_SendRequestSchema = z.object({\n /** Recipient phone number in E.164 format */\n to: z.string().regex(/^\\+?[1-9]\\d{1,14}$/, { error: \"Invalid phone number (E.164 format required)\" }),\n\n /** Sender phone number or short code (optional, uses provider default if not set) */\n from: z.string().optional(),\n\n /** SMS message body */\n body: z.string().min(1).max(1600),\n\n /** Metadata for correlation/tracking */\n metadata: z.record(z.string(), z.string()).optional(),\n\n /**\n * Where the provider should report this message's delivery states (#3394): the engine's own endpoint for the\n * provider's notifications, composed by the ENGINE from the application's public API URL, never by a provider module.\n * Absent when the application serves no such endpoint (the notification half is undeclared or its endpoint is not\n * enabled) or has no public URL; a provider then reports through whatever its account is configured with.\n *\n * A provider whose delivery reports go only where each send asks (Twilio, outside a Messaging Service) passes it on;\n * one whose account-level webhook already carries every report (Telnyx's messaging profile) may ignore it.\n */\n statusCallbackUrl: z.url().optional(),\n});\nexport type StandardSMS_SendRequest = z.infer<typeof StandardSMS_SendRequestSchema>;\n\n// ===============================================================\n// Standard SMS Send Response\n// ===============================================================\n\n/**\n * The delivery states this framework recognises, and the vocabulary a provider's\n * `parseSendResponse` projects its vendor's own states onto.\n *\n * Named rather than left inline because a vendor's vocabulary is LARGER than this one and the\n * mapping between them is the interesting part. Twilio alone reports `accepted`, `scheduled`,\n * `sending`, `undelivered` and `canceled`, none of which is a member here — so the per-member\n * question \"which vendor states land on this one, and why\" needs somewhere to be answered, and an\n * inline `z.enum` has nowhere to put it.\n *\n * The four members are unchanged; this only gives them a home. `.optional()` on the field is what\n * says a provider may report NO state, which is the honest answer for a vendor state this\n * vocabulary does not cover — better than forcing a wrong one.\n */\nexport enum SmsDeliveryStatus {\n /** Accepted by the provider, not yet handed to a carrier. */\n QUEUED = \"queued\",\n /** Handed to a carrier; delivery not yet confirmed. */\n SENT = \"sent\",\n /** The carrier confirmed handset delivery. */\n DELIVERED = \"delivered\",\n /** Terminal failure, whether the provider rejected it or the carrier could not deliver it. */\n FAILED = \"failed\",\n}\n\nexport const StandardSMS_SendResponseSchema = z.object({\n success: z.boolean(),\n /** Provider-assigned message ID */\n messageId: z.string(),\n /** Delivery status if available immediately */\n status: z.enum(SmsDeliveryStatus).optional(),\n});\nexport type StandardSMS_SendResponse = z.infer<typeof StandardSMS_SendResponseSchema>;\n\n// ===============================================================\n// Standard SMS Notification (#3394)\n// ===============================================================\n\n/**\n * What a verified SMS provider notification reports. A vendor reports both through its webhooks, often to one URL:\n * a change in an outbound message's delivery, and a message a person sent to one of the application's numbers.\n */\nexport enum SmsNotificationKind {\n /** An outbound message moved: queued, handed to a carrier, delivered, or failed. */\n DELIVERY_STATUS = \"delivery_status\",\n /** A person texted one of the application's numbers. */\n INBOUND_MESSAGE = \"inbound_message\",\n}\n\n/**\n * A change to whether the application may text a number, read from a message the number sent: a STOP (the person\n * withdrew) or a START (they took it back). The engine reads it from every inbound text by the carrier keywords\n * (`classifySmsOptOutKeyword`, `@wildo-ai/saas-models`); some vendors also report their own reading (Twilio's\n * `OptOutType`, under Advanced Opt-Out), which is a second opinion that can only widen an opt-out, never narrow one.\n */\nexport enum SmsOptOutChange {\n /** The message withdraws permission to text the number. */\n OPTED_OUT = \"opted_out\",\n /** The message gives it back after an opt-out. */\n OPTED_IN = \"opted_in\",\n}\n\n/** E.164: what the engine keys a number on. A provider that receives a number in any other form reports no event. */\nconst E164PhoneNumberSchema = z.string().regex(/^\\+[1-9]\\d{1,14}$/, { error: \"Invalid phone number (E.164 format required)\" });\n\nexport const StandardSMS_DeliveryStatusNotificationSchema = z.object({\n kind: z.literal(SmsNotificationKind.DELIVERY_STATUS),\n /** The provider's id for the outbound message: the `messageId` its send answered. */\n providerMessageId: z.string().min(1).max(128),\n /**\n * The vendor's state projected onto the framework's. Absent when the vendor's state has no honest projection\n * (Telnyx's `delivery_unconfirmed`), exactly as on the send response.\n */\n status: z.enum(SmsDeliveryStatus).optional(),\n /** The vendor's own word for the state, kept because the projection collapses several of them. */\n providerStatus: z.string().min(1).max(64),\n /** The vendor's error code on a failure, never its message (a message can quote the number). */\n errorCode: z.string().min(1).max(64).optional(),\n /** The recipient, when the vendor's report names it. */\n to: E164PhoneNumberSchema.optional(),\n /** When the vendor says the change happened. Absent when it does not say (Twilio): the engine uses the receipt instant. */\n occurredAt: z.date().optional(),\n});\nexport type StandardSMS_DeliveryStatusNotification = z.infer<typeof StandardSMS_DeliveryStatusNotificationSchema>;\n\nexport const StandardSMS_InboundMessageNotificationSchema = z.object({\n kind: z.literal(SmsNotificationKind.INBOUND_MESSAGE),\n /** The provider's id for the received message. */\n providerMessageId: z.string().min(1).max(128),\n /** The person who texted. */\n from: E164PhoneNumberSchema,\n /** The application's number or short code they texted. */\n to: z.string().min(1).max(32),\n /** What they wrote. A concatenated message arrives whole; 1,600 characters is the ten-segment ceiling vendors apply. */\n text: z.string().max(1600),\n /** The vendor's own reading of the message as an opt-out or opt-in, when it reports one. */\n reportedOptOutChange: z.enum(SmsOptOutChange).optional(),\n /** When the vendor received it. Absent when it does not say (Twilio): the engine uses the receipt instant. */\n occurredAt: z.date().optional(),\n});\nexport type StandardSMS_InboundMessageNotification = z.infer<typeof StandardSMS_InboundMessageNotificationSchema>;\n\n/**\n * One verified SMS provider notification, projected onto vendor-neutral terms by the provider's `parseNotification`.\n * The engine re-validates it, so a module that returns a malformed one fails the delivery, which retries and then dies\n * where an operator can replay it.\n */\nexport const StandardSMS_NotificationSchema = z.discriminatedUnion(\"kind\", [\n StandardSMS_DeliveryStatusNotificationSchema,\n StandardSMS_InboundMessageNotificationSchema,\n]);\nexport type StandardSMS_Notification = z.infer<typeof StandardSMS_NotificationSchema>;\n\n// ===============================================================\n// Standard SMS Error\n// ===============================================================\n\nexport const StandardSMS_ErrorSchema = z.object({\n code: z.enum([\n \"VALIDATION_ERROR\",\n \"PROVIDER_ERROR\",\n \"INVALID_PHONE_NUMBER\",\n \"RATE_LIMIT_EXCEEDED\",\n \"AUTHENTICATION_FAILED\",\n \"QUOTA_EXCEEDED\",\n \"UNKNOWN_ERROR\",\n ]),\n message: z.string(),\n provider: z.string().optional(),\n details: z.unknown().optional(),\n});\nexport type StandardSMS_Error = z.infer<typeof StandardSMS_ErrorSchema>;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subject-erasure-effect.standard-interface.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"subject-erasure-effect.standard-interface.d.ts","sourceRoot":"","sources":["../../../src/protocols/subject-erasure-effect.standard-interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,6HAA6H;AAC7H,iHAAiH;AACjH,MAAM,MAAM,gCAAgC,GACxC;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,+GAA+G;AAC/G,oBAAY,kCAAkC;IAC5C,wEAAwE;IACxE,MAAM,WAAW;IACjB;;;;OAIG;IACH,MAAM,WAAW;IACjB,iHAAiH;IACjH,YAAY,iBAAiB;IAC7B,kHAAkH;IAClH,UAAU,eAAe;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,sCAAsC;IACrD,uGAAuG;IACvG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,uGAAuG;IACvG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wDAAwD;AACxD,MAAM,WAAW,iCAAiC;IAChD;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,sCAAsC,CAAC;IACnE;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,kCAAkC,CAAC;CAC/E;AAED,yEAAyE;AACzE,MAAM,WAAW,iCAAiC;IAChD,qFAAqF;IACrF,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,CAChB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iCAAiC,KACxC,OAAO,CAAC,gCAAgC,CAAC,CAAC;CAChD;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,KAAK,EAAE,iCAAiC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AACD,+EAA+E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subject-erasure-effect.standard-interface.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"subject-erasure-effect.standard-interface.js","sourceRoot":"","sources":["../../../src/protocols/subject-erasure-effect.standard-interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAQH,+GAA+G;AAC/G,MAAM,CAAN,IAAY,kCAaX;AAbD,WAAY,kCAAkC;IAC5C,wEAAwE;IACxE,uDAAiB,CAAA;IACjB;;;;OAIG;IACH,uDAAiB,CAAA;IACjB,iHAAiH;IACjH,mEAA6B,CAAA;IAC7B,kHAAkH;IAClH,+DAAyB,CAAA;AAC3B,CAAC,EAbW,kCAAkC,KAAlC,kCAAkC,QAa7C;AA0ED,+EAA+E","sourcesContent":["/**\n * Standard Subject Erasure Effect Interface (#2006)\n * --------\n * The contract a PROVIDER implements so a subject erasure reaches what its vendor keeps about the erased\n * person. It is what a provider's `complianceProfile.subjectErasure.stance = EXTERNAL_ERASURE_OPERATION`\n * promises. Before this, only the engine could register such an effect (the billing provider, an HTTP_API\n * resource), so a provider PACKAGE that honestly declared the stance was reported NOT_REGISTERED at every\n * erasure.\n *\n * ## What the effect receives, and what it does not\n *\n * The effect receives the subject's IDENTIFIERS AT THIS VENDOR, and a way to call this provider's own\n * operations. It never receives an execution context, a credential, the subject's personal fields, or any\n * way to read the application's data:\n *\n * - **The references are read by the engine**, from the resource fields the OPERATOR declared hold them\n * (`providerComplianceChoices.<ref>.subjectReferences` in `wildo.saas.config.ts`). A provider package does not\n * know the application's resources, and an open read door into them would hand third-party-authored code\n * every row the application keeps. The engine reads them BEFORE the local scrub, because afterwards the\n * subject's row is erased and hidden.\n * - **`execute` calls this provider's operations only, on the APPLICATION's connection.** The erasure is the\n * operator's obligation, so it spends the operator's account at the vendor. The call goes through the\n * engine's operation executor like any provider call: recorded, rate-budgeted, attributed to this package.\n *\n * ## Why the effect reports no status\n *\n * The engine derives the outcome from the calls IT recorded through `execute`: every call succeeded →\n * COMPLETED, some → PARTIAL, none → FAILED, and an effect that made no call while there were references to\n * erase → FAILED. A package therefore cannot report an erasure it did not perform. `execute` never throws: a\n * vendor error comes back as `{ ok: false }`, so one failing call cannot abort the others, and nothing a\n * vendor already applied is replayed.\n *\n * ## A vendor that finishes the deletion later, or holds nothing (#2181)\n *\n * Some vendors accept a deletion and carry it out on their own schedule: PostHog answers `202` and clears a person's\n * events in a weekly job. Reporting that call COMPLETED would say the data is gone while it is still there. So a call\n * may declare the vendor's published completion window (`vendorCompletion`), and may read the vendor's answer\n * (`readAnswer`) to say what that answer reports: erased, queued, nothing held, or not erased. The engine still\n * decides the outcome, from those recorded answers: a queued deletion makes the effect COMPLETES_AT_VENDOR with the\n * window's lapse, a call whose every answer was \"nothing held\" makes it NOTHING_TO_ERASE, and an answer the reader\n * cannot classify, or classifies as not erased, is a FAILED call. A reader can only describe an answer the engine\n * received from a call it made; it never invents one.\n */\n\n/** @wildo_source:part:start external-connectors.models.subject-erasure-effect facet:kind:api facet:audience:app-developer */\n/** The answer to one call an erasure effect made through `execute`. A vendor error is a value, never a throw. */\nexport type ProviderSubjectErasureCallResult =\n | { readonly ok: true; readonly output: unknown }\n | { readonly ok: false; readonly error: string };\n\n/** What a vendor's successful answer to one erasure call reports, as the call's `readAnswer` classifies it. */\nexport enum ProviderSubjectErasureVendorAnswer {\n /** The vendor erased what it held under the reference, in this call. */\n ERASED = 'erased',\n /**\n * The vendor ACCEPTED the deletion and finishes it on its own schedule. Requires the call's `vendorCompletion`\n * window: the erasure then reports COMPLETES_AT_VENDOR, by the instant the window lapses. Without a window the\n * answer is treated as NOT_ERASED, because nothing bounds when the data leaves.\n */\n QUEUED = 'queued',\n /** The vendor holds nothing under the reference. Every call answering this makes the effect NOTHING_TO_ERASE. */\n NOTHING_HELD = 'nothing-held',\n /** The vendor answered with a success status but reports it did not erase (a per-record failure inside a 2xx). */\n NOT_ERASED = 'not-erased',\n}\n\n/**\n * The vendor's PUBLISHED schedule for finishing a deletion it accepted: an upper bound, in whole days, from the call.\n * Copied from the vendor's own documentation by the provider package, never computed from the answer.\n */\nexport interface ProviderSubjectErasureVendorCompletion {\n /** At most this many days after the call, the vendor has finished the deletion. A positive integer. */\n readonly withinDays: number;\n /** Where the vendor publishes that schedule, so a reviewer can check the number against the source. */\n readonly basis: string;\n}\n\n/** How one `execute` call reads the vendor's answer. */\nexport interface ProviderSubjectErasureCallOptions {\n /**\n * The call DELETES something, so a vendor answering 404 or 410 (the record is not there) means it is already erased:\n * the step counts as done instead of failed. Set it only on a deletion: on a read, \"not found\" is not an erasure.\n */\n readonly absentMeansErased?: boolean;\n /**\n * The vendor finishes this deletion on its own schedule after accepting it, within this window. A successful answer\n * is then QUEUED unless `readAnswer` says otherwise. A window that is not a positive whole number of days, or that\n * names no basis, refuses the call before it is made.\n */\n readonly vendorCompletion?: ProviderSubjectErasureVendorCompletion;\n /**\n * Classify the vendor's successful answer (its parsed body). Absent: ERASED, or QUEUED when `vendorCompletion` is\n * declared. A reader that throws, or returns anything outside {@link ProviderSubjectErasureVendorAnswer}, makes the\n * call FAILED: an answer nobody could read is not evidence of an erasure.\n */\n readonly readAnswer?: (output: unknown) => ProviderSubjectErasureVendorAnswer;\n}\n\n/** What the engine hands a provider's erasure effect for one erasure. */\nexport interface ProviderSubjectErasureEffectInput {\n /** The resource type of the subject being erased (`users` for an account holder). */\n readonly subjectResourceType: string;\n /**\n * This vendor's identifiers for the subjects being erased: the values of the fields the operator declared\n * under `providerComplianceChoices.<ref>.subjectReferences`, read before the local scrub. Unique, and never\n * empty: when there is nothing to erase the engine reports NOTHING_TO_ERASE without calling `run`.\n * Identifiers that come from a row under a legal hold, or from a subject the erasure kept under one, are left out.\n */\n readonly references: ReadonlyArray<string>;\n /**\n * Call one of THIS provider's operations on the application's connection, and get its answer. Never throws.\n * Every call is a step of the erasure's outcome, labelled with `targetRef` (pass the reference the call is\n * about), so the receipt says which identifier failed.\n */\n readonly execute: (\n operationId: string,\n input: Readonly<Record<string, unknown>>,\n targetRef?: string,\n options?: ProviderSubjectErasureCallOptions,\n ) => Promise<ProviderSubjectErasureCallResult>;\n}\n\n/**\n * A provider's erasure effect: erase, at the vendor, what it keeps under each reference.\n *\n * Make it IDEMPOTENT: when every call fails (nothing applied), the engine runs it again, up to three times. Pass\n * `{ absentMeansErased: true }` on a deletion so a record the previous attempt already removed is not a failure.\n * It must finish within two minutes; past that the erasure stops waiting, refuses further calls, and reports from the\n * calls already recorded.\n *\n * Make one `execute` call per thing to erase, and keep going when one fails. Do not catch-and-ignore: the\n * outcome is derived from the calls, so a call you never made is a reference that stays at the vendor.\n * Declared on the backend provider module as `subjectErasureEffect`, beside a compliance profile whose\n * `subjectErasure.stance` is `EXTERNAL_ERASURE_OPERATION`; the engine refuses it on any other stance.\n */\nexport interface ProviderSubjectErasureEffect {\n run(input: ProviderSubjectErasureEffectInput): Promise<void>;\n}\n/** @wildo_source:part:end external-connectors.models.subject-erasure-effect */\n"]}
|