Files
html/api/anonymize-pii.php

79 lines
3.2 KiB
PHP

<?php
// Opus v5.5.1 19avr: PII Anonymization - sqlite default fix
header('Content-Type: application/json');
$in = json_decode(file_get_contents('php://input'), true) ?: [];
$text = $in['text'] ?? $_REQUEST['text'] ?? '';
$direction = $in['direction'] ?? 'anonymize';
if (!$text) { echo json_encode(['ok'=>false, 'error'=>'no text provided']); exit; }
$vault_db = '/opt/wevia-brain/pii-vault/vault.sqlite';
@mkdir(dirname($vault_db), 0755, true);
try {
$db = new PDO('sqlite:' . $vault_db);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->exec('CREATE TABLE IF NOT EXISTS surrogate_map (
original TEXT PRIMARY KEY,
surrogate TEXT UNIQUE NOT NULL,
category TEXT,
created_at INTEGER
)');
} catch (Exception $e) {
echo json_encode(['ok'=>false, 'error'=>'vault init: '.$e->getMessage()]);
exit;
}
$patterns = [
'email' => '/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/',
'phone' => '/(?:\+212|0)[0-9]{9,10}/',
'ipv4' => '/\b(?:\d{1,3}\.){3}\d{1,3}\b/',
'aws_key' => '/AKIA[0-9A-Z]{16}/',
'jwt' => '/eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/',
'uuid' => '/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i'
];
$result = $text;
$mappings = [];
$now = time();
if ($direction === 'anonymize') {
foreach ($patterns as $cat => $regex) {
preg_match_all($regex, $result, $matches);
foreach (array_unique($matches[0] ?? []) as $orig) {
$stmt = $db->prepare('SELECT surrogate FROM surrogate_map WHERE original=?');
$stmt->execute([$orig]);
$surr = $stmt->fetchColumn();
if (!$surr) {
$surr = strtoupper($cat) . '_' . substr(hash('sha256', $orig . 'wevia_salt'), 0, 8);
$ins = $db->prepare('INSERT INTO surrogate_map (original, surrogate, category, created_at) VALUES (?, ?, ?, ?)');
try { $ins->execute([$orig, $surr, $cat, $now]); } catch(Exception $e){}
}
$result = str_replace($orig, $surr, $result);
$mappings[$orig] = ['surrogate' => $surr, 'category' => $cat];
}
}
echo json_encode([
'ok' => true, 'direction' => 'anonymize',
'v' => 'V5.5.1-deeprepo-style-opus-19avr',
'original_preview' => substr($text, 0, 200),
'anonymized_text' => $result,
'surrogates_count' => count($mappings),
'categories_found' => array_values(array_unique(array_column($mappings, 'category'))),
'vault_db' => $vault_db,
'vault_total_mappings' => (int)$db->query('SELECT COUNT(*) FROM surrogate_map')->fetchColumn(),
'inspired_by' => 'DeepRepo.ai LLM-Anonymization layer 1+2 (regex safety net + vault)',
'ts' => date('c')
], JSON_PRETTY_PRINT);
} else {
$rows = $db->query('SELECT original, surrogate FROM surrogate_map')->fetchAll(PDO::FETCH_ASSOC);
$replaced = 0;
foreach ($rows as $r) {
if (strpos($result, $r['surrogate']) !== false) {
$result = str_replace($r['surrogate'], $r['original'], $result);
$replaced++;
}
}
echo json_encode(['ok'=>true,'direction'=>'restore','restored_text'=>$result,'replaced_count'=>$replaced,'ts'=>date('c')], JSON_PRETTY_PRINT);
}