/**
* decision-otlp.ts, map permission/policy decision-log records to OpenTelemetry
* (OTLP) span and log semantics, and export them as OTLP/HTTP JSON.
*
* HONEST SCOPE: this is EXPORT-ONLY. It surfaces ahead-of-field data that
* already exists, every allow/deny the DecisionLog already records, by
* mapping each decision to the OTLP wire shape and POSTing it to a configured
* collector. There is no ingestion path, no span/trace correlation with the
* runtime tracer, and no new heavyweight dependency: the payload is plain
* OTLP/HTTP JSON (which the protocol supports) emitted with the platform's
* `instrumentedFetch`. Off by default; enabled only with an endpoint.
*
* Each decision maps to the same attribute set in both shapes:
* decision.id , the log entry's monotonic sequence number
* tool.name , the tool evaluated
* command.class , the semantic classification (read/write/network/…)
* permission.mode , the active permission mode, when the caller supplies it
* decision.layer , the evaluation layer that produced the decision
* decision.reason , the canonical reason code
* decision.allowed, the boolean outcome
*/
import type { DecisionLogEntry } from './decision-log.js';
/** An OTLP AnyValue (the subset this mapping emits). */
export type OtlpAnyValue = {
readonly stringValue: string;
} | {
readonly boolValue: boolean;
} | {
readonly intValue: string;
};
/** An OTLP KeyValue attribute. */
export interface OtlpKeyValue {
readonly key: string;
readonly value: OtlpAnyValue;
}
/** An OTLP span (v1/traces), the fields this mapping populates. */
export interface OtlpSpan {
readonly traceId: string;
readonly spanId: string;
readonly name: string;
readonly kind: number;
readonly startTimeUnixNano: string;
readonly endTimeUnixNano: string;
readonly attributes: readonly OtlpKeyValue[];
readonly status: {
readonly code: number;
};
}
/** An OTLP log record (v1/logs), the fields this mapping populates. */
export interface OtlpLogRecord {
readonly timeUnixNano: string;
readonly observedTimeUnixNano: string;
readonly severityNumber: number;
readonly severityText: string;
readonly body: {
readonly stringValue: string;
};
readonly attributes: readonly OtlpKeyValue[];
}
/** The OTLP/HTTP JSON envelope for a batch of spans. */
export interface OtlpTracePayload {
readonly resourceSpans: readonly {
readonly resource: {
readonly attributes: readonly OtlpKeyValue[];
};
readonly scopeSpans: readonly {
readonly scope: {
readonly name: string;
};
readonly spans: readonly OtlpSpan[];
}[];
}[];
}
/** The OTLP/HTTP JSON envelope for a batch of log records. */
export interface OtlpLogsPayload {
readonly resourceLogs: readonly {
readonly resource: {
readonly attributes: readonly OtlpKeyValue[];
};
readonly scopeLogs: readonly {
readonly scope: {
readonly name: string;
};
readonly logRecords: readonly OtlpLogRecord[];
}[];
}[];
}
/** Export configuration; mirrors the `telemetry.decisionOtlp*` config keys. */
export interface DecisionOtlpConfig {
/** Master switch, off by default. */
readonly enabled: boolean;
/** OTLP/HTTP JSON endpoint base (spans → `/v1/traces`, logs → `/v1/logs`). */
readonly endpoint: string;
/** Which record shape(s) to emit per decision. */
readonly signal: 'span' | 'log' | 'both';
/** `service.name` resource attribute (default: goodvibes-sdk). */
readonly serviceName?: string | undefined;
/** Per-request timeout (default 8000ms). */
readonly timeoutMs?: number | undefined;
/** Extra headers (e.g. an auth token). */
readonly headers?: Record | undefined;
}
/** Optional per-decision context the log entry does not carry itself. */
export interface DecisionOtlpContext {
/** The active permission mode, mapped to the `permission.mode` attribute. */
readonly mode?: string | undefined;
}
/** Map a decision-log entry to the shared OTLP attribute set. */
export declare function decisionAttributes(entry: DecisionLogEntry, ctx?: DecisionOtlpContext): OtlpKeyValue[];
/** Map a decision-log entry to an OTLP span. */
export declare function decisionToSpan(entry: DecisionLogEntry, ctx?: DecisionOtlpContext): OtlpSpan;
/** Map a decision-log entry to an OTLP log record. */
export declare function decisionToLogRecord(entry: DecisionLogEntry, ctx?: DecisionOtlpContext): OtlpLogRecord;
/** Build the OTLP/HTTP JSON trace payload for a batch of decisions. */
export declare function buildTracePayload(entries: readonly DecisionLogEntry[], serviceName?: string, ctx?: DecisionOtlpContext): OtlpTracePayload;
/** Build the OTLP/HTTP JSON logs payload for a batch of decisions. */
export declare function buildLogsPayload(entries: readonly DecisionLogEntry[], serviceName?: string, ctx?: DecisionOtlpContext): OtlpLogsPayload;
/** Outcome of an export attempt. Never thrown, export never blocks the runtime. */
export interface DecisionExportResult {
readonly exported: boolean;
/** Why nothing was exported, when `exported` is false. */
readonly reason?: string | undefined;
/** The OTLP signals that were POSTed. */
readonly signals: readonly ('span' | 'log')[];
}
/**
* Export a batch of decision-log entries as OTLP/HTTP JSON. Off by default: when
* `enabled` is false or no endpoint is configured, this is a no-op that reports
* why. Never throws, an unreachable collector never blocks a permission
* decision.
*/
export declare function exportDecisions(entries: readonly DecisionLogEntry[], config: DecisionOtlpConfig, ctx?: DecisionOtlpContext): Promise;
//# sourceMappingURL=decision-otlp.d.ts.map