Releases: SharkableIO/Sharkable
Releases · SharkableIO/Sharkable
Release list
v0.5.5
security
- Add
MaxFingerprintBodySize(default 64 KiB) toSharkIdempotencyOptions— prevent OOM via attacker-controlledContent-Lengthheader in idempotency middleware fingerprinting. Fixed chunked-transfer bypass where allTransfer-Encoding: chunkedrequests hashed to the same fingerprint (now hashes body incrementally with-1sentinel for unknown length); setter rejects<= 0 - Replace
Thread.Sleeppolling withawait Task.Delayin graceful shutdown drain — prevent ApplicationStopping thread block (SHARK-SEC-003). Initial fix used.GetAwaiter().GetResult()on the drain task which still blocked the callback; corrected to true fire-and-forget soApplicationStoppingreturns immediately. - Make
SagaExecutor.LockTtlconfigurable; addLockRenewalIntervalwith periodic lock extension — prevent split-brain sagas when step duration exceeds lock TTL (SHARK-SEC-004, cross-repo withSharkable.Cache.Redis).ISagaStore.RenewLockAsyncconverted from a required interface member to a default interface method (DIM) so existing third-party implementations keep compiling unchanged. - Replace unconditional
KeyDeleteinRedisSagaStore.ReleaseLockAsyncandRedisCronJobStore.ReleaseJobLockAsyncwith check-and-delete Lua script — prevent split-brain when LockTtl expires mid-work (SHARK-SEC-005, cross-repo withSharkable.Cache.Redis) - Add
ICronJobStore.RenewJobLockAsyncplusCronScheduler.CronLockTtl(default 10 min) and a background renewal task mirroringSagaExecutor— prevent split-brain cron jobs when job duration exceeds lock TTL (SHARK-SEC-005 follow-up, cross-repo withSharkable.Cache.Redis) - BREAKING: Add
[CrudAllow]attribute for explicit field allowlist on AutoCrud insertable/updateable — endpoints withCreate | Updateenabled and zero[CrudAllow]properties now throwInvalidOperationExceptionat startup. Existing entities must mark every writable field with[CrudAllow]. Prevents mass-assignment privilege escalation (SHARK-SEC-006) - BREAKING (SHARK-SEC-006 follow-up): Exclude the configured soft-delete column (
SqlSugarOptions.SoftDeleteFieldName, default"IsDeleted") from the[CrudAllow]allow-list even when explicitly marked — otherwise an attacker can revive soft-deleted rows by sending the field in a PUT body. Honors[SugarColumn(ColumnName = "...")]renames - BREAKING (SHARK-SEC-006 follow-up): AutoCrud
POST /andPUT /{id}now return the persisted row re-read from the database instead of the user-controlled request body — previous behavior silently hid server-side defaults (timestamps, identity-generated PK, server-set soft-delete state) from the client - Require API key on profiler endpoint
/_sharkable/profilerby default; return 404 if no API keys configured (SHARK-SEC-015). AddsSharkOption.ProfilerRequireApiKey(defaulttrue); also caps thetopslow-requests surface at 50 to bound data exposure - Require API key on cron admin endpoint
/_sharkable/jobs; redactLastErrorfield to its first 100 characters +...to prevent business-logic leakage (SHARK-SEC-016). AddsSharkOption.CronAdminRequireApiKey(defaulttrue); returns 404 if no API keys are configured - BREAKING: Make
CronScheduler.Registerasync — eliminate sync-over-async deadlock risk with distributed stores (SHARK-SEC-017).ICronScheduler.Registeris replaced byRegisterAsyncreturningTask;SharkOption.ConfigureCronJobscallback type changes fromAction<ICronScheduler>toFunc<ICronScheduler, Task>so the hosted service can await it without blocking on startup. Internalawait _store.LoadStateAsync(...)replaces.GetAwaiter().GetResult(). - Add
SharkOption.RequireAuthenticatedByDefaultopt-in flag — enforce auth on framework endpoints via fallback policy (SHARK-SEC-011, closes both H-4 and H-6) - Add
ETagOptions.MaxResponseSize(default 10 MiB) + counting stream + incremental hashing — prevent OOM via huge response bodies (SHARK-SEC-012) - Add
IMemoryCacheSizeLimit (100k) + periodic eviction sweep toMemoryRateLimitStore— prevent slow-loris DoS via unique path explosion (SHARK-SEC-013) - Add
IMemoryCacheSizeLimit (10k) + entry.Size tracking toMemoryIdempotencyStore— prevent TB-DoS via unique idempotency keys (SHARK-SEC-014) - Add JWT algorithm allowlist +
RequireSignedTokens+RequireExpirationTime+ reduceClockSkewto 30s — prevent algorithm confusion attacks (SHARK-SEC-007) - Use
CryptographicOperations.FixedTimeEqualsfor API key comparison — prevent timing oracle (SHARK-SEC-008) - Gate
ScalarJwtToken/ScalarApiKeyValuetoIHostEnvironment.IsDevelopment()— prevent token leakage to public/scalar/v1UI (SHARK-SEC-009) - Implement
AuditTrailMiddlewareheader redaction perRedactHeaderslist — credential-bearing headers (Authorization,X-Api-Key,Cookieby default) have their values replaced with***in audit log output. Header names preserved so reviewers see which credentials were presented (SHARK-SEC-010) - Redact RedisHealthCheck description — never expose topology or exception messages on public
/healthz(SHARK-SEC-018) - Validate connection string at AddSharkableRedis — null-check + default
abortConnect=false+ optional TLS enforcement (SHARK-SEC-019) - Replace
JsonSerializer.Serialize<T>with source-generatedJsonSerializerContextinRedisIdempotencyStore— Cache.Redis is now AOT-compatible (SHARK-SEC-020 follow-up, cross-repo withSharkable.Cache.Redis) - Remove auto-registration of
RedisHealthCheckasIHealthCheckinAddSharkableRedis—UseSharkableRedisHealthCheck()is the only way to wire it (SHARK-SEC-021 follow-up, cross-repo withSharkable.Cache.Redis) - Connection string: only override
abortConnect=falsewhen the key is absent — respect an explicitabortConnect=true(SHARK-SEC-019 follow-up, cross-repo withSharkable.Cache.Redis) - Replace empty catch in RedisIdempotencyStore deserialization with typed exception handling + tombstone record — prevent silent double-execution on corruption (SHARK-SEC-020)
- Add
UseSharkableRedisHealthCheck()extension — explicit opt-in to wire health check into/healthz(SHARK-SEC-021) - Set TTL on RedisSagaStore progress records via
RedisStoreOptions.SagaProgressTtl(default 7d) — prevent unbounded memory growth (SHARK-SEC-022) - Add
AutoCrudSqlSugar.AutoCrudRequireAuthorizationopt-in flag — auto-attach.RequireAuthorization()to generated CRUD endpoints. Defaultfalsefor backward compat; production deployments MUST enable. (SHARK-SEC-023, cross-repo withSharkable.AutoCrud.SqlSugar) - Defense-in-depth: also exclude
SafeSoftDeleteFieldfrom[CrudAllow]allow-list by case-insensitive name match — protects against entities whose C# property name matches the configured soft-delete column but lacks[SugarColumn]rename (SHARK-SEC-024, cross-repo withSharkable.AutoCrud.SqlSugar) - Add
AutoCrudSqlSugar.MaxPageNumber(default 1M) + overflow check on(page - 1) * pageSize— prevent pagination DoS viapage=int.MaxValueproducing a negative OFFSET (SHARK-SEC-025, cross-repo withSharkable.AutoCrud.SqlSugar) - Redact
SqlSugarHealthCheckdescription — never exposedbTypeorex.Messageon public/healthz; full diagnostic detail logged atLogWarningfor operators only (SHARK-SEC-026, cross-repo withSharkable.AutoCrud.SqlSugar) - Escape SQL
LIKEwildcards + cap filter value length (200) + capINarray size (100) in AutoCrud search — prevent LIKE wildcard DoS and large-IN clause DoS (SHARK-SEC-027, cross-repo withSharkable.AutoCrud.SqlSugar) - Fix ETag
CountingResponseBody.FlushAsyncduplicate body write on over-cap responses (SHARK-SEC-012 follow-up) - Fix
MemoryRateLimitStore.IncrementAsyncnon-atomic increment allowing concurrent bypass (SHARK-SEC-013 follow-up) - Replace
AuditTrailMiddleware.CaptureHeadersJsonSerializer.Serializewith hand-rolled formatter — AOT-compatible (SHARK-SEC-010 follow-up) - Make JWT audience validation mandatory when
ConfigureJwtis called — reject empty audience list at config time (SHARK-SEC-007 follow-up) - Strip assembly-qualified type name from
ExceptionHandlerOptions.GetErrorMessagedev output — prevent fingerprinting ofSharkable.X.Y, Version=1.0.0.0over the wire (SHARK-SEC-M003) - Redact
JwtHealthCheckdescription on/healthz— replace authority URL +ex.Messageechoes with generic descriptions; full URL + exception now surface viaILogger.LogWarningfor operators only (SHARK-SEC-M004) - Pin
CultureInfo.InvariantCultureforstring.FormatinHttpContext.Localize(key, args)— prevent culture-dependent format-string growth attacks via malicious translations (SHARK-SEC-M005) - Implement
IDisposableonAdaptiveLimitMonitor+ wrapAdjust()in try/catch — prevent timer-callback exception tearing the process down + close theProcesshandle leak (SHARK-SEC-M010) - Cap
CronExpression.GetNextiteration count at 2.2 M — bound CPU on non-matching patterns (e.g.0 0 30 2 *) that previously looped 2.1 M times per hosted-service tick (SHARK-SEC-M011) - Link
SharkCronHostedServicehost stoppingToken to a per-jobCancellationTokenSource— prevent orphaned long-running cron jobs survivingapp.StopAsync()and tripping k8s termination grace periods (SHARK-SEC-M012) - Collapse
CronSchedulerthree correlated dictionaries (_jobs/_states/_expressions) into oneDictionary<string, JobEntry>under a single lock — eliminate TOCTOU betweenRegisterandGetDueJobsAsync(SHARK-SEC-M013) - Bound
/healthzaggregateHealthCheckService.CheckHealthAsyncwith a 10 sCancellationTokenSource— prevent a single hung check from keeping the endpoint open and tripping k8s probes (SHARK-SEC-M015) JwtHealthChecknow acceptsIHttpClientFactoryvia DI — reuse a pooledHttpMessageHandlerinstead of opening a new socket per probe (SHARK-SEC-M016)- Default rate-...
v0.5.4
security
- Add 100ms regex timeout to FormatAsGroupName / GetVersionFormat — prevent ReDoS via malicious GroupNameSuffixPattern / VersionFormatPattern
- Add SafeSoftDeleteField validation in AutoCrudGenerator — reject non-alphanumeric field names to prevent SQL injection
Full Changelog: v0.5.3...v0.5.4
v0.5.3
feat
- Add
HttpContext.Localize(string key, params object[] args)overload — format args in localized strings - Add
HttpContext.GetCulture()extension — resolve client culture fromAccept-Languageheader ApiKeyFilterautomatically skipped whenAuthorizationInterceptorFactoryis set — interceptor owns auth entirely- Add
SqlSugarOptions.MaxPageSize/DefaultPageSize— configurable AutoCrud pagination limits (defaults: 100 / 20) - Add
SqlSugarOptions.SoftDeleteFieldName— configurable soft delete field (default:"IsDeleted") - Add
SharkOption.ETagOptions.CacheableMethods/CacheControlHeader/ShouldSkipStatus— ETag method set, cache header, and cacheable status logic are now configurable - Add
SharkOption.ApiKeyHeaderName— configurable API key request header - Add
GracefulShutdownOptions.ShutdownStatusCode/DrainPollingInterval— configurable 503 status code and drain polling interval - Add
SharkOption.ProblemDetailsTypeFactory/ProblemDetailsTitleFactory— delegates for customizing RFC 7807typeURI andtitle - Add
SharkOption.DefaultCulture— configurable default locale for error localizer - Add
SharkRateLimiterOptions.AdaptiveGcHighThreshold/AdaptiveGcLowThreshold/AdaptiveReductionDivisor— GC pressure thresholds and reduction factor for adaptive rate limiting - Add
ProfilerOptions.MaxEntries— configurable profiler ring buffer size - Add
SharkIdempotencyOptions.RetryAfterSeconds/ShouldCacheStatus— configurable Retry-After and cacheable status predicate - Add
SharkOption.HealthCheckPath— configurable health check endpoint path - Add
TracingOptions.ActivitySourceName— configurableActivitySourcename (separate fromServiceName) - Add
SharkOption.GroupNameSuffixPattern/VersionFormatPattern/VersionFormatReplacement— customizable endpoint URL naming regexes - Remove hardcoded
"Sharkable"ActivitySourceName inTracingMiddleware— now usesTracingOptions.ActivitySourceName - Add
HttpContext.Localize(string key)extension method — easy localization in user endpoints - Add
LocalizationExtensions— public scaffolding for endpoint-level error translation - Add
SharkOption.EnableAuthorization(defaulttrue) — allows users to opt out of authorization service registration - Add
SharkOption.ConfigureAuthorization— delegate for customizingAuthorizationOptions(policies, fallback, etc.) - Add
SharkOption.ScalarJwtToken/SharkOption.ScalarApiKeyValue— configure pre-filled credentials in Scalar UI
docs
- Add complete error localization guide with
IErrorLocalizerimplementation example,HttpContext.Localize()usage, and middleware integration pattern (EN + ZH)
fix
- Fix
InvalidOperationExceptionwhenUseAuthorizationis called withoutAddAuthorization— registerAddAuthorizationby default (configurable viaEnableAuthorization), with factory support viaConfigureAuthorizationdelegate - Fix
UnifiedResultWrapFilteralways wrapping with status 200 — now uses actualHttpContext.Response.StatusCode - Fix
AuditTrailMiddlewareresponse header hardcoded to"X-Correlation-Id"— now respectsAuditTrailOptions.CorrelationIdHeader
v0.5.1
v0.3.2
v0.3.1
v0.3.0
What's Changed
- fix: correct license expression, add README.md and packaging items by @charleypeng in #71
- docs: comprehensive README.md update with all features by @charleypeng in #72
- feat: add test project + NativeTest demo improvements by @charleypeng in #73
- Feat/tests and native test demo by @charleypeng in #75
- Feat/tests and native test demo by @charleypeng in #76
- add built-in middleware (E) and security (F) features by @charleypeng in #77
- chore: bump version to 0.2.0 by @charleypeng in #78
- feat: add audit trail / request logging middleware by @charleypeng in #79
- Feat/idempotency middleware by @charleypeng in #80
Full Changelog: https://github.com/SharkableIO/Sharkable/blob/main/CHANGELOG.md
v0.2.0
What's Changed
- fix: correct license expression, add README.md and packaging items by @charleypeng in #71
- docs: comprehensive README.md update with all features by @charleypeng in #72
- feat: add test project + NativeTest demo improvements by @charleypeng in #73
- Feat/tests and native test demo by @charleypeng in #75
- Feat/tests and native test demo by @charleypeng in #76
- add built-in middleware (E) and security (F) features by @charleypeng in #77
Full Changelog: v0.1.0...v0.2.0
v0.1.0
What's Changed
- update nuget dependency to avoid downgrade warning/invoke method as nullable by @charleypeng in #59
- add unifiedresults factory and code refactor by @charleypeng in #60
- feat: add global exception handler + auto unified result wrap by @charleypeng in #61
- refactor: pluggable UnifiedResult with IUnifiedResultFactory by @charleypeng in #63
- update AGENTS.md: add branch sync & rebase workflow by @charleypeng in #64
- feat: add FluentValidation integration with auto-validate filter by @charleypeng in #65
- docs: add XML doc comments to validation code + coding standard to AG… by @charleypeng in #66
- fix: audit XML comments, fix bugs, remove dead code by @charleypeng in #67
- feat: upgrade to .NET 10, replace Swagger with Scalar by @charleypeng in #68
- Feat/endpoint grouping tags by @charleypeng in #70
Full Changelog: v0.0.25...v0.1.0
v0.0.25
What's Changed
- fix where generic type of return delegate might be null by @charleypeng in #55
- fix unified result extension method and code refactor by @charleypeng in #56
- Feat/unifiedresults by @charleypeng in #57
- fix: where results like badrequest should only contains error message by @charleypeng in #58
Full Changelog: v0.0.24...v0.0.25