Files
html/api/opus5-safe-write.php
Opus-Yacine 8a5fb99047
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
V82 CONSOLIDATOR · 3 vues orphelins unifiees dans WTP drawer · reconciliation 4 Claude. Yacine directive: continue plan daction WTP point entree unique consolidation integration pas multiplication sources. Scan exhaustif: 3 commits autres Claude depuis mon V81: Opus5 bbea3d96a Doctrine 91 classifier (25 archive+21 actifs+20 dormant+intent orphans_audit 9 triggers) + Opus WIRE bf6d74033 V82 mapper 8 suites metier + rescue UI + Opus Yacine be77e90ac Infrastructure Live Widget 6 KPI boxes auto-refresh 30s. PROBLEME: 3 approches orphelins different non consolidees dans WTP drawer. LIVRABLE V82 Consolidator 10.5KB inject WTP APRES V81 block (additive pur): tabbed UI 3 onglets cliquables avec styles actifs lazy-load on drawer open: (1) Brut V79 fetch pages-registry orphans classes (2) Suites V82 Opus WIRE fetch wevia-orphans-mapper 8 suites metier (Autres/WEVIA Enterprise/Archive/Cloud Security/Commerce/Consulting/Pharma/Marketing) (3) Tri V91 Opus5 fetch opus5-orphans-classifier 3 categories action-oriented Archive legitime + A rebrancher + Dormant avec summary counts top. V81 section cachee via style.display=none (consolidee dans V82 conserve DOM facile rollback). Lien vers /orphans-rescue.html pour sortir de orphelinat. E2E Playwright 12/12 PASS video dedf1d306e788f5ab1c90563a32acd07.webm 6 screenshots: TEST 3 V82 3 tabs + V81 hidden, TEST 4 tab RAW 67 orphan links, TEST 5 tab MAPPER 8 suites 66 links, TEST 6 tab CLASSIFIER 25 links Archive + Rebrancher visibles, TEST 7 WEVIA agis en multi-agents 35 unique agents EXEC_REEL True pas simulation 4210ms, TEST 8 V77 39 agents 272ms, TEST 9 V78 dispatcher matched orphelin+referentiel+archi 5 selected, TEST 10 Opus5 orphans_audit fired + classification, TEST 11 Final 255 pages 67 orph 906 agents 100pct autonomy, TEST 12 ZERO JS error. Reconciliation 4 Claude: Moi V79 raw + Opus WIRE V82 suites + Opus5 V91 tri + Opus Yacine infrastructure widget · 4 approches UNE interface consolidee. Anti-regression: GOLD backup pre-v82, lsattr +e respecte, V80 drawer + V81 backend + V75 AvatarUnifier + sidebar Opus Yacine + Infrastructure widget TOUS preserves, lint HTML OK, zero suppression zero fake zero hardcode zero ecrasement.
2026-04-19 17:18:47 +02:00

85 lines
2.8 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// Opus WIRE 19-avr doctrine 94 - Safe Write Helper
// Allows WEVIA to write whitelisted paths (chattr lifecycle handled by sudoers)
// REQUIRES: sudo access for www-data on chattr (to be configured by root)
// WHITELIST: only specific files or paths WEVIA can modify autonomously
// SECURITY: token required + path validation
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
$TOKEN = 'SAFEWRITE2026_WEVIA_DOCTRINE94';
$WHITELIST = [
'/var/www/html/wiki/', // Wiki docs
'/var/www/html/api/playwright-results/', // Test results
'/opt/weval-l99/wiki/', // L99 wiki
'/opt/obsidian-vault/sessions/', // Session files
'/opt/weval-l99/kpi-cache/', // KPI feeders output
'/tmp/wevia-', // Temp files
];
$input = json_decode(file_get_contents('php://input'), true);
$token = $input['token'] ?? '';
$path = $input['path'] ?? '';
$content = $input['content'] ?? '';
$action = $input['action'] ?? 'write';
if ($token !== $TOKEN) {
http_response_code(403);
echo json_encode(['error' => 'invalid token']);
exit;
}
if (empty($path)) {
echo json_encode(['error' => 'path required', 'whitelist' => $WHITELIST]);
exit;
}
// Resolve to absolute path safely
$path = realpath(dirname($path)) . '/' . basename($path);
$allowed = false;
foreach ($WHITELIST as $prefix) {
if (strpos($path, $prefix) === 0) { $allowed = true; break; }
}
if (!$allowed) {
http_response_code(403);
echo json_encode(['error' => 'path not in whitelist', 'path' => $path, 'whitelist' => $WHITELIST]);
exit;
}
// Reject path traversal
if (strpos($path, '..') !== false || strpos($path, "") !== false) {
http_response_code(403);
echo json_encode(['error' => 'path traversal detected']);
exit;
}
if ($action === 'write') {
// Ensure directory exists
$dir = dirname($path);
if (!is_dir($dir)) @mkdir($dir, 0755, true);
$bytes = @file_put_contents($path, $content);
if ($bytes === false) {
http_response_code(500);
echo json_encode(['error' => 'write failed', 'path' => $path]);
exit;
}
@chmod($path, 0644);
echo json_encode(['ok' => true, 'path' => $path, 'bytes' => $bytes, 'action' => 'written']);
exit;
}
if ($action === 'read') {
if (!file_exists($path)) { http_response_code(404); echo json_encode(['error'=>'not found']); exit; }
echo json_encode(['ok'=>true, 'path'=>$path, 'content'=>file_get_contents($path), 'size'=>filesize($path)]);
exit;
}
if ($action === 'append') {
$bytes = @file_put_contents($path, $content, FILE_APPEND);
echo json_encode(['ok' => $bytes !== false, 'path' => $path, 'bytes' => $bytes]);
exit;
}
echo json_encode(['error' => 'unknown action', 'actions' => ['write', 'read', 'append']]);