Webority.Azure.DataProtection
0.2.0
See the version list below for details.
dotnet add package Webority.Azure.DataProtection --version 0.2.0
NuGet\Install-Package Webority.Azure.DataProtection -Version 0.2.0
<PackageReference Include="Webority.Azure.DataProtection" Version="0.2.0" />
<PackageVersion Include="Webority.Azure.DataProtection" Version="0.2.0" />
<PackageReference Include="Webority.Azure.DataProtection" />
paket add Webority.Azure.DataProtection --version 0.2.0
#r "nuget: Webority.Azure.DataProtection, 0.2.0"
#:package Webority.Azure.DataProtection@0.2.0
#addin nuget:?package=Webority.Azure.DataProtection&version=0.2.0
#tool nuget:?package=Webority.Azure.DataProtection&version=0.2.0
Webority.Azure
Shared Azure infrastructure for the Webority product fleet — one canonical, optimized implementation of the Azure plumbing every product used to hand-copy (and drift on).
Package IDs stay Webority.Azure.* for a tidy nuget.org grouping, but the C# namespaces are
deliberately Webority.AzureStorage / Webority.AzureTelemetry / Webority.AzureDataProtection /
Webority.AzureNotificationHubs — not Webority.Azure.*. A Webority.Azure.* namespace would
shadow the Azure SDK's own Azure root namespace for any consumer code living under a
Webority.* namespace, since C# walks enclosing namespaces and finds Webority.Azure before it
ever reaches global Azure.Core/Azure.Identity.
| Package | What it gives a product |
|---|---|
Webority.Azure.Storage |
Blob / Queue / Table services: singleton cached clients, streaming downloads (DownloadStreamingAsync), seekable OpenReadAsync for range-resumable large downloads, resumable chunked block upload (caller-supplied block ids shareable with a browser client, plus GetStagedBlockIdsAsync to resume an interrupted upload) with content type on commit, HTTPS-only read and write SAS for both auth models (user-delegation key cached), Base64 queues with known-queue cache, Table service + IDistributedCache implementation. |
Webority.Azure.DataProtection |
One-call ASP.NET Core DataProtection key persistence to blob storage. |
Webority.Azure.Telemetry |
One-call OpenTelemetry → Azure Monitor bootstrap (connection string, sampling ratio, failed-only span filtering, export-level log floor) replacing the per-head copied block — see "Telemetry collection policy" below. |
Webority.Azure.NotificationHubs |
Push notifications (FCM v1 + APNS) over Azure Notification Hubs with typed payload building. |
Auth model (Storage)
One options contract, two modes — set exactly one:
Azure:Storage:StorageAccountName→ Entra / managed identity via a narrowedDefaultAzureCredentialchain (ManagedIdentity in Azure, Azure CLI locally — nothing else, so no slow credential probing on constrained plans). One cached credential per process.Azure:Storage:ConnectionString→ shared key (the local-development default: developers without Azure access use the staging account's connection string).
Conventions
- All services register as singletons (Azure SDK clients own their transport and are built
for process-wide reuse — see
dotnet.md, HttpClient/SDK-client rule). - Options are validated on start (
ValidateDataAnnotations().ValidateOnStart()); a misconfigured host crashes at boot, never at first request. - Public type names match the pre-extraction fleet implementations (
IAzureStorageBlobService, …), so migrating a product is ausingswap plus deleting its local copy.
Telemetry collection policy
AddWeborityTelemetry's fleet defaults implement one rule: collect only what is consumed.
Application Insights ingestion is billed, and near nobody looks at the Metrics blade or a
complete log of every successful outbound call — so none of that ships to Azure Monitor unless a
head opts in.
- No metrics export by default (
EnableMetrics = false). This suppresses the distro's standard-metrics/performance-counter pipeline (AzureMonitorOptions.EnableStandardMetrics/EnablePerformanceCounters, bothtrueby default upstream) and the ASP.NET Core/HttpClient runtime metersUseAzureMonitorwires in on .NET 8+, via a catch-all dropping view. SetEnableMetrics = trueto restore metrics fleet-wide;DroppedMetricsthen trims just the known-noisy subset instead of everything. - Failed-only spans, sampled successes. Failed spans (
Status == Error, or any span carrying a recorded exception event) are always kept. Successful dependency/client spans are always dropped. Successful server/request spans are kept with probabilitySuccessfulRequestSamplingRatio(default0.25), decided deterministically per trace so every span belonging to one trace agrees. - Log export floors at Warning (
MinimumLogExportLevel). This filters only whatOpenTelemetryLoggerProviderforwards to Azure Monitor — a head's ownILoggercalls, and any other registered provider (console, debug, ...), are unaffected.
All three are options on WeborityTelemetryOptions, overridable per head via the configure
delegate or the WeborityTelemetry configuration section — this is the fleet default, not a
hard rule.
Upgrading
- Table cache rows written by an earlier version are treated as expired and rewritten. The
cache stores its TTL in
ExpiresDateTimeUtc(previouslyExpiresAtUtc) and its write time inCachedDateTimeUtc(previouslyCachedAtUtc). A row whose expiry cannot be read — column absent, null, or unparseable — is a miss, never a never-expiring hit, so pre-existing rows simply miss once and are rewritten. No action needed, and no dual-read shim: reading both names would restore exactly the ambiguity that let a stale short-TTL entry validate forever. - A table cache miss is quiet. The cache reads with the not-found-tolerant overload, so a missing row no longer throws inside the SDK, logs an error trace, or exports as a failed dependency. Products that count failed dependencies will see the revocation-check misses disappear from that stream. Writes and deletes are unchanged.
- Blob containers are created on first write.
SaveAsyncand the block-staging paths create the resolved container (private,PublicAccessType.None) once per container name per process, matching the queue and table services. Products can drop their own create-if-missing call before every upload. Read paths still fail on a missing container, so a wrong container name surfaces instead of being silently created.
Releasing
Version lives once in Directory.Build.props (<Version>). Push to main runs tests, packs
all four packages, and publishes to public nuget.org (.github/workflows/publish.yml).
Work happens on development; a release is a PR development → main merged with a merge
commit, per the fleet git conventions.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Azure.Extensions.AspNetCore.DataProtection.Blobs (>= 1.5.3)
- Microsoft.AspNetCore.DataProtection (>= 10.0.10)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.10)
- Webority.Azure.Storage (>= 0.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.10.0 | 79 | 10/4/2026 |
| 0.9.0 | 79 | 10/4/2026 |
| 0.8.0 | 88 | 10/3/2026 |
| 0.7.0 | 84 | 9/27/2026 |
| 0.6.0 | 91 | 9/25/2026 |
| 0.5.1 | 101 | 9/25/2026 |
| 0.5.0 | 91 | 9/22/2026 |
| 0.4.0 | 91 | 9/22/2026 |
| 0.3.1 | 102 | 9/22/2026 |
| 0.3.0 | 100 | 9/15/2026 |
| 0.2.0 | 98 | 9/13/2026 |
| 0.1.4 | 127 | 8/12/2026 |
| 0.1.3 | 113 | 8/12/2026 |
| 0.1.2 | 111 | 8/12/2026 |
| 0.1.1 | 116 | 8/12/2026 |
| 0.1.0 | 118 | 8/12/2026 |