From 3dc02b08ad310b7bafc6fbc72c84a24da2f790b2 Mon Sep 17 00:00:00 2001 From: CrHackHead Date: Sun, 10 Aug 2025 11:44:40 +0200 Subject: [PATCH] feat: implement builder workflow --- frontend/src/lib/api.ts | 31 +++++ frontend/src/main.tsx | 5 + frontend/src/pages/Builder.tsx | 222 +++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 frontend/src/pages/Builder.tsx diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index c9b828e..320c3a3 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -63,6 +63,37 @@ export function withAuth(token: string) { if (customizationId) url.searchParams.set("customization_id", customizationId); return fetch(url.toString(), { method: "POST", headers }).then(j); }, + builderOperators() { + return fetch(`${API_BASE}/api/v1/builder/operators`, { headers }).then(j); + }, + builderSchema(dataset_uri: string, limit_events = 100, samples_per_field = 5) { + return fetch(`${API_BASE}/api/v1/builder/schema`, { + method: "POST", + headers, + body: JSON.stringify({ dataset_uri, limit_events, samples_per_field }), + }).then(j); + }, + builderCompile(draft: any) { + return fetch(`${API_BASE}/api/v1/builder/compile`, { + method: "POST", + headers, + body: JSON.stringify(draft), + }).then(j); + }, + builderPreview(draft: any, dataset_uri: string, sample_limit = 5) { + return fetch(`${API_BASE}/api/v1/builder/preview`, { + method: "POST", + headers, + body: JSON.stringify({ draft, dataset_uri, sample_limit }), + }).then(j); + }, + saveRule(body: any) { + return fetch(`${API_BASE}/api/v1/rules`, { + method: "POST", + headers, + body: JSON.stringify(body), + }).then(j); + }, createRun(name: string, source: "local" | "atomic" | "caldera") { const form = new FormData(); form.set("name", name); diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index c407b8e..45164e8 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -8,7 +8,9 @@ import Runs from "./pages/Runs"; import Deploy from "./pages/Deploy"; import AIWorkbench from "./pages/AIWorkbench"; import Library from "./pages/Library"; +import Builder from "./pages/Builder"; +// eslint-disable-next-line react-refresh/only-export-components function Router(){ const hash = window.location.hash.slice(2); // e.g. /rules or /rule/ if(hash.startsWith("coverage")) return ; @@ -18,9 +20,11 @@ function Router(){ if(hash.startsWith("runs")) return ; if(hash.startsWith("deploy")) return ; if(hash.startsWith("ai")) return ; + if(hash.startsWith("builder")) return ; return ; } +// eslint-disable-next-line react-refresh/only-export-components function App(){ const [tok,setTok]=React.useState(localStorage.getItem("catchattack.token")||""); async function doLogin(role:"admin"|"analyst"|"viewer"){ @@ -34,6 +38,7 @@ function App(){