DarkVault.Client 2.2.0

dotnet add package DarkVault.Client --version 2.2.0
                    
NuGet\Install-Package DarkVault.Client -Version 2.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DarkVault.Client" Version="2.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DarkVault.Client" Version="2.2.0" />
                    
Directory.Packages.props
<PackageReference Include="DarkVault.Client" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DarkVault.Client --version 2.2.0
                    
#r "nuget: DarkVault.Client, 2.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DarkVault.Client@2.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DarkVault.Client&version=2.2.0
                    
Install as a Cake Addin
#tool nuget:?package=DarkVault.Client&version=2.2.0
                    
Install as a Cake Tool

DarkVault.Client

NuGet .NET 10 CI License: MIT

The asynchronous .NET SDK for DarkVault buckets, secrets, and token metadata. Load application configuration or manage individual secrets with revision checks.

Install

dotnet add package DarkVault.Client

Targets .NET 10. For ASP.NET Core configuration, use DarkVault.Extensions.Configuration.

Quick start

using DarkVault.Client;

var token = Environment.GetEnvironmentVariable("DARKVAULT_TOKEN")
    ?? throw new InvalidOperationException("DARKVAULT_TOKEN is required");

using var vault = new DarkVaultClient("https://vault.example.com", token);
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10));

var settings = await vault.ReadBucketAsync("app_prod", timeout.Token);
var databaseUrl = settings["Database:Url"];

Reuse a client and dispose it when its owner shuts down. The client disposes its own HTTP client but never a caller-supplied one.

Connection and permissions

Use the server's HTTPS origin, for example https://vault.example.com, without an API path, URL credentials, query, or fragment. Tokens are issued in the DarkVault web UI and use the dv1_ format (64 characters total). Supply the token explicitly from a protected source; this SDK does not load CLI configuration.

Bucket arguments are exact names, not UUIDs. Each operation needs its matching token scopes and bucket access. Reading an entire bucket needs bucket:read, secret:read, and secret:list. Bucket creation additionally depends on the token's allowed creation names. Token issuance and revocation are administrative operations, not SDK methods.

Values are strings. Treat returned secrets as sensitive in-memory data; do not log values, Authorization headers, or request bodies. TLS verification must stay enabled. JWE uses ECDH-ES/P-256/A256GCM in addition to HTTPS; the server still sees plaintext secrets, so this is not a zero-knowledge system.

Required scopes

Operation Required scopes
List buckets bucket:list
Get bucket metadata bucket:read
Read bucket values bucket:read, secret:read, secret:list
Create bucket bucket:create
Update bucket description bucket:write
Delete empty bucket bucket:delete
Delete bucket recursively bucket:delete, secret:delete
List secret metadata secret:list
Read secret value secret:read
Create, update, or set secret secret:write
Delete secret secret:delete
Inspect own token Any valid token

Scopes do not replace bucket grants.

API reference

All operations are asynchronous. Every method below accepts a final optional CancellationToken cancellationToken = default. Results in the table are wrapped in Task<T>; delete methods return Task.

Method (excluding cancellation token) Result
AddBucketAsync(name, description = "") Bucket
GetBucketAsync(bucket) Bucket
ListBucketsAsync(cursor = null, limit = 100) Page<Bucket>
ReadBucketAsync(bucket) IReadOnlyDictionary<string, string?>
ReadBucketSnapshotAsync(bucket) BucketSnapshot
UpdateBucketAsync(bucket, description, expectedRevision) Bucket
RenameBucketAsync(bucket, name, expectedRevision) Bucket
DeleteBucketAsync(bucket, expectedRevision, recursive = false) No value
AddSecretAsync(bucket, key, value) SecretMetadata
ReadSecretAsync(bucket, key) Secret
ListSecretsAsync(bucket, cursor = null, limit = 100) Page<SecretMetadata>
UpdateSecretAsync(bucket, key, value, expectedRevision) SecretMetadata
SetSecretAsync(bucket, key, value, expectedRevision = 0) SecretMetadata
DeleteSecretAsync(bucket, key, expectedRevision) No value
GetTokenInfoAsync() TokenInfo
ExecuteAsync<T>(operation, parameters) Deserialized T; advanced wire API

Names, keys, values, and descriptions are strings; revisions are long, limits are int, and cursors are nullable strings.

  • Bucket: Id, Name, Description, Revision, CreatedAt, UpdatedAt.
  • SecretMetadata: Id, BucketId, Key, Revision, CreatedAt, UpdatedAt.
  • Secret: the same fields plus Value. Listing does not return values.
  • BucketSnapshot: BucketId, Revision, Secrets.
  • Page<T>: Items, NextCursor.
  • TokenInfo: Id, Name, Scopes, BucketIds, AllBuckets, CreatableBucketNames, and nullable ExpiresAt.

Timestamps use DateTimeOffset. Bucket dictionaries preserve secret names.

Updates and revisions

The following snippet assumes the vault instance above and an existing bucket:

var created = await vault.AddSecretAsync("app_prod", "Feature:Enabled", "true");

var updated = await vault.UpdateSecretAsync(
    "app_prod",
    "Feature:Enabled",
    "false",
    created.Revision
);

await vault.DeleteSecretAsync("app_prod", "Feature:Enabled", updated.Revision);

Updates/deletes require the revision read from the affected object. A stale revision returns revision_conflict; fetch current state and decide whether to apply your change. SetSecretAsync with revision 0 creates only if absent. Deleting a nonempty bucket requires recursive: true. Refresh bucket metadata after secret changes before using its revision for deletion.

Pagination

string? cursor = null;

do {
    var page = await vault.ListSecretsAsync("app_prod", cursor, limit: 100);

    foreach (var item in page.Items) {
        // Metadata only; never print values.
        Console.WriteLine(item.Key);
    }

    cursor = page.NextCursor;
} while (cursor is not null);

Limits are 1–200. Cursors are opaque; continue the same listing with the returned cursor. Neither list method automatically reads all pages.

Errors, cancellation, and retries

try {
    var snapshot = await vault.ReadBucketSnapshotAsync("app_prod");
} catch (DarkVaultException error) {
    Console.Error.WriteLine(
        $"DarkVault: {error.Code}; HTTP {error.Status}; request {error.RequestId}"
    );
}

DarkVaultException exposes Code, Status (0 for local/transport failures), and optional RequestId. Invalid constructor arguments can throw argument exceptions. Cancellation/deadline expiry can throw OperationCanceledException.

Each operation has a 30-second deadline, including discovery and retries. Pass a cancellation token to shorten it. Reads may retry twice after network errors or retryable 429/5xx responses. An explicit unknown_key response permits one key refresh. Uncertain writes are not automatically retried: on outcome_unknown, or cancellation after a write was sent, inspect current state before retrying.

Common server errors include unauthorized, forbidden, not_found, already_exists, revision_conflict, and bucket_not_empty.

Custom HTTP transport

using var http = new HttpClient(new HttpClientHandler {
    AllowAutoRedirect = false
});
using var vaultWithTransport = new DarkVaultClient("https://vault.example.com", token, http);

Retain normal TLS validation. For a private CA, install the CA into the trust store used by your application. Do not use an accept-all certificate callback. The caller owns and disposes http. Configure transport behavior before use.

DarkVault and server setup · API schema · Issues · MIT license

Typed configuration

Secret types are string, number, boolean, and null. String reads remain available; typed reads preserve scalar types. See the configuration contract for SDK methods, nested paths, JSON/YAML export, and string fallback rules.

Connection string

Use https://<token>@host[:port]/bucket-name to keep connection settings in one secret variable, for example DARKVAULT_URL. The scheme, token and bucket are required. Bucket names use 1–63 lowercase letters, digits, _ or -, starting with a letter or digit. Additional paths, query strings, fragments and passwords are rejected. Use the literal token and bucket name without percent encoding.

The client constructor and URL factory do not read environment variables. The factory separates the token from the HTTPS origin before making requests. Treat the entire string as a secret. Existing constructors and explicit bucket arguments still work. The default bucket is used for bucket/configuration reads when omitted; other operations can use the exposed default-bucket property explicitly.

var connection = Environment.GetEnvironmentVariable("DARKVAULT_URL")
    ?? throw new InvalidOperationException("DARKVAULT_URL is required");
using var client = DarkVaultClient.FromUrl(connection);
var secrets = await client.ReadBucketAsync();
var secret = await client.ReadSecretAsync(client.DefaultBucket!, "ApiKey");

Load configuration in one call

var settings = await DarkVaultClient.LoadConfigurationAsync(
    connection, SettingsJsonContext.Default.AppSettings);

Supply your source-generated JsonTypeInfo<T>, as for ReadConfigurationAsync, to preserve Native AOT support. The helper loads one typed, nested snapshot and disposes its client. An optional cancellation token and caller-owned HttpClient are supported.

Load settings from the environment

var settings = await DarkVaultClient.LoadConfigurationAsync(
    SettingsJsonContext.Default.AppSettings);

The overload without a URL reads DARKVAULT_URL. It accepts the same optional cancellation token and caller-owned HttpClient.

Missing or whitespace-only DARKVAULT_URL produces a clear error. An explicit URL is used independently of the environment. The SDK does not load .env files; load one beforehand if needed. Existing timeouts and cancellation behavior apply.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on DarkVault.Client:

Package Downloads
DarkVault.Extensions.Configuration

Load an encrypted DarkVault bucket into .NET configuration.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.2.0 95 9/22/2026
2.1.0 102 9/21/2026
2.0.1 105 9/20/2026
2.0.0 92 9/20/2026
1.0.0 94 9/20/2026