Skip to content

🐛 fix: eliminate race condition in ISO 27001 parallel cluster audit (#3968)#3985

Merged
clubanderson merged 1 commit intomainfrom
fix/iso27001-race-condition
Mar 31, 2026
Merged

🐛 fix: eliminate race condition in ISO 27001 parallel cluster audit (#3968)#3985
clubanderson merged 1 commit intomainfrom
fix/iso27001-race-condition

Conversation

@clubanderson
Copy link
Copy Markdown
Collaborator

Summary

  • Fixes shared mutable array (accumulated) being mutated concurrently from parallel cluster tasks in fetchISO27001AuditViaKubectl
  • Each parallel task now returns its own findings array independently
  • Final results are collected from settled promises via flatMap, eliminating interleaved push corruption
  • Progressive onProgress updates still work by flattening all completed results so far

Test plan

  • Connect 5+ clusters via kc-agent
  • Open the ISO 27001 audit card
  • Verify findings count is consistent across page reloads
  • Verify progressive loading still shows partial results as clusters complete

Closes #3968

…3968)

Replace shared mutable `accumulated` array with per-task return values.
Each parallel task now returns its own findings array independently.
Results are collected from settled promises via flatMap after all tasks
complete, eliminating the possibility of interleaved push operations
corrupting the array when cluster tasks resolve concurrently.

Closes #3968

Signed-off-by: Andrew Anderson <andy@clubanderson.com>
Copilot AI review requested due to automatic review settings March 31, 2026 14:12
@kubestellar-prow kubestellar-prow bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Mar 31, 2026
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 31, 2026

Deploy Preview for kubestellarconsole ready!

Name Link
🔨 Latest commit cb0343e
🔍 Latest deploy log https://app.netlify.com/projects/kubestellarconsole/deploys/69cbd635d0867c0008122ee5
😎 Deploy Preview https://deploy-preview-3985.console-deploy-preview.kubestellar.io
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@kubestellar-prow
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign clubanderson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubestellar-prow kubestellar-prow bot added the size/S Denotes a PR that changes 10-29 lines, ignoring generated files. label Mar 31, 2026
@clubanderson clubanderson merged commit 160cdcc into main Mar 31, 2026
19 of 20 checks passed
@kubestellar-prow kubestellar-prow bot deleted the fix/iso27001-race-condition branch March 31, 2026 14:12
@github-actions
Copy link
Copy Markdown
Contributor

👋 Hey @clubanderson — thanks for opening this PR!

🤖 This project is developed exclusively using AI coding assistants.

Please do not attempt to code anything for this project manually.
All contributions should be authored using an AI coding tool such as:

This ensures consistency in code style, architecture patterns, test coverage,
and commit quality across the entire codebase.


This is an automated message.

@github-actions
Copy link
Copy Markdown
Contributor

Thank you for your contribution! Your PR has been merged.

Check out what's new:

Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a concurrency-related correctness issue in the ISO 27001 audit fetcher by removing shared accumulation of findings across parallel cluster tasks.

Changes:

  • Refactors fetchISO27001AuditViaKubectl so each parallel cluster task returns its own ISO27001Finding[] rather than mutating a shared accumulated array.
  • Collects final findings by flattening fulfilled results from settledWithConcurrency.
  • Keeps progressive onProgress updates by aggregating completed cluster results.

Comment on lines +268 to +269
// Each task returns its own findings array to avoid shared-state mutation.
// Progressive updates are built by collecting all fulfilled results so far.
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says this avoids shared-state mutation, but completed is still shared mutable state that every parallel task mutates via completed.push(...). Either update the comment to match what the code is actually doing, or switch to an immutable accumulator approach for progress (e.g., reassign a partial array with concat / spread into a new array each time) so there’s no shared in-place mutation at all.

Suggested change
// Each task returns its own findings array to avoid shared-state mutation.
// Progressive updates are built by collecting all fulfilled results so far.
// Each task returns its own findings array; we accumulate results in a shared
// `completed` array and build progressive updates by collecting all fulfilled
// results so far.

Copilot uses AI. Check for mistakes.
Comment on lines 276 to 279
const clusterFindings = await runISO27001ChecksForCluster(name, context || name)
accumulated.push(...clusterFindings)
onProgress?.([...accumulated])
completed.push(clusterFindings)
onProgress?.(completed.flat())
return clusterFindings
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onProgress?.(completed.flat()) emits findings in completion order (because of completed.push(...)), but the final return value is flattened in cluster/task order via settledWithConcurrency’s indexed results. That means the UI can reorder/shuffle findings when the final result replaces the progressive data. Consider storing per-task results by index (e.g., completed[idx] = clusterFindings) and building progress by flattening indices in order, so progressive updates and the final payload have consistent ordering.

Copilot uses AI. Check for mistakes.
@clubanderson
Copy link
Copy Markdown
Collaborator Author

🔄 Auto-Applying Copilot Code Review

Copilot code review found 1 code suggestion(s) and 1 general comment(s).

@copilot Please apply all of the following code review suggestions:

  • web/src/hooks/useCachedISO27001.ts (line 269): // Each task returns its own findings array; we accumulate results in a shared ...

Also address these general comments:

  • web/src/hooks/useCachedISO27001.ts (line 279): onProgress?.(completed.flat()) emits findings in completion order (because of completed.push(...)), but the final

Push all fixes in a single commit. Run cd web && npm run build && npm run lint before committing.


Auto-generated by copilot-review-apply workflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ISO 27001: accumulated array mutated concurrently from parallel cluster tasks — race condition

3 participants