Skip to content

Proposal: generate sync attestation methods from the async ones with a source generator #4799

Description

@virzak

The enclave providers keep hand-written sync and async twins of the same methods, and they have drifted. In HostGuardianServiceEnclaveProvider, MakeRequest deserializes through the source-generated JSON context while MakeRequestAsync uses reflection, which produces two trim-analyzer errors (#1947).

Proposal: write the async method only and generate the sync one with Zomp.SyncMethodGenerator, a build-time source generator (PrivateAssets="all", no runtime or package dependency). Full disclosure: I maintain it.

A trial on the VBS/HGS provider converts MakeRequest, GetSigningCertificate and VerifyAttestationInfo: -106/+55 lines, the two trim errors gone, unit tests passing on net462 and net8.0. Branch: virzak/SqlClient@main...dev/automation/sync-method-generator

The blocker is the governed feed: Zomp.SyncMethodGenerator isn't on it, so the trial temporarily maps it to nuget.org. Would you approve adding it? If so, I'll open a PR without that commit.

Activity

  1. github-actions commented on Oct 7, 2026

    @github-actions

    🔍 Triage Summary

    Check Result
    Issue type Feature
    Environment All required environment details provided for investigation (not a bug report; environment validation not applicable)
    Area Area\Engineering (build tooling / new build-time dependency; touches enclave providers)
    Duplicates None found (#1947 is referenced for the trim-analyzer errors)
    Regression Not indicated

    Analysis

    The proposal adds a third-party build-time source generator (Zomp.SyncMethodGenerator) to derive sync enclave-provider methods from their async twins. This would fix the drift between MakeRequest and MakeRequestAsync in HostGuardianServiceEnclaveProvider (source-generated vs reflection JSON), which causes the trim errors in #1947. The main concerns are supply-chain approval for a new package on the governed feed, maintainer-owned dependency disclosure, and behavioral risk from sync-over-async generation. Severity is P3 (maintainability / trimming).

    Next Steps

    • Maintainers need to decide whether adding Zomp.SyncMethodGenerator to the governed NuGet feed is acceptable (security/compliance review, license, and Directory.Packages.props / 3rd-party-package-versions policy).
    • Author: please don't open a PR until that is approved. Once it is, open it without the temporary nuget.org mapping commit and with unit tests covering both the sync and async paths, on net462 and net8.0 and net9.0.
    • Consider whether the narrower fix (making MakeRequestAsync use the source-generated JSON context) resolves NativeAOT support: get to zero warnings #1947 without a new dependency.

    Note: This triage summary is auto-generated by an AI agent. The analysis and suggestions above have not been verified by a human maintainer. Please treat as preliminary guidance only.

    Generated by SqlClient Issue Auto-Triage for #4799 · copilot · auto · 23.8 AIC · ⌖ 11.7 AIC · ⊞ 13.4K · ◷

  2. virzak commented on Oct 7, 2026

    @virzak
    ContributorAuthor

    The generated code is synchronous, not sync-over-async: Task.Delay becomes Thread.Sleep, DeserializeAsync becomes Deserialize, and so on. The one blocking call in the trial is HttpClient.GetStreamAsync, which the hand-written MakeRequest already blocks on because HttpClient has no synchronous GetStream.

    Agreed that using the source-generated context in MakeRequestAsync alone fixes the trim errors. The broader case is drift: the async VBS path also skips the enclave key binding check the sync path does (#4798).

  3. virzak commented on Oct 7, 2026

    @virzak
    ContributorAuthor

    For comparison, the dependency-free alternative is the bool async pattern the BCL networking stack uses: one method with if (async) await x.ReadAsync(...) else x.Read(...) at each I/O call. It needs no package approval and prevents drift the same way. The generator keeps the async method free of those branches, which matters more as more pairs are converted. For the three methods here, either would work.

    I've also updated the trial so the sync path uses HttpClient.Send on .NET, which removes its sync-over-async call there; .NET Framework still blocks, as today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions