Skip to content

feat: add actor model to SecretManager for redaction map thread safety#354

Merged
ahmedhesham6 merged 10 commits intostakpak:betafrom
abd0-omar:actor-model
Jan 5, 2026
Merged

feat: add actor model to SecretManager for redaction map thread safety#354
ahmedhesham6 merged 10 commits intostakpak:betafrom
abd0-omar:actor-model

Conversation

@abd0-omar
Copy link
Contributor

  • the pr was made to resolve this todo comment
    // TODO: this is not thread safe, we need to use a mutex or an actor to protect the redaction map
  • all secret operations are now async with message passing
  • added benchmarks that showed the actor model was slightly slower but was thread safe

Converted SecretManager to an actor-based architecture for improved
thread-safety with benchmarks
Copy link
Collaborator

@ahmedhesham6 ahmedhesham6 left a comment

Choose a reason for hiding this comment

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

The actor model implementation is solid and correctly addresses the thread safety concern. Good use of Tokio channels, spawn_blocking for file I/O, and lazy loading of gitleaks config.

Suggestions

1. Unused fields in SecretManagerHandle

redact_secrets and privacy_mode fields are stored but never used. Consider either:

  • Removing them
  • Using them for fast-path checks before sending messages (e.g., skip sending if !redact_secrets)
// Example fast-path optimization:
pub async fn redact_and_store_secrets(&self, content: &str, path: Option<&str>) -> Result<String, SecretManagerError> {
    if !self.redact_secrets {
        return Ok(content.to_string());
    }
    // ... send message
}

2. File I/O on every save

save_session_redaction_map().await is called on every redaction operation. For frequent operations, this could be a performance bottleneck.

Consider:

  • Debouncing saves (e.g., save at most once per second)
  • Batching saves (save after N operations or on shutdown)
  • Only saving when new secrets are actually added:
let old_len = self.redaction_map.len();
self.redaction_map.extend(redaction_result.redaction_map);
if self.redaction_map.len() > old_len {
    self.save_session_redaction_map().await;
}

3. Error handling context

Consider adding more context to error messages to aid debugging:

// Current
.map_err(|e| McpError::internal_error(e.to_string(), None))?;

// Suggested
.map_err(|e| McpError::internal_error(format!("Failed to redact command output: {}", e), None))?;

4. Potential backpressure in format_tasks_table

This function is called from within task progress reporting loops. If the secret manager channel is full (capacity 100), the .await could cause backpressure on progress reporting.

Not a blocker, but worth monitoring. If issues arise, consider using try_send with fallback to unredacted output.


Thanks for the thorough work on this! Can you please resolve the merge conflicts?

@abd0-omar
Copy link
Contributor Author

Thanks for the detailed review I appreciate it! @ahmedhesham6

  • Fast-path optimization: Removed unused fields in SecretManagerHandle and applied the suggested fast-path check in 9624cb0.

  • Optimized File I/O: In a648bfd and 448df71, it only now saves if the redaction_map has actually grown. I also refactored redact_secrets to return only the new mappings as the caller use extend to merge the old map and the new one.

  • Improved Error Context: Added more descriptive context to error messages in e48ed57.

  • Backpressure Handling: In 805368d It now falls back to unredacted output if the channel is full.

@ahmedhesham6 ahmedhesham6 changed the base branch from main to beta January 4, 2026 01:02
@ahmedhesham6
Copy link
Collaborator

@abd0-omar Can you sync with beta branch?

@abd0-omar
Copy link
Contributor Author

@ahmedhesham6 I've merged branch beta to the current branch

@ahmedhesham6 ahmedhesham6 merged commit 4cd922e into stakpak:beta Jan 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants