Deneblab.StashLock.Client
0.3.110
There is a newer version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package Deneblab.StashLock.Client --version 0.3.110
NuGet\Install-Package Deneblab.StashLock.Client -Version 0.3.110
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="Deneblab.StashLock.Client" Version="0.3.110" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Deneblab.StashLock.Client" Version="0.3.110" />
<PackageReference Include="Deneblab.StashLock.Client" />
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 Deneblab.StashLock.Client --version 0.3.110
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Deneblab.StashLock.Client, 0.3.110"
#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 Deneblab.StashLock.Client@0.3.110
#: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=Deneblab.StashLock.Client&version=0.3.110
#tool nuget:?package=Deneblab.StashLock.Client&version=0.3.110
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Deneblab.StashLock.Client
Async-first .NET secrets management client for StashLock vault.
Installation
dotnet add package Deneblab.StashLock.Client
Quick Start
using Deneblab.StashLock.Client;
// From environment variable STASHLOCK_VAULT_KEY
var store = await StashLock.CreateClient()
.FromEnvironment()
.OpenAsync();
var dbPassword = store["Database:Password"];
Fluent API
All access starts with StashLock.CreateClient() which returns a fluent builder.
Remote vault (password-based)
// From environment variable
var store = await StashLock.CreateClient()
.FromEnvironment()
.OpenAsync();
// Explicit vault key
var store = await StashLock.CreateClient()
.WithVaultKey("myapp.prod.00001.password")
.OpenAsync();
Remote sealed-box (X25519)
var store = await StashLock.CreateClient()
.WithBox("myapp", "prod")
.WithPrivateKey(key) // optional, falls back to env var
.OpenAsync();
Sealed-box with offline cache
var store = await StashLock.CreateClient()
.WithBox("myapp", "prod")
.WithPrivateKey(key)
.WithCache(ttl: TimeSpan.FromHours(2))
.OpenAsync();
// With custom cache directory
var store = await StashLock.CreateClient()
.WithBox("myapp", "prod")
.WithCache(cacheDir: "/app/cache", ttl: TimeSpan.FromHours(4))
.OpenAsync();
Local files
// Plain JSON file (development)
var store = await StashLock.CreateClient()
.FromDevFile() // auto-discovers dev/secrets/secrets.json
.OpenAsync();
// Explicit plain JSON file
var store = await StashLock.CreateClient()
.FromFile("./secrets.json")
.OpenAsync();
// Local encrypted file (SOPS or whole-file mode)
var store = await StashLock.CreateClient()
.FromEncryptedFile("./stashlock.enc.prod.secrets.json")
.WithPrivateKey(key)
.OpenAsync();
Configuration validation
var result = await StashLock.CreateClient()
.WithBox("myapp", "prod")
.ValidateAsync();
if (!result.IsValid)
foreach (var issue in result.Issues)
Console.WriteLine($"ERROR: {issue}");
Builder options
| Method | Description |
|---|---|
.FromEnvironment() |
Read vault key from STASHLOCK_VAULT_KEY env var |
.WithVaultKey(string) |
Explicit vault key (box.tag.version.password) |
.WithBox(box, tag, version?) |
Sealed-box mode with box/tag/version |
.FromDevFile(path?) |
Plain JSON file (auto-discovers if no path) |
.FromFile(path) |
Explicit plain JSON file |
.FromEncryptedFile(path) |
Local encrypted file (SOPS or whole-file) |
.WithApiUrl(url) |
Override API URL |
.WithApiKey(key) |
Override API key |
.WithPrivateKey(base64) |
X25519 private key for sealed-box decryption |
.WithCache(cacheDir?, ttl?, machineId?) |
Enable encrypted offline cache |
.OpenAsync() |
Open the secrets store |
.ValidateAsync() |
Validate configuration without opening |
Reading Secrets
// Indexer (synchronous — secrets are pre-loaded)
string value = store["Database:Password"];
// Async
string value = await store.GetAsync("Database:Password");
// TryGet (no exception on missing key)
if (store.TryGet("OptionalKey", out var value))
{
// use value
}
// Section as dictionary
var dbConfig = await store.GetSectionAsDictionaryAsync("Database");
// Returns: { "Host": "localhost", "Password": "secret", ... }
// Typed section (deserializes into a POCO)
var dbConfig = store.GetSection<DatabaseConfig>("Database");
IConfiguration Integration
Single AddStashLock extension method with the same fluent builder:
using Deneblab.StashLock.Client.Configuration;
var builder = WebApplication.CreateBuilder(args);
// Remote sealed-box vault with cache
builder.Configuration.AddStashLock(cfg => cfg
.WithBox("myapp", "prod")
.WithCache(cacheDir: "/app/cache", ttl: TimeSpan.FromHours(4))
);
var app = builder.Build();
// Access secrets via standard IConfiguration
var connString = app.Configuration["Database:ConnectionString"];
var apiKey = app.Configuration["ExternalService:ApiKey"];
Dev/prod branching
builder.ConfigureAppConfiguration((ctx, config) =>
{
if (ctx.HostingEnvironment.IsDevelopment())
{
config.AddStashLock(cfg => cfg
.FromDevFile("dev/secrets/secrets.json")
);
}
else
{
config.AddStashLock(cfg => cfg
.WithBox("myapp", ctx.HostingEnvironment.EnvironmentName.ToLower())
.WithCache(ttl: TimeSpan.FromHours(2))
);
}
});
Encrypted local file
builder.Configuration.AddStashLock(cfg => cfg
.FromEncryptedFile("secrets.enc.json")
.WithPrivateKey(key)
);
Dependency Injection
Register ISecretsStore as a singleton in your DI container:
using Deneblab.StashLock.Client.Configuration;
builder.Services.AddStashLock(cfg => cfg
.WithBox("myapp", "prod")
.WithCache(ttl: TimeSpan.FromHours(2))
);
// Inject anywhere
public class MyService(ISecretsStore secrets)
{
public string GetDbPassword() => secrets["Database:Password"];
}
Environment Variables
| Variable | Purpose | Fallback |
|---|---|---|
STASHLOCK_VAULT_KEY |
Vault key string (box.tag.version.password) |
Used by .FromEnvironment() |
STASHLOCK_PRIVATE_KEY |
Base64-encoded X25519 private key | Used by .WithBox(), .FromEncryptedFile() |
STASHLOCK_API_URL |
Vault API base URL | Defaults to https://deneblabvault.azurewebsites.net/api/ |
STASHLOCK_API_KEY |
API authentication key (Bearer token) | Optional |
Error Handling
try
{
var store = await StashLock.CreateClient()
.FromEnvironment()
.OpenAsync();
}
catch (VaultConfigurationException ex)
{
// Missing or invalid configuration (env var, key format)
}
catch (VaultNotFoundException ex)
{
// Vault entry not found on server
}
catch (DecryptionException ex)
{
// Decryption failed — wrong password or key
}
Development Secrets File
Create a secrets.json in dev/secrets/ under your project root:
{
"Database:ConnectionString": "Server=localhost;Database=dev",
"Database:Password": "dev-password",
"ExternalApi:Key": "dev-api-key"
}
FromDevFile() (without a path) auto-discovers this file when running in Dev or Test mode.
License
MIT License - see LICENSE file for details
Links
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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.
-
net8.0
- BouncyCastle.Cryptography (>= 2.6.2)
- Microsoft.Extensions.Configuration (>= 10.0.3)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.3)
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.4.2 | 0 | 3/12/2026 |
| 0.3.122 | 2 | 3/12/2026 |
| 0.3.121 | 35 | 3/12/2026 |
| 0.3.119 | 28 | 3/12/2026 |
| 0.3.118 | 26 | 3/12/2026 |
| 0.3.117 | 22 | 3/12/2026 |
| 0.3.115 | 27 | 3/12/2026 |
| 0.3.112 | 28 | 3/12/2026 |
| 0.3.111 | 26 | 3/12/2026 |
| 0.3.110 | 29 | 3/12/2026 |
| 0.3.109 | 27 | 3/12/2026 |
| 0.3.108 | 34 | 3/11/2026 |
| 0.3.107 | 28 | 3/11/2026 |
| 0.3.106 | 30 | 3/11/2026 |
| 0.3.105 | 33 | 3/11/2026 |
| 0.3.103 | 26 | 3/11/2026 |
| 0.3.102 | 32 | 3/11/2026 |
| 0.3.100 | 33 | 3/11/2026 |
| 0.3.99 | 32 | 3/11/2026 |
| 0.3.98 | 31 | 3/11/2026 |
Loading failed