updates on the ai and agent and all thse things awith onboarding
This commit is contained in:
78
internal/ai/playground/redact.go
Normal file
78
internal/ai/playground/redact.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package playground
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Redacted replaces every value Redact removes.
|
||||
const Redacted = "[redacted]"
|
||||
|
||||
// piiKeys: a field whose name contains one of these is personal or free text
|
||||
// (free text is where people type phone numbers and addresses).
|
||||
var piiKeys = []string{
|
||||
"name", "phone", "mobile", "email", "address", "landmark", "otp", "contact",
|
||||
"note", "remark", "instruction", "description", "reason", "comment",
|
||||
}
|
||||
|
||||
var (
|
||||
emailLike = regexp.MustCompile(`[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}`)
|
||||
// An Indian mobile (10 digits from 6-9, optional +91). Narrow on purpose:
|
||||
// a looser digit-run pattern also masks dates like "2026-09-29 12".
|
||||
phoneLike = regexp.MustCompile(`(?:\+?91[\s-]?)?\b[6-9]\d{4}[\s-]?\d{5}\b`)
|
||||
)
|
||||
|
||||
// Redact returns a copy of v, as plain JSON values, with personal data
|
||||
// removed: values under personal keys are replaced, and any remaining string
|
||||
// that contains an email or a phone-like number has it masked.
|
||||
//
|
||||
// Executors already select only non-personal columns; this is the backstop
|
||||
// that makes a later column addition safe by default.
|
||||
func Redact(v any) any {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var generic any
|
||||
if err := json.Unmarshal(b, &generic); err != nil {
|
||||
return nil
|
||||
}
|
||||
return redactValue(generic)
|
||||
}
|
||||
|
||||
func redactValue(v any) any {
|
||||
switch t := v.(type) {
|
||||
case map[string]any:
|
||||
out := make(map[string]any, len(t))
|
||||
for k, val := range t {
|
||||
if isPIIKey(k) && val != nil {
|
||||
out[k] = Redacted
|
||||
continue
|
||||
}
|
||||
out[k] = redactValue(val)
|
||||
}
|
||||
return out
|
||||
case []any:
|
||||
out := make([]any, len(t))
|
||||
for i, val := range t {
|
||||
out[i] = redactValue(val)
|
||||
}
|
||||
return out
|
||||
case string:
|
||||
s := emailLike.ReplaceAllString(t, Redacted)
|
||||
return phoneLike.ReplaceAllString(s, Redacted)
|
||||
default:
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func isPIIKey(k string) bool {
|
||||
k = strings.ToLower(k)
|
||||
for _, p := range piiKeys {
|
||||
if strings.Contains(k, p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user