@absolutejs/voice 0.0.22-beta.257 → 0.0.22-beta.259

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.
@@ -190,6 +190,26 @@ export type VoiceCampaignReadinessProofReport = {
190
190
  windowBlocked: VoiceCampaignTickResult;
191
191
  };
192
192
  };
193
+ export type VoiceCampaignReadinessAssertionInput = {
194
+ maxFailedChecks?: number;
195
+ minAcceptedImports?: number;
196
+ minRejectedImports?: number;
197
+ minTotalImports?: number;
198
+ requiredBlockedReasons?: VoiceCampaignTickResult['blocked'][number]['reason'][];
199
+ requiredChecks?: string[];
200
+ requireOk?: boolean;
201
+ };
202
+ export type VoiceCampaignReadinessAssertionReport = {
203
+ acceptedImports: number;
204
+ blockedReasons: VoiceCampaignTickResult['blocked'][number]['reason'][];
205
+ failed: number;
206
+ issues: string[];
207
+ ok: boolean;
208
+ passed: number;
209
+ rejectedImports: number;
210
+ total: number;
211
+ totalImports: number;
212
+ };
193
213
  export type VoiceCampaignSummary = {
194
214
  attempts: {
195
215
  failed: number;
@@ -381,6 +401,8 @@ export declare const applyVoiceCampaignTelephonyOutcome: <TResult = unknown>(inp
381
401
  export declare const createVoiceCampaignTelephonyOutcomeHandler: <TResult = unknown>(options: VoiceCampaignTelephonyOutcomeOptions<TResult>) => (input: VoiceTelephonyWebhookDecision<TResult>) => Promise<VoiceCampaignTelephonyOutcomeResult>;
382
402
  export declare const runVoiceCampaignProof: (options?: VoiceCampaignProofOptions) => Promise<VoiceCampaignProofReport>;
383
403
  export declare const runVoiceCampaignReadinessProof: (options?: VoiceCampaignReadinessProofOptions) => Promise<VoiceCampaignReadinessProofReport>;
404
+ export declare const evaluateVoiceCampaignReadinessEvidence: (report: VoiceCampaignReadinessProofReport, input?: VoiceCampaignReadinessAssertionInput) => VoiceCampaignReadinessAssertionReport;
405
+ export declare const assertVoiceCampaignReadinessEvidence: (report: VoiceCampaignReadinessProofReport, input?: VoiceCampaignReadinessAssertionInput) => VoiceCampaignReadinessAssertionReport;
384
406
  export declare const renderVoiceCampaignsHTML: (records: VoiceCampaignRecord[], options?: Pick<VoiceCampaignRoutesOptions, "operationsRecordHref" | "title">) => string;
385
407
  export declare const renderVoiceCampaignObservabilityHTML: (report: VoiceCampaignObservabilityReport, options?: {
386
408
  title?: string;
@@ -82,9 +82,30 @@ export type VoiceCampaignDialerProofOptions = {
82
82
  runPath?: string;
83
83
  store?: VoiceCampaignStore;
84
84
  };
85
+ export type VoiceCampaignDialerProofAssertionInput = {
86
+ maxFailedProviders?: number;
87
+ minCarrierRequests?: number;
88
+ minProviders?: number;
89
+ minSuccessfulOutcomes?: number;
90
+ requiredProviders?: VoiceCampaignDialerProofProvider[];
91
+ requireDryRun?: boolean;
92
+ requireOk?: boolean;
93
+ };
94
+ export type VoiceCampaignDialerProofAssertionReport = {
95
+ carrierRequests: number;
96
+ failedProviders: number;
97
+ issues: string[];
98
+ mode: VoiceCampaignDialerProofReport['mode'];
99
+ ok: boolean;
100
+ providers: VoiceCampaignDialerProofProvider[];
101
+ successfulOutcomes: number;
102
+ totalProviders: number;
103
+ };
85
104
  export declare const createVoiceTwilioCampaignDialer: (options: VoiceTwilioCampaignDialerOptions) => VoiceCampaignDialer;
86
105
  export declare const createVoiceTelnyxCampaignDialer: (options: VoiceTelnyxCampaignDialerOptions) => VoiceCampaignDialer;
87
106
  export declare const createVoicePlivoCampaignDialer: (options: VoicePlivoCampaignDialerOptions) => VoiceCampaignDialer;
88
107
  export declare const getVoiceCampaignDialerProofStatus: (options?: Pick<VoiceCampaignDialerProofOptions, "providers" | "runPath">) => VoiceCampaignDialerProofStatus;
89
108
  export declare const runVoiceCampaignDialerProof: (options?: VoiceCampaignDialerProofOptions) => Promise<VoiceCampaignDialerProofReport>;
109
+ export declare const evaluateVoiceCampaignDialerProofEvidence: (report: VoiceCampaignDialerProofReport, input?: VoiceCampaignDialerProofAssertionInput) => VoiceCampaignDialerProofAssertionReport;
110
+ export declare const assertVoiceCampaignDialerProofEvidence: (report: VoiceCampaignDialerProofReport, input?: VoiceCampaignDialerProofAssertionInput) => VoiceCampaignDialerProofAssertionReport;
90
111
  export {};
@@ -77,6 +77,44 @@ export type VoiceDataControlReport = {
77
77
  providerKeys: VoiceDataControlProviderKeySurface[];
78
78
  zeroRetentionAvailable: boolean;
79
79
  };
80
+ export type VoiceDataControlAssertionInput = {
81
+ maxDeletionDeleted?: number;
82
+ maxMissingConfiguredStorage?: number;
83
+ maxMissingSelfHostedStorage?: number;
84
+ maxRetentionDeleted?: number;
85
+ minAuditExportEvents?: number;
86
+ minConfiguredStorage?: number;
87
+ minProviderKeys?: number;
88
+ requiredControls?: VoiceDataControlStorageSurface['control'][];
89
+ requiredDeletionScopes?: VoiceDataRetentionScope[];
90
+ requiredProviderKeys?: string[];
91
+ requiredRetentionScopes?: VoiceDataRetentionScope[];
92
+ requiredStorage?: string[];
93
+ requireAuditExport?: boolean;
94
+ requireDeletionDryRun?: boolean;
95
+ requireDeletionProof?: boolean;
96
+ requireRedaction?: boolean;
97
+ requireRetentionDryRun?: boolean;
98
+ requireSelfHostedStorage?: boolean;
99
+ requireZeroRetentionAvailable?: boolean;
100
+ };
101
+ export type VoiceDataControlAssertionReport = {
102
+ auditExportEvents: number;
103
+ configuredStorage: string[];
104
+ controls: VoiceDataControlStorageSurface['control'][];
105
+ deletionDeleted: number;
106
+ deletionDryRun?: boolean;
107
+ deletionScopes: VoiceDataRetentionScope[];
108
+ issues: string[];
109
+ ok: boolean;
110
+ providerKeys: string[];
111
+ redactionEnabled: boolean;
112
+ retentionDeleted: number;
113
+ retentionDryRun: boolean;
114
+ retentionScopes: VoiceDataRetentionScope[];
115
+ selfHostedConfiguredStorage: string[];
116
+ zeroRetentionAvailable: boolean;
117
+ };
80
118
  export type VoiceDataControlRoutesOptions = VoiceDataRetentionStores & {
81
119
  audit?: VoiceAuditEventStore;
82
120
  auditActor?: VoiceAuditActor;
@@ -91,6 +129,8 @@ export type VoiceDataControlRoutesOptions = VoiceDataRetentionStores & {
91
129
  };
92
130
  export declare const applyVoiceDataRetentionPolicy: (options: VoiceDataRetentionPolicy) => Promise<VoiceDataRetentionReport>;
93
131
  export declare const buildVoiceDataRetentionPlan: (options: Omit<VoiceDataRetentionPolicy, "dryRun">) => Promise<VoiceDataRetentionReport>;
132
+ export declare const evaluateVoiceDataControlEvidence: (report: VoiceDataControlReport, input?: VoiceDataControlAssertionInput) => VoiceDataControlAssertionReport;
133
+ export declare const assertVoiceDataControlEvidence: (report: VoiceDataControlReport, input?: VoiceDataControlAssertionInput) => VoiceDataControlAssertionReport;
94
134
  export declare const createVoiceZeroRetentionPolicy: (options: VoiceDataRetentionStores & {
95
135
  audit?: VoiceAuditEventStore;
96
136
  auditActor?: VoiceAuditActor;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { voice } from './plugin';
2
- export { applyVoiceCampaignTelephonyOutcome, buildVoiceCampaignObservabilityReport, createVoiceCampaignTelephonyOutcomeHandler, createVoiceCampaign, createVoiceCampaignRoutes, createVoiceCampaignWorker, createVoiceCampaignWorkerLoop, createVoiceMemoryCampaignStore, importVoiceCampaignRecipients, renderVoiceCampaignObservabilityHTML, renderVoiceCampaignsHTML, runVoiceCampaignProof, runVoiceCampaignReadinessProof, summarizeVoiceCampaigns } from './campaign';
3
- export { createVoicePlivoCampaignDialer, createVoiceTelnyxCampaignDialer, createVoiceTwilioCampaignDialer, getVoiceCampaignDialerProofStatus, runVoiceCampaignDialerProof } from './campaignDialers';
2
+ export { applyVoiceCampaignTelephonyOutcome, assertVoiceCampaignReadinessEvidence, buildVoiceCampaignObservabilityReport, createVoiceCampaignTelephonyOutcomeHandler, createVoiceCampaign, createVoiceCampaignRoutes, createVoiceCampaignWorker, createVoiceCampaignWorkerLoop, createVoiceMemoryCampaignStore, evaluateVoiceCampaignReadinessEvidence, importVoiceCampaignRecipients, renderVoiceCampaignObservabilityHTML, renderVoiceCampaignsHTML, runVoiceCampaignProof, runVoiceCampaignReadinessProof, summarizeVoiceCampaigns } from './campaign';
3
+ export { assertVoiceCampaignDialerProofEvidence, createVoicePlivoCampaignDialer, createVoiceTelnyxCampaignDialer, createVoiceTwilioCampaignDialer, evaluateVoiceCampaignDialerProofEvidence, getVoiceCampaignDialerProofStatus, runVoiceCampaignDialerProof } from './campaignDialers';
4
4
  export { createVoiceAssistant, createVoiceExperiment, summarizeVoiceAssistantRuns } from './assistant';
5
5
  export { createVoiceAssistantHealthHTMLHandler, createVoiceAssistantHealthJSONHandler, createVoiceAssistantHealthRoutes, renderVoiceAssistantHealthHTML, summarizeVoiceAssistantHealth } from './assistantHealth';
6
6
  export { createVoiceAuditEvent, createVoiceAuditLogger, createVoiceMemoryAuditEventStore, filterVoiceAuditEvents, recordVoiceAuditEvent, recordVoiceHandoffAuditEvent, recordVoiceOperatorAuditEvent, recordVoiceProviderAuditEvent, recordVoiceRetentionAuditEvent, recordVoiceToolAuditEvent } from './audit';
@@ -21,8 +21,8 @@ export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, Voi
21
21
  export { buildVoiceLiveOpsControlState, createVoiceLiveOpsController, createVoiceLiveOpsRoutes, createVoiceMemoryLiveOpsControlStore, getVoiceLiveOpsControlStatus, VOICE_LIVE_OPS_ACTIONS } from './liveOps';
22
22
  export type { VoiceLiveOpsAction, VoiceLiveOpsActionInput, VoiceLiveOpsActionResult, VoiceLiveOpsControllerOptions, VoiceLiveOpsControlState, VoiceLiveOpsControlStatus, VoiceLiveOpsControlStore, VoiceLiveOpsRoutesOptions } from './liveOps';
23
23
  export { buildVoiceDeliveryRuntimeReport, createVoiceDeliveryRuntime, createVoiceDeliveryRuntimePresetConfig, createVoiceDeliveryRuntimeRoutes, renderVoiceDeliveryRuntimeHTML } from './deliveryRuntime';
24
- export { applyVoiceDataRetentionPolicy, buildVoiceDataControlReport, buildVoiceDataRetentionPlan, createVoiceDataControlRoutes, createVoiceZeroRetentionPolicy, renderVoiceDataControlHTML, renderVoiceDataControlMarkdown, voiceComplianceRedactionDefaults } from './dataControl';
25
- export type { VoiceDataControlProviderKeySurface, VoiceDataControlReport, VoiceDataControlRoutesOptions, VoiceDataControlStorageSurface, VoiceDataRetentionPolicy, VoiceDataRetentionReport, VoiceDataRetentionScope, VoiceDataRetentionScopeReport, VoiceDataRetentionStores } from './dataControl';
24
+ export { applyVoiceDataRetentionPolicy, assertVoiceDataControlEvidence, buildVoiceDataControlReport, buildVoiceDataRetentionPlan, createVoiceDataControlRoutes, createVoiceZeroRetentionPolicy, evaluateVoiceDataControlEvidence, renderVoiceDataControlHTML, renderVoiceDataControlMarkdown, voiceComplianceRedactionDefaults } from './dataControl';
25
+ export type { VoiceDataControlAssertionInput, VoiceDataControlAssertionReport, VoiceDataControlProviderKeySurface, VoiceDataControlReport, VoiceDataControlRoutesOptions, VoiceDataControlStorageSurface, VoiceDataRetentionPolicy, VoiceDataRetentionReport, VoiceDataRetentionScope, VoiceDataRetentionScopeReport, VoiceDataRetentionStores } from './dataControl';
26
26
  export type { VoiceDemoReadyReport, VoiceDemoReadyRoutesOptions, VoiceDemoReadySection, VoiceDemoReadyStatus } from './demoReadyRoutes';
27
27
  export type { VoiceDeliverySinkDescriptor, VoiceDeliverySinkDescriptorInput, VoiceDeliverySinkKind, VoiceDeliverySinkPairOptions, VoiceDeliverySinkReport, VoiceDeliverySinkRoutesOptions, VoiceTraceDeliverySinkSurface } from './deliverySinkRoutes';
28
28
  export type { VoiceOpsActionAuditRecord, VoiceOpsActionAuditRoutesOptions, VoiceOpsActionHistoryEntry, VoiceOpsActionHistoryReport } from './opsActionAuditRoutes';
@@ -92,8 +92,8 @@ export { conditionAudioChunk, resolveAudioConditioningConfig } from './audioCond
92
92
  export { resolveVoiceRuntimePreset } from './presets';
93
93
  export { resolveTurnDetectionConfig, TURN_PROFILE_DEFAULTS } from './turnProfiles';
94
94
  export { createVoiceCallReviewFromLiveTelephonyReport, createVoiceCallReviewRecorder, renderVoiceCallReviewHTML, renderVoiceCallReviewMarkdown } from './testing/review';
95
- export type { VoiceCampaign, VoiceCampaignAttempt, VoiceCampaignAttemptResultInput, VoiceCampaignAttemptStatus, VoiceCampaignCreateInput, VoiceCampaignDialer, VoiceCampaignDialerInput, VoiceCampaignDialerResult, VoiceCampaignProofOptions, VoiceCampaignProofReport, VoiceCampaignReadinessCheck, VoiceCampaignReadinessProofOptions, VoiceCampaignReadinessProofReport, VoiceCampaignRecipient, VoiceCampaignRecipientImportIssue, VoiceCampaignRecipientImportIssueCode, VoiceCampaignRecipientImportOptions, VoiceCampaignRecipientImportResult, VoiceCampaignRecipientImportRow, VoiceCampaignRecipientInput, VoiceCampaignRecipientStatus, VoiceCampaignRecord, VoiceCampaignRoutesOptions, VoiceCampaignRuntime, VoiceCampaignRuntimeOptions, VoiceCampaignRateLimit, VoiceCampaignRetryPolicy, VoiceCampaignSchedule, VoiceCampaignStatus, VoiceCampaignStore, VoiceCampaignSummary, VoiceCampaignTimeWindow, VoiceCampaignTickResult } from './campaign';
96
- export type { VoiceCampaignDialerProofCarrierRequest, VoiceCampaignDialerProofOptions, VoiceCampaignDialerProofProvider, VoiceCampaignDialerProofProviderResult, VoiceCampaignDialerProofReport, VoiceCampaignDialerProofStatus, VoicePlivoCampaignDialerOptions, VoiceTelnyxCampaignDialerOptions, VoiceTwilioCampaignDialerOptions } from './campaignDialers';
95
+ export type { VoiceCampaign, VoiceCampaignAttempt, VoiceCampaignAttemptResultInput, VoiceCampaignAttemptStatus, VoiceCampaignCreateInput, VoiceCampaignDialer, VoiceCampaignDialerInput, VoiceCampaignDialerResult, VoiceCampaignProofOptions, VoiceCampaignProofReport, VoiceCampaignReadinessAssertionInput, VoiceCampaignReadinessAssertionReport, VoiceCampaignReadinessCheck, VoiceCampaignReadinessProofOptions, VoiceCampaignReadinessProofReport, VoiceCampaignRecipient, VoiceCampaignRecipientImportIssue, VoiceCampaignRecipientImportIssueCode, VoiceCampaignRecipientImportOptions, VoiceCampaignRecipientImportResult, VoiceCampaignRecipientImportRow, VoiceCampaignRecipientInput, VoiceCampaignRecipientStatus, VoiceCampaignRecord, VoiceCampaignRoutesOptions, VoiceCampaignRuntime, VoiceCampaignRuntimeOptions, VoiceCampaignRateLimit, VoiceCampaignRetryPolicy, VoiceCampaignSchedule, VoiceCampaignStatus, VoiceCampaignStore, VoiceCampaignSummary, VoiceCampaignTimeWindow, VoiceCampaignTickResult } from './campaign';
96
+ export type { VoiceCampaignDialerProofAssertionInput, VoiceCampaignDialerProofAssertionReport, VoiceCampaignDialerProofCarrierRequest, VoiceCampaignDialerProofOptions, VoiceCampaignDialerProofProvider, VoiceCampaignDialerProofProviderResult, VoiceCampaignDialerProofReport, VoiceCampaignDialerProofStatus, VoicePlivoCampaignDialerOptions, VoiceTelnyxCampaignDialerOptions, VoiceTwilioCampaignDialerOptions } from './campaignDialers';
97
97
  export type { VoiceBargeInReport, VoiceBargeInRoutesOptions } from './bargeInRoutes';
98
98
  export type { VoiceAssistant, VoiceAssistantArtifactPlan, VoiceAssistantExperiment, VoiceAssistantExperimentOptions, VoiceAssistantGuardrailInput, VoiceAssistantGuardrails, VoiceAssistantMemoryLifecycle, VoiceAssistantMemoryLifecycleInput, VoiceAssistantOptions, VoiceAssistantOutputGuardrailInput, VoiceAssistantPreset, VoiceAssistantRunsSummary, VoiceAssistantRunSummary, VoiceAssistantVariant } from './assistant';
99
99
  export type { VoiceAssistantHealthFailure, VoiceAssistantHealthHTMLHandlerOptions, VoiceAssistantHealthRoutesOptions, VoiceAssistantHealthSummary, VoiceAssistantHealthSummaryOptions } from './assistantHealth';
package/dist/index.js CHANGED
@@ -6661,6 +6661,60 @@ recipient-no-consent,Barbara,+15550001004,no,delta`,
6661
6661
  }
6662
6662
  };
6663
6663
  };
6664
+ var evaluateVoiceCampaignReadinessEvidence = (report, input = {}) => {
6665
+ const issues = [];
6666
+ const maxFailedChecks = input.maxFailedChecks ?? 0;
6667
+ const requireOk = input.requireOk ?? true;
6668
+ const failed = report.checks.filter((check) => check.status === "fail").length;
6669
+ const passed = report.checks.length - failed;
6670
+ const checkNames = new Set(report.checks.map((check) => check.name));
6671
+ const blockedReasons = [
6672
+ ...new Set(Object.values(report.ticks).flatMap((tick) => tick.blocked.map((block) => block.reason)))
6673
+ ].sort();
6674
+ if (requireOk && !report.ok) {
6675
+ issues.push("Expected campaign readiness proof to pass.");
6676
+ }
6677
+ if (failed > maxFailedChecks) {
6678
+ issues.push(`Expected at most ${String(maxFailedChecks)} failing campaign readiness check(s), found ${String(failed)}.`);
6679
+ }
6680
+ if (input.minTotalImports !== undefined && report.import.total < input.minTotalImports) {
6681
+ issues.push(`Expected at least ${String(input.minTotalImports)} campaign import row(s), found ${String(report.import.total)}.`);
6682
+ }
6683
+ if (input.minAcceptedImports !== undefined && report.import.accepted.length < input.minAcceptedImports) {
6684
+ issues.push(`Expected at least ${String(input.minAcceptedImports)} accepted campaign import(s), found ${String(report.import.accepted.length)}.`);
6685
+ }
6686
+ if (input.minRejectedImports !== undefined && report.import.rejected.length < input.minRejectedImports) {
6687
+ issues.push(`Expected at least ${String(input.minRejectedImports)} rejected campaign import(s), found ${String(report.import.rejected.length)}.`);
6688
+ }
6689
+ for (const check of input.requiredChecks ?? []) {
6690
+ if (!checkNames.has(check)) {
6691
+ issues.push(`Missing campaign readiness check: ${check}.`);
6692
+ }
6693
+ }
6694
+ for (const reason of input.requiredBlockedReasons ?? []) {
6695
+ if (!blockedReasons.includes(reason)) {
6696
+ issues.push(`Missing campaign readiness blocked reason: ${reason}.`);
6697
+ }
6698
+ }
6699
+ return {
6700
+ acceptedImports: report.import.accepted.length,
6701
+ blockedReasons,
6702
+ failed,
6703
+ issues,
6704
+ ok: issues.length === 0,
6705
+ passed,
6706
+ rejectedImports: report.import.rejected.length,
6707
+ total: report.checks.length,
6708
+ totalImports: report.import.total
6709
+ };
6710
+ };
6711
+ var assertVoiceCampaignReadinessEvidence = (report, input = {}) => {
6712
+ const assertion = evaluateVoiceCampaignReadinessEvidence(report, input);
6713
+ if (!assertion.ok) {
6714
+ throw new Error(`Voice campaign readiness evidence assertion failed: ${assertion.issues.join(" ")}`);
6715
+ }
6716
+ return assertion;
6717
+ };
6664
6718
  var escapeHtml3 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6665
6719
  var getString = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
6666
6720
  var campaignAttemptSessionId = (attempt) => getString(attempt.metadata?.sessionId) ?? getString(attempt.metadata?.voiceSessionId) ?? getString(attempt.metadata?.callSessionId);
@@ -7094,6 +7148,56 @@ var runVoiceCampaignDialerProof = async (options = {}) => {
7094
7148
  providers: results
7095
7149
  };
7096
7150
  };
7151
+ var evaluateVoiceCampaignDialerProofEvidence = (report, input = {}) => {
7152
+ const issues = [];
7153
+ const maxFailedProviders = input.maxFailedProviders ?? 0;
7154
+ const requireOk = input.requireOk ?? true;
7155
+ const requireDryRun = input.requireDryRun ?? true;
7156
+ const providers = report.providers.map((provider) => provider.provider).sort();
7157
+ const carrierRequests = report.providers.reduce((total, provider) => total + provider.carrierRequests.length, 0);
7158
+ const successfulOutcomes = report.providers.reduce((total, provider) => total + provider.outcomes.filter((outcome) => outcome.applied).length, 0);
7159
+ const failedProviders = report.providers.filter((provider) => provider.carrierRequests.length === 0 || provider.outcomes.some((outcome) => !outcome.applied)).length;
7160
+ if (requireOk && !report.ok) {
7161
+ issues.push("Expected campaign dialer proof to pass.");
7162
+ }
7163
+ if (requireDryRun && report.mode !== "dry-run") {
7164
+ issues.push(`Expected campaign dialer proof mode dry-run, found ${report.mode}.`);
7165
+ }
7166
+ if (failedProviders > maxFailedProviders) {
7167
+ issues.push(`Expected at most ${String(maxFailedProviders)} failing campaign dialer provider(s), found ${String(failedProviders)}.`);
7168
+ }
7169
+ if (input.minProviders !== undefined && report.providers.length < input.minProviders) {
7170
+ issues.push(`Expected at least ${String(input.minProviders)} campaign dialer provider(s), found ${String(report.providers.length)}.`);
7171
+ }
7172
+ if (input.minCarrierRequests !== undefined && carrierRequests < input.minCarrierRequests) {
7173
+ issues.push(`Expected at least ${String(input.minCarrierRequests)} campaign dialer carrier request(s), found ${String(carrierRequests)}.`);
7174
+ }
7175
+ if (input.minSuccessfulOutcomes !== undefined && successfulOutcomes < input.minSuccessfulOutcomes) {
7176
+ issues.push(`Expected at least ${String(input.minSuccessfulOutcomes)} applied campaign dialer outcome(s), found ${String(successfulOutcomes)}.`);
7177
+ }
7178
+ for (const provider of input.requiredProviders ?? []) {
7179
+ if (!providers.includes(provider)) {
7180
+ issues.push(`Missing campaign dialer provider: ${provider}.`);
7181
+ }
7182
+ }
7183
+ return {
7184
+ carrierRequests,
7185
+ failedProviders,
7186
+ issues,
7187
+ mode: report.mode,
7188
+ ok: issues.length === 0,
7189
+ providers,
7190
+ successfulOutcomes,
7191
+ totalProviders: report.providers.length
7192
+ };
7193
+ };
7194
+ var assertVoiceCampaignDialerProofEvidence = (report, input = {}) => {
7195
+ const assertion = evaluateVoiceCampaignDialerProofEvidence(report, input);
7196
+ if (!assertion.ok) {
7197
+ throw new Error(`Voice campaign dialer proof evidence assertion failed: ${assertion.issues.join(" ")}`);
7198
+ }
7199
+ return assertion;
7200
+ };
7097
7201
  // src/audit.ts
7098
7202
  var includes = (filter, value) => {
7099
7203
  if (!filter) {
@@ -13318,6 +13422,127 @@ var defaultProviderKeys = [
13318
13422
  }
13319
13423
  ];
13320
13424
  var resolveDataControlRedaction = (redact) => redact === false ? undefined : redact === true || redact === undefined ? voiceComplianceRedactionDefaults : redact;
13425
+ var uniqueSorted = (values) => Array.from(new Set(values)).sort();
13426
+ var findMissing = (values, required) => {
13427
+ if (!required?.length) {
13428
+ return [];
13429
+ }
13430
+ const valueSet = new Set(values);
13431
+ return required.filter((value) => !valueSet.has(value));
13432
+ };
13433
+ var evaluateVoiceDataControlEvidence = (report, input = {}) => {
13434
+ const issues = [];
13435
+ const configuredStorage = report.storage.filter((surface) => surface.configured).map((surface) => surface.name);
13436
+ const selfHostedConfiguredStorage = report.storage.filter((surface) => surface.configured && surface.selfHosted).map((surface) => surface.name);
13437
+ const controls = uniqueSorted(report.storage.filter((surface) => surface.configured).map((surface) => surface.control));
13438
+ const retentionScopes = uniqueSorted(report.retentionPlan.scopes.map((scope) => scope.scope));
13439
+ const deletionScopes = uniqueSorted(report.deletionProof?.scopes.map((scope) => scope.scope) ?? []);
13440
+ const providerKeys = uniqueSorted(report.providerKeys.map((key) => key.name.toLowerCase()));
13441
+ const auditExportEvents = report.auditExport?.events.length ?? 0;
13442
+ const deletionDeleted = report.deletionProof?.deletedCount ?? 0;
13443
+ const maxRetentionDeleted = input.maxRetentionDeleted;
13444
+ const maxDeletionDeleted = input.maxDeletionDeleted;
13445
+ const requireAuditExport = input.requireAuditExport ?? true;
13446
+ const requireDeletionDryRun = input.requireDeletionDryRun ?? true;
13447
+ const requireDeletionProof = input.requireDeletionProof ?? false;
13448
+ const requireRedaction = input.requireRedaction ?? true;
13449
+ const requireRetentionDryRun = input.requireRetentionDryRun ?? true;
13450
+ const requireSelfHostedStorage = input.requireSelfHostedStorage ?? true;
13451
+ const requireZeroRetentionAvailable = input.requireZeroRetentionAvailable ?? true;
13452
+ if (requireRedaction && !report.redaction.enabled) {
13453
+ issues.push("Expected data-control redaction to be enabled.");
13454
+ }
13455
+ if (requireZeroRetentionAvailable && !report.zeroRetentionAvailable) {
13456
+ issues.push("Expected zero-retention policy recipe to be available.");
13457
+ }
13458
+ if (requireAuditExport && !report.auditExport) {
13459
+ issues.push("Expected redacted audit export to be available.");
13460
+ }
13461
+ if (input.minAuditExportEvents !== undefined && auditExportEvents < input.minAuditExportEvents) {
13462
+ issues.push(`Expected at least ${String(input.minAuditExportEvents)} audit export events, found ${String(auditExportEvents)}.`);
13463
+ }
13464
+ if (requireRetentionDryRun && !report.retentionPlan.dryRun) {
13465
+ issues.push("Expected retention plan to run in dry-run mode.");
13466
+ }
13467
+ if (maxRetentionDeleted !== undefined && report.retentionPlan.deletedCount > maxRetentionDeleted) {
13468
+ issues.push(`Expected retention plan to delete at most ${String(maxRetentionDeleted)} records, found ${String(report.retentionPlan.deletedCount)}.`);
13469
+ }
13470
+ if (requireDeletionProof && !report.deletionProof) {
13471
+ issues.push("Expected deletion proof to be present.");
13472
+ }
13473
+ if (report.deletionProof && requireDeletionDryRun && !report.deletionProof.dryRun) {
13474
+ issues.push("Expected deletion proof to run in dry-run mode.");
13475
+ }
13476
+ if (maxDeletionDeleted !== undefined && deletionDeleted > maxDeletionDeleted) {
13477
+ issues.push(`Expected deletion proof to delete at most ${String(maxDeletionDeleted)} records, found ${String(deletionDeleted)}.`);
13478
+ }
13479
+ if (input.minConfiguredStorage !== undefined && configuredStorage.length < input.minConfiguredStorage) {
13480
+ issues.push(`Expected at least ${String(input.minConfiguredStorage)} configured storage surfaces, found ${String(configuredStorage.length)}.`);
13481
+ }
13482
+ if (requireSelfHostedStorage) {
13483
+ const nonSelfHostedConfigured = configuredStorage.length - selfHostedConfiguredStorage.length;
13484
+ if (nonSelfHostedConfigured > (input.maxMissingSelfHostedStorage ?? 0)) {
13485
+ issues.push(`Expected configured storage to be self-hosted, found ${String(nonSelfHostedConfigured)} non-self-hosted surfaces.`);
13486
+ }
13487
+ }
13488
+ const missingConfiguredStorage = findMissing(configuredStorage, input.requiredStorage);
13489
+ if (missingConfiguredStorage.length > (input.maxMissingConfiguredStorage ?? 0)) {
13490
+ issues.push(`Missing configured storage surfaces: ${missingConfiguredStorage.join(", ")}.`);
13491
+ }
13492
+ for (const control of findMissing(controls, input.requiredControls)) {
13493
+ issues.push(`Missing configured storage control: ${control}.`);
13494
+ }
13495
+ for (const scope of findMissing(retentionScopes, input.requiredRetentionScopes)) {
13496
+ issues.push(`Missing retention scope: ${scope}.`);
13497
+ }
13498
+ for (const scope of input.requiredRetentionScopes ?? []) {
13499
+ const retentionScope = report.retentionPlan.scopes.find((candidate) => candidate.scope === scope);
13500
+ if (retentionScope?.skippedReason) {
13501
+ issues.push(`Retention scope ${scope} was skipped: ${retentionScope.skippedReason}.`);
13502
+ }
13503
+ }
13504
+ for (const scope of findMissing(deletionScopes, input.requiredDeletionScopes)) {
13505
+ issues.push(`Missing deletion-proof scope: ${scope}.`);
13506
+ }
13507
+ for (const scope of input.requiredDeletionScopes ?? []) {
13508
+ const deletionScope = report.deletionProof?.scopes.find((candidate) => candidate.scope === scope);
13509
+ if (deletionScope?.skippedReason) {
13510
+ issues.push(`Deletion-proof scope ${scope} was skipped: ${deletionScope.skippedReason}.`);
13511
+ }
13512
+ }
13513
+ for (const provider of input.requiredProviderKeys ?? []) {
13514
+ if (!providerKeys.includes(provider.toLowerCase())) {
13515
+ issues.push(`Missing provider-key guidance: ${provider}.`);
13516
+ }
13517
+ }
13518
+ if (input.minProviderKeys !== undefined && providerKeys.length < input.minProviderKeys) {
13519
+ issues.push(`Expected at least ${String(input.minProviderKeys)} provider-key guidance entries, found ${String(providerKeys.length)}.`);
13520
+ }
13521
+ return {
13522
+ auditExportEvents,
13523
+ configuredStorage: configuredStorage.sort(),
13524
+ controls,
13525
+ deletionDeleted,
13526
+ deletionDryRun: report.deletionProof?.dryRun,
13527
+ deletionScopes,
13528
+ issues,
13529
+ ok: issues.length === 0,
13530
+ providerKeys,
13531
+ redactionEnabled: report.redaction.enabled,
13532
+ retentionDeleted: report.retentionPlan.deletedCount,
13533
+ retentionDryRun: report.retentionPlan.dryRun,
13534
+ retentionScopes,
13535
+ selfHostedConfiguredStorage: selfHostedConfiguredStorage.sort(),
13536
+ zeroRetentionAvailable: report.zeroRetentionAvailable
13537
+ };
13538
+ };
13539
+ var assertVoiceDataControlEvidence = (report, input = {}) => {
13540
+ const assertion = evaluateVoiceDataControlEvidence(report, input);
13541
+ if (!assertion.ok) {
13542
+ throw new Error(`Voice data-control evidence assertion failed: ${assertion.issues.join(" ")}`);
13543
+ }
13544
+ return assertion;
13545
+ };
13321
13546
  var createVoiceZeroRetentionPolicy = (options) => ({
13322
13547
  ...options,
13323
13548
  beforeOrAt: options.beforeOrAt ?? Date.now(),
@@ -22582,7 +22807,7 @@ var statusRank = {
22582
22807
  var escapeHtml36 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
22583
22808
  var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
22584
22809
  var rate3 = (count, total) => count / Math.max(1, total);
22585
- var uniqueSorted = (values) => [
22810
+ var uniqueSorted2 = (values) => [
22586
22811
  ...new Set(values.filter((value) => typeof value === "string"))
22587
22812
  ].sort();
22588
22813
  var percentile3 = (values, rank) => {
@@ -22765,7 +22990,7 @@ var buildVoiceProviderSloReport = async (options = {}) => {
22765
22990
  var evaluateVoiceProviderSloEvidence = (report, input = {}) => {
22766
22991
  const issues = [];
22767
22992
  const kindReports = Object.values(report.kinds);
22768
- const providers = uniqueSorted(kindReports.flatMap((kind) => kind.providers));
22993
+ const providers = uniqueSorted2(kindReports.flatMap((kind) => kind.providers));
22769
22994
  const kinds = providerKinds.filter((kind) => report.kinds[kind].events > 0);
22770
22995
  const fallbacks = kindReports.reduce((total, kind) => total + kind.fallbacks, 0);
22771
22996
  const timeouts = kindReports.reduce((total, kind) => total + kind.timeouts, 0);
@@ -23486,7 +23711,7 @@ var hasPayloadValue = (payload, key, values) => {
23486
23711
  return typeof value === "string" && values.has(value);
23487
23712
  };
23488
23713
  var countIntegrationDeliveryStatus = (events, status) => events.filter((event) => event.deliveryStatus === status).length;
23489
- var uniqueSorted2 = (values) => [
23714
+ var uniqueSorted3 = (values) => [
23490
23715
  ...new Set(values.filter((value) => typeof value === "string"))
23491
23716
  ].sort();
23492
23717
  var pushMissingValuesIssue = (input) => {
@@ -23665,11 +23890,11 @@ var buildVoiceOperationsRecord = async (options) => {
23665
23890
  var evaluateVoiceOperationsRecordGuardrails = (record, input = {}) => {
23666
23891
  const issues = [];
23667
23892
  const decisions = record.guardrails.decisions;
23668
- const proofs = uniqueSorted2(decisions.map((decision) => decision.proof));
23669
- const ruleIds = uniqueSorted2(decisions.flatMap((decision) => decision.findings.map((finding) => finding.ruleId)));
23670
- const stages = uniqueSorted2(decisions.map((decision) => decision.stage));
23671
- const statuses = uniqueSorted2(decisions.map((decision) => decision.status));
23672
- const toolNames = uniqueSorted2(decisions.map((decision) => decision.toolName));
23893
+ const proofs = uniqueSorted3(decisions.map((decision) => decision.proof));
23894
+ const ruleIds = uniqueSorted3(decisions.flatMap((decision) => decision.findings.map((finding) => finding.ruleId)));
23895
+ const stages = uniqueSorted3(decisions.map((decision) => decision.stage));
23896
+ const statuses = uniqueSorted3(decisions.map((decision) => decision.status));
23897
+ const toolNames = uniqueSorted3(decisions.map((decision) => decision.toolName));
23673
23898
  const minDecisions = input.minDecisions ?? 1;
23674
23899
  if (record.guardrails.total < minDecisions) {
23675
23900
  issues.push(`Expected at least ${String(minDecisions)} guardrail decisions, found ${String(record.guardrails.total)}.`);
@@ -30922,6 +31147,9 @@ export {
30922
31147
  evaluateVoiceObservabilityExportReplayEvidence,
30923
31148
  evaluateVoiceObservabilityExportDeliveryEvidence,
30924
31149
  evaluateVoiceGuardrailPolicy,
31150
+ evaluateVoiceDataControlEvidence,
31151
+ evaluateVoiceCampaignReadinessEvidence,
31152
+ evaluateVoiceCampaignDialerProofEvidence,
30925
31153
  evaluateVoiceAgentSquadContractEvidence,
30926
31154
  encodeTwilioMulawBase64,
30927
31155
  deliverVoiceTraceEventsToSinks,
@@ -31251,6 +31479,9 @@ export {
31251
31479
  assertVoiceObservabilityExportRecord,
31252
31480
  assertVoiceObservabilityExportDeliveryEvidence,
31253
31481
  assertVoiceLatencySLOGate,
31482
+ assertVoiceDataControlEvidence,
31483
+ assertVoiceCampaignReadinessEvidence,
31484
+ assertVoiceCampaignDialerProofEvidence,
31254
31485
  assertVoiceAgentSquadContractEvidence,
31255
31486
  assertVoiceAgentSquadContract,
31256
31487
  applyVoiceTelephonyOutcome,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.257",
3
+ "version": "0.0.22-beta.259",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",