fix(backend): scope-cache invalidation, log backpressure test, rate-limit audit (#1148 #1146 #1147) - #1188
Open
Malik6828 wants to merge 1 commit into
Open
Conversation
…t#1147 — scope-cache invalidation, log backpressure test, rate-limit audit StellerCraft#1148 — Invalidate GitHub scope-validation cache on provider disconnect - Add clearScopeValidationCacheEntry(token) to scope-validator.ts; performs targeted eviction by token hash without flushing unrelated cache entries. - Update MultiProviderAuthService.disconnectProvider (GitHub branch) to read the encrypted token before clearing the DB row, then call clearScopeValidationCacheEntry so a same-token reconnect is forced to re-validate against GitHub instead of serving a stale 'valid: true' result. - Add integration tests in multi-provider-oauth.integration.test.ts covering connect → cache-populate → disconnect → same-token reuse (expects network hit), targeted entry removal, and graceful no-op when token is already null. StellerCraft#1146 — Sustained-throughput backpressure integration test for log streaming - Extend tests/logs/log-streaming.integration.test.ts with a new describe block using the real LogStreamBuffer and DeploymentLogBatcher classes backed by a deliberately slow Supabase stub (configurable insert delay). - Tests assert: pending buffer size ≤ capacity, pendingFlushes ≤ MAX_PENDING_BATCHES, no throws under backpressure, overflow tracking via hasOverflow()/consumeDropped(), and replay correctness via replayFrom(). StellerCraft#1147 — Audit and reconcile stacked rate-limit middlewares - Audit finding: no route in apps/backend/src/app/api currently applies both withTierRateLimit and withRateLimit/checkRateLimit on the same path. - Add a comprehensive audit comment to tier-rate-limit.ts documenting the shared-store risk, the audit outcome, and the invariant that must be maintained by future contributors. - Add tests/rate-limit/stacked-middleware-quota.integration.test.ts with tests that document the shared-store behaviour, demonstrate the double-consume failure mode, encode the 'no double-wrap' audit invariant as a living assertion, and verify per-slot quota correctness for single-middleware routes. Closes StellerCraft#1148 Closes StellerCraft#1146 Closes StellerCraft#1147
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.
Summary
Resolves three backend issues in a single focused PR.
#1148 — Invalidate GitHub scope-validation cache on provider disconnect
Problem:
MultiProviderAuthService.disconnectProviderclearedgithub_token_encryptedin the DB but left any matching entry in the in-memoryscopeValidationCachealive. A disconnect → reconnect cycle that reuses the same raw OAuth token value (reproducible in test/staging, possible in production) would serve a stalevalid: truescope result for up toSCOPE_VALIDATION_CACHE_TTL_MS(5 min default).Fix:
clearScopeValidationCacheEntry(accessToken)toscope-validator.ts— targeted eviction by SHA-256 token hash, leaves all other cache entries untouched.disconnectProvider(GitHub branch) inmulti-provider-auth.service.tsto read the encrypted token before clearing the DB row, then callclearScopeValidationCacheEntry. Decryption failure is caught and treated as non-fatal (the entry will expire naturally).Tests: Added 3 integration tests in
multi-provider-oauth.integration.test.ts:fetchAndValidateScopescall with the same token.clearScopeValidationCacheEntrydoes not throw for unknown tokens.disconnectProvideris a no-op whengithub_token_encryptedis already null.#1146 — Sustained-throughput backpressure integration test for log streaming
Problem:
tests/logs/log-streaming.integration.test.tsonly tested a mockMockSSEStream— it never exercised the realLogStreamBufferorDeploymentLogBatcherunder load, and did not drivependingFlushespastMAX_PENDING_BATCHES.Added tests in a new
describeblock at the end of the same file using the real classes backed by a slow Supabase stub (configurable insert delay):LogStreamBufferpending size stays withincapacityduring a 200-event burst.drain()correctly clears pending entries and populates history.DeploymentLogBatcher.pendingFlushesnever exceedsMAX_PENDING_BATCHES(10) under a 75-entry burst against a 200ms-delayed Supabase mock.hasOverflow()/consumeDropped()accurately track and reset the drop counter.replayFrom(seq)returns only events after the given sequence.#1147 — Audit and reconcile stacked rate-limit middlewares
Audit finding: No route in
apps/backend/src/app/apicurrently stacks bothwithTierRateLimitandwithRateLimit/checkRateLimiton the same path. Routes checked:auth/signin,auth/signup,auth/reset-password→withRateLimitonlydeployments/route→checkDeploymentRateLimit(own store, no conflict)payments/checkout→withAuthonlyerror-reports/route→withRateLimitonlyRisk documented:
withTierRateLimitinternally callscheckRateLimit()fromrate-limit.ts, so both middlewares share the same in-memory store. Double-wrapping the same route key with both would cause a rejection from the outer limiter to also consume a slot in the shared store, visible to the inner limiter.Changes:
tier-rate-limit.tsdocumenting the shared-store risk, the 2026-08-28 audit outcome, and the invariant future contributors must maintain.tests/rate-limit/stacked-middleware-quota.integration.test.tswith:withRateLimitroutes ∩withTierRateLimitroutes = ∅).withRateLimitand directcheckRateLimitsee the same counter for the same key).Testing
All new tests are isolated and use in-memory mocks — no network or DB required.
Checklist
Closes #1148
Closes #1146
Closes #1147