autotel-audit 0.4.15 → 1.0.0
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.cjs +23 -22
- package/dist/index.d.cts +33 -8
- package/dist/index.d.ts +33 -8
- package/dist/index.js +23 -22
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -95,34 +95,35 @@ function lazyCounter(name, description) {
|
|
|
95
95
|
* Drives both standard-field emission and the reserved-key check for the
|
|
96
96
|
* custom-attribute loop — adding a field here is the whole change.
|
|
97
97
|
*/
|
|
98
|
-
const FIELD_ATTRIBUTES =
|
|
99
|
-
name
|
|
100
|
-
category
|
|
101
|
-
outcome
|
|
102
|
-
severity
|
|
103
|
-
actorId
|
|
104
|
-
targetType
|
|
105
|
-
targetId
|
|
106
|
-
tenantId
|
|
107
|
-
reason
|
|
108
|
-
|
|
98
|
+
const FIELD_ATTRIBUTES = /* @__PURE__ */ new Map([
|
|
99
|
+
["name", autotel_security_schema.SECURITY_ATTR.event],
|
|
100
|
+
["category", autotel_security_schema.SECURITY_ATTR.category],
|
|
101
|
+
["outcome", autotel_security_schema.SECURITY_ATTR.outcome],
|
|
102
|
+
["severity", autotel_security_schema.SECURITY_ATTR.severity],
|
|
103
|
+
["actorId", autotel_security_schema.SECURITY_ATTR.actorId],
|
|
104
|
+
["targetType", autotel_security_schema.SECURITY_ATTR.targetType],
|
|
105
|
+
["targetId", autotel_security_schema.SECURITY_ATTR.targetId],
|
|
106
|
+
["tenantId", autotel_security_schema.SECURITY_ATTR.tenantId],
|
|
107
|
+
["reason", autotel_security_schema.SECURITY_ATTR.reason]
|
|
108
|
+
]);
|
|
109
109
|
function flattenSecurityAttributes(metadata) {
|
|
110
|
-
const
|
|
111
|
-
[autotel_security_schema.SECURITY_ATTR.marker]: true,
|
|
112
|
-
[autotel_security_schema.SECURITY_ATTR.severity]: metadata.severity ?? "info"
|
|
113
|
-
};
|
|
110
|
+
const custom = [];
|
|
114
111
|
const droppedKeys = [];
|
|
115
112
|
for (const [key, value] of Object.entries(metadata)) {
|
|
116
|
-
const standardAttribute = FIELD_ATTRIBUTES
|
|
113
|
+
const standardAttribute = FIELD_ATTRIBUTES.get(key);
|
|
117
114
|
if (standardAttribute === void 0 && autotel.REDACTOR_PATTERNS.sensitiveKey.test(key)) {
|
|
118
115
|
droppedKeys.push(key);
|
|
119
116
|
continue;
|
|
120
117
|
}
|
|
121
118
|
const attr = toAttributeValue(value);
|
|
122
|
-
if (attr !== void 0)
|
|
119
|
+
if (attr !== void 0) custom.push([standardAttribute ?? `security.${key}`, attr]);
|
|
123
120
|
}
|
|
124
|
-
if (droppedKeys.length > 0)
|
|
125
|
-
return
|
|
121
|
+
if (droppedKeys.length > 0) custom.push([autotel_security_schema.SECURITY_ATTR.droppedKeys, droppedKeys]);
|
|
122
|
+
return Object.fromEntries([
|
|
123
|
+
[autotel_security_schema.SECURITY_ATTR.marker, true],
|
|
124
|
+
[autotel_security_schema.SECURITY_ATTR.severity, metadata.severity ?? "info"],
|
|
125
|
+
...custom
|
|
126
|
+
]);
|
|
126
127
|
}
|
|
127
128
|
const eventsCounter = lazyCounter(autotel_security_schema.SECURITY_METRICS.events, "Security events by name, category, outcome, and severity");
|
|
128
129
|
function countSecurityEvent(metadata) {
|
|
@@ -570,12 +571,12 @@ function createMcpSecurityEventBridge(options = {}) {
|
|
|
570
571
|
//#endregion
|
|
571
572
|
//#region src/index.ts
|
|
572
573
|
function flattenAuditAttributes(metadata) {
|
|
573
|
-
const
|
|
574
|
+
const custom = [];
|
|
574
575
|
for (const [key, value] of Object.entries(metadata)) {
|
|
575
576
|
const attr = toAttributeValue(value);
|
|
576
|
-
if (attr !== void 0)
|
|
577
|
+
if (attr !== void 0) custom.push([`audit.${key}`, attr]);
|
|
577
578
|
}
|
|
578
|
-
return
|
|
579
|
+
return Object.fromEntries([["autotel.audit", true], ...custom]);
|
|
579
580
|
}
|
|
580
581
|
function forceKeepAuditEvent(ctx) {
|
|
581
582
|
const traceCtx = resolveContextSafe(ctx);
|
package/dist/index.d.cts
CHANGED
|
@@ -32,6 +32,8 @@ type SecurityOutcome = 'success' | 'failure' | 'denied' | 'blocked' | 'error';
|
|
|
32
32
|
* this union exists for autocomplete and consistency across services.
|
|
33
33
|
*/
|
|
34
34
|
type SuggestedSecurityEventName = 'auth.login.success' | 'auth.login.failed' | 'auth.mfa.failed' | 'auth.session.revoked' | 'auth.password.reset' | 'auth.account.locked' | 'access.denied' | 'access.role.changed' | 'access.permission.changed' | 'access.tenant.violation' | 'admin.action' | 'config.changed' | 'secret.accessed' | 'secret.rotation.failed' | 'api_key.created' | 'api_key.revoked' | 'rate_limit.exceeded' | 'validation.failed' | 'webhook.signature.failed' | 'dependency.scan.failed' | 'llm.prompt_injection.detected' | 'llm.tool_call.denied' | 'llm.output.blocked' | 'llm.output.budget_exceeded' | 'llm.guard.triggered' | 'llm.action_chain.suspicious' | 'llm.manifest.suspicious' | 'llm.plan.risk.elevated';
|
|
35
|
+
/** An attribute value, as OpenTelemetry allows one on a span. */
|
|
36
|
+
type SecurityAttributeValue = string | number | boolean | string[] | number[] | boolean[];
|
|
35
37
|
interface SecurityEventMetadata {
|
|
36
38
|
/** Stable, dot-separated event name, e.g. `auth.login.failed`. */
|
|
37
39
|
name: SuggestedSecurityEventName | (string & {});
|
|
@@ -46,7 +48,8 @@ interface SecurityEventMetadata {
|
|
|
46
48
|
tenantId?: string;
|
|
47
49
|
/** Short machine-readable reason, e.g. `invalid_password`. */
|
|
48
50
|
reason?: string;
|
|
49
|
-
|
|
51
|
+
/** Extra fields ride along as span attributes; see AuditMetadataValue. */
|
|
52
|
+
[key: string]: AuditMetadataValue;
|
|
50
53
|
}
|
|
51
54
|
interface SecurityEventOptions {
|
|
52
55
|
ctx?: AuditContext;
|
|
@@ -76,7 +79,7 @@ interface SecurityEventOptions {
|
|
|
76
79
|
}
|
|
77
80
|
type WithSecurityOptions = SecurityEventOptions;
|
|
78
81
|
interface SecurityAttributeSink {
|
|
79
|
-
setAttribute(key: string, value:
|
|
82
|
+
setAttribute(key: string, value: SecurityAttributeValue): void;
|
|
80
83
|
}
|
|
81
84
|
declare function applySecurityEventAttributes(sink: SecurityAttributeSink, metadata: SecurityEventMetadata, options?: Pick<SecurityEventOptions, 'forceKeep' | 'metrics'>): void;
|
|
82
85
|
/**
|
|
@@ -153,12 +156,18 @@ declare function hashIdentifier(value: string, options?: HashIdentifierOptions):
|
|
|
153
156
|
* exist, survive sampling, and stay queryable under a stable schema.
|
|
154
157
|
*/
|
|
155
158
|
type AttributeValue = string | number | boolean | Array<null | undefined | string> | Array<null | undefined | number> | Array<null | undefined | boolean>;
|
|
159
|
+
/** The parent context OTel hands a processor. This package never reads it. */
|
|
160
|
+
interface SpanParentContext {
|
|
161
|
+
getValue?: (key: symbol) => ContextValue;
|
|
162
|
+
}
|
|
163
|
+
/** Whatever OTel stored under a context key. This package never reads one. */
|
|
164
|
+
type ContextValue = object | string | number | boolean | undefined;
|
|
156
165
|
interface MutableSpanLike {
|
|
157
166
|
attributes: Record<string, AttributeValue | undefined>;
|
|
158
167
|
spanContext?: {
|
|
159
168
|
traceId: string;
|
|
160
169
|
};
|
|
161
|
-
setAttribute(key: string, value: AttributeValue):
|
|
170
|
+
setAttribute(key: string, value: AttributeValue): void;
|
|
162
171
|
}
|
|
163
172
|
interface ReadableSpanLike {
|
|
164
173
|
attributes: Record<string, AttributeValue | undefined>;
|
|
@@ -167,7 +176,7 @@ interface ReadableSpanLike {
|
|
|
167
176
|
};
|
|
168
177
|
}
|
|
169
178
|
interface SecuritySignalProcessor {
|
|
170
|
-
onStart(span: MutableSpanLike, parentContext?:
|
|
179
|
+
onStart(span: MutableSpanLike, parentContext?: SpanParentContext): void;
|
|
171
180
|
onEnd(span: ReadableSpanLike): void;
|
|
172
181
|
shutdown(): Promise<void>;
|
|
173
182
|
forceFlush(): Promise<void>;
|
|
@@ -289,7 +298,13 @@ interface SecuritySignalProcessorOptions {
|
|
|
289
298
|
* Conservative request-target patterns. Tuned for scanner/probe traffic —
|
|
290
299
|
* high signal, low false-positive — not as a WAF. Extend via `extraPatterns`.
|
|
291
300
|
*/
|
|
292
|
-
declare const SUSPICIOUS_REQUEST_PATTERNS:
|
|
301
|
+
declare const SUSPICIOUS_REQUEST_PATTERNS: {
|
|
302
|
+
path_traversal: RegExp;
|
|
303
|
+
sensitive_file_probe: RegExp;
|
|
304
|
+
sqli_probe: RegExp;
|
|
305
|
+
xss_probe: RegExp;
|
|
306
|
+
null_byte: RegExp;
|
|
307
|
+
};
|
|
293
308
|
declare function createSecuritySignalProcessor(options?: SecuritySignalProcessorOptions): SecuritySignalProcessor;
|
|
294
309
|
//#endregion
|
|
295
310
|
//#region src/security-heartbeat.d.ts
|
|
@@ -338,7 +353,8 @@ interface McpBridgedSecurityEvent {
|
|
|
338
353
|
toolName?: string;
|
|
339
354
|
verdict?: string;
|
|
340
355
|
source?: string;
|
|
341
|
-
|
|
356
|
+
/** Extra fields ride along as span attributes; see AuditMetadataValue. */
|
|
357
|
+
[key: string]: AuditMetadataValue;
|
|
342
358
|
}
|
|
343
359
|
interface McpSecurityEventBridgeOptions extends SecurityEventOptions {
|
|
344
360
|
/** Optional fixed audit context for bridged events. */
|
|
@@ -368,8 +384,17 @@ interface AuditMetadata {
|
|
|
368
384
|
actorId?: string;
|
|
369
385
|
category?: string;
|
|
370
386
|
outcome?: 'success' | 'failure' | (string & {});
|
|
371
|
-
|
|
387
|
+
/** Extra fields ride along as span attributes, so they must be attribute-shaped. */
|
|
388
|
+
[key: string]: AuditMetadataValue;
|
|
372
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* What a metadata field can hold: anything `toAttributeValue` can render onto a
|
|
392
|
+
* span. Scalars and scalar arrays pass through; a Date becomes an ISO string;
|
|
393
|
+
* anything else nested is JSON-serialized.
|
|
394
|
+
*/
|
|
395
|
+
type AuditMetadataValue = string | number | boolean | null | undefined | Date | Array<AuditMetadataValue> | {
|
|
396
|
+
[key: string]: AuditMetadataValue;
|
|
397
|
+
};
|
|
373
398
|
interface WithAuditOptions {
|
|
374
399
|
ctx?: AuditContext;
|
|
375
400
|
emitNow?: boolean;
|
|
@@ -385,4 +410,4 @@ declare function forceKeepAuditEvent(ctx?: AuditContext): void;
|
|
|
385
410
|
declare function setAuditAttributes(metadata: AuditMetadata, ctx?: AuditContext): void;
|
|
386
411
|
declare function withAudit<T>(metadata: AuditMetadata, fn: (ctx: AuditContext, logger: RequestLogger) => T | Promise<T>, options?: WithAuditOptions): Promise<T>;
|
|
387
412
|
//#endregion
|
|
388
|
-
export { type AuditContext, AuditMetadata, AuthFailureBurstSignal, BurstOptions, HashIdentifierOptions, LlmActionChainSuspiciousSignal, LlmExcessiveTokensSignal, LlmSignalOptions, LlmTokenBudgetSignal, McpBridgedSecurityEvent, McpSecurityEventBridgeOptions, type OnMissingContext, SUSPICIOUS_REQUEST_PATTERNS, SecurityEventCategory, SecurityEventMetadata, SecurityEventOptions, SecurityHeartbeat, SecurityHeartbeatOptions, SecurityOutcome, type SecuritySeverity, SecuritySignal, SecuritySignalProcessor, SecuritySignalProcessorOptions, SuggestedSecurityEventName, SuspiciousRequestSignal, WithAuditOptions, WithSecurityOptions, applySecurityEventAttributes, createMcpSecurityEventBridge, createSecuritySignalProcessor, forceKeepAuditEvent, hashIdentifier, securityEvent, setAuditAttributes, startSecurityHeartbeat, withAudit, withSecurity };
|
|
413
|
+
export { AttributeValue, type AuditContext, AuditMetadata, AuditMetadataValue, AuthFailureBurstSignal, BurstOptions, ContextValue, HashIdentifierOptions, LlmActionChainSuspiciousSignal, LlmExcessiveTokensSignal, LlmSignalOptions, LlmTokenBudgetSignal, McpBridgedSecurityEvent, McpSecurityEventBridgeOptions, type OnMissingContext, SUSPICIOUS_REQUEST_PATTERNS, SecurityAttributeValue, SecurityEventCategory, SecurityEventMetadata, SecurityEventOptions, SecurityHeartbeat, SecurityHeartbeatOptions, SecurityOutcome, type SecuritySeverity, SecuritySignal, SecuritySignalProcessor, SecuritySignalProcessorOptions, SpanParentContext, SuggestedSecurityEventName, SuspiciousRequestSignal, WithAuditOptions, WithSecurityOptions, applySecurityEventAttributes, createMcpSecurityEventBridge, createSecuritySignalProcessor, forceKeepAuditEvent, hashIdentifier, securityEvent, setAuditAttributes, startSecurityHeartbeat, withAudit, withSecurity };
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ type SecurityOutcome = 'success' | 'failure' | 'denied' | 'blocked' | 'error';
|
|
|
32
32
|
* this union exists for autocomplete and consistency across services.
|
|
33
33
|
*/
|
|
34
34
|
type SuggestedSecurityEventName = 'auth.login.success' | 'auth.login.failed' | 'auth.mfa.failed' | 'auth.session.revoked' | 'auth.password.reset' | 'auth.account.locked' | 'access.denied' | 'access.role.changed' | 'access.permission.changed' | 'access.tenant.violation' | 'admin.action' | 'config.changed' | 'secret.accessed' | 'secret.rotation.failed' | 'api_key.created' | 'api_key.revoked' | 'rate_limit.exceeded' | 'validation.failed' | 'webhook.signature.failed' | 'dependency.scan.failed' | 'llm.prompt_injection.detected' | 'llm.tool_call.denied' | 'llm.output.blocked' | 'llm.output.budget_exceeded' | 'llm.guard.triggered' | 'llm.action_chain.suspicious' | 'llm.manifest.suspicious' | 'llm.plan.risk.elevated';
|
|
35
|
+
/** An attribute value, as OpenTelemetry allows one on a span. */
|
|
36
|
+
type SecurityAttributeValue = string | number | boolean | string[] | number[] | boolean[];
|
|
35
37
|
interface SecurityEventMetadata {
|
|
36
38
|
/** Stable, dot-separated event name, e.g. `auth.login.failed`. */
|
|
37
39
|
name: SuggestedSecurityEventName | (string & {});
|
|
@@ -46,7 +48,8 @@ interface SecurityEventMetadata {
|
|
|
46
48
|
tenantId?: string;
|
|
47
49
|
/** Short machine-readable reason, e.g. `invalid_password`. */
|
|
48
50
|
reason?: string;
|
|
49
|
-
|
|
51
|
+
/** Extra fields ride along as span attributes; see AuditMetadataValue. */
|
|
52
|
+
[key: string]: AuditMetadataValue;
|
|
50
53
|
}
|
|
51
54
|
interface SecurityEventOptions {
|
|
52
55
|
ctx?: AuditContext;
|
|
@@ -76,7 +79,7 @@ interface SecurityEventOptions {
|
|
|
76
79
|
}
|
|
77
80
|
type WithSecurityOptions = SecurityEventOptions;
|
|
78
81
|
interface SecurityAttributeSink {
|
|
79
|
-
setAttribute(key: string, value:
|
|
82
|
+
setAttribute(key: string, value: SecurityAttributeValue): void;
|
|
80
83
|
}
|
|
81
84
|
declare function applySecurityEventAttributes(sink: SecurityAttributeSink, metadata: SecurityEventMetadata, options?: Pick<SecurityEventOptions, 'forceKeep' | 'metrics'>): void;
|
|
82
85
|
/**
|
|
@@ -153,12 +156,18 @@ declare function hashIdentifier(value: string, options?: HashIdentifierOptions):
|
|
|
153
156
|
* exist, survive sampling, and stay queryable under a stable schema.
|
|
154
157
|
*/
|
|
155
158
|
type AttributeValue = string | number | boolean | Array<null | undefined | string> | Array<null | undefined | number> | Array<null | undefined | boolean>;
|
|
159
|
+
/** The parent context OTel hands a processor. This package never reads it. */
|
|
160
|
+
interface SpanParentContext {
|
|
161
|
+
getValue?: (key: symbol) => ContextValue;
|
|
162
|
+
}
|
|
163
|
+
/** Whatever OTel stored under a context key. This package never reads one. */
|
|
164
|
+
type ContextValue = object | string | number | boolean | undefined;
|
|
156
165
|
interface MutableSpanLike {
|
|
157
166
|
attributes: Record<string, AttributeValue | undefined>;
|
|
158
167
|
spanContext?: {
|
|
159
168
|
traceId: string;
|
|
160
169
|
};
|
|
161
|
-
setAttribute(key: string, value: AttributeValue):
|
|
170
|
+
setAttribute(key: string, value: AttributeValue): void;
|
|
162
171
|
}
|
|
163
172
|
interface ReadableSpanLike {
|
|
164
173
|
attributes: Record<string, AttributeValue | undefined>;
|
|
@@ -167,7 +176,7 @@ interface ReadableSpanLike {
|
|
|
167
176
|
};
|
|
168
177
|
}
|
|
169
178
|
interface SecuritySignalProcessor {
|
|
170
|
-
onStart(span: MutableSpanLike, parentContext?:
|
|
179
|
+
onStart(span: MutableSpanLike, parentContext?: SpanParentContext): void;
|
|
171
180
|
onEnd(span: ReadableSpanLike): void;
|
|
172
181
|
shutdown(): Promise<void>;
|
|
173
182
|
forceFlush(): Promise<void>;
|
|
@@ -289,7 +298,13 @@ interface SecuritySignalProcessorOptions {
|
|
|
289
298
|
* Conservative request-target patterns. Tuned for scanner/probe traffic —
|
|
290
299
|
* high signal, low false-positive — not as a WAF. Extend via `extraPatterns`.
|
|
291
300
|
*/
|
|
292
|
-
declare const SUSPICIOUS_REQUEST_PATTERNS:
|
|
301
|
+
declare const SUSPICIOUS_REQUEST_PATTERNS: {
|
|
302
|
+
path_traversal: RegExp;
|
|
303
|
+
sensitive_file_probe: RegExp;
|
|
304
|
+
sqli_probe: RegExp;
|
|
305
|
+
xss_probe: RegExp;
|
|
306
|
+
null_byte: RegExp;
|
|
307
|
+
};
|
|
293
308
|
declare function createSecuritySignalProcessor(options?: SecuritySignalProcessorOptions): SecuritySignalProcessor;
|
|
294
309
|
//#endregion
|
|
295
310
|
//#region src/security-heartbeat.d.ts
|
|
@@ -338,7 +353,8 @@ interface McpBridgedSecurityEvent {
|
|
|
338
353
|
toolName?: string;
|
|
339
354
|
verdict?: string;
|
|
340
355
|
source?: string;
|
|
341
|
-
|
|
356
|
+
/** Extra fields ride along as span attributes; see AuditMetadataValue. */
|
|
357
|
+
[key: string]: AuditMetadataValue;
|
|
342
358
|
}
|
|
343
359
|
interface McpSecurityEventBridgeOptions extends SecurityEventOptions {
|
|
344
360
|
/** Optional fixed audit context for bridged events. */
|
|
@@ -368,8 +384,17 @@ interface AuditMetadata {
|
|
|
368
384
|
actorId?: string;
|
|
369
385
|
category?: string;
|
|
370
386
|
outcome?: 'success' | 'failure' | (string & {});
|
|
371
|
-
|
|
387
|
+
/** Extra fields ride along as span attributes, so they must be attribute-shaped. */
|
|
388
|
+
[key: string]: AuditMetadataValue;
|
|
372
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* What a metadata field can hold: anything `toAttributeValue` can render onto a
|
|
392
|
+
* span. Scalars and scalar arrays pass through; a Date becomes an ISO string;
|
|
393
|
+
* anything else nested is JSON-serialized.
|
|
394
|
+
*/
|
|
395
|
+
type AuditMetadataValue = string | number | boolean | null | undefined | Date | Array<AuditMetadataValue> | {
|
|
396
|
+
[key: string]: AuditMetadataValue;
|
|
397
|
+
};
|
|
373
398
|
interface WithAuditOptions {
|
|
374
399
|
ctx?: AuditContext;
|
|
375
400
|
emitNow?: boolean;
|
|
@@ -385,4 +410,4 @@ declare function forceKeepAuditEvent(ctx?: AuditContext): void;
|
|
|
385
410
|
declare function setAuditAttributes(metadata: AuditMetadata, ctx?: AuditContext): void;
|
|
386
411
|
declare function withAudit<T>(metadata: AuditMetadata, fn: (ctx: AuditContext, logger: RequestLogger) => T | Promise<T>, options?: WithAuditOptions): Promise<T>;
|
|
387
412
|
//#endregion
|
|
388
|
-
export { type AuditContext, AuditMetadata, AuthFailureBurstSignal, BurstOptions, HashIdentifierOptions, LlmActionChainSuspiciousSignal, LlmExcessiveTokensSignal, LlmSignalOptions, LlmTokenBudgetSignal, McpBridgedSecurityEvent, McpSecurityEventBridgeOptions, type OnMissingContext, SUSPICIOUS_REQUEST_PATTERNS, SecurityEventCategory, SecurityEventMetadata, SecurityEventOptions, SecurityHeartbeat, SecurityHeartbeatOptions, SecurityOutcome, type SecuritySeverity, SecuritySignal, SecuritySignalProcessor, SecuritySignalProcessorOptions, SuggestedSecurityEventName, SuspiciousRequestSignal, WithAuditOptions, WithSecurityOptions, applySecurityEventAttributes, createMcpSecurityEventBridge, createSecuritySignalProcessor, forceKeepAuditEvent, hashIdentifier, securityEvent, setAuditAttributes, startSecurityHeartbeat, withAudit, withSecurity };
|
|
413
|
+
export { AttributeValue, type AuditContext, AuditMetadata, AuditMetadataValue, AuthFailureBurstSignal, BurstOptions, ContextValue, HashIdentifierOptions, LlmActionChainSuspiciousSignal, LlmExcessiveTokensSignal, LlmSignalOptions, LlmTokenBudgetSignal, McpBridgedSecurityEvent, McpSecurityEventBridgeOptions, type OnMissingContext, SUSPICIOUS_REQUEST_PATTERNS, SecurityAttributeValue, SecurityEventCategory, SecurityEventMetadata, SecurityEventOptions, SecurityHeartbeat, SecurityHeartbeatOptions, SecurityOutcome, type SecuritySeverity, SecuritySignal, SecuritySignalProcessor, SecuritySignalProcessorOptions, SpanParentContext, SuggestedSecurityEventName, SuspiciousRequestSignal, WithAuditOptions, WithSecurityOptions, applySecurityEventAttributes, createMcpSecurityEventBridge, createSecuritySignalProcessor, forceKeepAuditEvent, hashIdentifier, securityEvent, setAuditAttributes, startSecurityHeartbeat, withAudit, withSecurity };
|
package/dist/index.js
CHANGED
|
@@ -94,34 +94,35 @@ function lazyCounter(name, description) {
|
|
|
94
94
|
* Drives both standard-field emission and the reserved-key check for the
|
|
95
95
|
* custom-attribute loop — adding a field here is the whole change.
|
|
96
96
|
*/
|
|
97
|
-
const FIELD_ATTRIBUTES =
|
|
98
|
-
name
|
|
99
|
-
category
|
|
100
|
-
outcome
|
|
101
|
-
severity
|
|
102
|
-
actorId
|
|
103
|
-
targetType
|
|
104
|
-
targetId
|
|
105
|
-
tenantId
|
|
106
|
-
reason
|
|
107
|
-
|
|
97
|
+
const FIELD_ATTRIBUTES = /* @__PURE__ */ new Map([
|
|
98
|
+
["name", SECURITY_ATTR.event],
|
|
99
|
+
["category", SECURITY_ATTR.category],
|
|
100
|
+
["outcome", SECURITY_ATTR.outcome],
|
|
101
|
+
["severity", SECURITY_ATTR.severity],
|
|
102
|
+
["actorId", SECURITY_ATTR.actorId],
|
|
103
|
+
["targetType", SECURITY_ATTR.targetType],
|
|
104
|
+
["targetId", SECURITY_ATTR.targetId],
|
|
105
|
+
["tenantId", SECURITY_ATTR.tenantId],
|
|
106
|
+
["reason", SECURITY_ATTR.reason]
|
|
107
|
+
]);
|
|
108
108
|
function flattenSecurityAttributes(metadata) {
|
|
109
|
-
const
|
|
110
|
-
[SECURITY_ATTR.marker]: true,
|
|
111
|
-
[SECURITY_ATTR.severity]: metadata.severity ?? "info"
|
|
112
|
-
};
|
|
109
|
+
const custom = [];
|
|
113
110
|
const droppedKeys = [];
|
|
114
111
|
for (const [key, value] of Object.entries(metadata)) {
|
|
115
|
-
const standardAttribute = FIELD_ATTRIBUTES
|
|
112
|
+
const standardAttribute = FIELD_ATTRIBUTES.get(key);
|
|
116
113
|
if (standardAttribute === void 0 && REDACTOR_PATTERNS.sensitiveKey.test(key)) {
|
|
117
114
|
droppedKeys.push(key);
|
|
118
115
|
continue;
|
|
119
116
|
}
|
|
120
117
|
const attr = toAttributeValue(value);
|
|
121
|
-
if (attr !== void 0)
|
|
118
|
+
if (attr !== void 0) custom.push([standardAttribute ?? `security.${key}`, attr]);
|
|
122
119
|
}
|
|
123
|
-
if (droppedKeys.length > 0)
|
|
124
|
-
return
|
|
120
|
+
if (droppedKeys.length > 0) custom.push([SECURITY_ATTR.droppedKeys, droppedKeys]);
|
|
121
|
+
return Object.fromEntries([
|
|
122
|
+
[SECURITY_ATTR.marker, true],
|
|
123
|
+
[SECURITY_ATTR.severity, metadata.severity ?? "info"],
|
|
124
|
+
...custom
|
|
125
|
+
]);
|
|
125
126
|
}
|
|
126
127
|
const eventsCounter = lazyCounter(SECURITY_METRICS.events, "Security events by name, category, outcome, and severity");
|
|
127
128
|
function countSecurityEvent(metadata) {
|
|
@@ -569,12 +570,12 @@ function createMcpSecurityEventBridge(options = {}) {
|
|
|
569
570
|
//#endregion
|
|
570
571
|
//#region src/index.ts
|
|
571
572
|
function flattenAuditAttributes(metadata) {
|
|
572
|
-
const
|
|
573
|
+
const custom = [];
|
|
573
574
|
for (const [key, value] of Object.entries(metadata)) {
|
|
574
575
|
const attr = toAttributeValue(value);
|
|
575
|
-
if (attr !== void 0)
|
|
576
|
+
if (attr !== void 0) custom.push([`audit.${key}`, attr]);
|
|
576
577
|
}
|
|
577
|
-
return
|
|
578
|
+
return Object.fromEntries([["autotel.audit", true], ...custom]);
|
|
578
579
|
}
|
|
579
580
|
function forceKeepAuditEvent(ctx) {
|
|
580
581
|
const traceCtx = resolveContextSafe(ctx);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autotel-audit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Audit-focused helpers for Autotel (force-keep + structured audit instrumentation)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"author": "Jag Reehal <jag@jagreehal.com> (https://jagreehal.com)",
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"autotel": "
|
|
30
|
+
"autotel": "7.0.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^26.1.2",
|