diff --git a/docs/compatibility-promise.md b/docs/compatibility-promise.md index 9b4a391..3d59d7b 100644 --- a/docs/compatibility-promise.md +++ b/docs/compatibility-promise.md @@ -38,6 +38,8 @@ way that breaks stored data or removes/alters public surface. - Core value types: `KeyId`, `TenantId`, `LogicalName`, `EncryptedDataScope`, `EncryptionContext`, `KeyDescriptor`, `CiphertextEnvelope`, `CiphertextEnvelopeHeader`, and the envelope id types (`EnvelopeVersion`, `CryptoSuiteId`, `AadSchemeId`). +- `IKeyMaterialProvider` and `KeyResolutionException` live in the dependency-free + `Proteos.Encryption.Abstractions` package (the provider seam is public via `UseKeyProvider`). - Entity Framework Core integration: the attributes (`[Encrypted]`, `[EncryptedSearchable]`, `[EncryptedEmail]`, `[Plaintext]`, `[EncryptedEntity]`), the fluent configuration API, the query helpers (`WhereEncryptedEquals`, `WhereEncryptedIn`, `WhereEncryptedEmail`), the registration entry @@ -93,8 +95,6 @@ Areas that may evolve after `1.0` without violating the promise: While still on `0.x`, the following changes are considered acceptable and may land before `1.0`. They are listed so the intent is on record; none is guaranteed to happen. -- Moving `IKeyMaterialProvider` from `Proteos.Encryption.Core` to `Proteos.Encryption.Abstractions` for - cleaner layering. (Currently expected to be left as-is, but allowed.) - Adjusting the re-encryption (preview) API surface. - Refining registration ergonomics and adding startup-time configuration validation. - Analyzer message wording and rule scope. diff --git a/samples/Proteos.FeatureShowcase/Infrastructure/ShowcaseHost.cs b/samples/Proteos.FeatureShowcase/Infrastructure/ShowcaseHost.cs index c512241..665e70c 100644 --- a/samples/Proteos.FeatureShowcase/Infrastructure/ShowcaseHost.cs +++ b/samples/Proteos.FeatureShowcase/Infrastructure/ShowcaseHost.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Proteos.Encryption.Abstractions; using Proteos.Encryption.Core; namespace Proteos.FeatureShowcase.Infrastructure; diff --git a/src/Proteos.Encryption.Core/Keys/IKeyMaterialProvider.cs b/src/Proteos.Encryption.Abstractions/Keys/IKeyMaterialProvider.cs similarity index 96% rename from src/Proteos.Encryption.Core/Keys/IKeyMaterialProvider.cs rename to src/Proteos.Encryption.Abstractions/Keys/IKeyMaterialProvider.cs index 8114e14..50665b2 100644 --- a/src/Proteos.Encryption.Core/Keys/IKeyMaterialProvider.cs +++ b/src/Proteos.Encryption.Abstractions/Keys/IKeyMaterialProvider.cs @@ -1,6 +1,4 @@ -using Proteos.Encryption.Abstractions; - -namespace Proteos.Encryption.Core; +namespace Proteos.Encryption.Abstractions; /// /// Resolves the symmetric key material the encryption layer uses for a tenant and a specific diff --git a/src/Proteos.Encryption.Core/Keys/KeyResolutionException.cs b/src/Proteos.Encryption.Abstractions/Keys/KeyResolutionException.cs similarity index 85% rename from src/Proteos.Encryption.Core/Keys/KeyResolutionException.cs rename to src/Proteos.Encryption.Abstractions/Keys/KeyResolutionException.cs index 9b8c351..dd72f21 100644 --- a/src/Proteos.Encryption.Core/Keys/KeyResolutionException.cs +++ b/src/Proteos.Encryption.Abstractions/Keys/KeyResolutionException.cs @@ -1,6 +1,4 @@ -using Proteos.Encryption.Abstractions; - -namespace Proteos.Encryption.Core; +namespace Proteos.Encryption.Abstractions; /// /// Thrown when a key cannot be resolved for the requested tenant and descriptor — for example diff --git a/src/Proteos.Encryption.Abstractions/PublicAPI.Shipped.txt b/src/Proteos.Encryption.Abstractions/PublicAPI.Shipped.txt index b301648..9e99702 100644 --- a/src/Proteos.Encryption.Abstractions/PublicAPI.Shipped.txt +++ b/src/Proteos.Encryption.Abstractions/PublicAPI.Shipped.txt @@ -216,3 +216,10 @@ static readonly Proteos.Encryption.Abstractions.CryptoSuiteId.Aes256GcmSiv -> Pr static readonly Proteos.Encryption.Abstractions.CryptoSuiteId.Aes256SivDeterministic -> Proteos.Encryption.Abstractions.CryptoSuiteId static readonly Proteos.Encryption.Abstractions.CryptoSuiteId.XChaCha20Poly1305 -> Proteos.Encryption.Abstractions.CryptoSuiteId static readonly Proteos.Encryption.Abstractions.EnvelopeVersion.V1 -> Proteos.Encryption.Abstractions.EnvelopeVersion +Proteos.Encryption.Abstractions.IKeyMaterialProvider +Proteos.Encryption.Abstractions.IKeyMaterialProvider.DeriveKey(Proteos.Encryption.Abstractions.TenantId! tenant, Proteos.Encryption.Abstractions.KeyDescriptor! descriptor) -> byte[]! +Proteos.Encryption.Abstractions.IKeyMaterialProvider.GetCurrentKeyId(Proteos.Encryption.Abstractions.TenantId! tenant) -> Proteos.Encryption.Abstractions.KeyId! +Proteos.Encryption.Abstractions.IKeyMaterialProvider.GetKnownKeyIds(Proteos.Encryption.Abstractions.TenantId! tenant) -> System.Collections.Generic.IReadOnlyCollection! +Proteos.Encryption.Abstractions.IKeyMaterialProvider.ProviderId.get -> string! +Proteos.Encryption.Abstractions.KeyResolutionException +Proteos.Encryption.Abstractions.KeyResolutionException.KeyResolutionException(string! message) -> void diff --git a/src/Proteos.Encryption.Core/PublicAPI.Shipped.txt b/src/Proteos.Encryption.Core/PublicAPI.Shipped.txt index bacef94..14e93ed 100644 --- a/src/Proteos.Encryption.Core/PublicAPI.Shipped.txt +++ b/src/Proteos.Encryption.Core/PublicAPI.Shipped.txt @@ -2,7 +2,7 @@ const Proteos.Encryption.Core.LocalDevelopmentKeyProvider.DerivedKeyLength = 32 -> int const Proteos.Encryption.Core.LocalDevelopmentKeyProvider.RootKeyMinLength = 32 -> int Proteos.Encryption.Core.AesGcmValueEncryptionService -Proteos.Encryption.Core.AesGcmValueEncryptionService.AesGcmValueEncryptionService(Proteos.Encryption.Core.IKeyMaterialProvider! keyProvider, Proteos.Encryption.Core.ICiphertextEnvelopeCodec! codec) -> void +Proteos.Encryption.Core.AesGcmValueEncryptionService.AesGcmValueEncryptionService(Proteos.Encryption.Abstractions.IKeyMaterialProvider! keyProvider, Proteos.Encryption.Core.ICiphertextEnvelopeCodec! codec) -> void Proteos.Encryption.Core.AesGcmValueEncryptionService.Decrypt(Proteos.Encryption.Abstractions.CiphertextEnvelope! envelope, Proteos.Encryption.Abstractions.EncryptionContext! context) -> byte[]! Proteos.Encryption.Core.AesGcmValueEncryptionService.DecryptFromBytes(System.ReadOnlySpan envelopeBytes, Proteos.Encryption.Abstractions.EncryptionContext! context) -> byte[]! Proteos.Encryption.Core.AesGcmValueEncryptionService.Encrypt(System.ReadOnlySpan plaintext, Proteos.Encryption.Abstractions.EncryptionContext! context) -> Proteos.Encryption.Abstractions.CiphertextEnvelope! @@ -50,7 +50,7 @@ Proteos.Encryption.Core.HmacBlindIndexProvider.Compute(System.ReadOnlySpan Proteos.Encryption.Core.HmacBlindIndexProvider.ComputeForAllKnownKeys(System.ReadOnlySpan value, Proteos.Encryption.Abstractions.BlindIndexDescriptor! descriptor, Proteos.Encryption.Abstractions.EncryptionContext! context) -> System.Collections.Generic.IReadOnlyCollection! Proteos.Encryption.Core.HmacBlindIndexProvider.CreateIndex(string! value, Proteos.Encryption.Abstractions.EncryptionContext! context, Proteos.Encryption.Abstractions.BlindIndexPurpose purpose) -> Proteos.Encryption.Abstractions.BlindIndexValue! Proteos.Encryption.Core.HmacBlindIndexProvider.CreateIndex(string! value, Proteos.Encryption.Abstractions.EncryptionContext! context, Proteos.Encryption.Abstractions.BlindIndexPurpose purpose, Proteos.Encryption.Core.IBlindIndexNormalizer! normalizer) -> Proteos.Encryption.Abstractions.BlindIndexValue! -Proteos.Encryption.Core.HmacBlindIndexProvider.HmacBlindIndexProvider(Proteos.Encryption.Core.IKeyMaterialProvider! keyProvider) -> void +Proteos.Encryption.Core.HmacBlindIndexProvider.HmacBlindIndexProvider(Proteos.Encryption.Abstractions.IKeyMaterialProvider! keyProvider) -> void Proteos.Encryption.Core.IBlindIndexNormalizer Proteos.Encryption.Core.IBlindIndexNormalizer.Normalize(string! value) -> string! Proteos.Encryption.Core.ICiphertextEnvelopeCodec @@ -58,16 +58,9 @@ Proteos.Encryption.Core.ICiphertextEnvelopeCodec.CreateAad(Proteos.Encryption.Ab Proteos.Encryption.Core.ICiphertextEnvelopeCodec.Parse(System.ReadOnlySpan data) -> Proteos.Encryption.Abstractions.CiphertextEnvelope! Proteos.Encryption.Core.ICiphertextEnvelopeCodec.Serialize(Proteos.Encryption.Abstractions.CiphertextEnvelope! envelope) -> byte[]! Proteos.Encryption.Core.ICiphertextEnvelopeCodec.TryParse(System.ReadOnlySpan data, out Proteos.Encryption.Abstractions.CiphertextEnvelope? envelope, out Proteos.Encryption.Core.EnvelopeParseError? error) -> bool -Proteos.Encryption.Core.IKeyMaterialProvider -Proteos.Encryption.Core.IKeyMaterialProvider.DeriveKey(Proteos.Encryption.Abstractions.TenantId! tenant, Proteos.Encryption.Abstractions.KeyDescriptor! descriptor) -> byte[]! -Proteos.Encryption.Core.IKeyMaterialProvider.GetCurrentKeyId(Proteos.Encryption.Abstractions.TenantId! tenant) -> Proteos.Encryption.Abstractions.KeyId! -Proteos.Encryption.Core.IKeyMaterialProvider.GetKnownKeyIds(Proteos.Encryption.Abstractions.TenantId! tenant) -> System.Collections.Generic.IReadOnlyCollection! -Proteos.Encryption.Core.IKeyMaterialProvider.ProviderId.get -> string! Proteos.Encryption.Core.InMemoryTenantKeyRegistry Proteos.Encryption.Core.InMemoryTenantKeyRegistry.GetRecord(Proteos.Encryption.Abstractions.TenantId! tenant) -> Proteos.Encryption.Abstractions.TenantKeyRecord! Proteos.Encryption.Core.InMemoryTenantKeyRegistry.InMemoryTenantKeyRegistry(System.Collections.Generic.IEnumerable! records) -> void -Proteos.Encryption.Core.KeyResolutionException -Proteos.Encryption.Core.KeyResolutionException.KeyResolutionException(string! message) -> void Proteos.Encryption.Core.LocalDevelopmentKeyProvider Proteos.Encryption.Core.LocalDevelopmentKeyProvider.CurrentVersion.get -> ushort Proteos.Encryption.Core.LocalDevelopmentKeyProvider.DeriveKey(Proteos.Encryption.Abstractions.TenantId! tenant, Proteos.Encryption.Abstractions.KeyDescriptor! descriptor) -> byte[]! diff --git a/src/Proteos.Encryption.EntityFrameworkCore/PublicAPI.Shipped.txt b/src/Proteos.Encryption.EntityFrameworkCore/PublicAPI.Shipped.txt index 351fabb..0f3f9f7 100644 --- a/src/Proteos.Encryption.EntityFrameworkCore/PublicAPI.Shipped.txt +++ b/src/Proteos.Encryption.EntityFrameworkCore/PublicAPI.Shipped.txt @@ -125,7 +125,7 @@ Proteos.Encryption.EntityFrameworkCore.PlaintextAttribute.PlaintextAttribute() - Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions.EnableStrictMode() -> Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions! Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions.ProteosEncryptionOptions() -> void -Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions.UseKeyProvider(System.Func! factory) -> Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions! +Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions.UseKeyProvider(System.Func! factory) -> Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions! Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions.UseLocalDevelopmentKeyProvider(byte[]? rootKey = null) -> Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions! Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions.UseSingleTenant(string! tenantId) -> Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions! Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions.UseTenant(System.Func! tenantResolver) -> Proteos.Encryption.EntityFrameworkCore.ProteosEncryptionOptions!