Release 1.0.0#13
Merged
Merged
Conversation
Bring the library to a stable 1.0 release. Crypto/security: - Hybrid envelope format v2: fold the ML-KEM encapsulation block into the AES-GCM associated data (HPKE-style; no unauthenticated bytes). Reads legacy v1 hybrid envelopes; AES envelopes unchanged (still v1). - Fail-fast validation of the default scheme at protector construction, so a misconfiguration (e.g. ML-KEM default on an unsupported host) throws at startup instead of on first write. - Pin the patched SQLite native bundle (SQLitePCLRaw 3.x) to clear advisory GHSA-2m69-gcr7-jv3q (test/sample-only; not shipped). API/DX: - IsEncrypted rejects unsupported property types with a clear, property-named error instead of an opaque EF model-build failure. - In-place, thread-safe key rotation on the in-memory rings (AddKey/ SetActiveKey/RemoveKey). Required because EF caches the model (and the captured protector) per context type, so swapping the ring cannot rotate. - Re-encryption helpers ReEncryptAsync<T>() and MarkEncryptedPropertiesModified, which force EF to re-run the value converter (a plain SaveChanges does not, since change tracking compares the unchanged decrypted value). - Lock the public API surface with Microsoft.CodeAnalysis.PublicApiAnalyzers and a PublicAPI.Shipped.txt baseline. Sample: - Fix a latent bug where the KEK was disposed inside the configure lambda, breaking the sample on any ML-KEM-capable machine. Docs/versioning: - README: Always Encrypted/TDE comparison table, "not ASP.NET Data Protection" note, rewritten rotation guide, 1.x API + format stability commitment. - Update KNOWN-GAPS, threat model, migration guide, CHANGELOG; bump to 1.0.0. Tests expanded from 35 to 55 (envelope hardening + v1 back-compat, fail-fast, type guard, rotation, re-encryption, concurrency, documented relocation). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fixes three findings from review (gdm.md): 1. Data loss in online re-encryption. ReEncryptAsync used offset pagination (Skip/Take), which can skip an unswept old-key row when concurrent inserts/ deletes shift rows across a batch boundary — losing that row's plaintext once the old key is dropped. Now snapshots primary keys once and fetches each batch by key membership (IN), which is immune to row shifting. Rows inserted after the snapshot are already under the active key; deleted rows are simply not found. Signature is now ReEncryptAsync<TEntity, TKey>() (typed key for the snapshot/IN); validates the key type against the model. 2. TOCTOU race retiring keys. The active-key check and dictionary mutation in RemoveKey were not atomic, and the id->dictionary indirection could let a lock-free ActiveKey read observe a removed key. Rings now hold the active key as a direct volatile reference and serialize AddKey/SetActiveKey/RemoveKey under a lock, so check-then-act is atomic and reads never dangle. 3. ChangeTracker pollution. ReEncryptAsync operated on the caller's context, committing pending changes and evicting the tracked graph. It now requires a dedicated context (no tracked entities), reads AsNoTracking, and clears only its own batch. Tests: +3 (online-sweep verifies every row across batches, dedicated-context guard, key-type mismatch, concurrent rotation stress). 58 pass on net8/net10. Docs and PublicAPI baseline updated for the new signature. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the long-lived NUGET_API_KEY secret with OIDC-based Trusted Publishing: grant the publish job id-token: write and exchange the GitHub OIDC token for a short-lived key via NuGet/login before dotnet nuget push. The secret can be removed from the repo once this ships. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First stable release. Brings the library from 0.1.0 to a production-ready 1.0 with a frozen, authenticated envelope, a real key-rotation story, a locked public API surface, and expanded security tests. Commits to SemVer (API + format stability) for the 1.x line.
Highlights
Crypto / security
API / DX
IsEncryptedrejects unsupported property types with a clear, property-named error.AddKey/SetActiveKey/RemoveKey) — required because EF caches the model (and the captured protector) per context type, so swapping the ring cannot rotate.ReEncryptAsync<TEntity, TKey>()+MarkEncryptedPropertiesModified, which force EF to re-run the converter (a plainSaveChangesdoes not). The sweep snapshots primary keys and batches by key membership (not offset paging), so it is safe to run online, and requires a dedicated context so it never touches your app's tracked graph.PublicApiAnalyzer+PublicAPI.Shipped.txtbaseline.Sample
Docs / versioning
Testing
Notes for release
v1.0.0to trigger the Publish workflow (requires a validNUGET_API_KEYsecret).🤖 Generated with Claude Code