All notable changes to QuerySpec are documented here. Generated from Conventional Commits by standard-version.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
5.0.0 (2026-04-30)
- core: Any consumer that subclasses AesEncryptionProvider, AesGcmEncryptionProvider, BulkheadPolicy, CircuitBreaker, ComplianceExporter, CustomOperatorRegistry, DistributedCacheProvider, InMemoryAuditLogger, MetricsCollector, MultiLevelCache, N1DetectionEngine, RateLimiter, ResiliencePolicy, RetryPolicy, or RowLevelSecurityEngine will receive a compile error (CS0509). The protected virtual Dispose(bool) hook on BulkheadPolicy and InMemoryAuditLogger is removed; callers that overrode it must switch to composing a new IDisposable wrapper instead.
- auditing: IComplianceExporter.GenerateGdprExportAsync(string, string, Stream, CancellationToken) is now the abstract interface member; the GenerateGDPRExportAsync overloads are demoted to default-interface-methods. Customer code that implements IComplianceExporter by overriding only the acronym-form member no longer satisfies the interface contract and must override GenerateGdprExportAsync(..., CancellationToken) instead. v4.x-built binaries that implemented only the acronym-form member will throw TypeLoadException when loaded against the v5.0 interface.
- core: removes the optional-parameter overloads of DataMaskingEngine.Mask, CircuitBreaker.ExecuteAsync, IAuditReader.GetAuditsByUserAsync, IAuditReader.GetAuditsByTenantAsync, InMemoryAuditLogger.GetAuditsByUserAsync and InMemoryAuditLogger.GetAuditsByTenantAsync. Callers that relied on default-argument bindings must update to the explicit overloads.
- auditing: flip IComplianceExporter abstract member to GenerateGdprExportAsync (#276) (8728535), closes #255
- ci: flip ci.yml harden-runner to egress-policy block (#281) (d64039f), closes #164 #216 #216
- core: resolve RS0026/RS0027 optional-parameter overload violations (cdc2126), closes #192
- core: seal 15 public concrete classes (#277) (f63220f), closes #159 #159
- observability: emit System.Diagnostics.Metrics counters under Meter QuerySpec (#273) (91c1420), closes #172
- tests,ci,efcore: coverage ratchet 93/83 → 95/87 and fix BuildIn nullable semantics (#268) (2e453a3), closes #195 #269
- tests,ci: coverage ratchet step 1 - 90/81 → 93/83 (#265) (85809cb), closes #194
- auditing: IAuditReader DIM applies since filter instead of dropping it (#280) (a754ce1), closes #275
- ci: pre-pull Testcontainers images with exponential-backoff retry (#267) (8974fb0), closes #258 #264 #265
- release: postbump-baseline halts on NuGet/git failure instead of silent exit 0 (#264) (174c589), closes #262
- benchmarks: add RowLevelSecurityEngine coverage (#278) (8bf8811), closes #176
- core: allocation-free Validate on valid-input path (#270) (615954e), closes #173 #173
- efcore: generation-based eviction for PredicateCache/PropertyCache (#272) (845ae3e), closes #175 #270 #271
- security: use HMACSHA256.HashData static + cache tenant-derived keys (#271) (3ffefbb), closes #174
- efcore: close coverage gaps in metrics, Xor logic, class null-guard, temporal, regex timeout (#283) (86c576b), closes #282
- tests: close coverage gaps in QuerySpec.Analyzers and CodeFixes (#285) (a5de26d), closes #284
- refresh NuGet metadata, tags, and README badges (53f1c9b)
4.3.0 (2026-04-29)
- ci: gate CodeQL quality findings above count threshold (#260) (3cf2a41), closes #202
- quality: pin NetAnalyzers and BannedApiAnalyzers; LoggerMessage for DistributedCacheProvider (#258) (cafcd24), closes #158 #160 #194 #195 #159
- tests,ci: add SQL snapshots, trim/AOT smoke, sample-build CI; xunit.v3 migration; Core.Tests TFM (#259) (d0993de), closes #171 #181 #184 #185 #246
4.1.3 (2026-04-29)
4.1.2 (2026-04-29)
- release: test SourceLink against .snupkg when symbols are external (#250) (8a348a7)
- release: walk back postbump baseline through unpublished tags (#252) (0dd3d32), closes #251
4.1.1 (2026-04-29)
4.1.0 (2026-04-29)
- ci: fail CI on CodeQL high-severity alerts (#244) (b50d2f3), closes #200
- ci: ratchet coverage gate with line+branch enforcement (77f8120), closes #177
- core: declare IsTrimmable/IsAotCompatible and annotate reflection-using surface (#243) (560493d), closes #170
- release: enable strict ApiCompat baseline validation and prune unused suppressions (#229) (e4b453c), closes #167
- release: polish NuGet package metadata to first-party standard (#206) (5cd8bbb), closes #186 #205
- release: verify SBOM in nupkg and broaden reproducibility to all shipped assemblies (ea14962), closes #187
- security: add gitleaks secret-scanning workflow (#220) (db8e876), closes #165
- security: add step-security/harden-runner in audit mode (#215) (35c96a6), closes #164
- security: emit SLSA build provenance for released NuGet packages (#204) (e9e93ee), closes #163
- tests: add public-API approval baselines via PublicApiGenerator + Verify (#245) (454fa23), closes #182
- tests: add SQL Server and PostgreSQL provider matrix via Testcontainers (#247) (bc93698), closes #178
- benchmarks: guard against vacuous gate pass and exclude flaky SimpleEqual (7211698), closes #179 #179 #198 #199 #197 #198 #199
- ci: exempt dependabot from body/footer line-length rules (#241) (1f10ae1), closes #211 #214 #212 #209 #240
- ci: parse real CodeQL alert counts in evidence gate (90cf713), closes #200 #189
- ci: remove git push from mutation jobs; reports via artifacts (#232) (fd2f23a), closes #190
- ci: switch dependabot to chore(deps) prefix and add deps-dev scope (#239) (b97e3d8)
- release: enforce PublicAPI tracking and populate Shipped.txt for v4.0.0 surface (46cba49), closes #166
- security: use fixed-time compare for audit chain-link verification (#233) (6e15761), closes #188
4.0.0 (2026-04-27)
- security: remove IEncryptionProvider.RotateKeyAsync overloads (#157)
- di: remove 11 throwing DI-builder stub methods (#156)
- efcore: convert QuerySpecExpressionTranslator to static class (#155)
- core: remove 3.x deprecations GeoLocation/AdvancedFilterExpression/ICacheProvider (#154)
- analyzers: ship QuerySpec.Analyzers package with QSPEC0001/2/3 diagnostics and code fixes (#153) (c9032a8), closes #151 #151
- core: Microsoft-grade additive replacements + PublicAPI tracking (#84) (#152) (773353e), closes #151 #150
- core: remove 3.x deprecations GeoLocation/AdvancedFilterExpression/ICacheProvider (#154) (90d6bee), closes #150 #84
- di: remove 11 throwing DI-builder stub methods (#156) (ed3be34), closes #77 #139 #77
- efcore: convert QuerySpecExpressionTranslator to static class (#155) (032dec4), closes #79 #141 #79
- security: remove IEncryptionProvider.RotateKeyAsync overloads (#157) (1d2e35c), closes #138 #73
- auditing: stream GDPR JSON export and propagate cancellation (#62) (#126) (4f19193)
- efcore: translate string operators via EF-recognized methods (#113) (#124) (dfa8fe5)
- resilience: inject TimeProvider into RateLimiter and replace wall-clock test (#143) (#146) (04f1877)
- tests: replace wall-clock timing with FakeTimeProvider and sync primitives (#74) (#125) (b2d74ed)
- emit per-gate JSON evidence and aggregate release-health index (7bcb4aa)
- core: eliminate params object[] alloc in CacheKeyGenerator hot path (#58) (9f88a21)
- efcore: cache Nullable HasValue/Value PropertyInfo in translator (#87) (#127) (534eb7e)
- core: complete /// on public surface (#136) (332a2f5), closes #3
- efcore: mark QuerySpecExpressionTranslator for 3.0 static-class conversion (#79) (#142) (571cc0a)
- release: document supported TFM policy and netstandard2.0 stance (#66) (43bdc24)
- auditing: cover InMemoryAuditLogger query and report methods (#80) (#131) (8fddcb1)
- efcore: add property-based tests and replace silent catch-all with NotSupportedException (#78) (#135) (69a3112)
- monitoring: cover N1DetectionEngine eviction/truncation paths and HealthStatus contract (#83) (#132) (59d9ff9)
- security: configure Stryker.NET mutation testing scoped to security paths (#76) (#134) (2caee91), closes #130
- security: cover large-AAD heap path in MigratingAuthenticatedEncryptionProvider (#85) (#130) (3dec4e3)
- tests: full-library Stryker mutation gating with per-PR incremental + weekly sweep (#76) (9ebff94)
3.0.1-rc1 (2026-04-26)
- release: bump PackageValidation baseline to 3.0.0 (80d1528), closes #72
- release: trim PackageTags and lead with queryspec brand (133be12), closes #51
- release: benchmark smoke gate before pack (10346d3), closes #57
- release: publish to NuGet.org via OIDC trusted publishing (802eafc), closes #59
- release: validate package contents and metadata before publish (#121) (067df9b), closes #64
3.0.0 (2026-04-26)
- core:
ICacheProviderasync members returnValueTaskinstead ofTask. Every method on the interface (GetAsync,SetAsync,RemoveAsync,ExistsAsync,FlushAsync,GetStatsAsync) is affected. Callers that simplyawaitcontinue to work unchanged; code that captures the returned task explicitly must call.AsTask()to convert. CustomICacheProviderimplementations must update their return types. (#115) - core:
AssemblyVersionbumped from2.x.x.xto3.0.0.0. Update any strong-name binding redirects or[assembly: AssemblyVersion]-pinned references.
- core: CancellationToken-accepting overloads across the async public surface (#107) (6d88a17), closes #68 #47
- core: ICacheProvider returns ValueTask, AssemblyVersion -> 3.0.0.0 (#115) (fb28a5b), closes #4 #90
- di: expose Services getter on every QuerySpec DI builder (#106) (857a10b), closes #69
- auditing: InMemoryAuditLogger implements IDisposable to release ReaderWriterLockSlim (#102) (3457e1e), closes #100 #52
- di: WithAuditing uses TryAddSingleton so caller-supplied IAuditLogger wins (#100) (3cad22f), closes #60
- release: set PackageValidationBaselineVersion=2.0.1 with AssemblyVersion pinning (#105) (2efe5e9), closes #102 #104 #70 #55
- resilience: add ConfigureAwait(false) to library awaits in resilience and compliance paths (#101) (f59d7e5), closes #46
- resilience: BulkheadPolicy implements IDisposable to release SemaphoreSlim (#104) (1b7c6f7), closes #102 #103
- efcore: cache Enumerable.Contains open generic + closed instantiations in BuildIn (#108) (beae14b), closes #86
- monitoring: bound stack walk in N1DetectionEngine.RecordQuery (#109) (c842dc0), closes #88
- efcore: add SQLite-backed translator fixture and document StringHelper translation gap (#111) (8bb2705), closes #71 #71
- efcore: cover translator branches at 0% from EFCore tests (#110) (0e9d9f0), closes #69 #78 #69
- resilience: synchronise BulkheadPolicy tests via ManualResetEventSlim (#114) (6527e32), closes #74 #112 #107
2.0.1 (2026-04-26)
- auditing: materialise read snapshots in InMemoryAuditLogger under the read lock (#96) (8219192), closes #54
- auditing: refuse partial PurgeOldLogsAsync to preserve audit-chain integrity (#94) (e72fd22), closes #2
- ci: pin reproducibility job actions to SHAs (#98) (050ccc4), closes #6
- monitoring: bound MetricsCollector, return zero-report on empty, aggregate outside lock (#97) (59385c5), closes #50 #81 #89
- release: replace stale Directory.Build.props version with 0.0.0-local sentinel (c67b7e3)
- security: bound RegexHelper.RegexCache to prevent heap-DoS over user patterns (#95) (d0e18ef), closes #3
- security: default RLSPolicy.FilterGenerator to DenyAll instead of AllowAll (#93) (710b37b), closes #56
- security: make AdvancedFilterExpression.MaskResult/EncryptValue fail Validate when true (#92) (7ba4834), closes #1
- security: promote IsPii(string, object?) Obsolete from warning to error (#99) (29c06ca), closes #73
2.0.0 (2026-04-25)
- security: nested public types in
QuerySpec.Core.SecurityandQuerySpec.Core.Resilienceare now top-level. Drop theHostEngine.qualifier from usages; existingusingdirectives stay valid since the namespace is unchanged. - di:
PluginBuilder,QuerySpecBuilder.WithPlugins,MonitoringBuilder.EnableDashboard, andMonitoringBuilder.EnablePrometheusare removed. Other no-op builder stubs now throwNotImplementedExceptionand carry[Obsolete];ApplyAggregationthrows on non-null aggregation where it previously returned the input unchanged. Remove the calls or replace with concrete implementations. - security:
AesEncryptionProvider.RotateKeyAsyncnow throwsNotSupportedException; the class is marked[Obsolete]. New ciphertexts should useAesGcmEncryptionProvider. Existing ciphertexts encrypted underAesEncryptionProvidermust be re-encrypted under the new provider — there is no automatic upgrade path. - auditing:
AuditLogEntryproperties (other thanIdandErrorMessage) are nowinit-only;HashandPreviousHashsetters areprivate.ComputeHash()is[Obsolete]. Move post-construction mutations into the object initializer or build a fresh entry, and callSeal(previousHash)(owned byIAuditLogger) instead ofComputeHash(). - security:
HashMasknow requires a hash key at construction or registration. Output length is no longer 8 characters, and old SHA-256-truncated values are not reversibly migratable. Pass a hash key to the constructor, re-mask persisted values, and rotate any join keys built on the old algorithm. - security: the strong-name public key has been rotated. Update any
[InternalsVisibleTo]pins, binding redirects, or GAC-resolved references to the new token. - security:
RowLevelSecurityEnginefails closed by default — a missing policy denies access instead of permitting it. Either passRLSDefaultBehavior.AllowAllto the engine constructor or callRegisterUnrestricted<T>(resourceType)per resource that should bypass RLS.
- auditing: link audit log hash chain and seal entries (2d34e69)
- security: add aes-gcm authenticated encryption provider (59e2f46), closes #27 #27
- security: add MigratingEncryptionProvider with prefix-tag dispatch (#37) (deab402), closes #27
- security: keyed hash masking with per-tenant separation (38a0d05), closes #24
- security: row-level security engine fails closed by default (d6a0c84), closes #10
- security: typed SetPredicate helper on RLSPolicy (f23a353)
-
ci: default to delay-sign so CI builds without the private key succeed (5001c96)
-
ci: mark xunit.v3 test projects as OutputType=Exe so CodeQL build doesn't trip (#44) (1fbc653)
-
ci: per-run trx filenames so parallel test runners don't race on a shared file (#45) (dec2e4f), closes #44
-
di: null-check IServiceCollection in builder constructors (7b4f7b6), closes #29
-
resilience: add standard exception constructors (CA1032) (cc402ec)
-
security: explicit IPiiClassifier replaces name-heuristic for PII decisions (#36) (7fb0a5b), closes #24
-
security: guard dynamic permission evaluator against null and empty subject (986a84c)
-
security: seal DataMaskingEngine (#43) (fb98538), closes #38
-
security: rotate strong-name keypair after public exposure (b68305f), closes #8 #9 #18
- ci: pin actions to commit SHAs and lock workflow permissions (efa25be)
- release: gate release on tag reachable from main or develop (9771531)
- di: triage every no-op builder stub (c688627)
- security: extract nested public types to top-level (3b29d59), closes #7
1.0.8 (2026-04-25)
- ci: fix devcontainer permission errors on dotnet first-run sentinel (2ebf8a1)
1.0.7 (2026-04-25)
- add reproducible devcontainer with multi-tfm dotnet, node, and tooling (275ab96)
1.0.6 (2026-04-25)
- mirror packages to github packages and strip workflow comments (9358836)
1.0.5 (2026-04-24)
- add nuget release pipeline triggered on version tags (f012887)
1.0.4 (2026-04-24)
- ci: collect coverage from Core.Tests and fix summary parser regex (a2da606)
1.0.3 (2026-04-24)
1.0.2 (2026-04-24)
- ci: use --severity warn (dropped 'warning' in dotnet format 10.x) (3f20d5c)
1.0.1 (2026-04-24)
- deps: downgrade @commitlint to 19 for standard-version compatibility (29ca743)
- add sample projects (d80f143)
- release: add standard-version for changelog and versioning (3d847f1)