@absolutejs/voice 0.0.22-beta.227 → 0.0.22-beta.229
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/README.md +27 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +181 -4
- package/dist/observabilityExport.d.ts +30 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2753,6 +2753,19 @@ Readiness emits the stable `voice.readiness.ops_recovery` gate code when unresol
|
|
|
2753
2753
|
|
|
2754
2754
|
Use observability exports when a buyer wants the hosted-dashboard evidence graph, but inside their own storage, warehouse, SIEM, incident flow, or release notes. The export manifest links traces, audits, operations records, delivery queues, provider SLOs, readiness reports, screenshots, and proof-pack artifacts without making AbsoluteJS Voice the dashboard.
|
|
2755
2755
|
|
|
2756
|
+
Every export manifest and artifact index includes a stable schema contract:
|
|
2757
|
+
|
|
2758
|
+
```ts
|
|
2759
|
+
import {
|
|
2760
|
+
assertVoiceObservabilityExportSchema,
|
|
2761
|
+
voiceObservabilityExportSchemaId,
|
|
2762
|
+
voiceObservabilityExportSchemaVersion
|
|
2763
|
+
} from '@absolutejs/voice';
|
|
2764
|
+
|
|
2765
|
+
assertVoiceObservabilityExportSchema(exportReport);
|
|
2766
|
+
console.log(voiceObservabilityExportSchemaId, voiceObservabilityExportSchemaVersion);
|
|
2767
|
+
```
|
|
2768
|
+
|
|
2756
2769
|
```ts
|
|
2757
2770
|
import {
|
|
2758
2771
|
buildVoiceObservabilityExport,
|
|
@@ -2781,6 +2794,19 @@ app.use(
|
|
|
2781
2794
|
keyPrefix: 'voice/observability-exports',
|
|
2782
2795
|
kind: 's3',
|
|
2783
2796
|
label: 'S3 customer-owned observability archive'
|
|
2797
|
+
},
|
|
2798
|
+
{
|
|
2799
|
+
kind: 'sqlite',
|
|
2800
|
+
path: '.voice-runtime/observability-exports.sqlite',
|
|
2801
|
+
tableName: 'voice_observability_exports',
|
|
2802
|
+
label: 'SQLite customer-owned observability warehouse'
|
|
2803
|
+
},
|
|
2804
|
+
{
|
|
2805
|
+
connectionString: process.env.VOICE_OBSERVABILITY_EXPORT_POSTGRES_URL,
|
|
2806
|
+
kind: 'postgres',
|
|
2807
|
+
schemaName: 'voice',
|
|
2808
|
+
tableName: 'observability_exports',
|
|
2809
|
+
label: 'Postgres customer-owned observability warehouse'
|
|
2784
2810
|
}
|
|
2785
2811
|
],
|
|
2786
2812
|
deliveryReceipts: observabilityReceipts,
|
|
@@ -2819,7 +2845,7 @@ const exportReport = await buildVoiceObservabilityExport({
|
|
|
2819
2845
|
});
|
|
2820
2846
|
```
|
|
2821
2847
|
|
|
2822
|
-
The route helper exposes JSON at `/api/voice/observability-export`, an artifact index at `/api/voice/observability-export/artifacts`, per-artifact downloads at `/api/voice/observability-export/artifacts/:artifactId`, delivery at `POST /api/voice/observability-export/deliveries`, delivery history at `GET /api/voice/observability-export/deliveries`, Markdown at `/voice/observability-export.md`, and HTML at `/voice/observability-export`. Path-backed artifacts are hashed with SHA-256 by default, include byte size and freshness metadata, and can fail the export when required evidence is missing or stale. File delivery writes `manifest.json`, `artifact-index.json`, and artifact files into a customer-owned archive directory; webhook delivery posts the manifest and artifact index to a buyer-owned collector, SIEM bridge, or warehouse endpoint; S3 delivery writes the same manifest, index, and artifact files through Bun's native S3 client. Delivery receipt stores persist run id, destinations, status, and target history so operators can prove exports have been continuously healthy. Failed trace/audit deliveries fail the export report, pending deliveries warn, and every trace/audit envelope includes the linked operations-record URL when one is configured. This is the primitive to use when customers ask how voice evidence leaves the app without going through a hosted vendor dashboard.
|
|
2848
|
+
The route helper exposes JSON at `/api/voice/observability-export`, an artifact index at `/api/voice/observability-export/artifacts`, per-artifact downloads at `/api/voice/observability-export/artifacts/:artifactId`, delivery at `POST /api/voice/observability-export/deliveries`, delivery history at `GET /api/voice/observability-export/deliveries`, Markdown at `/voice/observability-export.md`, and HTML at `/voice/observability-export`. Path-backed artifacts are hashed with SHA-256 by default, include byte size and freshness metadata, and can fail the export when required evidence is missing or stale. File delivery writes `manifest.json`, `artifact-index.json`, and artifact files into a customer-owned archive directory; webhook delivery posts the manifest and artifact index to a buyer-owned collector, SIEM bridge, or warehouse endpoint; S3 delivery writes the same manifest, index, and artifact files through Bun's native S3 client; SQLite and Postgres delivery persist the schema id/version, manifest, artifact index, checksum metadata, status, run id, and timestamps into buyer-owned database tables. Delivery receipt stores persist run id, destinations, status, schema, and target history so operators can prove exports have been continuously healthy. Failed trace/audit deliveries fail the export report, pending deliveries warn, and every trace/audit envelope includes the linked operations-record URL when one is configured. This is the primitive to use when customers ask how voice evidence leaves the app without going through a hosted vendor dashboard.
|
|
2823
2849
|
|
|
2824
2850
|
Pass the same report into production readiness when export health should block deploys:
|
|
2825
2851
|
|
package/dist/index.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export { createVoiceReadinessProfile, recommendVoiceReadinessProfile } from './r
|
|
|
53
53
|
export { buildVoiceProviderContractMatrix, createVoiceProviderContractMatrixHTMLHandler, createVoiceProviderContractMatrixJSONHandler, createVoiceProviderContractMatrixPreset, createVoiceProviderContractMatrixRoutes, evaluateVoiceProviderStackGaps, renderVoiceProviderContractMatrixHTML, recommendVoiceProviderStack } from './providerStackRecommendations';
|
|
54
54
|
export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
|
|
55
55
|
export { buildVoiceOperationsRecord, createVoiceOperationsRecordRoutes, renderVoiceOperationsRecordHTML, renderVoiceOperationsRecordIncidentMarkdown } from './operationsRecord';
|
|
56
|
-
export { buildVoiceObservabilityArtifactIndex, buildVoiceObservabilityExportDeliveryHistory, buildVoiceObservabilityExport, createVoiceFileObservabilityExportDeliveryReceiptStore, createVoiceMemoryObservabilityExportDeliveryReceiptStore, createVoiceObservabilityExportRoutes, deliverVoiceObservabilityExport, renderVoiceObservabilityExportMarkdown } from './observabilityExport';
|
|
56
|
+
export { buildVoiceObservabilityArtifactIndex, buildVoiceObservabilityExportDeliveryHistory, buildVoiceObservabilityExport, assertVoiceObservabilityExportSchema, createVoiceObservabilityExportSchema, createVoiceFileObservabilityExportDeliveryReceiptStore, createVoiceMemoryObservabilityExportDeliveryReceiptStore, createVoiceObservabilityExportRoutes, deliverVoiceObservabilityExport, renderVoiceObservabilityExportMarkdown, voiceObservabilityExportSchemaId, voiceObservabilityExportSchemaVersion } from './observabilityExport';
|
|
57
57
|
export { buildVoiceOpsRecoveryReadinessCheck, buildVoiceOpsRecoveryReport, createVoiceOpsRecoveryRoutes, renderVoiceOpsRecoveryHTML, renderVoiceOpsRecoveryMarkdown } from './opsRecovery';
|
|
58
58
|
export { buildVoiceIncidentBundle, createStoredVoiceIncidentBundleArtifact, createVoiceIncidentBundleRoutes, createVoiceMemoryIncidentBundleStore, pruneVoiceIncidentBundleArtifacts, saveVoiceIncidentBundleArtifact } from './incidentBundle';
|
|
59
59
|
export { summarizeVoiceOpsStatus } from './opsStatus';
|
|
@@ -118,7 +118,7 @@ export type { VoiceProductionReadinessAction, VoiceProductionReadinessAuditOptio
|
|
|
118
118
|
export type { VoiceReadinessProfileName, VoiceReadinessProfileOptions, VoiceReadinessProfileRecommendation, VoiceReadinessProfileRecommendationScore, VoiceReadinessProfileRoutesOptions } from './readinessProfiles';
|
|
119
119
|
export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderContractCheck, VoiceProviderContractCheckStatus, VoiceProviderContractDefinition, VoiceProviderContractMatrixHandlerOptions, VoiceProviderContractMatrixHTMLHandlerOptions, VoiceProviderContractMatrixInput, VoiceProviderContractMatrixPresetOptions, VoiceProviderContractMatrixReport, VoiceProviderContractMatrixRoutesOptions, VoiceProviderContractMatrixRow, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
|
|
120
120
|
export type { VoiceOperationsRecord, VoiceOperationsRecordAgentHandoff, VoiceOperationsRecordAuditSummary, VoiceOperationsRecordIntegrationEventSummary, VoiceOperationsRecordOptions, VoiceOperationsRecordOutcome, VoiceOperationsRecordProviderDecision, VoiceOperationsRecordReviewSummary, VoiceOperationsRecordRoutesOptions, VoiceOperationsRecordStatus, VoiceOperationsRecordTaskSummary, VoiceOperationsRecordTranscriptTurn, VoiceOperationsRecordTool } from './operationsRecord';
|
|
121
|
-
export type { VoiceObservabilityExportArtifact, VoiceObservabilityExportArtifactChecksum, VoiceObservabilityExportArtifactFreshness, VoiceObservabilityExportArtifactIndex, VoiceObservabilityExportArtifactIndexItem, VoiceObservabilityExportArtifactKind, VoiceObservabilityExportDeliverySummary, VoiceObservabilityExportDeliveryDestination, VoiceObservabilityExportDeliveryDestinationResult, VoiceObservabilityExportDeliveryHistory, VoiceObservabilityExportDeliveryOptions, VoiceObservabilityExportDeliveryReceipt, VoiceObservabilityExportDeliveryReceiptStore, VoiceObservabilityExportDeliveryReport, VoiceObservabilityExportEnvelope, VoiceObservabilityExportIssue, VoiceObservabilityExportIssueCode, VoiceObservabilityExportOptions, VoiceObservabilityExportRedactionSummary, VoiceObservabilityExportReport, VoiceObservabilityExportRoutesOptions, VoiceObservabilityExportStatus } from './observabilityExport';
|
|
121
|
+
export type { VoiceObservabilityExportArtifact, VoiceObservabilityExportArtifactChecksum, VoiceObservabilityExportArtifactFreshness, VoiceObservabilityExportArtifactIndex, VoiceObservabilityExportArtifactIndexItem, VoiceObservabilityExportArtifactKind, VoiceObservabilityExportDeliverySummary, VoiceObservabilityExportDeliveryDestination, VoiceObservabilityExportDeliveryDestinationResult, VoiceObservabilityExportDeliveryHistory, VoiceObservabilityExportDeliveryOptions, VoiceObservabilityExportDeliveryReceipt, VoiceObservabilityExportDeliveryReceiptStore, VoiceObservabilityExportDeliveryReport, VoiceObservabilityExportEnvelope, VoiceObservabilityExportIssue, VoiceObservabilityExportIssueCode, VoiceObservabilityExportOptions, VoiceObservabilityExportRedactionSummary, VoiceObservabilityExportReport, VoiceObservabilityExportRoutesOptions, VoiceObservabilityExportSchema, VoiceObservabilityExportStatus } from './observabilityExport';
|
|
122
122
|
export type { VoiceOpsRecoveryFailedSession, VoiceOpsRecoveryInterventionSummary, VoiceOpsRecoveryIssue, VoiceOpsRecoveryIssueCode, VoiceOpsRecoveryLinks, VoiceOpsRecoveryProviderSummary, VoiceOpsRecoveryReport, VoiceOpsRecoveryReportOptions, VoiceOpsRecoveryRoutesOptions, VoiceOpsRecoveryStatus } from './opsRecovery';
|
|
123
123
|
export type { StoredVoiceIncidentBundleArtifact, VoiceIncidentBundle, VoiceIncidentBundleArtifactOptions, VoiceIncidentBundleFormat, VoiceIncidentBundleOptions, VoiceIncidentBundleRetentionOptions, VoiceIncidentBundleRetentionReport, VoiceIncidentBundleRoutesOptions, VoiceIncidentBundleStore, VoiceIncidentBundleStoreFilter, VoiceIncidentBundleSummary } from './incidentBundle';
|
|
124
124
|
export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
|
package/dist/index.js
CHANGED
|
@@ -22448,6 +22448,7 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
22448
22448
|
|
|
22449
22449
|
// src/observabilityExport.ts
|
|
22450
22450
|
import { Elysia as Elysia39 } from "elysia";
|
|
22451
|
+
import { Database } from "bun:sqlite";
|
|
22451
22452
|
import { createHash } from "crypto";
|
|
22452
22453
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
22453
22454
|
import { join as join3 } from "path";
|
|
@@ -22986,6 +22987,17 @@ var createVoiceOperationsRecordRoutes = (options) => {
|
|
|
22986
22987
|
};
|
|
22987
22988
|
|
|
22988
22989
|
// src/observabilityExport.ts
|
|
22990
|
+
var voiceObservabilityExportSchemaVersion = "1.0.0";
|
|
22991
|
+
var voiceObservabilityExportSchemaId = "com.absolutejs.voice.observability-export";
|
|
22992
|
+
var createVoiceObservabilityExportSchema = () => ({
|
|
22993
|
+
id: voiceObservabilityExportSchemaId,
|
|
22994
|
+
version: voiceObservabilityExportSchemaVersion
|
|
22995
|
+
});
|
|
22996
|
+
var assertVoiceObservabilityExportSchema = (input) => {
|
|
22997
|
+
if (input.schema?.id !== voiceObservabilityExportSchemaId || input.schema?.version !== voiceObservabilityExportSchemaVersion) {
|
|
22998
|
+
throw new Error(`Unsupported voice observability export schema: ${input.schema?.id ?? "missing"}@${input.schema?.version ?? "missing"}`);
|
|
22999
|
+
}
|
|
23000
|
+
};
|
|
22989
23001
|
var isDeliveryStore = (value) => !Array.isArray(value) && typeof value.list === "function";
|
|
22990
23002
|
var getString17 = (value) => typeof value === "string" ? value : undefined;
|
|
22991
23003
|
var getProviderKind = (payload) => getString17(payload.kind) ?? getString17(payload.providerKind);
|
|
@@ -23038,6 +23050,117 @@ var writeS3Object = async (input) => {
|
|
|
23038
23050
|
type: input.contentType
|
|
23039
23051
|
});
|
|
23040
23052
|
};
|
|
23053
|
+
var quoteObservabilityIdentifier = (value) => `"${value.replace(/"/g, '""')}"`;
|
|
23054
|
+
var normalizeObservabilityIdentifier = (value) => value?.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice_observability_exports";
|
|
23055
|
+
var buildObservabilityExportDatabaseRecord = (input) => ({
|
|
23056
|
+
artifactCount: input.artifactIndex.summary.total,
|
|
23057
|
+
artifactIndex: input.artifactIndex,
|
|
23058
|
+
checkedAt: input.checkedAt,
|
|
23059
|
+
exportStatus: input.report.status,
|
|
23060
|
+
manifest: input.report,
|
|
23061
|
+
runId: input.runId,
|
|
23062
|
+
schema: input.report.schema,
|
|
23063
|
+
status: input.report.status
|
|
23064
|
+
});
|
|
23065
|
+
var deliverObservabilityExportToSQLite = async (input) => {
|
|
23066
|
+
if (!input.destination.database && !input.destination.path) {
|
|
23067
|
+
throw new Error("SQLite observability export delivery requires destination.database or destination.path.");
|
|
23068
|
+
}
|
|
23069
|
+
const database = input.destination.database ?? new Database(input.destination.path, { create: true });
|
|
23070
|
+
const table = quoteObservabilityIdentifier(normalizeObservabilityIdentifier(input.destination.tableName));
|
|
23071
|
+
const record = buildObservabilityExportDatabaseRecord(input);
|
|
23072
|
+
database.exec(`CREATE TABLE IF NOT EXISTS ${table} (
|
|
23073
|
+
run_id TEXT PRIMARY KEY,
|
|
23074
|
+
checked_at INTEGER NOT NULL,
|
|
23075
|
+
status TEXT NOT NULL,
|
|
23076
|
+
export_status TEXT NOT NULL,
|
|
23077
|
+
artifact_count INTEGER NOT NULL,
|
|
23078
|
+
manifest_json TEXT NOT NULL,
|
|
23079
|
+
artifact_index_json TEXT NOT NULL,
|
|
23080
|
+
payload_json TEXT NOT NULL
|
|
23081
|
+
)`);
|
|
23082
|
+
database.query(`INSERT INTO ${table}
|
|
23083
|
+
(run_id, checked_at, status, export_status, artifact_count, manifest_json, artifact_index_json, payload_json)
|
|
23084
|
+
VALUES ($runId, $checkedAt, $status, $exportStatus, $artifactCount, $manifest, $artifactIndex, $payload)
|
|
23085
|
+
ON CONFLICT(run_id) DO UPDATE SET
|
|
23086
|
+
checked_at = excluded.checked_at,
|
|
23087
|
+
status = excluded.status,
|
|
23088
|
+
export_status = excluded.export_status,
|
|
23089
|
+
artifact_count = excluded.artifact_count,
|
|
23090
|
+
manifest_json = excluded.manifest_json,
|
|
23091
|
+
artifact_index_json = excluded.artifact_index_json,
|
|
23092
|
+
payload_json = excluded.payload_json`).run({
|
|
23093
|
+
$artifactCount: input.artifactIndex.summary.total,
|
|
23094
|
+
$artifactIndex: input.index,
|
|
23095
|
+
$checkedAt: input.checkedAt,
|
|
23096
|
+
$exportStatus: input.report.status,
|
|
23097
|
+
$manifest: input.manifest,
|
|
23098
|
+
$payload: JSON.stringify(record),
|
|
23099
|
+
$runId: input.runId,
|
|
23100
|
+
$status: input.report.status
|
|
23101
|
+
});
|
|
23102
|
+
return input.destination.path ? `sqlite://${input.destination.path}/${table.replaceAll('"', "")}` : `sqlite://memory/${table.replaceAll('"', "")}`;
|
|
23103
|
+
};
|
|
23104
|
+
var deliverObservabilityExportToPostgres = async (input) => {
|
|
23105
|
+
const sql = input.destination.sql ?? (input.destination.connectionString ? (() => {
|
|
23106
|
+
const client = new Bun.SQL(input.destination.connectionString);
|
|
23107
|
+
return { unsafe: client.unsafe.bind(client) };
|
|
23108
|
+
})() : undefined);
|
|
23109
|
+
if (!sql) {
|
|
23110
|
+
throw new Error("Postgres observability export delivery requires destination.sql or destination.connectionString.");
|
|
23111
|
+
}
|
|
23112
|
+
const schema = normalizeObservabilityIdentifier(input.destination.schemaName ?? "public");
|
|
23113
|
+
const table = normalizeObservabilityIdentifier(input.destination.tableName);
|
|
23114
|
+
const qualifiedTable = `${quoteObservabilityIdentifier(schema)}.${quoteObservabilityIdentifier(table)}`;
|
|
23115
|
+
const record = buildObservabilityExportDatabaseRecord(input);
|
|
23116
|
+
await sql.unsafe(`CREATE SCHEMA IF NOT EXISTS ${quoteObservabilityIdentifier(schema)}`);
|
|
23117
|
+
await sql.unsafe(`CREATE TABLE IF NOT EXISTS ${qualifiedTable} (
|
|
23118
|
+
run_id TEXT PRIMARY KEY,
|
|
23119
|
+
checked_at BIGINT NOT NULL,
|
|
23120
|
+
status TEXT NOT NULL,
|
|
23121
|
+
export_status TEXT NOT NULL,
|
|
23122
|
+
artifact_count INTEGER NOT NULL,
|
|
23123
|
+
manifest_json JSONB NOT NULL,
|
|
23124
|
+
artifact_index_json JSONB NOT NULL,
|
|
23125
|
+
payload JSONB NOT NULL
|
|
23126
|
+
)`);
|
|
23127
|
+
await sql.unsafe(`INSERT INTO ${qualifiedTable}
|
|
23128
|
+
(run_id, checked_at, status, export_status, artifact_count, manifest_json, artifact_index_json, payload)
|
|
23129
|
+
VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7::jsonb, $8::jsonb)
|
|
23130
|
+
ON CONFLICT (run_id) DO UPDATE SET
|
|
23131
|
+
checked_at = EXCLUDED.checked_at,
|
|
23132
|
+
status = EXCLUDED.status,
|
|
23133
|
+
export_status = EXCLUDED.export_status,
|
|
23134
|
+
artifact_count = EXCLUDED.artifact_count,
|
|
23135
|
+
manifest_json = EXCLUDED.manifest_json,
|
|
23136
|
+
artifact_index_json = EXCLUDED.artifact_index_json,
|
|
23137
|
+
payload = EXCLUDED.payload`, [
|
|
23138
|
+
input.runId,
|
|
23139
|
+
input.checkedAt,
|
|
23140
|
+
input.report.status,
|
|
23141
|
+
input.report.status,
|
|
23142
|
+
input.artifactIndex.summary.total,
|
|
23143
|
+
input.manifest,
|
|
23144
|
+
input.index,
|
|
23145
|
+
JSON.stringify(record)
|
|
23146
|
+
]);
|
|
23147
|
+
return `postgres://${schema}/${table}`;
|
|
23148
|
+
};
|
|
23149
|
+
var observabilityExportDeliveryFailureTarget = (destination) => {
|
|
23150
|
+
if (destination.kind === "file") {
|
|
23151
|
+
return destination.directory;
|
|
23152
|
+
}
|
|
23153
|
+
if (destination.kind === "s3") {
|
|
23154
|
+
return destination.bucket ? `s3://${destination.bucket}/${normalizeExportS3KeyPrefix(destination.keyPrefix)}` : normalizeExportS3KeyPrefix(destination.keyPrefix);
|
|
23155
|
+
}
|
|
23156
|
+
if (destination.kind === "sqlite") {
|
|
23157
|
+
return destination.path ?? "sqlite://memory";
|
|
23158
|
+
}
|
|
23159
|
+
if (destination.kind === "postgres") {
|
|
23160
|
+
return destination.connectionString ?? "postgres://configured-client";
|
|
23161
|
+
}
|
|
23162
|
+
return destination.url;
|
|
23163
|
+
};
|
|
23041
23164
|
var createVoiceMemoryObservabilityExportDeliveryReceiptStore = () => {
|
|
23042
23165
|
const receipts = new Map;
|
|
23043
23166
|
return {
|
|
@@ -23349,6 +23472,7 @@ var buildVoiceObservabilityExport = async (options = {}) => {
|
|
|
23349
23472
|
enabled: Boolean(options.redact),
|
|
23350
23473
|
mode: options.redact ? "redacted" : "none"
|
|
23351
23474
|
},
|
|
23475
|
+
schema: createVoiceObservabilityExportSchema(),
|
|
23352
23476
|
sessionIds,
|
|
23353
23477
|
status,
|
|
23354
23478
|
summary: {
|
|
@@ -23417,6 +23541,7 @@ var buildVoiceObservabilityArtifactIndex = (report) => {
|
|
|
23417
23541
|
return {
|
|
23418
23542
|
artifacts,
|
|
23419
23543
|
checkedAt: report.checkedAt,
|
|
23544
|
+
schema: report.schema,
|
|
23420
23545
|
status: report.status,
|
|
23421
23546
|
summary: {
|
|
23422
23547
|
downloadable: artifacts.filter((artifact) => artifact.downloadHref).length,
|
|
@@ -23437,7 +23562,7 @@ var deliverVoiceObservabilityExport = async (options) => {
|
|
|
23437
23562
|
`;
|
|
23438
23563
|
const destinations = await Promise.all(options.destinations.map(async (destination) => {
|
|
23439
23564
|
const destinationId = destination.id ?? `${destination.kind}-${destination.label ?? "export"}`;
|
|
23440
|
-
const label = destination.label ?? (destination.kind === "file" ? "File observability export" : "Webhook observability export");
|
|
23565
|
+
const label = destination.label ?? (destination.kind === "file" ? "File observability export" : destination.kind === "s3" ? "S3 observability export" : destination.kind === "sqlite" ? "SQLite observability export" : destination.kind === "postgres" ? "Postgres observability export" : "Webhook observability export");
|
|
23441
23566
|
try {
|
|
23442
23567
|
if (destination.kind === "file") {
|
|
23443
23568
|
const target = join3(destination.directory, runId);
|
|
@@ -23459,6 +23584,7 @@ var deliverVoiceObservabilityExport = async (options) => {
|
|
|
23459
23584
|
destinationKind: destination.kind,
|
|
23460
23585
|
label,
|
|
23461
23586
|
manifestBytes: byteLength(manifest),
|
|
23587
|
+
schema: options.report.schema,
|
|
23462
23588
|
status: "delivered",
|
|
23463
23589
|
target
|
|
23464
23590
|
};
|
|
@@ -23503,10 +23629,55 @@ var deliverVoiceObservabilityExport = async (options) => {
|
|
|
23503
23629
|
destinationKind: destination.kind,
|
|
23504
23630
|
label,
|
|
23505
23631
|
manifestBytes: byteLength(manifest),
|
|
23632
|
+
schema: options.report.schema,
|
|
23506
23633
|
status: "delivered",
|
|
23507
23634
|
target: destination.bucket ? `s3://${destination.bucket}/${rootKey}` : rootKey
|
|
23508
23635
|
};
|
|
23509
23636
|
}
|
|
23637
|
+
if (destination.kind === "sqlite") {
|
|
23638
|
+
const target = await deliverObservabilityExportToSQLite({
|
|
23639
|
+
artifactIndex,
|
|
23640
|
+
checkedAt,
|
|
23641
|
+
destination,
|
|
23642
|
+
index,
|
|
23643
|
+
manifest,
|
|
23644
|
+
report: options.report,
|
|
23645
|
+
runId
|
|
23646
|
+
});
|
|
23647
|
+
return {
|
|
23648
|
+
artifactCount: artifactIndex.summary.total,
|
|
23649
|
+
deliveredAt: Date.now(),
|
|
23650
|
+
destinationId,
|
|
23651
|
+
destinationKind: destination.kind,
|
|
23652
|
+
label,
|
|
23653
|
+
manifestBytes: byteLength(manifest),
|
|
23654
|
+
schema: options.report.schema,
|
|
23655
|
+
status: "delivered",
|
|
23656
|
+
target
|
|
23657
|
+
};
|
|
23658
|
+
}
|
|
23659
|
+
if (destination.kind === "postgres") {
|
|
23660
|
+
const target = await deliverObservabilityExportToPostgres({
|
|
23661
|
+
artifactIndex,
|
|
23662
|
+
checkedAt,
|
|
23663
|
+
destination,
|
|
23664
|
+
index,
|
|
23665
|
+
manifest,
|
|
23666
|
+
report: options.report,
|
|
23667
|
+
runId
|
|
23668
|
+
});
|
|
23669
|
+
return {
|
|
23670
|
+
artifactCount: artifactIndex.summary.total,
|
|
23671
|
+
deliveredAt: Date.now(),
|
|
23672
|
+
destinationId,
|
|
23673
|
+
destinationKind: destination.kind,
|
|
23674
|
+
label,
|
|
23675
|
+
manifestBytes: byteLength(manifest),
|
|
23676
|
+
schema: options.report.schema,
|
|
23677
|
+
status: "delivered",
|
|
23678
|
+
target
|
|
23679
|
+
};
|
|
23680
|
+
}
|
|
23510
23681
|
const controller = new AbortController;
|
|
23511
23682
|
const timeout = setTimeout(() => controller.abort(), destination.timeoutMs ?? 1e4);
|
|
23512
23683
|
try {
|
|
@@ -23538,6 +23709,7 @@ var deliverVoiceObservabilityExport = async (options) => {
|
|
|
23538
23709
|
destinationKind: destination.kind,
|
|
23539
23710
|
label,
|
|
23540
23711
|
manifestBytes: byteLength(manifest),
|
|
23712
|
+
schema: options.report.schema,
|
|
23541
23713
|
status: "delivered",
|
|
23542
23714
|
target: destination.url
|
|
23543
23715
|
};
|
|
@@ -23550,8 +23722,9 @@ var deliverVoiceObservabilityExport = async (options) => {
|
|
|
23550
23722
|
error: error instanceof Error ? error.message : String(error),
|
|
23551
23723
|
label,
|
|
23552
23724
|
manifestBytes: byteLength(manifest),
|
|
23725
|
+
schema: options.report.schema,
|
|
23553
23726
|
status: "failed",
|
|
23554
|
-
target:
|
|
23727
|
+
target: observabilityExportDeliveryFailureTarget(destination)
|
|
23555
23728
|
};
|
|
23556
23729
|
}
|
|
23557
23730
|
}));
|
|
@@ -26701,7 +26874,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
26701
26874
|
return routes;
|
|
26702
26875
|
};
|
|
26703
26876
|
// src/sqliteStore.ts
|
|
26704
|
-
import { Database } from "bun:sqlite";
|
|
26877
|
+
import { Database as Database2 } from "bun:sqlite";
|
|
26705
26878
|
var normalizeTableNameSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
26706
26879
|
var resolveTableName = (input) => {
|
|
26707
26880
|
if (input.options.tableName) {
|
|
@@ -26712,7 +26885,7 @@ var resolveTableName = (input) => {
|
|
|
26712
26885
|
return `${prefix}_${fallback}`;
|
|
26713
26886
|
};
|
|
26714
26887
|
var openVoiceSQLiteDatabase = (path) => {
|
|
26715
|
-
const database = new
|
|
26888
|
+
const database = new Database2(path, {
|
|
26716
26889
|
create: true
|
|
26717
26890
|
});
|
|
26718
26891
|
database.exec("PRAGMA journal_mode = WAL;");
|
|
@@ -28281,6 +28454,8 @@ export {
|
|
|
28281
28454
|
withVoiceOpsTaskId,
|
|
28282
28455
|
withVoiceIntegrationEventId,
|
|
28283
28456
|
voiceTelephonyOutcomeToRouteResult,
|
|
28457
|
+
voiceObservabilityExportSchemaVersion,
|
|
28458
|
+
voiceObservabilityExportSchemaId,
|
|
28284
28459
|
voiceComplianceRedactionDefaults,
|
|
28285
28460
|
voice,
|
|
28286
28461
|
verifyVoiceTwilioWebhookSignature,
|
|
@@ -28588,6 +28763,7 @@ export {
|
|
|
28588
28763
|
createVoiceOpsConsoleRoutes,
|
|
28589
28764
|
createVoiceOpsActionAuditRoutes,
|
|
28590
28765
|
createVoiceOperationsRecordRoutes,
|
|
28766
|
+
createVoiceObservabilityExportSchema,
|
|
28591
28767
|
createVoiceObservabilityExportRoutes,
|
|
28592
28768
|
createVoiceMemoryTraceSinkDeliveryStore,
|
|
28593
28769
|
createVoiceMemoryTraceEventStore,
|
|
@@ -28745,6 +28921,7 @@ export {
|
|
|
28745
28921
|
buildVoiceAuditDeliveryReport,
|
|
28746
28922
|
assignVoiceOpsTask,
|
|
28747
28923
|
assertVoiceProviderRoutingContract,
|
|
28924
|
+
assertVoiceObservabilityExportSchema,
|
|
28748
28925
|
assertVoiceLatencySLOGate,
|
|
28749
28926
|
assertVoiceAgentSquadContract,
|
|
28750
28927
|
applyVoiceTelephonyOutcome,
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { Elysia } from 'elysia';
|
|
2
2
|
import type { S3Client, S3Options } from 'bun';
|
|
3
|
+
import { Database } from 'bun:sqlite';
|
|
3
4
|
import { type VoiceAuditSinkDeliveryQueueSummary, type VoiceAuditSinkDeliveryRecord, type VoiceAuditSinkDeliveryStore } from './auditSinks';
|
|
4
5
|
import type { VoiceAuditEventStore, VoiceAuditEventType } from './audit';
|
|
5
6
|
import { type VoiceOperationsRecord } from './operationsRecord';
|
|
6
7
|
import { type VoiceTraceSinkDeliveryQueueSummary } from './queue';
|
|
7
8
|
import { type StoredVoiceTraceEvent, type VoiceTraceEventStore, type VoiceTraceEventType, type VoiceTraceRedactionConfig, type VoiceTraceSinkDeliveryRecord, type VoiceTraceSinkDeliveryStore, type VoiceTraceSummary } from './trace';
|
|
9
|
+
import type { VoicePostgresClient } from './postgresStore';
|
|
8
10
|
export type VoiceObservabilityExportStatus = 'fail' | 'pass' | 'warn';
|
|
11
|
+
export declare const voiceObservabilityExportSchemaVersion = "1.0.0";
|
|
12
|
+
export declare const voiceObservabilityExportSchemaId = "com.absolutejs.voice.observability-export";
|
|
13
|
+
export type VoiceObservabilityExportSchema = {
|
|
14
|
+
id: typeof voiceObservabilityExportSchemaId;
|
|
15
|
+
version: typeof voiceObservabilityExportSchemaVersion;
|
|
16
|
+
};
|
|
17
|
+
export declare const createVoiceObservabilityExportSchema: () => VoiceObservabilityExportSchema;
|
|
18
|
+
export declare const assertVoiceObservabilityExportSchema: (input: {
|
|
19
|
+
schema?: Partial<VoiceObservabilityExportSchema>;
|
|
20
|
+
}) => void;
|
|
9
21
|
export type VoiceObservabilityExportArtifactKind = 'incident' | 'markdown' | 'operations-record' | 'proof-pack' | 'readiness' | 'screenshot' | 'slo' | 'trace' | 'audit' | 'custom';
|
|
10
22
|
export type VoiceObservabilityExportArtifactChecksum = {
|
|
11
23
|
algorithm: 'sha256';
|
|
@@ -72,6 +84,7 @@ export type VoiceObservabilityExportReport = {
|
|
|
72
84
|
issues: VoiceObservabilityExportIssue[];
|
|
73
85
|
operationsRecords: VoiceOperationsRecord[];
|
|
74
86
|
redaction: VoiceObservabilityExportRedactionSummary;
|
|
87
|
+
schema: VoiceObservabilityExportSchema;
|
|
75
88
|
sessionIds: string[];
|
|
76
89
|
status: VoiceObservabilityExportStatus;
|
|
77
90
|
summary: {
|
|
@@ -99,6 +112,7 @@ export type VoiceObservabilityExportArtifactIndexItem = {
|
|
|
99
112
|
export type VoiceObservabilityExportArtifactIndex = {
|
|
100
113
|
artifacts: VoiceObservabilityExportArtifactIndexItem[];
|
|
101
114
|
checkedAt: number;
|
|
115
|
+
schema: VoiceObservabilityExportSchema;
|
|
102
116
|
status: VoiceObservabilityExportStatus;
|
|
103
117
|
summary: {
|
|
104
118
|
downloadable: number;
|
|
@@ -123,6 +137,21 @@ export type VoiceObservabilityExportDeliveryDestination = {
|
|
|
123
137
|
kind: 's3';
|
|
124
138
|
label?: string;
|
|
125
139
|
}) | {
|
|
140
|
+
database?: Database;
|
|
141
|
+
id?: string;
|
|
142
|
+
kind: 'sqlite';
|
|
143
|
+
label?: string;
|
|
144
|
+
path?: string;
|
|
145
|
+
tableName?: string;
|
|
146
|
+
} | {
|
|
147
|
+
connectionString?: string;
|
|
148
|
+
id?: string;
|
|
149
|
+
kind: 'postgres';
|
|
150
|
+
label?: string;
|
|
151
|
+
schemaName?: string;
|
|
152
|
+
sql?: VoicePostgresClient;
|
|
153
|
+
tableName?: string;
|
|
154
|
+
} | {
|
|
126
155
|
fetch?: typeof fetch;
|
|
127
156
|
headers?: Record<string, string>;
|
|
128
157
|
id?: string;
|
|
@@ -140,6 +169,7 @@ export type VoiceObservabilityExportDeliveryDestinationResult = {
|
|
|
140
169
|
error?: string;
|
|
141
170
|
label: string;
|
|
142
171
|
manifestBytes: number;
|
|
172
|
+
schema: VoiceObservabilityExportSchema;
|
|
143
173
|
status: 'delivered' | 'failed';
|
|
144
174
|
target: string;
|
|
145
175
|
};
|