diff --git a/packages/dfe-engine-types/specs/openapi.e2e.json b/packages/dfe-engine-types/specs/openapi.e2e.json index f1d0b6f2..df5eca3e 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.88" }, "paths": { "/api/e2e/status": { diff --git a/packages/dfe-engine-types/specs/openapi.json b/packages/dfe-engine-types/specs/openapi.json index 2bfea47e..4de12fda 100644 --- a/packages/dfe-engine-types/specs/openapi.json +++ b/packages/dfe-engine-types/specs/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "DFE Engine API", "description": "Data Fusion Engine -- configuration, scheduling, and query API", - "version": "1.22.80" + "version": "1.22.88" }, "paths": { "/api/v1/auth/login": { @@ -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": { @@ -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, @@ -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": { @@ -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": [ { @@ -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": [ { @@ -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": { @@ -18707,6 +18713,78 @@ } } }, + "/api/v1/schemas/vocabulary": { + "get": { + "tags": [ + "schemas" + ], + "summary": "Get Schema Vocabulary", + "description": "The primitives, use cases, attributes and override types a column may use.", + "operationId": "schemas.vocabulary", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SchemaVocabulary" + } + } + } + }, + "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" + } + } + } + }, + "default": { + "description": "Problem details (RFC 9457)", + "content": { + "application/problem+json": { + "schema": { + "$ref": "#/components/schemas/Problem" + } + } + } + } + }, + "security": [ + { + "BearerAuth": [] + } + ], + "x-scalo": { + "group": "schemas", + "resource": "schemas", + "hierarchy": [ + "schemas" + ], + "verb": "vocabulary", + "read_only": true, + "cli": { + "hidden": false, + "aliases": [], + "positional": [] + }, + "action": "schema:read" + } + } + }, "/api/v1/schemas/definitions/{schema_path}/versions/columns": { "get": { "tags": [ @@ -33404,8 +33482,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": { @@ -33967,7 +34045,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": { @@ -34035,9 +34113,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": { @@ -34106,10 +34184,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": { @@ -39708,10 +39786,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 } }, @@ -40517,7 +40594,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": { @@ -41725,7 +41802,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": { @@ -41744,6 +41821,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", @@ -41751,10 +41846,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": { @@ -41768,19 +41866,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": { @@ -41797,19 +41895,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": { @@ -41825,7 +41923,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": { @@ -42132,6 +42230,11 @@ "deployment_default": { "type": "integer", "title": "Deployment Default" + }, + "maximum": { + "type": "integer", + "title": "Maximum", + "description": "The largest value a PATCH accepts, so a form can bound it." } }, "type": "object", @@ -42139,7 +42242,8 @@ "effective", "stored", "origin", - "deployment_default" + "deployment_default", + "maximum" ], "title": "IntDefault", "description": "One integer default: the value in force, and where it came from." @@ -44010,7 +44114,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": { @@ -48133,7 +48237,7 @@ "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" } }, @@ -48212,7 +48316,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": [ @@ -48224,7 +48328,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", @@ -48263,7 +48367,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": { @@ -48302,7 +48406,7 @@ "display_name" ], "title": "RuleFromHyperdxResponse", - "description": "The rule created from a HyperDX query." + "description": "The rule created from a Search query." }, "RuleOrderRequest": { "properties": { @@ -49816,7 +49920,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": [ @@ -49828,7 +49932,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": { @@ -50349,6 +50453,51 @@ "title": "SchemaVersionGet", "description": "The selected version's metadata, its columns paged in the answer's ``items``." }, + "SchemaVocabulary": { + "properties": { + "cardinality": { + "$ref": "#/components/schemas/VocabularyCardinality" + }, + "primitives": { + "items": { + "$ref": "#/components/schemas/VocabularyPrimitive" + }, + "type": "array", + "title": "Primitives" + }, + "use_cases": { + "items": { + "$ref": "#/components/schemas/VocabularyUseCase" + }, + "type": "array", + "title": "Use Cases" + }, + "attributes": { + "items": { + "$ref": "#/components/schemas/VocabularyAttribute" + }, + "type": "array", + "title": "Attributes" + }, + "ch_overrides": { + "items": { + "$ref": "#/components/schemas/VocabularyChOverride" + }, + "type": "array", + "title": "Ch Overrides" + } + }, + "type": "object", + "required": [ + "cardinality", + "primitives", + "use_cases", + "attributes", + "ch_overrides" + ], + "title": "SchemaVocabulary", + "description": "What a schema form may offer, read from the dfe-schemas registry the engine runs." + }, "SelectionResponse": { "properties": { "rules": { @@ -50389,7 +50538,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": { @@ -50734,7 +50883,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", @@ -50742,7 +50891,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": { @@ -51857,8 +52006,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", @@ -55366,7 +55514,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", @@ -55976,6 +56124,231 @@ "title": "ViewParameter", "description": "Parameter discovered from a ClickHouse parameterized view.\n\nExtracted from the view's CREATE SQL by parsing {param:Type} patterns.\nProvides type metadata across the full stack (ClickHouse -> Python -> TypeScript -> HTML)." }, + "VocabularyAttribute": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "label": { + "type": "string", + "title": "Label" + }, + "valid_primitives": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Valid Primitives" + } + }, + "type": "object", + "required": [ + "name", + "label", + "valid_primitives" + ], + "title": "VocabularyAttribute", + "description": "An attribute a column may carry." + }, + "VocabularyCardinality": { + "properties": { + "values": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Values" + }, + "default": { + "type": "string", + "title": "Default", + "description": "What a column that declares none is read as." + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Labels", + "description": "The label to show for each value." + }, + "retired_attributes": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Retired Attributes", + "description": "A retired attribute and the cardinality a column holding it reads as." + } + }, + "type": "object", + "required": [ + "values", + "default", + "labels", + "retired_attributes" + ], + "title": "VocabularyCardinality", + "description": "The cardinalities a column may declare." + }, + "VocabularyChOverride": { + "properties": { + "value": { + "type": "string", + "title": "Value" + }, + "label": { + "type": "string", + "title": "Label" + }, + "primitive": { + "type": "string", + "title": "Primitive" + }, + "parameters": { + "items": { + "$ref": "#/components/schemas/VocabularyOverrideParameter" + }, + "type": "array", + "title": "Parameters", + "description": "Inputs the type needs, in the order the type takes them." + }, + "template": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Template", + "description": "The override text with each parameter in braces; null when it takes none." + }, + "hint": { + "type": "string", + "title": "Hint", + "description": "A note to show beside the option, empty when there is none." + } + }, + "type": "object", + "required": [ + "value", + "label", + "primitive", + "parameters", + "template", + "hint" + ], + "title": "VocabularyChOverride", + "description": "A ClickHouse type offered as an override, and the primitive it refines." + }, + "VocabularyOverrideParameter": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "The name the template wraps in braces." + }, + "label": { + "type": "string", + "title": "Label" + }, + "kind": { + "type": "string", + "enum": [ + "integer", + "text" + ], + "title": "Kind" + } + }, + "type": "object", + "required": [ + "name", + "label", + "kind" + ], + "title": "VocabularyOverrideParameter", + "description": "An argument an override type takes, and the input a form shows for it." + }, + "VocabularyPrimitive": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "label": { + "type": "string", + "title": "Label" + }, + "ch_type": { + "type": "string", + "title": "Ch Type", + "description": "The ClickHouse type the primitive maps to." + } + }, + "type": "object", + "required": [ + "name", + "label", + "ch_type" + ], + "title": "VocabularyPrimitive", + "description": "A primitive a column may declare." + }, + "VocabularyUseCase": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "label": { + "type": "string", + "title": "Label" + }, + "description": { + "type": "string", + "title": "Description", + "description": "The question the use case answers, in plain words." + }, + "valid_primitives": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Valid Primitives" + }, + "parameters": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Parameters", + "description": "Arguments the use case takes in brackets, such as dims for similarity_search." + }, + "retired_names": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Retired Names", + "description": "Names this use case replaced. A stored column may still carry one." + } + }, + "type": "object", + "required": [ + "name", + "label", + "description", + "valid_primitives", + "parameters", + "retired_names" + ], + "title": "VocabularyUseCase", + "description": "An index use case: the question the user asks of a column." + }, "VolumeBand": { "type": "string", "enum": [ @@ -56576,6 +56949,23 @@ ], "title": "Attribute" }, + "cardinality": { + "anyOf": [ + { + "type": "string", + "enum": [ + "low", + "high", + "unknown" + ] + }, + { + "type": "null" + } + ], + "title": "Cardinality", + "description": "How many distinct values the column holds, as declared. A column holding the retired lowcardinality attribute reads as low. Absent means unknown." + }, "description": { "type": "string", "title": "Description", diff --git a/packages/dfe-engine-types/types/index.d.ts b/packages/dfe-engine-types/types/index.d.ts index 55286890..2ee93867 100644 --- a/packages/dfe-engine-types/types/index.d.ts +++ b/packages/dfe-engine-types/types/index.d.ts @@ -91,7 +91,7 @@ export interface paths { * * ``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. + * so a group change reaches dfe-hyperdx in that window rather than at token expiry. */ get: operations["auth.me.list"]; put?: never; @@ -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 @@ -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. */ @@ -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; @@ -2058,8 +2062,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. @@ -3252,6 +3256,26 @@ export interface paths { patch?: never; trace?: never; }; + "/api/v1/schemas/vocabulary": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Schema Vocabulary + * @description The primitives, use cases, attributes and override types a column may use. + */ + get: operations["schemas.vocabulary"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/v1/schemas/definitions/{schema_path}/versions/columns": { parameters: { query?: never; @@ -5584,8 +5608,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; @@ -5705,7 +5729,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"]; @@ -5725,7 +5749,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 @@ -5751,11 +5775,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"]; @@ -8772,7 +8796,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; @@ -9205,7 +9229,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 */ @@ -9862,7 +9886,7 @@ export interface components { }; /** * HyperDXConfig - * @description Whether the UI links to HyperDX, and where. + * @description Whether the UI links to Search, and where. */ HyperDXConfig: { /** @@ -9878,7 +9902,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 */ @@ -9889,10 +9913,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 */ @@ -9900,17 +9941,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; /** @@ -9923,17 +9964,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 */ @@ -10117,6 +10158,11 @@ export interface components { origin: "override" | "deployment"; /** Deployment Default */ deployment_default: number; + /** + * Maximum + * @description The largest value a PATCH accepts, so a form can bound it. + */ + maximum: number; }; /** * InvokeRequest @@ -11149,8 +11195,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. @@ -12846,7 +12892,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} */ @@ -12880,23 +12926,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; /** @@ -12918,7 +12964,7 @@ export interface components { }; /** * RuleFromHyperdxResponse - * @description The rule created from a HyperDX query. + * @description The rule created from a Search query. */ RuleFromHyperdxResponse: { /** @@ -13666,12 +13712,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; /** @@ -13997,6 +14043,21 @@ export interface components { */ summary: string; }; + /** + * SchemaVocabulary + * @description What a schema form may offer, read from the dfe-schemas registry the engine runs. + */ + SchemaVocabulary: { + cardinality: components["schemas"]["VocabularyCardinality"]; + /** Primitives */ + primitives: components["schemas"]["VocabularyPrimitive"][]; + /** Use Cases */ + use_cases: components["schemas"]["VocabularyUseCase"][]; + /** Attributes */ + attributes: components["schemas"]["VocabularyAttribute"][]; + /** Ch Overrides */ + ch_overrides: components["schemas"]["VocabularyChOverride"][]; + }; /** * SelectionResponse * @description The curated selection list (rule ids). @@ -14007,7 +14068,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: { /** @@ -14218,8 +14279,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: { @@ -14240,7 +14300,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; }; @@ -14848,10 +14908,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 @@ -16604,7 +16663,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[]; /** @@ -16994,6 +17053,132 @@ export interface components { */ enum?: unknown[] | null; }; + /** + * VocabularyAttribute + * @description An attribute a column may carry. + */ + VocabularyAttribute: { + /** Name */ + name: string; + /** Label */ + label: string; + /** Valid Primitives */ + valid_primitives: string[]; + }; + /** + * VocabularyCardinality + * @description The cardinalities a column may declare. + */ + VocabularyCardinality: { + /** Values */ + values: string[]; + /** + * Default + * @description What a column that declares none is read as. + */ + default: string; + /** + * Labels + * @description The label to show for each value. + */ + labels: { + [key: string]: string; + }; + /** + * Retired Attributes + * @description A retired attribute and the cardinality a column holding it reads as. + */ + retired_attributes: { + [key: string]: string; + }; + }; + /** + * VocabularyChOverride + * @description A ClickHouse type offered as an override, and the primitive it refines. + */ + VocabularyChOverride: { + /** Value */ + value: string; + /** Label */ + label: string; + /** Primitive */ + primitive: string; + /** + * Parameters + * @description Inputs the type needs, in the order the type takes them. + */ + parameters: components["schemas"]["VocabularyOverrideParameter"][]; + /** + * Template + * @description The override text with each parameter in braces; null when it takes none. + */ + template: string | null; + /** + * Hint + * @description A note to show beside the option, empty when there is none. + */ + hint: string; + }; + /** + * VocabularyOverrideParameter + * @description An argument an override type takes, and the input a form shows for it. + */ + VocabularyOverrideParameter: { + /** + * Name + * @description The name the template wraps in braces. + */ + name: string; + /** Label */ + label: string; + /** + * Kind + * @enum {string} + */ + kind: "integer" | "text"; + }; + /** + * VocabularyPrimitive + * @description A primitive a column may declare. + */ + VocabularyPrimitive: { + /** Name */ + name: string; + /** Label */ + label: string; + /** + * Ch Type + * @description The ClickHouse type the primitive maps to. + */ + ch_type: string; + }; + /** + * VocabularyUseCase + * @description An index use case: the question the user asks of a column. + */ + VocabularyUseCase: { + /** Name */ + name: string; + /** Label */ + label: string; + /** + * Description + * @description The question the use case answers, in plain words. + */ + description: string; + /** Valid Primitives */ + valid_primitives: string[]; + /** + * Parameters + * @description Arguments the use case takes in brackets, such as dims for similarity_search. + */ + parameters: string[]; + /** + * Retired Names + * @description Names this use case replaced. A stored column may still carry one. + */ + retired_names: string[]; + }; /** * VolumeBand * @description How much a rule's projected alert volume asks of the people reviewing it. @@ -17276,6 +17461,11 @@ export interface components { use_case: string; /** Attribute */ attribute?: string[] | null; + /** + * Cardinality + * @description How many distinct values the column holds, as declared. A column holding the retired lowcardinality attribute reads as low. Absent means unknown. + */ + cardinality?: ("low" | "high" | "unknown") | null; /** * Description * @default @@ -17421,7 +17611,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; @@ -20571,8 +20761,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; @@ -27930,6 +28120,53 @@ export interface operations { }; }; }; + "schemas.vocabulary": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SchemaVocabulary"]; + }; + }; + /** @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 Problem details (RFC 9457) */ + default: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["Problem"]; + }; + }; + }; + }; "schemas.definitions.versions.columns": { parameters: { query: {