From 29b6d0ff125e98157975dbd52c77c1a3eff85b8e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 15 Nov 2026 00:46:47 +0000 Subject: [PATCH] chore(dfe-engine-types): sync from dfe-engine Auto-generated from hyperi-io/dfe-engine@b7a5e29f281f0e9a88334ce7d22cc98995e3e1c9 --- .../dfe-engine-types/specs/openapi.e2e.json | 2 +- packages/dfe-engine-types/specs/openapi.json | 674 ++++++++++++++---- packages/dfe-engine-types/types/index.d.ts | 463 ++++++++---- 3 files changed, 887 insertions(+), 252 deletions(-) diff --git a/packages/dfe-engine-types/specs/openapi.e2e.json b/packages/dfe-engine-types/specs/openapi.e2e.json index f1d0b6f25..f4a375f2f 100644 --- a/packages/dfe-engine-types/specs/openapi.e2e.json +++ b/packages/dfe-engine-types/specs/openapi.e2e.json @@ -3,7 +3,7 @@ "info": { "title": "DFE Engine API -- E2E", "description": "Playwright helpers for `make e2e-server`. Unauthenticated. Mounted and documented only in that mode -- not in the product spec.", - "version": "1.22.80" + "version": "1.22.90" }, "paths": { "/api/e2e/status": { diff --git a/packages/dfe-engine-types/specs/openapi.json b/packages/dfe-engine-types/specs/openapi.json index 67d31ebd4..def1498b2 100644 --- a/packages/dfe-engine-types/specs/openapi.json +++ b/packages/dfe-engine-types/specs/openapi.json @@ -2,8 +2,8 @@ "openapi": "3.1.0", "info": { "title": "DFE Engine API", - "description": "Data Fusion Engine -- configuration, scheduling, and query API", - "version": "1.22.80" + "description": "Configuration, scheduling and query API for the Data Fusion Engine.\n\nEvery route sits under `/api/v1` on the engine URL your deployment publishes. Get a token with `POST /api/v1/auth/login` (JSON body `username` and `password`, the console's accounts work here), then send it as `Authorization: Bearer ` on every other call.", + "version": "1.22.90" }, "paths": { "/api/v1/auth/login": { @@ -12,7 +12,7 @@ "Auth" ], "summary": "Login", - "description": "Authenticate with local credentials and receive a JWT token.\n\nThe password check runs off the event loop. Failed attempts back off per\nusername and per client address (``auth.login_throttle``); a waiting attempt is\nrefused with 429 before the password is checked.", + "description": "Authenticate with local credentials and receive a JWT token.\n\nThe password check runs off the event loop. Failed attempts back off per\nusername and per client address (``auth.login_throttle``). A waiting attempt is\nrefused with 429 before the password is checked.", "operationId": "auth.login", "requestBody": { "content": { @@ -46,7 +46,7 @@ } }, "403": { - "description": "The break-glass account is disabled in governance settings", + "description": "The break-glass password is right, but the account is disabled in governance settings", "content": { "application/problem+json": { "schema": { @@ -243,7 +243,7 @@ "Auth" ], "summary": "Get Me", - "description": "Get the current authenticated user's info.\n\nA session on an issued password reports the flag and no roles, permissions,\ngroups or orgs, because its token carries none until the change.\n\n``hyperdx_role`` and ``hyperdx_identity`` are what dfe-hyperdx takes a\nsession's dashboard role and team from; it caches this answer for 30 seconds,\nso a group change reaches HyperDX in that window rather than at token expiry.", + "description": "Get the current authenticated user's info.\n\nA session on an issued password reports the flag and no roles, permissions,\ngroups or orgs, because its token carries none until the change.\n\n``hyperdx_role`` and ``hyperdx_identity`` are what dfe-hyperdx takes a\nsession's dashboard role and team from. It caches this answer for 30 seconds,\nso a group change reaches dfe-hyperdx in that window rather than at token expiry.", "operationId": "auth.me.list", "responses": { "200": { @@ -387,7 +387,7 @@ "Auth" ], "summary": "Get Setup Status", - "description": "Report first-run setup state and what is configured (no auth -- pre-login UI).\n\nDriven by the setup state machine (``state_machines/setup.py``). The\nregistries the wizard renders -- OIDC providers and organisations -- are\nreturned while setup is outstanding and dropped once it completes, so a\nconfigured deployment does not serve its inventory to anonymous callers.\nThe exception is the name and display name of each enabled OIDC provider,\nwhich stay (no configuration) because the login screen needs to know which\nIdPs to offer and what to call them. Accounts are never returned; the\n``first_user`` step reports whether a real (non break-glass) user exists.", + "description": "Report first-run setup state and what is configured (no auth -- pre-login UI).\n\nDriven by the setup state machine (``state_machines/setup.py``). The\nregistries the wizard renders -- OIDC providers and organisations -- are\nreturned while setup is outstanding and dropped once it completes, so a\nconfigured deployment does not serve its inventory to anonymous callers.\nThe exception is the name and display name of each enabled OIDC provider,\nwhich stay (no configuration) because the login screen needs to know which\nIdPs to offer and what to call them. Accounts are never returned. The\n``first_user`` step reports whether a real (non break-glass) user exists.", "operationId": "auth.setup-status.list", "responses": { "200": { @@ -1757,7 +1757,7 @@ "Accounts" ], "summary": "Account Git Status", - "description": "Poll whether an account's password has merged to the deploy repo's main.\n\nStep 2 of the review-PR path for the local admin and ``breakglass``: the UI\npolls this after the operator merges the PR; it fetches remote main and flips\n``merged`` true. Durable immediately in the auto-merge and file-share modes. A\nregular user is never git-persisted, so it reports not-git-backed (durable in\nits own store).", + "description": "Poll whether an account's password has merged to the deploy repo's main.\n\nStep 2 of the review-PR path for the local admin and ``breakglass``: the UI\npolls this after the operator merges the PR. It fetches remote main and flips\n``merged`` true. Durable immediately in the auto-merge and file-share modes. A\nregular user is never git-persisted, so it reports not-git-backed (durable in\nits own store).", "operationId": "auth.accounts.git-status", "parameters": [ { @@ -2771,7 +2771,7 @@ "Groups" ], "summary": "Add Member", - "description": "Add a member to a group (idempotent; checked at the group's scope).", + "description": "Add a member to a group (idempotent, checked at the group's scope).", "operationId": "auth.groups.members.create", "parameters": [ { @@ -4763,7 +4763,7 @@ "OIDC Providers" ], "summary": "Update Provider", - "description": "Update an OIDC provider configuration (admin only).\n\nA secret the body omits, value and env var name alike, keeps what the provider already holds, so an update that only flips ``enabled`` does not strand a stored credential; an empty env var name clears the name and keeps the stored copy. A secret the body names an env var for and sends no value for moves onto that env var and its stored copy is deleted once the update is saved, unless the name is the one already held with nothing stored. A move onto an env var the engine does not set is refused (``env_var_not_set``). Any update that touches more than ``enabled`` or ``display_name`` must leave the provider passing the field rules. Both are checked before a secret is written or deleted.", + "description": "Update an OIDC provider configuration (admin only).\n\nA secret the body omits, value and env var name alike, keeps what the provider already holds, so an update that only flips ``enabled`` does not strand a stored credential. An empty env var name clears the name and keeps the stored copy. A secret the body names an env var for and sends no value for moves onto that env var and its stored copy is deleted once the update is saved, unless the name is the one already held with nothing stored. A move onto an env var the engine does not set is refused (``env_var_not_set``). Any update that touches more than ``enabled`` or ``display_name`` must leave the provider passing the field rules. Both are checked before a secret is written or deleted.", "operationId": "auth.oidc-providers.apply", "parameters": [ { @@ -5241,7 +5241,7 @@ "Organisations" ], "summary": "Create Org", - "description": "Create a new customer organisation (admin only).\n\nIf HyperDX integration is enabled, the lifecycle manager handles\nteam creation as part of org provisioning. Failure is non-fatal.\n\nA hunt already naming the org, such as one whose org was deleted, has the new\norg's tenant ids stored first. A production+team posture routes that hunt\nchange to review, and the ``X-DFE-Review-Required`` header says so.", + "description": "Create a new customer organisation (admin only).\n\nIf the Search integration is enabled, the lifecycle manager handles\nteam creation as part of org provisioning. Failure is non-fatal.\n\nA hunt already naming the org, such as one whose org was deleted, has the new\norg's tenant ids stored first. A production+team posture routes that hunt\nchange to review, and the ``X-DFE-Review-Required`` header says so.", "operationId": "orgs.create", "requestBody": { "required": true, @@ -5331,7 +5331,7 @@ "Organisations" ], "summary": "List Orgs", - "description": "List organisations visible to the caller, paginated.\n\nSystem-scope org:read holders see every org; org-scope holders see\nonly the orgs their grants cover.", + "description": "List organisations visible to the caller, paginated.\n\nSystem-scope org:read holders see every org. Org-scope holders see\nonly the orgs their grants cover.", "operationId": "orgs.list", "parameters": [ { @@ -5502,14 +5502,20 @@ "in": "query", "required": false, "schema": { - "type": "integer", - "maximum": 1000, - "minimum": 1, - "description": "Most tenant ids to return -- a suggestion list, not an export", - "default": 200, + "anyOf": [ + { + "type": "integer", + "maximum": 1000, + "minimum": 1 + }, + { + "type": "null" + } + ], + "description": "Most tenant ids to return -- a suggestion list, not an export. Unset takes orgs.available_ids_limit (200 by default)", "title": "Limit" }, - "description": "Most tenant ids to return -- a suggestion list, not an export" + "description": "Most tenant ids to return -- a suggestion list, not an export. Unset takes orgs.available_ids_limit (200 by default)" } ], "responses": { @@ -6570,7 +6576,7 @@ "Sources" ], "summary": "List Sources", - "description": "List sources with pagination, search, filtering, and a full object tree.\n\nThe landing source (``main``) is always the first item when it is in the\nresult set; remaining sources keep the requested sort. A caller held to its\norgs does not see a fetcher source bound to another org.", + "description": "List sources with pagination, search, filtering, and a full object tree.\n\nThe landing source (``main``) is always the first item when it is in the\nresult set. Remaining sources keep the requested sort. A caller held to its\norgs does not see a fetcher source bound to another org.", "operationId": "sources.list", "parameters": [ { @@ -8400,7 +8406,7 @@ "Sources" ], "summary": "Delete Source", - "description": "Delete a source by name. Its fetcher instance, receiver rule and topics go with it.\n\nAn engine-owned source -- the landing table's own -- is refused with 409\n``conflict``, the same answer PUT and PATCH give.\n\nThe answer reports the reconcile as a create or an update does: on a\ndeployment that renders the app config itself, ``restart_required`` names the\ncommand that takes away the containers the source's instances ran in.\n\nA delete production+team sends to review answers ``review_required`` and\ntouches nothing else: main still carries the source, so its topics, records and\nHyperDX source stay until the branch is merged.", + "description": "Delete a source by name. Its fetcher instance, receiver rule and topics go with it.\n\nAn engine-owned source -- the landing table's own -- is refused with 409\n``conflict``, the same answer PUT and PATCH give.\n\nThe answer reports the reconcile as a create or an update does: on a\ndeployment that renders the app config itself, ``restart_required`` names the\ncommand that takes away the containers the source's instances ran in.\n\nA delete production+team sends to review answers ``review_required`` and\ntouches nothing else: main still carries the source, so its topics, records and\nSearch source stay until the branch is merged.", "operationId": "sources.delete", "parameters": [ { @@ -8689,7 +8695,7 @@ "Sources" ], "summary": "Get Source Signals", - "description": "Whether this source's records are arriving, and how fast.\n\nReads the loader's per-table counter out of the otel tables over a bounded\nfive-minute window, so the console can put a number beside a source without\nthe operator opening HyperDX. It answers 200 with nulls where the series is\nabsent: a source that was only just defined has nothing to report, and that\nis not an error.", + "description": "Whether this source's records are arriving, and how fast.\n\nReads the loader's per-table counter out of the otel tables over a bounded\nfive-minute window, so the console can put a number beside a source without\nthe operator opening Search. It answers 200 with nulls where the series is\nabsent: a source that was only just defined has nothing to report, and that\nis not an error.", "operationId": "sources.signals", "parameters": [ { @@ -8893,7 +8899,7 @@ "Sources" ], "summary": "Bulk Action", - "description": "Perform a bulk action on multiple sources.\n\n``enable`` / ``disable`` / ``dormant`` / ``delete`` apply immediately.\n``deploy`` submits one ``source:deploy`` background task per accepted source\n(poll ``GET /operations/{operation}``); refused names land in ``failed``.\n\nAn action that applies immediately reports the one reconcile it ends with, as\na single-source write does.", + "description": "Perform a bulk action on multiple sources.\n\n``enable`` / ``disable`` / ``dormant`` / ``delete`` apply immediately.\n``deploy`` submits one ``source:deploy`` background task per accepted source\n(poll ``GET /operations/{operation}``). Refused names land in ``failed``.\n\nAn action that applies immediately reports the one reconcile it ends with, as\na single-source write does.", "operationId": "sources.bulk", "requestBody": { "content": { @@ -8985,7 +8991,7 @@ "Sources" ], "summary": "Reconcile Apps", - "description": "Bring the deploy repo's derived app state into step with the sources.\n\nRecompiles every stack-scoped routing block (receiver, loader, archiver) and\ndeploys, syncs or removes the instances of every instance-scoped app (a fetcher\nper active fetcher-based source). Every source write does this on its own; this\nroute is the retry when one reported ``apps_sync_error``, and the pass that\ndeletes a stranded ``_load`` topic a deploy reported in ``topics_pending_removal``.", + "description": "Bring the deploy repo's derived app state into step with the sources.\n\nRecompiles every stack-scoped routing block (receiver, loader, archiver) and\ndeploys, syncs or removes the instances of every instance-scoped app (a fetcher\nper active fetcher-based source). Every source write does this on its own. This\nroute is the retry when one reported ``apps_sync_error``, and the pass that\ndeletes a stranded ``_load`` topic a deploy reported in ``topics_pending_removal``.", "operationId": "sources.reconcile-apps", "responses": { "200": { @@ -10622,7 +10628,7 @@ "Services" ], "summary": "Get Service Config", - "description": "Get a full service config by service + instance, every credential masked.", + "description": "A service config as its instance runs it, every credential masked.\n\nThe stored keys over the app's own defaults, read from its mounted contract.\nWith no contract mounted only the stored keys are shown.", "operationId": "services.get", "parameters": [ { @@ -10722,7 +10728,7 @@ "Services" ], "summary": "Save Service Config", - "description": "Create or update a service config.\n\nEach top-level section in the body replaces the stored one, and a section the\nbody leaves out is kept as stored, so a form that sends some sections cannot\ndrop the rest and the secrets in them. A section written as ``null`` is removed.\n\nA read shows every set secret masked, so a masked value written back keeps the\nsecret stored there, matched as the app surface matches one. A mask with nothing\nstored behind it, or in a list entry that cannot be told apart, is a 400\n``masked_value`` and nothing is saved. A changed field beside a masked secret,\nin the same mapping or with the secret one mapping down, is a 400\n``credential_reentry_required``: the secret is typed again.", + "description": "Create or update a service config.\n\nEach top-level section in the body replaces the stored one, and a section the\nbody leaves out is kept as stored, so a form that sends some sections cannot\ndrop the rest and the secrets in them. A section written as ``null`` is removed.\n\nA read shows every set secret masked, so a masked value written back keeps the\nsecret stored there, matched as the app surface matches one. A mask with nothing\nstored behind it, or in a list entry that cannot be told apart, is a 400\n``masked_value`` and nothing is saved. A changed field beside a masked secret,\nin the same mapping or with the secret one mapping down, is a 400\n``credential_reentry_required``: the secret is typed again. A value the app's\ncontract refuses is a 422 ``invalid_config``.", "operationId": "services.apply", "parameters": [ { @@ -11113,7 +11119,7 @@ "Deployment" ], "summary": "List Admin Links", - "description": "Each admin UI this deployment runs, in the order its deployer listed them.\n\nThe deployer supplies the list, so an empty one means it listed none. Gated to\nthe admin-class roles, which hold ``deployment:*`` or ``*``: the list maps the\ndeployment's consoles. Links only; nothing here carries a credential.", + "description": "Each admin UI this deployment runs, in the order its deployer listed them.\n\nThe deployer supplies the list, so an empty one means it listed none. Gated to\nthe admin-class roles, which hold ``deployment:*`` or ``*``: the list maps the\ndeployment's consoles. Links only. Nothing here carries a credential.", "operationId": "deployment.admin-links.list", "parameters": [ { @@ -12072,7 +12078,7 @@ "Rules" ], "summary": "Create Rule", - "description": "Create a new hunt rule via RuleCreationService.\n\nThe service sanitizes the SQL, applies CEL->SQL transpilation,\nvalidates column references, and optionally estimates query cost. A rule\nwhose SQL the hunt runner could not compile is refused with 422. The cost\npreview counts only the orgs the hunts running the rule read, cut to the orgs\nits author may read.\n\nA production+team write is routed to a review branch instead of the branch the\nrunner git-syncs, and the ``X-DFE-Review-Required`` header says so.", + "description": "Create a new hunt rule via RuleCreationService.\n\nThe rule is written as SQL or as a structured ``condition``, which the engine\ncompiles to the SQL and stores with it. The service sanitizes the SQL,\napplies CEL->SQL transpilation, validates column references, and optionally\nestimates query cost. A rule whose SQL the hunt runner could not compile is\nrefused with 422. The cost preview counts only the orgs the hunts running the\nrule read, cut to the orgs its author may read.\n\nA production+team write is routed to a review branch instead of the branch the\nrunner git-syncs, and the ``X-DFE-Review-Required`` header says so.", "operationId": "rules.create", "requestBody": { "required": true, @@ -12163,8 +12169,8 @@ "tags": [ "Rules" ], - "summary": "Create Rule From Hyperdx", - "description": "Create a hunt rule from the SQL a HyperDX view renders to.\n\nWraps the create pipeline with ``source_type='hyperdx'`` and auto-derives a\nunique rule id from the saved-search name, so the caller need not supply one.\nA view whose SQL the hunt runner could not compile, or that matches every\nevent, is refused with 422. RBAC: ``rule:write`` (data_analyst) --\n``org_viewer`` has neither this grant nor the UI button.", + "summary": "Create Rule From Search", + "description": "Create a hunt rule from the SQL a Search view renders to.\n\nWraps the create pipeline with ``source_type='hyperdx'`` and auto-derives a\nunique rule id from the saved-search name, so the caller need not supply one.\nA view whose SQL the hunt runner could not compile, or that matches every\nevent, is refused with 422. RBAC: ``rule:write`` (data_analyst) --\n``org_viewer`` has neither this grant nor the UI button.", "operationId": "rules.from-hyperdx", "requestBody": { "content": { @@ -12342,6 +12348,98 @@ } } }, + "/api/v1/rules/preview": { + "post": { + "tags": [ + "Rules" + ], + "summary": "Preview Rule", + "description": "Compile a condition and check it exactly as a save would, writing nothing.\n\nRuns the creation pipeline of ``POST /rules`` (compile, parse, the forbidden-keyword\nand column checks, the matches-everything check and the alert-volume preview) under the\nsame org fence, and stops before the save. A condition the save would refuse comes back\nwith 200 and its reasons in ``sql_errors`` or ``matches_everything``, so a builder can\nshow them as the author edits. A body that is not a condition at all is 422.", + "operationId": "rules.preview", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RulePreviewRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RulePreviewResponse" + } + } + } + }, + "401": { + "description": "No valid session: the credentials are missing, invalid or expired, or the account behind them is disabled or blocked", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Problem" + } + } + } + }, + "403": { + "description": "Refused: the session lacks the action this route checks, or its account must replace an issued password first. A SCIM route answers a refused action in the RFC 7644 error envelope", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Problem" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Problem" + } + } + } + }, + "default": { + "description": "Problem details (RFC 9457)", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Problem" + } + } + } + } + }, + "security": [ + { + "BearerAuth": [] + } + ], + "x-scalo": { + "group": "rules", + "resource": "rules", + "hierarchy": [ + "rules" + ], + "verb": "preview", + "read_only": false, + "cli": { + "hidden": false, + "aliases": [], + "positional": [] + }, + "action": "rule:validate" + } + } + }, "/api/v1/rules/{name}": { "get": { "tags": [ @@ -12439,7 +12537,7 @@ "Rules" ], "summary": "Update Rule", - "description": "Replace a detection rule (re-runs creation pipeline, preserves created_at).\n\nA replacement the hunt runner could not compile is refused with 422 and the\nstored rule is left as it was. A production+team write is routed to a review\nbranch instead of the branch the runner git-syncs, and the\n``X-DFE-Review-Required`` header says so.", + "description": "Replace a detection rule (re-runs creation pipeline, preserves created_at).\n\nThe replacement is written as SQL or as a ``condition``, as on create, and a\nrule replaced with SQL no longer carries a condition.\n\nA replacement the hunt runner could not compile is refused with 422 and the\nstored rule is left as it was. A production+team write is routed to a review\nbranch instead of the branch the runner git-syncs, and the\n``X-DFE-Review-Required`` header says so.", "operationId": "rules.apply", "parameters": [ { @@ -13393,7 +13491,7 @@ "System" ], "summary": "Get System Status", - "description": "Conditions that leave the engine degraded while it keeps serving.\n\nA refused YAML write keeps the old file or the old deploy-repo content, so reads\nstay correct and readiness is not failed; this is where the refusal shows.", + "description": "Conditions that leave the engine degraded while it keeps serving.\n\nA refused YAML write keeps the old file or the old deploy-repo content, so reads\nstay correct and readiness is not failed. This is where the refusal shows.", "operationId": "system.status", "responses": { "200": { @@ -13608,7 +13706,7 @@ "System" ], "summary": "Put Retention", - "description": "Store the override in the deploy repo, then apply it to every table that follows it.\n\nThe engine's own tables and every deployed source's table are brought to the new\neffective default in this request, with ``ALTER TABLE ... MODIFY TTL`` (or\n``REMOVE TTL`` for 0). A table that declares its own TTL is left alone. A\nClickHouse failure answers 502 with the override ALREADY committed; sending the\nsame value again applies it.", + "description": "Store the override in the deploy repo, then apply it to every table that follows it.\n\nThe engine's own tables and every deployed source's table are brought to the new\neffective default in this request, with ``ALTER TABLE ... MODIFY TTL`` (or\n``REMOVE TTL`` for 0). A table that declares its own TTL is left alone. A\nClickHouse failure answers 502 with the override ALREADY committed. Sending the\nsame value again applies it.", "operationId": "system.retention.apply", "requestBody": { "content": { @@ -13792,7 +13890,7 @@ "System" ], "summary": "Patch Defaults", - "description": "Store the named defaults. Only ttl_days is applied to live tables.\n\nOmitted fields are left alone. null clears that override. Common-header type,\nversion and engine are what a source inherits the next time it is deployed;\nthis request does not rewrite them onto live tables. A patch that names\nttl_days stores it and then runs the same reconcile as PUT /retention.", + "description": "Store the named defaults. Only ttl_days is applied to live tables.\n\nOmitted fields are left alone. null clears that override. Common-header type,\nversion and engine are what a source inherits the next time it is deployed.\nThis request does not rewrite them onto live tables. A patch that names\nttl_days stores it and then runs the same reconcile as PUT /retention.", "operationId": "system.defaults.update", "requestBody": { "content": { @@ -14578,7 +14676,7 @@ "hunts" ], "summary": "Get Engine Status", - "description": "Report hunt scheduling status.\n\nHunts execute in the separate dfe-hunt-runner service (pull-based, coordinated\nvia ClickHouse), not in this API process, so ``runners`` counts the runners that\nbeat within their last two polls and ``running`` is whether any did. For \"is this\nhunt running\", read the per-hunt ``running`` on the hunts list; ``hunt_count`` is\nthe configured-hunt count.", + "description": "Report hunt scheduling status.\n\nHunts execute in the separate dfe-hunt-runner service (pull-based, coordinated\nvia ClickHouse), not in this API process, so ``runners`` counts the runners that\nbeat within their last two polls and ``running`` is whether any did. For \"is this\nhunt running\", read the per-hunt ``running`` on the hunts list. ``hunt_count`` is\nthe configured-hunt count.", "operationId": "hunts.status", "responses": { "200": { @@ -14671,6 +14769,24 @@ }, "description": "Case-insensitive search in name, display_name, customers, rules, source_table, target_table" }, + { + "name": "rule", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Only the hunts whose rules include this rule, by its exact name", + "title": "Rule" + }, + "description": "Only the hunts whose rules include this rule, by its exact name" + }, { "name": "page_size", "in": "query", @@ -15096,7 +15212,7 @@ "hunts" ], "summary": "Delete Hunt", - "description": "Delete a hunt configuration.\n\nA production+team delete is routed to a review branch, so the runner keeps\nexecuting the hunt until that branch is merged; ``X-DFE-Review-Required`` says so.", + "description": "Delete a hunt configuration.\n\nA production+team delete is routed to a review branch, so the runner keeps\nexecuting the hunt until that branch is merged. ``X-DFE-Review-Required`` says so.", "operationId": "hunts.delete", "parameters": [ { @@ -15182,7 +15298,7 @@ "hunts" ], "summary": "Trigger Hunt", - "description": "Queue an ad-hoc run: mark the hunt due now for the runner to claim.\n\nThe pull model is kept. Nothing is pushed at the runner and no listener is added\n-- the fire is written into the coordination state, and the runner that is\nalready running picks it up on its next poll, through the same claim that stops\na hunt double-running. 202 says it is queued, not that it has run; the response\ncarries the poll interval so the caller knows the longest wait before it starts.\n\nA hunt with no rate schedule is not something the runner ticks, so a queued run\nfor one sits unclaimed. That is the schedule's shape, not a failure here.\n\n503 is reserved for ClickHouse actually being unreachable; any other failure to\nwrite the request is a 500, so a bug here never reads as an outage.", + "description": "Queue an ad-hoc run: mark the hunt due now for the runner to claim.\n\nThe pull model is kept. Nothing is pushed at the runner and no listener is added\n-- the fire is written into the coordination state, and the runner that is\nalready running picks it up on its next poll, through the same claim that stops\na hunt double-running. 202 says it is queued, not that it has run. The response\ncarries the poll interval so the caller knows the longest wait before it starts.\n\nA hunt with no rate schedule is not something the runner ticks, so a queued run\nfor one sits unclaimed. That is the schedule's shape, not a failure here.\n\n503 is reserved for ClickHouse actually being unreachable. Any other failure to\nwrite the request is a 500, so a bug here never reads as an outage.", "operationId": "hunts.run", "parameters": [ { @@ -16296,7 +16412,7 @@ "sampler" ], "summary": "List Samples", - "description": "List recent sample tasks (most recent first); a caller held to its orgs sees only theirs.", + "description": "List recent sample tasks (most recent first). A caller held to its orgs sees only theirs.", "operationId": "samples.list", "parameters": [ { @@ -20180,7 +20296,7 @@ "schemas" ], "summary": "Discover Json Paths", - "description": "Discover JSON paths inside a source's ``_json`` column.\n\nResolves the requested ``version`` (or the source's current version). If that\nversion defines a ``meta_schema`` it uses ``db.`` only after deploy;\nuntil then discovery runs on ``db.`` filtered by the version's\nmatch rule. Versions without ``meta_schema`` always use the landing table.\n\nReturns one record per path with observed types, a suggested column name,\nand whether the path is already promoted. ``?samples=N`` adds random\ndistinct example values; ``?stats=true`` adds coverage + distinct counts.\n\nA caller without a platform grant holding ``schema:read`` reads only its own\norgs' rows, as the sampler holds it, and a table it cannot be held on is 403.", + "description": "Discover JSON paths inside a source's ``_json`` column.\n\nResolves the requested ``version`` (or the source's current version). If that\nversion defines a ``meta_schema`` it uses ``db.`` only after deploy;\nuntil then discovery runs on ``db.`` filtered by the version's\nmatch rule. Versions without ``meta_schema`` always use the landing table.\n\nReturns one record per path with observed types, a suggested column name,\nand whether the path is already promoted. ``?samples=N`` adds random\ndistinct example values. ``?stats=true`` adds coverage + distinct counts.\n\nA caller without a platform grant holding ``schema:read`` reads only its own\norgs' rows, as the sampler holds it, and a table it cannot be held on is 403.", "operationId": "schemas.json-paths", "parameters": [ { @@ -20341,7 +20457,7 @@ "schemas" ], "summary": "Sample Source Rows", - "description": "Return random sample rows for a source, scoped to its match rule.\n\nResolves the requested ``version`` (or the source's current version). A\nversion with a ``meta_schema`` uses ``db.`` only after that version\nis deployed and the table exists; otherwise rows are read from\n``db.`` filtered by the version's match rule.\n\nIntended for inspecting real data while authoring a match condition or CEL\nbefore promoting any JSON path -- a row-level companion to the per-path\n``?samples=N`` on ``/json-paths``.\n\nA caller without a platform grant holding ``schema:read`` reads only its own\norgs' rows, as the sampler holds it, and a table it cannot be held on is 403.", + "description": "Return random sample rows for a source, scoped to its match rule.\n\nResolves the requested ``version`` (or the source's current version). A\nversion with a ``meta_schema`` uses ``db.`` only after that version\nis deployed and the table exists. Otherwise rows are read from\n``db.`` filtered by the version's match rule.\n\nIntended for inspecting real data while authoring a match condition or CEL\nbefore promoting any JSON path -- a row-level companion to the per-path\n``?samples=N`` on ``/json-paths``.\n\nA caller without a platform grant holding ``schema:read`` reads only its own\norgs' rows, as the sampler holds it, and a table it cannot be held on is 403.", "operationId": "schemas.sample-rows", "parameters": [ { @@ -20466,7 +20582,7 @@ "schemas" ], "summary": "Promote Field", - "description": "Promote JSON path(s) into dedicated typed columns.\n\nCreates a new schema version on the source's meta-schema (or on ``schema_path``\nwhen the source has none), adding one column per path with an ``@source`` directive\nnaming the bare record path, which is what dfe-loader reads to fill the column on\nthe next ingest. Existing rows are not backfilled. Core meta-schemas are forked to\n``{source_name}_{schema_stem}`` under the same parent path before promoting.\n``?dry_run=true`` returns the proposed diff and DDL without forking core schemas,\nadding meta-schema versions, or updating the source. A core source, such as the\nlanding source ``main``, is refused with 409 before any schema is resolved or\nwritten, dry run included; its ``json-paths`` and ``sample-rows`` reads stay open.", + "description": "Promote JSON path(s) into dedicated typed columns.\n\nCreates a new schema version on the source's meta-schema (or on ``schema_path``\nwhen the source has none), adding one column per path with an ``@source`` directive\nnaming the bare record path, which is what dfe-loader reads to fill the column on\nthe next ingest. Existing rows are not backfilled. Core meta-schemas are forked to\n``{source_name}_{schema_stem}`` under the same parent path before promoting.\n``?dry_run=true`` returns the proposed diff and DDL without forking core schemas,\nadding meta-schema versions, or updating the source. A core source, such as the\nlanding source ``main``, is refused with 409 before any schema is resolved or\nwritten, dry run included. Its ``json-paths`` and ``sample-rows`` reads stay open.", "operationId": "schemas.promote-field", "parameters": [ { @@ -20661,7 +20777,7 @@ "SCIM" ], "summary": "Create User", - "description": "Provision a user. IdP-owned; local password is randomised when omitted.\n\nA password the IdP does send is held to the same length floor as every other\npassword the API sets, and one under it is refused rather than replaced.", + "description": "Provision a user. IdP-owned. Local password is randomised when omitted.\n\nA password the IdP does send is held to the same length floor as every other\npassword the API sets, and one under it is refused rather than replaced.", "operationId": "scim.v2.users.create", "responses": { "200": { @@ -21966,7 +22082,7 @@ "sigma" ], "summary": "Generate All Sigma Views", - "description": "Generate Sigma view DDL for all sources (stored definitions win over field maps).\n\nDefaults to the data database, since that is where a propagated hunt reads\nthe view from (``{source}_sigma``); an explicit ``database`` still overrides it.", + "description": "Generate Sigma view DDL for all sources (stored definitions win over field maps).\n\nDefaults to the data database, since that is where a propagated hunt reads\nthe view from (``{source}_sigma``). An explicit ``database`` still overrides it.", "operationId": "sigma.views.create", "parameters": [ { @@ -22364,7 +22480,7 @@ "sigma" ], "summary": "Generate Sigma View", - "description": "Generate (preview) Sigma view DDL for a source.\n\nA stored view definition drives generation - including its JSON-derived\ncolumns - when one exists; otherwise falls back to the static field maps via\nthe source mapper, keeping only the mappings whose column the source's table\ncarries. Returns the DDL string; does NOT execute it against ClickHouse.\n\nDefaults to the data database, since that is where a propagated hunt reads\nthe view from (``{source}_sigma``); an explicit ``database`` still overrides it.", + "description": "Generate (preview) Sigma view DDL for a source.\n\nA stored view definition drives generation - including its JSON-derived\ncolumns - when one exists. Otherwise falls back to the static field maps via\nthe source mapper, keeping only the mappings whose column the source's table\ncarries. Returns the DDL string. Does NOT execute it against ClickHouse.\n\nDefaults to the data database, since that is where a propagated hunt reads\nthe view from (``{source}_sigma``). An explicit ``database`` still overrides it.", "operationId": "sigma.views.post", "parameters": [ { @@ -23254,7 +23370,7 @@ "sigma" ], "summary": "Disable Provider", - "description": "Disable a provider (blocks scheduled polling; a manual sync is refused).", + "description": "Disable a provider (blocks scheduled polling, a manual sync is refused).", "operationId": "sigma.providers.disable", "parameters": [ { @@ -23348,7 +23464,7 @@ "sigma" ], "summary": "Sync Provider Endpoint", - "description": "Trigger a provider sync into the catalogue.\n\nSubmitted to the task manager (a git-repo clone is long-running); blocks up to\n``wait`` seconds for inline completion, else returns ``pending`` - poll via\nGET /sigma/syncs/{task_id}.", + "description": "Trigger a provider sync into the catalogue.\n\nSubmitted to the task manager (a git-repo clone is long-running). Blocks up to\n``wait`` seconds for inline completion, else returns ``pending`` - poll via\nGET /sigma/syncs/{task_id}.", "operationId": "sigma.providers.sync", "parameters": [ { @@ -24014,7 +24130,7 @@ "sigma" ], "summary": "Adopt Catalogue Rule", - "description": "Detach a rule from upstream (pin its content; a re-import records drift only).", + "description": "Detach a rule from upstream (pin its content, a re-import records drift only).", "operationId": "sigma.catalogue.adopt", "parameters": [ { @@ -24369,7 +24485,7 @@ "sigma" ], "summary": "Propagate", - "description": "Generate sigma-bound DFE rules + hunts from the current selection.\n\nFor each SELECTED sigma rule, converts its detection to a ClickHouse WHERE over\nthe matching source's ``{source}_sigma`` view and stores a DFE rule (with a\n``sigma_rule_id`` back-reference), then binds it into a per-source hunt. Drifted\nor hand-edited bindings are reported ``skipped_drifted`` unless ``force``.\nSubmitted to the task manager; blocks up to ``wait`` seconds for inline\ncompletion, else returns ``pending`` - poll via GET /sigma/propagations/{id}.\n\nA production+team run commits each generated rule and hunt to its own review\nbranch rather than the branch the hunt runner syncs; the report carries every\nbranch and PR, and ``X-DFE-Review-Required`` says so on a run that completed\ninline. 422 ``unknown_org`` when ``hunt_customers`` names no registered org.", + "description": "Generate sigma-bound DFE rules + hunts from the current selection.\n\nFor each SELECTED sigma rule, converts its detection to a ClickHouse WHERE over\nthe matching source's ``{source}_sigma`` view and stores a DFE rule (with a\n``sigma_rule_id`` back-reference), then binds it into a per-source hunt. Drifted\nor hand-edited bindings are reported ``skipped_drifted`` unless ``force``.\nSubmitted to the task manager. Blocks up to ``wait`` seconds for inline\ncompletion, else returns ``pending`` - poll via GET /sigma/propagations/{id}.\n\nA production+team run commits each generated rule and hunt to its own review\nbranch rather than the branch the hunt runner syncs. The report carries every\nbranch and PR, and ``X-DFE-Review-Required`` says so on a run that completed\ninline. 422 ``unknown_org`` when ``hunt_customers`` names no registered org.", "operationId": "sigma.propagate", "parameters": [ { @@ -25733,7 +25849,7 @@ "Governed Ops: Backing Services" ], "summary": "List Overlays", - "description": "List substrate/platform overlay resources in the deploy repo's infra/ dir.", + "description": "List infra overlay resources in the deploy repo's infra/ dir.", "operationId": "backing-services.overlays", "parameters": [ { @@ -26093,7 +26209,7 @@ "Governed Ops: Backing Services" ], "summary": "Set Overlay Var", - "description": "Set a substrate/platform value.\n\n409 managed_by_provider, before any other check, when DFE does not run the\nservice and the value is one of its read_only paths; helmvars:override does not\nlift it. 403 with the policy that blocked it when the var is protected - the\nstorage model, the data-layer modes and the disk size are decided at deploy, and\nmoving one on a live deployment is a data migration. 400 when the value would\nlower a declared node or broker count, or leave it undeclared (a parent map that\nomits it), which loses data rather than capacity; helmvars:override does not lift it.", + "description": "Set an infra overlay value.\n\n409 managed_by_provider, before any other check, when DFE does not run the\nservice and the value is one of its read_only paths. helmvars:override does not\nlift it. 403 with the policy that blocked it when the var is protected - the\nstorage model, the data-layer modes and the disk size are decided at deploy, and\nmoving one on a live deployment is a data migration. 400 when the value would\nlower a declared node or broker count, or leave it undeclared (a parent map that\nomits it), which loses data rather than capacity. helmvars:override does not lift it.", "operationId": "backing-services.overlays.vars.apply", "parameters": [ { @@ -26231,7 +26347,7 @@ "Governed Ops: Backing Services" ], "summary": "Delete Overlay Var", - "description": "Revert a substrate/platform value to its chart default. Protected vars refuse.\n\n409 managed_by_provider, before any other check and whatever the caller holds,\nwhen DFE does not run the service and the value is one of its read_only paths.\n400 when the revert would lower a declared node or broker count, or leave it\nundeclared, unless the caller holds helmvars:override. An undeclared count falls\nto the chart or profile default, which the engine cannot read, so a revert that\nleaves one undeclared is refused whatever that default is.", + "description": "Revert an infra overlay value to its chart default. Protected vars refuse.\n\n409 managed_by_provider, before any other check and whatever the caller holds,\nwhen DFE does not run the service and the value is one of its read_only paths.\n400 when the revert would lower a declared node or broker count, or leave it\nundeclared, unless the caller holds helmvars:override. An undeclared count falls\nto the chart or profile default, which the engine cannot read, so a revert that\nleaves one undeclared is refused whatever that default is.", "operationId": "backing-services.overlays.vars.delete", "parameters": [ { @@ -27206,7 +27322,7 @@ "App Management" ], "summary": "Set App Config", - "description": "Write options the app declares, and environment keys it does not.\n\nJudged against the app's own contract before anything is committed, so a value\nthe app would refuse at startup leaves the deploy repo where it was rather than\nlanding a commit an operator then has to revert.\n\nA secret is written like any other option: it goes into the overlay as the rest\nof this surface writes one, and neither this response nor a read route on this\nsurface says what it is. A masked value written back as it was read keeps the\nstored credential; the mask where nothing is stored is a 400 ``masked_value``.\nA changed field beside a stored credential, in the same mapping or with the\ncredential one mapping down (``brokers`` beside ``sasl.password``), is a 400\n``credential_reentry_required`` until that mapping is written whole with its\ncredentials typed again. A setting inside another mapping beside it, such as\n``producer.retries``, is not. ``config`` and ``extraEnv`` are roots, so a\nsetting directly under either never needs one.\n\n409 where the deployment already decides the value: a config path the chart\nderives, or an `extraEnv` name the chart sets for this app.", + "description": "Write options the app declares, and environment keys it does not.\n\nJudged against the app's own contract before anything is committed, so a value\nthe app would refuse at startup leaves the deploy repo where it was rather than\nlanding a commit an operator then has to revert.\n\nA secret is written like any other option: it goes into the overlay as the rest\nof this surface writes one, and neither this response nor a read route on this\nsurface says what it is. A masked value written back as it was read keeps the\nstored credential. The mask where nothing is stored is a 400 ``masked_value``.\nA changed field beside a stored credential, in the same mapping or with the\ncredential one mapping down (``brokers`` beside ``sasl.password``), is a 400\n``credential_reentry_required`` until that mapping is written whole with its\ncredentials typed again. A setting inside another mapping beside it, such as\n``producer.retries``, is not. ``config`` and ``extraEnv`` are roots, so a\nsetting directly under either never needs one.\n\n409 where the deployment already decides the value: a config path the chart\nderives, or an `extraEnv` name the chart sets for this app.", "operationId": "apps.config.put", "parameters": [ { @@ -28155,7 +28271,7 @@ "App Management" ], "summary": "Relink App Files", - "description": "Re-resolve every link in the set to what its target now names.\n\nA tag link follows its tag; a version-pinned link advances to the artefact's\ncurrent version. This is the fix-once-roll-everywhere half of the library.", + "description": "Re-resolve every link in the set to what its target now names.\n\nA tag link follows its tag. A version-pinned link advances to the artefact's\ncurrent version. This is the fix-once-roll-everywhere half of the library.", "operationId": "apps.files.relink", "parameters": [ { @@ -28283,7 +28399,7 @@ "App Management" ], "summary": "Copy App Files", - "description": "Copy this instance's authored files onto another instance of the same app.\n\nA transform is written against one source; reusing it on another should not mean\nretyping it. Only the files move - the target keeps its own source binding,\nscaling and identity.", + "description": "Copy this instance's authored files onto another instance of the same app.\n\nA transform is written against one source. Reusing it on another should not mean\nretyping it. Only the files move - the target keeps its own source binding,\nscaling and identity.", "operationId": "apps.files.copy", "parameters": [ { @@ -29073,7 +29189,7 @@ "App Management" ], "summary": "Dry Run App File", - "description": "Run an authored file over real events from the source, and report each one.\n\nNothing is written: no topic, no table, no commit. ``content`` runs unsaved\ncontent, which is what makes this useful in an editor; omitted, the file\nalready in the overlay runs instead.", + "description": "Run an authored file over real events from the source, and report each one.\n\nNothing is written: no topic, no table, no commit. ``content`` runs unsaved\ncontent, which is what makes this useful in an editor. Omitted, the file\nalready in the overlay runs instead.", "operationId": "apps.files.dry-run", "parameters": [ { @@ -30740,7 +30856,7 @@ "Artefact Library" ], "summary": "Publish Version", - "description": "Publish content as a version.\n\nRe-sending identical content is a no-op naming the version that already holds\nit; sending different content at an existing version number is refused.", + "description": "Publish content as a version.\n\nRe-sending identical content is a no-op naming the version that already holds\nit. Sending different content at an existing version number is refused.", "operationId": "library.versions.create", "parameters": [ { @@ -31547,7 +31663,7 @@ "Governed Ops: Actions" ], "summary": "Get Action", - "description": "One defined action; a credential a legacy definition still carries comes back masked.", + "description": "One defined action. A credential a legacy definition still carries comes back masked.", "operationId": "governance.actions.get", "parameters": [ { @@ -31864,7 +31980,7 @@ "Governed Ops: Actions" ], "summary": "Invoke Action", - "description": "Invoke a defined action - gated on the action's OWN required_action.\n\n``body.params`` supplies values for the action's declared params (422 on a\nconstraint violation; omitted params take their defaults). A hunt or rule\ndocument the action would leave invalid is 422 ``invalid_document``, with the\nhunts API's own message. A change to the infra overlay meets the backing-services\nguards on what the action leaves, dry run included, whatever the caller holds:\n409 ``managed_by_provider`` for a read-only value of a service DFE does not run,\nthen 400 ``scale_down_refused`` where it lowers or un-declares a node or broker\ncount.\nDirect commit in dev/solo; a production+team invoke is routed to a review PR (or\n409 ``review_required`` when no forge is configured).", + "description": "Invoke a defined action - gated on the action's OWN required_action.\n\n``body.params`` supplies values for the action's declared params (422 on a\nconstraint violation. Omitted params take their defaults). A hunt or rule\ndocument the action would leave invalid is 422 ``invalid_document``, with the\nhunts API's own message. A change to the infra overlay meets the backing-services\nguards on what the action leaves, dry run included, whatever the caller holds:\n409 ``managed_by_provider`` for a read-only value of a service DFE does not run,\nthen 400 ``scale_down_refused`` where it lowers or un-declares a node or broker\ncount.\nDirect commit in dev/solo. A production+team invoke is routed to a review PR (or\n409 ``review_required`` when no forge is configured).", "operationId": "governance.actions.invoke", "parameters": [ { @@ -32586,7 +32702,7 @@ "Governed Ops: Gitops" ], "summary": "Put Auto Merge", - "description": "Toggle auto-merge. Enabling requires the deployment gate; disabling always works.", + "description": "Toggle auto-merge. Enabling requires the deployment gate. Disabling always works.", "operationId": "gitops.auto-merge.put", "requestBody": { "content": { @@ -32679,7 +32795,7 @@ "Governed Ops: Gitops" ], "summary": "List Classes", - "description": "The resource-class registry - what VarChange.cls may legally name.\n\nRegistry metadata only (no resource content), so any authenticated caller\nmay read it; the per-class listings below are gated by each class's grant.", + "description": "The resource-class registry - what VarChange.cls may legally name.\n\nRegistry metadata only (no resource content), so any authenticated caller\nmay read it. The per-class listings below are gated by each class's grant.", "operationId": "gitops.classes.list", "parameters": [ { @@ -33093,7 +33209,7 @@ "Governed Ops: Gitops" ], "summary": "Get Log", - "description": "Gitcrud audit log: every governed-ops git change, newest-first.\n\nFlat + cursor-paginated by default; ?group_by= buckets the page for\nsummaries. applied_revision (the Argo-synced SHA) turns state into\napplied/pending; without it every entry is 'committed'.", + "description": "Gitcrud audit log: every governed-ops git change, newest-first.\n\nFlat + cursor-paginated by default; ?group_by= buckets the page for\nsummaries. applied_revision (the Argo-synced SHA) turns state into\napplied/pending. Without it every entry is 'committed'.", "operationId": "gitops.log.list", "parameters": [ { @@ -33375,7 +33491,7 @@ "Governed Ops: Lifecycle" ], "summary": "Set Lifecycle", - "description": "Set a service's lifecycle state - per-service RBAC; pinned services are 404.", + "description": "Set a service's lifecycle state - per-service RBAC. Pinned services are 404.", "operationId": "lifecycle.post", "parameters": [ { @@ -33476,8 +33592,8 @@ "tags": [ "Rules: Authoring" ], - "summary": "From Hyperdx", - "description": "Strip a HyperDX query's time bounds -> {window}, ready to save as a rule.", + "summary": "Strip Search Query Time Bounds", + "description": "Strip a Search query's time bounds -> {window}, ready to save as a rule.", "operationId": "authoring.from-hyperdx", "requestBody": { "content": { @@ -34039,7 +34155,7 @@ "Client Config" ], "summary": "Client Config", - "description": "Runtime config for the web UI.\n\nAuthenticated but ungated: every console pane may read it, and the HyperDX URL\nit returns is internal to the deployment.", + "description": "Runtime config for the web UI.\n\nAuthenticated but ungated: every console pane may read it, and the Search URL\nit returns is internal to the deployment.", "operationId": "config.client", "responses": { "200": { @@ -34107,9 +34223,9 @@ "/api/v1/hyperdx/connection": { "get": { "tags": [ - "HyperDX" + "Search" ], - "summary": "Hyperdx Connection", + "summary": "Get Search Connection", "description": "Return the caller's OWN org connection - never another org's.\n\nA caller granted ``query:execute`` at system scope by a declared, unscoped role\nother than ``org_viewer`` gets the platform reader. Any other caller gets its org's pinned\n``dfe_org_`` user, whatever roles it holds at that org's scope. A caller\nthat resolves to zero or several separate orgs is refused (403) so isolation\nfails closed rather than guessing.", "operationId": "hyperdx.connection", "responses": { @@ -34178,10 +34294,10 @@ "/api/v1/hyperdx/sources": { "get": { "tags": [ - "HyperDX" + "Search" ], - "summary": "Hyperdx Sources", - "description": "List every HyperDX team and the DFE sources on it.\n\nA deploy writes its source to every team, so this is the read that says where\nit landed. 503 when HyperDX is not deployed or not answering -- an empty list\nwould read as \"the source is missing\", which is a different fault.", + "summary": "List Search Sources", + "description": "List every Search team and the DFE sources on it.\n\nA deploy writes its source to every team, so this is the read that says where\nit landed. 503 when Search is not deployed or not answering -- an empty list\nwould read as \"the source is missing\", which is a different fault.", "operationId": "hyperdx.sources", "responses": { "200": { @@ -39156,7 +39272,7 @@ }, "type": "object", "title": "DeclaredValue", - "description": "One value as the deploy repo declares it.\n\n``source`` names the overlay file it came from; a null source means the\ndeployment declared nothing and the chart or profile default applies. Those\ndefaults live in dfe-infra, which the engine does not read, so the API says\n\"not declared\" rather than guessing a number." + "description": "One value as the deploy repo declares it.\n\n``source`` names the overlay file it came from. A null source means the\ndeployment declared nothing and the chart or profile default applies. Those\ndefaults live in dfe-infra, which the engine does not read, so the API says\n\"not declared\" rather than guessing a number." }, "DefaultComparison": { "properties": { @@ -39712,7 +39828,7 @@ "_field_type" ], "title": "DraftColumn", - "description": "A ready-to-send meta-schema column derived from a discovered JSON path.\n\nShaped to drop straight into ``MetaSchemaAddVersionRequest.columns`` (the\ncreate-version endpoint) or a new meta-schema's version -- the UI sends these\nverbatim, no field mapping. ``type`` is derived from the first observed\nClickHouse type; for a multi-type path (``is_consistent=false``) confirm it\nbefore saving." + "description": "A ready-to-send meta-schema column derived from a discovered JSON path.\n\nShaped to drop straight into ``MetaSchemaAddVersionRequest.columns`` (the\ncreate-version endpoint) or a new meta-schema's version -- the UI sends these\nverbatim, no field mapping. ``type`` is derived from the first observed\nClickHouse type. For a multi-type path (``is_consistent=false``) confirm it\nbefore saving." }, "DryRunEventModel": { "properties": { @@ -39780,10 +39896,9 @@ }, "limit": { "type": "integer", - "maximum": 100.0, "minimum": 1.0, "title": "Limit", - "description": "Events to sample and run over", + "description": "Events to sample and run over, at most transform_validation.dry_run_max_events (100 by default), which a larger value is refused against", "default": 10 } }, @@ -40589,7 +40704,7 @@ "query" ], "title": "FromHyperdxRequest", - "description": "Body for turning a HyperDX query into rule SQL." + "description": "Body for turning a Search query into rule SQL." }, "GenerateRequest": { "properties": { @@ -41797,7 +41912,7 @@ }, "type": "object", "title": "HyperDXConfig", - "description": "Whether the UI links to HyperDX, and where." + "description": "Whether the UI links to Search, and where." }, "HyperDXConnection": { "properties": { @@ -41816,6 +41931,24 @@ "password": { "type": "string", "title": "Password" + }, + "platform": { + "type": "boolean", + "title": "Platform", + "description": "True for the platform reader, which reads every org" + }, + "database": { + "type": "string", + "title": "Database", + "description": "The DFE data database every seeded table lives in" + }, + "tables": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Tables", + "description": "Seeded table name by dfe-schemas manifest id" } }, "type": "object", @@ -41823,10 +41956,13 @@ "name", "host", "username", - "password" + "password", + "platform", + "database", + "tables" ], "title": "HyperDXConnection", - "description": "Connection material in the fork's shape (name, host URL, username, password)." + "description": "Connection material in the fork's shape, plus where its seed sources live." }, "HyperDXSourcesResponse": { "properties": { @@ -41840,19 +41976,19 @@ }, "type": "object", "title": "HyperDXSourcesResponse", - "description": "Where every deployed DFE source actually landed in HyperDX." + "description": "Where every deployed DFE source actually landed in Search." }, "HyperDXTeamSource": { "properties": { "id": { "type": "string", "title": "Id", - "description": "HyperDX source id on that team" + "description": "Search source id on that team" }, "name": { "type": "string", "title": "Name", - "description": "DFE source name; the HyperDX source carries the same one" + "description": "DFE source name; the Search source carries the same one" }, "table": { "additionalProperties": { @@ -41869,19 +42005,19 @@ "name" ], "title": "HyperDXTeamSource", - "description": "One HyperDX source on one team, as the fork holds it." + "description": "One Search source on one team, as dfe-hyperdx holds it." }, "HyperDXTeamSources": { "properties": { "team": { "type": "string", "title": "Team", - "description": "HyperDX team id" + "description": "Search team id" }, "team_name": { "type": "string", "title": "Team Name", - "description": "HyperDX team name: the ClickHouse user its members read as" + "description": "Search team name: the ClickHouse user its members read as" }, "sources": { "items": { @@ -41897,7 +42033,7 @@ "team_name" ], "title": "HyperDXTeamSources", - "description": "One HyperDX team and the DFE sources it holds." + "description": "One Search team and the DFE sources it holds." }, "IngestCredentialResponse": { "properties": { @@ -43123,7 +43259,7 @@ "versions" ], "title": "MetaSchema", - "description": "A schema for a ClickHouse table.\n\nAttributes:\n current: Current version of the schema.\n versions: Dictionary of versions and their metadata.\n path: Registry path key (e.g. ``aws/cloudtrail``); omitted from YAML on disk." + "description": "A schema for a ClickHouse table.\n\nAttributes:\n current: Current version of the schema.\n versions: Dictionary of versions and their metadata.\n path: Registry path key (e.g. ``aws/cloudtrail``). Omitted from YAML on disk." }, "MetaSchemaAddVersionRequest": { "properties": { @@ -44088,7 +44224,7 @@ "name" ], "title": "Org", - "description": "A customer organisation.\n\nAttributes:\n name: Primary identifier (filename stem).\n display_name: Human-readable label for UI display.\n org_ids: Tenant IDs used for ClickHouse row-level security filters.\n enabled: Whether this org is active.\n hyperdx_team_id: HyperDX team ID for this org's connection sync.\n hyperdx_team_api_key_env: Environment variable name holding the org's HyperDX team API key.\n ch_password_env: Environment variable name holding the ClickHouse password.\n created_at: ISO 8601 timestamp of creation.\n updated_at: ISO 8601 timestamp of last update." + "description": "A customer organisation.\n\nAttributes:\n name: Primary identifier (filename stem).\n display_name: Human-readable label for UI display.\n org_ids: Tenant IDs used for ClickHouse row-level security filters.\n enabled: Whether this org is active.\n hyperdx_team_id: dfe-hyperdx team ID for this org's connection sync.\n hyperdx_team_api_key_env: Environment variable name holding the org's dfe-hyperdx team API key.\n ch_password_env: Environment variable name holding the ClickHouse password.\n created_at: ISO 8601 timestamp of creation.\n updated_at: ISO 8601 timestamp of last update." }, "OrgResponse": { "properties": { @@ -47136,18 +47272,6 @@ "title": "Cache", "description": "Allow cached results", "default": true - }, - "store": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Store", - "description": "Target store (database/schema/topic) - only if query allows" } }, "type": "object", @@ -48117,6 +48241,105 @@ "title": "RuleBlockResponse", "description": "One block of the receiver's rule set: a source's rows, a profile's, or the default." }, + "RuleCondition": { + "properties": { + "field": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Field", + "description": "Field a test reads: a column of the source table, or a dotted path inside the record as it arrived (e.g. 'tags.collector.type', or '_json.tags.collector.type'). Each part is letters, digits, '_' and '-', starting with a letter or '_'. Absent on a group" + }, + "operator": { + "anyOf": [ + { + "type": "string", + "enum": [ + "equals", + "not_equals", + "exists", + "includes", + "starts_with", + "ends_with", + "lt", + "lte", + "gt", + "gte", + "in" + ] + }, + { + "type": "null" + } + ], + "title": "Operator", + "description": "How a test compares ``field`` to ``value``: equals (the default for a test), not_equals, exists, includes, starts_with, ends_with, lt, lte, gt, gte, in. Absent on a group", + "x-dfe-operand-kinds": { + "ends_with": "text", + "equals": "text_or_number", + "exists": "none", + "gt": "number_or_date", + "gte": "number_or_date", + "in": "list", + "includes": "text", + "lt": "number_or_date", + "lte": "number_or_date", + "not_equals": "text_or_number", + "starts_with": "text" + } + }, + "value": { + "anyOf": [ + { + "$ref": "#/components/schemas/Scalar" + }, + { + "items": { + "$ref": "#/components/schemas/Scalar" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Value", + "description": "Operand for the operator, by its kind: none for exists, text for includes, starts_with and ends_with, text or a number for equals and not_equals, a number or an ISO 8601 date or date-time for lt, lte, gt and gte, a list of texts or of numbers for in" + }, + "negate": { + "type": "boolean", + "title": "Negate", + "description": "Invert this test or group", + "default": false + }, + "all": { + "items": { + "$ref": "#/components/schemas/RuleCondition" + }, + "type": "array", + "title": "All", + "description": "A group that holds when every part holds" + }, + "any": { + "items": { + "$ref": "#/components/schemas/RuleCondition" + }, + "type": "array", + "title": "Any", + "description": "A group that holds when at least one part holds" + } + }, + "additionalProperties": false, + "type": "object", + "title": "RuleCondition", + "description": "One test on a field, or ``all`` or ``any`` of several, as the rule builder writes it.\n\nA test compares one ``field`` with an ``operator``. ``all`` holds when every\npart does and ``any`` when at least one does. Each part is a condition of its\nown, so groups nest, and ``negate`` inverts the test or group it sits on.", + "x-dfe-max-nesting": 4 + }, "RuleCreateRequest": { "properties": { "display_name": { @@ -48138,10 +48361,28 @@ "default": "medium" }, "user_sql": { - "type": "string", - "minLength": 1, + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "null" + } + ], "title": "User Sql", - "description": "Full detection query: SELECT ... FROM . WHERE ... (the FROM names the source table)" + "description": "Full detection query: SELECT ... FROM .
WHERE ... (the FROM names the source table). Give this or ``condition``, not both. A rule saved this way has no ``condition``" + }, + "condition": { + "anyOf": [ + { + "$ref": "#/components/schemas/RuleCondition" + }, + { + "type": "null" + } + ], + "description": "The rule's structured condition, which the engine compiles to its SQL and stores with it, so the builder reopens on it. Reads the table of ``source``. Give this or ``user_sql``, not both" }, "cel_filter": { "anyOf": [ @@ -48211,13 +48452,12 @@ "hyperdx" ], "title": "Source Type", - "description": "'raw' (plain SQL) or 'hyperdx' (HyperDX saved search format)", + "description": "'raw' (plain SQL) or 'hyperdx' (Search saved search format)", "default": "raw" } }, "type": "object", "required": [ - "user_sql", "name" ], "title": "RuleCreateRequest", @@ -48290,7 +48530,7 @@ "type": "string", "minLength": 1, "title": "Raw Sql", - "description": "The ClickHouse SELECT the HyperDX view renders to" + "description": "The ClickHouse SELECT the Search view renders to" }, "saved_search_name": { "anyOf": [ @@ -48302,7 +48542,7 @@ } ], "title": "Saved Search Name", - "description": "HyperDX saved-search name; seeds the rule id and label" + "description": "Search saved-search name; seeds the rule id and label" }, "severity": { "type": "string", @@ -48341,7 +48581,7 @@ "raw_sql" ], "title": "RuleFromHyperdxRequest", - "description": "Create a hunt rule from the SQL a HyperDX view runs.\n\nHyperDX renders the view to ``raw_sql`` and sends it here. The create\npipeline strips the UI meta (time bounds, LIMIT, ``__hdx_time_bucket``,\nSETTINGS) via the HyperDX sanitizer, and the engine derives a unique rule id\nfrom the saved-search name. The caller gets that id back and opens\n``/rules/{id}`` -- no id to invent, no IndexedDB round-trip." + "description": "Create a hunt rule from the SQL a Search view runs.\n\nSearch renders the view to ``raw_sql`` and sends it here. The create\npipeline strips the UI meta (time bounds, LIMIT, ``__hdx_time_bucket``,\nSETTINGS) via the dfe-hyperdx sanitizer, and the engine derives a unique rule id\nfrom the saved-search name. The caller gets that id back and opens\n``/rules/{id}`` -- no id to invent, no IndexedDB round-trip." }, "RuleFromHyperdxResponse": { "properties": { @@ -48380,7 +48620,7 @@ "display_name" ], "title": "RuleFromHyperdxResponse", - "description": "The rule created from a HyperDX query." + "description": "The rule created from a Search query." }, "RuleOrderRequest": { "properties": { @@ -48511,6 +48751,146 @@ "title": "RuleOrderResponse", "description": "The field's blocks as the reorder leaves them." }, + "RulePreviewRequest": { + "properties": { + "source": { + "type": "string", + "title": "Source", + "description": "Source label whose table the condition reads" + }, + "condition": { + "$ref": "#/components/schemas/RuleCondition" + }, + "cel_filter": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cel Filter", + "description": "CEL expression ANDed in, as on save" + }, + "cost_window_minutes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Cost Window Minutes", + "description": "Lookback window in minutes the volume preview counts over. Absent or 0 uses the deployment's preview window." + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name", + "description": "The rule being edited. The volume preview then counts the orgs of the hunts that run it and of the hunt it names, as its save would" + }, + "hunt_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Hunt Name", + "description": "The hunt the rule names as its own, which the count follows. Defaults to the stored rule's" + } + }, + "type": "object", + "required": [ + "source", + "condition" + ], + "title": "RulePreviewRequest", + "description": "A condition to compile and check as a save would, without saving it." + }, + "RulePreviewResponse": { + "properties": { + "user_sql": { + "type": "string", + "title": "User Sql", + "description": "The rule SQL the condition compiles to, empty when it does not" + }, + "source_db": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Db" + }, + "source_table": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source Table" + }, + "where_clause": { + "type": "string", + "title": "Where Clause", + "description": "The detection WHERE the rule would store" + }, + "sql_errors": { + "items": { + "$ref": "#/components/schemas/SqlValidationError" + }, + "type": "array", + "title": "Sql Errors", + "description": "Why a save would be refused as invalid" + }, + "matches_everything": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Matches Everything", + "description": "Why a save would be refused for matching every event, when it would" + }, + "cost_estimate": { + "anyOf": [ + { + "$ref": "#/components/schemas/CostEstimate" + }, + { + "type": "null" + } + ] + } + }, + "type": "object", + "required": [ + "user_sql", + "where_clause" + ], + "title": "RulePreviewResponse", + "description": "What a save of the condition would compile to and find, and nothing written." + }, "RuleResponse": { "properties": { "name": { @@ -48564,6 +48944,17 @@ ], "title": "Cel Filter" }, + "condition": { + "anyOf": [ + { + "$ref": "#/components/schemas/RuleCondition" + }, + { + "type": "null" + } + ], + "description": "The structured condition the SQL was compiled from, absent for a rule written as SQL" + }, "original_sql": { "type": "string", "title": "Original Sql" @@ -48716,10 +49107,28 @@ "default": "medium" }, "user_sql": { - "type": "string", - "minLength": 1, + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "null" + } + ], "title": "User Sql", - "description": "Full detection query: SELECT ... FROM .
WHERE ... (the FROM names the source table)" + "description": "Full detection query: SELECT ... FROM .
WHERE ... (the FROM names the source table). Give this or ``condition``, not both. A rule saved this way has no ``condition``" + }, + "condition": { + "anyOf": [ + { + "$ref": "#/components/schemas/RuleCondition" + }, + { + "type": "null" + } + ], + "description": "The rule's structured condition, which the engine compiles to its SQL and stores with it, so the builder reopens on it. Reads the table of ``source``. Give this or ``user_sql``, not both" }, "cel_filter": { "anyOf": [ @@ -48777,9 +49186,6 @@ } }, "type": "object", - "required": [ - "user_sql" - ], "title": "RuleUpdateRequest", "description": "Update an existing hunt rule (re-runs creation pipeline, and ``source_type`` is not accepted)." }, @@ -48801,7 +49207,7 @@ "anomaly" ], "title": "SampleMode", - "description": "How to pick the sample.\n\n- ``recent`` - newest rows first (fast tail; ClickHouse ORDER BY ts DESC,\n Kafka reads from the partition high-watermark backwards).\n- ``random`` - uniform-ish random rows (fair distribution, no recency bias).\n- ``smart`` - logreducer representative/diverse sample (default). Gated.\n- ``anomaly`` - logreducer isolation-forest outliers (the weird events). Gated." + "description": "How to pick the sample.\n\n- ``recent`` - newest rows first (fast tail, ClickHouse ORDER BY ts DESC,\n Kafka reads from the partition high-watermark backwards).\n- ``random`` - uniform-ish random rows (fair distribution, no recency bias).\n- ``smart`` - logreducer representative/diverse sample (default). Gated.\n- ``anomaly`` - logreducer isolation-forest outliers (the weird events). Gated." }, "SampleRecord": { "properties": { @@ -48969,7 +49375,7 @@ }, "type": "object", "title": "SampleRequest", - "description": "A request to sample a source.\n\nProvide EITHER a registered ``source`` (its CH table / land topic are\nresolved for you) OR an explicit ``table``/``topic`` (ad-hoc - for a source\nthat is not registered yet, e.g. AI onboarding). ``filter`` (ClickHouse\nbackend only) must be one condition over the sampled table's columns; it is\nreplaced by the condition rendered from its parse tree, and anything else is\nrefused when the request is built." + "description": "A request to sample a source.\n\nProvide EITHER a registered ``source`` (its CH table / land topic are\nresolved for you) OR an explicit ``table``/``topic`` (ad-hoc - for a source\nthat is not registered yet, e.g. AI onboarding). ``filter`` (ClickHouse\nbackend only) must be one condition over the sampled table's columns. It is\nreplaced by the condition rendered from its parse tree, and anything else is\nrefused when the request is built." }, "SampleResult": { "properties": { @@ -49229,6 +49635,19 @@ "title": "ScaffoldRequest", "description": "Body for a starter SELECT over a table's columns." }, + "Scalar": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "number" + } + ] + }, "ScalingRequest": { "properties": { "replica_count": { @@ -49894,7 +50313,7 @@ } ], "title": "Hyperdx Source Teams", - "description": "How many HyperDX teams now carry a source over this source's table" + "description": "How many Search teams now carry a source over this source's table" }, "hyperdx_source_error": { "anyOf": [ @@ -49906,7 +50325,7 @@ } ], "title": "Hyperdx Source Error", - "description": "Why HyperDX was not pointed at the table. Never fails the deploy - the schema is live and HyperDX may be down or not deployed at all." + "description": "Why Search was not pointed at the table. Never fails the deploy - the schema is live and Search may be down or not deployed at all." }, "restart_required": { "items": { @@ -50512,7 +50931,7 @@ "config" ], "title": "ServiceConfigDetail", - "description": "Full service config. Inner config is dynamic (schema-less mode)." + "description": "One service config as its instance runs it: the stored keys over the app's defaults." }, "ServiceConfigSummary": { "properties": { @@ -50775,7 +51194,7 @@ "default_ttl_days" ], "title": "SetupStatus", - "description": "Pre-login setup snapshot: the wizard state plus what is configured.\n\nAccounts are deliberately absent. Whether a real user exists is reported\nthrough the ``first_user`` step; the account list itself is never served\nto an unauthenticated caller." + "description": "Pre-login setup snapshot: the wizard state plus what is configured.\n\nAccounts are deliberately absent. Whether a real user exists is reported\nthrough the ``first_user`` step. The account list itself is never served\nto an unauthenticated caller." }, "SetupStep": { "properties": { @@ -50857,7 +51276,7 @@ } ], "title": "Type", - "description": "Optional ClickHouse type to CAST the value to (e.g. 'String', 'UInt32')" + "description": "Optional ClickHouse type for the value (e.g. 'String', 'UInt32')" } }, "type": "object", @@ -50865,7 +51284,7 @@ "sigma_field" ], "title": "SigmaViewColumn", - "description": "One column exposed by a Sigma source-view.\n\nA column maps a standard ``sigma_field`` (the alias the view exposes) to EITHER\na real table column (``source_column``) OR a dotted path inside the source's\n``_json`` column (``json_path``) - exactly one of the two. ``type`` is an\noptional ClickHouse type the extracted value is CAST to (mainly for a\nJSON-derived column, whose subcolumn is otherwise a ``Dynamic``). This is the\nSigma-named shape of :class:`~dfe_engine.fieldmap.remap_view.RemapColumn`." + "description": "One column exposed by a Sigma source-view.\n\nA column maps a standard ``sigma_field`` (the alias the view exposes) to EITHER\na real table column (``source_column``) OR a dotted path inside the source's\n``_json`` column (``json_path``) - exactly one of the two. ``type`` is an\noptional ClickHouse type for the value, read as RemapColumn reads it. This is the\nSigma-named shape of :class:`~dfe_engine.fieldmap.remap_view.RemapColumn`." }, "SigmaViewDefinition": { "properties": { @@ -50900,7 +51319,7 @@ "source_name" ], "title": "SigmaViewDefinition", - "description": "A CRUD-managed Sigma view definition for one source.\n\nKeyed (in the store) by ``source_name``; the generated view targets table\n``source_name`` and is named ``{source_name}_sigma``. ``include_source_columns``\nappends ``SELECT *`` so the base table columns remain visible alongside the\nSigma-aligned aliases (the legacy view's behaviour)." + "description": "A CRUD-managed Sigma view definition for one source.\n\nKeyed (in the store) by ``source_name``. The generated view targets table\n``source_name`` and is named ``{source_name}_sigma``. ``include_source_columns``\nappends ``SELECT *`` so the base table columns remain visible alongside the\nSigma-aligned aliases (the legacy view's behaviour)." }, "SigmaViewResult": { "properties": { @@ -50983,7 +51402,7 @@ }, "type": "object", "title": "SigmaViewWriteRequest", - "description": "Create/replace body for a source's Sigma view definition (source_name is the path).\n\nEach column maps a Sigma field to a real source column OR a path inside the\nsource's ``_json`` payload (a JSON-derived column); the ``SigmaViewColumn``\nvalidator enforces exactly one per column." + "description": "Create/replace body for a source's Sigma view definition (source_name is the path).\n\nEach column maps a Sigma field to a real source column OR a path inside the\nsource's ``_json`` payload (a JSON-derived column). The ``SigmaViewColumn``\nvalidator enforces exactly one per column." }, "SourceBundle-Input": { "properties": { @@ -51980,8 +52399,7 @@ "version": { "type": "string", "title": "Version", - "description": "Common header version (semver)", - "default": "1.0.3" + "description": "Common header version (semver); the profile's current version when omitted" } }, "type": "object", @@ -54080,7 +54498,7 @@ }, "type": "object", "title": "SystemDefaultsPatch", - "description": "A partial change. Omitted fields stay as they are; null clears that override." + "description": "A partial change. Omitted fields stay as they are. Null clears that override." }, "SystemDefaultsUpdate": { "properties": { @@ -54431,7 +54849,7 @@ "error" ], "title": "TopicFailure", - "description": "One topic the broker would not do the thing to; the broker's own text is in the log." + "description": "One topic the broker would not do the thing to. The broker's own text is in the log." }, "TopicRemoveResponse": { "properties": { @@ -54622,7 +55040,7 @@ }, "type": "object", "title": "TopicUpdateResponse", - "description": "Outcome of a converge pass.\n\n``refused`` is what DFE declined to do (a partition decrease, a replication\nfactor change); ``failed`` is what the broker rejected. They are different\nproblems with different fixes, so they are different lists." + "description": "Outcome of a converge pass.\n\n``refused`` is what DFE declined to do (a partition decrease, a replication\nfactor change). ``failed`` is what the broker rejected. They are different\nproblems with different fixes, so they are different lists." }, "TotalsResponse": { "properties": { @@ -55489,7 +55907,7 @@ }, "type": "array", "title": "Org Ids", - "description": "Orgs this user can browse in the data plane (HyperDX). Empty means no org-scoped data access." + "description": "Orgs this user can browse in the data plane (Search). Empty means no org-scoped data access." }, "external": { "type": "boolean", diff --git a/packages/dfe-engine-types/types/index.d.ts b/packages/dfe-engine-types/types/index.d.ts index 4740eb80f..f1460d89f 100644 --- a/packages/dfe-engine-types/types/index.d.ts +++ b/packages/dfe-engine-types/types/index.d.ts @@ -18,7 +18,7 @@ export interface paths { * @description Authenticate with local credentials and receive a JWT token. * * The password check runs off the event loop. Failed attempts back off per - * username and per client address (``auth.login_throttle``); a waiting attempt is + * username and per client address (``auth.login_throttle``). A waiting attempt is * refused with 429 before the password is checked. */ post: operations["auth.login"]; @@ -90,8 +90,8 @@ export interface paths { * groups or orgs, because its token carries none until the change. * * ``hyperdx_role`` and ``hyperdx_identity`` are what dfe-hyperdx takes a - * session's dashboard role and team from; it caches this answer for 30 seconds, - * so a group change reaches HyperDX in that window rather than at token expiry. + * session's dashboard role and team from. It caches this answer for 30 seconds, + * so a group change reaches dfe-hyperdx in that window rather than at token expiry. */ get: operations["auth.me.list"]; put?: never; @@ -139,7 +139,7 @@ export interface paths { * configured deployment does not serve its inventory to anonymous callers. * The exception is the name and display name of each enabled OIDC provider, * which stay (no configuration) because the login screen needs to know which - * IdPs to offer and what to call them. Accounts are never returned; the + * IdPs to offer and what to call them. Accounts are never returned. The * ``first_user`` step reports whether a real (non break-glass) user exists. */ get: operations["auth.setup-status.list"]; @@ -421,7 +421,7 @@ export interface paths { * @description Poll whether an account's password has merged to the deploy repo's main. * * Step 2 of the review-PR path for the local admin and ``breakglass``: the UI - * polls this after the operator merges the PR; it fetches remote main and flips + * polls this after the operator merges the PR. It fetches remote main and flips * ``merged`` true. Durable immediately in the auto-merge and file-share modes. A * regular user is never git-persisted, so it reports not-git-backed (durable in * its own store). @@ -550,7 +550,7 @@ export interface paths { put?: never; /** * Add Member - * @description Add a member to a group (idempotent; checked at the group's scope). + * @description Add a member to a group (idempotent, checked at the group's scope). */ post: operations["auth.groups.members.create"]; delete?: never; @@ -790,7 +790,7 @@ export interface paths { * Update Provider * @description Update an OIDC provider configuration (admin only). * - * A secret the body omits, value and env var name alike, keeps what the provider already holds, so an update that only flips ``enabled`` does not strand a stored credential; an empty env var name clears the name and keeps the stored copy. A secret the body names an env var for and sends no value for moves onto that env var and its stored copy is deleted once the update is saved, unless the name is the one already held with nothing stored. A move onto an env var the engine does not set is refused (``env_var_not_set``). Any update that touches more than ``enabled`` or ``display_name`` must leave the provider passing the field rules. Both are checked before a secret is written or deleted. + * A secret the body omits, value and env var name alike, keeps what the provider already holds, so an update that only flips ``enabled`` does not strand a stored credential. An empty env var name clears the name and keeps the stored copy. A secret the body names an env var for and sends no value for moves onto that env var and its stored copy is deleted once the update is saved, unless the name is the one already held with nothing stored. A move onto an env var the engine does not set is refused (``env_var_not_set``). Any update that touches more than ``enabled`` or ``display_name`` must leave the provider passing the field rules. Both are checked before a secret is written or deleted. */ put: operations["auth.oidc-providers.apply"]; post?: never; @@ -887,7 +887,7 @@ export interface paths { * List Orgs * @description List organisations visible to the caller, paginated. * - * System-scope org:read holders see every org; org-scope holders see + * System-scope org:read holders see every org. Org-scope holders see * only the orgs their grants cover. */ get: operations["orgs.list"]; @@ -896,7 +896,7 @@ export interface paths { * Create Org * @description Create a new customer organisation (admin only). * - * If HyperDX integration is enabled, the lifecycle manager handles + * If the Search integration is enabled, the lifecycle manager handles * team creation as part of org provisioning. Failure is non-fatal. * * A hunt already naming the org, such as one whose org was deleted, has the new @@ -1071,7 +1071,7 @@ export interface paths { * @description List sources with pagination, search, filtering, and a full object tree. * * The landing source (``main``) is always the first item when it is in the - * result set; remaining sources keep the requested sort. A caller held to its + * result set. Remaining sources keep the requested sort. A caller held to its * orgs does not see a fetcher source bound to another org. */ get: operations["sources.list"]; @@ -1373,7 +1373,7 @@ export interface paths { * * A delete production+team sends to review answers ``review_required`` and * touches nothing else: main still carries the source, so its topics, records and - * HyperDX source stay until the branch is merged. + * Search source stay until the branch is merged. */ delete: operations["sources.delete"]; options?: never; @@ -1452,7 +1452,7 @@ export interface paths { * * Reads the loader's per-table counter out of the otel tables over a bounded * five-minute window, so the console can put a number beside a source without - * the operator opening HyperDX. It answers 200 with nulls where the series is + * the operator opening Search. It answers 200 with nulls where the series is * absent: a source that was only just defined has nothing to report, and that * is not an error. */ @@ -1506,7 +1506,7 @@ export interface paths { * * ``enable`` / ``disable`` / ``dormant`` / ``delete`` apply immediately. * ``deploy`` submits one ``source:deploy`` background task per accepted source - * (poll ``GET /operations/{operation}``); refused names land in ``failed``. + * (poll ``GET /operations/{operation}``). Refused names land in ``failed``. * * An action that applies immediately reports the one reconcile it ends with, as * a single-source write does. @@ -1533,7 +1533,7 @@ export interface paths { * * Recompiles every stack-scoped routing block (receiver, loader, archiver) and * deploys, syncs or removes the instances of every instance-scoped app (a fetcher - * per active fetcher-based source). Every source write does this on its own; this + * per active fetcher-based source). Every source write does this on its own. This * route is the retry when one reported ``apps_sync_error``, and the pass that * deletes a stranded ``_load`` topic a deploy reported in ``topics_pending_removal``. */ @@ -1833,7 +1833,10 @@ export interface paths { }; /** * Get Service Config - * @description Get a full service config by service + instance, every credential masked. + * @description A service config as its instance runs it, every credential masked. + * + * The stored keys over the app's own defaults, read from its mounted contract. + * With no contract mounted only the stored keys are shown. */ get: operations["services.get"]; /** @@ -1849,7 +1852,8 @@ export interface paths { * stored behind it, or in a list entry that cannot be told apart, is a 400 * ``masked_value`` and nothing is saved. A changed field beside a masked secret, * in the same mapping or with the secret one mapping down, is a 400 - * ``credential_reentry_required``: the secret is typed again. + * ``credential_reentry_required``: the secret is typed again. A value the app's + * contract refuses is a 422 ``invalid_config``. */ put: operations["services.apply"]; post?: never; @@ -1916,7 +1920,7 @@ export interface paths { * * The deployer supplies the list, so an empty one means it listed none. Gated to * the admin-class roles, which hold ``deployment:*`` or ``*``: the list maps the - * deployment's consoles. Links only; nothing here carries a credential. + * deployment's consoles. Links only. Nothing here carries a credential. */ get: operations["deployment.admin-links.list"]; put?: never; @@ -2032,11 +2036,12 @@ export interface paths { * Create Rule * @description Create a new hunt rule via RuleCreationService. * - * The service sanitizes the SQL, applies CEL->SQL transpilation, - * validates column references, and optionally estimates query cost. A rule - * whose SQL the hunt runner could not compile is refused with 422. The cost - * preview counts only the orgs the hunts running the rule read, cut to the orgs - * its author may read. + * The rule is written as SQL or as a structured ``condition``, which the engine + * compiles to the SQL and stores with it. The service sanitizes the SQL, + * applies CEL->SQL transpilation, validates column references, and optionally + * estimates query cost. A rule whose SQL the hunt runner could not compile is + * refused with 422. The cost preview counts only the orgs the hunts running the + * rule read, cut to the orgs its author may read. * * A production+team write is routed to a review branch instead of the branch the * runner git-syncs, and the ``X-DFE-Review-Required`` header says so. @@ -2058,8 +2063,8 @@ export interface paths { get?: never; put?: never; /** - * Create Rule From Hyperdx - * @description Create a hunt rule from the SQL a HyperDX view renders to. + * Create Rule From Search + * @description Create a hunt rule from the SQL a Search view renders to. * * Wraps the create pipeline with ``source_type='hyperdx'`` and auto-derives a * unique rule id from the saved-search name, so the caller need not supply one. @@ -2096,6 +2101,32 @@ export interface paths { patch?: never; trace?: never; }; + "/api/v1/rules/preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Preview Rule + * @description Compile a condition and check it exactly as a save would, writing nothing. + * + * Runs the creation pipeline of ``POST /rules`` (compile, parse, the forbidden-keyword + * and column checks, the matches-everything check and the alert-volume preview) under the + * same org fence, and stops before the save. A condition the save would refuse comes back + * with 200 and its reasons in ``sql_errors`` or ``matches_everything``, so a builder can + * show them as the author edits. A body that is not a condition at all is 422. + */ + post: operations["rules.preview"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/v1/rules/{name}": { parameters: { query?: never; @@ -2112,6 +2143,9 @@ export interface paths { * Update Rule * @description Replace a detection rule (re-runs creation pipeline, preserves created_at). * + * The replacement is written as SQL or as a ``condition``, as on create, and a + * rule replaced with SQL no longer carries a condition. + * * A replacement the hunt runner could not compile is refused with 422 and the * stored rule is left as it was. A production+team write is routed to a review * branch instead of the branch the runner git-syncs, and the @@ -2276,7 +2310,7 @@ export interface paths { * @description Conditions that leave the engine degraded while it keeps serving. * * A refused YAML write keeps the old file or the old deploy-repo content, so reads - * stay correct and readiness is not failed; this is where the refusal shows. + * stay correct and readiness is not failed. This is where the refusal shows. */ get: operations["system.status"]; put?: never; @@ -2326,7 +2360,7 @@ export interface paths { * The engine's own tables and every deployed source's table are brought to the new * effective default in this request, with ``ALTER TABLE ... MODIFY TTL`` (or * ``REMOVE TTL`` for 0). A table that declares its own TTL is left alone. A - * ClickHouse failure answers 502 with the override ALREADY committed; sending the + * ClickHouse failure answers 502 with the override ALREADY committed. Sending the * same value again applies it. */ put: operations["system.retention.apply"]; @@ -2359,8 +2393,8 @@ export interface paths { * @description Store the named defaults. Only ttl_days is applied to live tables. * * Omitted fields are left alone. null clears that override. Common-header type, - * version and engine are what a source inherits the next time it is deployed; - * this request does not rewrite them onto live tables. A patch that names + * version and engine are what a source inherits the next time it is deployed. + * This request does not rewrite them onto live tables. A patch that names * ttl_days stores it and then runs the same reconcile as PUT /retention. */ patch: operations["system.defaults.update"]; @@ -2557,7 +2591,7 @@ export interface paths { * Hunts execute in the separate dfe-hunt-runner service (pull-based, coordinated * via ClickHouse), not in this API process, so ``runners`` counts the runners that * beat within their last two polls and ``running`` is whether any did. For "is this - * hunt running", read the per-hunt ``running`` on the hunts list; ``hunt_count`` is + * hunt running", read the per-hunt ``running`` on the hunts list. ``hunt_count`` is * the configured-hunt count. */ get: operations["hunts.status"]; @@ -2628,7 +2662,7 @@ export interface paths { * @description Delete a hunt configuration. * * A production+team delete is routed to a review branch, so the runner keeps - * executing the hunt until that branch is merged; ``X-DFE-Review-Required`` says so. + * executing the hunt until that branch is merged. ``X-DFE-Review-Required`` says so. */ delete: operations["hunts.delete"]; options?: never; @@ -2652,13 +2686,13 @@ export interface paths { * The pull model is kept. Nothing is pushed at the runner and no listener is added * -- the fire is written into the coordination state, and the runner that is * already running picks it up on its next poll, through the same claim that stops - * a hunt double-running. 202 says it is queued, not that it has run; the response + * a hunt double-running. 202 says it is queued, not that it has run. The response * carries the poll interval so the caller knows the longest wait before it starts. * * A hunt with no rate schedule is not something the runner ticks, so a queued run * for one sits unclaimed. That is the schedule's shape, not a failure here. * - * 503 is reserved for ClickHouse actually being unreachable; any other failure to + * 503 is reserved for ClickHouse actually being unreachable. Any other failure to * write the request is a 500, so a bug here never reads as an outage. */ post: operations["hunts.run"]; @@ -2878,7 +2912,7 @@ export interface paths { }; /** * List Samples - * @description List recent sample tasks (most recent first); a caller held to its orgs sees only theirs. + * @description List recent sample tasks (most recent first). A caller held to its orgs sees only theirs. */ get: operations["samples.list"]; put?: never; @@ -3503,7 +3537,7 @@ export interface paths { * * Returns one record per path with observed types, a suggested column name, * and whether the path is already promoted. ``?samples=N`` adds random - * distinct example values; ``?stats=true`` adds coverage + distinct counts. + * distinct example values. ``?stats=true`` adds coverage + distinct counts. * * A caller without a platform grant holding ``schema:read`` reads only its own * orgs' rows, as the sampler holds it, and a table it cannot be held on is 403. @@ -3530,7 +3564,7 @@ export interface paths { * * Resolves the requested ``version`` (or the source's current version). A * version with a ``meta_schema`` uses ``db.`` only after that version - * is deployed and the table exists; otherwise rows are read from + * is deployed and the table exists. Otherwise rows are read from * ``db.`` filtered by the version's match rule. * * Intended for inspecting real data while authoring a match condition or CEL @@ -3570,7 +3604,7 @@ export interface paths { * ``?dry_run=true`` returns the proposed diff and DDL without forking core schemas, * adding meta-schema versions, or updating the source. A core source, such as the * landing source ``main``, is refused with 409 before any schema is resolved or - * written, dry run included; its ``json-paths`` and ``sample-rows`` reads stay open. + * written, dry run included. Its ``json-paths`` and ``sample-rows`` reads stay open. */ post: operations["schemas.promote-field"]; delete?: never; @@ -3594,7 +3628,7 @@ export interface paths { put?: never; /** * Create User - * @description Provision a user. IdP-owned; local password is randomised when omitted. + * @description Provision a user. IdP-owned. Local password is randomised when omitted. * * A password the IdP does send is held to the same length floor as every other * password the API sets, and one under it is refused rather than replaced. @@ -3794,7 +3828,7 @@ export interface paths { * @description Generate Sigma view DDL for all sources (stored definitions win over field maps). * * Defaults to the data database, since that is where a propagated hunt reads - * the view from (``{source}_sigma``); an explicit ``database`` still overrides it. + * the view from (``{source}_sigma``). An explicit ``database`` still overrides it. */ post: operations["sigma.views.create"]; delete?: never; @@ -3825,12 +3859,12 @@ export interface paths { * @description Generate (preview) Sigma view DDL for a source. * * A stored view definition drives generation - including its JSON-derived - * columns - when one exists; otherwise falls back to the static field maps via + * columns - when one exists. Otherwise falls back to the static field maps via * the source mapper, keeping only the mappings whose column the source's table - * carries. Returns the DDL string; does NOT execute it against ClickHouse. + * carries. Returns the DDL string. Does NOT execute it against ClickHouse. * * Defaults to the data database, since that is where a propagated hunt reads - * the view from (``{source}_sigma``); an explicit ``database`` still overrides it. + * the view from (``{source}_sigma``). An explicit ``database`` still overrides it. */ post: operations["sigma.views.post"]; /** @@ -3946,7 +3980,7 @@ export interface paths { put?: never; /** * Disable Provider - * @description Disable a provider (blocks scheduled polling; a manual sync is refused). + * @description Disable a provider (blocks scheduled polling, a manual sync is refused). */ post: operations["sigma.providers.disable"]; delete?: never; @@ -3968,7 +4002,7 @@ export interface paths { * Sync Provider Endpoint * @description Trigger a provider sync into the catalogue. * - * Submitted to the task manager (a git-repo clone is long-running); blocks up to + * Submitted to the task manager (a git-repo clone is long-running). Blocks up to * ``wait`` seconds for inline completion, else returns ``pending`` - poll via * GET /sigma/syncs/{task_id}. */ @@ -4058,7 +4092,7 @@ export interface paths { put?: never; /** * Adopt Catalogue Rule - * @description Detach a rule from upstream (pin its content; a re-import records drift only). + * @description Detach a rule from upstream (pin its content, a re-import records drift only). */ post: operations["sigma.catalogue.adopt"]; delete?: never; @@ -4144,11 +4178,11 @@ export interface paths { * the matching source's ``{source}_sigma`` view and stores a DFE rule (with a * ``sigma_rule_id`` back-reference), then binds it into a per-source hunt. Drifted * or hand-edited bindings are reported ``skipped_drifted`` unless ``force``. - * Submitted to the task manager; blocks up to ``wait`` seconds for inline + * Submitted to the task manager. Blocks up to ``wait`` seconds for inline * completion, else returns ``pending`` - poll via GET /sigma/propagations/{id}. * * A production+team run commits each generated rule and hunt to its own review - * branch rather than the branch the hunt runner syncs; the report carries every + * branch rather than the branch the hunt runner syncs. The report carries every * branch and PR, and ``X-DFE-Review-Required`` says so on a run that completed * inline. 422 ``unknown_org`` when ``hunt_customers`` names no registered org. */ @@ -4375,7 +4409,7 @@ export interface paths { }; /** * List Overlays - * @description List substrate/platform overlay resources in the deploy repo's infra/ dir. + * @description List infra overlay resources in the deploy repo's infra/ dir. */ get: operations["backing-services.overlays"]; put?: never; @@ -4438,21 +4472,21 @@ export interface paths { get?: never; /** * Set Overlay Var - * @description Set a substrate/platform value. + * @description Set an infra overlay value. * * 409 managed_by_provider, before any other check, when DFE does not run the - * service and the value is one of its read_only paths; helmvars:override does not + * service and the value is one of its read_only paths. helmvars:override does not * lift it. 403 with the policy that blocked it when the var is protected - the * storage model, the data-layer modes and the disk size are decided at deploy, and * moving one on a live deployment is a data migration. 400 when the value would * lower a declared node or broker count, or leave it undeclared (a parent map that - * omits it), which loses data rather than capacity; helmvars:override does not lift it. + * omits it), which loses data rather than capacity. helmvars:override does not lift it. */ put: operations["backing-services.overlays.vars.apply"]; post?: never; /** * Delete Overlay Var - * @description Revert a substrate/platform value to its chart default. Protected vars refuse. + * @description Revert an infra overlay value to its chart default. Protected vars refuse. * * 409 managed_by_provider, before any other check and whatever the caller holds, * when DFE does not run the service and the value is one of its read_only paths. @@ -4609,7 +4643,7 @@ export interface paths { * A secret is written like any other option: it goes into the overlay as the rest * of this surface writes one, and neither this response nor a read route on this * surface says what it is. A masked value written back as it was read keeps the - * stored credential; the mask where nothing is stored is a 400 ``masked_value``. + * stored credential. The mask where nothing is stored is a 400 ``masked_value``. * A changed field beside a stored credential, in the same mapping or with the * credential one mapping down (``brokers`` beside ``sasl.password``), is a 400 * ``credential_reentry_required`` until that mapping is written whole with its @@ -4747,7 +4781,7 @@ export interface paths { * Relink App Files * @description Re-resolve every link in the set to what its target now names. * - * A tag link follows its tag; a version-pinned link advances to the artefact's + * A tag link follows its tag. A version-pinned link advances to the artefact's * current version. This is the fix-once-roll-everywhere half of the library. */ post: operations["apps.files.relink"]; @@ -4770,7 +4804,7 @@ export interface paths { * Copy App Files * @description Copy this instance's authored files onto another instance of the same app. * - * A transform is written against one source; reusing it on another should not mean + * A transform is written against one source. Reusing it on another should not mean * retyping it. Only the files move - the target keeps its own source binding, * scaling and identity. */ @@ -4870,7 +4904,7 @@ export interface paths { * @description Run an authored file over real events from the source, and report each one. * * Nothing is written: no topic, no table, no commit. ``content`` runs unsaved - * content, which is what makes this useful in an editor; omitted, the file + * content, which is what makes this useful in an editor. Omitted, the file * already in the overlay runs instead. */ post: operations["apps.files.dry-run"]; @@ -5104,7 +5138,7 @@ export interface paths { * @description Publish content as a version. * * Re-sending identical content is a no-op naming the version that already holds - * it; sending different content at an existing version number is refused. + * it. Sending different content at an existing version number is refused. */ post: operations["library.versions.create"]; delete?: never; @@ -5226,7 +5260,7 @@ export interface paths { }; /** * Get Action - * @description One defined action; a credential a legacy definition still carries comes back masked. + * @description One defined action. A credential a legacy definition still carries comes back masked. */ get: operations["governance.actions.get"]; put?: never; @@ -5291,14 +5325,14 @@ export interface paths { * @description Invoke a defined action - gated on the action's OWN required_action. * * ``body.params`` supplies values for the action's declared params (422 on a - * constraint violation; omitted params take their defaults). A hunt or rule + * constraint violation. Omitted params take their defaults). A hunt or rule * document the action would leave invalid is 422 ``invalid_document``, with the * hunts API's own message. A change to the infra overlay meets the backing-services * guards on what the action leaves, dry run included, whatever the caller holds: * 409 ``managed_by_provider`` for a read-only value of a service DFE does not run, * then 400 ``scale_down_refused`` where it lowers or un-declares a node or broker * count. - * Direct commit in dev/solo; a production+team invoke is routed to a review PR (or + * Direct commit in dev/solo. A production+team invoke is routed to a review PR (or * 409 ``review_required`` when no forge is configured). */ post: operations["governance.actions.invoke"]; @@ -5454,7 +5488,7 @@ export interface paths { get: operations["gitops.auto-merge.list"]; /** * Put Auto Merge - * @description Toggle auto-merge. Enabling requires the deployment gate; disabling always works. + * @description Toggle auto-merge. Enabling requires the deployment gate. Disabling always works. */ put: operations["gitops.auto-merge.put"]; post?: never; @@ -5476,7 +5510,7 @@ export interface paths { * @description The resource-class registry - what VarChange.cls may legally name. * * Registry metadata only (no resource content), so any authenticated caller - * may read it; the per-class listings below are gated by each class's grant. + * may read it. The per-class listings below are gated by each class's grant. */ get: operations["gitops.classes.list"]; put?: never; @@ -5543,7 +5577,7 @@ export interface paths { * * Flat + cursor-paginated by default; ?group_by= buckets the page for * summaries. applied_revision (the Argo-synced SHA) turns state into - * applied/pending; without it every entry is 'committed'. + * applied/pending. Without it every entry is 'committed'. */ get: operations["gitops.log.list"]; put?: never; @@ -5585,7 +5619,7 @@ export interface paths { put?: never; /** * Set Lifecycle - * @description Set a service's lifecycle state - per-service RBAC; pinned services are 404. + * @description Set a service's lifecycle state - per-service RBAC. Pinned services are 404. */ post: operations["lifecycle.post"]; delete?: never; @@ -5604,8 +5638,8 @@ export interface paths { get?: never; put?: never; /** - * From Hyperdx - * @description Strip a HyperDX query's time bounds -> {window}, ready to save as a rule. + * Strip Search Query Time Bounds + * @description Strip a Search query's time bounds -> {window}, ready to save as a rule. */ post: operations["authoring.from-hyperdx"]; delete?: never; @@ -5725,7 +5759,7 @@ export interface paths { * Client Config * @description Runtime config for the web UI. * - * Authenticated but ungated: every console pane may read it, and the HyperDX URL + * Authenticated but ungated: every console pane may read it, and the Search URL * it returns is internal to the deployment. */ get: operations["config.client"]; @@ -5745,7 +5779,7 @@ export interface paths { cookie?: never; }; /** - * Hyperdx Connection + * Get Search Connection * @description Return the caller's OWN org connection - never another org's. * * A caller granted ``query:execute`` at system scope by a declared, unscoped role @@ -5771,11 +5805,11 @@ export interface paths { cookie?: never; }; /** - * Hyperdx Sources - * @description List every HyperDX team and the DFE sources on it. + * List Search Sources + * @description List every Search team and the DFE sources on it. * * A deploy writes its source to every team, so this is the read that says where - * it landed. 503 when HyperDX is not deployed or not answering -- an empty list + * it landed. 503 when Search is not deployed or not answering -- an empty list * would read as "the source is missing", which is a different fault. */ get: operations["hyperdx.sources"]; @@ -8362,7 +8396,7 @@ export interface components { * DeclaredValue * @description One value as the deploy repo declares it. * - * ``source`` names the overlay file it came from; a null source means the + * ``source`` names the overlay file it came from. A null source means the * deployment declared nothing and the chart or profile default applies. Those * defaults live in dfe-infra, which the engine does not read, so the API says * "not declared" rather than guessing a number. @@ -8699,7 +8733,7 @@ export interface components { * Shaped to drop straight into ``MetaSchemaAddVersionRequest.columns`` (the * create-version endpoint) or a new meta-schema's version -- the UI sends these * verbatim, no field mapping. ``type`` is derived from the first observed - * ClickHouse type; for a multi-type path (``is_consistent=false``) confirm it + * ClickHouse type. For a multi-type path (``is_consistent=false``) confirm it * before saving. */ DraftColumn: { @@ -8792,7 +8826,7 @@ export interface components { source: string; /** * Limit - * @description Events to sample and run over + * @description Events to sample and run over, at most transform_validation.dry_run_max_events (100 by default), which a larger value is refused against * @default 10 */ limit: number; @@ -9225,7 +9259,7 @@ export interface components { }; /** * FromHyperdxRequest - * @description Body for turning a HyperDX query into rule SQL. + * @description Body for turning a Search query into rule SQL. */ FromHyperdxRequest: { /** Query */ @@ -9882,7 +9916,7 @@ export interface components { }; /** * HyperDXConfig - * @description Whether the UI links to HyperDX, and where. + * @description Whether the UI links to Search, and where. */ HyperDXConfig: { /** @@ -9898,7 +9932,7 @@ export interface components { }; /** * HyperDXConnection - * @description Connection material in the fork's shape (name, host URL, username, password). + * @description Connection material in the fork's shape, plus where its seed sources live. */ HyperDXConnection: { /** Name */ @@ -9909,10 +9943,27 @@ export interface components { username: string; /** Password */ password: string; + /** + * Platform + * @description True for the platform reader, which reads every org + */ + platform: boolean; + /** + * Database + * @description The DFE data database every seeded table lives in + */ + database: string; + /** + * Tables + * @description Seeded table name by dfe-schemas manifest id + */ + tables: { + [key: string]: string; + }; }; /** * HyperDXSourcesResponse - * @description Where every deployed DFE source actually landed in HyperDX. + * @description Where every deployed DFE source actually landed in Search. */ HyperDXSourcesResponse: { /** Teams */ @@ -9920,17 +9971,17 @@ export interface components { }; /** * HyperDXTeamSource - * @description One HyperDX source on one team, as the fork holds it. + * @description One Search source on one team, as dfe-hyperdx holds it. */ HyperDXTeamSource: { /** * Id - * @description HyperDX source id on that team + * @description Search source id on that team */ id: string; /** * Name - * @description DFE source name; the HyperDX source carries the same one + * @description DFE source name; the Search source carries the same one */ name: string; /** @@ -9943,17 +9994,17 @@ export interface components { }; /** * HyperDXTeamSources - * @description One HyperDX team and the DFE sources it holds. + * @description One Search team and the DFE sources it holds. */ HyperDXTeamSources: { /** * Team - * @description HyperDX team id + * @description Search team id */ team: string; /** * Team Name - * @description HyperDX team name: the ClickHouse user its members read as + * @description Search team name: the ClickHouse user its members read as */ team_name: string; /** Sources */ @@ -10615,7 +10666,7 @@ export interface components { * Attributes: * current: Current version of the schema. * versions: Dictionary of versions and their metadata. - * path: Registry path key (e.g. ``aws/cloudtrail``); omitted from YAML on disk. + * path: Registry path key (e.g. ``aws/cloudtrail``). Omitted from YAML on disk. */ MetaSchema: { /** @@ -11174,8 +11225,8 @@ export interface components { * display_name: Human-readable label for UI display. * org_ids: Tenant IDs used for ClickHouse row-level security filters. * enabled: Whether this org is active. - * hyperdx_team_id: HyperDX team ID for this org's connection sync. - * hyperdx_team_api_key_env: Environment variable name holding the org's HyperDX team API key. + * hyperdx_team_id: dfe-hyperdx team ID for this org's connection sync. + * hyperdx_team_api_key_env: Environment variable name holding the org's dfe-hyperdx team API key. * ch_password_env: Environment variable name holding the ClickHouse password. * created_at: ISO 8601 timestamp of creation. * updated_at: ISO 8601 timestamp of last update. @@ -12339,11 +12390,6 @@ export interface components { * @default true */ cache: boolean; - /** - * Store - * @description Target store (database/schema/topic) - only if query allows - */ - store?: string | null; }; /** * QueryResponse @@ -12817,6 +12863,47 @@ export interface components { */ warnings?: string[]; }; + /** + * RuleCondition + * @description One test on a field, or ``all`` or ``any`` of several, as the rule builder writes it. + * + * A test compares one ``field`` with an ``operator``. ``all`` holds when every + * part does and ``any`` when at least one does. Each part is a condition of its + * own, so groups nest, and ``negate`` inverts the test or group it sits on. + */ + RuleCondition: { + /** + * Field + * @description Field a test reads: a column of the source table, or a dotted path inside the record as it arrived (e.g. 'tags.collector.type', or '_json.tags.collector.type'). Each part is letters, digits, '_' and '-', starting with a letter or '_'. Absent on a group + */ + field?: string | null; + /** + * Operator + * @description How a test compares ``field`` to ``value``: equals (the default for a test), not_equals, exists, includes, starts_with, ends_with, lt, lte, gt, gte, in. Absent on a group + */ + operator?: ("equals" | "not_equals" | "exists" | "includes" | "starts_with" | "ends_with" | "lt" | "lte" | "gt" | "gte" | "in") | null; + /** + * Value + * @description Operand for the operator, by its kind: none for exists, text for includes, starts_with and ends_with, text or a number for equals and not_equals, a number or an ISO 8601 date or date-time for lt, lte, gt and gte, a list of texts or of numbers for in + */ + value?: components["schemas"]["Scalar"] | components["schemas"]["Scalar"][] | null; + /** + * Negate + * @description Invert this test or group + * @default false + */ + negate: boolean; + /** + * All + * @description A group that holds when every part holds + */ + all?: components["schemas"]["RuleCondition"][]; + /** + * Any + * @description A group that holds when at least one part holds + */ + any?: components["schemas"]["RuleCondition"][]; + }; /** * RuleCreateRequest * @description Create a hunt rule via RuleCreationService. @@ -12835,9 +12922,11 @@ export interface components { severity: string; /** * User Sql - * @description Full detection query: SELECT ... FROM .
WHERE ... (the FROM names the source table) + * @description Full detection query: SELECT ... FROM .
WHERE ... (the FROM names the source table). Give this or ``condition``, not both. A rule saved this way has no ``condition`` */ - user_sql: string; + user_sql?: string | null; + /** @description The rule's structured condition, which the engine compiles to its SQL and stores with it, so the builder reopens on it. Reads the table of ``source``. Give this or ``user_sql``, not both */ + condition?: components["schemas"]["RuleCondition"] | null; /** * Cel Filter * @description CEL expression filter @@ -12871,7 +12960,7 @@ export interface components { name: string; /** * Source Type - * @description 'raw' (plain SQL) or 'hyperdx' (HyperDX saved search format) + * @description 'raw' (plain SQL) or 'hyperdx' (Search saved search format) * @default raw * @enum {string} */ @@ -12905,23 +12994,23 @@ export interface components { }; /** * RuleFromHyperdxRequest - * @description Create a hunt rule from the SQL a HyperDX view runs. + * @description Create a hunt rule from the SQL a Search view runs. * - * HyperDX renders the view to ``raw_sql`` and sends it here. The create + * Search renders the view to ``raw_sql`` and sends it here. The create * pipeline strips the UI meta (time bounds, LIMIT, ``__hdx_time_bucket``, - * SETTINGS) via the HyperDX sanitizer, and the engine derives a unique rule id + * SETTINGS) via the dfe-hyperdx sanitizer, and the engine derives a unique rule id * from the saved-search name. The caller gets that id back and opens * ``/rules/{id}`` -- no id to invent, no IndexedDB round-trip. */ RuleFromHyperdxRequest: { /** * Raw Sql - * @description The ClickHouse SELECT the HyperDX view renders to + * @description The ClickHouse SELECT the Search view renders to */ raw_sql: string; /** * Saved Search Name - * @description HyperDX saved-search name; seeds the rule id and label + * @description Search saved-search name; seeds the rule id and label */ saved_search_name?: string | null; /** @@ -12943,7 +13032,7 @@ export interface components { }; /** * RuleFromHyperdxResponse - * @description The rule created from a HyperDX query. + * @description The rule created from a Search query. */ RuleFromHyperdxResponse: { /** @@ -13034,6 +13123,69 @@ export interface components { /** Blocks */ blocks: components["schemas"]["RuleBlockResponse"][]; }; + /** + * RulePreviewRequest + * @description A condition to compile and check as a save would, without saving it. + */ + RulePreviewRequest: { + /** + * Source + * @description Source label whose table the condition reads + */ + source: string; + condition: components["schemas"]["RuleCondition"]; + /** + * Cel Filter + * @description CEL expression ANDed in, as on save + */ + cel_filter?: string | null; + /** + * Cost Window Minutes + * @description Lookback window in minutes the volume preview counts over. Absent or 0 uses the deployment's preview window. + */ + cost_window_minutes?: number | null; + /** + * Name + * @description The rule being edited. The volume preview then counts the orgs of the hunts that run it and of the hunt it names, as its save would + */ + name?: string | null; + /** + * Hunt Name + * @description The hunt the rule names as its own, which the count follows. Defaults to the stored rule's + */ + hunt_name?: string | null; + }; + /** + * RulePreviewResponse + * @description What a save of the condition would compile to and find, and nothing written. + */ + RulePreviewResponse: { + /** + * User Sql + * @description The rule SQL the condition compiles to, empty when it does not + */ + user_sql: string; + /** Source Db */ + source_db?: string | null; + /** Source Table */ + source_table?: string | null; + /** + * Where Clause + * @description The detection WHERE the rule would store + */ + where_clause: string; + /** + * Sql Errors + * @description Why a save would be refused as invalid + */ + sql_errors?: components["schemas"]["SqlValidationError"][]; + /** + * Matches Everything + * @description Why a save would be refused for matching every event, when it would + */ + matches_everything?: string | null; + cost_estimate?: components["schemas"]["CostEstimate"] | null; + }; /** * RuleResponse * @description A detection rule as the API returns it. @@ -13059,6 +13211,8 @@ export interface components { where_clause: string; /** Cel Filter */ cel_filter?: string | null; + /** @description The structured condition the SQL was compiled from, absent for a rule written as SQL */ + condition?: components["schemas"]["RuleCondition"] | null; /** Original Sql */ original_sql: string; /** Hunt Name */ @@ -13115,9 +13269,11 @@ export interface components { severity: string; /** * User Sql - * @description Full detection query: SELECT ... FROM .
WHERE ... (the FROM names the source table) + * @description Full detection query: SELECT ... FROM .
WHERE ... (the FROM names the source table). Give this or ``condition``, not both. A rule saved this way has no ``condition`` */ - user_sql: string; + user_sql?: string | null; + /** @description The rule's structured condition, which the engine compiles to its SQL and stores with it, so the builder reopens on it. Reads the table of ``source``. Give this or ``user_sql``, not both */ + condition?: components["schemas"]["RuleCondition"] | null; /** * Cel Filter * @description CEL expression filter @@ -13155,7 +13311,7 @@ export interface components { * SampleMode * @description How to pick the sample. * - * - ``recent`` - newest rows first (fast tail; ClickHouse ORDER BY ts DESC, + * - ``recent`` - newest rows first (fast tail, ClickHouse ORDER BY ts DESC, * Kafka reads from the partition high-watermark backwards). * - ``random`` - uniform-ish random rows (fair distribution, no recency bias). * - ``smart`` - logreducer representative/diverse sample (default). Gated. @@ -13192,7 +13348,7 @@ export interface components { * Provide EITHER a registered ``source`` (its CH table / land topic are * resolved for you) OR an explicit ``table``/``topic`` (ad-hoc - for a source * that is not registered yet, e.g. AI onboarding). ``filter`` (ClickHouse - * backend only) must be one condition over the sampled table's columns; it is + * backend only) must be one condition over the sampled table's columns. It is * replaced by the condition rendered from its parse tree, and anything else is * refused when the request is built. */ @@ -13399,6 +13555,7 @@ export interface components { */ limit: number; }; + Scalar: string | number; /** * ScalingRequest * @description Body for setting an instance's scaling dials. @@ -13691,12 +13848,12 @@ export interface components { apps_sync_error?: string | null; /** * Hyperdx Source Teams - * @description How many HyperDX teams now carry a source over this source's table + * @description How many Search teams now carry a source over this source's table */ hyperdx_source_teams?: number | null; /** * Hyperdx Source Error - * @description Why HyperDX was not pointed at the table. Never fails the deploy - the schema is live and HyperDX may be down or not deployed at all. + * @description Why Search was not pointed at the table. Never fails the deploy - the schema is live and Search may be down or not deployed at all. */ hyperdx_source_error?: string | null; /** @@ -14047,7 +14204,7 @@ export interface components { }; /** * ServiceConfigDetail - * @description Full service config. Inner config is dynamic (schema-less mode). + * @description One service config as its instance runs it: the stored keys over the app's defaults. */ ServiceConfigDetail: { /** @@ -14154,7 +14311,7 @@ export interface components { * @description Pre-login setup snapshot: the wizard state plus what is configured. * * Accounts are deliberately absent. Whether a real user exists is reported - * through the ``first_user`` step; the account list itself is never served + * through the ``first_user`` step. The account list itself is never served * to an unauthenticated caller. */ SetupStatus: { @@ -14258,8 +14415,7 @@ export interface components { * A column maps a standard ``sigma_field`` (the alias the view exposes) to EITHER * a real table column (``source_column``) OR a dotted path inside the source's * ``_json`` column (``json_path``) - exactly one of the two. ``type`` is an - * optional ClickHouse type the extracted value is CAST to (mainly for a - * JSON-derived column, whose subcolumn is otherwise a ``Dynamic``). This is the + * optional ClickHouse type for the value, read as RemapColumn reads it. This is the * Sigma-named shape of :class:`~dfe_engine.fieldmap.remap_view.RemapColumn`. */ SigmaViewColumn: { @@ -14280,7 +14436,7 @@ export interface components { json_path?: string | null; /** * Type - * @description Optional ClickHouse type to CAST the value to (e.g. 'String', 'UInt32') + * @description Optional ClickHouse type for the value (e.g. 'String', 'UInt32') */ type?: string | null; }; @@ -14288,7 +14444,7 @@ export interface components { * SigmaViewDefinition * @description A CRUD-managed Sigma view definition for one source. * - * Keyed (in the store) by ``source_name``; the generated view targets table + * Keyed (in the store) by ``source_name``. The generated view targets table * ``source_name`` and is named ``{source_name}_sigma``. ``include_source_columns`` * appends ``SELECT *`` so the base table columns remain visible alongside the * Sigma-aligned aliases (the legacy view's behaviour). @@ -14358,7 +14514,7 @@ export interface components { * @description Create/replace body for a source's Sigma view definition (source_name is the path). * * Each column maps a Sigma field to a real source column OR a path inside the - * source's ``_json`` payload (a JSON-derived column); the ``SigmaViewColumn`` + * source's ``_json`` payload (a JSON-derived column). The ``SigmaViewColumn`` * validator enforces exactly one per column. */ SigmaViewWriteRequest: { @@ -14888,10 +15044,9 @@ export interface components { type: string; /** * Version - * @description Common header version (semver) - * @default 1.0.3 + * @description Common header version (semver); the profile's current version when omitted */ - version: string; + version?: string; }; /** * SourceImportResponse @@ -15883,7 +16038,7 @@ export interface components { }; /** * SystemDefaultsPatch - * @description A partial change. Omitted fields stay as they are; null clears that override. + * @description A partial change. Omitted fields stay as they are. Null clears that override. */ SystemDefaultsPatch: { /** @@ -16108,7 +16263,7 @@ export interface components { }; /** * TopicFailure - * @description One topic the broker would not do the thing to; the broker's own text is in the log. + * @description One topic the broker would not do the thing to. The broker's own text is in the log. */ TopicFailure: { /** Name */ @@ -16182,7 +16337,7 @@ export interface components { * @description Outcome of a converge pass. * * ``refused`` is what DFE declined to do (a partition decrease, a replication - * factor change); ``failed`` is what the broker rejected. They are different + * factor change). ``failed`` is what the broker rejected. They are different * problems with different fixes, so they are different lists. */ TopicUpdateResponse: { @@ -16644,7 +16799,7 @@ export interface components { groups?: string[]; /** * Org Ids - * @description Orgs this user can browse in the data plane (HyperDX). Empty means no org-scoped data access. + * @description Orgs this user can browse in the data plane (Search). Empty means no org-scoped data access. */ org_ids?: string[]; /** @@ -17592,7 +17747,7 @@ export interface operations { "application/problem+json": components["schemas"]["Problem"]; }; }; - /** @description The break-glass account is disabled in governance settings */ + /** @description The break-glass password is right, but the account is disabled in governance settings */ 403: { headers: { [name: string]: unknown; @@ -20742,8 +20897,8 @@ export interface operations { "orgs.available-ids": { parameters: { query?: { - /** @description Most tenant ids to return -- a suggestion list, not an export */ - limit?: number; + /** @description Most tenant ids to return -- a suggestion list, not an export. Unset takes orgs.available_ids_limit (200 by default) */ + limit?: number | null; }; header?: never; path?: never; @@ -24458,6 +24613,66 @@ export interface operations { }; }; }; + "rules.preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RulePreviewRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["RulePreviewResponse"]; + }; + }; + /** @description No valid session: the credentials are missing, invalid or expired, or the account behind them is disabled or blocked */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["Problem"]; + }; + }; + /** @description Refused: the session lacks the action this route checks, or its account must replace an issued password first. A SCIM route answers a refused action in the RFC 7644 error envelope */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["Problem"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["Problem"]; + }; + }; + /** @description Problem details (RFC 9457) */ + default: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["Problem"]; + }; + }; + }; + }; "rules.get": { parameters: { query?: never; @@ -25889,6 +26104,8 @@ export interface operations { query?: { /** @description Case-insensitive search in name, display_name, customers, rules, source_table, target_table */ search?: string | null; + /** @description Only the hunts whose rules include this rule, by its exact name */ + rule?: string | null; /** @description Items per page: 0 means 50, above 1000 is cut to it */ page_size?: number; /** @description The next_page_token of the previous page */