@absolutejs/voice 0.0.22-beta.274 → 0.0.22-beta.275

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/index.d.ts CHANGED
@@ -159,13 +159,13 @@ export type { VoiceS3ReviewStoreClient, VoiceS3ReviewStoreFile, VoiceS3ReviewSto
159
159
  export type { VoiceSQLiteRuntimeStorage, VoiceSQLiteStoreOptions } from './sqliteStore';
160
160
  export type { StoredVoiceIntegrationEvent, StoredVoiceExternalObjectMap, StoredVoiceOpsTask, VoiceExternalObjectMap, VoiceExternalObjectMapStore, VoiceOpsTaskAgeBucket, VoiceOpsTaskAnalyticsOptions, VoiceOpsTaskAnalyticsSummary, VoiceOpsTaskAssignmentRule, VoiceOpsTaskAssignmentRuleCondition, VoiceOpsTaskAssignmentRules, VoiceOpsTaskAssigneeAnalytics, VoiceOpsDispositionTaskPolicies, VoiceOpsSLABreachPolicy, VoiceIntegrationDeliveryStatus, VoiceIntegrationEvent, VoiceIntegrationEventStore, VoiceIntegrationSinkDelivery, VoiceIntegrationEventType, VoiceIntegrationWebhookConfig, VoiceOpsTask, VoiceOpsTaskHistoryEntry, VoiceOpsTaskKind, VoiceOpsTaskPolicy, VoiceOpsTaskPriority, VoiceOpsTaskStatus, VoiceOpsTaskStore, VoiceOpsTaskSummary, VoiceOpsTaskWorkerAnalytics } from './ops';
161
161
  export { createTwilioMediaStreamBridge, createTwilioVoiceRoutes, createTwilioVoiceResponse, decodeTwilioMulawBase64, encodeTwilioMulawBase64, transcodePCMToTwilioOutboundPayload, transcodeTwilioInboundPayloadToPCM16 } from './telephony/twilio';
162
- export { createVoiceTelephonyWebhookSecurityPreset } from './telephony/security';
162
+ export { assertVoiceTelephonyWebhookSecurityEvidence, buildVoiceTelephonyWebhookSecurityReport, createVoiceTelephonyWebhookSecurityPreset, createVoiceTelephonyWebhookSecurityRoutes, evaluateVoiceTelephonyWebhookSecurityEvidence } from './telephony/security';
163
163
  export { evaluateVoiceTelephonyContract } from './telephony/contract';
164
164
  export { createMemoryVoiceTelnyxWebhookEventStore, createTelnyxMediaStreamBridge, createTelnyxVoiceResponse, createTelnyxVoiceRoutes, createVoicePostgresTelnyxWebhookEventStore, createVoiceRedisTelnyxWebhookEventStore, createVoiceSQLiteTelnyxWebhookEventStore, createVoiceTelnyxWebhookVerifier, verifyVoiceTelnyxWebhookSignature } from './telephony/telnyx';
165
165
  export { createMemoryVoicePlivoWebhookNonceStore, createPlivoMediaStreamBridge, createPlivoVoiceResponse, createPlivoVoiceRoutes, createVoicePostgresPlivoWebhookNonceStore, createVoicePlivoWebhookVerifier, createVoiceRedisPlivoWebhookNonceStore, createVoiceSQLitePlivoWebhookNonceStore, signVoicePlivoWebhook, verifyVoicePlivoWebhookSignature } from './telephony/plivo';
166
166
  export { createVoiceTelephonyCarrierMatrix, createVoiceTelephonyCarrierMatrixRoutes, renderVoiceTelephonyCarrierMatrixHTML } from './telephony/matrix';
167
167
  export type { TwilioInboundMessage, TwilioMediaStreamBridge, TwilioMediaStreamBridgeOptions, TwilioMediaStreamSocket, TwilioOutboundClearMessage, TwilioOutboundMarkMessage, TwilioOutboundMediaMessage, TwilioOutboundMessage, TwilioVoiceRouteParameters, TwilioVoiceResponseOptions, TwilioVoiceSmokeCheck, TwilioVoiceSmokeOptions, TwilioVoiceSmokeReport, TwilioVoiceSetupOptions, TwilioVoiceSetupStatus, TwilioVoiceRoutesOptions } from './telephony/twilio';
168
- export type { VoiceTelephonyWebhookSecurityOptions, VoiceTelephonyWebhookSecurityPreset, VoiceTelephonyWebhookSecurityStorePreset } from './telephony/security';
168
+ export type { VoiceTelephonyWebhookSecurityOptions, VoiceTelephonyWebhookSecurityPreset, VoiceTelephonyWebhookSecurityAssertionInput, VoiceTelephonyWebhookSecurityAssertionReport, VoiceTelephonyWebhookSecurityProviderStatus, VoiceTelephonyWebhookSecurityReport, VoiceTelephonyWebhookSecurityRoutesOptions, VoiceTelephonyWebhookSecurityStorePreset } from './telephony/security';
169
169
  export type { VoiceTelephonyContractIssue, VoiceTelephonyContractOptions, VoiceTelephonyContractReport, VoiceTelephonyContractRequirement, VoiceTelephonyProvider, VoiceTelephonySetupStatus, VoiceTelephonySmokeCheck, VoiceTelephonySmokeReport } from './telephony/contract';
170
170
  export type { TelnyxInboundMessage, TelnyxMediaPayload, TelnyxMediaStreamBridge, TelnyxMediaStreamBridgeOptions, TelnyxMediaStreamSocket, TelnyxOutboundClearMessage, TelnyxOutboundMarkMessage, TelnyxOutboundMediaMessage, TelnyxOutboundMessage, TelnyxVoiceResponseOptions, TelnyxVoiceRoutesOptions, TelnyxVoiceSetupOptions, TelnyxVoiceSetupStatus, TelnyxVoiceSmokeCheck, TelnyxVoiceSmokeOptions, TelnyxVoiceSmokeReport, VoicePostgresTelnyxWebhookEventStoreOptions, VoiceRedisTelnyxWebhookEventClient, VoiceRedisTelnyxWebhookEventStoreOptions, VoiceSQLiteTelnyxWebhookEventStoreOptions, VoiceTelnyxWebhookEventStore, VoiceTelnyxWebhookEventStoreOptions, VoiceTelnyxWebhookVerifierOptions } from './telephony/telnyx';
171
171
  export type { PlivoInboundMessage, PlivoMediaStreamBridge, PlivoMediaStreamBridgeOptions, PlivoMediaStreamSocket, PlivoOutboundCheckpointMessage, PlivoOutboundClearAudioMessage, PlivoOutboundMessage, PlivoOutboundPlayAudioMessage, PlivoVoiceResponseOptions, PlivoVoiceRoutesOptions, PlivoVoiceSetupOptions, PlivoVoiceSetupStatus, PlivoVoiceSmokeCheck, PlivoVoiceSmokeOptions, PlivoVoiceSmokeReport, VoicePostgresPlivoWebhookNonceStoreOptions, VoicePlivoWebhookNonceStore, VoicePlivoWebhookNonceStoreOptions, VoicePlivoWebhookVerifierOptions, VoiceRedisPlivoWebhookNonceClient, VoiceRedisPlivoWebhookNonceStoreOptions, VoiceSQLitePlivoWebhookNonceStoreOptions } from './telephony/plivo';
package/dist/index.js CHANGED
@@ -31679,6 +31679,7 @@ var createVoiceSTTRoutingCorrectionHandler = (mode = "generic") => {
31679
31679
  return createPhraseHintCorrectionHandler();
31680
31680
  };
31681
31681
  // src/telephony/security.ts
31682
+ import { Elysia as Elysia51 } from "elysia";
31682
31683
  var resolveVerificationUrl2 = (option, input) => typeof option === "function" ? option(input) : option ?? input.request.url;
31683
31684
  var createStores = (options) => {
31684
31685
  const ttlSeconds = options.ttlSeconds;
@@ -31760,6 +31761,135 @@ var createStores = (options) => {
31760
31761
  telnyx: options.telnyx?.eventStore ?? createMemoryVoiceTelnyxWebhookEventStore()
31761
31762
  };
31762
31763
  };
31764
+ var resolveStoreKind = (store) => store?.kind ?? "memory";
31765
+ var isPersistentStore = (store) => {
31766
+ const kind = resolveStoreKind(store);
31767
+ return kind === "postgres" || kind === "redis" || kind === "sqlite";
31768
+ };
31769
+ var providerStatus = (input) => {
31770
+ const issues = [];
31771
+ if (input.enabled && !input.checks.verification) {
31772
+ issues.push("Webhook verification is not configured.");
31773
+ }
31774
+ if (input.enabled && !input.checks.replayProtection) {
31775
+ issues.push("Replay protection is not configured.");
31776
+ }
31777
+ if (input.enabled && input.checks.idempotency === false) {
31778
+ issues.push("Webhook idempotency is not configured.");
31779
+ }
31780
+ if (input.enabled && !input.checks.persistentStore) {
31781
+ issues.push("Webhook security store is in-memory; use SQLite, Postgres, or Redis for production.");
31782
+ }
31783
+ return {
31784
+ ...input,
31785
+ issues,
31786
+ status: !input.enabled ? "warn" : issues.length === 0 ? "pass" : "fail"
31787
+ };
31788
+ };
31789
+ var buildVoiceTelephonyWebhookSecurityReport = (options = {}) => {
31790
+ const store = resolveStoreKind(options.store);
31791
+ const persistentStore = isPersistentStore(options.store);
31792
+ const providers = [
31793
+ providerStatus({
31794
+ checks: {
31795
+ idempotency: Boolean(options.twilio),
31796
+ persistentStore,
31797
+ replayProtection: Boolean(options.twilio),
31798
+ verification: Boolean(options.twilio?.authToken)
31799
+ },
31800
+ enabled: Boolean(options.twilio),
31801
+ provider: "twilio",
31802
+ store
31803
+ }),
31804
+ providerStatus({
31805
+ checks: {
31806
+ persistentStore,
31807
+ replayProtection: Boolean(options.telnyx),
31808
+ verification: Boolean(options.telnyx?.publicKey)
31809
+ },
31810
+ enabled: Boolean(options.telnyx),
31811
+ provider: "telnyx",
31812
+ store
31813
+ }),
31814
+ providerStatus({
31815
+ checks: {
31816
+ persistentStore,
31817
+ replayProtection: Boolean(options.plivo),
31818
+ verification: Boolean(options.plivo?.authToken)
31819
+ },
31820
+ enabled: Boolean(options.plivo),
31821
+ provider: "plivo",
31822
+ store
31823
+ })
31824
+ ];
31825
+ const enabled = providers.filter((provider) => provider.enabled);
31826
+ const failed = enabled.filter((provider) => provider.status === "fail").length;
31827
+ const warned = enabled.filter((provider) => provider.status === "warn").length;
31828
+ const passed = enabled.filter((provider) => provider.status === "pass").length;
31829
+ const status = failed > 0 ? "fail" : warned > 0 || enabled.length === 0 ? "warn" : "pass";
31830
+ return {
31831
+ generatedAt: Date.now(),
31832
+ ok: status === "pass",
31833
+ providers,
31834
+ status,
31835
+ summary: {
31836
+ enabled: enabled.length,
31837
+ failed,
31838
+ passed,
31839
+ warned
31840
+ }
31841
+ };
31842
+ };
31843
+ var evaluateVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
31844
+ const issues = [...report.providers.flatMap((provider) => provider.issues)];
31845
+ const enabledProviders = report.providers.filter((provider) => provider.enabled).map((provider) => provider.provider);
31846
+ const passingProviders = report.providers.filter((provider) => provider.enabled && provider.status === "pass").map((provider) => provider.provider);
31847
+ const failedProviders = report.providers.filter((provider) => provider.enabled && provider.status === "fail").map((provider) => provider.provider);
31848
+ const maxFailedProviders = input.maxFailedProviders ?? 0;
31849
+ const minEnabledProviders = input.minEnabledProviders ?? 1;
31850
+ const requirePersistentStores = input.requirePersistentStores ?? true;
31851
+ if (enabledProviders.length < minEnabledProviders) {
31852
+ issues.push(`Expected at least ${String(minEnabledProviders)} enabled telephony webhook provider(s), found ${String(enabledProviders.length)}.`);
31853
+ }
31854
+ if (failedProviders.length > maxFailedProviders) {
31855
+ issues.push(`Expected at most ${String(maxFailedProviders)} failing telephony webhook provider(s), found ${String(failedProviders.length)}.`);
31856
+ }
31857
+ for (const provider of input.requiredProviders ?? []) {
31858
+ if (!enabledProviders.includes(provider)) {
31859
+ issues.push(`Missing enabled telephony webhook provider: ${provider}.`);
31860
+ }
31861
+ if (!passingProviders.includes(provider)) {
31862
+ issues.push(`Telephony webhook provider is not passing: ${provider}.`);
31863
+ }
31864
+ }
31865
+ if (requirePersistentStores) {
31866
+ for (const provider of report.providers) {
31867
+ if (provider.enabled && !provider.checks.persistentStore) {
31868
+ issues.push(`Telephony webhook provider ${provider.provider} is not using a persistent security store.`);
31869
+ }
31870
+ }
31871
+ }
31872
+ return {
31873
+ failedProviders,
31874
+ issues,
31875
+ ok: issues.length === 0,
31876
+ passingProviders,
31877
+ status: report.status
31878
+ };
31879
+ };
31880
+ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
31881
+ const assertion = evaluateVoiceTelephonyWebhookSecurityEvidence(report, input);
31882
+ if (!assertion.ok) {
31883
+ throw new Error(`Voice telephony webhook security assertion failed: ${assertion.issues.join(" ")}`);
31884
+ }
31885
+ return assertion;
31886
+ };
31887
+ var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
31888
+ const path = options.path ?? "/api/voice/telephony/webhook-security";
31889
+ return new Elysia51({
31890
+ name: options.name ?? "absolutejs-voice-telephony-webhook-security"
31891
+ }).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
31892
+ };
31763
31893
  var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
31764
31894
  const stores = createStores(options);
31765
31895
  const twilioVerificationUrl = options.twilio?.verificationUrl;
@@ -32044,6 +32174,7 @@ export {
32044
32174
  exportVoiceAuditTrail,
32045
32175
  evaluateVoiceTrace,
32046
32176
  evaluateVoiceToolContractEvidence,
32177
+ evaluateVoiceTelephonyWebhookSecurityEvidence,
32047
32178
  evaluateVoiceTelephonyWebhookNormalizationEvidence,
32048
32179
  evaluateVoiceTelephonyContract,
32049
32180
  evaluateVoiceSimulationSuiteEvidence,
@@ -32121,6 +32252,7 @@ export {
32121
32252
  createVoiceToolContract,
32122
32253
  createVoiceTelnyxWebhookVerifier,
32123
32254
  createVoiceTelnyxCampaignDialer,
32255
+ createVoiceTelephonyWebhookSecurityRoutes,
32124
32256
  createVoiceTelephonyWebhookSecurityPreset,
32125
32257
  createVoiceTelephonyWebhookRoutes,
32126
32258
  createVoiceTelephonyWebhookHandler,
@@ -32357,6 +32489,7 @@ export {
32357
32489
  claimVoiceOpsTask,
32358
32490
  buildVoiceTraceReplay,
32359
32491
  buildVoiceTraceDeliveryReport,
32492
+ buildVoiceTelephonyWebhookSecurityReport,
32360
32493
  buildVoiceProviderSloReport,
32361
32494
  buildVoiceProviderContractMatrix,
32362
32495
  buildVoiceProofTrendReport,
@@ -32392,6 +32525,7 @@ export {
32392
32525
  buildEmptyVoiceProofTrendReport,
32393
32526
  assignVoiceOpsTask,
32394
32527
  assertVoiceToolContractEvidence,
32528
+ assertVoiceTelephonyWebhookSecurityEvidence,
32395
32529
  assertVoiceTelephonyWebhookNormalizationEvidence,
32396
32530
  assertVoiceSimulationSuiteEvidence,
32397
32531
  assertVoiceProviderStackEvidence,
@@ -1,4 +1,5 @@
1
- import { type VoiceTelephonyWebhookIdempotencyStore, type VoiceTelephonyWebhookVerificationResult } from '../telephonyOutcome';
1
+ import { type VoiceTelephonyWebhookIdempotencyStore, type VoiceTelephonyWebhookProvider, type VoiceTelephonyWebhookVerificationResult } from '../telephonyOutcome';
2
+ import { Elysia } from 'elysia';
2
3
  import { type VoicePostgresClient } from '../postgresStore';
3
4
  import { type VoiceRedisTelephonyWebhookIdempotencyClient } from '../queue';
4
5
  import { type VoicePlivoWebhookNonceStore, type VoiceRedisPlivoWebhookNonceClient } from './plivo';
@@ -92,4 +93,90 @@ export type VoiceTelephonyWebhookSecurityPreset<TResult = unknown> = {
92
93
  twilio: VoiceTelephonyWebhookSecurityPreset<TResult>['twilio']['verify'];
93
94
  };
94
95
  };
96
+ export type VoiceTelephonyWebhookSecurityProviderStatus = {
97
+ checks: {
98
+ idempotency?: boolean;
99
+ persistentStore: boolean;
100
+ replayProtection: boolean;
101
+ verification: boolean;
102
+ };
103
+ enabled: boolean;
104
+ issues: string[];
105
+ provider: VoiceTelephonyWebhookProvider;
106
+ status: 'fail' | 'pass' | 'warn';
107
+ store: VoiceTelephonyWebhookSecurityStorePreset['kind'] | 'memory';
108
+ };
109
+ export type VoiceTelephonyWebhookSecurityReport = {
110
+ generatedAt: number;
111
+ ok: boolean;
112
+ providers: VoiceTelephonyWebhookSecurityProviderStatus[];
113
+ status: 'fail' | 'pass' | 'warn';
114
+ summary: {
115
+ enabled: number;
116
+ failed: number;
117
+ passed: number;
118
+ warned: number;
119
+ };
120
+ };
121
+ export type VoiceTelephonyWebhookSecurityAssertionInput = {
122
+ maxFailedProviders?: number;
123
+ minEnabledProviders?: number;
124
+ requirePersistentStores?: boolean;
125
+ requiredProviders?: VoiceTelephonyWebhookProvider[];
126
+ };
127
+ export type VoiceTelephonyWebhookSecurityAssertionReport = {
128
+ failedProviders: VoiceTelephonyWebhookProvider[];
129
+ issues: string[];
130
+ ok: boolean;
131
+ passingProviders: VoiceTelephonyWebhookProvider[];
132
+ status: VoiceTelephonyWebhookSecurityReport['status'];
133
+ };
134
+ export type VoiceTelephonyWebhookSecurityRoutesOptions<TResult = unknown> = {
135
+ name?: string;
136
+ options: VoiceTelephonyWebhookSecurityOptions<TResult>;
137
+ path?: string;
138
+ };
139
+ export declare const buildVoiceTelephonyWebhookSecurityReport: <TResult = unknown>(options?: VoiceTelephonyWebhookSecurityOptions<TResult>) => VoiceTelephonyWebhookSecurityReport;
140
+ export declare const evaluateVoiceTelephonyWebhookSecurityEvidence: (report: VoiceTelephonyWebhookSecurityReport, input?: VoiceTelephonyWebhookSecurityAssertionInput) => VoiceTelephonyWebhookSecurityAssertionReport;
141
+ export declare const assertVoiceTelephonyWebhookSecurityEvidence: (report: VoiceTelephonyWebhookSecurityReport, input?: VoiceTelephonyWebhookSecurityAssertionInput) => VoiceTelephonyWebhookSecurityAssertionReport;
142
+ export declare const createVoiceTelephonyWebhookSecurityRoutes: <TResult = unknown>(options: VoiceTelephonyWebhookSecurityRoutesOptions<TResult>) => Elysia<"", {
143
+ decorator: {};
144
+ store: {};
145
+ derive: {};
146
+ resolve: {};
147
+ }, {
148
+ typebox: {};
149
+ error: {};
150
+ }, {
151
+ schema: {};
152
+ standaloneSchema: {};
153
+ macro: {};
154
+ macroFn: {};
155
+ parser: {};
156
+ response: {};
157
+ }, {
158
+ [x: string]: {
159
+ get: {
160
+ body: unknown;
161
+ params: {};
162
+ query: unknown;
163
+ headers: unknown;
164
+ response: {
165
+ 200: VoiceTelephonyWebhookSecurityReport;
166
+ };
167
+ };
168
+ };
169
+ }, {
170
+ derive: {};
171
+ resolve: {};
172
+ schema: {};
173
+ standaloneSchema: {};
174
+ response: {};
175
+ }, {
176
+ derive: {};
177
+ resolve: {};
178
+ schema: {};
179
+ standaloneSchema: {};
180
+ response: {};
181
+ }>;
95
182
  export declare const createVoiceTelephonyWebhookSecurityPreset: <TResult = unknown>(options?: VoiceTelephonyWebhookSecurityOptions<TResult>) => VoiceTelephonyWebhookSecurityPreset<TResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.274",
3
+ "version": "0.0.22-beta.275",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",