Skip to content

Provider permissions: history redaction on model switch #168

Description

@jeonghun-jj-lee

Important

Decision Surface

Problem: When switching from Model A (trusted) to Model B (limited), file contents already in the conversation history from directories denied by Model B's tier would leak to the new provider.

Approach: Implement redactHistory(messages, newModelId) — walks messages, checks each sourcePaths entry against the new model's tier, and replaces denied content with a placeholder at send-time. Does NOT mutate stored messages (filters a copy).

Scope: Redaction logic + integration at the model-switch point. Requires slices #2 (resolution) and #3 (source-path tagging).


Acceptance Criteria

  • redactHistory(messages, modelId) returns a filtered copy of messages with denied content replaced
  • Replacement text is: [Content from {path} filtered — trust tier "{tierLabel}" does not have read access]
  • Messages with no sourcePaths metadata are passed through unchanged (not redacted)
  • Messages with sourcePaths in allowed directories are passed through unchanged
  • The stored message history is NEVER mutated — redaction produces a new array for the API call
  • If the model switches back to the original (trusted) model, the original content is visible again (because stored messages are untouched)
  • Redaction is called automatically when the LLM runner detects a provider/model change
  • Multiple sourcePaths in one message: redact only the portions from denied paths (if the message contains content from both allowed and denied dirs, keep the allowed portions)

Key Decisions

# Decision Rationale
1 Non-mutating filter (copy on send) Switching back to a trusted model should restore visibility; also preserves audit trail
2 Per-sourcePath granularity A single tool result might reference multiple files; redact only the denied ones
3 Placeholder names the tier User/debugging visibility into why content disappeared

Testing Decisions

Constraints & Invariants

  • Redaction must be fast enough for large histories (linear scan, no re-resolution of already-computed tier lookups within one call)
  • A message whose content is fully redacted still appears in history (as the placeholder) — never dropped entirely

Source

Part of #163
Blocked by #165, #166

Metadata

Metadata

Assignees

Labels

afkImplement + merge unattended

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions