הרצת-סקריפט-מ-UI ב-/scripts, רק לסקריפטי קריאה-בלבד/אודיט, דרך גשר-המארח
הקיים (court-fetch) — שיכפול דפוס /adapter-migration.
אבטחה:
- allowlist בצד-המארח (services/script_runner.py, מקור-אמת יחיד): name→argv
קבוע ובטוח. 5 סקריפטים מאומתים: leak_guard, check_undefined_names,
storage_leak_tripwire, audit_training_corpus, audit_corpus_integrity --no-notify.
- הגשר (court_fetch_service/server.py): endpoint POST /run-script, Bearer-auth,
ולידציית-allowlist, create_subprocess_exec (ללא shell), timeout 600s,
audit-log; מתעלם מארגומנטים מהבקשה (argv מה-allowlist בלבד).
- קונטיינר (web/app.py): POX /api/scripts/{name}/run proxy ל-גשר + pre-check
allowlist; הרחבת /api/scripts/catalog ב-runnable_scripts.
- UI: כפתור "הרץ" (ירוק) רק לשורות-runnable + דיאלוג-פלט (exit-code+stdout);
שאר השורות "מקור" בלבד. confirm לפני הרצה.
מאושר דרך שער-העיצוב (מוקאפ 16-scripts עודכן עם כפתור "הרץ").
G12: leak_guard עובר (אין סמלי-פלטפורמה בשכבת-האינטליגנציה).
Deploy דו-שלבי: גשר-המארח דורש git pull בעותק-המארח + pm2 restart
legal-court-fetch-service; הקונטיינר נפרס דרך Coolify כרגיל.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
44 lines
1.6 KiB
TypeScript
44 lines
1.6 KiB
TypeScript
import { useMutation } from "@tanstack/react-query";
|
|
import { apiRequest } from "./client";
|
|
|
|
// ── Scripts catalog ───────────────────────────────────────────────
|
|
// Surfaces the maintained `scripts/SCRIPTS.md` (single source of truth for
|
|
// every script under scripts/) read-only at /scripts. Edits go through
|
|
// git/Gitea, not the UI — the backend just reads the file at runtime.
|
|
|
|
export type ScriptsCatalog = {
|
|
content: string;
|
|
filename: string;
|
|
bytes: number;
|
|
last_modified: number;
|
|
gitea_url: string;
|
|
// #4 — basenames the UI may offer a "הרץ" button for (read-only allowlist,
|
|
// enforced host-side). Optional so an older backend (pre-deploy) degrades to
|
|
// "מקור"-only with no run buttons.
|
|
runnable_scripts?: string[];
|
|
};
|
|
|
|
export function fetchScriptsCatalog(signal?: AbortSignal) {
|
|
return apiRequest<ScriptsCatalog>("/api/scripts/catalog", { signal });
|
|
}
|
|
|
|
// ── Run a read-only script (#4) ───────────────────────────────────
|
|
// Proxies to the court-fetch host bridge; only allowlisted read-only scripts
|
|
// run, with a fixed safe argv. Exit code + captured output are relayed verbatim.
|
|
export type ScriptRunResult = {
|
|
ok: boolean;
|
|
exit_code: number;
|
|
stdout: string;
|
|
stderr: string;
|
|
};
|
|
|
|
export function useRunScript() {
|
|
return useMutation({
|
|
mutationFn: (name: string) =>
|
|
apiRequest<ScriptRunResult>(
|
|
`/api/scripts/${encodeURIComponent(name)}/run`,
|
|
{ method: "POST" },
|
|
),
|
|
});
|
|
}
|