* Add secrets module * Address Greptile feedback for secrets module * Handle unavailable secrets in provider adapter * Address path combine review comments * Address additional Greptile secrets review * Address final Greptile secrets feedback * Handle secrets test payload failures * address greptile feedback on secrets rotation * fix secret recreation concurrency * address greptile secrets followups * address greptile secrets reliability feedback * align secret store capabilities
3.4 KiB
Runtime Contract: Secrets Module
Secret Resolver
Runtime consumers resolve by immutable technical name. Implementations return latest active versions only and never expose cleartext through metadata APIs.
public interface ISecretResolver
{
ValueTask<ResolvedSecret> ResolveAsync(SecretReference reference, CancellationToken cancellationToken = default);
}
Resolution failures use safe error codes such as NotFound, Inactive, Expired, Revoked, TypeMismatch, ScopeMismatch, StoreUnavailable, or Unauthorized.
Secret Manager
Management operations create logical secrets, rotate values, revoke/delete secrets, and return metadata-only models.
public interface ISecretManager
{
ValueTask<SecretMetadata> CreateAsync(CreateSecretRequest request, CancellationToken cancellationToken = default);
ValueTask<SecretMetadata> RotateAsync(string technicalName, RotateSecretRequest request, CancellationToken cancellationToken = default);
ValueTask<SecretMetadata?> FindAsync(string technicalName, CancellationToken cancellationToken = default);
ValueTask<Page<SecretMetadata>> ListAsync(SecretQuery query, CancellationToken cancellationToken = default);
ValueTask RevokeAsync(string technicalName, CancellationToken cancellationToken = default);
ValueTask DeleteAsync(string technicalName, CancellationToken cancellationToken = default);
}
Rules:
technicalNameis immutable after creation.RotateAsyncretires the current latest active version and creates a new latest active version.- No method returns current cleartext values.
Secret Store
Stores own payload persistence and declare their capabilities.
public interface ISecretStore
{
SecretStoreDescriptor Descriptor { get; }
ValueTask<SecretPayload> WriteAsync(SecretWriteContext context, CancellationToken cancellationToken = default);
ValueTask<SecretPayload?> ReadAsync(SecretReadContext context, CancellationToken cancellationToken = default);
ValueTask DeleteAsync(SecretDeleteContext context, CancellationToken cancellationToken = default);
ValueTask<SecretTestResult> TestAsync(SecretTestContext context, CancellationToken cancellationToken = default);
}
Capability rules:
- Configuration store supports read/test where possible, not write/delete/rotate.
- Elsa encrypted store supports read/write/delete/rotate/encrypted export.
- Store-private payloads are not exposed through general metadata APIs.
Secret Type Provider
Types provide validation, generation, payload shaping, and Studio editor metadata.
public interface ISecretTypeProvider
{
SecretTypeDescriptor Descriptor { get; }
ValueTask ValidateAsync(SecretTypeValidationContext context, CancellationToken cancellationToken = default);
ValueTask<SecretPayloadInput> GenerateAsync(SecretGenerationContext context, CancellationToken cancellationToken = default);
}
V1 built-in types are Text, RsaKey, and X509CertificateReference.
Compatibility Adapter
Existing ISecretProvider.GetSecretAsync(name) consumers continue through an adapter.
public interface ISecretProvider
{
Task<string?> GetSecretAsync(string name, CancellationToken cancellationToken = default);
}
Adapter behavior:
- Map
nametoSecretReference.TechnicalName. - Resolve latest active version.
- Return
nullonly for legacy compatibility where the current provider did so; new APIs should return structured failures.