Skip to content

Cosmos: native driver distribution design + ADRs - #4651

Open
ananth7592 wants to merge 9 commits into
mainfrom
users/amudumba/cosmos-native-driver-distribution-adrs
Open

Cosmos: native driver distribution design + ADRs#4651
ananth7592 wants to merge 9 commits into
mainfrom
users/amudumba/cosmos-native-driver-distribution-adrs

Conversation

@ananth7592

Copy link
Copy Markdown
Member

What this is

A design doc + ADRs (documentation only — no code or pipeline changes) proposing how the Rust-built native Cosmos driver (azure_data_cosmos_driver_nativeazurecosmosdriver.{dll,so,dylib} plus the cbindgen C header) is distributed to the language SDKs (.NET first, Go near-term, Java later).

The design doc carries the discussion — context, alternatives, and the "why". The ADRs record each decision in short, numbered, immutable form (Context · Decision · Consequences · Alternatives · Status). If the two ever disagree, the ADR wins.

These are proposed for design review — nothing here changes build or release behavior yet.

TL;DR of the design

  • Separate provenance from distribution — the core principle the rest follows from.
  • Build-once provenance (ADR 0001): one Rust build per release produces and signs all platform binaries (cdylib + staticlib + C header + ABI version) as an internal-only hand-off artifact. It is never consumer-facing and never language-shaped.
  • Per-language distribution (ADR 0002): each language consumes the driver as a normal dependency on its own existing feed — no neutral cross-language bundle, no new consumer feed. A Go user never downloads a DLL or JAR.
    • .NET (ADR 0003): per-RID NuGet NativeAssets packages + a thin meta-package (the SkiaSharp / SqlClient.SNI model) — download only your RID.
    • Go (ADR 0004): cgo against a prebuilt header + lib delivered through the azure-sdk-for-go feed; no NuGet, no runtime resolver.
    • Java: JAR on Maven, later — deliberately unspecified, but the hand-off stays general enough to repackage.
  • ABI handshake (ADR 0005): the lib exports cosmos_abi_version(); every host checks it before first use and fails fast on mismatch instead of corrupting memory.
  • Bindings own marshalling (ADR 0006): the ABI stays bytes-in / bytes-out; each language owns serialization and buffer copy-out.
  • Native is opt-in (ADR 0007): opt-in per SDK until GA on all platforms, then default-with-managed-fallback. Pure-managed / pure-Go consumers are never force-migrated by a version bump.
  • Bounded platform matrix (ADR 0008) with actionable errors on unsupported targets, and one build → sign once → fan-out (ADR 0009) where per-language jobs consume the signed hand-off and never rebuild.
Rust build (ONE run, all platforms) → sign binaries
        │
        ▼
INTERNAL HAND-OFF ARTIFACT  (provenance + SBOM anchor; not consumer-facing)   ← ADR 0001
        │
   ┌────┼─────────────┐
 .NET   Go            Java        ← each job pulls the SAME signed binaries (never rebuilds)
 NuGet  cgo header+lib JAR
 → nuget.org → azure-sdk-for-go → Maven                                        ← ADR 0002

Contents

  • docs/native-distribution/distribution-design.md — the discussion doc: purpose, goals/constraints, the model, per-consumer link model, platform matrix, rollout phases, and open questions.
  • docs/native-distribution/adr/0000-index.md and 00010009 — one decision per record.

Status & open questions

Status is provisional ("proposed for review"). The main open questions the doc captures for reviewers: the internal hand-off shape (Universal Package vs pipeline artifact), packaging-pipeline ownership and its security boundary, the Go delivery model, version-mapping across the three feeds, and SBOM / component-governance ownership for the Rust crate graph.

ananth7592 and others added 3 commits June 19, 2026 20:18
Add a design doc and a numbered ADR set describing how the native Cosmos
driver (azurecosmosdriver cdylib/staticlib + C header) is distributed to
language SDKs.

Core model: separate provenance from distribution. One Rust build produces
all signed platform binaries as an internal-only hand-off artifact (ADR
0001/0008); distribution is per-language native packages on each language's
existing internal + external feed (ADR 0009) -- NuGet NativeAssets + meta
for .NET (0002), cgo prebuilt header+lib via the Go feed (0003), JAR for
Java (future). ABI handshake (0004), bytes-in/bytes-out copy-out (0005),
opt-in transport (0006), and platform matrix (0007) round out the set.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Since these ADRs are unpublished (no PR, no accepted record),
the immutability/supersession discipline does not yet apply, so
the pre-publication editing history was scrubbed for a clean first
cut:

- Drop ghost "supersedes the earlier canonical-bundle" scaffolding
  from 0001 and 0002 and the design doc; no reviewer ever saw that
  draft, so referencing it is noise.
- Reorder per-language-feed distribution from 0009 to 0002 so the
  keystone distribution decision sits next to the build-once
  provenance decision (0001); renumber the former 0002-0008 to
  0003-0009. Provenance (0001) and distribution (0002) stay as two
  decoupled records so either can be superseded independently later.
- Re-point all in-text and link cross-references to the new numbers;
  reorder the index and design-doc decision tables to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The generic "distribution" name was ambiguous; "native-distribution"
makes clear these docs cover distributing the native (FFI) driver
artifact to the language SDKs. Pure directory rename — all internal
links are relative and unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 23, 2026 22:06
@ananth7592
ananth7592 requested a review from a team as a code owner June 23, 2026 22:06
@github-actions github-actions Bot added the Cosmos The azure_cosmos crate label Jun 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This documentation-only PR adds a design document plus nine Architecture Decision Records (ADRs) describing how the future Rust-built native Cosmos driver (azure_data_cosmos_driver_nativeazurecosmosdriver.{dll,so,dylib} + cbindgen C header) will be distributed to the .NET, Go, and (later) Java SDKs. The core idea is to separate provenance (one signed build → internal hand-off artifact) from distribution (per-language packages on each language's existing feed). No code, build, or pipeline behavior changes; everything is marked "proposed for review."

Changes:

  • Adds distribution-design.md — the discussion doc (purpose, goals, model, per-consumer link model, platform matrix, rollout, open questions).
  • Adds ADRs 00000009 capturing each decision (build-once hand-off, per-language feeds, .NET NuGet NativeAssets, Go cgo, ABI handshake, marshalling ownership, opt-in native, platform matrix, build/sign pipeline).
  • References an existing/planned NATIVE_WRAPPER_SPEC.md as the owner of the C-ABI surface.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/native-distribution/distribution-design.md Main design discussion; links to ADRs and to a non-existent NATIVE_WRAPPER_SPEC.md; introduces many domain terms not in the cSpell dictionaries.
docs/native-distribution/adr/0000-index.md ADR index/template overview; links resolve correctly.
docs/native-distribution/adr/0001-build-once-internal-handoff.md Decision: single build → internal-only hand-off artifact.
docs/native-distribution/adr/0002-per-language-feed-distribution.md Decision: distribute via each language's existing feeds.
docs/native-distribution/adr/0003-dotnet-nuget-nativeassets.md Decision: .NET per-RID NuGet NativeAssets + meta-package.
docs/native-distribution/adr/0004-go-cgo-prebuilt.md Decision: Go consumes prebuilt header+lib via cgo.
docs/native-distribution/adr/0005-abi-version-handshake.md Decision: lib exports cosmos_abi_version(); hosts check before use.
docs/native-distribution/adr/0006-binding-owns-marshalling.md Decision: bindings own marshalling/copy-out; links to non-existent NATIVE_WRAPPER_SPEC.md.
docs/native-distribution/adr/0007-native-is-opt-in.md Decision: native is opt-in until GA, then default-with-fallback.
docs/native-distribution/adr/0008-platform-matrix.md Decision: bounded platform matrix; clear error on unsupported targets.
docs/native-distribution/adr/0009-build-and-signing-pipeline.md Decision: one build, sign once, fan-out; jobs never rebuild.

The two notable issues are CI-blocking: a broken relative link to NATIVE_WRAPPER_SPEC.md (referenced from the design doc and ADR 0006, but the file doesn't exist) which verify-links will fail, and numerous new domain terms missing from the cSpell dictionaries (with no per-file <!-- cspell:ignore --> comment that sibling specs use) which the ContinueOnError:false spell check will fail.

ananth7592 added a commit that referenced this pull request Jun 23, 2026
Resolve the 9 review findings on PR #4651:
- #1 CI: drop broken NATIVE_WRAPPER_SPEC.md links (lives in #4461); add
  cSpell terms (cbindgen, Authenticode, ESRP, manylinux, etc.)
- #2 ADR 0001/0009: require RID-keyed hand-off + both .so/.a + C-only header
- #3 ADR 0009: enforce build-once via checksum+signature verification
- #4 ADR 0005: u32 is a monotonic ABI revision; add MaxSupported (reject too-new)
- #5 promote Q5 to new ADR 0010 (single version fan-out)
- #6 ADR 0000 template: Status under the title
- #7 reciprocal Pairs-with note in ADR 0001
- #8 ADR 0008: name glibc floor 2.17 (manylinux2014)
- #9 ADR 0007: silent-fallback for benign causes vs fail-loud for integrity/ABI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rust/Native as opt-in is a no-go in my mind.

@github-project-automation github-project-automation Bot moved this from Todo to Changes Requested in CosmosDB Rust SDK and Driver Jun 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Design review — native driver distribution

Read the whole set (design doc + ADRs 0000–0010). Overall this is a strong, well-structured design and the ADR hygiene is clean. I spot-checked the external references and they hold up: the SkiaSharp / Microsoft.Data.SqlClient.SNI per-RID runtimes/<rid>/native/ + runtime.json meta-package pattern, manylinux2014 ⇔ glibc 2.17, the cgo CFLAGS -I / LDFLAGS -L -l mechanics, cbindgen C-only header, and crate-type = ["cdylib","staticlib"] are all described correctly.

A few things I'd want resolved before these move from "proposed" to "accepted". Inline comments cover the independent ones; the three below overlap with Fabian's open CHANGES_REQUESTED, so I'm reinforcing rather than restating.

Blocking

  • Opt-in / "pure-managed users" premise (ADR 0007 + G4, ADR 0003). If the next .NET major requires the native package (as Fabian notes), then "never force-migrated" / "opt-in" mis-frames the rollout, and ADR 0003's rejected-alternative argument ("bloats the flagship for pure-managed users") rests on a user class that won't exist. Independently: a NuGet <PackageReference> is not "opt-in" — it always restores transitively. Please state the actual mechanism (flagship has no dep + consumer adds the meta-package, OR hard dep that's inert behind a client flag) and reconcile 0003/0007 with "mandatory at next major."
  • Linux has no signature for the integrity gate (ADR 0009 / 0007). See inline.
  • ABI range vs single-version lockstep (ADR 0005 [Min,Max] vs ADR 0010 "never forked"). These two read as contradictory; if fan-out is always one coordinated version, the acceptance range only grows the test matrix. Collapse to a single targeted revision (Min==Max) or explain how a range coexists with 0010.

Important — see inline on ADR 0004 (public-Go delivery + static link flags), ADR 0010 (atomic fan-out on immutable feeds), and distribution-design.md §8 (now stale vs ADR 0009).

Also: design-doc §10 ("fallback on load failure") contradicts ADR 0007's fail-loud-on-integrity rule — §10 should mirror the benign-vs-integrity split. And the heavy §5–§11 restatement of the ADRs is what's producing these drifts (the §8 one is a concrete example); consider trimming the design body to discussion/alternatives and linking out for decisions.

Nits: status convention split (0010 "Proposed" while dependents are "Accepted"); the "Pairs with" note is on 0001/0002 only — either add it to the template or to the other coupled pairs; dangling NATIVE_WRAPPER_SPEC.md refs (add "forthcoming, #4461") and a pointer to the cosmos_free-style dealloc export behind ADR 0006's "frees the native buffer"; "download only your RID" is unconditional-sounding but differs for framework-dependent builds.

Nothing here is a showstopper for the idea — it's a genuinely good design. These are about closing the seams before downstream teams build against it.

## Decision
- Go consumes the prebuilt **`include/` header and `lib/` library via cgo** (`#cgo CFLAGS -I…` to parse the header into `C.*` symbols; `#cgo LDFLAGS -L… -lazurecosmosdriver` to link), **not NuGet**.
- Prefer the **static `.a`** for a self-contained Go binary; dynamic linking is supported as an option.
- The header + lib are delivered through the **azure-sdk-for-go feed** — an Azure Artifacts Universal Package fetched at build, or a vendored "binaries" Go module with per-OS build tags (delivery shape is open Q3). Either way it derives from the ADR 0001 hand-off artifact.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both delivery options here are problematic for public Go consumers. Azure Artifacts Universal Packages are internal-only, so an external go get user can't fetch them — that option only really covers the internal/dogfood phases. And a vendored "binaries" Go module means committing ~7 platforms of multi-MB native libs into a module the proxy pulls wholesale on every go get; that's exactly why the canonical cgo libraries (e.g. go-sqlite3) ship C source rather than prebuilt binaries. Related: Go has no package "feed" — modules resolve from VCS via the module proxy, so describing azure-sdk-for-go as a "feed" (also ADR 0002 / §6.2) is misleading. Can we add a concrete public-Go answer (GitHub Releases + a small fetch shim, or build-tag selection of a per-RID .a)? This feels bigger than Q3's internal-only "Universal Package vs vendored module" framing.


## Consequences
- Go reuses the exact same signed binaries as .NET — no Go-specific build of the driver.
- cgo + static lib means `CGO_ENABLED=1` and a C toolchain on the Go build host; cross-compilation needs a cross C toolchain.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One -lazurecosmosdriver won't be enough to statically link a Rust staticlib through cgo. A Rust staticlib isn't self-contained at link time — it pulls in the Rust std/panic/unwind runtime plus system libs (typically -lpthread -ldl -lm, often -lgcc_s/-lunwind), and static-cgo on musl is notoriously fiddly. Since linux-musl-x64 is in the GA matrix and this ADR prefers the static .a by default, worth noting the per-OS LDFLAGS must include the transitive system libs and flagging musl-static-cgo as a known-hard case (it bears on whether "static by default" is realistic on every matrix row — Q4).

Comment on lines +9 to +10
- Ship per-RID **`Microsoft.Azure.Cosmos.NativeAssets.<rid>`** packages, each carrying one platform's dynamic lib under `runtimes/<rid>/native/`.
- Front them with a thin **meta-package** whose `runtime.json` resolves the consumer's RID to the right per-RID package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should run this by the .NET/NuGet teams and see if there are any unexpected consequences to this choice.

@ananth7592 ananth7592 Jul 15, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. The ADR stays at the packaging-shape level, but we should validate the NuGet consequences with the .NET/NuGet folks before treating the layout as final.

@heaths Heath Stewart (heaths) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep changes to sdk/cosmos and you won't need my sign-off.

Comment thread .vscode/cspell.json
Resolve the 9 review findings on PR #4651:
- #1 CI: drop broken NATIVE_WRAPPER_SPEC.md links (lives in #4461); add
  cSpell terms (cbindgen, Authenticode, ESRP, manylinux, etc.)
- #2 ADR 0001/0009: require RID-keyed hand-off + both .so/.a + C-only header
- #3 ADR 0009: enforce build-once via checksum+signature verification
- #4 ADR 0005: u32 is a monotonic ABI revision; add MaxSupported (reject too-new)
- #5 promote Q5 to new ADR 0010 (single version fan-out)
- #6 ADR 0000 template: Status under the title
- #7 reciprocal Pairs-with note in ADR 0001
- #8 ADR 0008: name glibc floor 2.17 (manylinux2014)
- #9 ADR 0007: silent-fallback for benign causes vs fail-loud for integrity/ABI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ananth7592
ananth7592 force-pushed the users/amudumba/cosmos-native-driver-distribution-adrs branch from a6ee645 to 7e72641 Compare June 30, 2026 19:09
Copilot AI and others added 3 commits July 9, 2026 13:03
…ry, discuss pure-Go-port alternative

Go distribution (ADR 0004) is marked WIP on its delivery shape while the core
model is stated firmly: Go links a PACKAGED native binary via cgo (CGO_ENABLED=1)
through the C.* FFI stubs from the cbindgen header. Explicitly rules out a pure-Go
shim that downloads the native library at build/run time — the binary is packaged
and linked, never fetched by a stub.

Also expands the pure-Go-reimplementation alternative with the findings from the
time-boxed spike (a working CGO=0, zero-dependency vertical slice validated
behavior-for-behavior against the real Rust driver via a differential harness),
and records why it stays rejected for distribution (abandons build-once single
provenance). Adds a narrative 'Alternative considered — a pure-Go port' section
and tightens the Go-delivery open question to encode the no-shim constraint.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Align the non-Go native-distribution ADRs with the current
review direction so the docs answer the outstanding comments
without changing the still-open Go delivery decision.

Update the ADR index and design summary to match the accepted
cutover and versioning model, clarify that build-once means one
coordinated provenance event even if multiple platform jobs feed
it, make UTF-8 explicit at the binding boundary, add the win-x86
platform case, and describe Linux authenticity plus roll-forward
handling for public fan-out failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a focused ADR for the Go v2 implementation direction. The decision record keeps the SDK-level FFI choice separate from the packaging mechanics already covered by the native distribution ADRs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f7d60272-a96c-48e4-9a85-6e918db6ac26
Copilot AI review requested due to automatic review settings July 17, 2026 20:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.


## 1. Purpose

The crate `azure_data_cosmos_driver_native` compiles to a native library — `azurecosmosdriver.{dll,so,dylib}` (and a static `.a`) plus a cbindgen-generated C header — wrapping the schema-agnostic driver core (see `NATIVE_WRAPPER_SPEC.md`, introduced in #4461). It is the single reuse point for **every non-Rust language SDK**. This doc defines how that compiled artifact reaches those SDKs:
- Go consumes the prebuilt **`include/` header and `lib/` library via cgo** with **`CGO_ENABLED=1`**: `#cgo CFLAGS -I…` parses the header into the `C.*` **FFI stubs**, and `#cgo LDFLAGS -L… -lazurecosmosdriver` links the library. **Not** NuGet, and **not** a pure-Go build.
- The native library is **packaged inside the delivered artifact** and linked at `go build`. It is **not** a pure-Go shim that downloads the library at build/run time — customers link a real binary through the FFI stubs; they are not handed a downloader stub.
- Prefer the **static `.a`** for a self-contained Go binary; dynamic linking is supported as an option.
- The header + lib are delivered through the **azure-sdk-for-go feed** — an Azure Artifacts Universal Package fetched at build, or a vendored "binaries" Go module with per-OS build tags (delivery *shape* is open Q3; in every shape the binary is **packaged**, not fetched by a shim). Either way it derives from the ADR 0001 hand-off artifact.
Comment on lines +9 to +11
- Native transport is introduced in a **new SDK major version**. Adopting that major **is** adopting native: there is no per-client / per-call opt-in switch, and no managed transport kept in parallel *inside the same major*.
- Existing majors keep their current managed / pure transport unchanged. No consumer is **force-migrated by a routine (minor/patch) bump** — they move to native deliberately, by choosing to take the new major.
- The supported surface is bounded by the platform matrix (ADR 0008). On an unsupported platform/RID the native major fails with a **clear, actionable error**; it does **not** silently fall back to a managed path. If a pure-managed / pure-Go audience must be served long-term, that is a **separate, explicitly limited package**, not a hidden fallback inside the flagship.
## Decision
- A single coordinated release pipeline next to the Rust build produces the per-platform binaries (ADR 0001), potentially across multiple platform-specific jobs, then joins them into one hand-off artifact. It **signs each binary once** where platform-native signing exists (Authenticode on Windows; codesign + notarization on macOS), records checksums for every artifact, and publishes the internal hand-off artifact.
- Per-language publish jobs **consume the already-signed hand-off** and emit NuGet / Go-consumable / JAR packages; they **never rebuild or re-sign the native binary** (they may sign their own package wrapper, e.g. the `.nupkg`/`.jar`, in that language's existing ESRP flow).
- Build-once is **enforced by verification, not just discipline**: before repackaging, every per-language publish job **verifies the hand-off's checksums and platform authenticity material** against the values published by the build job, and **fails the publish** on any mismatch — so a job physically cannot ship a rebuilt, altered, or unsigned native binary. On Windows/macOS this means verifying the binary signatures; on Linux, where the binary itself has no equivalent platform code-signing convention, this means verifying the checksum plus the build's provenance attestation / signed manifest for that RID.
Comment thread .vscode/cspell.json
"amqp",
"asyncoperation",
"authenticode",
"azcosmos",
Copilot AI review requested due to automatic review settings July 17, 2026 20:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 19 comments.


## Decision
- Ship per-RID **`Microsoft.Azure.Cosmos.NativeAssets.<rid>`** packages, each carrying one platform's dynamic lib under `runtimes/<rid>/native/`.
- Front them with a thin **meta-package** whose `runtime.json` resolves the consumer's RID to the right per-RID package.
| [0004](adr/0004-go-cgo-prebuilt.md) | Go consumes via **cgo against a prebuilt header + lib** delivered through the azure-sdk-for-go feed (Universal Package / vendored module). | Go has no NuGet; cgo links a C header + lib at build time. |
| [0005](adr/0005-abi-version-handshake.md) | The native lib exports **`cosmos_abi_version()`**; every host checks it before first use. | Independent cadences drift; fail fast, not corrupt. |
| [0006](adr/0006-binding-owns-marshalling.md) | Each binding **owns its marshalling and buffer copy-out**; the ABI stays bytes-in/bytes-out. | Keeps the ABI schema-agnostic. |
| [0007](adr/0007-native-is-opt-in.md) | Native transport ships in a **new SDK major**; no parallel managed transport, no silent fallback. | A major-version cutover, not a per-call opt-in. |
## Decision
- A given native release (one build + signing, ADR 0001) is **fanned out to all language feeds simultaneously** from that single hand-off — .NET, Go, and (later) Java publish the *same* native version together.
- Each language SDK **pins the exact native version** from that fan-out and may cut its *own* managed/SDK releases independently between native releases; what it must not do is float onto a *different* native build.
- The native SemVer is the **one source of truth** for "which driver"; per-language package versions map to it but never fork it. Hosts enforce this at load by accepting only that exact ABI revision (ADR 0005) — there is no compatibility *range*, which keeps the test matrix a single point.
- Go consumes the prebuilt **`include/` header and `lib/` library via cgo** with **`CGO_ENABLED=1`**: `#cgo CFLAGS -I…` parses the header into the `C.*` **FFI stubs**, and `#cgo LDFLAGS -L… -lazurecosmosdriver` links the library. **Not** NuGet, and **not** a pure-Go build.
- The native library is **packaged inside the delivered artifact** and linked at `go build`. It is **not** a pure-Go shim that downloads the library at build/run time — customers link a real binary through the FFI stubs; they are not handed a downloader stub.
- Prefer the **static `.a`** for a self-contained Go binary; dynamic linking is supported as an option.
- The header + lib are delivered through the **azure-sdk-for-go feed** — an Azure Artifacts Universal Package fetched at build, or a vendored "binaries" Go module with per-OS build tags (delivery *shape* is open Q3; in every shape the binary is **packaged**, not fetched by a shim). Either way it derives from the ADR 0001 hand-off artifact.
- For each release, **one coordinated Rust release build/pipeline** produces all platform binaries (cdylib + staticlib), the cbindgen C header, an `ABI_VERSION`, and checksums, and **signs the binaries**. This may fan out across platform-specific jobs, but they join back into one hand-off governed as a single provenance event.
- These are published as an **internal-only hand-off artifact** (e.g. an Azure Artifacts Universal Package or a pipeline artifact) that is the **single source of truth for provenance**.
- This artifact is **not consumer-facing and not language-shaped.** Consumers never download it; per-language publish jobs consume it (distribution is ADR 0002; the pipeline that produces and fans it out is ADR 0009).
- The hand-off is **RID-keyed** (one subtree per `<os>-<arch>`/libc target) and carries **both link forms per RID** — the dynamic `.dll`/`.so`/`.dylib` *and* the static `.a` — plus a single **C-only header** (no C++ constructs). This layout is a hard requirement so any language, including a future Java JAR (ADR 0002), can repackage straight from the hand-off with **no redesign and no rebuild**.

**Status:** Accepted (proposed for review)

## Context

**Status:** Accepted (proposed for review)

## Context

**Status:** Accepted (proposed for review)

## Context

**Status:** Accepted (proposed for review)

## Context

**Status:** Proposed (for design review)

## Context
Move the native distribution design and ADRs under docs/native-driver-distribution so related language-specific distribution decisions can share a common root.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f7d60272-a96c-48e4-9a85-6e918db6ac26
Copilot AI review requested due to automatic review settings July 17, 2026 20:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 21 comments.


## 1. Purpose

The crate `azure_data_cosmos_driver_native` compiles to a native library — `azurecosmosdriver.{dll,so,dylib}` (and a static `.a`) plus a cbindgen-generated C header — wrapping the schema-agnostic driver core (see `NATIVE_WRAPPER_SPEC.md`, introduced in #4461). It is the single reuse point for **every non-Rust language SDK**. This doc defines how that compiled artifact reaches those SDKs:
Comment on lines +9 to +11
- Native transport is introduced in a **new SDK major version**. Adopting that major **is** adopting native: there is no per-client / per-call opt-in switch, and no managed transport kept in parallel *inside the same major*.
- Existing majors keep their current managed / pure transport unchanged. No consumer is **force-migrated by a routine (minor/patch) bump** — they move to native deliberately, by choosing to take the new major.
- The supported surface is bounded by the platform matrix (ADR 0008). On an unsupported platform/RID the native major fails with a **clear, actionable error**; it does **not** silently fall back to a managed path. If a pure-managed / pure-Go audience must be served long-term, that is a **separate, explicitly limited package**, not a hidden fallback inside the flagship.
- For each release, **one coordinated Rust release build/pipeline** produces all platform binaries (cdylib + staticlib), the cbindgen C header, an `ABI_VERSION`, and checksums, and **signs the binaries**. This may fan out across platform-specific jobs, but they join back into one hand-off governed as a single provenance event.
- These are published as an **internal-only hand-off artifact** (e.g. an Azure Artifacts Universal Package or a pipeline artifact) that is the **single source of truth for provenance**.
- This artifact is **not consumer-facing and not language-shaped.** Consumers never download it; per-language publish jobs consume it (distribution is ADR 0002; the pipeline that produces and fans it out is ADR 0009).
- The hand-off is **RID-keyed** (one subtree per `<os>-<arch>`/libc target) and carries **both link forms per RID** — the dynamic `.dll`/`.so`/`.dylib` *and* the static `.a` — plus a single **C-only header** (no C++ constructs). This layout is a hard requirement so any language, including a future Java JAR (ADR 0002), can repackage straight from the hand-off with **no redesign and no rebuild**.

```
Rust release build — ONE coordinated provenance event
produces .dll/.so/.dylib/.a + azurecosmosdriver.h + ABI_VERSION
Comment on lines +9 to +11
- A single coordinated release pipeline next to the Rust build produces the per-platform binaries (ADR 0001), potentially across multiple platform-specific jobs, then joins them into one hand-off artifact. It **signs each binary once** where platform-native signing exists (Authenticode on Windows; codesign + notarization on macOS), records checksums for every artifact, and publishes the internal hand-off artifact.
- Per-language publish jobs **consume the already-signed hand-off** and emit NuGet / Go-consumable / JAR packages; they **never rebuild or re-sign the native binary** (they may sign their own package wrapper, e.g. the `.nupkg`/`.jar`, in that language's existing ESRP flow).
- Build-once is **enforced by verification, not just discipline**: before repackaging, every per-language publish job **verifies the hand-off's checksums and platform authenticity material** against the values published by the build job, and **fails the publish** on any mismatch — so a job physically cannot ship a rebuilt, altered, or unsigned native binary. On Windows/macOS this means verifying the binary signatures; on Linux, where the binary itself has no equivalent platform code-signing convention, this means verifying the checksum plus the build's provenance attestation / signed manifest for that RID.

**Status:** Accepted (proposed for review)

## Context

**Status:** Accepted (proposed for review)

## Context

**Status:** Accepted (proposed for review)

## Context

**Status:** Accepted (proposed for review)

## Context

**Status:** Proposed (for design review)

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

Labels

Cosmos The azure_cosmos crate

Projects

Status: Needs Attention

Development

Successfully merging this pull request may close these issues.

7 participants