exa-data-handling

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Exa Data Handling

Exa 数据处理

Overview

概述

Handle sensitive data correctly when integrating with Exa.
在与Exa集成时正确处理敏感数据。

Prerequisites

前提条件

  • Understanding of GDPR/CCPA requirements
  • Exa SDK with data export capabilities
  • Database for audit logging
  • Scheduled job infrastructure for cleanup
  • 了解GDPR/CCPA要求
  • 具备数据导出功能的Exa SDK
  • 用于审计日志的数据库
  • 用于清理任务的定时作业基础设施

Data Classification

数据分类

CategoryExamplesHandling
PIIEmail, name, phoneEncrypt, minimize
SensitiveAPI keys, tokensNever log, rotate
BusinessUsage metricsAggregate when possible
PublicProduct namesStandard handling
类别示例处理方式
PII邮箱、姓名、电话加密、最小化存储
敏感数据API密钥、令牌绝不记录、定期轮换
业务数据使用指标尽可能聚合
公开数据产品名称标准处理

PII Detection

PII 检测

typescript
const PII_PATTERNS = [
  { type: 'email', regex: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g },
  { type: 'phone', regex: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g },
  { type: 'ssn', regex: /\b\d{3}-\d{2}-\d{4}\b/g },
  { type: 'credit_card', regex: /\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/g },
];

function detectPII(text: string): { type: string; match: string }[] {
  const findings: { type: string; match: string }[] = [];

  for (const pattern of PII_PATTERNS) {
    const matches = text.matchAll(pattern.regex);
    for (const match of matches) {
      findings.push({ type: pattern.type, match: match[0] });
    }
  }

  return findings;
}
typescript
const PII_PATTERNS = [
  { type: 'email', regex: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g },
  { type: 'phone', regex: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g },
  { type: 'ssn', regex: /\b\d{3}-\d{2}-\d{4}\b/g },
  { type: 'credit_card', regex: /\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/g },
];

function detectPII(text: string): { type: string; match: string }[] {
  const findings: { type: string; match: string }[] = [];

  for (const pattern of PII_PATTERNS) {
    const matches = text.matchAll(pattern.regex);
    for (const match of matches) {
      findings.push({ type: pattern.type, match: match[0] });
    }
  }

  return findings;
}

Data Redaction

数据脱敏

typescript
function redactPII(data: Record<string, any>): Record<string, any> {
  const sensitiveFields = ['email', 'phone', 'ssn', 'password', 'apiKey'];
  const redacted = { ...data };

  for (const field of sensitiveFields) {
    if (redacted[field]) {
      redacted[field] = '[REDACTED]';
    }
  }

  return redacted;
}

// Use in logging
console.log('Exa request:', redactPII(requestData));
typescript
function redactPII(data: Record<string, any>): Record<string, any> {
  const sensitiveFields = ['email', 'phone', 'ssn', 'password', 'apiKey'];
  const redacted = { ...data };

  for (const field of sensitiveFields) {
    if (redacted[field]) {
      redacted[field] = '[REDACTED]';
    }
  }

  return redacted;
}

// Use in logging
console.log('Exa request:', redactPII(requestData));

Data Retention Policy

数据保留策略

Retention Periods

保留期限

Data TypeRetentionReason
API logs30 daysDebugging
Error logs90 daysRoot cause analysis
Audit logs7 yearsCompliance
PIIUntil deletion requestGDPR/CCPA
数据类型保留时长原因
API日志30天调试
错误日志90天根因分析
审计日志7年合规要求
PII数据直至收到删除请求GDPR/CCPA要求

Automatic Cleanup

自动清理

typescript
async function cleanupExaData(retentionDays: number): Promise<void> {
  const cutoff = new Date();
  cutoff.setDate(cutoff.getDate() - retentionDays);

  await db.exaLogs.deleteMany({
    createdAt: { $lt: cutoff },
    type: { $nin: ['audit', 'compliance'] },
  });
}

// Schedule daily cleanup
cron.schedule('0 3 * * *', () => cleanupExaData(30));
typescript
async function cleanupExaData(retentionDays: number): Promise<void> {
  const cutoff = new Date();
  cutoff.setDate(cutoff.getDate() - retentionDays);

  await db.exaLogs.deleteMany({
    createdAt: { $lt: cutoff },
    type: { $nin: ['audit', 'compliance'] },
  });
}

// Schedule daily cleanup
cron.schedule('0 3 * * *', () => cleanupExaData(30));

GDPR/CCPA Compliance

GDPR/CCPA 合规

Data Subject Access Request (DSAR)

数据主体访问请求(DSAR)

typescript
async function exportUserData(userId: string): Promise<DataExport> {
  const exaData = await exaClient.getUserData(userId);

  return {
    source: 'Exa',
    exportedAt: new Date().toISOString(),
    data: {
      profile: exaData.profile,
      activities: exaData.activities,
      // Include all user-related data
    },
  };
}
typescript
async function exportUserData(userId: string): Promise<DataExport> {
  const exaData = await exaClient.getUserData(userId);

  return {
    source: 'Exa',
    exportedAt: new Date().toISOString(),
    data: {
      profile: exaData.profile,
      activities: exaData.activities,
      // Include all user-related data
    },
  };
}

Right to Deletion

删除权

typescript
async function deleteUserData(userId: string): Promise<DeletionResult> {
  // 1. Delete from Exa
  await exaClient.deleteUser(userId);

  // 2. Delete local copies
  await db.exaUserCache.deleteMany({ userId });

  // 3. Audit log (required to keep)
  await auditLog.record({
    action: 'GDPR_DELETION',
    userId,
    service: 'exa',
    timestamp: new Date(),
  });

  return { success: true, deletedAt: new Date() };
}
typescript
async function deleteUserData(userId: string): Promise<DeletionResult> {
  // 1. Delete from Exa
  await exaClient.deleteUser(userId);

  // 2. Delete local copies
  await db.exaUserCache.deleteMany({ userId });

  // 3. Audit log (required to keep)
  await auditLog.record({
    action: 'GDPR_DELETION',
    userId,
    service: 'exa',
    timestamp: new Date(),
  });

  return { success: true, deletedAt: new Date() };
}

Data Minimization

数据最小化

typescript
// Only request needed fields
const user = await exaClient.getUser(userId, {
  fields: ['id', 'name'], // Not email, phone, address
});

// Don't store unnecessary data
const cacheData = {
  id: user.id,
  name: user.name,
  // Omit sensitive fields
};
typescript
// Only request needed fields
const user = await exaClient.getUser(userId, {
  fields: ['id', 'name'], // Not email, phone, address
});

// Don't store unnecessary data
const cacheData = {
  id: user.id,
  name: user.name,
  // Omit sensitive fields
};

Instructions

操作步骤

Step 1: Classify Data

步骤1:数据分类

Categorize all Exa data by sensitivity level.
按敏感度级别对所有Exa数据进行分类。

Step 2: Implement PII Detection

步骤2:实现PII检测

Add regex patterns to detect sensitive data in logs.
添加正则表达式模式以检测日志中的敏感数据。

Step 3: Configure Redaction

步骤3:配置脱敏

Apply redaction to sensitive fields before logging.
在记录日志前对敏感字段应用脱敏处理。

Step 4: Set Up Retention

步骤4:设置保留策略

Configure automatic cleanup with appropriate retention periods.
配置自动清理任务并设置合适的保留期限。

Output

输出结果

  • Data classification documented
  • PII detection implemented
  • Redaction in logging active
  • Retention policy enforced
  • 已记录数据分类
  • 已实现PII检测
  • 日志脱敏已启用
  • 保留策略已生效

Error Handling

错误处理

IssueCauseSolution
PII in logsMissing redactionWrap logging with redact
Deletion failedData lockedCheck dependencies
Export incompleteTimeoutIncrease batch size
Audit gapMissing entriesReview log pipeline
问题原因解决方案
日志中存在PII未启用脱敏用脱敏函数包裹日志记录
删除失败数据被锁定检查依赖关系
导出不完整超时增大批量处理大小
审计缺口缺少日志条目检查日志管道

Examples

示例

Quick PII Scan

快速PII扫描

typescript
const findings = detectPII(JSON.stringify(userData));
if (findings.length > 0) {
  console.warn(`PII detected: ${findings.map(f => f.type).join(', ')}`);
}
typescript
const findings = detectPII(JSON.stringify(userData));
if (findings.length > 0) {
  console.warn(`PII detected: ${findings.map(f => f.type).join(', ')}`);
}

Redact Before Logging

日志前脱敏

typescript
const safeData = redactPII(apiResponse);
logger.info('Exa response:', safeData);
typescript
const safeData = redactPII(apiResponse);
logger.info('Exa response:', safeData);

GDPR Data Export

GDPR数据导出

typescript
const userExport = await exportUserData('user-123');
await sendToUser(userExport);
typescript
const userExport = await exportUserData('user-123');
await sendToUser(userExport);

Resources

参考资源

Next Steps

下一步

For enterprise access control, see
exa-enterprise-rbac
.
如需企业访问控制,请查看
exa-enterprise-rbac