@uipath/common 1.201.0 → 1.202.0-preview.136

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.
Files changed (37) hide show
  1. package/dist/catch-error.d.ts +14 -0
  2. package/dist/catch-error.js +259 -10
  3. package/dist/classified-failure.d.ts +28 -0
  4. package/dist/entity-name-rules.d.ts +18 -0
  5. package/dist/entity-name-rules.js +241 -0
  6. package/dist/error-handler.d.ts +13 -0
  7. package/dist/exit-code.d.ts +42 -0
  8. package/dist/formatter.d.ts +34 -5
  9. package/dist/index.browser.d.ts +3 -0
  10. package/dist/index.browser.js +11328 -10486
  11. package/dist/index.d.ts +10 -1
  12. package/dist/index.js +12320 -11208
  13. package/dist/logger.d.ts +15 -0
  14. package/dist/package-metadata-options.js +3 -3
  15. package/dist/polling/poll-failure-mapping.d.ts +15 -1
  16. package/dist/sdk-user-agent.js +6 -6
  17. package/dist/telemetry/command-name.d.ts +60 -0
  18. package/dist/telemetry/console-telemetry-provider.d.ts +5 -6
  19. package/dist/telemetry/debug-telemetry-provider.d.ts +5 -6
  20. package/dist/telemetry/index.d.ts +3 -3
  21. package/dist/telemetry/index.js +18581 -105
  22. package/dist/telemetry/invocation-request.d.ts +38 -0
  23. package/dist/telemetry/logger-telemetry-provider.d.ts +5 -6
  24. package/dist/telemetry/node-appinsights-telemetry-provider.d.ts +17 -29
  25. package/dist/telemetry/node.d.ts +2 -2
  26. package/dist/telemetry/packaged-name.d.ts +22 -0
  27. package/dist/telemetry/pii-redactor.d.ts +110 -13
  28. package/dist/telemetry/pseudonymize.d.ts +57 -0
  29. package/dist/telemetry/span-clock.d.ts +27 -0
  30. package/dist/telemetry/supplied-values.d.ts +59 -0
  31. package/dist/telemetry/telemetry-init.d.ts +27 -0
  32. package/dist/telemetry/telemetry-provider.d.ts +84 -16
  33. package/dist/telemetry/telemetry-service.d.ts +71 -41
  34. package/dist/telemetry/telemetry-spool.d.ts +17 -0
  35. package/dist/timings.d.ts +99 -0
  36. package/dist/trackedAction.d.ts +25 -2
  37. package/package.json +6 -2
@@ -0,0 +1,38 @@
1
+ import type { TelemetryContext, TelemetryProperties } from "./telemetry-service.js";
2
+ /**
3
+ * Open this invocation's request scope and run `fn` inside it.
4
+ *
5
+ * Call once, as early in the run as there is a run — inside the timing scope,
6
+ * since the span's start and duration are read from the invocation's baseline.
7
+ */
8
+ export declare function runWithInvocationRequest<T>(fn: () => Promise<T>): Promise<T>;
9
+ /**
10
+ * Run `fn` inside the invocation's request scope, opening one only if nothing
11
+ * has.
12
+ *
13
+ * For a caller that cannot assume the entry point ran: the standalone tool bins
14
+ * (`packages/*​/src/index.ts`) go straight to Commander, so without this their
15
+ * commands would have no scope and their outbound calls would go untracked.
16
+ */
17
+ export declare function ensureInvocationRequestScope<T>(fn: () => Promise<T>): Promise<T>;
18
+ /**
19
+ * This invocation's request context — the span every dependency and leaf in the
20
+ * run hangs under. `undefined` before the scope is opened.
21
+ *
22
+ * The active context wins over the slot, because it is the per-invocation one:
23
+ * in a host running two commands at once (the MCP bridge) the slot holds
24
+ * whichever opened last, so reading it alone made one command's request
25
+ * envelope ship under the other's span id.
26
+ */
27
+ export declare function getInvocationRequestContext(): TelemetryContext | undefined;
28
+ /**
29
+ * Emit this invocation's request span. One call per run.
30
+ *
31
+ * Duration is read here rather than passed in, so it covers everything from the
32
+ * invocation's start to this moment. The only part of the run left out is the
33
+ * telemetry flush, which is what sends this envelope — a span cannot contain
34
+ * its own delivery.
35
+ */
36
+ export declare function emitInvocationRequest(name: string, success: boolean, properties?: TelemetryProperties): void;
37
+ /** Drop the scope, so the next invocation in this process opens its own. */
38
+ export declare function resetInvocationRequest(): void;
@@ -1,5 +1,4 @@
1
- import type { ITelemetryProvider } from "./telemetry-provider.js";
2
- import type { TelemetryProperties } from "./telemetry-service.js";
1
+ import type { ITelemetryProvider, TrackedDependencySpan, TrackedEvent, TrackedException, TrackedSpan } from "./telemetry-provider.js";
3
2
  /**
4
3
  * Telemetry provider that enriches all events with analyticsUniqueId
5
4
  * from the Windows registry and forwards them to the shared logger.
@@ -8,8 +7,8 @@ export declare class LoggerTelemetryProvider implements ITelemetryProvider {
8
7
  private readonly analyticsUniqueId;
9
8
  constructor();
10
9
  private enrich;
11
- trackEvent(eventName: string, properties?: TelemetryProperties): Promise<void>;
12
- trackException(error: Error, properties?: TelemetryProperties): Promise<void>;
13
- trackRequest(name: string, duration: number, success: boolean, properties?: TelemetryProperties): Promise<void>;
14
- trackDependency(name: string, type: string, duration: number, success: boolean, properties?: TelemetryProperties): Promise<void>;
10
+ trackEvent({ name, properties }: TrackedEvent): Promise<void>;
11
+ trackException({ error, properties, }: TrackedException): Promise<void>;
12
+ trackRequest({ name, durationMs, success, properties, }: TrackedSpan): Promise<void>;
13
+ trackDependency({ name, type, durationMs, success, properties, }: TrackedDependencySpan): Promise<void>;
15
14
  }
@@ -1,5 +1,4 @@
1
- import type { ITelemetryProvider } from "./telemetry-provider.js";
2
- import { type TelemetryProperties } from "./telemetry-service.js";
1
+ import type { ITelemetryProvider, TrackedDependencySpan, TrackedEvent, TrackedException, TrackedSpan } from "./telemetry-provider.js";
3
2
  export { getGlobalTelemetryProperties, setGlobalTelemetryProperties, } from "./global-telemetry-properties.js";
4
3
  /**
5
4
  * Envelopes still buffered in the SDK channel at exit, plus the ingestion
@@ -43,40 +42,29 @@ export declare class NodeAppInsightsTelemetryProvider implements ITelemetryProvi
43
42
  */
44
43
  private mergeProperties;
45
44
  /**
46
- * Read the trace context off the internal `uip.trace.*` routing keys and
47
- * strip them, so nothing correlation-related ever ships as a custom
48
- * dimension. `merged` is a fresh per-call object, so mutating it in place is
49
- * safe; the same reference is what the client call emits as `properties`.
45
+ * Native correlation tags for any tracked item.
50
46
  *
51
- * `operationId` falls back to the per-invocation id when no context is set
52
- * (events outside a `trackRequest` scope), so every item in one run still
53
- * groups under the same `operation_Id`. `parentId`/`spanId` are only present
54
- * inside a scope.
55
- */
56
- private consumeCorrelation;
57
- /**
58
- * Native correlation tags for a LEAF item (event/exception). It has no item
59
- * id of its own, so it nests under the current operation: `operation_Id` is
60
- * the trace id, and `operation_ParentId` is the enclosing request/
61
- * dependency's id (the context's `spanId`), present only inside a scope.
47
+ * `operation_Id` is the trace; `operation_ParentId` is whatever the item
48
+ * hangs under — for a span its parent span, for a leaf (event/exception)
49
+ * the span it was emitted inside. Both arrive as fields on the item, so
50
+ * one mapping serves requests, dependencies, events and exceptions alike,
51
+ * and nothing correlation-related has to be read out of — or stripped
52
+ * from — the custom dimensions.
53
+ *
54
+ * `operationId` falls back to the per-invocation id for an item emitted
55
+ * outside any scope, so every item in one run still groups under the same
56
+ * `operation_Id`.
62
57
  *
63
58
  * Cross-service join: `makeTrackedFetch` stamps a W3C `traceparent`
64
59
  * (`00-<operation_Id>-<span>-01`) on every outbound call made inside a
65
60
  * request scope, so the API side can line its telemetry up with this trace.
66
61
  * These native tags are the CLI-side half of that join.
67
62
  */
68
- private leafTagOverrides;
69
- /**
70
- * Native correlation for an OPERATION item (request/dependency). It carries
71
- * its own item `id` (the context's `spanId`) so child items can point their
72
- * `operation_ParentId` at it, and its own `operation_ParentId` is the
73
- * context's `parentId` (absent for a top-level request → a trace root).
74
- */
75
- private operationCorrelation;
76
- trackEvent(eventName: string, properties?: TelemetryProperties): Promise<void>;
77
- trackException(error: Error, properties?: TelemetryProperties): Promise<void>;
78
- trackRequest(name: string, duration: number, success: boolean, properties?: TelemetryProperties): Promise<void>;
79
- trackDependency(name: string, type: string, duration: number, success: boolean, properties?: TelemetryProperties, resultCode?: string): Promise<void>;
63
+ private correlationTags;
64
+ trackEvent(event: TrackedEvent): Promise<void>;
65
+ trackException(exception: TrackedException): Promise<void>;
66
+ trackRequest(span: TrackedSpan): Promise<void>;
67
+ trackDependency(span: TrackedDependencySpan): Promise<void>;
80
68
  flush(): Promise<void>;
81
69
  /**
82
70
  * Take the envelopes still buffered in the SDK channel (nothing has sent
@@ -5,8 +5,8 @@ export { buildEnvironmentProperties, type NormalizedEnvironment, normalizeBaseUr
5
5
  export { type CiProvider, detectExecutionContext, EXECUTION_CONTEXT_VALUES, type ExecutionContext, type ExecutionContextDetection, type ExecutionContextDetectionOptions, getExecutionContextTelemetryProperties, setExecutionContextAuthSignal, } from "./execution-context.js";
6
6
  export { NodeContextStorage } from "./node-context-storage.js";
7
7
  export { getConfiguredTelemetrySessionId, getTelemetrySessionId, getTelemetrySessionSource, TELEMETRY_SESSION_ID_ENV, TELEMETRY_SESSION_SOURCE_PROPERTY, } from "./session-id.js";
8
- export type { ITelemetryProvider } from "./telemetry-provider.js";
8
+ export type { ITelemetryProvider, TelemetryCorrelation, TrackedDependencySpan, TrackedEvent, TrackedException, TrackedSpan, } from "./telemetry-provider.js";
9
9
  export type { ITelemetryService, TelemetryContext, TelemetryProperties, } from "./telemetry-service.js";
10
- export { TELEMETRY_OPERATION_ID_PROPERTY, TELEMETRY_PARENT_ID_PROPERTY, TELEMETRY_SPAN_ID_PROPERTY, TelemetryService, } from "./telemetry-service.js";
10
+ export { TelemetryService } from "./telemetry-service.js";
11
11
  export { getInboundTraceContext, type InboundTraceContext, parseInboundTraceparent, TELEMETRY_TRACEPARENT_ENV, } from "./trace-context.js";
12
12
  export { makeTrackedFetch } from "./tracked-fetch.js";
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Split a pack service's `<name>@<version>` display string.
3
+ *
4
+ * `flow-pack-service` and `maestro-pack-service` both return the packed
5
+ * artifact as one display string — `invoice-process@2.0.0` — and both hand it
6
+ * straight to telemetry's `package_name`. That breaks the dimension it feeds:
7
+ * the pseudonym is computed over the whole string, so the same package gets a
8
+ * different `package_name` for every version, and a publish event can no longer
9
+ * be joined to the deploy event for the same package. Splitting first is what
10
+ * makes the pseudonym stable across versions.
11
+ *
12
+ * The separator is unambiguous. Both services validate the name against
13
+ * `VALID_PACKAGE_NAME_REGEX` — letters, numbers, dots, underscores, hyphens —
14
+ * so a name can never contain `@`, and the last `@` is always the one the
15
+ * service added. A string with no `@` is returned as a name with no version,
16
+ * which is the right answer for a caller that already passes a bare name.
17
+ */
18
+ export interface PackagedName {
19
+ name: string;
20
+ version?: string;
21
+ }
22
+ export declare function splitPackagedName(packaged: string): PackagedName;
@@ -9,29 +9,126 @@
9
9
  * by a sensitive prefix (apiKey, accessKey, signingKey, …) so benign
10
10
  * names like sortKey, cacheKey, keyword pass through.
11
11
  * 2. Value detectors — JWTs, UUIDs, emails, URLs, user-home paths are
12
- * rewritten to a non-reversible form (hash or structural redaction).
13
- * Long strings are truncated.
12
+ * rewritten to a pseudonym or structurally redacted. Long strings are
13
+ * truncated.
14
14
  *
15
15
  * The goal is defense in depth: even if a new sensitive option slips through
16
16
  * without being added to the denylist, value detectors catch common shapes.
17
+ *
18
+ * A pseudonym is NOT anonymous — see `pseudonymize.ts`. It keeps plaintext off
19
+ * the wire and out of the store, and it joins across events; it does not stop
20
+ * someone holding a candidate list from confirming a guess. Emitted `email#…` /
21
+ * `uuid#…` values carry the same handling obligations as the values they stand
22
+ * in for.
17
23
  */
18
24
  /**
19
- * Run the value detectors over a free-form string (no name-based check). Use for
20
- * strings that aren't property values but can still carry PII — a telemetry
21
- * event/dependency name (`GET /odata/Users/alice@corp.com`) or an exception
22
- * message. Emails/UUIDs are hashed, URLs reduced to origin, tokens/JWTs and
23
- * user-home paths redacted, over-long strings truncated.
25
+ * Cap on an emitted property value.
26
+ *
27
+ * Sized against what redaction ADDS, not just what the caller wrote. Each
28
+ * detector hit swaps its match for a `kind#<32 hex>` pseudonym, which is 24
29
+ * characters wider than the 8-hex digest this replaced — so a message carrying
30
+ * two or three ids or addresses would grow past a 200-character cap and lose its
31
+ * tail to truncation, taking the HTTP status and the failure shape with it.
32
+ * 280 restores the headroom the old cap gave before the digests widened, and is
33
+ * far below the App Insights 8192-character property limit, so nothing
34
+ * downstream reshapes it.
24
35
  */
25
- export declare function redactValue(value: string): string;
36
+ export declare const MAX_VALUE_LENGTH = 280;
26
37
  /**
27
- * Return a sanitized copy of an Error whose `message` and `stack` have been run
28
- * through the value detectors, so telemetry never ships a raw exception string
29
- * (they routinely embed the offending token, URL, path, or id). The original
30
- * frames are preserved — only their sensitive substrings are rewritten — and
31
- * the `name` is kept so App Insights still groups by exception type.
38
+ * Cap on a redacted stack trace.
39
+ *
40
+ * A stack is not a dimension and the value cap makes no sense for it: at 280
41
+ * characters a stack is two or three frames, which is the part every stack has in
42
+ * common and none of the part that says where the bug is. App Insights allows
43
+ * 8192 characters per property, so this leaves headroom under it while keeping
44
+ * enough frames to be worth shipping.
45
+ */
46
+ export declare const MAX_STACK_LENGTH = 4096;
47
+ /**
48
+ * Redact a free-form message — an error string built from whatever a server or
49
+ * an OS sent back.
50
+ *
51
+ * The value detectors alone are not enough here. `HTTP 409: Queue
52
+ * 'BigBank_AG_Inv_2024' is locked by user Jane D.` matches none of them: those
53
+ * are names, not tokens, URLs or ids. What the message is worth keeping for is
54
+ * its *shape* — which call failed and how — so the three places customer data
55
+ * actually sits are removed and the rest is kept:
56
+ *
57
+ * - an embedded JSON body, which is an API response folded into the message;
58
+ * - quoted literals, where a server names the offending resource or person;
59
+ * - anything this run was *given* as an argument, quoted or not, because the
60
+ * CLI's own messages interpolate a value bare (`Unknown agent: bogusagent`
61
+ * echoes back exactly the string `trackedAction` had just withheld from the
62
+ * `uip.cmd.arg.*` dimensions). See `supplied-values.ts`.
63
+ *
64
+ * `HTTP 409: Queue '<redacted>' is locked by user Jane D.` still tells an
65
+ * operator what happened.
66
+ *
67
+ * Order matters: structure first, then the supplied-value scrub. The scrub
68
+ * emits `[REDACTED]`, and running it before the body pass would let that
69
+ * placeholder be read as an embedded array. Anything inside a body or a quoted
70
+ * span is already gone by the time the scrub runs, so nothing is missed by
71
+ * going in this order.
72
+ */
73
+ /**
74
+ * Scrub a span or event NAME.
75
+ *
76
+ * A name is not a message, and the difference is the supplied-value scrub. That
77
+ * scrub is a substring replace over the whole string, and a command path is
78
+ * made of the same words a user types as arguments: with the full message
79
+ * treatment, `uip tools install tools` shipped
80
+ * `requests.name = uip.[REDACTED].install` — the column every command count,
81
+ * failure rate and duration percentile groups by, destroyed by the run's own
82
+ * argument. So a name gets the quoted-literal rule, which is what an OData key
83
+ * predicate needs (`GET /odata/QueueDefinitions('BigBank_AG_Inv_2024')`), plus
84
+ * the detectors, and nothing that can rewrite a word the CLI itself chose.
85
+ *
86
+ * The one name that IS untrusted end to end is the fetch wrapper's
87
+ * `METHOD /path` — see {@link redactHttpDependencyName}, which
88
+ * {@link ITelemetryService.trackDependencyResult} calls before this.
89
+ */
90
+ export declare function redactSpanName(name: string): string;
91
+ /**
92
+ * Scrub the fetch wrapper's `METHOD /path`, the one name that is untrusted end
93
+ * to end: a path segment can be an email or an id (`/odata/Users/a@b.com`), a
94
+ * resource the server quoted, or the exact string the user typed as an argument.
95
+ * So the PATH gets the full message treatment, supplied-value scrub included —
96
+ * a command path can never arrive here, which is why the scrub that would wreck
97
+ * one is safe on this name and on no other.
98
+ *
99
+ * The METHOD does not. It is a word the CLI chose, from a set of eight, and the
100
+ * scrub is a plain substring replace: a run whose own argument was `POST` (or
101
+ * `HEAD`, `PATCH`, `DELETE`) turned every one of its outbound calls into
102
+ * `[REDACTED] /path` and took the verb out of the column that separates a read
103
+ * from a write. Split first, scrub the half that is data.
104
+ */
105
+ export declare function redactHttpDependencyName(name: string): string;
106
+ export declare function redactMessage(value: string): string;
107
+ /**
108
+ * Return a sanitized copy of an Error whose `message` and `stack` have been
109
+ * scrubbed, so telemetry never ships a raw exception string (they routinely
110
+ * embed the offending token, URL, path, or id). The original frames are
111
+ * preserved — only their sensitive substrings are rewritten — and the `name` is
112
+ * kept so App Insights still groups by exception type.
113
+ *
114
+ * The message gets {@link redactMessage}, not the detectors alone. An exception
115
+ * message IS a message: it is where a server names the thing that went wrong
116
+ * (`Queue 'BigBank_AG_Inv_2024' is locked`), where a response body ends up
117
+ * inlined, and where the CLI interpolates what the user typed. Running only the
118
+ * detectors here shipped all three verbatim in `exceptions.message` while the
119
+ * identical text was scrubbed out of the request row's `errorMessage` — the same
120
+ * string, two answers, and the looser one on the surface that also carries a
121
+ * stack.
32
122
  */
33
123
  export declare function redactError(error: Error): Error;
34
124
  type TelemetryValue = string | number | boolean;
125
+ /**
126
+ * True when a property name looks like it holds credentials. Exported so
127
+ * `describeThrownValue` can drop the same names when it serializes a thrown
128
+ * object into a user-facing message — a rejected HTTP client payload often
129
+ * carries the request's own `Authorization` header.
130
+ */
131
+ export declare function isSensitiveName(name: string): boolean;
35
132
  /**
36
133
  * Redact a single telemetry property.
37
134
  * Preserves the original value's type (number/boolean pass through unchanged);
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The one-way transform every identifying value in telemetry goes through.
3
+ *
4
+ * ## What this is, and what it is not
5
+ *
6
+ * This produces a **pseudonym**, not an anonymous token. Hashing cannot make a
7
+ * low-entropy value unrecoverable: anyone holding the telemetry AND a candidate
8
+ * list (a company's employee directory, a customer's domain list) can hash the
9
+ * candidates and match. That is true of any unkeyed digest, and the salt below
10
+ * ships in this source file, so it does not change the analysis. Treat every
11
+ * `email#…` / `uuid#…` / `origin#…` value as *pseudonymous personal data* under
12
+ * the same retention and access rules as the raw value would be.
13
+ *
14
+ * What the digest DOES buy:
15
+ *
16
+ * - it removes the plaintext from the wire and the store, so nobody reading a
17
+ * dashboard, an export, or a spool file sees a customer's address;
18
+ * - it is stable, so the same value joins across events and runs;
19
+ * - at 128 bits it does not collide, which the previous 32-bit FNV-1a did:
20
+ * that space hit a 50% collision chance at ~77k distinct values, so at real
21
+ * telemetry volume distinct tenants, projects and people silently merged
22
+ * into one bucket — breaking the joins the hash exists for.
23
+ *
24
+ * This is the ONLY digest in the telemetry pipeline. `pii-redactor.ts` calls it
25
+ * directly for every `email#…`, `uuid#…` and `url#…` it writes, rather than
26
+ * through the FNV-1a wrapper it used to keep. Two strengths for one job would have
27
+ * left an email on the very payload whose `package_name` is pseudonymized here
28
+ * carrying the collision risk this file exists to remove. Anything new that
29
+ * needs to hash an identifying value calls this, and nothing rolls its own.
30
+ *
31
+ * ## Two implementations, one digest
32
+ *
33
+ * The redactor runs inside `String.prototype.replace` callbacks, so the digest
34
+ * has to be synchronous — which rules out `crypto.subtle.digest`, the async
35
+ * one. It does NOT rule out `node:crypto`: `createHash().digest()` is fully
36
+ * synchronous, and about 36x faster than the pure implementation below (0.28us
37
+ * against 10.2us on a short string). So Node takes `node:crypto` and the pure
38
+ * version is the browser fallback, where `node:crypto` does not resolve. Both
39
+ * produce the same bytes, so a pseudonym computed on either path joins with the
40
+ * other — and `resolveSha256Hex` checks that rather than assuming it.
41
+ *
42
+ * @see hashContent in `../content-hash.ts` for the async SHA-256 used for
43
+ * content addressing — a different job with no sync constraint.
44
+ */
45
+ /**
46
+ * FIPS 180-4 SHA-256 over the UTF-8 bytes of `input`, as 64 lowercase hex.
47
+ *
48
+ * The portable reference implementation: the browser fallback, and the value
49
+ * `resolveSha256Hex` checks `node:crypto` against before adopting it.
50
+ */
51
+ export declare function sha256Hex(input: string): string;
52
+ /**
53
+ * The stable pseudonym for an identifying value: 32 lowercase hex characters.
54
+ *
55
+ * Read the module comment before treating the output as anonymous — it is not.
56
+ */
57
+ export declare function pseudonymize(input: string): string;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * One clock reading, serving both halves of a span.
3
+ *
4
+ * A span carries two numbers that have to agree: the wall-clock moment it
5
+ * began, which is where App Insights draws the bar, and its duration, which is
6
+ * how far the bar extends. Reading `new Date()` for the first and a separate
7
+ * `performance.now()` baseline for the second samples two clocks at two
8
+ * moments, and those clocks drift independently — the wall clock can be stepped
9
+ * by NTP or a suspend/resume mid-span, the monotonic one cannot.
10
+ *
11
+ * {@link startSpanClock} reads `performance.now()` once. The start is that
12
+ * reading projected onto the wall clock through `performance.timeOrigin`, and
13
+ * the duration is measured back against the same reading, so the bar's position
14
+ * and its length are two views of a single instant.
15
+ *
16
+ * `timings.ts` applies the same projection to the whole invocation
17
+ * (`invocationStartedAt` / `invocationElapsedMs`); this is that pattern for a
18
+ * span that opens and closes inside one.
19
+ */
20
+ export interface SpanClock {
21
+ /** Wall-clock moment the span opened. */
22
+ readonly startedAt: Date;
23
+ /** Milliseconds since it opened, off the monotonic clock. */
24
+ elapsedMs(): number;
25
+ }
26
+ /** Open a clock for a span that is starting now. */
27
+ export declare function startSpanClock(): SpanClock;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The literal strings this run's user typed as argument and option values.
3
+ *
4
+ * Held in memory and **never emitted** — the point is the opposite.
5
+ * `trackedAction` withholds an argument's value from the `uip.cmd.arg.*`
6
+ * dimensions unless the value cannot carry a payload, but that only covers those
7
+ * dimensions. Nothing stopped the same string coming back out through a
8
+ * *message*: a command that says `Unknown agent: bogusagent`, or a server that
9
+ * says `Queue 'BigBank_AG_Inv_2024' not found`, hands it to
10
+ * `OutputFormatter.error`, which ships `Message` to telemetry.
11
+ *
12
+ * Quoting rules cannot close that, because the CLI's own messages interpolate
13
+ * the value bare. What closes it is knowing what the user typed and refusing to
14
+ * echo it — see `redactMessage`.
15
+ *
16
+ * Process-wide, like every other telemetry slot on this path, and held as one
17
+ * ENTRY PER RUN rather than a single list. A long-lived host runs commands
18
+ * concurrently (the MCP bridge), and a single list made both directions wrong:
19
+ * the second command to start replaced the first one's values, so the first
20
+ * stopped scrubbing its own arguments, and the first to finish emptied the list
21
+ * and stopped scrubbing the second's. With an entry per run, an overlap scrubs
22
+ * the union — over-scrub, the safe direction — and a run that ends takes only
23
+ * its own values with it.
24
+ */
25
+ export interface SuppliedValueEntry {
26
+ readonly values: readonly string[];
27
+ }
28
+ /**
29
+ * Record the values this run was given, and return the handle that releases
30
+ * them again.
31
+ *
32
+ * The handle is the entry object itself, so it works across bundles: a number
33
+ * or a name would have to be unique in a process where several copies of this
34
+ * module are live, and object identity already is.
35
+ *
36
+ * Hand the handle back to {@link releaseSuppliedArgumentValues} when the run
37
+ * ends — never to {@link clearSuppliedArgumentValues}, which drops every
38
+ * concurrent run's entries too. The pair is exported together from the package
39
+ * barrel for that reason: a caller that can record and cannot release leaks its
40
+ * values into every later run in the process.
41
+ */
42
+ export declare function recordSuppliedArgumentValues(values: unknown): SuppliedValueEntry;
43
+ /** Drop one run's values, leaving any other run's in place. */
44
+ export declare function releaseSuppliedArgumentValues(entry: SuppliedValueEntry): void;
45
+ /**
46
+ * Every value a run in flight was given, longest first.
47
+ *
48
+ * Longest first so a value that contains another is replaced whole rather than
49
+ * leaving the tail of it behind.
50
+ */
51
+ export declare function getSuppliedArgumentValues(): readonly string[];
52
+ /**
53
+ * Drop every run's values.
54
+ *
55
+ * For tests, and for a host that knows nothing is in flight.
56
+ * `trackedAction` releases its own entry instead — see
57
+ * {@link releaseSuppliedArgumentValues}.
58
+ */
59
+ export declare function clearSuppliedArgumentValues(): void;
@@ -1,5 +1,32 @@
1
1
  import type { ITelemetryProvider, ITelemetryService } from "./node.js";
2
2
  import { type NodeAppInsightsTelemetryProvider } from "./node-appinsights-telemetry-provider.js";
3
+ /**
4
+ * The one origin this process is allowed to send telemetry to.
5
+ *
6
+ * The spool sender needs this because the URL it POSTs to arrives from a **file
7
+ * on disk**, and a spool file is not a trusted input — anything running as the
8
+ * user can drop one in, which on a shared CI agent is any other job on the same
9
+ * uid. Checking only the scheme (all the sender used to do) let such a file
10
+ * point the CLI's own sidecar at an arbitrary host and hand it whole envelopes.
11
+ * Comparing against this closes it: the file supplies the path, never the
12
+ * destination.
13
+ *
14
+ * Read from the connection string rather than hardcoded, so an operator's
15
+ * `UIPATH_AI_CONNECTION_STRING` (and the e2e suite's local ingestion server)
16
+ * keeps working — the destination is theirs to choose through configuration,
17
+ * which is exactly the channel a file on disk is not.
18
+ *
19
+ * This has to answer with whatever the SDK would have used, because the URL in
20
+ * the spool file is the SDK's `config.endpointUrl` and a mismatch means the
21
+ * file is dropped. `InstrumentationKey=…` with no `IngestionEndpoint` is legal
22
+ * and common, and the SDK then sends to {@link DEFAULT_INGESTION_ORIGIN} — so
23
+ * returning "no endpoint" there and failing closed silently discarded every
24
+ * spooled envelope for anyone using the short form. There is no case left where
25
+ * a spool file exists and no origin resolves: without a usable instrumentation
26
+ * key the SDK throws instead of constructing a client, so nothing is ever
27
+ * spooled.
28
+ */
29
+ export declare function getTelemetryIngestionOrigin(): string;
3
30
  /**
4
31
  * Create or retrieve the shared Node.js Application Insights telemetry provider.
5
32
  * Uses globalThis to ensure all bundled copies share a single TelemetryClient.
@@ -1,31 +1,99 @@
1
1
  import type { TelemetryProperties } from "./telemetry-service.js";
2
2
  /**
3
- * Interface for telemetry providers that can be injected into the solution packager.
4
- * Providers are simple adapters that send pre-measured telemetry data to their backends.
3
+ * Where an item sits in the trace.
4
+ *
5
+ * Every tracked item carries this, because every backend needs it and none of
6
+ * it belongs in custom dimensions. It used to travel as reserved `uip.trace.*`
7
+ * keys inside `properties`, which meant each provider had to know the contract,
8
+ * read the keys, and delete them before emitting — and a provider that forgot
9
+ * (the logger one, the browser one) shipped raw correlation ids as dimensions.
10
+ * An item that describes itself needs no such contract.
5
11
  */
12
+ export interface TelemetryCorrelation {
13
+ /** The trace this item belongs to (`operation_Id`). */
14
+ operationId?: string;
15
+ /**
16
+ * The span this item hangs under (`operation_ParentId`). For a span, the
17
+ * span containing it — absent on a trace root. For a leaf, the span it was
18
+ * emitted inside — absent outside any span scope.
19
+ */
20
+ parentId?: string;
21
+ }
22
+ /**
23
+ * One finished span, as a provider receives it.
24
+ *
25
+ * Everything the backend needs about a request or dependency arrives as this
26
+ * one object: what it was, how long it took, whether it worked, when it began,
27
+ * and where it sits in the trace.
28
+ */
29
+ export interface TrackedSpan extends TelemetryCorrelation {
30
+ /** Operation name — the command path, or `METHOD /path` for a call. */
31
+ name: string;
32
+ /** Measured wall-clock length, in milliseconds. */
33
+ durationMs: number;
34
+ success: boolean;
35
+ /**
36
+ * When the span began.
37
+ *
38
+ * App Insights reads this as the span START and draws the bar forward by
39
+ * `durationMs`. A provider whose backend timestamps on arrival must use it;
40
+ * without it, the only start available is the moment of emit, which charges
41
+ * the bar for everything that happened after the clock stopped.
42
+ */
43
+ startedAt?: Date;
44
+ /** This span's own id, which its children point their parent id at. */
45
+ id?: string;
46
+ /** Custom dimensions. Correlation is not among them — see above. */
47
+ properties?: TelemetryProperties;
48
+ }
49
+ /** A {@link TrackedSpan} for an outbound call. */
50
+ export interface TrackedDependencySpan extends TrackedSpan {
51
+ /** Dependency kind, e.g. `HTTP`. */
52
+ type: string;
53
+ /**
54
+ * Backend-native status of the call (e.g. the HTTP status code). Omitted,
55
+ * a provider derives a coarse code from `success`; supplying the real one
56
+ * keeps `dependencies.resultCode` truthful instead of collapsing every
57
+ * outcome to 200/500.
58
+ */
59
+ resultCode?: string;
60
+ }
61
+ /**
62
+ * One event, as a provider receives it.
63
+ *
64
+ * A leaf: it marks an instant rather than an interval, so it has no duration
65
+ * and no id of its own. It nests under whichever span was open when it was
66
+ * emitted, via {@link TelemetryCorrelation.parentId}.
67
+ */
68
+ export interface TrackedEvent extends TelemetryCorrelation {
69
+ name: string;
70
+ /** Custom dimensions. Correlation is not among them. */
71
+ properties?: TelemetryProperties;
72
+ }
73
+ /** A {@link TrackedEvent}-shaped leaf carrying an error instead of a name. */
74
+ export interface TrackedException extends TelemetryCorrelation {
75
+ /** Already redacted by the service — providers emit it as-is. */
76
+ error: Error;
77
+ /** Custom dimensions. Correlation is not among them. */
78
+ properties?: TelemetryProperties;
79
+ }
6
80
  export interface ITelemetryProvider {
7
81
  /**
8
- * Track a custom event with optional properties.
82
+ * Track a custom event.
9
83
  */
10
- trackEvent(eventName: string, properties?: TelemetryProperties): Promise<void>;
84
+ trackEvent(event: TrackedEvent): Promise<void>;
11
85
  /**
12
- * Track an exception with optional properties.
86
+ * Track an exception.
13
87
  */
14
- trackException(error: Error, properties?: TelemetryProperties): Promise<void>;
88
+ trackException(exception: TrackedException): Promise<void>;
15
89
  /**
16
- * Track a completed request operation with measured duration.
90
+ * Track a completed request operation.
17
91
  */
18
- trackRequest(name: string, duration: number, success: boolean, properties?: TelemetryProperties): Promise<void>;
92
+ trackRequest(span: TrackedSpan): Promise<void>;
19
93
  /**
20
- * Track a completed dependency operation with measured duration.
21
- *
22
- * `resultCode` is the backend-native status of the call (e.g. the HTTP
23
- * status code for an outbound request). When omitted the provider derives a
24
- * coarse code from `success`. Passing the real code keeps the App Insights
25
- * `dependencies.resultCode` column accurate instead of collapsing every
26
- * outcome to 200/500.
94
+ * Track a completed dependency operation.
27
95
  */
28
- trackDependency(name: string, type: string, duration: number, success: boolean, properties?: TelemetryProperties, resultCode?: string): Promise<void>;
96
+ trackDependency(span: TrackedDependencySpan): Promise<void>;
29
97
  /**
30
98
  * Get the current session ID, if available.
31
99
  */