Skip to content

feat(platform): add PII policy tab to governance page#1370

Merged
larryro merged 7 commits into
mainfrom
feat/issue-1345-pii-policy-ui
Apr 11, 2026
Merged

feat(platform): add PII policy tab to governance page#1370
larryro merged 7 commits into
mainfrom
feat/issue-1345-pii-policy-ui

Conversation

@yannickmonney

@yannickmonney yannickmonney commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Wire existing PiiConfig component into governance settings page as a fourth tab (after System Prompt, Budgets, Usage)
  • Migrate hardcoded English tab labels to i18n keys (governance.tabs.*)
  • Fix translation key mismatch between PiiConfig component and locale files
  • Add IBAN and German ID (Personalausweis) regex detection patterns to pii_patterns.ts
  • Add shared Zod schema (piiConfigSchema) for PII config validation
  • Sync POLICY_TYPES to include system_prompt and pii_config
  • Add Zod validation in upsertPiiConfig mutation before writing to DB
  • Add German translations for all governance subsections (budgets, models, upload, retention, feature flags, PII)
  • Add Swiss German (de-CH) overrides for ss/sz differences

Changes

File Change
governance.tsx Import PiiConfig, add PII tab, migrate tab labels to i18n
pii_patterns.ts Add IBAN and germanId patterns
mutations.ts Add Zod validation in upsertPiiConfig
governance.ts (schemas) Add piiConfigSchema, sync POLICY_TYPES
en.json Restructure governance.pii keys, add tabs keys
de.json Add all governance subsection translations
de-CH.json Add Swiss German overrides
pii_patterns.test.ts New: 20 tests for patterns, detection, masking, scrubPii

Testing checklist

  • Backend tests: 20 new tests covering IBAN/German ID detection, masking, scrubPii integration, block mode
  • Client tests: existing PiiConfig a11y test passes
  • Full server test suite: 1966 tests pass
  • Full client test suite: 1852 tests pass
  • Lint: 0 warnings, 0 errors
  • Typecheck: passes

Closes #1345

Summary by CodeRabbit

  • New Features

    • Added PII protection configuration to governance settings with mask or block modes.
    • Introduced built-in PII detection patterns for IBAN and German ID numbers.
    • Added ability to create and test custom PII detection patterns.
  • Documentation

    • Added multilingual support for PII protection UI labels and descriptions.

@greptile-apps greptile-apps 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.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR implements a dedicated PII (Personally Identifiable Information) policy configuration interface in the governance settings dashboard. It adds a new "pii" tab to the governance settings page with structured configuration for PII detection and masking, introduces Zod schema validation for PII configurations (enabled, mode, enabledPatterns, customPatterns), adds two new built-in PII detection patterns (iban and germanId) to expand coverage, and includes comprehensive translations in German and English. The implementation includes runtime validation in mutations to ensure configuration integrity and a new test suite validating pattern detection, masking behavior, and integration scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the primary change: adding a PII policy tab to the governance page.
Linked Issues check ✅ Passed All primary coding requirements from issue #1345 are fully met: dedicated PII policy UI added to governance settings with toggles, mode selection (mask/block), selectable data categories (via enabledPatterns and custom patterns), and proper schema validation implemented.
Out of Scope Changes check ✅ Passed All changes are within scope and directly support the PII policy UI feature: governance page modifications, PII pattern additions, schema definitions, mutation validation, translations, and comprehensive test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-1345-pii-policy-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@services/platform/convex/governance/mutations.ts`:
- Around line 127-135: upsertPolicy currently accepts policyType: 'pii_config'
with config: v.any() and bypasses the schema check you added in upsertPiiConfig;
update upsertPolicy to detect when args.policyType === 'pii_config' and validate
args.config using piiConfigSchema.safeParse (same validation logic as in
upsertPiiConfig), throwing a descriptive error if parsed.success is false before
persisting; reference the upsertPolicy function, the piiConfigSchema, and the
policyType/config fields when making the change.

In `@services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts`:
- Around line 124-126: The test uses `as const` to narrow test config objects
(e.g., the `config` variable) which over-constrains the `mode` field; replace
those `as const` assertions with `satisfies PiiConfig` so the object shape is
validated against the `PiiConfig` type without forcing literal narrowing (update
occurrences for `config` and any other test config objects in this file, keeping
the object values the same but changing the assertion to `satisfies PiiConfig`).

In `@services/platform/convex/governance/pii/pii_patterns.ts`:
- Around line 53-57: The current germanId pattern allows a digit as the first
character; update the regex for the object with name 'germanId' so the first
character is restricted to the allowed letters only (e.g. change the leading
character class from [CFGHJKLMNPRTVWXYZ\d] to [CFGHJKLMNPRTVWXYZ] and keep the
following {8} characters as the existing allowed set), and add a unit test
asserting that a numeric-only string like "123456789" does NOT match or get
masked to prevent regressions; reference the 'germanId' entry and the test file
that covers pii_patterns matching when making the change.

In `@services/platform/lib/shared/schemas/governance.ts`:
- Around line 78-81: piiCustomPatternSchema currently allows any non-empty
string for regex which can lead to runtime RegExp errors in buildPatterns() when
calling new RegExp(cp.regex, 'g'); update piiCustomPatternSchema to validate
regex syntax by adding a refinement on the regex field that attempts to
construct a RegExp (e.g., try new RegExp(value) and return true on success,
false on throw) and return a clear error message like "invalid regex pattern";
reference piiCustomPatternSchema and the consumer buildPatterns()/new
RegExp(cp.regex, 'g') so reviewers can locate the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7b07c8f9-37ef-432b-a082-4692d1baea91

📥 Commits

Reviewing files that changed from the base of the PR and between 6feddbe and 5286e61.

📒 Files selected for processing (8)
  • services/platform/app/routes/dashboard/$id/settings/governance.tsx
  • services/platform/convex/governance/mutations.ts
  • services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts
  • services/platform/convex/governance/pii/pii_patterns.ts
  • services/platform/lib/shared/schemas/governance.ts
  • services/platform/messages/de-CH.json
  • services/platform/messages/de.json
  • services/platform/messages/en.json

Comment on lines +127 to +135
const parsed = piiConfigSchema.safeParse({
enabled: args.enabled,
mode: args.mode,
enabledPatterns: args.enabledPatterns,
customPatterns: args.customPatterns,
});
if (!parsed.success) {
throw new Error(`Invalid PII configuration: ${parsed.error.message}`);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Close the pii_config validation bypass in generic upsert.

Line 127 adds validation in upsertPiiConfig, but upsertPolicy (Line 18 onward) still allows policyType: 'pii_config' with config: v.any() and no schema check. That leaves a direct path to persist invalid PII policy config.

🔧 Suggested fix
   if (args.policyType === 'budgets') {
     const parsed = budgetConfigSchema.safeParse(args.config);
     if (!parsed.success) {
       throw new Error(
         `Invalid budget configuration: ${parsed.error.message}`,
       );
     }
   }
+  if (args.policyType === 'pii_config') {
+    const parsed = piiConfigSchema.safeParse(args.config);
+    if (!parsed.success) {
+      throw new Error(`Invalid PII configuration: ${parsed.error.message}`);
+    }
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const parsed = piiConfigSchema.safeParse({
enabled: args.enabled,
mode: args.mode,
enabledPatterns: args.enabledPatterns,
customPatterns: args.customPatterns,
});
if (!parsed.success) {
throw new Error(`Invalid PII configuration: ${parsed.error.message}`);
}
if (args.policyType === 'budgets') {
const parsed = budgetConfigSchema.safeParse(args.config);
if (!parsed.success) {
throw new Error(
`Invalid budget configuration: ${parsed.error.message}`,
);
}
}
if (args.policyType === 'pii_config') {
const parsed = piiConfigSchema.safeParse(args.config);
if (!parsed.success) {
throw new Error(`Invalid PII configuration: ${parsed.error.message}`);
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/platform/convex/governance/mutations.ts` around lines 127 - 135,
upsertPolicy currently accepts policyType: 'pii_config' with config: v.any() and
bypasses the schema check you added in upsertPiiConfig; update upsertPolicy to
detect when args.policyType === 'pii_config' and validate args.config using
piiConfigSchema.safeParse (same validation logic as in upsertPiiConfig),
throwing a descriptive error if parsed.success is false before persisting;
reference the upsertPolicy function, the piiConfigSchema, and the
policyType/config fields when making the change.

Comment on lines +124 to +126
const config = {
enabled: true,
mode: 'mask' as const,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "pii_patterns.test.ts" | head -20

Repository: tale-project/tale

Length of output: 133


🏁 Script executed:

if [ -f "services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts" ]; then
  wc -l "services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts"
fi

Repository: tale-project/tale

Length of output: 135


🏁 Script executed:

if [ -f "services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts" ]; then
  sed -n '120,160p' "services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts"
fi

Repository: tale-project/tale

Length of output: 1416


🏁 Script executed:

# Find the scrubPii function definition
fd . -type f -name "*.ts" | xargs rg -l "export.*scrubPii|function scrubPii" | head -10

Repository: tale-project/tale

Length of output: 297


🏁 Script executed:

sed -n '1,100p' "services/platform/convex/governance/pii/index.ts"

Repository: tale-project/tale

Length of output: 1878


🏁 Script executed:

# Get the full scrubPii function signature and parameters
rg -A 15 "function scrubPii|export.*scrubPii|const scrubPii" "services/platform/convex/governance/pii/index.ts"

Repository: tale-project/tale

Length of output: 552


Replace as const assertions with satisfies PiiConfig for test config objects.

The as const assertions here narrow the mode field to literal types ('mask', 'block'), which is stricter than the PiiConfig interface requires. Since the interface expects mode: 'mask' | 'block' and the code doesn't rely on literal type narrowing, these assertions are unnecessary. Use satisfies instead to validate the object structure without over-narrowing.

🔧 Suggested refactor
 const config = {
   enabled: true,
-  mode: 'mask' as const,
+  mode: 'mask',
   enabledPatterns: ['iban', 'germanId', 'email'],
   customPatterns: [],
-};
+} satisfies PiiConfig;

-const blockConfig = { ...config, mode: 'block' as const };
+const blockConfig = {
+  ...config,
+  mode: 'block',
+} satisfies PiiConfig;

Also applies to: lines 145–152

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts`
around lines 124 - 126, The test uses `as const` to narrow test config objects
(e.g., the `config` variable) which over-constrains the `mode` field; replace
those `as const` assertions with `satisfies PiiConfig` so the object shape is
validated against the `PiiConfig` type without forcing literal narrowing (update
occurrences for `config` and any other test config objects in this file, keeping
the object values the same but changing the assertion to `satisfies PiiConfig`).

Comment on lines +53 to +57
{
name: 'germanId',
regex: /\b[CFGHJKLMNPRTVWXYZ\d][CFGHJKLMNPRTVWXYZ\d]{8}\b/g,
replacement: '[GERMAN_ID]',
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current pattern and test coverage for numeric-only false positives.
sed -n '50,60p' services/platform/convex/governance/pii/pii_patterns.ts
rg -n "germanId|123456789|does not match" services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts

Repository: tale-project/tale

Length of output: 1094


🏁 Script executed:

# Search for all test cases in the germanId test section
rg -A 3 "germanId" services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts | head -80

# Check if there are tests for numeric-only strings
rg "123456789|^\d{9}" services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts

Repository: tale-project/tale

Length of output: 1267


🏁 Script executed:

# Get the complete germanId test section to see all test cases
sed -n '93,120p' services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts

# Check if any integration or other test files test germanId
fd -e test.ts -e test.js | xargs rg "germanId" 2>/dev/null | wc -l

Repository: tale-project/tale

Length of output: 1007


🏁 Script executed:

# Verify the actual regex behavior with numeric-only strings
python3 << 'EOF'
import re

# Current regex from the code
current_pattern = r'\b[CFGHJKLMNPRTVWXYZ\d][CFGHJKLMNPRTVWXYZ\d]{8}\b'
# Suggested fix
suggested_pattern = r'\b[CFGHJKLMNPRTVWXYZ][CFGHJKLMNPRTVWXYZ\d]{8}\b'

current_regex = re.compile(current_pattern, re.MULTILINE)
suggested_regex = re.compile(suggested_pattern, re.MULTILINE)

test_cases = [
    ('123456789', 'all-digit 9-char'),
    ('T22000129', 'letter+digits'),
    ('L0100FG57', 'letter+mixed'),
    ('1T2000012', 'digit+letter+digits'),
]

print("Current regex behavior:")
for test, desc in test_cases:
    match = current_regex.search(test)
    print(f"  {desc:25} '{test}' -> {'MATCH' if match else 'NO MATCH'}")

print("\nSuggested regex behavior:")
for test, desc in test_cases:
    match = suggested_regex.search(test)
    print(f"  {desc:25} '{test}' -> {'MATCH' if match else 'NO MATCH'}")
EOF

Repository: tale-project/tale

Length of output: 509


germanId regex is too permissive and matches invalid identifiers.

Current pattern allows any 9-character string starting with a digit (e.g., 123456789), which can incorrectly trigger masking in normal messages. German Personalausweis IDs must start with a valid letter from the allowed character set.

🔧 Suggested fix
-    regex: /\b[CFGHJKLMNPRTVWXYZ\d][CFGHJKLMNPRTVWXYZ\d]{8}\b/g,
+    regex: /\b[CFGHJKLMNPRTVWXYZ][CFGHJKLMNPRTVWXYZ\d]{8}\b/g,

Additionally, add a test case to prevent regression of numeric-only false positives.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
name: 'germanId',
regex: /\b[CFGHJKLMNPRTVWXYZ\d][CFGHJKLMNPRTVWXYZ\d]{8}\b/g,
replacement: '[GERMAN_ID]',
},
{
name: 'germanId',
regex: /\b[CFGHJKLMNPRTVWXYZ][CFGHJKLMNPRTVWXYZ\d]{8}\b/g,
replacement: '[GERMAN_ID]',
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/platform/convex/governance/pii/pii_patterns.ts` around lines 53 -
57, The current germanId pattern allows a digit as the first character; update
the regex for the object with name 'germanId' so the first character is
restricted to the allowed letters only (e.g. change the leading character class
from [CFGHJKLMNPRTVWXYZ\d] to [CFGHJKLMNPRTVWXYZ] and keep the following {8}
characters as the existing allowed set), and add a unit test asserting that a
numeric-only string like "123456789" does NOT match or get masked to prevent
regressions; reference the 'germanId' entry and the test file that covers
pii_patterns matching when making the change.

Comment on lines +78 to +81
export const piiCustomPatternSchema = z.object({
name: z.string().min(1),
regex: z.string().min(1),
replacement: z.string().min(1),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect where custom regex is compiled and whether compilation is guarded.
rg -n "new RegExp\\(|RegExp\\(" services/platform/convex/governance/pii
rg -n "try\\s*\\{" services/platform/convex/governance/pii

Repository: tale-project/tale

Length of output: 282


🏁 Script executed:

cat -n services/platform/lib/shared/schemas/governance.ts | sed -n '75,95p'

Repository: tale-project/tale

Length of output: 741


🏁 Script executed:

cat -n services/platform/convex/governance/pii/pii_detector.ts | sed -n '10,25p'

Repository: tale-project/tale

Length of output: 696


🏁 Script executed:

cat -n services/platform/convex/governance/pii/index.ts | sed -n '25,40p'

Repository: tale-project/tale

Length of output: 658


🏁 Script executed:

rg -B 5 -A 10 "buildPatterns\(" services/platform/convex/governance/pii/index.ts

Repository: tale-project/tale

Length of output: 954


🏁 Script executed:

grep -r "scrubPii\|buildPatterns" services/platform/convex/governance/pii --include="*.ts" -n

Repository: tale-project/tale

Length of output: 1362


🏁 Script executed:

cat -n services/platform/convex/governance/pii/__tests__/pii_patterns.test.ts | head -170

Repository: tale-project/tale

Length of output: 6598


🏁 Script executed:

rg -n "piiConfigSchema\|PiiConfig" services/platform/convex/governance/ --include="*.ts" -B 2 -A 2

Repository: tale-project/tale

Length of output: 502


🏁 Script executed:

rg -n "customPatterns" services/platform/convex/governance/ --include="*.ts" | head -20

Repository: tale-project/tale

Length of output: 502


🏁 Script executed:

rg -n "piiConfigSchema|PiiConfig" services/platform/convex/governance/ -t ts -B 2 -A 2

Repository: tale-project/tale

Length of output: 2795


🏁 Script executed:

rg -n "customPatterns" services/platform/convex/governance/ -t ts | head -20

Repository: tale-project/tale

Length of output: 643


🏁 Script executed:

cat -n services/platform/convex/governance/mutations.ts | sed -n '97,155p'

Repository: tale-project/tale

Length of output: 2115


Add regex syntax validation to piiCustomPatternSchema.

Line 80 accepts any non-empty string for the regex field. Invalid regex patterns pass schema validation but cause runtime errors when new RegExp(cp.regex, 'g') is called in buildPatterns() at index.ts:31. Unlike email validation (where SSO providers validate upstream), custom regex patterns receive no prior validation.

🔧 Suggested fix
+const isValidRegex = (pattern: string): boolean => {
+  try {
+    new RegExp(pattern);
+    return true;
+  } catch {
+    return false;
+  }
+};
+
 export const piiCustomPatternSchema = z.object({
   name: z.string().min(1),
-  regex: z.string().min(1),
+  regex: z.string().min(1).refine(isValidRegex, 'Invalid regex pattern'),
   replacement: z.string().min(1),
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const piiCustomPatternSchema = z.object({
name: z.string().min(1),
regex: z.string().min(1),
replacement: z.string().min(1),
const isValidRegex = (pattern: string): boolean => {
try {
new RegExp(pattern);
return true;
} catch {
return false;
}
};
export const piiCustomPatternSchema = z.object({
name: z.string().min(1),
regex: z.string().min(1).refine(isValidRegex, 'Invalid regex pattern'),
replacement: z.string().min(1),
🧰 Tools
🪛 GitHub Actions: Lint

[warning] 78-78: knip: Unused export 'piiCustomPatternSchema' (Unused exports: 1).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/platform/lib/shared/schemas/governance.ts` around lines 78 - 81,
piiCustomPatternSchema currently allows any non-empty string for regex which can
lead to runtime RegExp errors in buildPatterns() when calling new
RegExp(cp.regex, 'g'); update piiCustomPatternSchema to validate regex syntax by
adding a refinement on the regex field that attempts to construct a RegExp
(e.g., try new RegExp(value) and return true on success, false on throw) and
return a clear error message like "invalid regex pattern"; reference
piiCustomPatternSchema and the consumer buildPatterns()/new RegExp(cp.regex,
'g') so reviewers can locate the change.

@yannickmonney yannickmonney force-pushed the feat/issue-1345-pii-policy-ui branch from 4c81795 to bbd219a Compare April 11, 2026 02:39
Wire existing PiiConfig component into governance settings as a fourth
tab. Migrate hardcoded tab labels to i18n keys. Fix translation key
mismatch between component and locale files. Add IBAN and German ID
detection patterns. Add shared Zod schema for PII config validation.

- Add PII tab with translated label alongside System Prompt, Budgets,
  Usage tabs
- Restructure governance.pii translation keys to match component
  expectations (nested patterns, descriptive labels)
- Add governance.tabs i18n keys for all tab labels (en, de, de-CH)
- Add German translations for all governance subsections
- Add IBAN and German ID (Personalausweis) regex patterns to
  pii_patterns.ts
- Add piiConfigSchema and piiCustomPatternSchema to shared governance
  schemas
- Sync POLICY_TYPES to include system_prompt and pii_config
- Add Zod validation in upsertPiiConfig mutation
- Add backend tests for new patterns and scrubPii integration

Closes #1345
- Add pii_config validation in upsertPolicy mutation to prevent schema bypass
- Fix germanId regex to reject digit-only strings (e.g. 123456789)
- Replace `as const` with `satisfies PiiConfig` in test config objects
- Remove unused piiCustomPatternSchema export and add regex validation
@larryro larryro force-pushed the feat/issue-1345-pii-policy-ui branch from bbd219a to 53823f7 Compare April 11, 2026 06:12
larryro added 3 commits April 11, 2026 14:18
Track server state after load and save, compare against current form
values to compute isDirty flag for the Save changes button.
…terns

- Toggle, mode, and pattern changes now save immediately
- Custom pattern cards use Save + Cancel instead of Delete
- Test detection requires explicit Test button click
- Remove redundant bottom Save changes button
Add client-side PII validation before creating a chat thread so that
blocked messages never produce empty threads. Also improve the error
toast to show the specific PII block reason instead of a generic
"Failed to send message".
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.

PII masking has no dedicated policy UI, only configurable via system prompt workaround

2 participants