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 Permalink 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']]);