Skip to content

feat(logs): redact PII from workflow logs via configurable rules#5136

Merged
TheodoreSpeaks merged 13 commits into
stagingfrom
feat/redact-pii-workflow-log
Jun 19, 2026
Merged

feat(logs): redact PII from workflow logs via configurable rules#5136
TheodoreSpeaks merged 13 commits into
stagingfrom
feat/redact-pii-workflow-log

Conversation

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator

Summary

  • Adds enterprise PII redaction for workflow execution logs, configured under Data Retention as org-scoped rules — each rule selects which PII entity types to mask and which workspaces it applies to (empty workspaces = all; empty entity types = redact nothing).
  • Reuses the guardrails Microsoft Presidio engine in mask mode, applied at the single log-persist choke point (completeWorkflowExecution), covering both the inline and externalized write paths.
  • Redaction is byte-budgeted/chunked (one batched subprocess per persist, not per block), structure-preserving (masks string leaves, rebuilds via structuredClone), and fail-safe (scrubs rather than leaks on error).
  • Adds a check-digit-validated VIN recognizer so it won't false-match arbitrary 17-char codes.
  • Adds per-workspace data-retention-hours overrides (resolved workspace ?? org ?? plan default) via a new nullable workspace.data_retention_settings column.
  • UI mirrors Access Control: a rules list + ChipModal (grouped checkbox grid for entity types, workspace multiselect), persisting on save with an unsaved-changes guard.

Type of Change

  • New feature

Testing

  • Unit tests for the redaction transform (recursion, batched substitution, structure preservation, fail-safe scrub, oversized-string skip) — passing.
  • Verified Presidio masking end-to-end locally (email/phone/credit-card/VIN), incl. VIN check-digit precision (valid VINs masked, random 17-char tokens left alone).
  • bun run lint, bun run check:api-validation:strict, and bun run check:migrations origin/staging all pass. Migration is a single additive nullable column (expand-phase, backward-compatible).

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Enterprise PII redaction for workflow execution logs, configured under
Data Retention as org-scoped rules (each rule picks entity types + which
workspaces it applies to). Reuses the guardrails Presidio engine in mask
mode at the log-persist choke point, with a check-digit-validated VIN
recognizer. Also adds per-workspace data-retention-hours overrides.
@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 19, 2026 9:05pm

Request Review

@cursor

cursor Bot commented Jun 19, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Changes sit on the workflow log persist path and handle sensitive data; incorrect masking or fail-open behavior could leak PII, while fail-safe scrubbing could hide debug content on Presidio outages.

Overview
Enterprise PII redaction is wired end-to-end: org dataRetentionSettings now includes piiRedaction rules (default for all workspaces plus optional per-workspace overrides), validated via new Zod schemas and persisted through the data-retention API.

The Data Retention settings page gains a PII Redaction section—modals with a searchable Presidio entity picker, immediate saves for rules, and unsaved-changes handling—while retention-hour saves stay separate. Form hydration is keyed to the active org so switches do not cross-save.

At log completion, completeWorkflowExecution resolves the effective rule for the workspace and runs structure-preserving masking over trace spans, outputs, inputs, errors, and related fields before inline or externalized storage. Masking batches string leaves through Presidio (byte-chunked subprocesses, shared VIN recognizer, stdin error handling); failures or oversized payloads replace text with [REDACTION_FAILED] instead of persisting raw PII. Policy resolution intentionally fail-safe (masks when rules exist rather than skipping on flaky enterprise checks).

Supporting pieces: shared client-safe PII entity catalog, resolveEffectivePiiRedaction, and unit tests for resolution and redaction behavior.

Reviewed by Cursor Bugbot for commit ad7d1fa. Bugbot is set up for automated code reviews on this repo. Configure here.

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

Comment thread apps/sim/lib/logs/execution/logger.ts
Comment thread apps/sim/lib/logs/execution/pii-redaction.ts
…rkflow-log

# Conflicts:
#	packages/db/migrations/meta/0241_snapshot.json
#	packages/db/migrations/meta/_journal.json
#	scripts/check-api-validation-contracts.ts
Comment thread apps/sim/lib/billing/retention.ts Outdated
Comment thread apps/sim/lib/logs/execution/logger.ts Outdated
@greptile-apps

greptile-apps Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds enterprise-grade PII redaction for workflow execution logs, applied at the single completeWorkflowExecution choke point in logger.ts. Redaction is driven by org-scoped rules stored in organization.dataRetentionSettings, resolved per-workspace using a most-specific-wins policy, and executed via a batched Microsoft Presidio subprocess with a fail-safe scrub path that replaces all strings on error rather than persisting potentially sensitive data.

  • Redaction engine (pii-redaction.ts): Two-pass collect-then-substitute walk over traceSpans, finalOutput, workflowInput, and related fields; single batched (byte-chunked) Presidio call per log persist; scrubs all strings with [REDACTION_FAILED] on timeout, Presidio error, or when the 16 MB budget is exceeded.
  • VIN recognizer (validate_pii.py): Custom PatternRecognizer with ISO 3779 check-digit validation, making it precise enough to skip arbitrary 17-char codes (request IDs, SKUs).
  • Settings UI (data-retention-settings.tsx): Rules list with a ChipModal grouped-checkbox picker for entity types and a workspace multi-select; each save persists immediately via the data-retention route; unsaved-changes guard on modal close.

Confidence Score: 4/5

Safe to merge after addressing the orphaned-override visibility bug in the settings UI.

The redaction engine, Presidio integration, VIN recognizer, and API contract changes are all solid. The one concrete defect is in the settings UI: deleting the default (all-workspaces) rule while per-workspace override rules exist removes those overrides from view entirely — they stay active in the database and keep redacting PII, but an admin has no way to see, edit, or delete them without first re-adding a default rule. This creates a control-plane blind spot for enterprise privacy configuration that should be fixed before shipping.

apps/sim/ee/data-retention/components/data-retention-settings.tsx — the Workspace overrides section gating logic needs attention.

Important Files Changed

Filename Overview
apps/sim/lib/logs/execution/pii-redaction.ts New module for structure-preserving PII redaction across execution payloads. Two-pass approach (collect → batch mask → substitute) is correct and deterministic. Fail-safe scrub path works as intended. Tests cover key scenarios including fail-safe and large-string masking.
apps/sim/lib/logs/execution/logger.ts Adds applyPiiRedaction to the completion hot path. DB query for org settings on every execution is acknowledged in the code; error handling for the DB lookup (noted in prior threads) remains absent.
apps/sim/lib/billing/retention.ts Correct most-specific-wins resolution. Empty entityTypes on a workspace-specific rule correctly maps to enabled: false (exemption), matching the schema.ts JSDoc updated in this PR. Well-tested.
apps/sim/lib/guardrails/validate_pii.ts Adds maskPIIBatch (byte-chunked sequential subprocess calls) and the shared runPythonScript helper. EPIPE guard on python.stdin correctly funnels the error into the promise. Chunking logic handles oversized individual texts correctly.
apps/sim/lib/guardrails/validate_pii.py Adds mask_batch (reuses one engine pair per subprocess), VinRecognizer with ISO 3779 check-digit validation, and build_analyzer. VIN transliteration table and weight vector match the standard algorithm. Error propagation through main()'s outer try/except is intact.
apps/sim/ee/data-retention/components/data-retention-settings.tsx Adds PII rules UI (default rule + workspace overrides). Contains a P1 bug: the Workspace overrides section is gated on defaultRule being non-null, so deleting the default rule orphans existing override rules (invisible in UI but still active in DB).
packages/db/schema.ts Adds PiiRedactionRule and DataRetentionSettings interfaces; updates dataRetentionSettings column type to reference them. Additive/backward-compatible change with no migration breakage.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant E as ExecutionLogger
    participant DB as Database
    participant R as redactPIIFromExecution
    participant P as maskPIIBatch (validate_pii.ts)
    participant PY as validate_pii.py (Presidio)

    E->>DB: SELECT orgSettings FROM workspace LEFT JOIN organization
    DB-->>E: orgSettings (DataRetentionSettings)
    E->>E: resolveEffectivePiiRedaction(orgSettings, workspaceId)
    alt "enabled = false"
        E-->>E: return payload unchanged
    else "enabled = true"
        E->>R: redactPIIFromExecution(payload, entityTypes)
        R->>R: collect all eligible strings (two-pass walk)
        alt "totalBytes > 16 MB"
            R-->>R: scrub all strings with REDACTION_FAILED
        else within budget
            R->>P: maskPIIBatch(texts, entityTypes) chunked 256 KB each
            loop for each chunk
                P->>PY: spawn subprocess, write JSON to stdin
                PY-->>P: __SIM_RESULT__ passed results
            end
            P-->>R: masked string array
        end
        R->>R: substitute masked strings back into payload structure
        R-->>E: redacted RedactablePayload
    end
    E->>DB: INSERT/UPDATE workflowExecutionLogs (redacted data)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant E as ExecutionLogger
    participant DB as Database
    participant R as redactPIIFromExecution
    participant P as maskPIIBatch (validate_pii.ts)
    participant PY as validate_pii.py (Presidio)

    E->>DB: SELECT orgSettings FROM workspace LEFT JOIN organization
    DB-->>E: orgSettings (DataRetentionSettings)
    E->>E: resolveEffectivePiiRedaction(orgSettings, workspaceId)
    alt "enabled = false"
        E-->>E: return payload unchanged
    else "enabled = true"
        E->>R: redactPIIFromExecution(payload, entityTypes)
        R->>R: collect all eligible strings (two-pass walk)
        alt "totalBytes > 16 MB"
            R-->>R: scrub all strings with REDACTION_FAILED
        else within budget
            R->>P: maskPIIBatch(texts, entityTypes) chunked 256 KB each
            loop for each chunk
                P->>PY: spawn subprocess, write JSON to stdin
                PY-->>P: __SIM_RESULT__ passed results
            end
            P-->>R: masked string array
        end
        R->>R: substitute masked strings back into payload structure
        R-->>E: redacted RedactablePayload
    end
    E->>DB: INSERT/UPDATE workflowExecutionLogs (redacted data)
Loading

Reviews (11): Last reviewed commit: "fix(logs): re-hydrate data-retention for..." | Re-trigger Greptile

Comment thread apps/sim/lib/billing/retention.ts Outdated
Comment thread apps/sim/lib/logs/execution/pii-redaction.ts Outdated
Comment thread apps/sim/lib/logs/execution/logger.ts
@greptile-apps

greptile-apps Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds enterprise-grade PII redaction for workflow execution logs, a new per-workspace data-retention-hours override, and a check-digit-validated VIN recognizer. The core redaction pipeline is well-engineered: a deterministic two-pass collect/substitute approach batches all strings from a single execution into one chunked Presidio call, and a fail-safe ensures PII is never persisted when masking fails.

  • PII redaction: hooked at completeWorkflowExecution after filterForDisplay and redactApiKeys; org-scoped rules are resolved at persist time covering both inline and externalized write paths; oversized payloads (>16 MB) are scrubbed rather than leaked.
  • Workspace retention overrides: new nullable workspace.data_retention_settings column with a clean workspace ?? org ?? plan-default resolution chain; a new /api/workspaces/[id]/data-retention endpoint mirrors the org-level API with proper admin + enterprise gating.
  • Three copies of the comment \"Empty = redact all detected PII\" on entityTypes (in schema.ts, primitives.ts, and pii-redaction.ts) directly contradict retention.ts, which treats an empty entity-type list as "contribute nothing, rule is inactive." The PR description confirms the correct semantic is "empty = redact nothing", so those three comments need updating to avoid operators mistakenly believing empty rules provide full coverage.

Confidence Score: 3/5

The redaction pipeline and workspace-override logic are structurally sound, but three copies of a wrong comment on a security-sensitive field create a genuine risk of operators deploying empty-entity-type rules under the false impression that they cover all PII.

The core machinery — two-pass collect/substitute, byte-chunked Presidio calls, fail-safe scrubbing, and the workspace ?? org ?? plan-default retention resolution — is implemented correctly. Three conflicting entityTypes comments in schema.ts, primitives.ts, and pii-redaction.ts say the opposite of what retention.ts implements. An enterprise admin who follows those comments and creates a rule with no entity types selected will have no PII masked at all — a silent failure in a privacy-protection feature.

packages/db/schema.ts, apps/sim/lib/api/contracts/primitives.ts, and apps/sim/lib/logs/execution/pii-redaction.ts all carry the wrong entityTypes comment that contradicts retention.ts.

Important Files Changed

Filename Overview
apps/sim/lib/logs/execution/pii-redaction.ts New PII redaction transform: deterministic two-pass collect/substitute approach is sound; fail-safe scrubbing on error is correct; misleading entityTypes comment and reuse of REDACTION_FAILED_MARKER for the byte-ceiling case need fixing.
apps/sim/lib/logs/execution/logger.ts PII redaction correctly hooked at the single persist choke point after filterForDisplay + redactApiKeys; adds 2 extra DB queries per execution on the hot path that could be consolidated into the existing log fetch.
apps/sim/lib/billing/retention.ts New file with clean resolution logic for both retention hours (workspace ?? org ?? fallback) and PII redaction (union of applicable rule entity types). Correctly returns disabled when union is empty, though this contradicts comments elsewhere.
packages/db/schema.ts Adds DataRetentionSettings interface and workspace.dataRetentionSettings column; PiiRedactionRule.entityTypes comment says Empty = redact all detected PII which contradicts the actual retention.ts behavior (empty = redact nothing).
apps/sim/lib/api/contracts/primitives.ts Adds well-validated piiRedactionRuleSchema and piiRedactionSettingsSchema; same misleading entityTypes comment as schema.ts.
apps/sim/lib/guardrails/validate_pii.ts New maskPIIBatch function correctly chunks texts by byte budget (256KB), rejects on subprocess failure so callers can apply fail-safe; existing validatePII single-text path unchanged.
apps/sim/lib/guardrails/validate_pii.py Adds mask_batch function reusing a single AnalyzerEngine + AnonymizerEngine across all texts in a chunk; VinRecognizer with ISO 3779 check-digit validation is well-implemented.
apps/sim/lib/billing/cleanup-dispatcher.ts Adds workspace-level settings to the cleanup scope query; fallback is null for all enterprise jobs so behavior is identical to the previous code for unconfigured orgs.
apps/sim/app/api/workspaces/[id]/data-retention/route.ts New workspace-level data retention GET/PUT endpoints; auth gating (session, admin permission, enterprise plan) is correct.
apps/sim/lib/logs/execution/pii-redaction.test.ts Good coverage: structure preservation, immutability, fail-safe scrub on error, oversized-string skip, and no-op when no strings collected.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant E as Executor
    participant L as ExecutionLogger
    participant R as retention.ts
    participant P as pii-redaction.ts
    participant V as validate_pii.ts
    participant Py as validate_pii.py
    participant DB as Postgres

    E->>L: completeWorkflowExecution
    L->>L: filterForDisplay + redactApiKeys
    L->>DB: SELECT org.dataRetentionSettings
    DB-->>L: orgSettings
    L->>R: resolveEffectivePiiRedaction
    R-->>L: enabled + entityTypes
    alt PII enabled
        L->>DB: isWorkspaceOnEnterprisePlan
        DB-->>L: true
        L->>P: redactPIIFromExecution
        P->>P: collect string leaves
        loop Per 256KB chunk
            P->>V: maskPIIBatch
            V->>Py: spawn subprocess
            Py-->>V: masked strings
            V-->>P: masked strings
        end
        P-->>L: redacted payload
    end
    L->>DB: UPDATE workflowExecutionLogs
    L-->>E: WorkflowExecutionLog
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant E as Executor
    participant L as ExecutionLogger
    participant R as retention.ts
    participant P as pii-redaction.ts
    participant V as validate_pii.ts
    participant Py as validate_pii.py
    participant DB as Postgres

    E->>L: completeWorkflowExecution
    L->>L: filterForDisplay + redactApiKeys
    L->>DB: SELECT org.dataRetentionSettings
    DB-->>L: orgSettings
    L->>R: resolveEffectivePiiRedaction
    R-->>L: enabled + entityTypes
    alt PII enabled
        L->>DB: isWorkspaceOnEnterprisePlan
        DB-->>L: true
        L->>P: redactPIIFromExecution
        P->>P: collect string leaves
        loop Per 256KB chunk
            P->>V: maskPIIBatch
            V->>Py: spawn subprocess
            Py-->>V: masked strings
            V-->>P: masked strings
        end
        P-->>L: redacted payload
    end
    L->>DB: UPDATE workflowExecutionLogs
    L-->>E: WorkflowExecutionLog
Loading

Reviews (2): Last reviewed commit: "Merge remote-tracking branch 'origin/sta..." | Re-trigger Greptile

Comment thread apps/sim/lib/logs/execution/pii-redaction.ts
Comment thread apps/sim/lib/logs/execution/pii-redaction.ts
Comment thread apps/sim/lib/logs/execution/logger.ts
Comment thread packages/db/schema.ts Outdated
Comment thread apps/sim/lib/api/contracts/primitives.ts Outdated
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

Comment thread apps/sim/lib/logs/execution/logger.ts
…t lazy

- Extend PII redaction to span error/errorMessage/toolCalls and top-level
  error/completionFailure/trigger/executionState (Bugbot: PII in execution
  metadata). executionState is safe to redact — resume reads from the separate
  pausedExecutions table, not the log copy.
- Lazy-import validate_pii in pii-redaction so the Python/child_process
  guardrails module stays out of the static middleware/RSC graph.
- Type the org retention mutation to the contract body (optional, non-null).
Comment thread apps/sim/lib/logs/execution/pii-redaction.ts
…stays org-scoped

- Remove the unused per-workspace data-retention-hours override (no UI; superseded
  by workspace-scoped PII rules). Reverts cleanup-dispatcher to org-only retention,
  drops resolveEffectiveRetentionHours, the workspace.dataRetentionSettings column +
  migration, and the workspace data-retention route/contract/hooks. Fixes Bugbot's
  null-as-unset finding by removing the buggy path entirely; org retention behavior
  is unchanged.
- Stop re-checking isWorkspaceOnEnterprisePlan at persist time (it returns false on
  transient errors, which would fail-open and leak PII). Enabled rules already imply
  entitlement; redact whenever rules apply (fail-safe).
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

Comment thread apps/sim/lib/logs/execution/pii-redaction.ts
- Drop the per-string size cap in PII redaction: oversized strings were left
  unmasked (leak). Nothing is skipped now; large payloads still fail-safe via the
  total-bytes ceiling + per-chunk timeout (scrub, never leak).
- Add executionData.environment (incl. variables) to the redaction set.
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

…tion

Each rule now targets one scope — all workspaces (workspaceId: null) or a single
workspace — with workspaceId unique across rules. Resolution is most-specific-wins
(a workspace's own rule overrides the all rule), not union; an empty specific rule
exempts that workspace. Matches Access Control's resolveWorkspaceGroup precedence.
UI 'Applies to' becomes a single-select; Add rule disables when all scopes are taken.
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

Comment thread apps/sim/lib/logs/execution/logger.ts
Comment thread apps/sim/lib/api/contracts/primitives.ts
Reshape the PII redaction settings into a 'Default (all workspaces)' block plus a
'Workspace overrides' list, making the most-specific-wins precedence explicit
(overrides replace the default; unlisted workspaces use it). Same data model
(workspaceId null = default), UI only.
Drop the uppercase section labels and the overrides description; gate the
Workspace overrides section behind a configured default; use a single Delete
action; 'Add redaction' creates the all-workspaces default and disappears once set.
Comment thread apps/sim/ee/data-retention/components/data-retention-settings.tsx
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

Comment thread apps/sim/lib/guardrails/validate_pii.ts
Attach an 'error' listener to the child's stdin in both runPythonScript (the
batch masking hot path) and executePythonPIIDetection. A 256KB chunk can exceed
the OS pipe buffer, so if the Python process exits mid-read (OOM/kill) the EPIPE
emitted on stdin was unhandled and would crash the Node process. Funnel it into
the promise rejection so the fail-safe scrub path handles it gracefully.
Comment thread apps/sim/lib/logs/execution/logger.ts
The top-level correlation field is copied from pre-redaction trigger data, so
webhook/schedule correlation values could persist unredacted. Add it to the
redaction set alongside trigger/environment.
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@BugBot review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

1 issue from previous review remains unresolved.

Fix All in Cursor

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 7313e18. Configure here.

The contract accepted multiple rules with the same workspaceId (or several
null all-rules); resolution is first-match, so duplicates could disagree with
the UI. Add a schema refine rejecting duplicate scopes.
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

2 similar comments
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@BugBot review

Comment thread apps/sim/ee/data-retention/components/data-retention-settings.tsx
The form hydrated once via a boolean ref, so switching the active org left stale
retention days + PII rules and saves targeted the new org with old config. Key
hydration on orgId so it re-loads per org.
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@BugBot review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ad7d1fa. Configure here.

@TheodoreSpeaks TheodoreSpeaks merged commit 9d2a6ef into staging Jun 19, 2026
16 checks passed
@TheodoreSpeaks TheodoreSpeaks deleted the feat/redact-pii-workflow-log branch June 19, 2026 21:16
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.

1 participant