Skip to Content
SDK ReferenceTypeScriptveriproof-sdk-core

@veriproof/sdk-core

@veriproof/sdk-core is the TypeScript foundation for VeriProof instrumentation. It handles OpenTelemetry configuration, governance session helpers, transport reliability, Merkle utilities, and optional payload encryption. Framework adapters (LangChain.js, Vercel AI SDK, etc.) build on top of this package.

Compatibility: Node.js ≥ 18, TypeScript ≥ 5.0, OpenTelemetry JS ≥ 2.1


Installation

npm install @veriproof/sdk-core

With a framework adapter:

npm install @veriproof/sdk-core @veriproof/sdk-instrumentation-ai-sdk ai

Setup

configureVeriproof

Call this once at process startup, before any AI framework initializes:

import { configureVeriproof, VeriproofSdkOptions } from '@veriproof/sdk-core'; const { provider, exporter } = configureVeriproof( VeriproofSdkOptions.createDevelopment({ apiKey: process.env.VERIPROOF_API_KEY!, applicationId: 'your-application-id', }), { serviceName: 'your-application-id', setGlobal: true, // registers as the global TracerProvider }, );

After this call, any OTel span created in the process — by your code or by any adapter — is automatically exported to VeriProof.

ConfigureVeriproofOptions

OptionTypeDefaultDescription
serviceNamestringrequiredSets service.name on the OTel resource
setGlobalbooleanfalseRegister as the global OTel TracerProvider
batchExportbooleantrueUse BatchSpanProcessor (recommended for production)
resourceAttributesRecord<string, ...>Additional OTel resource attributes
tracerProviderTracerProviderProvide an existing provider instead of creating one

VeriproofSdkOptions factory

// Development / sandbox VeriproofSdkOptions.createDevelopment({ apiKey, applicationId, tenantId? }) // Production VeriproofSdkOptions.createProduction({ apiKey, applicationId, tenantId? }) // From environment variables: reads VERIPROOF_API_KEY and VERIPROOF_APPLICATION_ID veriproofClientOptionsFromEnv()

Building sessions

Use VeriproofClient to construct and emit governance session traces. The client provides a fluent builder API:

import { VeriproofClient, VeriproofSdkOptions, DecisionContext, SessionMetadata, StepTags, } from '@veriproof/sdk-core'; const client = new VeriproofClient( VeriproofSdkOptions.createProduction({ apiKey: process.env.VERIPROOF_API_KEY!, applicationId: 'loan-underwriting' }), ); const session = client .startSession('loan-decision') .withSessionMetadata( SessionMetadata.forTransaction('txn-4421').withEnvironment('production'), ) .addStep('retrieve_credit_profile', { output: { score: 742 } }, StepTags.retrieval()) .addChatTurn( 'Should we approve applicant #4421?', 'Approve with standard terms — strong credit and acceptable leverage.', 'gpt-4o', ) .setDecision( DecisionContext.withOptions( 'Loan decision', ['approve', 'deny', 'manual-review'], 'approve', 'Score 742 exceeds threshold; no recent derogatory marks.', 0.93, ), ); await session.complete();

VeriproofSession methods

MethodReturnsDescription
.addStep(name, data, tags?)thisRecord a discrete processing step
.addChatTurn(userMsg, assistantMsg, model?)thisRecord one LLM conversation turn
.setDecision(decision)thisAttach a DecisionContext or string description
.setOutcome(outcome)thisSet a SessionOutcome on the root span
.setRiskLevel(level)thisSet a RiskLevel on the root span
.addRiskFactor(factor)thisAppend a RiskFactor observation
.setDescription(text)thisFree-form description for this session
.setExpectedOutcome(text)thisExpected outcome for A/B or regression comparison
.setBaselineSessionId(id)thisLink to a baseline session for comparison
.withTags(...tags)thisAttach string tags to the root span
.withMetadata(key, value)thisAttach a veriproof.metadata.* attribute to the most recent step
.withTransactionType(type)thisDomain-specific transaction label
.withSessionMetadata(meta)thisAttach a SessionMetadata object
.complete()Promise<SessionCompletionResult>Flush and seal the session trace

DecisionContext

// Decision with options DecisionContext.withOptions( label, // e.g. "Loan decision" options, // e.g. ['approve', 'deny', 'manual-review'] selected, // e.g. 'approve' reasoning?, // explanatory text confidence?, // 0.0 – 1.0 ) // Simple decision DecisionContext.withScore(label, score, threshold?)

Enumerations

EnumMembers
SessionOutcomeUnknown, Success, Failure, Escalated, Cancelled, Partial
RiskLevelLow, Medium, High, Critical
RiskSeverityLow, Medium, High, Critical
StepTypeUnknown, LlmCall, ToolCall, Retrieval, Decision, UserInteraction, Validation, Output, Error, AgentDelegation
DataSensitivityPublic, Internal, Sensitive, Pii, Restricted
DataFormatText, Json, Markdown, Html, Binary, Audio, Image, Pdf
VeriproofEnvironmentLocal, Development, Staging, Production

Merkle utilities

import { computeMerkleRootHex, MerkleTree } from '@veriproof/sdk-core'; const tree = new MerkleTree(); tree.addLeaf({ step: 'retrieve_credit_profile', score: 742 }); tree.addLeaf({ step: 'evaluate_rule_set', passed: true }); tree.addLeaf({ decision: 'approve', confidence: 0.93 }); const root = tree.getRootHex(); // SHA-256 Merkle root (hex) const proof = tree.generateProof(2); // proof for the third leaf

MerkleTree methods:

MethodDescription
.addLeaf(data)Hash and append a leaf (accepts object, string, or Uint8Array)
.getRootHex()Return the hex Merkle root
.generateProof(index)Return a MerkleProof for the leaf at index

computeMerkleRootHex(leaves) — standalone function that computes the root from an array of strings.


Transport

The VeriproofIngestTransport handles HTTP communication with the ingest API. It includes per-endpoint circuit breaking, overflow buffering, and retry with exponential backoff.

import { VeriproofIngestTransport } from '@veriproof/sdk-core'; const transport = new VeriproofIngestTransport(options); await transport.submit(payload); // single payload await transport.submitBatch(payloads); // multiple payloads const healthy = transport.isHealthy(); // false when circuit is open await transport.forceFlush(); // drain retry buffer immediately await transport.shutdown(); // graceful shutdown

Access metrics via transport.metricsTransportMetrics (export counts, circuit breaker state, last error/success timestamp).

Circuit breaker behavior

StateBehavior
Closed (normal)Exports proceed; failures trigger retries
Open (failing)Exports buffered; no outbound calls made
Half-open (recovering)One probe export sent; success closes the circuit

Data encryption

DataEncryptionService provides AES-256-GCM authenticated encryption. Use it when you need to protect sensitive span fields before they leave the process.

import { DataEncryptionService } from '@veriproof/sdk-core'; const masterKey = DataEncryptionService.generateKeyHex(); const svc = new DataEncryptionService(masterKey); const encrypted = svc.encrypt('sensitive data', 'session-context'); const plain = svc.decryptToString(encrypted, 'session-context');

DataEncryptionService API:

MethodDescription
new DataEncryptionService(key)Construct with a ≥16-byte master key (raw bytes, 64-char hex, or base64)
.encrypt(plaintext, context?)Encrypt; optional HKDF context derives an independent sub-key
.decrypt(data, context?)Decrypt; throws if GCM auth tag doesn’t match
.decryptToString(data, context?)Decrypt and return as UTF-8 string
.deriveKey(options)HKDF-SHA256 sub-key derivation
DataEncryptionService.serialize(data)Compact iv.ciphertext.authTag (base64url) encoding
DataEncryptionService.deserialize(compact)Inverse of serialize
DataEncryptionService.generateKey()Generate a cryptographically random 32-byte key
DataEncryptionService.generateKeyHex()Generate a random 32-byte key as a 64-char hex string

Overflow buffering

LogBuffer<T> is a typed ring buffer with configurable overflow behavior, used internally by the transport layer and available for custom use:

import { LogBuffer, BufferFullMode } from '@veriproof/sdk-core'; const buf = new LogBuffer<string>(100, BufferFullMode.DropOldest); buf.write('span-abc'); // returns { accepted: true, dropped: [] } const items = buf.drain(); // removes and returns all items atomically const snap = buf.snapshot(); // non-destructive copy buf.prependMany(['priority-item']); // insert at front

BufferFullMode.DropOldest evicts the oldest item when at capacity. BufferFullMode.DropWrite rejects the new item.


OTel compatibility

If your application already exports spans to another backend (Datadog, Honeycomb, etc.), you can add VeriProof as a second processor on the same TracerProvider:

import { configureVeriproof } from '@veriproof/sdk-core'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; const { provider } = configureVeriproof(options, { serviceName: 'your-app', setGlobal: true }); // Add your secondary exporter on the returned provider provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter({ url: 'https://api.honeycomb.io/v1/traces', })));

FAQ

No spans are exported — what do I check first?

Make sure setGlobal: true is set in ConfigureVeriproofOptions, or that you are passing the returned provider explicitly to your OTel wiring. Without this, spans created by framework adapters may not reach the VeriProof exporter.

Can I call configureVeriproof more than once?

No — the second call logs a warning and is ignored. The first call wins. Ensure your telemetry bootstrap file loads before any adapter.

Does the SDK work with Deno or Bun?

Node.js ≥ 18 is the tested runtime. Bun compatibility is experimental. Deno is not currently supported.


Next steps

Last updated on