Uh oh!
There was an error while loading. Please reload this page.
Add Node.js and .NET telemetry SDKs - #822
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Adds stable telemetry consent, policy, and per-run controls to the Node.js and .NET SDKs over the native telemetry contract.
Changes:
- Adds presenter-driven consent and fail-closed policy APIs.
- Propagates telemetry through one-shot and state-aware execution.
- Adds tests, parity/codegen checks, and SDK documentation.
Reviewed changes
Copilot reviewed 33 out of 38 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
tests/scripts/run_telemetry_consent_smoke_test.ps1 | Normalizes the consent smoke test. |
src/core/wxc_common/src/telemetry/policy.rs | Normalizes telemetry policy source. |
sdk/node/tests/unit/wire-conformance.test.ts | Checks telemetry wire conformance. |
sdk/node/tests/unit/telemetry.test.ts | Tests Node consent APIs. |
sdk/node/tests/unit/state-aware.test.ts | Tests state-aware telemetry propagation. |
sdk/node/tests/unit/sandbox.test.ts | Tests one-shot telemetry options. |
sdk/node/src/types.ts | Promotes telemetry configuration. |
sdk/node/src/telemetry.ts | Implements Node consent APIs. |
sdk/node/src/state-aware.ts | Relays state-aware telemetry. |
sdk/node/src/state-aware-types.ts | Updates telemetry documentation. |
sdk/node/src/state-aware-helper.ts | Builds top-level telemetry envelopes. |
sdk/node/src/sandbox.ts | Adds per-invocation telemetry options. |
sdk/node/src/index.ts | Exports telemetry APIs. |
sdk/node/src/helper.ts | Applies one-shot telemetry overrides. |
sdk/node/src/generated/wire.ts | Updates generated stable wire types. |
sdk/node/src/generated/telemetry-consent-wire.ts | Adds generated consent wire types. |
sdk/node/README.md | Documents Node telemetry usage. |
sdk/node/package.json | Runs telemetry unit tests. |
sdk/dotnet/README.md | Documents .NET telemetry usage. |
sdk/dotnet/Microsoft.Mxc.Sdk/TelemetryPolicyState.cs | Defines policy states. |
sdk/dotnet/Microsoft.Mxc.Sdk/TelemetryConsentState.cs | Defines consent states. |
sdk/dotnet/Microsoft.Mxc.Sdk/TelemetryConsent.cs | Defines consent models. |
sdk/dotnet/Microsoft.Mxc.Sdk/StateAwareTypes.cs | Adds lifecycle telemetry options. |
sdk/dotnet/Microsoft.Mxc.Sdk/SandboxPolicy.cs | Adds one-shot telemetry opt-in. |
sdk/dotnet/Microsoft.Mxc.Sdk/Native/NativeLibraryResolver.cs | Improves native profile resolution. |
sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs | Implements .NET consent APIs. |
sdk/dotnet/Microsoft.Mxc.Sdk/MxcLifecycle.cs | Propagates lifecycle telemetry. |
sdk/dotnet/Microsoft.Mxc.Sdk/MxcException.cs | Preserves underlying exceptions. |
sdk/dotnet/Microsoft.Mxc.Sdk/Microsoft.Mxc.Sdk.csproj | Builds profile-specific native libraries. |
sdk/dotnet/Microsoft.Mxc.Sdk/ErrorCode.cs | Adds consent-write failure code. |
sdk/dotnet/Microsoft.Mxc.Sdk.Tests/MxcTelemetryTests.cs | Tests .NET consent and policy behavior. |
sdk/dotnet/Microsoft.Mxc.Sdk.Tests/MxcLifecycleTests.cs | Tests lifecycle telemetry envelopes. |
scripts/versioning/check-telemetry-consent-codegen.js | Verifies generated consent artifacts. |
scripts/check-telemetry-policy-parity.js | Checks cross-language policy states. |
README.md | Documents stable telemetry behavior. |
docs/telemetry/telemetry-policy.md | Normalizes administrative policy docs. |
.github/workflows/Versioning.Checks.Job.yml | Adds telemetry parity checks. |
.github/copilot-instructions.md | Records telemetry architecture and commands. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 33 out of 38 changed files in this pull request and generated no new comments.
Suppressed comments (6)
sdk/dotnet/README.md:133
- The referenced
telemetry-administrative-policy.mdfile does not exist; the policy guide added to the repository isdocs/telemetry/telemetry-policy.md. Point this link at the actual document.
`Allowed` does not grant user consent, while `Blocked` disables collection and
the consent prompt. The policy query fails closed to `Blocked` if the native
library cannot be loaded; non-Windows hosts return `NotApplicable`. See
[`docs/telemetry/telemetry-administrative-policy.md`](../../docs/telemetry/telemetry-administrative-policy.md).
sdk/node/README.md:516
- This link targets
telemetry-administrative-policy.md, which does not exist; the administrative policy document in this PR isdocs/telemetry/telemetry-policy.md. Update the URL so published package documentation does not lead to a 404.
`'allowed'` does not grant user consent, while `'blocked'` disables collection
and the consent prompt. An unreadable or missing `policy` field reads back as
`'blocked'`; non-Windows hosts return `'not-applicable'`. See
[`docs/telemetry/telemetry-administrative-policy.md`](https://github.com/microsoft/mxc/blob/main/docs/telemetry/telemetry-administrative-policy.md).
sdk/dotnet/Microsoft.Mxc.Sdk/TelemetryPolicyState.cs:8
- This XML documentation references a nonexistent
telemetry-administrative-policy.md; the repository's administrator-facing guide isdocs/telemetry/telemetry-policy.md. Correct the path so generated API docs direct users to a real file.
/// <summary>
/// The administrative (MDM / Group Policy) telemetry decision for this machine.
/// See docs/telemetry/telemetry-administrative-policy.md for the admin-facing reference.
sdk/node/src/telemetry.ts:153
- A presenter may legally
throw undefinedin JavaScript. In that case this assignment leavespresenterFailureequal to the “no failure” sentinel, so the close handler can resolve the dismissed native response instead of propagating the presenter failure. Track failure with a separate boolean or normalize every caught value to anError.
sdk/node/src/telemetry.ts:353 - This convenience getter discards
queryTelemetryConsent().error, so a missing/mismatched executable is indistinguishable from a genuine undecided user. Consent reads are required to surface failures through the binding's documented exception type; only prompt/policy queries should silently fail closed. Check the query result and throw anMxcErrorwhenerroris present.
sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:65 - Returning
Undeterminedfor native-load failures makes a broken or outdated native installation indistinguishable from a user who has not decided. Consent reads must raise the documentedMxcExceptionon infrastructure failures; reserve silent fail-closed behavior forNeedsConsentPromptandGetPolicy. Wrap this failure asMxcExceptioninstead of returning a consent state.
catch (Exception ex) when (IsNativeLoadFailure(ex))
{
ReportFailClosed("GetConsent", "Undetermined", ex);
return TelemetryConsentState.Undetermined;
}
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
c8415af to
2f8f372CompareThere was a problem hiding this comment.
Pull request overview
Copilot reviewed 54 out of 58 changed files in this pull request and generated 1 comment.
Suppressed comments (6)
src/core/wxc_common/src/telemetry/events.rs:119
- This always derives the error event's
sandbox_kindfromctx.backend, so callers that resolved a broad SDK request such asprocessorvmemit paired records with different attribution:MXC.Executionkeeps the requested kind, whileMXC.Errorreports the concrete backend. Pass the request-scoped sandbox kind through the error path as well so both events remain joinable and semantically consistent.
sdk/dotnet/Microsoft.Mxc.Sdk/SandboxPolicy.cs:41 - The FFI contract identifies nested
telemetry.enabledas canonical andtelemetryEnabledonly as a legacy compatibility alias (src/ffi/mxc_ffi/src/lib.rs:31-35). Serializing the newly shipped .NET surface through that alias makes new clients depend on the compatibility path; retain the convenience property but project it onto the canonical nested section.
[JsonPropertyName("telemetryEnabled")]
public bool? TelemetryEnabled { get; set; }
sdk/node/src/telemetry.ts:376
- This catch handles every transport/parser failure, including a missing executable, timeout, and malformed child output, but labels all of them as
store-unreadable. That reason specifically describes consent-store state and is false for these failures; omit it here and let the diagnosticerrordistinguish transport failures.
src/mxc_telemetry/src/lib.rs:358 - This source-text assertion is self-fulfilling:
provider_sourceincludes this test, so the searchedstr8("mxc.sandbox_kind", sandbox_kind)literal still appears later in the file even if the productionMXC.Errorfield is removed. Bound the extracted event body before the test module or assert captured/decoded event fields instead.
.github/copilot-instructions.md:228 - This changes the reference to
docs/telemetry/telemetry-policy.md, but that file does not exist; the checked-in policy document isdocs/telemetry/telemetry-administrative-policy.md. Keep the existing filename unless this PR also renames the document and updates all remaining SDK links.
- `docs/telemetry/telemetry.md` — telemetry overview; `docs/telemetry/telemetry-consent-design.md` (Windows-only consent design and per-SDK surface) and `docs/telemetry/telemetry-policy.md` (the MDM / Group Policy ceiling)
.github/copilot-instructions.md:333
- The referenced
docs/telemetry/telemetry-policy.mdis absent; the repository currently containstelemetry-administrative-policy.md, which the Node.js and .NET README links also use. Point this convention at the existing document or include a coordinated rename.
- **Telemetry consent or policy changes** → update `docs/telemetry/telemetry-consent-design.md` and/or `docs/telemetry/telemetry-policy.md`, and keep `scripts/check-telemetry-policy-parity.js` green across all three bindings
Uh oh!
There was an error while loading. Please reload this page.
RamonArjona4
commented
Sep 3, 2026
Addressed the three suppressed SDK findings in 58f02ab: executable discovery now invalidates and revalidates its cache when |
There was a problem hiding this comment.
🔵 Needs a closer look
Two moderate issues remain involving hidden Node.js diagnostics and silently discarded .NET lifecycle options.
Review details
Suppressed comments (6)
Previously missed (2) — in code that hasn't changed since the last review.
sdk/dotnet/Microsoft.Mxc.Sdk/StateAwareTypes.cs:190
- This public alias is accepted by
StopSandboxandDeprovisionSandboxbecause it derives fromStateAwarePhaseOptions, but it also exposesWorkingDirectory,Environment, andTimeoutMsthroughStateAwareExecOptions. If a caller sets those properties for stop/deprovision, the envelope builders silently discard them. Please use separate exec and non-exec option types (or stop advertising this alias for all three phases) so supplied options are either honored or rejected.
sdk/node/src/telemetry.ts:141 - This callback drops
stderron successful exits. The native consent/status path deliberately writes diagnostics there when the consent store or administrative policy cannot be read, while still returning exit code 0 with fail-closed JSON. As a result,queryTelemetryConsentAsync()can returnundetermined/blockedwith no visible diagnostic. Capture and safely report/deduplicate non-empty stderr (or translate the response reason into the query diagnostic).
This issue also appears on line 369 of the same file.
sdk/dotnet/Microsoft.Mxc.Sdk/ErrorCode.cs:68
- Status 103 represents every native
ConsentError::Persist, not only an unavailable or unwritable%LOCALAPPDATA%. For example, the native consent flow also returns it when consent changes concurrently while a presenter is open. This description can misdirect consumers diagnosing a valid concurrency conflict; keep the enum documentation generic.
/// <summary>
/// Telemetry consent could not be persisted because %LOCALAPPDATA% is
/// unavailable or unwritable (FFI-local). MXC only
/// collects telemetry on Windows and only with persisted, explicit consent;
/// see docs/telemetry/telemetry-consent-design.md.
/// </summary>
ConsentWriteFailed = 103,
sdk/node/README.md:554
- This overstates what
errordistinguishes. Native store failures such asstore-unreadableandstore-malformedreturn a successful status response witheffectiveState: 'undetermined';consentQueryFromResponsediscardsreason, soerrorremains undefined just as it does for a fresh undecided store. Document thaterroronly covers command/protocol failures, or expose the native reason.
`queryTelemetryConsentAsync()` fails closed to `'undetermined'` rather than
`'granted'`. Its diagnostic `error` field distinguishes that result from a
genuine undecided state:
sdk/node/src/state-aware-types.ts:38
- The omitted-version behavior is not always the backend default:
buildStateAwareEnvelopeselects0.9.0-alphawhenever telemetry is present, instead of the IsolationSession/Windows Sandbox0.6.0-alphaor WSLC0.8.0-alphadefault. Describe this telemetry-specific selection so callers know which schema is emitted.
/** Schema version. When omitted, the SDK selects the backend default. */
version?: string;
sdk/node/src/telemetry.ts:374
- The interactive request path likewise accumulates native stderr but only includes it when the child fails. A policy/store read can legitimately produce a successful terminal response plus a native fail-closed diagnostic, which is silently discarded here. Report/deduplicate accumulated stderr before resolving successful responses.
if (code !== 0 || finalResponse === undefined) {
fail(new Error(`telemetry consent process failed (${code ?? 'no exit code'}): ${stderr.trim()}`));
return;
}
settled = true;
resolve(finalResponse);
- Files reviewed: 35/35 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Separate exec and non-exec lifecycle options, preserve successful native consent diagnostics, and correct the public telemetry documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
RamonArjona4
commented
Sep 3, 2026
Addressed the six suppressed SDK findings in
Focused regression coverage was added for the type boundary and both diagnostic paths. |
There was a problem hiding this comment.
🔵 Needs a closer look
Two moderate correctness issues must be resolved before approval.
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:194
GetConsent()is a read-only consent query, but these catch blocks now rethrow native status failures and other read errors. That regresses the previous fail-closed behavior and is inconsistent with the other read-only APIs, which resolve failures toUndetermined/Blocked; for example, an FFIPanicstatus now escapes asMxcException. Report every failure and returnTelemetryConsentState.Undetermined, then update the method's XML contract accordingly.
sdk/node/src/platform.ts:749- When
MXC_BIN_DIRis set but its binary is temporarily absent, the fallback path found below is cached with that samebinDir. If the override binary is later staged without changing the environment variable, this fast path keeps returning the fallback and never rechecks the higher-priority override. Only reuse a cached entry under an active override when it is the override path itself (or probe the override before consulting the fallback cache).
- Files reviewed: 34/34 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
RamonArjona4
commented
Sep 3, 2026
Addressed the two suppressed moderate correctness findings in
Validation completed before push: Node build and 376 tests passed (19 expected skips); .NET 228 tests passed (24 expected host-dependent skips). |
There was a problem hiding this comment.
🔵 Needs a closer look
The public StartSandboxOptions alias conflicts with the documented release contract.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
sdk/dotnet/Microsoft.Mxc.Sdk/StateAwareTypes.cs:180
- This reintroduces
StartSandboxOptionsas a public API even thoughsdk/dotnet/CHANGELOG.md:23-24says it is removed and replaced byStateAwarePhaseOptions. Remove the alias (and useStateAwarePhaseOptionsin the new tests), or update the release contract if retaining it is intentional; otherwise consumers receive contradictory API guidance.
- Files reviewed: 34/34 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
RamonArjona4
commented
Sep 3, 2026
Addressed the remaining suppressed Copilot finding in Removed the public Validation completed before push: all 228 .NET tests completed with 204 passed and 24 expected host-dependent skips; the C# public API parity gate passed. |
There was a problem hiding this comment.
🟡 Changes recommended
A critical .NET telemetry test issue causes the Windows Release test suite to fail.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 34/34 changed files
- Comments generated: 1
- Review effort level: Balanced
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
There was a problem hiding this comment.
🔵 Needs a closer look
Its broad cross-language and native-boundary changes warrant final human review.
Review details
Suppressed comments (1)
docs/telemetry/telemetry.md:121
- This overstates the field's precision for ProcessContainer runs. The emitter still receives
request.containment(src/core/wxc/src/main.rs:1331-1335), andContainmentBackend::ProcessContainerrepresents the runtime-selected BaseContainer/AppContainer family rather than the selected tier (src/core/wxc_common/src/models.rs:14-20). Such events therefore reportprocesscontainer, not the concrete host-selected implementation; please document that distinction instead of promising a concrete backend.
| `mxc.backend` | string | Concrete containment backend selected on the host |
- Files reviewed: 35/35 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
RamonArjona4
commented
Sep 3, 2026
Addressed the suppressed documentation finding in The |
There was a problem hiding this comment.
🔵 Needs a closer look
The .NET consent documentation must distinguish persisted consent from effective consent.
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:166
mxc_telemetry_get_consentreturns the validated effective state (get_status().effective_state), not the persisted state. A stale stored grant therefore returnsUndetermined, so this public method documentation should identify the value as effective consent rather than directing callers to interpret it as the stored choice.
sdk/dotnet/Microsoft.Mxc.Sdk/TelemetryConsentState.cs:13- This enum is also used for
EffectiveState, so describing every value as the persisted decision is misleading. In particular, a persisted grant can coexist with an effectiveUndeterminedstate after prompt-version validation; hosts must not treatStoredState == Grantedas authorization. Document the dual stored/effective use and reserve the collection statement for an effective grant.
- Files reviewed: 35/35 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
RamonArjona4
commented
Sep 4, 2026
Addressed the suppressed consent-documentation finding in
The .NET SDK builds with zero warnings and errors. |
There was a problem hiding this comment.
🟡 Changes recommended
The critical .NET inheritance change breaks existing state-aware API callers.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 35/35 changed files
- Comments generated: 1
- Review effort level: Balanced
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
There was a problem hiding this comment.
🟡 Changes recommended
A critical test compilation failure and a moderate parity-gate contract mismatch remain unresolved.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 36/36 changed files
- Comments generated: 2
- Review effort level: Balanced
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Carry the current PR #821 stack forward while retaining the language SDK telemetry documentation and published review history. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
There was a problem hiding this comment.
🔵 Needs a closer look
The parity gate must validate .NET against the Rust SDK/C ABI contract rather than the differing CLI protocol.
Review details
Suppressed comments (1)
scripts/check-telemetry-policy-parity.js:15
- This gate validates the .NET binding against the executor CLI protocol, but .NET consumes the Rust SDK/C ABI contract. Those producers already differ: the CLI adds
presentationUnavailableand two CLI-only reasons, whilemxc-sdk/src/telemetry.rsdoes not expose them. As written, CI can pass even when the actual C ABI and C# binding drift. Derive the Node expectations fromconsent_protocol.rsand the C# expectations from the Rust SDK/C ABI producer separately.
const policy = readFileSync(
join(root, "src", "core", "wxc_common", "src", "telemetry", "policy.rs"),
"utf8"
- Files reviewed: 36/36 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Carry the post-#820 merge resolution forward without rewriting the published language SDK history. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Merge the updated Rust SDK and FFI foundation, centralize policy parsing, preserve async consent cancellation semantics, and add bounded redacted .NET fail-closed diagnostics with regression coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
There was a problem hiding this comment.
🟡 Changes recommended
Node.js consent-response validation must require reason so malformed responses fail closed.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 36/36 changed files
- Comments generated: 1
- Review effort level: Balanced
| || ( | ||
| value.reason !== undefined | ||
| && value.reason !== null | ||
| && !isStatusReason(value.reason) | ||
| ) |
.github/copilot-instructions.md.Summary
Adds the Node.js and .NET telemetry surfaces over the reviewed native contract: presenter-driven consent, policy-aware status, withdrawal, per-run options for one-shot and state-aware execution, generated wire types, parity checks, tests, and final SDK/product documentation.
This is PR 5 of 5 and depends on the Rust SDK/C ABI in PR 4.
Stack
Review only this PR's diff; prerequisite behavior is in the PR above.