@superblocksteam/telemetry 2.0.93 → 2.0.94-next.1
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 +59 -44
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/resilient-exporter.d.ts.map +1 -1
- package/dist/browser/resilient-exporter.js.map +1 -1
- package/dist/common/contracts/tier2-traces.d.ts +62 -50
- package/dist/common/contracts/tier2-traces.d.ts.map +1 -1
- package/dist/common/contracts/tier2-traces.js +484 -138
- package/dist/common/contracts/tier2-traces.js.map +1 -1
- package/dist/common/guardrails.d.ts +2 -2
- package/dist/common/guardrails.d.ts.map +1 -1
- package/dist/common/guardrails.js +7 -7
- package/dist/common/guardrails.js.map +1 -1
- package/dist/common/log-sanitizer.d.ts +88 -0
- package/dist/common/log-sanitizer.d.ts.map +1 -1
- package/dist/common/log-sanitizer.js +304 -6
- package/dist/common/log-sanitizer.js.map +1 -1
- package/dist/common/resource.d.ts +4 -1
- package/dist/common/resource.d.ts.map +1 -1
- package/dist/common/resource.js +4 -2
- package/dist/common/resource.js.map +1 -1
- package/dist/common/trace-sanitizer.d.ts +82 -0
- package/dist/common/trace-sanitizer.d.ts.map +1 -0
- package/dist/common/trace-sanitizer.js +230 -0
- package/dist/common/trace-sanitizer.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -8
- package/dist/index.js.map +1 -1
- package/dist/lint/forbidden-attributes.d.ts +2 -2
- package/dist/lint/forbidden-attributes.d.ts.map +1 -1
- package/dist/lint/forbidden-attributes.js +41 -40
- package/dist/lint/forbidden-attributes.js.map +1 -1
- package/dist/lint/index.d.ts +1 -1
- package/dist/llmobs/index.d.ts +2 -2
- package/dist/llmobs/tier1-exporter.d.ts +2 -2
- package/dist/llmobs/tier1-exporter.d.ts.map +1 -1
- package/dist/llmobs/tier1-exporter.js +17 -14
- package/dist/llmobs/tier1-exporter.js.map +1 -1
- package/dist/llmobs/tier2-summarizer.d.ts.map +1 -1
- package/dist/llmobs/tier2-summarizer.js +10 -4
- package/dist/llmobs/tier2-summarizer.js.map +1 -1
- package/dist/node/exporters/resilient-exporter.d.ts +14 -0
- package/dist/node/exporters/resilient-exporter.d.ts.map +1 -1
- package/dist/node/exporters/resilient-exporter.js +8 -1
- package/dist/node/exporters/resilient-exporter.js.map +1 -1
- package/dist/node/index.d.ts +2 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +7 -2
- package/dist/node/index.js.map +1 -1
- package/dist/node/init.d.ts.map +1 -1
- package/dist/node/init.js +61 -12
- package/dist/node/init.js.map +1 -1
- package/dist/node/log-processor.d.ts +41 -6
- package/dist/node/log-processor.d.ts.map +1 -1
- package/dist/node/log-processor.js +152 -61
- package/dist/node/log-processor.js.map +1 -1
- package/dist/node/metrics-client.d.ts.map +1 -1
- package/dist/node/metrics-client.js.map +1 -1
- package/dist/node/safe-logger.d.ts +55 -0
- package/dist/node/safe-logger.d.ts.map +1 -0
- package/dist/node/safe-logger.js +158 -0
- package/dist/node/safe-logger.js.map +1 -0
- package/dist/node/sanitizing-processor.d.ts +56 -0
- package/dist/node/sanitizing-processor.d.ts.map +1 -0
- package/dist/node/sanitizing-processor.js +124 -0
- package/dist/node/sanitizing-processor.js.map +1 -0
- package/dist/node/traced-socket.d.ts +47 -3
- package/dist/node/traced-socket.d.ts.map +1 -1
- package/dist/node/traced-socket.js +96 -19
- package/dist/node/traced-socket.js.map +1 -1
- package/dist/testing/in-memory-exporter.d.ts +3 -3
- package/dist/testing/in-memory-exporter.d.ts.map +1 -1
- package/dist/testing/in-memory-exporter.js +3 -1
- package/dist/testing/in-memory-exporter.js.map +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/types/index.d.ts +28 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist-esm/browser/index.d.ts +2 -2
- package/dist-esm/browser/index.js +2 -2
- package/dist-esm/browser/resilient-exporter.d.ts.map +1 -1
- package/dist-esm/browser/resilient-exporter.js.map +1 -1
- package/dist-esm/common/contracts/tier2-traces.d.ts +62 -50
- package/dist-esm/common/contracts/tier2-traces.d.ts.map +1 -1
- package/dist-esm/common/contracts/tier2-traces.js +480 -137
- package/dist-esm/common/contracts/tier2-traces.js.map +1 -1
- package/dist-esm/common/guardrails.d.ts +2 -2
- package/dist-esm/common/guardrails.d.ts.map +1 -1
- package/dist-esm/common/guardrails.js +9 -9
- package/dist-esm/common/guardrails.js.map +1 -1
- package/dist-esm/common/log-sanitizer.d.ts +88 -0
- package/dist-esm/common/log-sanitizer.d.ts.map +1 -1
- package/dist-esm/common/log-sanitizer.js +294 -5
- package/dist-esm/common/log-sanitizer.js.map +1 -1
- package/dist-esm/common/resource.d.ts +4 -1
- package/dist-esm/common/resource.d.ts.map +1 -1
- package/dist-esm/common/resource.js +3 -1
- package/dist-esm/common/resource.js.map +1 -1
- package/dist-esm/common/trace-sanitizer.d.ts +82 -0
- package/dist-esm/common/trace-sanitizer.d.ts.map +1 -0
- package/dist-esm/common/trace-sanitizer.js +226 -0
- package/dist-esm/common/trace-sanitizer.js.map +1 -0
- package/dist-esm/index.d.ts +2 -1
- package/dist-esm/index.d.ts.map +1 -1
- package/dist-esm/index.js +2 -1
- package/dist-esm/index.js.map +1 -1
- package/dist-esm/lint/forbidden-attributes.d.ts +2 -2
- package/dist-esm/lint/forbidden-attributes.d.ts.map +1 -1
- package/dist-esm/lint/forbidden-attributes.js +43 -42
- package/dist-esm/lint/forbidden-attributes.js.map +1 -1
- package/dist-esm/lint/index.d.ts +1 -1
- package/dist-esm/lint/index.js +1 -1
- package/dist-esm/llmobs/index.d.ts +2 -2
- package/dist-esm/llmobs/index.js +2 -2
- package/dist-esm/llmobs/tier1-exporter.d.ts +2 -2
- package/dist-esm/llmobs/tier1-exporter.d.ts.map +1 -1
- package/dist-esm/llmobs/tier1-exporter.js +18 -15
- package/dist-esm/llmobs/tier1-exporter.js.map +1 -1
- package/dist-esm/llmobs/tier2-summarizer.d.ts.map +1 -1
- package/dist-esm/llmobs/tier2-summarizer.js +10 -4
- package/dist-esm/llmobs/tier2-summarizer.js.map +1 -1
- package/dist-esm/node/exporters/resilient-exporter.d.ts +14 -0
- package/dist-esm/node/exporters/resilient-exporter.d.ts.map +1 -1
- package/dist-esm/node/exporters/resilient-exporter.js +8 -1
- package/dist-esm/node/exporters/resilient-exporter.js.map +1 -1
- package/dist-esm/node/index.d.ts +2 -1
- package/dist-esm/node/index.d.ts.map +1 -1
- package/dist-esm/node/index.js +2 -1
- package/dist-esm/node/index.js.map +1 -1
- package/dist-esm/node/init.d.ts.map +1 -1
- package/dist-esm/node/init.js +61 -12
- package/dist-esm/node/init.js.map +1 -1
- package/dist-esm/node/log-processor.d.ts +41 -6
- package/dist-esm/node/log-processor.d.ts.map +1 -1
- package/dist-esm/node/log-processor.js +151 -62
- package/dist-esm/node/log-processor.js.map +1 -1
- package/dist-esm/node/metrics-client.d.ts.map +1 -1
- package/dist-esm/node/metrics-client.js.map +1 -1
- package/dist-esm/node/safe-logger.d.ts +55 -0
- package/dist-esm/node/safe-logger.d.ts.map +1 -0
- package/dist-esm/node/safe-logger.js +154 -0
- package/dist-esm/node/safe-logger.js.map +1 -0
- package/dist-esm/node/sanitizing-processor.d.ts +56 -0
- package/dist-esm/node/sanitizing-processor.d.ts.map +1 -0
- package/dist-esm/node/sanitizing-processor.js +120 -0
- package/dist-esm/node/sanitizing-processor.js.map +1 -0
- package/dist-esm/node/traced-socket.d.ts +47 -3
- package/dist-esm/node/traced-socket.d.ts.map +1 -1
- package/dist-esm/node/traced-socket.js +96 -19
- package/dist-esm/node/traced-socket.js.map +1 -1
- package/dist-esm/testing/in-memory-exporter.d.ts +3 -3
- package/dist-esm/testing/in-memory-exporter.d.ts.map +1 -1
- package/dist-esm/testing/in-memory-exporter.js +4 -2
- package/dist-esm/testing/in-memory-exporter.js.map +1 -1
- package/dist-esm/testing/index.d.ts +2 -2
- package/dist-esm/testing/index.js +2 -2
- package/dist-esm/types/index.d.ts +28 -1
- package/dist-esm/types/index.d.ts.map +1 -1
- package/dist-esm/types/index.js +1 -1
- package/package.json +17 -18
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy-Aware Safe Logger (Pino Wrapper)
|
|
3
|
+
*
|
|
4
|
+
* Wraps a Pino logger to redact forbidden fields (e.g. stack, prompt, code)
|
|
5
|
+
* from log call arguments so Tier 1 data is not written to stdout/log export.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/superblocksteam/engineering/blob/main/projects/o11y-refactor/epics/epic-c4-logging-strategy.md
|
|
8
|
+
*/
|
|
9
|
+
import { type LoggingPolicyConfig } from "./log-processor.js";
|
|
10
|
+
/**
|
|
11
|
+
* Minimal logger interface compatible with Pino.
|
|
12
|
+
* Use createSafeLogger(pinoLogger, policy) with a Pino logger instance.
|
|
13
|
+
*/
|
|
14
|
+
export interface SafeLoggerLike {
|
|
15
|
+
trace(...args: unknown[]): void;
|
|
16
|
+
debug(...args: unknown[]): void;
|
|
17
|
+
info(...args: unknown[]): void;
|
|
18
|
+
warn(...args: unknown[]): void;
|
|
19
|
+
error(...args: unknown[]): void;
|
|
20
|
+
fatal(...args: unknown[]): void;
|
|
21
|
+
child(bindings: Record<string, unknown>): SafeLoggerLike;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Redact and sanitize a single log argument: key-based (forbidden fields) and
|
|
25
|
+
* value-based (stack traces, PII, policy redactPatterns). Error instances are
|
|
26
|
+
* converted to a plain object first. Exported for use by callers (e.g. server
|
|
27
|
+
* RemoteLogger redactRecord) so stdout and OTLP paths share the same rules.
|
|
28
|
+
*/
|
|
29
|
+
export declare function redactForbiddenFields(arg: unknown, policy: LoggingPolicyConfig): unknown;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a logger wrapper that redacts policy-forbidden fields from log calls
|
|
32
|
+
* and applies the policy-effective log level (exportMode + envLevel) so that
|
|
33
|
+
* both the root and any child loggers respect exportMode (e.g. ERRORS_ONLY → warn floor).
|
|
34
|
+
*
|
|
35
|
+
* Use when logging in contexts where output may be exported (e.g. cloud-prem).
|
|
36
|
+
* Forbidden fields (stack, prompt, code, filePath, etc.) are replaced with
|
|
37
|
+
* "[REDACTED]" so they never appear in exported logs.
|
|
38
|
+
*
|
|
39
|
+
* @param baseLogger - Underlying Pino (or compatible) logger
|
|
40
|
+
* @param policy - Logging policy (e.g. from getLoggingPolicy(telemetryPolicy))
|
|
41
|
+
* @param envLevel - Optional env-configured level (e.g. SUPERBLOCKS_SERVER_LOG_LEVEL).
|
|
42
|
+
* When provided, base logger level is set from getMinimumPinoLevelFromLoggingPolicy(policy, envLevel)
|
|
43
|
+
* so exportMode (e.g. ERRORS_ONLY) is respected; children inherit this level in .child().
|
|
44
|
+
* @returns A logger that redacts forbidden fields and respects policy level (same interface as baseLogger)
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const policy = getLoggingPolicy(telemetryPolicy);
|
|
49
|
+
* const safeLogger = createSafeLogger(logger, policy, envs.get('SUPERBLOCKS_SERVER_LOG_LEVEL'));
|
|
50
|
+
* safeLogger.error({ err, stack: err.stack }, 'Request failed');
|
|
51
|
+
* // Exported logs see stack: "[REDACTED]"
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function createSafeLogger<T extends SafeLoggerLike>(baseLogger: T, policy: LoggingPolicyConfig, envLevel?: string): T;
|
|
55
|
+
//# sourceMappingURL=safe-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-logger.d.ts","sourceRoot":"","sources":["../../src/node/safe-logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC;CAC1D;AA+BD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAaT;AAsCD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,cAAc,EACvD,UAAU,EAAE,CAAC,EACb,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,CAAC,CA6EH"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Policy-Aware Safe Logger (Pino Wrapper)
|
|
4
|
+
*
|
|
5
|
+
* Wraps a Pino logger to redact forbidden fields (e.g. stack, prompt, code)
|
|
6
|
+
* from log call arguments so Tier 1 data is not written to stdout/log export.
|
|
7
|
+
*
|
|
8
|
+
* @see https://github.com/superblocksteam/engineering/blob/main/projects/o11y-refactor/epics/epic-c4-logging-strategy.md
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.redactForbiddenFields = redactForbiddenFields;
|
|
12
|
+
exports.createSafeLogger = createSafeLogger;
|
|
13
|
+
const log_sanitizer_js_1 = require("../common/log-sanitizer.js");
|
|
14
|
+
const log_processor_js_1 = require("./log-processor.js");
|
|
15
|
+
/** Log level methods only. "child" is handled separately so returned children are also wrapped with createSafeLogger. */
|
|
16
|
+
const LOG_METHODS = new Set([
|
|
17
|
+
"trace",
|
|
18
|
+
"debug",
|
|
19
|
+
"info",
|
|
20
|
+
"warn",
|
|
21
|
+
"error",
|
|
22
|
+
"fatal",
|
|
23
|
+
]);
|
|
24
|
+
/**
|
|
25
|
+
* Convert an Error to a plain object so it can be redacted like any other object.
|
|
26
|
+
* Includes name, message, stack, and any own enumerable properties (e.g. code, statusCode).
|
|
27
|
+
*/
|
|
28
|
+
function errorToPlainObject(err) {
|
|
29
|
+
const obj = {
|
|
30
|
+
message: err.message,
|
|
31
|
+
name: err.name,
|
|
32
|
+
stack: err.stack,
|
|
33
|
+
};
|
|
34
|
+
const errRecord = err;
|
|
35
|
+
for (const key of Object.keys(err)) {
|
|
36
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
37
|
+
obj[key] = errRecord[key];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return obj;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Redact and sanitize a single log argument: key-based (forbidden fields) and
|
|
44
|
+
* value-based (stack traces, PII, policy redactPatterns). Error instances are
|
|
45
|
+
* converted to a plain object first. Exported for use by callers (e.g. server
|
|
46
|
+
* RemoteLogger redactRecord) so stdout and OTLP paths share the same rules.
|
|
47
|
+
*/
|
|
48
|
+
function redactForbiddenFields(arg, policy) {
|
|
49
|
+
if (arg === null || typeof arg !== "object") {
|
|
50
|
+
return arg;
|
|
51
|
+
}
|
|
52
|
+
if (arg instanceof Error) {
|
|
53
|
+
return redactForbiddenFields(errorToPlainObject(arg), policy);
|
|
54
|
+
}
|
|
55
|
+
return (0, log_sanitizer_js_1.sanitizeLogRecordForExport)(arg, policy.forbiddenFields, policy.redactPatterns, policy.sensitivePatterns);
|
|
56
|
+
}
|
|
57
|
+
function redactArg(arg, policy) {
|
|
58
|
+
return redactForbiddenFields(arg, policy);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Redact log call arguments: first arg (merge object) with key+value sanitization,
|
|
62
|
+
* and message string (second arg) with value-based sanitization (patterns, stack, PII).
|
|
63
|
+
*/
|
|
64
|
+
function redactArgs(args, policy) {
|
|
65
|
+
if (args.length === 0)
|
|
66
|
+
return args;
|
|
67
|
+
const [first, ...rest] = args;
|
|
68
|
+
const redactedFirst = typeof first === "object" && first !== null
|
|
69
|
+
? redactArg(first, policy)
|
|
70
|
+
: typeof first === "string"
|
|
71
|
+
? (0, log_sanitizer_js_1.sanitizeLogMessageForExport)(first, policy.redactPatterns, policy.sensitivePatterns)
|
|
72
|
+
: first;
|
|
73
|
+
const redactedRest = rest.map((r, i) => i === 0 && typeof r === "string"
|
|
74
|
+
? (0, log_sanitizer_js_1.sanitizeLogMessageForExport)(r, policy.redactPatterns, policy.sensitivePatterns)
|
|
75
|
+
: r);
|
|
76
|
+
return [redactedFirst, ...redactedRest];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Creates a logger wrapper that redacts policy-forbidden fields from log calls
|
|
80
|
+
* and applies the policy-effective log level (exportMode + envLevel) so that
|
|
81
|
+
* both the root and any child loggers respect exportMode (e.g. ERRORS_ONLY → warn floor).
|
|
82
|
+
*
|
|
83
|
+
* Use when logging in contexts where output may be exported (e.g. cloud-prem).
|
|
84
|
+
* Forbidden fields (stack, prompt, code, filePath, etc.) are replaced with
|
|
85
|
+
* "[REDACTED]" so they never appear in exported logs.
|
|
86
|
+
*
|
|
87
|
+
* @param baseLogger - Underlying Pino (or compatible) logger
|
|
88
|
+
* @param policy - Logging policy (e.g. from getLoggingPolicy(telemetryPolicy))
|
|
89
|
+
* @param envLevel - Optional env-configured level (e.g. SUPERBLOCKS_SERVER_LOG_LEVEL).
|
|
90
|
+
* When provided, base logger level is set from getMinimumPinoLevelFromLoggingPolicy(policy, envLevel)
|
|
91
|
+
* so exportMode (e.g. ERRORS_ONLY) is respected; children inherit this level in .child().
|
|
92
|
+
* @returns A logger that redacts forbidden fields and respects policy level (same interface as baseLogger)
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const policy = getLoggingPolicy(telemetryPolicy);
|
|
97
|
+
* const safeLogger = createSafeLogger(logger, policy, envs.get('SUPERBLOCKS_SERVER_LOG_LEVEL'));
|
|
98
|
+
* safeLogger.error({ err, stack: err.stack }, 'Request failed');
|
|
99
|
+
* // Exported logs see stack: "[REDACTED]"
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
function createSafeLogger(baseLogger, policy, envLevel) {
|
|
103
|
+
if (envLevel !== undefined) {
|
|
104
|
+
const effectiveLevel = (0, log_processor_js_1.getMinimumPinoLevelFromLoggingPolicy)(policy, envLevel);
|
|
105
|
+
baseLogger.level = effectiveLevel;
|
|
106
|
+
}
|
|
107
|
+
return new Proxy(baseLogger, {
|
|
108
|
+
get(target, prop) {
|
|
109
|
+
if (typeof prop === "symbol")
|
|
110
|
+
return Reflect.get(target, prop);
|
|
111
|
+
const value = target[prop];
|
|
112
|
+
if (LOG_METHODS.has(prop) && typeof value === "function") {
|
|
113
|
+
return (...args) => {
|
|
114
|
+
let redacted;
|
|
115
|
+
try {
|
|
116
|
+
redacted = redactArgs(args, policy);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Redaction can throw (e.g. Proxy with throwing getters, circular refs).
|
|
120
|
+
// Never emit original args — use a safe fallback so PII/Tier 1 is not exported.
|
|
121
|
+
redacted = [
|
|
122
|
+
{ "[SafeLogger]": "redaction_failed" },
|
|
123
|
+
"[SafeLogger] Log omitted: redaction failed",
|
|
124
|
+
];
|
|
125
|
+
target.error("[SafeLogger] Redaction failed; log omitted to avoid leaking data");
|
|
126
|
+
}
|
|
127
|
+
return value.apply(target, redacted);
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (prop === "child" && typeof value === "function") {
|
|
131
|
+
return (bindings) => {
|
|
132
|
+
// Redact forbidden fields from child bindings so they never appear in log output
|
|
133
|
+
// (e.g. user-email from req.logTags would otherwise be merged into every log line)
|
|
134
|
+
let redactedBindings;
|
|
135
|
+
try {
|
|
136
|
+
redactedBindings = redactArg(bindings, policy);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Never pass original bindings — use empty so PII/Tier 1 is not exported.
|
|
140
|
+
redactedBindings = {};
|
|
141
|
+
target.error("[SafeLogger] Child bindings omitted: redaction failed");
|
|
142
|
+
}
|
|
143
|
+
const child = value.call(target, redactedBindings);
|
|
144
|
+
// Ensure child respects same level as parent (exportMode / localMaxLevel)
|
|
145
|
+
const parentWithLevel = target;
|
|
146
|
+
const childWithLevel = child;
|
|
147
|
+
if (parentWithLevel.level !== undefined &&
|
|
148
|
+
childWithLevel.level !== undefined) {
|
|
149
|
+
childWithLevel.level = parentWithLevel.level;
|
|
150
|
+
}
|
|
151
|
+
return createSafeLogger(child, policy);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return value;
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=safe-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-logger.js","sourceRoot":"","sources":["../../src/node/safe-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitizing Span Processor (Tier 2)
|
|
3
|
+
*
|
|
4
|
+
* Sanitizes spans before export per epic-a3-sanitized-traces.
|
|
5
|
+
* - All spans are passed to localProcessor (full fidelity for local/on-prem retention).
|
|
6
|
+
* - Only contract-compliant, sanitized spans are exported to Tier 2.
|
|
7
|
+
* - Fail-closed: when Tier 2 export is disabled, no exporter is attached.
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from "@opentelemetry/api";
|
|
10
|
+
import type { ReadableSpan, Span, SpanExporter, SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
11
|
+
import { TelemetryPolicyEvaluator } from "../common/policy-evaluator.js";
|
|
12
|
+
import { TraceSanitizer } from "../common/trace-sanitizer.js";
|
|
13
|
+
/** No-op span processor for the "local" path when only Tier 2 export is used. */
|
|
14
|
+
declare class NoopSpanProcessor implements SpanProcessor {
|
|
15
|
+
onStart(): void;
|
|
16
|
+
onEnd(): void;
|
|
17
|
+
shutdown(): Promise<void>;
|
|
18
|
+
forceFlush(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare const noopSpanProcessor: NoopSpanProcessor;
|
|
21
|
+
/** Logger interface for processor messages (e.g. queue full, export failure). */
|
|
22
|
+
interface SanitizingProcessorLogger {
|
|
23
|
+
error?(obj: object, msg?: string): void;
|
|
24
|
+
error?(msg: string): void;
|
|
25
|
+
warn(obj: object, msg?: string): void;
|
|
26
|
+
warn(msg: string): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Span processor that sanitizes spans before Tier 2 export.
|
|
30
|
+
*
|
|
31
|
+
* CRITICAL: This processor owns the export path. The exporter is internal.
|
|
32
|
+
* For Tier 1: All spans passed to localProcessor (e.g. no-op or local collector).
|
|
33
|
+
* For Tier 2: Only contract-compliant spans, sanitized, then batched and exported.
|
|
34
|
+
*/
|
|
35
|
+
export declare class SanitizingSpanProcessor implements SpanProcessor {
|
|
36
|
+
private readonly sanitizer;
|
|
37
|
+
private readonly localProcessor;
|
|
38
|
+
private readonly tier2Exporter;
|
|
39
|
+
private readonly logger;
|
|
40
|
+
private pendingExports;
|
|
41
|
+
private exportTimer;
|
|
42
|
+
private droppedQueueFull;
|
|
43
|
+
constructor(policyEvaluator: TelemetryPolicyEvaluator, localProcessor: SpanProcessor, tier2Exporter: SpanExporter | null, traceSanitizer: TraceSanitizer, logger: SanitizingProcessorLogger);
|
|
44
|
+
onStart(span: Span, parentContext: Context): void;
|
|
45
|
+
onEnd(span: ReadableSpan): void;
|
|
46
|
+
/**
|
|
47
|
+
* Sends at most one batch (up to BATCH_SIZE) to the tier-2 exporter.
|
|
48
|
+
* Does not wait for the export callback. Call in a loop when a full drain
|
|
49
|
+
* is required (e.g. shutdown, forceFlush).
|
|
50
|
+
*/
|
|
51
|
+
private flushExports;
|
|
52
|
+
shutdown(): Promise<void>;
|
|
53
|
+
forceFlush(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=sanitizing-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizing-processor.d.ts","sourceRoot":"","sources":["../../src/node/sanitizing-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EACV,YAAY,EACZ,IAAI,EACJ,YAAY,EACZ,aAAa,EACd,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAO9D,iFAAiF;AACjF,cAAM,iBAAkB,YAAW,aAAa;IAC9C,OAAO,IAAI,IAAI;IACf,KAAK,IAAI,IAAI;IACP,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IACzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAClC;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC;AAGzD,iFAAiF;AACjF,UAAU,yBAAyB;IACjC,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;GAMG;AACH,qBAAa,uBAAwB,YAAW,aAAa;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,WAAW,CAA+C;IAClE,OAAO,CAAC,gBAAgB,CAAS;gBAG/B,eAAe,EAAE,wBAAwB,EACzC,cAAc,EAAE,aAAa,EAC7B,aAAa,EAAE,YAAY,GAAG,IAAI,EAClC,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,yBAAyB;IAoBnC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI;IAIjD,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IA8B/B;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAkBd,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAczB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CASlC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sanitizing Span Processor (Tier 2)
|
|
4
|
+
*
|
|
5
|
+
* Sanitizes spans before export per epic-a3-sanitized-traces.
|
|
6
|
+
* - All spans are passed to localProcessor (full fidelity for local/on-prem retention).
|
|
7
|
+
* - Only contract-compliant, sanitized spans are exported to Tier 2.
|
|
8
|
+
* - Fail-closed: when Tier 2 export is disabled, no exporter is attached.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.SanitizingSpanProcessor = exports.noopSpanProcessor = void 0;
|
|
12
|
+
const core_1 = require("@opentelemetry/core");
|
|
13
|
+
const policy_js_1 = require("../types/policy.js");
|
|
14
|
+
const BATCH_SIZE = 512;
|
|
15
|
+
/** Max pending spans before dropping. Aligns with BatchSpanProcessor / resilient-exporter queue limits. */
|
|
16
|
+
const MAX_PENDING_EXPORTS = 2048;
|
|
17
|
+
/** No-op span processor for the "local" path when only Tier 2 export is used. */
|
|
18
|
+
class NoopSpanProcessor {
|
|
19
|
+
onStart() { }
|
|
20
|
+
onEnd() { }
|
|
21
|
+
async shutdown() { }
|
|
22
|
+
async forceFlush() { }
|
|
23
|
+
}
|
|
24
|
+
exports.noopSpanProcessor = new NoopSpanProcessor();
|
|
25
|
+
const EXPORT_INTERVAL_MS = 5000;
|
|
26
|
+
/**
|
|
27
|
+
* Span processor that sanitizes spans before Tier 2 export.
|
|
28
|
+
*
|
|
29
|
+
* CRITICAL: This processor owns the export path. The exporter is internal.
|
|
30
|
+
* For Tier 1: All spans passed to localProcessor (e.g. no-op or local collector).
|
|
31
|
+
* For Tier 2: Only contract-compliant spans, sanitized, then batched and exported.
|
|
32
|
+
*/
|
|
33
|
+
class SanitizingSpanProcessor {
|
|
34
|
+
sanitizer;
|
|
35
|
+
localProcessor;
|
|
36
|
+
tier2Exporter;
|
|
37
|
+
logger;
|
|
38
|
+
pendingExports = [];
|
|
39
|
+
exportTimer = null;
|
|
40
|
+
droppedQueueFull = false;
|
|
41
|
+
constructor(policyEvaluator, localProcessor, tier2Exporter, traceSanitizer, logger) {
|
|
42
|
+
this.sanitizer = traceSanitizer;
|
|
43
|
+
this.localProcessor = localProcessor;
|
|
44
|
+
this.logger = logger;
|
|
45
|
+
this.tier2Exporter = policyEvaluator.isExportEnabled(policy_js_1.TelemetryTier.TIER_2_OPERATIONAL)
|
|
46
|
+
? tier2Exporter
|
|
47
|
+
: null;
|
|
48
|
+
if (this.tier2Exporter) {
|
|
49
|
+
this.exportTimer = setInterval(() => this.flushExports(), EXPORT_INTERVAL_MS);
|
|
50
|
+
this.exportTimer.unref();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
onStart(span, parentContext) {
|
|
54
|
+
this.localProcessor.onStart(span, parentContext);
|
|
55
|
+
}
|
|
56
|
+
onEnd(span) {
|
|
57
|
+
this.localProcessor.onEnd(span);
|
|
58
|
+
if (this.tier2Exporter) {
|
|
59
|
+
const sanitized = this.sanitizer.sanitize(span);
|
|
60
|
+
if (sanitized) {
|
|
61
|
+
if (this.pendingExports.length >= MAX_PENDING_EXPORTS) {
|
|
62
|
+
if (!this.droppedQueueFull) {
|
|
63
|
+
this.droppedQueueFull = true;
|
|
64
|
+
const msg = "Tier 2 pending queue full, dropping new spans until next flush";
|
|
65
|
+
const log = this.logger.error ?? this.logger.warn;
|
|
66
|
+
log({
|
|
67
|
+
component: "SanitizingSpanProcessor",
|
|
68
|
+
maxPendingExports: MAX_PENDING_EXPORTS,
|
|
69
|
+
}, msg);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.pendingExports.push(sanitized);
|
|
74
|
+
if (this.pendingExports.length >= BATCH_SIZE) {
|
|
75
|
+
this.flushExports();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Sends at most one batch (up to BATCH_SIZE) to the tier-2 exporter.
|
|
83
|
+
* Does not wait for the export callback. Call in a loop when a full drain
|
|
84
|
+
* is required (e.g. shutdown, forceFlush).
|
|
85
|
+
*/
|
|
86
|
+
flushExports() {
|
|
87
|
+
if (!this.tier2Exporter || this.pendingExports.length === 0) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (this.pendingExports.length < MAX_PENDING_EXPORTS) {
|
|
91
|
+
this.droppedQueueFull = false;
|
|
92
|
+
}
|
|
93
|
+
const batch = this.pendingExports.splice(0, BATCH_SIZE);
|
|
94
|
+
this.tier2Exporter.export(batch, (result) => {
|
|
95
|
+
if (result.code !== core_1.ExportResultCode.SUCCESS) {
|
|
96
|
+
this.logger.warn({ component: "SanitizingSpanProcessor", err: result.error }, "Tier 2 span export failed");
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async shutdown() {
|
|
101
|
+
if (this.exportTimer) {
|
|
102
|
+
clearInterval(this.exportTimer);
|
|
103
|
+
this.exportTimer = null;
|
|
104
|
+
}
|
|
105
|
+
while (this.pendingExports.length > 0) {
|
|
106
|
+
this.flushExports();
|
|
107
|
+
}
|
|
108
|
+
await this.localProcessor.shutdown();
|
|
109
|
+
if (this.tier2Exporter) {
|
|
110
|
+
await this.tier2Exporter.shutdown();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async forceFlush() {
|
|
114
|
+
while (this.pendingExports.length > 0) {
|
|
115
|
+
this.flushExports();
|
|
116
|
+
}
|
|
117
|
+
await this.localProcessor.forceFlush();
|
|
118
|
+
if (this.tier2Exporter?.forceFlush) {
|
|
119
|
+
await this.tier2Exporter.forceFlush();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.SanitizingSpanProcessor = SanitizingSpanProcessor;
|
|
124
|
+
//# sourceMappingURL=sanitizing-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizing-processor.js","sourceRoot":"","sources":["../../src/node/sanitizing-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* Server-specific behavior (like error handling) is injected via callbacks.
|
|
6
6
|
*/
|
|
7
7
|
import { IncomingHttpHeaders } from "http";
|
|
8
|
+
import { Tracer } from "@opentelemetry/api";
|
|
8
9
|
import { ISocket, ISocketClient, MethodHandler, RequestContextBase, SocketMessage, SocketError, MethodHandlers, GenericMiddleware, SocketTimeouts } from "@superblocksteam/shared";
|
|
10
|
+
import { TelemetryTier } from "../types/policy.js";
|
|
9
11
|
/**
|
|
10
12
|
* PinoLogger interface compatible with pino.
|
|
11
13
|
*/
|
|
@@ -24,12 +26,28 @@ interface WebSocketLike {
|
|
|
24
26
|
addEventListener(type: string, listener: (event: unknown) => void): void;
|
|
25
27
|
removeEventListener(type: string, listener: (event: unknown) => void): void;
|
|
26
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Policy evaluator type (avoids circular dependency on full init).
|
|
31
|
+
* Use TelemetryPolicyEvaluator from @superblocksteam/telemetry for policy-aware attribute filtering.
|
|
32
|
+
*/
|
|
33
|
+
export type TracedSocketPolicyEvaluator = {
|
|
34
|
+
evaluate: (tier: TelemetryTier) => {
|
|
35
|
+
export: boolean;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
27
38
|
/**
|
|
28
39
|
* Configuration options for TracedSocket.
|
|
40
|
+
*
|
|
41
|
+
* Supports both server (HTTP upgrade with requestHeaders) and client/dev (tracer-only) use cases
|
|
42
|
+
* for a single consolidated implementation per W3C context propagation epic.
|
|
29
43
|
*/
|
|
30
44
|
export interface TracedSocketConfig {
|
|
31
|
-
/** Request headers from the WebSocket upgrade request */
|
|
32
|
-
requestHeaders
|
|
45
|
+
/** Request headers from the WebSocket upgrade request (for W3C trace context extraction). Defaults to {}. */
|
|
46
|
+
requestHeaders?: IncomingHttpHeaders;
|
|
47
|
+
/** Tracer instance. Defaults to trace.getTracer("superblocks-ws", "0.0.0"). */
|
|
48
|
+
tracer?: Tracer;
|
|
49
|
+
/** Policy evaluator for tier-aware attribute filtering (e.g. from getTelemetryInstance()). */
|
|
50
|
+
policyEvaluator?: TracedSocketPolicyEvaluator;
|
|
33
51
|
/** Optional error handler to get HTTP status from errors */
|
|
34
52
|
getResponseMetaByError?: (error: Error, logger: PinoLogger) => {
|
|
35
53
|
status: number;
|
|
@@ -54,7 +72,9 @@ export interface TracedSocketOptions {
|
|
|
54
72
|
/**
|
|
55
73
|
* TracedSocket extends ISocket to add OpenTelemetry tracing capabilities.
|
|
56
74
|
*
|
|
57
|
-
*
|
|
75
|
+
* We override decorateToSend so that outbound request messages carry W3C
|
|
76
|
+
* traceparent/tracestate, enabling trace continuity for both inbound and
|
|
77
|
+
* outbound use (server and vite-plugin-file-sync).
|
|
58
78
|
*/
|
|
59
79
|
export declare class TracedSocket<ImplementedMethods, CallableMethods, RequestContext extends RequestContextBase> extends ISocket<ImplementedMethods, CallableMethods, RequestContext> {
|
|
60
80
|
private activeSpanByRequestId;
|
|
@@ -62,9 +82,33 @@ export declare class TracedSocket<ImplementedMethods, CallableMethods, RequestCo
|
|
|
62
82
|
private lastActiveSpan;
|
|
63
83
|
private readonly requestHeaders;
|
|
64
84
|
private readonly tracer;
|
|
85
|
+
private readonly policyEvaluator?;
|
|
65
86
|
private readonly setHttpStatusFromError;
|
|
66
87
|
constructor(ws: WebSocketLike, requestHandlers: MethodHandlers<ImplementedMethods, CallableMethods, RequestContext>, globalMiddlewares: GenericMiddleware<CallableMethods, RequestContext>[], config: TracedSocketConfig, options: TracedSocketOptions);
|
|
88
|
+
/**
|
|
89
|
+
* Injects W3C trace context (traceparent/tracestate) into outbound request messages
|
|
90
|
+
* so that receiver-side spans can be linked. Used for both response paths and
|
|
91
|
+
* outbound calls (e.g. vite-plugin callEditorClients/callLibraryClients, server-initiated socket.call.*).
|
|
92
|
+
*/
|
|
93
|
+
protected decorateToSend(message: SocketMessage): SocketMessage;
|
|
67
94
|
protected callHandler<Params, Result, CallableMethodsInner, RequestContextInner extends RequestContextBase>(handler: MethodHandler<Params, Result, CallableMethodsInner, RequestContextInner>, params: Params, ctx: RequestContextInner, client: ISocketClient<CallableMethodsInner>, next: () => Promise<Result>): Promise<Result>;
|
|
95
|
+
/**
|
|
96
|
+
* Extract parent trace context from HTTP upgrade request headers (W3C Trace Context).
|
|
97
|
+
* Enables trace continuity from HTTP → WebSocket per epic-c2-context-propagation.
|
|
98
|
+
*/
|
|
99
|
+
private extractParentContext;
|
|
100
|
+
/**
|
|
101
|
+
* Whether to attach Tier 1 attributes (e.g. user email) to spans.
|
|
102
|
+
* Attach PII when Tier 1 is exported (e.g. CLOUD: all tiers go to Superblocks-owned infra).
|
|
103
|
+
* Omit PII when Tier 1 is local-only (e.g. CLOUD_PREM: Tier 2 export must not contain PII).
|
|
104
|
+
* When there is no policy evaluator, do not attach Tier 1 (safe default for PII).
|
|
105
|
+
*/
|
|
106
|
+
private shouldAttachTier1Attributes;
|
|
107
|
+
/**
|
|
108
|
+
* Placeholder for Tier 1 attributes when omitted. Call only when shouldAttachTier1Attributes() is false.
|
|
109
|
+
* Distinguishes: policy evaluator present but Tier 1 not allowed vs no policy evaluator provided.
|
|
110
|
+
*/
|
|
111
|
+
private getTier1OmittedPlaceholder;
|
|
68
112
|
protected handleMessage(message: SocketMessage): Promise<void>;
|
|
69
113
|
request<Params, Result>(method: string, params: Params, authorization?: string): Promise<Result>;
|
|
70
114
|
protected respond<Result>(requestId: number, result: Result): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traced-socket.d.ts","sourceRoot":"","sources":["../../src/node/traced-socket.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"traced-socket.d.ts","sourceRoot":"","sources":["../../src/node/traced-socket.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAC3C,OAAO,EAWL,MAAM,EACP,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EACL,OAAO,EACP,aAAa,EACb,aAAa,EAEb,kBAAkB,EAClB,aAAa,EACb,WAAW,EAUX,cAAc,EACd,iBAAiB,EACjB,cAAc,EAEf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AASnD;;GAEG;AACH,UAAU,UAAU;IAClB,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAKD;;GAEG;AACH,UAAU,aAAa;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACvC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACzE,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;CAC7E;AAOD;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;CACxD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,6GAA6G;IAC7G,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,eAAe,CAAC,EAAE,2BAA2B,CAAC;IAC9C,4DAA4D;IAC5D,sBAAsB,CAAC,EAAE,CACvB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,KACf;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3D,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QACjC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;KAClC,CAAC;CACH;AAgED;;;;;;GAMG;AACH,qBAAa,YAAY,CACvB,kBAAkB,EAClB,eAAe,EACf,cAAc,SAAS,kBAAkB,CACzC,SAAQ,OAAO,CAAC,kBAAkB,EAAE,eAAe,EAAE,cAAc,CAAC;IACpE,OAAO,CAAC,qBAAqB,CAA2B;IACxD,OAAO,CAAC,qBAAqB,CAA2B;IACxD,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAA8B;IAC/D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAI7B;gBAGR,EAAE,EAAE,aAAa,EACjB,eAAe,EAAE,cAAc,CAC7B,kBAAkB,EAClB,eAAe,EACf,cAAc,CACf,EACD,iBAAiB,EAAE,iBAAiB,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE,EACvE,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,mBAAmB;IAkC9B;;;;OAIG;IACH,SAAS,CAAC,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa;cAc/C,WAAW,CACzB,MAAM,EACN,MAAM,EACN,oBAAoB,EACpB,mBAAmB,SAAS,kBAAkB,EAE9C,OAAO,EAAE,aAAa,CACpB,MAAM,EACN,MAAM,EACN,oBAAoB,EACpB,mBAAmB,CACpB,EACD,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,mBAAmB,EACxB,MAAM,EAAE,aAAa,CAAC,oBAAoB,CAAC,EAC3C,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAC1B,OAAO,CAAC,MAAM,CAAC;IA+ElB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;;;;OAKG;IACH,OAAO,CAAC,2BAA2B;IASnC;;;OAGG;IACH,OAAO,CAAC,0BAA0B;cAMlB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA2F7D,OAAO,CAAC,MAAM,EAAE,MAAM,EAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC;IAmBlB,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAmClE,SAAS,CAAC,YAAY,CACpB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,WAAW,EAClB,SAAS,CAAC,EAAE,KAAK,GAChB,IAAI;IA4BP,OAAO,CAAC,QAAQ;IAST,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;CAsBpC"}
|