Bug and security fixes - #2
Open
DylanBeMe wants to merge 5 commits into
Open
Conversation
added 5 commits
August 6, 2026 19:57
…bile navigation. Added optimistic theme/accent updates with rollback and race protection. Standardized the demo-mode banner across desktop and mobile. Hardened logout handling against failed and duplicate requests. Fixed investigation polling races that could miss completed reports or show stale data. Added request timeouts to S3 and Azure backup operations. Fixed S3 and Azure backup-retention pagination beyond provider result limits. Added safe XML entity decoding for cloud object names and continuation tokens. Improved chat hydration dependencies and unsupported AI-task handling. Made the global critical-error screen respect light and dark system themes. Added regression tests for backup pagination and XML parsing.
…lability findings: - Shared PostgreSQL-backed login throttling with bounded cleanup and successful-login reset. - Streaming backup upload limits, bounded decompression, row ceilings, batched inserts, and non-blocking crypto/decompression. - Indexed webhook lookup with transactional synchronization and shared rate limiting. - Aggregated workflow scheduler queries with bounded concurrency. - Bounded inventory processing across dashboards, topology maps, access maps, security analysis, MCP output, and integration matching. - Database-ranked storage utilization instead of loading every storage pool. - Consistent oversized-dataset states on desktop and mobile. - Hook dependency suppressions removed. - Concurrent backup-retention cleanup. - Nonce-based production CSP with unsafe-eval limited to development. After applying the patch, deploy the migration: `npx prisma migrate deploy` `npx prisma generate`
ORIGINAL CORRECTNESS / UX / RELIABILITY FINDINGS - Theme mode persistence could diverge between Settings, the desktop top bar, the mobile More sheet, local storage/cookies, and the persisted user profile; rapid changes could race: Fix: Added one shared persisted-theme hook with immediate preview, in-flight protection, persistence, disabled states while saving, and rollback when saving fails. - Accent-color persistence had the same race/rollback problem as theme mode: Fix: Added the same guarded optimistic-save and rollback behavior for accent-color changes. - Desktop and mobile demo-mode banners duplicated behavior, copy, and styling and used a fixed violet treatment that did not follow the selected accent theme: Fix: Replaced the duplicated banners with one shared DemoModeBanner using semantic theme tokens, shared copy/spacing/icon behavior, and consistent status semantics. - Logout navigated to /login even when the server failed to invalidate the session, making a failed logout look successful; duplicate submissions were also possible: Fix: Logout now checks the API result, guards against duplicate submissions, reports failures, and navigates only after successful session invalidation. - Investigation polling could remain stale because polling behavior was effectively tied to ticket-ID changes instead of all relevant persisted investigation state: Fix: Reworked the polling state/ref guards so a newly started or externally updated investigation re-engages correctly without relying on a suppressed dependency. - Investigation polling could use an older React Query report after another client started a new run, producing stale UI/notifications: Fix: Seed the query cache from the newly persisted ticket state before polling the new run. - Investigation completion could be consumed when SUCCESS arrived before the report payload, causing the completion callback/list invalidation to be missed: Fix: Completion is emitted only when both success state and report are present, so the callback and invalidation cannot be lost. - Opening an already completed investigation could incorrectly behave like a newly completed run and create a false completion notification: Fix: Added completion-edge tracking so already-completed tickets do not emit a new completion event merely because they were opened. - S3 backup upload/list/delete operations had no request timeout and could hang indefinitely on a degraded endpoint: Fix: Added bounded provider request timeouts, cache bypassing, and readable provider-specific timeout failures; uploads get a longer ceiling than metadata operations. - Azure Blob backup upload/list/delete operations had no request timeout and could hang indefinitely on a degraded endpoint: Fix: Added the same bounded provider request timeout handling and cache bypassing for Azure Blob operations. - S3 retention only processed the first ListObjectsV2 page, so old backups beyond the provider page limit could be silently ignored: Fix: Follow S3 continuation tokens until the listing is complete, with safety checks for missing/repeated continuation values. - Azure Blob retention only processed the first listing page, so old backups beyond the provider page limit could be silently ignored: Fix: Follow Azure NextMarker pagination until completion, with loop-safety checks. - Escaped XML entities in S3/Azure object names and continuation values were used without decoding, so retention could address the wrong key or fail deletion: Fix: Added shared XML decoding helpers and use decoded object/blob names and continuation values before subsequent requests/deletes. - Backup retention deleted old cloud objects strictly sequentially, making large cleanup backlogs unnecessarily slow: Fix: Added bounded concurrent deletion while keeping cleanup best-effort and avoiding unbounded request bursts. - Unsupported AI prompt task values had no runtime-safe default path and could fall through unexpectedly: Fix: Added an explicit default error for unsupported AI prompt tasks. - Chat hydration relied on a hook dependency suppression instead of declaring the stable dependency, making stale behavior easier to introduce: Fix: Removed the suppression and declared the stable dependency explicitly. - The root critical-error page mixed a light page treatment with a permanently dark action button and did not coherently follow system light/dark appearance: Fix: Updated the critical-error surface to follow the operating-system color scheme coherently. - Two edit-form effects suppressed react-hooks/exhaustive-deps to avoid overwriting drafts, leaving correctness dependent on lint suppression: Fix: Replaced the suppressions with ID-based ref guards that preserve the intended “reset only when the selected record changes” behavior. SECURITY / RESOURCE-BOUNDARY FINDINGS - The login endpoint had no throttling or backoff, allowing brute-force attempts and CPU exhaustion through intentionally expensive password verification: Fix: Added PostgreSQL-backed account and trusted-client-IP fixed-window rate limits shared across replicas, with successful-login reset and bounded expiry cleanup. - Client IP headers could be forged if blindly trusted for login limiting: Fix: Forwarded client-IP headers are used only when TRUST_PROXY_HEADERS=true, and values are validated as IP addresses; account limiting remains active otherwise. - A first version of the login limiter added a shared global bucket that one attacker could exhaust to deny login to every valid user: Fix: Removed the global lockout bucket; valid accounts have independent buckets and unknown usernames share one bounded bucket so arbitrary names cannot grow limiter state unboundedly. - Rate-limit expiry cleanup could select an expired row and then delete it after a concurrent request had refreshed the same bucket, erasing a fresh limit window: Fix: The DELETE predicate now rechecks expiresAt at deletion time, preventing cleanup from deleting concurrently refreshed buckets. - Backup import read the complete request into memory without a strict upload ceiling, allowing oversized/chunked uploads to consume excessive memory: Fix: Added incremental bounded request-body reading, a 64 MiB backup-file ceiling, and bounded multipart overhead before form parsing. - Multipart backup parsing could otherwise occur before a trustworthy raw-byte ceiling was enforced, allowing chunked multipart requests to grow beyond intended limits: Fix: Read and bound the raw request stream first, then parse multipart from the already-bounded buffer. - Backup decompression had no explicit expanded-size ceiling, allowing highly compressible input to expand into excessive memory use: Fix: Added a 256 MiB decompressed-data ceiling and bounded decompression checks. - The compressed-backup size ceiling originally existed only at the HTTP route, so alternate/internal decode callers could bypass it: Fix: Enforced the compressed-size ceiling again at the backup decode boundary and added regression coverage. - Backup import had no per-model or aggregate row ceilings, allowing pathological archives to trigger excessive validation/database work: Fix: Added per-model and total-row limits before destructive restore begins. - Backup restore wrote potentially very large model sets without batching: Fix: Added batched database inserts to bound restore memory/work-unit size. - Backup restore performed expensive scrypt/gzip work synchronously on the request path, risking event-loop stalls: Fix: Moved HTTP restore password derivation and gzip/decompression work to asynchronous Node APIs. - Backup archive validation did not cleanly separate manifest, model-row, and aggregate-data validation, making boundary rules harder to enforce and pushing complexity over the quality gate: Fix: Split validation into cohesive manifest/model/aggregate responsibilities and kept the orchestration function under the repository complexity threshold without suppressions. - Backup restore accepted an encrypted-backup password through a request header path, increasing the chance of credentials appearing in intermediary/request-header logging: Fix: Removed backup-password header handling; encrypted restore passwords are accepted through multipart form data. - Malformed backup rows and duplicate workflow webhook tokens could reach destructive restore work before being rejected: Fix: Added malformed-row and duplicate-webhook-token validation before destructive restore begins. - Derived webhook indexes and rate-limit state could be stale after a full backup restore: Fix: Restore now rebuilds the derived webhook index and clears derived rate-limit state. - Instance reset/reinstall paths did not initially include the new derived rate-limit/webhook-index tables introduced by the hardening work: Fix: Updated reset/reinstall cleanup and its tests to include the derived tables. - Production CSP allowed unsafe-inline scripts and unsafe-eval, increasing XSS impact: Fix: Moved CSP generation into middleware with a per-request nonce and strict-dynamic; unsafe-eval is development-only, and object/frame/base/form restrictions remain explicit. Inline styles remain allowed where required by the framework. WORKFLOW / WEBHOOK FINDINGS - Public webhook-token lookup loaded every enabled workflow and inspected JSON graphs for every webhook request: Fix: Added a materialized WorkflowWebhook table with indexed token lookup. - Workflow create/update operations could leave the materialized webhook lookup stale if the index was not synchronized with graph changes: Fix: Workflow saves maintain the webhook index transactionally with the workflow change. - The public webhook rate limit was process-local, so multiple app replicas could each allow their own independent request quota: Fix: Moved webhook limiting to the shared PostgreSQL-backed rate limiter. - The webhook-index migration could fail unpredictably on legacy graphs containing duplicate tokens, duplicate node IDs, blank IDs, or blank tokens that had previously been tolerated: Fix: Made migration backfill deterministic, ignores blank webhook IDs/tokens, preserves one deterministic row for legacy duplicates, and uses conflict handling so migration does not abort on ambiguous old data. - The workflow scheduler issued a latest-run lookup per workflow, creating an N+1 query pattern: Fix: Replaced per-workflow latest-run queries with one grouped query used for the scheduler pass. - The workflow scheduler evaluated enabled workflows strictly sequentially, causing scheduler latency to grow linearly with independent workflows: Fix: Added bounded workflow-processing concurrency with configurable clamped concurrency. - Scheduler and backup-retention code independently reimplemented the same worker-pool/concurrency loop, creating a DRY maintenance risk: Fix: Consolidated the behavior into a shared bounded-concurrency helper while preserving caller-specific error handling. INVENTORY / TOPOLOGY / DASHBOARD SCALE FINDINGS - Cloudflare inventory matching scanned complete device/VM/container inventories even when only a small set of integration identities was relevant: Fix: Added targeted normalized identity lookups and functional indexes so only matching active inventory rows are fetched. - Tailscale inventory matching scanned complete device/VM/container inventories even when only a small set of integration identities was relevant: Fix: Reused the targeted normalized identity lookup/index path for Tailscale matching. - The SQL functional inventory indexes initially used predicates/normalization that did not exactly match the application query semantics, including enum/text predicate handling and surrounding whitespace: Fix: Changed partial-index predicates to direct enum-compatible comparisons and aligned SQL normalization with application normalization using trim/case/first-label handling. - Large topology inputs loaded complete inventory/network/firewall/address/interface/lease/neighbor/tunnel/provider datasets with no explicit processing budget: Fix: Added explicit per-dataset budgets using limit+1 reads and a DatasetBudgetExceededError instead of unbounded processing. - Secondary topology inbound-vector/provider-snapshot loaders remained unbounded after the first scale pass, leaving a back door around the new topology budgets: Fix: Added budgets/bounded reads to those secondary paths as well so the whole topology load path is covered. - Access-map construction could process unbounded source datasets and become expensive or unstable as inventory grew: Fix: Added explicit data budgets and coherent oversized-state handling for the access-map path. - Security-advisor snapshot collection loaded large complete tables without explicit ceilings: Fix: Added explicit budgets for firewall rules, port forwards, DNS/tunnel/wireless data, machines, SSH deployments, and services. - Integration synchronization/provider snapshot paths could process complete datasets with no explicit budget: Fix: Added bounded provider/synchronization datasets and explicit failure when processing budgets are exceeded rather than silently consuming unbounded resources. - MCP overview generation loaded/output complete inventories, networks, guests, and integration lists, creating potentially huge responses: Fix: Use exact aggregate counts plus bounded representative rows/guests/integrations with explicit “showing N of M” messaging. - The main dashboard loaded every integration card even when only a bounded overview is useful: Fix: Limit dashboard integration cards, separately query the exact integration count, and display a visible “showing N of M” message. - The main dashboard loaded every qualifying storage pool and ranked them in application memory: Fix: Rank utilization in PostgreSQL and fetch only the six fullest pools. - Oversized topology/access-map data could otherwise produce an incomplete or misleading graph when naive truncation was used: Fix: Derived graph views fail closed with a clear paused/oversized state while exact inventory counts remain available; they do not silently render partial topology as complete evidence. - The dashboard topology fallback initially caught unexpected errors as though they were normal dataset-budget overflows, masking real failures: Fix: Catch only DatasetBudgetExceededError; all unrelated exceptions now propagate through normal error handling. CODE-QUALITY FINDINGS FOUND WHILE ENFORCING THE REPOSITORY SKILL - The backup import API route accumulated transport parsing, multipart handling, option parsing, decode/error translation, and restore orchestration in one complex function: Fix: Split those responsibilities into cohesive named helpers while preserving behavior and keeping complexity within the repository’s maximum of 15. - The Cloudflare sync path accumulated documented-service matching and stale-service reconciliation in one overly complex flow: Fix: Separated service matching and stale-service reconciliation into named responsibilities instead of suppressing or gaming the complexity metric. - The mobile dashboard component exceeded/pressed the repository complexity budget as scale-state behavior was added: Fix: Refactored cohesive presentation/state responsibilities into helpers/components while preserving the same UI behavior. - The topology data loader exceeded/pressed the repository complexity budget as dataset-budget handling expanded: Fix: Refactored cohesive data-loading/normalization responsibilities without one-line metric-hiding wrappers. - Shared concurrency tests were coupled to the workflow scheduler through a test-only re-export instead of testing the abstraction at its actual module boundary: Fix: Moved bounded-concurrency tests next to src/lib/concurrency.ts and removed the scheduler’s test-only re-export/API leakage. DELIVERY / PATCHING ERROR CORRECTED IN THIS HANDOFF
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.
ORIGINAL CORRECTNESS / UX / RELIABILITY FINDINGS
Theme mode persistence could diverge between Settings, the desktop top bar, the mobile More sheet, local storage/cookies, and the persisted user profile; rapid changes could race:
Fix: Added one shared persisted-theme hook with immediate preview, in-flight protection, persistence, disabled states while saving, and rollback when saving fails.
Accent-color persistence had the same race/rollback problem as theme mode:
Fix: Added the same guarded optimistic-save and rollback behavior for accent-color changes.
Desktop and mobile demo-mode banners duplicated behavior, copy, and styling and used a fixed violet treatment that did not follow the selected accent theme:
Fix: Replaced the duplicated banners with one shared DemoModeBanner using semantic theme tokens, shared copy/spacing/icon behavior, and consistent status semantics.
Logout navigated to /login even when the server failed to invalidate the session, making a failed logout look successful; duplicate submissions were also possible:
Fix: Logout now checks the API result, guards against duplicate submissions, reports failures, and navigates only after successful session invalidation.
Investigation polling could remain stale because polling behavior was effectively tied to ticket-ID changes instead of all relevant persisted investigation state:
Fix: Reworked the polling state/ref guards so a newly started or externally updated investigation re-engages correctly without relying on a suppressed dependency.
Investigation polling could use an older React Query report after another client started a new run, producing stale UI/notifications:
Fix: Seed the query cache from the newly persisted ticket state before polling the new run.
Investigation completion could be consumed when SUCCESS arrived before the report payload, causing the completion callback/list invalidation to be missed:
Fix: Completion is emitted only when both success state and report are present, so the callback and invalidation cannot be lost.
Opening an already completed investigation could incorrectly behave like a newly completed run and create a false completion notification:
Fix: Added completion-edge tracking so already-completed tickets do not emit a new completion event merely because they were opened.
S3 backup upload/list/delete operations had no request timeout and could hang indefinitely on a degraded endpoint:
Fix: Added bounded provider request timeouts, cache bypassing, and readable provider-specific timeout failures; uploads get a longer ceiling than metadata operations.
Azure Blob backup upload/list/delete operations had no request timeout and could hang indefinitely on a degraded endpoint:
Fix: Added the same bounded provider request timeout handling and cache bypassing for Azure Blob operations.
S3 retention only processed the first ListObjectsV2 page, so old backups beyond the provider page limit could be silently ignored:
Fix: Follow S3 continuation tokens until the listing is complete, with safety checks for missing/repeated continuation values.
Azure Blob retention only processed the first listing page, so old backups beyond the provider page limit could be silently ignored:
Fix: Follow Azure NextMarker pagination until completion, with loop-safety checks.
Escaped XML entities in S3/Azure object names and continuation values were used without decoding, so retention could address the wrong key or fail deletion:
Fix: Added shared XML decoding helpers and use decoded object/blob names and continuation values before subsequent requests/deletes.
Backup retention deleted old cloud objects strictly sequentially, making large cleanup backlogs unnecessarily slow:
Fix: Added bounded concurrent deletion while keeping cleanup best-effort and avoiding unbounded request bursts.
Unsupported AI prompt task values had no runtime-safe default path and could fall through unexpectedly:
Fix: Added an explicit default error for unsupported AI prompt tasks.
Chat hydration relied on a hook dependency suppression instead of declaring the stable dependency, making stale behavior easier to introduce:
Fix: Removed the suppression and declared the stable dependency explicitly.
The root critical-error page mixed a light page treatment with a permanently dark action button and did not coherently follow system light/dark appearance:
Fix: Updated the critical-error surface to follow the operating-system color scheme coherently.
Two edit-form effects suppressed react-hooks/exhaustive-deps to avoid overwriting drafts, leaving correctness dependent on lint suppression:
Fix: Replaced the suppressions with ID-based ref guards that preserve the intended “reset only when the selected record changes” behavior.
SECURITY / RESOURCE-BOUNDARY FINDINGS
The login endpoint had no throttling or backoff, allowing brute-force attempts and CPU exhaustion through intentionally expensive password verification:
Fix: Added PostgreSQL-backed account and trusted-client-IP fixed-window rate limits shared across replicas, with successful-login reset and bounded expiry cleanup.
Client IP headers could be forged if blindly trusted for login limiting:
Fix: Forwarded client-IP headers are used only when TRUST_PROXY_HEADERS=true, and values are validated as IP addresses; account limiting remains active otherwise.
A first version of the login limiter added a shared global bucket that one attacker could exhaust to deny login to every valid user:
Fix: Removed the global lockout bucket; valid accounts have independent buckets and unknown usernames share one bounded bucket so arbitrary names cannot grow limiter state unboundedly.
Rate-limit expiry cleanup could select an expired row and then delete it after a concurrent request had refreshed the same bucket, erasing a fresh limit window:
Fix: The DELETE predicate now rechecks expiresAt at deletion time, preventing cleanup from deleting concurrently refreshed buckets.
Backup import read the complete request into memory without a strict upload ceiling, allowing oversized/chunked uploads to consume excessive memory:
Fix: Added incremental bounded request-body reading, a 64 MiB backup-file ceiling, and bounded multipart overhead before form parsing.
Multipart backup parsing could otherwise occur before a trustworthy raw-byte ceiling was enforced, allowing chunked multipart requests to grow beyond intended limits:
Fix: Read and bound the raw request stream first, then parse multipart from the already-bounded buffer.
Backup decompression had no explicit expanded-size ceiling, allowing highly compressible input to expand into excessive memory use:
Fix: Added a 256 MiB decompressed-data ceiling and bounded decompression checks.
The compressed-backup size ceiling originally existed only at the HTTP route, so alternate/internal decode callers could bypass it:
Fix: Enforced the compressed-size ceiling again at the backup decode boundary and added regression coverage.
Backup import had no per-model or aggregate row ceilings, allowing pathological archives to trigger excessive validation/database work:
Fix: Added per-model and total-row limits before destructive restore begins.
Backup restore wrote potentially very large model sets without batching:
Fix: Added batched database inserts to bound restore memory/work-unit size.
Backup restore performed expensive scrypt/gzip work synchronously on the request path, risking event-loop stalls:
Fix: Moved HTTP restore password derivation and gzip/decompression work to asynchronous Node APIs.
Backup archive validation did not cleanly separate manifest, model-row, and aggregate-data validation, making boundary rules harder to enforce and pushing complexity over the quality gate:
Fix: Split validation into cohesive manifest/model/aggregate responsibilities and kept the orchestration function under the repository complexity threshold without suppressions.
Backup restore accepted an encrypted-backup password through a request header path, increasing the chance of credentials appearing in intermediary/request-header logging:
Fix: Removed backup-password header handling; encrypted restore passwords are accepted through multipart form data.
Malformed backup rows and duplicate workflow webhook tokens could reach destructive restore work before being rejected:
Fix: Added malformed-row and duplicate-webhook-token validation before destructive restore begins.
Derived webhook indexes and rate-limit state could be stale after a full backup restore:
Fix: Restore now rebuilds the derived webhook index and clears derived rate-limit state.
Instance reset/reinstall paths did not initially include the new derived rate-limit/webhook-index tables introduced by the hardening work:
Fix: Updated reset/reinstall cleanup and its tests to include the derived tables.
Production CSP allowed unsafe-inline scripts and unsafe-eval, increasing XSS impact:
Fix: Moved CSP generation into middleware with a per-request nonce and strict-dynamic; unsafe-eval is development-only, and object/frame/base/form restrictions remain explicit. Inline styles remain allowed where required by the framework.
WORKFLOW / WEBHOOK FINDINGS
Public webhook-token lookup loaded every enabled workflow and inspected JSON graphs for every webhook request:
Fix: Added a materialized WorkflowWebhook table with indexed token lookup.
Workflow create/update operations could leave the materialized webhook lookup stale if the index was not synchronized with graph changes:
Fix: Workflow saves maintain the webhook index transactionally with the workflow change.
The public webhook rate limit was process-local, so multiple app replicas could each allow their own independent request quota:
Fix: Moved webhook limiting to the shared PostgreSQL-backed rate limiter.
The webhook-index migration could fail unpredictably on legacy graphs containing duplicate tokens, duplicate node IDs, blank IDs, or blank tokens that had previously been tolerated:
Fix: Made migration backfill deterministic, ignores blank webhook IDs/tokens, preserves one deterministic row for legacy duplicates, and uses conflict handling so migration does not abort on ambiguous old data.
The workflow scheduler issued a latest-run lookup per workflow, creating an N+1 query pattern:
Fix: Replaced per-workflow latest-run queries with one grouped query used for the scheduler pass.
The workflow scheduler evaluated enabled workflows strictly sequentially, causing scheduler latency to grow linearly with independent workflows:
Fix: Added bounded workflow-processing concurrency with configurable clamped concurrency.
Scheduler and backup-retention code independently reimplemented the same worker-pool/concurrency loop, creating a DRY maintenance risk:
Fix: Consolidated the behavior into a shared bounded-concurrency helper while preserving caller-specific error handling.
INVENTORY / TOPOLOGY / DASHBOARD SCALE FINDINGS
Cloudflare inventory matching scanned complete device/VM/container inventories even when only a small set of integration identities was relevant:
Fix: Added targeted normalized identity lookups and functional indexes so only matching active inventory rows are fetched.
Tailscale inventory matching scanned complete device/VM/container inventories even when only a small set of integration identities was relevant:
Fix: Reused the targeted normalized identity lookup/index path for Tailscale matching.
The SQL functional inventory indexes initially used predicates/normalization that did not exactly match the application query semantics, including enum/text predicate handling and surrounding whitespace:
Fix: Changed partial-index predicates to direct enum-compatible comparisons and aligned SQL normalization with application normalization using trim/case/first-label handling.
Large topology inputs loaded complete inventory/network/firewall/address/interface/lease/neighbor/tunnel/provider datasets with no explicit processing budget:
Fix: Added explicit per-dataset budgets using limit+1 reads and a DatasetBudgetExceededError instead of unbounded processing.
Secondary topology inbound-vector/provider-snapshot loaders remained unbounded after the first scale pass, leaving a back door around the new topology budgets:
Fix: Added budgets/bounded reads to those secondary paths as well so the whole topology load path is covered.
Access-map construction could process unbounded source datasets and become expensive or unstable as inventory grew:
Fix: Added explicit data budgets and coherent oversized-state handling for the access-map path.
Security-advisor snapshot collection loaded large complete tables without explicit ceilings:
Fix: Added explicit budgets for firewall rules, port forwards, DNS/tunnel/wireless data, machines, SSH deployments, and services.
Integration synchronization/provider snapshot paths could process complete datasets with no explicit budget:
Fix: Added bounded provider/synchronization datasets and explicit failure when processing budgets are exceeded rather than silently consuming unbounded resources.
MCP overview generation loaded/output complete inventories, networks, guests, and integration lists, creating potentially huge responses:
Fix: Use exact aggregate counts plus bounded representative rows/guests/integrations with explicit “showing N of M” messaging.
The main dashboard loaded every integration card even when only a bounded overview is useful:
Fix: Limit dashboard integration cards, separately query the exact integration count, and display a visible “showing N of M” message.
The main dashboard loaded every qualifying storage pool and ranked them in application memory:
Fix: Rank utilization in PostgreSQL and fetch only the six fullest pools.
Oversized topology/access-map data could otherwise produce an incomplete or misleading graph when naive truncation was used:
Fix: Derived graph views fail closed with a clear paused/oversized state while exact inventory counts remain available; they do not silently render partial topology as complete evidence.
The dashboard topology fallback initially caught unexpected errors as though they were normal dataset-budget overflows, masking real failures:
Fix: Catch only DatasetBudgetExceededError; all unrelated exceptions now propagate through normal error handling.
CODE-QUALITY FINDINGS FOUND WHILE ENFORCING THE REPOSITORY SKILL
The backup import API route accumulated transport parsing, multipart handling, option parsing, decode/error translation, and restore orchestration in one complex function:
Fix: Split those responsibilities into cohesive named helpers while preserving behavior and keeping complexity within the repository’s maximum of 15.
The Cloudflare sync path accumulated documented-service matching and stale-service reconciliation in one overly complex flow:
Fix: Separated service matching and stale-service reconciliation into named responsibilities instead of suppressing or gaming the complexity metric.
The mobile dashboard component exceeded/pressed the repository complexity budget as scale-state behavior was added:
Fix: Refactored cohesive presentation/state responsibilities into helpers/components while preserving the same UI behavior.
The topology data loader exceeded/pressed the repository complexity budget as dataset-budget handling expanded:
Fix: Refactored cohesive data-loading/normalization responsibilities without one-line metric-hiding wrappers.
Shared concurrency tests were coupled to the workflow scheduler through a test-only re-export instead of testing the abstraction at its actual module boundary:
Fix: Moved bounded-concurrency tests next to src/lib/concurrency.ts and removed the scheduler’s test-only re-export/API leakage.