Required secret protection
Configure three independent random 32-byte Base64 values before starting Docker or registering the runtime. Keep the same keys on every node and across restarts. HMAC_KEY and JWT_KEY remain separate signing secrets. Run openssl rand -base64 32 separately for each protection key.
| Docker variable | ASP.NET Core configuration |
|---|---|
DB_ENCRYPTION_KEY | SecretProtection:DatabasePasswords:Keys:db-1 |
DML_ENCRYPTION_KEY | SecretProtection:DmlPayloads:Keys:dml-1 |
DML_FINGERPRINT_KEY | SecretProtection:DmlFingerprintKey |
Set SecretProtection:DatabasePasswords:ActiveKeyId to db-1 and SecretProtection:DmlPayloads:ActiveKeyId to dml-1. Missing, invalid or reused keys fail startup. Example placeholders are deliberately invalid.
HsSqlAgent.Hosting binds SecretProtection automatically. Modular hosts must bind it explicitly:
hs.AddHsSqlAgentRuntime(options =>
{
builder.Configuration.GetSection("SecretProtection").Bind(options.SecretProtection);
});
For new bootstrap MCP keys, provide explicit Bootstrap:Databases:*:McpKeys:*:Key values; startup does not generate or log them. Existing encrypted database passwords must be re-entered. Read the upgrade guide before changing an existing deployment.
Credential storage and rotation
Database passwords use purpose-bound AES-256-GCM ciphertext tied to the trusted record’s SecretBindingId; durable payloads are bound to RequestId. There is no legacy decryption fallback. ICryptoService accepts a context string rather than caller-provided key bytes.
To rotate an encryption ring, distribute old and new IDs to every node, switch ActiveKeyId, then re-save passwords. Retain old DML keys while pending or historical payloads still require inspection. The independent fingerprint key is not versioned; drain approvals before rotating it and retain prior secrets for historical witness inspection.
ExtraSettings accepts only JSON booleans Encrypt and TrustServerCertificate. Unknown/duplicate fields, strings and invalid JSON are rejected. Connection tests and health probes expose generic DB_CONNECTION_FAILED messages rather than driver details.
Doctor check security.secret-protection validates key IDs, Base64/length and independence without returning secrets. Public sample keys warn outside Production and error in Production, including retained inactive samples. Invalid placeholders error everywhere; invalid configuration can prevent startup before Doctor is available.
hs-sql-agent has three consumption paths, but the security boundary is the same in all of them.
| Path | Configuration model |
|---|---|
| Docker / ToolBox | complete standalone environment surface from .env.example |
HsSqlAgent.Hosting | same standard first-party composition through ASP.NET Core configuration |
HsSqlAgent.Server | capability-owned options selected explicitly by the host |
DML approval
MCP Elicitation is the default first-party approval provider. The standalone Docker image and HsSqlAgent.Hosting can switch to the official generic Webhook adapter without changing the SQL execution primitive.
| Environment variable | Meaning |
|---|---|
DML_APPROVAL_PROVIDER | McpElicitation or Webhook |
DML_APPROVAL_WEBHOOK_ENDPOINT | external approval service endpoint |
DML_APPROVAL_WEBHOOK_CALLBACK_URL | public callback URL used to complete pending approvals |
DML_APPROVAL_WEBHOOK_SIGNING_SECRET | Webhook signing secret; at least 32 UTF-8 bytes |
The equivalent ASP.NET Core configuration is:
{
"DmlApproval": {
"Provider": "Webhook",
"Webhook": {
"Endpoint": "https://approval.example.com/hssqlagent/requests",
"CallbackUrl": "https://sql-agent.example.com/api/hs-sql-agent/approvals/webhook",
"SigningSecret": "replace-with-a-unique-secret-at-least-32-bytes"
}
}
}
Unknown provider names fail at startup. An asynchronous provider may return Pending; durable resume requires the Admin Store capability so protected resume intent and approval fingerprints can be persisted.
A modular HsSqlAgent.Server host can register HsSqlAgent.Approvals.Webhook or its own IDmlApprovalProvider. Approval providers never receive a database connection, transaction, validated execution plan, or commit primitive.
Application and control plane
The standalone configuration includes:
ASPNETCORE_URLSandALLOWED_HOSTSfor application hosting;ADMIN_DATABASE_PROVIDERandADMIN_DATABASE_CONNECTION_STRINGfor the control plane;HMAC_KEYandMCP_PUBLIC_ENDPOINTfor MCP access;JWT_KEYand the JWT/authentication settings for built-in Admin identity;- SMTP, password-reset, OIDC/MFA, bootstrap, audit, health, and delivery settings;
- cache, rate-limit, policy-sync, outbound-delivery-sync, and SQL-concurrency providers;
- Prometheus and OTLP observability settings.
HMAC_KEY and JWT_KEY must be independent secrets of at least 32 bytes. Persist DATA_PROTECTION_KEY_PATH when protected identity state is enabled.
Single instance and distributed providers
The default single-instance shape can use SQLite for the Admin database and process-local Memory providers. When several application instances must share state, use a shared Admin database and the Redis-backed providers for cache, rate limiting, security-policy sync, outbound-delivery sync, and SQL concurrency.
Distributed coordination defaults to fail closed where the corresponding failure mode supports that choice.
Observability
Prometheus can run on a separate listener configured with PROMETHEUS_ENABLED, PROMETHEUS_HOST, and PROMETHEUS_PORT. OTLP export uses OTLP_ENDPOINT and OTEL_SERVICE_NAME.
Embedded .NET hosts
HsSqlAgent.Hosting owns the complete standard composition. HsSqlAgent.Server starts from AddHsSqlAgentCore() and only validates options for capabilities the application selects. Host authorization can replace built-in identity, and approval providers can be replaced independently.
See Deployment, ASP.NET Core integration, and Safe DML.