diff --git a/docs/docs.go b/docs/docs.go index a8b1a904..a9ea52e1 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -6935,7 +6935,43 @@ const docTemplate = `{ } } }, - "/api/v1/quality/evaluate": { + "/api/v1/roles": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BearerAuth": [] + } + ], + "description": "List all active roles with user counts and permissions", + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List roles", + "operationId": "getRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Role" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, "post": { "security": [ { @@ -6945,7 +6981,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Judges up to 200 assets as they are, with the current settings, profile rules and custom rules, and records nothing. It is what a card on an asset page shows: findings and the checks the asset meets. An id that is not an asset is left out.", + "description": "Create a new role with optional initial permissions", "consumes": [ "application/json" ], @@ -6953,18 +6989,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "quality" + "roles" ], - "summary": "Evaluate assets now", - "operationId": "evaluateQualityAssets", + "summary": "Create a role", + "operationId": "postRoles", "parameters": [ { - "description": "Assets", - "name": "request", + "description": "Role creation request", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/QualityEvaluateRequest" + "$ref": "#/definitions/v1_roles.createRoleRequest" } } ], @@ -6972,7 +7008,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityEvaluateResponse" + "$ref": "#/definitions/Role" } }, "400": { @@ -6981,20 +7017,8 @@ const docTemplate = `{ "$ref": "#/definitions/ErrorResponse" } }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "422": { - "description": "Unprocessable Entity", + "409": { + "description": "Conflict", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -7002,7 +7026,7 @@ const docTemplate = `{ } } }, - "/api/v1/quality/rules": { + "/api/v1/roles/{id}": { "get": { "security": [ { @@ -7012,37 +7036,40 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Every rule the audit applies: the built-in ones, the ones the metamodel profile declares (read-only here) and the custom ones people wrote. The severity and on/off of the first two are in the settings; a custom rule carries its own.", + "description": "Get a role by ID with its permissions", "produces": [ "application/json" ], "tags": [ - "quality" + "roles" + ], + "summary": "Get a role", + "operationId": "getRolesID", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true + } ], - "summary": "List the quality rules", - "operationId": "listQualityRules", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityRulesResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/Role" } }, - "403": { - "description": "Forbidden", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } } } }, - "post": { + "delete": { "security": [ { "ApiKeyAuth": [] @@ -7051,56 +7078,30 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "A declarative rule over the fields of the profile: a closed set of operators, never code. 400 lists every problem with its path. The id is generated when omitted.", - "consumes": [ - "application/json" - ], + "description": "Soft-delete a role. Fails if the role is a system role or has active user assignments.", "produces": [ "application/json" ], "tags": [ - "quality" + "roles" ], - "summary": "Create a custom quality rule", - "operationId": "createQualityRule", + "summary": "Delete a role", + "operationId": "deleteRolesID", "parameters": [ { - "description": "Rule", - "name": "rule", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/QualityRuleRequest" - } + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/QualityCustomRule" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/QualityRuleError" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } + "204": { + "description": "No Content" }, - "409": { - "description": "Conflict", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -7112,10 +7113,8 @@ const docTemplate = `{ } } } - } - }, - "/api/v1/quality/rules/{id}": { - "put": { + }, + "patch": { "security": [ { "ApiKeyAuth": [] @@ -7124,7 +7123,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Replaces a custom rule. Requires If-Match with the version read; 412 when someone changed it first. The rules of the profile cannot be changed here.", + "description": "Update a role's name or description. System roles cannot be renamed.", "consumes": [ "application/json" ], @@ -7132,32 +7131,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "quality" + "roles" ], - "summary": "Change a custom quality rule", - "operationId": "updateQualityRule", + "summary": "Update a role", + "operationId": "patchRolesID", "parameters": [ { "type": "string", - "description": "Rule ID", + "description": "Role ID", "name": "id", "in": "path", "required": true }, { - "type": "string", - "description": "Version read, quoted", - "name": "If-Match", - "in": "header", - "required": true - }, - { - "description": "Rule", - "name": "rule", + "description": "Role update request", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/QualityRuleRequest" + "$ref": "#/definitions/v1_roles.updateRoleRequest" } } ], @@ -7165,13 +7157,13 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityCustomRule" + "$ref": "#/definitions/Role" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/QualityRuleError" + "$ref": "#/definitions/ErrorResponse" } }, "404": { @@ -7180,21 +7172,17 @@ const docTemplate = `{ "$ref": "#/definitions/ErrorResponse" } }, - "412": { - "description": "Precondition Failed", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "428": { - "description": "Precondition Required", + "422": { + "description": "Unprocessable Entity", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, - "delete": { + } + }, + "/api/v1/roles/{id}/permissions": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -7203,34 +7191,65 @@ const docTemplate = `{ "BearerAuth": [] } ], + "description": "Atomically replace all permissions on a role. System roles enforce a minimum permission floor.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], "tags": [ - "quality" + "roles" ], - "summary": "Delete a custom quality rule", - "operationId": "deleteQualityRule", + "summary": "Replace role permissions", + "operationId": "postRolesIDPermissions", "parameters": [ { "type": "string", - "description": "Rule ID", + "description": "Role ID", "name": "id", "in": "path", "required": true + }, + { + "description": "Permission IDs to assign", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_roles.replacePermissionsRequest" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Role" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } } }, - "/api/v1/quality/runs": { + "/api/v1/runs": { "get": { "security": [ { @@ -7240,27 +7259,39 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Newest first, with the summary of the finished ones.", + "description": "Get paginated list of runs with filtering", "produces": [ "application/json" ], "tags": [ - "quality" + "runs" ], - "summary": "List quality audit runs", - "operationId": "listQualityRuns", + "summary": "List runs", + "operationId": "getRuns", "parameters": [ + { + "type": "string", + "description": "Comma-separated list of pipeline names", + "name": "pipelines", + "in": "query" + }, + { + "type": "string", + "description": "Comma-separated list of statuses", + "name": "statuses", + "in": "query" + }, { "type": "integer", - "default": 20, - "description": "Page size, up to 100", + "default": 50, + "description": "Number of results per page", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, - "description": "Offset", + "description": "Number of results to skip", "name": "offset", "in": "query" } @@ -7269,76 +7300,197 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityRunsResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { + "type": "object", + "properties": { + "limit": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "pipelines": { + "type": "array", + "items": { + "type": "string" + } + }, + "runs": { + "type": "array", + "items": { + "$ref": "#/definitions/PluginRun" + } + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "/api/v1/runs/assets/batch": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + }, + { "BearerAuth": [] } ], - "description": "Audits every asset of the catalog in the background, with the saved settings and the effective metamodel. One run at a time: a second request gets 409 with the run in progress.", + "description": "Create/update assets within a run", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "quality" + "runs" + ], + "summary": "Batch create assets", + "operationId": "postRunsAssetsBatch", + "parameters": [ + { + "description": "Batch create request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/BatchCreateRequest" + } + } ], - "summary": "Start a quality audit run", - "operationId": "startQualityRun", "responses": { - "202": { - "description": "Accepted", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/QualityRun" + "$ref": "#/definitions/BatchCreateResponse" } + } + } + } + }, + "/api/v1/runs/cleanup": { + "post": { + "security": [ + { + "ApiKeyAuth": [] }, - "401": { - "description": "Unauthorized", + { + "BearerAuth": [] + } + ], + "description": "Mark runs as failed if they've been running too long without updates", + "tags": [ + "runs" + ], + "summary": "Cleanup stale runs", + "operationId": "postRunsCleanup", + "responses": { + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/ErrorResponse" + "type": "object", + "additionalProperties": { + "type": "integer" + } } + } + } + } + }, + "/api/v1/runs/complete": { + "post": { + "security": [ + { + "ApiKeyAuth": [] }, - "403": { - "description": "Forbidden", + { + "BearerAuth": [] + } + ], + "description": "Complete a run with results", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "runs" + ], + "summary": "Complete run", + "operationId": "postRunsComplete", + "parameters": [ + { + "description": "Complete run request", + "name": "request", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/CompleteRunRequest" } - }, - "409": { - "description": "Conflict", + } + ], + "responses": { + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/QualityRunConflict" + "type": "object", + "additionalProperties": { + "type": "string" + } } + } + } + } + }, + "/api/v1/runs/start": { + "post": { + "security": [ + { + "ApiKeyAuth": [] }, - "422": { - "description": "Unprocessable Entity", + { + "BearerAuth": [] + } + ], + "description": "Start a new run for tracking", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "runs" + ], + "summary": "Start run", + "operationId": "postRunsStart", + "parameters": [ + { + "description": "Start run request", + "name": "request", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/StartRunRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/PluginRun" } } } } }, - "/api/v1/quality/runs/{id}": { + "/api/v1/runs/{id}": { "get": { "security": [ { @@ -7348,15 +7500,15 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "The run with its progress, the settings it used and, once finished, its summary.", + "description": "Get a specific run by ID", "produces": [ "application/json" ], "tags": [ - "quality" + "runs" ], - "summary": "Get a quality audit run", - "operationId": "getQualityRun", + "summary": "Get run", + "operationId": "getRunsID", "parameters": [ { "type": "string", @@ -7370,31 +7522,13 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityRun" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/PluginRun" } } } } }, - "/api/v1/quality/runs/{id}/results": { + "/api/v1/runs/{id}/entities": { "get": { "security": [ { @@ -7404,15 +7538,15 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "One entry per audited asset, weakest first. The findings of each asset are only kept for the last successful run.", + "description": "Get paginated list of entities for a specific run", "produces": [ "application/json" ], "tags": [ - "quality" + "runs" ], - "summary": "List the results of a quality audit run", - "operationId": "getQualityRunResults", + "summary": "Get run entities", + "operationId": "getRunsIDEntities", "parameters": [ { "type": "string", @@ -7423,45 +7557,27 @@ const docTemplate = `{ }, { "type": "string", - "description": "compliant, warning or noncompliant", - "name": "status", - "in": "query" - }, - { - "type": "string", - "description": "A domain ID, or unassigned", - "name": "domain", - "in": "query" - }, - { - "type": "string", - "description": "Asset type", - "name": "type", - "in": "query" - }, - { - "type": "string", - "description": "Text in the asset name or MRN", - "name": "q", + "description": "Filter by entity type (asset, lineage, documentation)", + "name": "entity_type", "in": "query" }, { "type": "string", - "description": "quality (default) or name", - "name": "sort", + "description": "Filter by status (created, updated, deleted, failed)", + "name": "status", "in": "query" }, { "type": "integer", - "default": 50, - "description": "Page size, up to 500", + "default": 100, + "description": "Number of results per page", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, - "description": "Offset", + "description": "Number of results to skip", "name": "offset", "in": "query" } @@ -7470,148 +7586,79 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityResultsResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/RunEntitiesResponse" } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/api/v1/quality/settings": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "The criterion the platform's quality scores are computed with. Version 0 means the defaults, not yet saved.", - "produces": [ - "application/json" - ], - "tags": [ - "quality" - ], - "summary": "Get the quality audit settings", - "operationId": "getQualitySettings", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/QualitySettingsResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - }, - "put": { - "security": [ - { - "ApiKeyAuth": [] + } + } + } + }, + "/api/v1/search": { + "get": { + "security": [ + { + "ApiKeyAuth": [] }, { "BearerAuth": [] } ], - "description": "Replaces the settings. Requires If-Match with the version read; 412 when someone saved first.", - "consumes": [ - "application/json" - ], + "description": "Search across assets, glossary terms, teams, and users", "produces": [ "application/json" ], "tags": [ - "quality" + "search" ], - "summary": "Change the quality audit settings", - "operationId": "putQualitySettings", + "summary": "Unified search", + "operationId": "getSearch", "parameters": [ { "type": "string", - "description": "Version read, quoted; \\", - "name": "If-Match", - "in": "header", + "description": "Search query", + "name": "q", + "in": "query", "required": true }, { - "description": "Settings", - "name": "settings", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/QualitySettings" - } + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "Filter by result types (asset, glossary, team, user)", + "name": "types", + "in": "query" + }, + { + "type": "integer", + "default": 20, + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "default": 0, + "description": "Offset", + "name": "offset", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualitySettingsResponse" + "$ref": "#/definitions/SearchResponse" } }, "400": { "description": "Bad Request", - "schema": { - "$ref": "#/definitions/QualityValidationError" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "412": { - "description": "Precondition Failed", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "428": { - "description": "Precondition Required", + "500": { + "description": "Internal Server Error", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -7619,7 +7666,7 @@ const docTemplate = `{ } } }, - "/api/v1/roles": { + "/api/v1/service-accounts": { "get": { "security": [ { @@ -7629,22 +7676,22 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "List all active roles with user counts and permissions", + "description": "Get all service accounts", "produces": [ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "List roles", - "operationId": "getRoles", + "summary": "List service accounts", + "operationId": "getServiceAccounts", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/Role" + "$ref": "#/definitions/ServiceAccount" } } }, @@ -7665,7 +7712,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Create a new role with optional initial permissions", + "description": "Create a new service account", "consumes": [ "application/json" ], @@ -7673,26 +7720,26 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "Create a role", - "operationId": "postRoles", + "summary": "Create service account", + "operationId": "postServiceAccounts", "parameters": [ { - "description": "Role creation request", - "name": "role", + "description": "Service account", + "name": "account", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1_roles.createRoleRequest" + "$ref": "#/definitions/CreateServiceAccountRequest" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/Role" + "$ref": "#/definitions/ServiceAccount" } }, "400": { @@ -7700,17 +7747,11 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/roles/{id}": { + "/api/v1/service-accounts/{id}": { "get": { "security": [ { @@ -7720,19 +7761,19 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get a role by ID with its permissions", + "description": "Get a service account by ID", "produces": [ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "Get a role", - "operationId": "getRolesID", + "summary": "Get service account", + "operationId": "getServiceAccountsID", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Service account ID", "name": "id", "in": "path", "required": true @@ -7742,7 +7783,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/Role" + "$ref": "#/definitions/ServiceAccount" } }, "404": { @@ -7762,19 +7803,16 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Soft-delete a role. Fails if the role is a system role or has active user assignments.", - "produces": [ - "application/json" - ], + "description": "Soft-delete a service account", "tags": [ - "roles" + "service_accounts" ], - "summary": "Delete a role", - "operationId": "deleteRolesID", + "summary": "Delete service account", + "operationId": "deleteServiceAccountsID", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Service account ID", "name": "id", "in": "path", "required": true @@ -7789,12 +7827,6 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } }, @@ -7807,7 +7839,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Update a role's name or description. System roles cannot be renamed.", + "description": "Update a service account", "consumes": [ "application/json" ], @@ -7815,25 +7847,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "Update a role", - "operationId": "patchRolesID", + "summary": "Update service account", + "operationId": "patchServiceAccountsID", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Service account ID", "name": "id", "in": "path", "required": true }, { - "description": "Role update request", - "name": "role", + "description": "Update fields", + "name": "account", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1_roles.updateRoleRequest" + "$ref": "#/definitions/UpdateServiceAccountRequest" } } ], @@ -7841,13 +7873,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/Role" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/ServiceAccount" } }, "404": { @@ -7855,18 +7881,12 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/roles/{id}/permissions": { - "post": { + "/api/v1/service-accounts/{id}/api-keys": { + "get": { "security": [ { "ApiKeyAuth": [] @@ -7875,146 +7895,93 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Atomically replace all permissions on a role. System roles enforce a minimum permission floor.", - "consumes": [ - "application/json" - ], + "description": "Get all API keys for a service account", "produces": [ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "Replace role permissions", - "operationId": "postRolesIDPermissions", + "summary": "List API keys for a service account", + "operationId": "getServiceAccountsIDAPIKeys", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Service account ID", "name": "id", "in": "path", "required": true - }, - { - "description": "Permission IDs to assign", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/v1_roles.replacePermissionsRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/Role" + "type": "array", + "items": { + "$ref": "#/definitions/ServiceAccountAPIKey" + } } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/api/v1/runs": { - "get": { - "security": [ - { - "ApiKeyAuth": [] + } + } + }, + "post": { + "security": [ + { + "ApiKeyAuth": [] }, { "BearerAuth": [] } ], - "description": "Get paginated list of runs with filtering", + "description": "Create a new API key. The plaintext key is only returned once.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "runs" + "service_accounts" ], - "summary": "List runs", - "operationId": "getRuns", + "summary": "Create API key for a service account", + "operationId": "postServiceAccountsIDAPIKeys", "parameters": [ { "type": "string", - "description": "Comma-separated list of pipeline names", - "name": "pipelines", - "in": "query" - }, - { - "type": "string", - "description": "Comma-separated list of statuses", - "name": "statuses", - "in": "query" - }, - { - "type": "integer", - "default": 50, - "description": "Number of results per page", - "name": "limit", - "in": "query" + "description": "Service account ID", + "name": "id", + "in": "path", + "required": true }, { - "type": "integer", - "default": 0, - "description": "Number of results to skip", - "name": "offset", - "in": "query" + "description": "API key details", + "name": "key", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/CreateServiceAccountAPIKeyRequest" + } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "type": "object", - "properties": { - "limit": { - "type": "integer" - }, - "offset": { - "type": "integer" - }, - "pipelines": { - "type": "array", - "items": { - "type": "string" - } - }, - "runs": { - "type": "array", - "items": { - "$ref": "#/definitions/PluginRun" - } - }, - "total": { - "type": "integer" - } - } + "$ref": "#/definitions/ServiceAccountAPIKey" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } } }, - "/api/v1/runs/assets/batch": { - "post": { + "/api/v1/service-accounts/{id}/api-keys/{keyId}": { + "delete": { "security": [ { "ApiKeyAuth": [] @@ -8023,41 +7990,43 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Create/update assets within a run", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], + "description": "Delete an API key for a service account", "tags": [ - "runs" + "service_accounts" ], - "summary": "Batch create assets", - "operationId": "postRunsAssetsBatch", + "summary": "Delete an API key", + "operationId": "deleteServiceAccountsIDAPIKeysKeyID", "parameters": [ { - "description": "Batch create request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/BatchCreateRequest" - } + "type": "string", + "description": "Service account ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "API key ID", + "name": "keyId", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", "schema": { - "$ref": "#/definitions/BatchCreateResponse" + "$ref": "#/definitions/ErrorResponse" } } } } }, - "/api/v1/runs/cleanup": { - "post": { + "/api/v1/sso-providers": { + "get": { "security": [ { "ApiKeyAuth": [] @@ -8066,27 +8035,27 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Mark runs as failed if they've been running too long without updates", + "description": "Read-only view of SSO providers wired via server config. Editing is done in config.yaml.", + "produces": [ + "application/json" + ], "tags": [ - "runs" + "auth" ], - "summary": "Cleanup stale runs", - "operationId": "postRunsCleanup", + "summary": "List configured SSO providers (admin)", + "operationId": "getSsoProviders", "responses": { "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "integer" - } + "$ref": "#/definitions/SSOProvidersResponse" } } } } }, - "/api/v1/runs/complete": { - "post": { + "/api/v1/sso/team-mappings": { + "get": { "security": [ { "ApiKeyAuth": [] @@ -8095,7 +8064,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Complete a run with results", + "description": "Get a list of SSO group to team mappings", "consumes": [ "application/json" ], @@ -8103,35 +8072,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "runs" + "sso" ], - "summary": "Complete run", - "operationId": "postRunsComplete", + "summary": "List SSO team mappings", + "operationId": "getSsoTeamMappings", "parameters": [ { - "description": "Complete run request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/CompleteRunRequest" - } + "type": "string", + "description": "Filter by SSO provider", + "name": "provider", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/ListSSOMappingsResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } - } - }, - "/api/v1/runs/start": { + }, "post": { "security": [ { @@ -8141,7 +8108,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Start a new run for tracking", + "description": "Create a new SSO group to team mapping", "consumes": [ "application/json" ], @@ -8149,32 +8116,50 @@ const docTemplate = `{ "application/json" ], "tags": [ - "runs" + "sso" ], - "summary": "Start run", - "operationId": "postRunsStart", + "summary": "Create an SSO team mapping", + "operationId": "postSsoTeamMappings", "parameters": [ { - "description": "Start run request", - "name": "request", + "description": "SSO mapping creation request", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/StartRunRequest" + "$ref": "#/definitions/CreateSSOMappingRequest" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/PluginRun" + "$ref": "#/definitions/SSOTeamMapping" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } } }, - "/api/v1/runs/{id}": { + "/api/v1/sso/team-mappings/{id}": { "get": { "security": [ { @@ -8184,19 +8169,22 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get a specific run by ID", + "description": "Get an SSO team mapping by its ID", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "runs" + "sso" ], - "summary": "Get run", - "operationId": "getRunsID", + "summary": "Get an SSO team mapping", + "operationId": "getSsoTeamMappingsID", "parameters": [ { "type": "string", - "description": "Run ID", + "description": "SSO mapping ID", "name": "id", "in": "path", "required": true @@ -8206,14 +8194,24 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/PluginRun" + "$ref": "#/definitions/SSOTeamMapping" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } - } - }, - "/api/v1/runs/{id}/entities": { - "get": { + }, + "put": { "security": [ { "ApiKeyAuth": [] @@ -8222,62 +8220,64 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get paginated list of entities for a specific run", + "description": "Update an SSO team mapping by its ID", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "runs" + "sso" ], - "summary": "Get run entities", - "operationId": "getRunsIDEntities", + "summary": "Update an SSO team mapping", + "operationId": "putSsoTeamMappingsID", "parameters": [ { "type": "string", - "description": "Run ID", + "description": "SSO mapping ID", "name": "id", "in": "path", "required": true }, { - "type": "string", - "description": "Filter by entity type (asset, lineage, documentation)", - "name": "entity_type", - "in": "query" - }, - { - "type": "string", - "description": "Filter by status (created, updated, deleted, failed)", - "name": "status", - "in": "query" - }, - { - "type": "integer", - "default": 100, - "description": "Number of results per page", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "default": 0, - "description": "Number of results to skip", - "name": "offset", - "in": "query" + "description": "SSO mapping update request", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/UpdateSSOMappingRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/RunEntitiesResponse" + "$ref": "#/definitions/MessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } - } - }, - "/api/v1/search": { - "get": { + }, + "delete": { "security": [ { "ApiKeyAuth": [] @@ -8286,57 +8286,36 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Search across assets, glossary terms, teams, and users", + "description": "Delete an SSO team mapping by its ID", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "search" + "sso" ], - "summary": "Unified search", - "operationId": "getSearch", + "summary": "Delete an SSO team mapping", + "operationId": "deleteSsoTeamMappingsID", "parameters": [ { "type": "string", - "description": "Search query", - "name": "q", - "in": "query", + "description": "SSO mapping ID", + "name": "id", + "in": "path", "required": true - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "Filter by result types (asset, glossary, team, user)", - "name": "types", - "in": "query" - }, - { - "type": "integer", - "default": 20, - "description": "Limit", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "default": 0, - "description": "Offset", - "name": "offset", - "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/SearchResponse" + "$ref": "#/definitions/MessageResponse" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -8350,7 +8329,7 @@ const docTemplate = `{ } } }, - "/api/v1/service-accounts": { + "/api/v1/teams": { "get": { "security": [ { @@ -8360,23 +8339,39 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get all service accounts", + "description": "Get a paginated list of teams", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "service_accounts" + "teams" + ], + "summary": "List teams", + "operationId": "getTeams", + "parameters": [ + { + "type": "integer", + "default": 50, + "description": "Number of items to return", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "default": 0, + "description": "Number of items to skip", + "name": "offset", + "in": "query" + } ], - "summary": "List service accounts", - "operationId": "getServiceAccounts", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/ServiceAccount" - } + "$ref": "#/definitions/ListTeamsResponse" } }, "500": { @@ -8396,7 +8391,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Create a new service account", + "description": "Create a new team", "consumes": [ "application/json" ], @@ -8404,18 +8399,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Create service account", - "operationId": "postServiceAccounts", + "summary": "Create a team", + "operationId": "postTeams", "parameters": [ { - "description": "Service account", - "name": "account", + "description": "Team creation request", + "name": "team", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateServiceAccountRequest" + "$ref": "#/definitions/CreateTeamRequest" } } ], @@ -8423,7 +8418,7 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/ServiceAccount" + "$ref": "#/definitions/Team" } }, "400": { @@ -8431,11 +8426,23 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } } }, - "/api/v1/service-accounts/{id}": { + "/api/v1/teams/{id}": { "get": { "security": [ { @@ -8445,19 +8452,22 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get a service account by ID", + "description": "Get a team by its ID", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Get service account", - "operationId": "getServiceAccountsID", + "summary": "Get a team", + "operationId": "getTeamsID", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true @@ -8467,7 +8477,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ServiceAccount" + "$ref": "#/definitions/Team" } }, "404": { @@ -8475,10 +8485,16 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } }, - "delete": { + "put": { "security": [ { "ApiKeyAuth": [] @@ -8487,34 +8503,76 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Soft-delete a service account", + "description": "Update a team's fields by its ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Delete service account", - "operationId": "deleteServiceAccountsID", + "summary": "Update a team", + "operationId": "putTeamsID", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true - } - ], - "responses": { - "204": { - "description": "No Content" }, - "404": { - "description": "Not Found", + { + "description": "Team update request", + "name": "team", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/UpdateTeamRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/MessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } }, - "patch": { + "delete": { "security": [ { "ApiKeyAuth": [] @@ -8523,7 +8581,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Update a service account", + "description": "Delete a team by its ID", "consumes": [ "application/json" ], @@ -8531,33 +8589,30 @@ const docTemplate = `{ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Update service account", - "operationId": "patchServiceAccountsID", + "summary": "Delete a team", + "operationId": "deleteTeamsID", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true - }, - { - "description": "Update fields", - "name": "account", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UpdateServiceAccountRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ServiceAccount" + "$ref": "#/definitions/MessageResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" } }, "404": { @@ -8565,11 +8620,17 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } } }, - "/api/v1/service-accounts/{id}/api-keys": { + "/api/v1/teams/{id}/members": { "get": { "security": [ { @@ -8579,19 +8640,22 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get all API keys for a service account", + "description": "Get the members of a team", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "List API keys for a service account", - "operationId": "getServiceAccountsIDAPIKeys", + "summary": "List team members", + "operationId": "getTeamsIDMembers", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true @@ -8601,10 +8665,13 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/ServiceAccountAPIKey" - } + "$ref": "#/definitions/ListMembersResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } @@ -8618,7 +8685,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Create a new API key. The plaintext key is only returned once.", + "description": "Add a user as a member of a team", "consumes": [ "application/json" ], @@ -8626,25 +8693,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Create API key for a service account", - "operationId": "postServiceAccountsIDAPIKeys", + "summary": "Add a team member", + "operationId": "postTeamsIDMembers", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true }, { - "description": "API key details", - "name": "key", + "description": "Member addition request", + "name": "member", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateServiceAccountAPIKeyRequest" + "$ref": "#/definitions/AddMemberRequest" } } ], @@ -8652,7 +8719,7 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/ServiceAccountAPIKey" + "$ref": "#/definitions/MessageResponse" } }, "400": { @@ -8660,11 +8727,29 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } } }, - "/api/v1/service-accounts/{id}/api-keys/{keyId}": { + "/api/v1/teams/{id}/members/{userId}": { "delete": { "security": [ { @@ -8674,72 +8759,58 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Delete an API key for a service account", + "description": "Remove a user from a team", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Delete an API key", - "operationId": "deleteServiceAccountsIDAPIKeysKeyID", + "summary": "Remove a team member", + "operationId": "deleteTeamsIDMembersUserID", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true }, { "type": "string", - "description": "API key ID", - "name": "keyId", + "description": "User ID", + "name": "userId", "in": "path", "required": true } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/MessageResponse" + } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/sso-providers": { - "get": { - "security": [ - { - "ApiKeyAuth": [] }, - { - "BearerAuth": [] - } - ], - "description": "Read-only view of SSO providers wired via server config. Editing is done in config.yaml.", - "produces": [ - "application/json" - ], - "tags": [ - "auth" - ], - "summary": "List configured SSO providers (admin)", - "operationId": "getSsoProviders", - "responses": { - "200": { - "description": "OK", + "500": { + "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/SSOProvidersResponse" + "$ref": "#/definitions/ErrorResponse" } } } } }, - "/api/v1/sso/team-mappings": { - "get": { + "/api/v1/teams/{id}/members/{userId}/convert-to-manual": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -8748,7 +8819,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get a list of SSO group to team mappings", + "description": "Convert an SSO-managed team member to a manually managed member", "consumes": [ "application/json" ], @@ -8756,23 +8827,37 @@ const docTemplate = `{ "application/json" ], "tags": [ - "sso" + "teams" ], - "summary": "List SSO team mappings", - "operationId": "getSsoTeamMappings", + "summary": "Convert member to manual", + "operationId": "postTeamsIDMembersUserIDConvertToManual", "parameters": [ { "type": "string", - "description": "Filter by SSO provider", - "name": "provider", - "in": "query" + "description": "Team ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ListSSOMappingsResponse" + "$ref": "#/definitions/MessageResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" } }, "500": { @@ -8782,8 +8867,10 @@ const docTemplate = `{ } } } - }, - "post": { + } + }, + "/api/v1/teams/{id}/members/{userId}/role": { + "put": { "security": [ { "ApiKeyAuth": [] @@ -8792,7 +8879,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Create a new SSO group to team mapping", + "description": "Update the role of a team member", "consumes": [ "application/json" ], @@ -8800,137 +8887,32 @@ const docTemplate = `{ "application/json" ], "tags": [ - "sso" + "teams" ], - "summary": "Create an SSO team mapping", - "operationId": "postSsoTeamMappings", - "parameters": [ - { - "description": "SSO mapping creation request", - "name": "mapping", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/CreateSSOMappingRequest" - } - } - ], - "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/SSOTeamMapping" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/api/v1/sso/team-mappings/{id}": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Get an SSO team mapping by its ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "sso" - ], - "summary": "Get an SSO team mapping", - "operationId": "getSsoTeamMappingsID", + "summary": "Update member role", + "operationId": "putTeamsIDMembersUserIDRole", "parameters": [ { "type": "string", - "description": "SSO mapping ID", + "description": "Team ID", "name": "id", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/SSOTeamMapping" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - }, - "put": { - "security": [ - { - "ApiKeyAuth": [] }, - { - "BearerAuth": [] - } - ], - "description": "Update an SSO team mapping by its ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "sso" - ], - "summary": "Update an SSO team mapping", - "operationId": "putSsoTeamMappingsID", - "parameters": [ { "type": "string", - "description": "SSO mapping ID", - "name": "id", + "description": "User ID", + "name": "userId", "in": "path", "required": true }, { - "description": "SSO mapping update request", - "name": "mapping", + "description": "Role update request", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/UpdateSSOMappingRequest" + "$ref": "#/definitions/UpdateMemberRoleRequest" } } ], @@ -8960,60 +8942,30 @@ const docTemplate = `{ } } } - }, - "delete": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Delete an SSO team mapping by its ID", - "consumes": [ - "application/json" - ], + } + }, + "/api/v1/ui/config": { + "get": { + "description": "Get UI configuration including banner settings", "produces": [ "application/json" ], "tags": [ - "sso" - ], - "summary": "Delete an SSO team mapping", - "operationId": "deleteSsoTeamMappingsID", - "parameters": [ - { - "type": "string", - "description": "SSO mapping ID", - "name": "id", - "in": "path", - "required": true - } + "ui" ], + "summary": "Get UI configuration", + "operationId": "getUIConfig", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/UIConfigResponse" } } } } }, - "/api/v1/teams": { + "/api/v1/users": { "get": { "security": [ { @@ -9023,7 +8975,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get a paginated list of teams", + "description": "Get a list of users with optional filtering", "consumes": [ "application/json" ], @@ -9031,10 +8983,10 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "List teams", - "operationId": "getTeams", + "summary": "List users", + "operationId": "getUsers", "parameters": [ { "type": "integer", @@ -9049,13 +9001,35 @@ const docTemplate = `{ "description": "Number of items to skip", "name": "offset", "in": "query" + }, + { + "type": "string", + "description": "Search query for username or email", + "name": "query", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "Filter by role IDs", + "name": "role_ids", + "in": "query" + }, + { + "type": "boolean", + "description": "Filter by active status", + "name": "active", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ListTeamsResponse" + "$ref": "#/definitions/ListUsersResponse" } }, "500": { @@ -9075,7 +9049,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Create a new team", + "description": "Create a new user in the system", "consumes": [ "application/json" ], @@ -9083,32 +9057,32 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Create a team", - "operationId": "postTeams", + "summary": "Create a new user", + "operationId": "postUsers", "parameters": [ { - "description": "Team creation request", - "name": "team", + "description": "User creation request", + "name": "user", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateTeamRequest" + "$ref": "#/definitions/CreateUserInput" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/Team" + "$ref": "#/definitions/User" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/ValidationErrorResponse" } }, "409": { @@ -9116,17 +9090,11 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/teams/{id}": { + "/api/v1/users/apikeys": { "get": { "security": [ { @@ -9136,7 +9104,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get a team by its ID", + "description": "Get all API keys for a user", "consumes": [ "application/json" ], @@ -9144,30 +9112,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" - ], - "summary": "Get a team", - "operationId": "getTeamsID", - "parameters": [ - { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - } + "users" ], + "summary": "List API keys", + "operationId": "getUsersApikeys", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/Team" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "type": "array", + "items": { + "$ref": "#/definitions/APIKey" + } } }, "500": { @@ -9178,7 +9134,7 @@ const docTemplate = `{ } } }, - "put": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -9187,7 +9143,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Update a team's fields by its ID", + "description": "Create a new API key for a user", "consumes": [ "application/json" ], @@ -9195,25 +9151,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Update a team", - "operationId": "putTeamsID", + "summary": "Create API key", + "operationId": "postUsersApikeys", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Team update request", - "name": "team", + "description": "API key creation request", + "name": "key", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/UpdateTeamRequest" + "$ref": "#/definitions/CreateAPIKeyRequest" } } ], @@ -9221,7 +9170,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" + "$ref": "#/definitions/APIKey" } }, "400": { @@ -9229,33 +9178,11 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } - }, + } + }, + "/api/v1/users/apikeys/{id}": { "delete": { "security": [ { @@ -9265,7 +9192,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Delete a team by its ID", + "description": "Delete an API key", "consumes": [ "application/json" ], @@ -9273,28 +9200,25 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Delete a team", - "operationId": "deleteTeamsID", + "summary": "Delete API key", + "operationId": "deleteUsersApikeysID", "parameters": [ { "type": "string", - "description": "Team ID", + "description": "API key ID", "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/MessageResponse" - } + "204": { + "description": "No Content" }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9304,27 +9228,17 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/teams/{id}/members": { - "get": { + "/api/v1/users/change-password": { + "post": { "security": [ - { - "ApiKeyAuth": [] - }, { "BearerAuth": [] } ], - "description": "Get the members of a team", "consumes": [ "application/json" ], @@ -9332,44 +9246,40 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "List team members", - "operationId": "getTeamsIDMembers", + "summary": "Change the current local user's password", + "operationId": "changeOwnPassword", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true + "description": "Current and new password", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_users.ChangePasswordRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ListMembersResponse" + "$ref": "#/definitions/TokenResponse" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, + } + }, + "/api/v1/users/login": { "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Add a user as a member of a team", + "description": "Authenticate a user with username/email and password", "consumes": [ "application/json" ], @@ -9377,33 +9287,26 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Add a team member", - "operationId": "postTeamsIDMembers", + "summary": "Login user", + "operationId": "postUsersLogin", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Member addition request", - "name": "member", + "description": "Login credentials", + "name": "credentials", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/AddMemberRequest" + "$ref": "#/definitions/LoginRequest" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" + "$ref": "#/definitions/TokenResponse" } }, "400": { @@ -9412,20 +9315,8 @@ const docTemplate = `{ "$ref": "#/definitions/ErrorResponse" } }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9433,17 +9324,8 @@ const docTemplate = `{ } } }, - "/api/v1/teams/{id}/members/{userId}": { - "delete": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Remove a user from a team", + "/api/v1/users/login/password": { + "post": { "consumes": [ "application/json" ], @@ -9451,41 +9333,54 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Remove a team member", - "operationId": "deleteTeamsIDMembersUserID", + "summary": "Change a mandatory password before the second factor", + "operationId": "changeLoginPassword", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true + "description": "Verification request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_users.TOTPRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" + "$ref": "#/definitions/TokenResponse" } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "429": { + "description": "Too Many Requests", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "503": { + "description": "Service Unavailable", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9493,17 +9388,8 @@ const docTemplate = `{ } } }, - "/api/v1/teams/{id}/members/{userId}/convert-to-manual": { + "/api/v1/users/login/totp": { "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Convert an SSO-managed team member to a manually managed member", "consumes": [ "application/json" ], @@ -9511,116 +9397,54 @@ const docTemplate = `{ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Convert member to manual", - "operationId": "postTeamsIDMembersUserIDConvertToManual", + "summary": "Complete local login using a second factor", + "operationId": "verifyTOTPLogin", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true + "description": "Verification request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_users.TOTPRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" + "$ref": "#/definitions/TokenResponse" } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/teams/{id}/members/{userId}/role": { - "put": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Update the role of a team member", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "teams" - ], - "summary": "Update member role", - "operationId": "putTeamsIDMembersUserIDRole", - "parameters": [ - { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true - }, - { - "description": "Role update request", - "name": "role", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UpdateMemberRoleRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/MessageResponse" - } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "404": { - "description": "Not Found", + "429": { + "description": "Too Many Requests", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "500": { - "description": "Internal Server Error", + "503": { + "description": "Service Unavailable", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9628,38 +9452,8 @@ const docTemplate = `{ } } }, - "/api/v1/ui/config": { - "get": { - "description": "Get UI configuration including banner settings", - "produces": [ - "application/json" - ], - "tags": [ - "ui" - ], - "summary": "Get UI configuration", - "operationId": "getUIConfig", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/UIConfigResponse" - } - } - } - } - }, - "/api/v1/users": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Get a list of users with optional filtering", + "/api/v1/users/login/totp/confirm": { + "post": { "consumes": [ "application/json" ], @@ -9669,71 +9463,37 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "List users", - "operationId": "getUsers", + "summary": "Confirm required TOTP enrollment and return recovery codes once", + "operationId": "confirmRequiredTOTP", "parameters": [ { - "type": "integer", - "default": 50, - "description": "Number of items to return", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "default": 0, - "description": "Number of items to skip", - "name": "offset", - "in": "query" - }, - { - "type": "string", - "description": "Search query for username or email", - "name": "query", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "Filter by role IDs", - "name": "role_ids", - "in": "query" - }, - { - "type": "boolean", - "description": "Filter by active status", - "name": "active", - "in": "query" + "description": "Enrollment challenge and code", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_users.TOTPRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ListUsersResponse" + "$ref": "#/definitions/v1_users.RecoveryResponse" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, + } + }, + "/api/v1/users/login/totp/setup": { "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Create a new user in the system", "consumes": [ "application/json" ], @@ -9743,16 +9503,16 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Create a new user", - "operationId": "postUsers", + "summary": "Prepare required TOTP enrollment after password login", + "operationId": "setupRequiredTOTP", "parameters": [ { - "description": "User creation request", - "name": "user", + "description": "Enrollment challenge", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateUserInput" + "$ref": "#/definitions/v1_users.TOTPRequest" } } ], @@ -9760,17 +9520,11 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/User" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ValidationErrorResponse" + "$ref": "#/definitions/mfa.SetupResult" } }, - "409": { - "description": "Conflict", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9778,7 +9532,7 @@ const docTemplate = `{ } } }, - "/api/v1/users/apikeys": { + "/api/v1/users/me": { "get": { "security": [ { @@ -9788,7 +9542,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get all API keys for a user", + "description": "Get detailed information about the currently authenticated user", "consumes": [ "application/json" ], @@ -9798,26 +9552,25 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "List API keys", - "operationId": "getUsersApikeys", + "summary": "Get current user profile", + "operationId": "getUsersMe", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/APIKey" - } + "$ref": "#/definitions/User" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, + } + }, + "/api/v1/users/oauth/link": { "post": { "security": [ { @@ -9827,7 +9580,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Create a new API key for a user", + "description": "Link an OAuth account to an existing user", "consumes": [ "application/json" ], @@ -9837,25 +9590,22 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Create API key", - "operationId": "postUsersApikeys", + "summary": "Link OAuth account", + "operationId": "postUsersOauthLink", "parameters": [ { - "description": "API key creation request", - "name": "key", + "description": "OAuth account link request", + "name": "link", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateAPIKeyRequest" + "$ref": "#/definitions/OAuthLinkRequest" } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/APIKey" - } + "description": "OK" }, "400": { "description": "Bad Request", @@ -9866,7 +9616,7 @@ const docTemplate = `{ } } }, - "/api/v1/users/apikeys/{id}": { + "/api/v1/users/oauth/unlink/{id}/{provider}": { "delete": { "security": [ { @@ -9876,7 +9626,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Delete an API key", + "description": "Unlink an OAuth account from a user", "consumes": [ "application/json" ], @@ -9886,15 +9636,22 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Delete API key", - "operationId": "deleteUsersApikeysID", + "summary": "Unlink OAuth account", + "operationId": "deleteUsersOauthUnlinkIDProvider", "parameters": [ { "type": "string", - "description": "API key ID", + "description": "User ID", "name": "id", "in": "path", "required": true + }, + { + "type": "string", + "description": "OAuth provider", + "name": "provider", + "in": "path", + "required": true } ], "responses": { @@ -9906,54 +9663,40 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/users/change-password": { + "/api/v1/users/password/require-change/{id}": { "post": { "security": [ { "BearerAuth": [] } ], - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "Change the current local user's password", - "operationId": "changeOwnPassword", + "summary": "Require a local user to change their password at next login", + "operationId": "requirePasswordChange", "parameters": [ { - "description": "Current and new password", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/v1_users.ChangePasswordRequest" - } + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/TokenResponse" - } + "204": { + "description": "No Content" }, - "401": { - "description": "Unauthorized", + "403": { + "description": "Forbidden", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9961,9 +9704,17 @@ const docTemplate = `{ } } }, - "/api/v1/users/login": { - "post": { - "description": "Authenticate a user with username/email and password", + "/api/v1/users/preferences": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BearerAuth": [] + } + ], + "description": "Update preferences for the current user", "consumes": [ "application/json" ], @@ -9973,70 +9724,100 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Login user", - "operationId": "postUsersLogin", + "summary": "Update user preferences", + "operationId": "putUsersPreferences", "parameters": [ { - "description": "Login credentials", - "name": "credentials", + "description": "User preferences", + "name": "preferences", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/LoginRequest" + "type": "object", + "additionalProperties": true } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/TokenResponse" - } + "description": "OK" }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/users/login/password": { + "/api/v1/users/sign-out-all/{id}": { "post": { - "consumes": [ - "application/json" + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BearerAuth": [] + } ], + "description": "Rejects every token issued to the user before now. Their password and API keys are untouched, so this is the response to a leaked or overexposed token rather than a lost credential.", "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "Change a mandatory password before the second factor", - "operationId": "changeLoginPassword", + "summary": "Sign a user out of all sessions", + "operationId": "postUsersIDSignOutAll", "parameters": [ { - "description": "Verification request", - "name": "request", - "in": "body", - "required": true, + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" + "$ref": "#/definitions/ErrorResponse" } } + } + } + }, + "/api/v1/users/totp": { + "get": { + "security": [ + { + "BearerAuth": [] + }, + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" ], + "tags": [ + "users" + ], + "summary": "Get local two-factor status", + "operationId": "totpStatus", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/TokenResponse" + "$ref": "#/definitions/mfa.Status" } }, "400": { @@ -10070,10 +9851,13 @@ const docTemplate = `{ } } } - } - }, - "/api/v1/users/login/totp": { - "post": { + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], "consumes": [ "application/json" ], @@ -10083,8 +9867,8 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Complete local login using a second factor", - "operationId": "verifyTOTPLogin", + "summary": "Disable TOTP with password and second factor", + "operationId": "disableTOTP", "parameters": [ { "description": "Verification request", @@ -10100,7 +9884,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/TokenResponse" + "$ref": "#/definitions/v1_users.RecoveryResponse" } }, "400": { @@ -10136,8 +9920,13 @@ const docTemplate = `{ } } }, - "/api/v1/users/login/totp/confirm": { + "/api/v1/users/totp/confirm": { "post": { + "security": [ + { + "BearerAuth": [] + } + ], "consumes": [ "application/json" ], @@ -10147,11 +9936,11 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Confirm required TOTP enrollment and return recovery codes once", - "operationId": "confirmRequiredTOTP", + "summary": "Confirm TOTP and return recovery codes once", + "operationId": "confirmTOTP", "parameters": [ { - "description": "Enrollment challenge and code", + "description": "Verification request", "name": "request", "in": "body", "required": true, @@ -10167,48 +9956,32 @@ const docTemplate = `{ "$ref": "#/definitions/v1_users.RecoveryResponse" } }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "401": { "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/users/login/totp/setup": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Prepare required TOTP enrollment after password login", - "operationId": "setupRequiredTOTP", - "parameters": [ - { - "description": "Enrollment challenge", - "name": "request", - "in": "body", - "required": true, + }, + "403": { + "description": "Forbidden", "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" + "$ref": "#/definitions/ErrorResponse" } - } - ], - "responses": { - "200": { - "description": "OK", + }, + "429": { + "description": "Too Many Requests", "schema": { - "$ref": "#/definitions/mfa.SetupResult" + "$ref": "#/definitions/ErrorResponse" } }, - "401": { - "description": "Unauthorized", + "503": { + "description": "Service Unavailable", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10216,55 +9989,44 @@ const docTemplate = `{ } } }, - "/api/v1/users/me": { + "/api/v1/users/totp/enrolled": { "get": { "security": [ - { - "ApiKeyAuth": [] - }, { "BearerAuth": [] } ], - "description": "Get detailed information about the currently authenticated user", - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "Get current user profile", - "operationId": "getUsersMe", + "summary": "List users with an enrolled second factor", + "operationId": "listTOTPEnrollment", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/User" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } } } } } }, - "/api/v1/users/oauth/link": { + "/api/v1/users/totp/recovery": { "post": { "security": [ - { - "ApiKeyAuth": [] - }, { "BearerAuth": [] } ], - "description": "Link an OAuth account to an existing user", "consumes": [ "application/json" ], @@ -10274,160 +10036,52 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Link OAuth account", - "operationId": "postUsersOauthLink", + "summary": "Replace one-use recovery codes", + "operationId": "regenerateRecovery", "parameters": [ { - "description": "OAuth account link request", - "name": "link", + "description": "Verification request", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/OAuthLinkRequest" + "$ref": "#/definitions/v1_users.TOTPRequest" } } ], "responses": { "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request", + "description": "OK", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/v1_users.RecoveryResponse" } - } - } - } - }, - "/api/v1/users/oauth/unlink/{id}/{provider}": { - "delete": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Unlink an OAuth account from a user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Unlink OAuth account", - "operationId": "deleteUsersOauthUnlinkIDProvider", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "OAuth provider", - "name": "provider", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/users/password/require-change/{id}": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Require a local user to change their password at next login", - "operationId": "requirePasswordChange", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } }, "403": { "description": "Forbidden", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/users/preferences": { - "put": { - "security": [ - { - "ApiKeyAuth": [] }, - { - "BearerAuth": [] - } - ], - "description": "Update preferences for the current user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Update user preferences", - "operationId": "putUsersPreferences", - "parameters": [ - { - "description": "User preferences", - "name": "preferences", - "in": "body", - "required": true, + "429": { + "description": "Too Many Requests", "schema": { - "type": "object", - "additionalProperties": true + "$ref": "#/definitions/ErrorResponse" } - } - ], - "responses": { - "200": { - "description": "OK" }, - "400": { - "description": "Bad Request", + "503": { + "description": "Service Unavailable", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10435,25 +10089,24 @@ const docTemplate = `{ } } }, - "/api/v1/users/sign-out-all/{id}": { - "post": { + "/api/v1/users/totp/reset/{id}": { + "delete": { "security": [ - { - "ApiKeyAuth": [] - }, { "BearerAuth": [] } ], - "description": "Rejects every token issued to the user before now. Their password and API keys are untouched, so this is the response to a leaked or overexposed token rather than a lost credential.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "Sign a user out of all sessions", - "operationId": "postUsersIDSignOutAll", + "summary": "Administratively reset a local second factor", + "operationId": "resetTOTP", "parameters": [ { "type": "string", @@ -10467,43 +10120,6 @@ const docTemplate = `{ "204": { "description": "No Content" }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/api/v1/users/totp": { - "get": { - "security": [ - { - "BearerAuth": [] - }, - { - "ApiKeyAuth": [] - } - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Get local two-factor status", - "operationId": "totpStatus", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/mfa.Status" - } - }, "400": { "description": "Bad Request", "schema": { @@ -10535,8 +10151,10 @@ const docTemplate = `{ } } } - }, - "delete": { + } + }, + "/api/v1/users/totp/setup": { + "post": { "security": [ { "BearerAuth": [] @@ -10551,8 +10169,8 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Disable TOTP with password and second factor", - "operationId": "disableTOTP", + "summary": "Prepare an encrypted TOTP enrollment", + "operationId": "setupTOTP", "parameters": [ { "description": "Verification request", @@ -10568,7 +10186,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1_users.RecoveryResponse" + "$ref": "#/definitions/mfa.SetupResult" } }, "400": { @@ -10604,13 +10222,14 @@ const docTemplate = `{ } } }, - "/api/v1/users/totp/confirm": { + "/api/v1/users/update-password": { "post": { "security": [ { "BearerAuth": [] } ], + "description": "Update current user's password", "consumes": [ "application/json" ], @@ -10620,16 +10239,16 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Confirm TOTP and return recovery codes once", - "operationId": "confirmTOTP", + "summary": "Update user password", + "operationId": "postUsersUpdatePassword", "parameters": [ { - "description": "Verification request", + "description": "Password update request", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" + "$ref": "#/definitions/UpdatePasswordRequest" } } ], @@ -10637,7 +10256,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1_users.RecoveryResponse" + "$ref": "#/definitions/TokenResponse" } }, "400": { @@ -10651,66 +10270,72 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "429": { - "description": "Too Many Requests", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "503": { - "description": "Service Unavailable", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/users/totp/enrolled": { + "/api/v1/users/{id}": { "get": { "security": [ + { + "ApiKeyAuth": [] + }, { "BearerAuth": [] } ], + "description": "Get detailed information about a specific user", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "List users with an enrolled second factor", - "operationId": "listTOTPEnrollment", + "summary": "Get a user by ID", + "operationId": "getUsersID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } + "$ref": "#/definitions/User" } - } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } } - } - }, - "/api/v1/users/totp/recovery": { - "post": { + }, + "put": { "security": [ + { + "ApiKeyAuth": [] + }, { "BearerAuth": [] } ], + "description": "Update user information", "consumes": [ "application/json" ], @@ -10720,16 +10345,23 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Replace one-use recovery codes", - "operationId": "regenerateRecovery", + "summary": "Update a user", + "operationId": "putUsersID", "parameters": [ { - "description": "Verification request", - "name": "request", + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User update request", + "name": "user", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" + "$ref": "#/definitions/UpdateUserInput" } } ], @@ -10737,49 +10369,39 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1_users.RecoveryResponse" + "$ref": "#/definitions/User" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/ValidationErrorResponse" } }, - "429": { - "description": "Too Many Requests", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "503": { - "description": "Service Unavailable", + "409": { + "description": "Conflict", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - } - }, - "/api/v1/users/totp/reset/{id}": { + }, "delete": { "security": [ + { + "ApiKeyAuth": [] + }, { "BearerAuth": [] } ], + "description": "Delete a user from the system", "consumes": [ "application/json" ], @@ -10789,8 +10411,8 @@ const docTemplate = `{ "tags": [ "users" ], - "summary": "Administratively reset a local second factor", - "operationId": "resetTOTP", + "summary": "Delete a user", + "operationId": "deleteUsersID", "parameters": [ { "type": "string", @@ -10804,32 +10426,20 @@ const docTemplate = `{ "204": { "description": "No Content" }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "429": { - "description": "Too Many Requests", + "409": { + "description": "Conflict", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "503": { - "description": "Service Unavailable", + "500": { + "description": "Internal Server Error", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10837,40 +10447,66 @@ const docTemplate = `{ } } }, - "/api/v1/users/totp/setup": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "consumes": [ + "/auth-providers": { + "get": { + "description": "Returns the enabled auth providers without sensitive data", + "produces": [ "application/json" ], + "tags": [ + "auth" + ], + "summary": "Get auth configuration", + "operationId": "getAuthProviders", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/AuthConfig" + } + } + } + } + }, + "/auth/{provider}/callback": { + "get": { + "description": "Processes the OAuth callback from any provider", "produces": [ "application/json" ], "tags": [ - "users" + "auth" ], - "summary": "Prepare an encrypted TOTP enrollment", - "operationId": "setupTOTP", + "summary": "Handle OAuth callback", + "operationId": "getAuthProviderCallback", "parameters": [ { - "description": "Verification request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" - } + "type": "string", + "description": "OAuth provider (okta, google, github, etc.)", + "name": "provider", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Authorization code", + "name": "code", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "State parameter for CSRF protection", + "name": "state", + "in": "query", + "required": true } ], "responses": { - "200": { - "description": "OK", + "307": { + "description": "Temporary Redirect", "schema": { - "$ref": "#/definitions/mfa.SetupResult" + "type": "string" } }, "400": { @@ -10879,26 +10515,14 @@ const docTemplate = `{ "$ref": "#/definitions/ErrorResponse" } }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "429": { - "description": "Too Many Requests", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "503": { - "description": "Service Unavailable", + "500": { + "description": "Internal Server Error", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10906,51 +10530,41 @@ const docTemplate = `{ } } }, - "/api/v1/users/update-password": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Update current user's password", - "consumes": [ - "application/json" - ], + "/auth/{provider}/login": { + "get": { + "description": "Redirects the user to the OAuth provider for authentication", "produces": [ "application/json" ], "tags": [ - "users" + "auth" ], - "summary": "Update user password", - "operationId": "postUsersUpdatePassword", + "summary": "Initiate OAuth login", + "operationId": "getAuthProviderLogin", "parameters": [ { - "description": "Password update request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UpdatePasswordRequest" - } + "type": "string", + "description": "OAuth provider (okta, google, github, etc.)", + "name": "provider", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "OK", + "307": { + "description": "Temporary Redirect", "schema": { - "$ref": "#/definitions/TokenResponse" + "type": "string" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "401": { - "description": "Unauthorized", + "500": { + "description": "Internal Server Error", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10958,7 +10572,7 @@ const docTemplate = `{ } } }, - "/api/v1/users/{id}": { + "/glossary/export": { "get": { "security": [ { @@ -10968,115 +10582,47 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Get detailed information about a specific user", - "consumes": [ - "application/json" - ], + "description": "Every term in the import template's columns, so the file can be edited and imported back with on_existing=update. Cells that a spreadsheet would run as formulas are escaped in CSV.", "produces": [ - "application/json" + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "text/csv" ], "tags": [ - "users" + "glossary" ], - "summary": "Get a user by ID", - "operationId": "getUsersID", + "summary": "Export the glossary", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/User" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - }, - "put": { - "security": [ - { - "ApiKeyAuth": [] + "description": "xlsx (default) or csv", + "name": "format", + "in": "query" }, - { - "BearerAuth": [] - } - ], - "description": "Update user information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Update a user", - "operationId": "putUsersID", - "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "User update request", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UpdateUserInput" - } + "description": "Language for labels and help", + "name": "locale", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/User" + "type": "file" } }, "400": { "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ValidationErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, - "delete": { + } + }, + "/glossary/import": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -11085,112 +10631,43 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Delete a user from the system", + "description": "Reads an XLSX or CSV in the template's shape and checks every row. mode=validate (default) writes nothing; mode=apply writes all rows or none, and only when no row has errors. Rows whose name matches a term are skipped unless on_existing=update; on update, empty cells keep the current value.", "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Delete a user", - "operationId": "deleteUsersID", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/auth-providers": { - "get": { - "description": "Returns the enabled auth providers without sensitive data", - "produces": [ - "application/json" - ], - "tags": [ - "auth" + "multipart/form-data" ], - "summary": "Get auth configuration", - "operationId": "getAuthProviders", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/AuthConfig" - } - } - } - } - }, - "/auth/{provider}/callback": { - "get": { - "description": "Processes the OAuth callback from any provider", "produces": [ "application/json" ], "tags": [ - "auth" + "glossary" ], - "summary": "Handle OAuth callback", - "operationId": "getAuthProviderCallback", + "summary": "Import glossary terms from a file", "parameters": [ { - "type": "string", - "description": "OAuth provider (okta, google, github, etc.)", - "name": "provider", - "in": "path", + "type": "file", + "description": "XLSX or CSV file", + "name": "file", + "in": "formData", "required": true }, { "type": "string", - "description": "Authorization code", - "name": "code", - "in": "query", - "required": true + "description": "validate (default) or apply", + "name": "mode", + "in": "query" }, { "type": "string", - "description": "State parameter for CSRF protection", - "name": "state", - "in": "query", - "required": true + "description": "skip (default) or update", + "name": "on_existing", + "in": "query" } ], "responses": { - "307": { - "description": "Temporary Redirect", + "200": { + "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/importer.Result" } }, "400": { @@ -11199,64 +10676,61 @@ const docTemplate = `{ "$ref": "#/definitions/ErrorResponse" } }, - "404": { - "description": "Not Found", + "413": { + "description": "Request Entity Too Large", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "500": { - "description": "Internal Server Error", + "422": { + "description": "Unprocessable Entity", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/importer.Result" } } } } }, - "/auth/{provider}/login": { + "/glossary/import/columns": { "get": { - "description": "Redirects the user to the OAuth provider for authentication", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BearerAuth": [] + } + ], + "description": "The template's columns with label and help in ?locale= (or Accept-Language), type, format, constraints, allowed values and list separator, for building a guide.", "produces": [ "application/json" ], "tags": [ - "auth" + "glossary" ], - "summary": "Initiate OAuth login", - "operationId": "getAuthProviderLogin", + "summary": "Describe the glossary import columns", "parameters": [ { "type": "string", - "description": "OAuth provider (okta, google, github, etc.)", - "name": "provider", - "in": "path", - "required": true + "description": "Language for labels and help", + "name": "locale", + "in": "query" } ], "responses": { - "307": { - "description": "Temporary Redirect", - "schema": { - "type": "string" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/ErrorResponse" + "type": "array", + "items": { + "$ref": "#/definitions/importer.ColumnInfo" + } } } } } }, - "/glossary/export": { + "/glossary/import/template": { "get": { "security": [ { @@ -11266,7 +10740,7 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Every term in the import template's columns, so the file can be edited and imported back with on_existing=update. Cells that a spreadsheet would run as formulas are escaped in CSV.", + "description": "An XLSX (with drop-downs, comments and a guide sheet) or CSV whose columns are the term's own fields plus the metamodel profile's glossary_term fields. Headers are stable field IDs; labels follow ?locale= or Accept-Language.", "produces": [ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "text/csv" @@ -11274,7 +10748,7 @@ const docTemplate = `{ "tags": [ "glossary" ], - "summary": "Export the glossary", + "summary": "Download the glossary import template", "parameters": [ { "type": "string", @@ -11305,167 +10779,9 @@ const docTemplate = `{ } } }, - "/glossary/import": { + "/oauth/token": { "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Reads an XLSX or CSV in the template's shape and checks every row. mode=validate (default) writes nothing; mode=apply writes all rows or none, and only when no row has errors. Rows whose name matches a term are skipped unless on_existing=update; on update, empty cells keep the current value.", - "consumes": [ - "multipart/form-data" - ], - "produces": [ - "application/json" - ], - "tags": [ - "glossary" - ], - "summary": "Import glossary terms from a file", - "parameters": [ - { - "type": "file", - "description": "XLSX or CSV file", - "name": "file", - "in": "formData", - "required": true - }, - { - "type": "string", - "description": "validate (default) or apply", - "name": "mode", - "in": "query" - }, - { - "type": "string", - "description": "skip (default) or update", - "name": "on_existing", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/importer.Result" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "413": { - "description": "Request Entity Too Large", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/importer.Result" - } - } - } - } - }, - "/glossary/import/columns": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "The template's columns with label and help in ?locale= (or Accept-Language), type, format, constraints, allowed values and list separator, for building a guide.", - "produces": [ - "application/json" - ], - "tags": [ - "glossary" - ], - "summary": "Describe the glossary import columns", - "parameters": [ - { - "type": "string", - "description": "Language for labels and help", - "name": "locale", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/importer.ColumnInfo" - } - } - } - } - } - }, - "/glossary/import/template": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "An XLSX (with drop-downs, comments and a guide sheet) or CSV whose columns are the term's own fields plus the metamodel profile's glossary_term fields. Headers are stable field IDs; labels follow ?locale= or Accept-Language.", - "produces": [ - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "text/csv" - ], - "tags": [ - "glossary" - ], - "summary": "Download the glossary import template", - "parameters": [ - { - "type": "string", - "description": "xlsx (default) or csv", - "name": "format", - "in": "query" - }, - { - "type": "string", - "description": "Language for labels and help", - "name": "locale", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "file" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/oauth/token": { - "post": { - "description": "Handles authorization_code grants (with PKCE) and token exchange (RFC 8693).\nFor token-exchange, supported subject_token_type values are\nurn:ietf:params:oauth:token-type:id_token and urn:ietf:params:oauth:token-type:access_token.", + "description": "Handles authorization_code grants (with PKCE) and token exchange (RFC 8693).\nFor token-exchange, supported subject_token_type values are\nurn:ietf:params:oauth:token-type:id_token and urn:ietf:params:oauth:token-type:access_token.", "consumes": [ "application/x-www-form-urlencoded" ], @@ -13860,951 +13176,187 @@ const docTemplate = `{ "provider": { "type": "string" }, - "provider_user_id": { - "type": "string" - }, - "user_id": { - "type": "string" - }, - "user_info": { - "type": "object", - "additionalProperties": true - } - } - }, - "OwnerRequest": { - "type": "object", - "required": [ - "id", - "type" - ], - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "user", - "team" - ] - } - } - }, - "Permission": { - "type": "object", - "properties": { - "action": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "resource_type": { - "type": "string" - } - } - }, - "PluginRun": { - "type": "object", - "properties": { - "completed_at": { - "type": "string" - }, - "config": { - "$ref": "#/definitions/RawPluginConfig" - }, - "created_by": { - "type": "string" - }, - "error_message": { - "type": "string" - }, - "id": { - "type": "string" - }, - "pipeline_name": { - "type": "string" - }, - "run_id": { - "type": "string" - }, - "source_name": { - "type": "string" - }, - "started_at": { - "type": "string" - }, - "status": { - "$ref": "#/definitions/RunStatus" - }, - "summary": { - "$ref": "#/definitions/RunSummary" - } - } - }, - "PreviewRequest": { - "type": "object", - "properties": { - "limit": { - "type": "integer" - }, - "metadata_field": { - "type": "string" - }, - "pattern_type": { - "type": "string" - }, - "pattern_value": { - "type": "string" - }, - "query_expression": { - "type": "string" - }, - "rule_type": { - "type": "string" - } - } - }, - "PreviewResponse": { - "type": "object", - "properties": { - "column_names": { - "type": "array", - "items": { - "type": "string" - } - }, - "rows": { - "type": "array", - "items": { - "type": "array", - "items": {} - } - }, - "total_rows": { - "type": "integer" - } - } - }, - "ProductImageMeta": { - "type": "object", - "properties": { - "content_type": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "data_product_id": { - "type": "string" - }, - "filename": { - "type": "string" - }, - "id": { - "type": "string" - }, - "purpose": { - "$ref": "#/definitions/ImagePurpose" - }, - "size_bytes": { - "type": "integer" - }, - "url": { - "type": "string" - } - } - }, - "QualityAssetResult": { - "type": "object", - "properties": { - "asset_id": { - "type": "string" - }, - "dimensions": { - "description": "Dimensions are the checks the asset meets, in the order of dimensionOrder; they are written\nto the asset with its score and are not stored with the results, so only an evaluation of\nan asset carries them.", - "type": "array", - "items": { - "type": "string" - } - }, - "domain_id": { - "type": "string" - }, - "issue_count": { - "type": "integer" - }, - "issues": { - "description": "Issues is filled for the last successful run only.", - "type": "array", - "items": { - "$ref": "#/definitions/QualityIssue" - } - }, - "mrn": { - "type": "string" - }, - "name": { - "type": "string" - }, - "quality": { - "type": "number" - }, - "scores": { - "description": "Scores are the score of each quality dimension that applies to the asset, out of 100.", - "type": "object", - "additionalProperties": { - "type": "number", - "format": "float64" - } - }, - "status": { - "enum": [ - "compliant", - "warning", - "noncompliant" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.Status" - } - ] - }, - "stub": { - "description": "Stub marks a placeholder created by lineage: it is counted apart and never stored or scored.", - "type": "boolean" - }, - "type": { - "type": "string" - } - } - }, - "QualityCondition": { - "type": "object", - "properties": { - "days": { - "description": "Days moves the date a date operator compares with, from today or from the given date.", - "type": "integer" - }, - "field": { - "type": "string" - }, - "op": { - "type": "string" - }, - "optional": { - "description": "Optional, in a check, lets an empty field pass instead of failing: nothing to judge.", - "type": "boolean" - }, - "value": { - "description": "Value is what the operator compares with; set and unset take none." - } - } - }, - "QualityCustomRule": { - "type": "object", - "properties": { - "checks": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - }, - "code": { - "description": "Code is the finding code the audit reports, which clients translate; it defaults to a\nsnake_case form of the id.", - "type": "string" - }, - "created_at": { - "type": "string" - }, - "created_by": { - "type": "string" - }, - "description": { - "type": "string" - }, - "descriptionKey": { - "type": "string" - }, - "dimension": { - "description": "Dimension is the quality dimension whose score the rule's checks feed.", - "type": "string", - "enum": [ - "completeness", - "validity", - "consistency", - "timeliness" - ] - }, - "enabled": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "labelKey": { - "type": "string" - }, - "name": { - "description": "Name and Description are text in the language of whoever wrote the rule. A profile rule\nuses LabelKey and DescriptionKey, which resolve through the profile's messages.", - "type": "string" - }, - "severity": { - "description": "Severity is what a finding of the rule counts as: error or warning.", - "type": "string" - }, - "updated_at": { - "type": "string" - }, - "updated_by": { - "type": "string" - }, - "version": { - "type": "integer" - }, - "when": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - } - } - }, - "QualityEvaluateRequest": { - "type": "object", - "properties": { - "asset_ids": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "QualityEvaluateResponse": { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityAssetResult" - } - } - } - }, - "QualityFieldCount": { - "type": "object", - "properties": { - "count": { - "type": "integer" - }, - "field_id": { - "type": "string" - } - } - }, - "QualityFieldError": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "field": { - "type": "string" - } - } - }, - "QualityGroupStat": { - "type": "object", - "properties": { - "count": { - "type": "integer" - }, - "key": { - "type": "string" - }, - "value": { - "type": "number" - } - } - }, - "QualityIssue": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "field_id": { - "type": "string" - }, - "item": { - "description": "Item is the position of the offending entry when the field is a list.", - "type": "integer" - }, - "rule_id": { - "$ref": "#/definitions/quality.RuleID" - }, - "section": { - "type": "string" - }, - "severity": { - "enum": [ - "error", - "warning" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.Severity" - } - ] - } - } - }, - "QualityResultsResponse": { - "type": "object", - "properties": { - "limit": { - "type": "integer" - }, - "offset": { - "type": "integer" - }, - "results": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityAssetResult" - } - }, - "total": { - "type": "integer" - } - } - }, - "QualityRetention": { - "type": "object", - "properties": { - "result_days": { - "type": "integer" - }, - "run_days": { - "type": "integer" - } - } - }, - "QualityRule": { - "type": "object", - "properties": { - "checks": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - }, - "code": { - "description": "Code is the finding code the audit reports, which clients translate; it defaults to a\nsnake_case form of the id.", - "type": "string" - }, - "description": { - "type": "string" - }, - "descriptionKey": { - "type": "string" - }, - "dimension": { - "description": "Dimension is the quality dimension whose score the rule's checks feed.", - "type": "string", - "enum": [ - "completeness", - "validity", - "consistency", - "timeliness" - ] - }, - "id": { - "type": "string" - }, - "labelKey": { - "type": "string" - }, - "name": { - "description": "Name and Description are text in the language of whoever wrote the rule. A profile rule\nuses LabelKey and DescriptionKey, which resolve through the profile's messages.", - "type": "string" - }, - "severity": { - "description": "Severity is what a finding of the rule counts as: error or warning.", - "type": "string" - }, - "when": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - } - } - }, - "QualityRuleError": { - "type": "object", - "properties": { - "problems": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityRuleProblem" - } - } - } - }, - "QualityRuleInfo": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "definition": { - "description": "Definition is what the rule checks, for the rules that declare it.", - "allOf": [ - { - "$ref": "#/definitions/QualityRule" - } - ] - }, - "description": { - "type": "string" - }, - "description_key": { - "type": "string" - }, - "dimension": { - "description": "Dimension is the quality dimension the rule feeds.", - "type": "string", - "enum": [ - "completeness", - "validity", - "consistency", - "timeliness" - ] - }, - "enabled": { - "type": "boolean" - }, - "id": { - "$ref": "#/definitions/quality.RuleID" - }, - "label_key": { - "type": "string" - }, - "name": { - "description": "Name and Description are literal text, of a custom rule; LabelKey and DescriptionKey resolve\nthrough the profile's messages, for a profile rule; a built-in rule has neither and the\nclient names it by its id.", - "type": "string" - }, - "problem": { - "description": "Problem says why a custom rule is not applied: it names a field the profile no longer has.", - "type": "string" - }, - "severity": { - "enum": [ - "error", - "warning" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.Severity" - } - ] - }, - "source": { - "enum": [ - "builtin", - "profile", - "custom" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.RuleSource" - } - ] - }, - "version": { - "description": "Version, for a custom rule, is what to send back with If-Match.", - "type": "integer" - } - } - }, - "QualityRuleProblem": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "path": { - "type": "string" - } - } - }, - "QualityRuleRequest": { - "type": "object", - "properties": { - "checks": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - }, - "code": { - "description": "Code is the finding code the audit reports, which clients translate; it defaults to a\nsnake_case form of the id.", - "type": "string" - }, - "description": { - "type": "string" - }, - "descriptionKey": { - "type": "string" - }, - "dimension": { - "description": "Dimension is the quality dimension whose score the rule's checks feed.", - "type": "string", - "enum": [ - "completeness", - "validity", - "consistency", - "timeliness" - ] - }, - "enabled": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "labelKey": { - "type": "string" - }, - "name": { - "description": "Name and Description are text in the language of whoever wrote the rule. A profile rule\nuses LabelKey and DescriptionKey, which resolve through the profile's messages.", - "type": "string" - }, - "severity": { - "description": "Severity is what a finding of the rule counts as: error or warning.", - "type": "string" - }, - "when": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - } - } - }, - "QualityRuleSetting": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "severity": { - "enum": [ - "error", - "warning" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.Severity" - } - ] - } - } - }, - "QualityRulesResponse": { - "type": "object", - "properties": { - "rules": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityRuleInfo" - } - } - } - }, - "QualityRun": { - "type": "object", - "properties": { - "custom_rules": { - "description": "CustomRules are the rules people wrote that the run applied, as they were when it started;\nonly a single run read carries them.", - "type": "array", - "items": { - "$ref": "#/definitions/QualityCustomRule" - } - }, - "error": { - "type": "string" - }, - "finished_at": { - "type": "string" - }, - "id": { - "type": "string" - }, - "metamodel_hash": { - "type": "string" - }, - "metamodel_profile": { - "type": "string" - }, - "metamodel_version": { - "type": "integer" - }, - "processed": { - "type": "integer" - }, - "score_conflicts": { - "type": "integer" - }, - "score_failures": { - "type": "integer" - }, - "scores_written": { - "description": "ScoresWritten, ScoreConflicts and ScoreFailures say how writing the scores on the assets\nwent: written, skipped because the asset was edited after it was read, and failed.", - "type": "integer" - }, - "settings": { - "$ref": "#/definitions/QualitySettings" - }, - "settings_version": { - "type": "integer" - }, - "started_at": { - "type": "string" - }, - "status": { - "enum": [ - "running", - "succeeded", - "failed" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.RunStatus" - } - ] - }, - "summary": { - "$ref": "#/definitions/QualitySummary" - }, - "total": { - "type": "integer" - }, - "trigger": { - "type": "string", - "enum": [ - "manual", - "schedule" - ] + "provider_user_id": { + "type": "string" }, - "triggered_by": { + "user_id": { "type": "string" + }, + "user_info": { + "type": "object", + "additionalProperties": true } } }, - "QualityRunConflict": { + "OwnerRequest": { "type": "object", + "required": [ + "id", + "type" + ], "properties": { - "error": { + "id": { "type": "string" }, - "run": { - "$ref": "#/definitions/QualityRun" + "type": { + "type": "string", + "enum": [ + "user", + "team" + ] } } }, - "QualityRunsResponse": { + "Permission": { "type": "object", "properties": { - "limit": { - "type": "integer" + "action": { + "type": "string" }, - "offset": { - "type": "integer" + "description": { + "type": "string" }, - "runs": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityRun" - } + "id": { + "type": "string" }, - "total": { - "type": "integer" + "name": { + "type": "string" + }, + "resource_type": { + "type": "string" } } }, - "QualitySettings": { + "PluginRun": { "type": "object", "properties": { - "batch_size": { - "type": "integer" + "completed_at": { + "type": "string" }, - "max_run_seconds": { - "type": "integer" + "config": { + "$ref": "#/definitions/RawPluginConfig" }, - "retention": { - "$ref": "#/definitions/QualityRetention" + "created_by": { + "type": "string" }, - "rules": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/QualityRuleSetting" - } + "error_message": { + "type": "string" + }, + "id": { + "type": "string" + }, + "pipeline_name": { + "type": "string" }, - "schedule": { - "description": "Schedule is a five-field cron expression; empty means runs are manual only.", + "run_id": { + "type": "string" + }, + "source_name": { "type": "string" }, - "thresholds": { - "$ref": "#/definitions/QualityThresholds" + "started_at": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/RunStatus" }, - "weights": { - "$ref": "#/definitions/QualityWeights" + "summary": { + "$ref": "#/definitions/RunSummary" } } }, - "QualitySettingsResponse": { + "PreviewRequest": { "type": "object", "properties": { - "batch_size": { - "type": "integer" - }, - "max_run_seconds": { + "limit": { "type": "integer" }, - "next_run": { + "metadata_field": { "type": "string" }, - "retention": { - "$ref": "#/definitions/QualityRetention" - }, - "rules": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/QualityRuleSetting" - } - }, - "schedule": { - "description": "Schedule is a five-field cron expression; empty means runs are manual only.", + "pattern_type": { "type": "string" }, - "thresholds": { - "$ref": "#/definitions/QualityThresholds" - }, - "updated_at": { + "pattern_value": { "type": "string" }, - "updated_by": { + "query_expression": { "type": "string" }, - "version": { - "type": "integer" - }, - "weights": { - "$ref": "#/definitions/QualityWeights" + "rule_type": { + "type": "string" } } }, - "QualitySummary": { + "PreviewResponse": { "type": "object", "properties": { - "by_dimension": { - "description": "ByDimension is the mean score of each quality dimension, over the assets it applies to.", + "column_names": { "type": "array", "items": { - "$ref": "#/definitions/QualityGroupStat" + "type": "string" } }, - "by_domain": { - "description": "ByDomain is one more aggregate of the run, not a filter of it; the assets of no domain are\nunder \"unassigned\".", + "rows": { "type": "array", "items": { - "$ref": "#/definitions/QualityGroupStat" + "type": "array", + "items": {} } }, - "by_section": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityGroupStat" - } + "total_rows": { + "type": "integer" + } + } + }, + "ProductImageMeta": { + "type": "object", + "properties": { + "content_type": { + "type": "string" }, - "by_type": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityGroupStat" - } + "created_at": { + "type": "string" }, - "quality": { - "type": "number" + "data_product_id": { + "type": "string" }, - "status_counts": { - "type": "object", - "additionalProperties": { - "type": "integer" - } + "filename": { + "type": "string" }, - "stubs": { - "type": "integer" + "id": { + "type": "string" }, - "top_fields": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityFieldCount" - } + "purpose": { + "$ref": "#/definitions/ImagePurpose" }, - "total_assets": { + "size_bytes": { "type": "integer" }, - "total_issues": { - "type": "integer" + "url": { + "type": "string" } } }, - "QualityThresholds": { + "QualityCondition": { "type": "object", "properties": { - "compliant": { - "type": "number" + "days": { + "description": "Days moves the date a date operator compares with, from today or from the given date.", + "type": "integer" }, - "warning": { - "type": "number" - } - } - }, - "QualityValidationError": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityFieldError" - } - } - } - }, - "QualityWeights": { - "type": "object", - "properties": { - "completeness": { - "type": "number" + "field": { + "type": "string" }, - "consistency": { - "type": "number" + "op": { + "type": "string" }, - "timeliness": { - "type": "number" + "optional": { + "description": "Optional, in a check, lets an empty field pass instead of failing: nothing to judge.", + "type": "boolean" }, - "validity": { - "type": "number" + "value": { + "description": "Value is what the operator compares with; set and unset take none." } } }, @@ -16904,6 +15456,57 @@ const docTemplate = `{ } } }, + "metamodel.QualityRule": { + "type": "object", + "properties": { + "checks": { + "type": "array", + "items": { + "$ref": "#/definitions/QualityCondition" + } + }, + "code": { + "description": "Code is the finding code the audit reports, which clients translate; it defaults to a\nsnake_case form of the id.", + "type": "string" + }, + "description": { + "type": "string" + }, + "descriptionKey": { + "type": "string" + }, + "dimension": { + "description": "Dimension is the quality dimension whose score the rule's checks feed.", + "type": "string", + "enum": [ + "completeness", + "validity", + "consistency", + "timeliness" + ] + }, + "id": { + "type": "string" + }, + "labelKey": { + "type": "string" + }, + "name": { + "description": "Name and Description are text in the language of whoever wrote the rule. A profile rule\nuses LabelKey and DescriptionKey, which resolve through the profile's messages.", + "type": "string" + }, + "severity": { + "description": "Severity is what a finding of the rule counts as: error or warning.", + "type": "string" + }, + "when": { + "type": "array", + "items": { + "$ref": "#/definitions/QualityCondition" + } + } + } + }, "metamodel.Schema": { "type": "object", "properties": { @@ -16942,7 +15545,7 @@ const docTemplate = `{ "description": "QualityRules are the checks the quality audit applies on top of the fields' own validation.", "type": "array", "items": { - "$ref": "#/definitions/QualityRule" + "$ref": "#/definitions/metamodel.QualityRule" } }, "version": { @@ -17170,71 +15773,6 @@ const docTemplate = `{ } } }, - "quality.RuleID": { - "type": "string", - "enum": [ - "required", - "validation", - "externalLinkInvalid", - "externalLinkEmpty" - ], - "x-enum-varnames": [ - "RuleRequired", - "RuleValidation", - "RuleExternalLinkInvalid", - "RuleExternalLinkEmpty" - ] - }, - "quality.RuleSource": { - "type": "string", - "enum": [ - "builtin", - "profile", - "custom" - ], - "x-enum-varnames": [ - "SourceBuiltin", - "SourceProfile", - "SourceCustom" - ] - }, - "quality.RunStatus": { - "type": "string", - "enum": [ - "running", - "succeeded", - "failed" - ], - "x-enum-varnames": [ - "RunRunning", - "RunSucceeded", - "RunFailed" - ] - }, - "quality.Severity": { - "type": "string", - "enum": [ - "error", - "warning" - ], - "x-enum-varnames": [ - "SeverityError", - "SeverityWarning" - ] - }, - "quality.Status": { - "type": "string", - "enum": [ - "compliant", - "warning", - "noncompliant" - ], - "x-enum-varnames": [ - "StatusCompliant", - "StatusWarning", - "StatusNoncompliant" - ] - }, "v1_assets.patchFieldsRequest": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 525ea357..8a89d6c1 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -6927,7 +6927,43 @@ } } }, - "/api/v1/quality/evaluate": { + "/api/v1/roles": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BearerAuth": [] + } + ], + "description": "List all active roles with user counts and permissions", + "produces": [ + "application/json" + ], + "tags": [ + "roles" + ], + "summary": "List roles", + "operationId": "getRoles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Role" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, "post": { "security": [ { @@ -6937,7 +6973,7 @@ "BearerAuth": [] } ], - "description": "Judges up to 200 assets as they are, with the current settings, profile rules and custom rules, and records nothing. It is what a card on an asset page shows: findings and the checks the asset meets. An id that is not an asset is left out.", + "description": "Create a new role with optional initial permissions", "consumes": [ "application/json" ], @@ -6945,18 +6981,18 @@ "application/json" ], "tags": [ - "quality" + "roles" ], - "summary": "Evaluate assets now", - "operationId": "evaluateQualityAssets", + "summary": "Create a role", + "operationId": "postRoles", "parameters": [ { - "description": "Assets", - "name": "request", + "description": "Role creation request", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/QualityEvaluateRequest" + "$ref": "#/definitions/v1_roles.createRoleRequest" } } ], @@ -6964,7 +7000,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityEvaluateResponse" + "$ref": "#/definitions/Role" } }, "400": { @@ -6973,20 +7009,8 @@ "$ref": "#/definitions/ErrorResponse" } }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "422": { - "description": "Unprocessable Entity", + "409": { + "description": "Conflict", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -6994,7 +7018,7 @@ } } }, - "/api/v1/quality/rules": { + "/api/v1/roles/{id}": { "get": { "security": [ { @@ -7004,37 +7028,40 @@ "BearerAuth": [] } ], - "description": "Every rule the audit applies: the built-in ones, the ones the metamodel profile declares (read-only here) and the custom ones people wrote. The severity and on/off of the first two are in the settings; a custom rule carries its own.", + "description": "Get a role by ID with its permissions", "produces": [ "application/json" ], "tags": [ - "quality" + "roles" + ], + "summary": "Get a role", + "operationId": "getRolesID", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true + } ], - "summary": "List the quality rules", - "operationId": "listQualityRules", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityRulesResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/Role" } }, - "403": { - "description": "Forbidden", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } } } }, - "post": { + "delete": { "security": [ { "ApiKeyAuth": [] @@ -7043,56 +7070,30 @@ "BearerAuth": [] } ], - "description": "A declarative rule over the fields of the profile: a closed set of operators, never code. 400 lists every problem with its path. The id is generated when omitted.", - "consumes": [ - "application/json" - ], + "description": "Soft-delete a role. Fails if the role is a system role or has active user assignments.", "produces": [ "application/json" ], "tags": [ - "quality" + "roles" ], - "summary": "Create a custom quality rule", - "operationId": "createQualityRule", + "summary": "Delete a role", + "operationId": "deleteRolesID", "parameters": [ { - "description": "Rule", - "name": "rule", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/QualityRuleRequest" - } + "type": "string", + "description": "Role ID", + "name": "id", + "in": "path", + "required": true } ], "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/QualityCustomRule" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/QualityRuleError" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } + "204": { + "description": "No Content" }, - "409": { - "description": "Conflict", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -7104,10 +7105,8 @@ } } } - } - }, - "/api/v1/quality/rules/{id}": { - "put": { + }, + "patch": { "security": [ { "ApiKeyAuth": [] @@ -7116,7 +7115,7 @@ "BearerAuth": [] } ], - "description": "Replaces a custom rule. Requires If-Match with the version read; 412 when someone changed it first. The rules of the profile cannot be changed here.", + "description": "Update a role's name or description. System roles cannot be renamed.", "consumes": [ "application/json" ], @@ -7124,32 +7123,25 @@ "application/json" ], "tags": [ - "quality" + "roles" ], - "summary": "Change a custom quality rule", - "operationId": "updateQualityRule", + "summary": "Update a role", + "operationId": "patchRolesID", "parameters": [ { "type": "string", - "description": "Rule ID", + "description": "Role ID", "name": "id", "in": "path", "required": true }, { - "type": "string", - "description": "Version read, quoted", - "name": "If-Match", - "in": "header", - "required": true - }, - { - "description": "Rule", - "name": "rule", + "description": "Role update request", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/QualityRuleRequest" + "$ref": "#/definitions/v1_roles.updateRoleRequest" } } ], @@ -7157,13 +7149,13 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityCustomRule" + "$ref": "#/definitions/Role" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/QualityRuleError" + "$ref": "#/definitions/ErrorResponse" } }, "404": { @@ -7172,21 +7164,17 @@ "$ref": "#/definitions/ErrorResponse" } }, - "412": { - "description": "Precondition Failed", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "428": { - "description": "Precondition Required", + "422": { + "description": "Unprocessable Entity", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, - "delete": { + } + }, + "/api/v1/roles/{id}/permissions": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -7195,34 +7183,65 @@ "BearerAuth": [] } ], + "description": "Atomically replace all permissions on a role. System roles enforce a minimum permission floor.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], "tags": [ - "quality" + "roles" ], - "summary": "Delete a custom quality rule", - "operationId": "deleteQualityRule", + "summary": "Replace role permissions", + "operationId": "postRolesIDPermissions", "parameters": [ { "type": "string", - "description": "Rule ID", + "description": "Role ID", "name": "id", "in": "path", "required": true + }, + { + "description": "Permission IDs to assign", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_roles.replacePermissionsRequest" + } } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/Role" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } } }, - "/api/v1/quality/runs": { + "/api/v1/runs": { "get": { "security": [ { @@ -7232,27 +7251,39 @@ "BearerAuth": [] } ], - "description": "Newest first, with the summary of the finished ones.", + "description": "Get paginated list of runs with filtering", "produces": [ "application/json" ], "tags": [ - "quality" + "runs" ], - "summary": "List quality audit runs", - "operationId": "listQualityRuns", + "summary": "List runs", + "operationId": "getRuns", "parameters": [ + { + "type": "string", + "description": "Comma-separated list of pipeline names", + "name": "pipelines", + "in": "query" + }, + { + "type": "string", + "description": "Comma-separated list of statuses", + "name": "statuses", + "in": "query" + }, { "type": "integer", - "default": 20, - "description": "Page size, up to 100", + "default": 50, + "description": "Number of results per page", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, - "description": "Offset", + "description": "Number of results to skip", "name": "offset", "in": "query" } @@ -7261,76 +7292,197 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityRunsResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { + "type": "object", + "properties": { + "limit": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "pipelines": { + "type": "array", + "items": { + "type": "string" + } + }, + "runs": { + "type": "array", + "items": { + "$ref": "#/definitions/PluginRun" + } + }, + "total": { + "type": "integer" + } + } + } + } + } + } + }, + "/api/v1/runs/assets/batch": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + }, + { "BearerAuth": [] } ], - "description": "Audits every asset of the catalog in the background, with the saved settings and the effective metamodel. One run at a time: a second request gets 409 with the run in progress.", + "description": "Create/update assets within a run", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "quality" + "runs" + ], + "summary": "Batch create assets", + "operationId": "postRunsAssetsBatch", + "parameters": [ + { + "description": "Batch create request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/BatchCreateRequest" + } + } ], - "summary": "Start a quality audit run", - "operationId": "startQualityRun", "responses": { - "202": { - "description": "Accepted", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/QualityRun" + "$ref": "#/definitions/BatchCreateResponse" } + } + } + } + }, + "/api/v1/runs/cleanup": { + "post": { + "security": [ + { + "ApiKeyAuth": [] }, - "401": { - "description": "Unauthorized", + { + "BearerAuth": [] + } + ], + "description": "Mark runs as failed if they've been running too long without updates", + "tags": [ + "runs" + ], + "summary": "Cleanup stale runs", + "operationId": "postRunsCleanup", + "responses": { + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/ErrorResponse" + "type": "object", + "additionalProperties": { + "type": "integer" + } } + } + } + } + }, + "/api/v1/runs/complete": { + "post": { + "security": [ + { + "ApiKeyAuth": [] }, - "403": { - "description": "Forbidden", + { + "BearerAuth": [] + } + ], + "description": "Complete a run with results", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "runs" + ], + "summary": "Complete run", + "operationId": "postRunsComplete", + "parameters": [ + { + "description": "Complete run request", + "name": "request", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/CompleteRunRequest" } - }, - "409": { - "description": "Conflict", + } + ], + "responses": { + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/QualityRunConflict" + "type": "object", + "additionalProperties": { + "type": "string" + } } + } + } + } + }, + "/api/v1/runs/start": { + "post": { + "security": [ + { + "ApiKeyAuth": [] }, - "422": { - "description": "Unprocessable Entity", + { + "BearerAuth": [] + } + ], + "description": "Start a new run for tracking", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "runs" + ], + "summary": "Start run", + "operationId": "postRunsStart", + "parameters": [ + { + "description": "Start run request", + "name": "request", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/StartRunRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/PluginRun" } } } } }, - "/api/v1/quality/runs/{id}": { + "/api/v1/runs/{id}": { "get": { "security": [ { @@ -7340,15 +7492,15 @@ "BearerAuth": [] } ], - "description": "The run with its progress, the settings it used and, once finished, its summary.", + "description": "Get a specific run by ID", "produces": [ "application/json" ], "tags": [ - "quality" + "runs" ], - "summary": "Get a quality audit run", - "operationId": "getQualityRun", + "summary": "Get run", + "operationId": "getRunsID", "parameters": [ { "type": "string", @@ -7362,31 +7514,13 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityRun" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/PluginRun" } } } } }, - "/api/v1/quality/runs/{id}/results": { + "/api/v1/runs/{id}/entities": { "get": { "security": [ { @@ -7396,15 +7530,15 @@ "BearerAuth": [] } ], - "description": "One entry per audited asset, weakest first. The findings of each asset are only kept for the last successful run.", + "description": "Get paginated list of entities for a specific run", "produces": [ "application/json" ], "tags": [ - "quality" + "runs" ], - "summary": "List the results of a quality audit run", - "operationId": "getQualityRunResults", + "summary": "Get run entities", + "operationId": "getRunsIDEntities", "parameters": [ { "type": "string", @@ -7415,45 +7549,27 @@ }, { "type": "string", - "description": "compliant, warning or noncompliant", - "name": "status", - "in": "query" - }, - { - "type": "string", - "description": "A domain ID, or unassigned", - "name": "domain", - "in": "query" - }, - { - "type": "string", - "description": "Asset type", - "name": "type", - "in": "query" - }, - { - "type": "string", - "description": "Text in the asset name or MRN", - "name": "q", + "description": "Filter by entity type (asset, lineage, documentation)", + "name": "entity_type", "in": "query" }, { "type": "string", - "description": "quality (default) or name", - "name": "sort", + "description": "Filter by status (created, updated, deleted, failed)", + "name": "status", "in": "query" }, { "type": "integer", - "default": 50, - "description": "Page size, up to 500", + "default": 100, + "description": "Number of results per page", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, - "description": "Offset", + "description": "Number of results to skip", "name": "offset", "in": "query" } @@ -7462,148 +7578,79 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualityResultsResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/RunEntitiesResponse" } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/api/v1/quality/settings": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "The criterion the platform's quality scores are computed with. Version 0 means the defaults, not yet saved.", - "produces": [ - "application/json" - ], - "tags": [ - "quality" - ], - "summary": "Get the quality audit settings", - "operationId": "getQualitySettings", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/QualitySettingsResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - }, - "put": { - "security": [ - { - "ApiKeyAuth": [] + } + } + } + }, + "/api/v1/search": { + "get": { + "security": [ + { + "ApiKeyAuth": [] }, { "BearerAuth": [] } ], - "description": "Replaces the settings. Requires If-Match with the version read; 412 when someone saved first.", - "consumes": [ - "application/json" - ], + "description": "Search across assets, glossary terms, teams, and users", "produces": [ "application/json" ], "tags": [ - "quality" + "search" ], - "summary": "Change the quality audit settings", - "operationId": "putQualitySettings", + "summary": "Unified search", + "operationId": "getSearch", "parameters": [ { "type": "string", - "description": "Version read, quoted; \\", - "name": "If-Match", - "in": "header", + "description": "Search query", + "name": "q", + "in": "query", "required": true }, { - "description": "Settings", - "name": "settings", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/QualitySettings" - } + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "Filter by result types (asset, glossary, team, user)", + "name": "types", + "in": "query" + }, + { + "type": "integer", + "default": 20, + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "default": 0, + "description": "Offset", + "name": "offset", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/QualitySettingsResponse" + "$ref": "#/definitions/SearchResponse" } }, "400": { "description": "Bad Request", - "schema": { - "$ref": "#/definitions/QualityValidationError" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "412": { - "description": "Precondition Failed", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "428": { - "description": "Precondition Required", + "500": { + "description": "Internal Server Error", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -7611,7 +7658,7 @@ } } }, - "/api/v1/roles": { + "/api/v1/service-accounts": { "get": { "security": [ { @@ -7621,22 +7668,22 @@ "BearerAuth": [] } ], - "description": "List all active roles with user counts and permissions", + "description": "Get all service accounts", "produces": [ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "List roles", - "operationId": "getRoles", + "summary": "List service accounts", + "operationId": "getServiceAccounts", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/Role" + "$ref": "#/definitions/ServiceAccount" } } }, @@ -7657,7 +7704,7 @@ "BearerAuth": [] } ], - "description": "Create a new role with optional initial permissions", + "description": "Create a new service account", "consumes": [ "application/json" ], @@ -7665,26 +7712,26 @@ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "Create a role", - "operationId": "postRoles", + "summary": "Create service account", + "operationId": "postServiceAccounts", "parameters": [ { - "description": "Role creation request", - "name": "role", + "description": "Service account", + "name": "account", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1_roles.createRoleRequest" + "$ref": "#/definitions/CreateServiceAccountRequest" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/Role" + "$ref": "#/definitions/ServiceAccount" } }, "400": { @@ -7692,17 +7739,11 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/roles/{id}": { + "/api/v1/service-accounts/{id}": { "get": { "security": [ { @@ -7712,19 +7753,19 @@ "BearerAuth": [] } ], - "description": "Get a role by ID with its permissions", + "description": "Get a service account by ID", "produces": [ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "Get a role", - "operationId": "getRolesID", + "summary": "Get service account", + "operationId": "getServiceAccountsID", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Service account ID", "name": "id", "in": "path", "required": true @@ -7734,7 +7775,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/Role" + "$ref": "#/definitions/ServiceAccount" } }, "404": { @@ -7754,19 +7795,16 @@ "BearerAuth": [] } ], - "description": "Soft-delete a role. Fails if the role is a system role or has active user assignments.", - "produces": [ - "application/json" - ], + "description": "Soft-delete a service account", "tags": [ - "roles" + "service_accounts" ], - "summary": "Delete a role", - "operationId": "deleteRolesID", + "summary": "Delete service account", + "operationId": "deleteServiceAccountsID", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Service account ID", "name": "id", "in": "path", "required": true @@ -7781,12 +7819,6 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } }, @@ -7799,7 +7831,7 @@ "BearerAuth": [] } ], - "description": "Update a role's name or description. System roles cannot be renamed.", + "description": "Update a service account", "consumes": [ "application/json" ], @@ -7807,25 +7839,25 @@ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "Update a role", - "operationId": "patchRolesID", + "summary": "Update service account", + "operationId": "patchServiceAccountsID", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Service account ID", "name": "id", "in": "path", "required": true }, { - "description": "Role update request", - "name": "role", + "description": "Update fields", + "name": "account", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1_roles.updateRoleRequest" + "$ref": "#/definitions/UpdateServiceAccountRequest" } } ], @@ -7833,13 +7865,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/Role" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/ServiceAccount" } }, "404": { @@ -7847,18 +7873,12 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/roles/{id}/permissions": { - "post": { + "/api/v1/service-accounts/{id}/api-keys": { + "get": { "security": [ { "ApiKeyAuth": [] @@ -7867,146 +7887,93 @@ "BearerAuth": [] } ], - "description": "Atomically replace all permissions on a role. System roles enforce a minimum permission floor.", - "consumes": [ - "application/json" - ], + "description": "Get all API keys for a service account", "produces": [ "application/json" ], "tags": [ - "roles" + "service_accounts" ], - "summary": "Replace role permissions", - "operationId": "postRolesIDPermissions", + "summary": "List API keys for a service account", + "operationId": "getServiceAccountsIDAPIKeys", "parameters": [ { "type": "string", - "description": "Role ID", + "description": "Service account ID", "name": "id", "in": "path", "required": true - }, - { - "description": "Permission IDs to assign", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/v1_roles.replacePermissionsRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/Role" + "type": "array", + "items": { + "$ref": "#/definitions/ServiceAccountAPIKey" + } } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/api/v1/runs": { - "get": { - "security": [ - { - "ApiKeyAuth": [] + } + } + }, + "post": { + "security": [ + { + "ApiKeyAuth": [] }, { "BearerAuth": [] } ], - "description": "Get paginated list of runs with filtering", + "description": "Create a new API key. The plaintext key is only returned once.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "runs" + "service_accounts" ], - "summary": "List runs", - "operationId": "getRuns", + "summary": "Create API key for a service account", + "operationId": "postServiceAccountsIDAPIKeys", "parameters": [ { "type": "string", - "description": "Comma-separated list of pipeline names", - "name": "pipelines", - "in": "query" - }, - { - "type": "string", - "description": "Comma-separated list of statuses", - "name": "statuses", - "in": "query" - }, - { - "type": "integer", - "default": 50, - "description": "Number of results per page", - "name": "limit", - "in": "query" + "description": "Service account ID", + "name": "id", + "in": "path", + "required": true }, { - "type": "integer", - "default": 0, - "description": "Number of results to skip", - "name": "offset", - "in": "query" + "description": "API key details", + "name": "key", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/CreateServiceAccountAPIKeyRequest" + } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "type": "object", - "properties": { - "limit": { - "type": "integer" - }, - "offset": { - "type": "integer" - }, - "pipelines": { - "type": "array", - "items": { - "type": "string" - } - }, - "runs": { - "type": "array", - "items": { - "$ref": "#/definitions/PluginRun" - } - }, - "total": { - "type": "integer" - } - } + "$ref": "#/definitions/ServiceAccountAPIKey" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } } }, - "/api/v1/runs/assets/batch": { - "post": { + "/api/v1/service-accounts/{id}/api-keys/{keyId}": { + "delete": { "security": [ { "ApiKeyAuth": [] @@ -8015,41 +7982,43 @@ "BearerAuth": [] } ], - "description": "Create/update assets within a run", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], + "description": "Delete an API key for a service account", "tags": [ - "runs" + "service_accounts" ], - "summary": "Batch create assets", - "operationId": "postRunsAssetsBatch", + "summary": "Delete an API key", + "operationId": "deleteServiceAccountsIDAPIKeysKeyID", "parameters": [ { - "description": "Batch create request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/BatchCreateRequest" - } + "type": "string", + "description": "Service account ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "API key ID", + "name": "keyId", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", "schema": { - "$ref": "#/definitions/BatchCreateResponse" + "$ref": "#/definitions/ErrorResponse" } } } } }, - "/api/v1/runs/cleanup": { - "post": { + "/api/v1/sso-providers": { + "get": { "security": [ { "ApiKeyAuth": [] @@ -8058,27 +8027,27 @@ "BearerAuth": [] } ], - "description": "Mark runs as failed if they've been running too long without updates", + "description": "Read-only view of SSO providers wired via server config. Editing is done in config.yaml.", + "produces": [ + "application/json" + ], "tags": [ - "runs" + "auth" ], - "summary": "Cleanup stale runs", - "operationId": "postRunsCleanup", + "summary": "List configured SSO providers (admin)", + "operationId": "getSsoProviders", "responses": { "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "integer" - } + "$ref": "#/definitions/SSOProvidersResponse" } } } } }, - "/api/v1/runs/complete": { - "post": { + "/api/v1/sso/team-mappings": { + "get": { "security": [ { "ApiKeyAuth": [] @@ -8087,7 +8056,7 @@ "BearerAuth": [] } ], - "description": "Complete a run with results", + "description": "Get a list of SSO group to team mappings", "consumes": [ "application/json" ], @@ -8095,35 +8064,33 @@ "application/json" ], "tags": [ - "runs" + "sso" ], - "summary": "Complete run", - "operationId": "postRunsComplete", + "summary": "List SSO team mappings", + "operationId": "getSsoTeamMappings", "parameters": [ { - "description": "Complete run request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/CompleteRunRequest" - } + "type": "string", + "description": "Filter by SSO provider", + "name": "provider", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/ListSSOMappingsResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } - } - }, - "/api/v1/runs/start": { + }, "post": { "security": [ { @@ -8133,7 +8100,7 @@ "BearerAuth": [] } ], - "description": "Start a new run for tracking", + "description": "Create a new SSO group to team mapping", "consumes": [ "application/json" ], @@ -8141,32 +8108,50 @@ "application/json" ], "tags": [ - "runs" + "sso" ], - "summary": "Start run", - "operationId": "postRunsStart", + "summary": "Create an SSO team mapping", + "operationId": "postSsoTeamMappings", "parameters": [ { - "description": "Start run request", - "name": "request", + "description": "SSO mapping creation request", + "name": "mapping", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/StartRunRequest" + "$ref": "#/definitions/CreateSSOMappingRequest" } } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/PluginRun" + "$ref": "#/definitions/SSOTeamMapping" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } } }, - "/api/v1/runs/{id}": { + "/api/v1/sso/team-mappings/{id}": { "get": { "security": [ { @@ -8176,19 +8161,22 @@ "BearerAuth": [] } ], - "description": "Get a specific run by ID", + "description": "Get an SSO team mapping by its ID", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "runs" + "sso" ], - "summary": "Get run", - "operationId": "getRunsID", + "summary": "Get an SSO team mapping", + "operationId": "getSsoTeamMappingsID", "parameters": [ { "type": "string", - "description": "Run ID", + "description": "SSO mapping ID", "name": "id", "in": "path", "required": true @@ -8198,14 +8186,24 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/PluginRun" + "$ref": "#/definitions/SSOTeamMapping" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } - } - }, - "/api/v1/runs/{id}/entities": { - "get": { + }, + "put": { "security": [ { "ApiKeyAuth": [] @@ -8214,62 +8212,64 @@ "BearerAuth": [] } ], - "description": "Get paginated list of entities for a specific run", + "description": "Update an SSO team mapping by its ID", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "runs" + "sso" ], - "summary": "Get run entities", - "operationId": "getRunsIDEntities", + "summary": "Update an SSO team mapping", + "operationId": "putSsoTeamMappingsID", "parameters": [ { "type": "string", - "description": "Run ID", + "description": "SSO mapping ID", "name": "id", "in": "path", "required": true }, { - "type": "string", - "description": "Filter by entity type (asset, lineage, documentation)", - "name": "entity_type", - "in": "query" - }, - { - "type": "string", - "description": "Filter by status (created, updated, deleted, failed)", - "name": "status", - "in": "query" - }, - { - "type": "integer", - "default": 100, - "description": "Number of results per page", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "default": 0, - "description": "Number of results to skip", - "name": "offset", - "in": "query" + "description": "SSO mapping update request", + "name": "mapping", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/UpdateSSOMappingRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/RunEntitiesResponse" + "$ref": "#/definitions/MessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } - } - }, - "/api/v1/search": { - "get": { + }, + "delete": { "security": [ { "ApiKeyAuth": [] @@ -8278,57 +8278,36 @@ "BearerAuth": [] } ], - "description": "Search across assets, glossary terms, teams, and users", + "description": "Delete an SSO team mapping by its ID", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "search" + "sso" ], - "summary": "Unified search", - "operationId": "getSearch", + "summary": "Delete an SSO team mapping", + "operationId": "deleteSsoTeamMappingsID", "parameters": [ { "type": "string", - "description": "Search query", - "name": "q", - "in": "query", + "description": "SSO mapping ID", + "name": "id", + "in": "path", "required": true - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "Filter by result types (asset, glossary, team, user)", - "name": "types", - "in": "query" - }, - { - "type": "integer", - "default": 20, - "description": "Limit", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "default": 0, - "description": "Offset", - "name": "offset", - "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/SearchResponse" + "$ref": "#/definitions/MessageResponse" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -8342,7 +8321,7 @@ } } }, - "/api/v1/service-accounts": { + "/api/v1/teams": { "get": { "security": [ { @@ -8352,23 +8331,39 @@ "BearerAuth": [] } ], - "description": "Get all service accounts", + "description": "Get a paginated list of teams", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "service_accounts" + "teams" + ], + "summary": "List teams", + "operationId": "getTeams", + "parameters": [ + { + "type": "integer", + "default": 50, + "description": "Number of items to return", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "default": 0, + "description": "Number of items to skip", + "name": "offset", + "in": "query" + } ], - "summary": "List service accounts", - "operationId": "getServiceAccounts", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/ServiceAccount" - } + "$ref": "#/definitions/ListTeamsResponse" } }, "500": { @@ -8388,7 +8383,7 @@ "BearerAuth": [] } ], - "description": "Create a new service account", + "description": "Create a new team", "consumes": [ "application/json" ], @@ -8396,18 +8391,18 @@ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Create service account", - "operationId": "postServiceAccounts", + "summary": "Create a team", + "operationId": "postTeams", "parameters": [ { - "description": "Service account", - "name": "account", + "description": "Team creation request", + "name": "team", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateServiceAccountRequest" + "$ref": "#/definitions/CreateTeamRequest" } } ], @@ -8415,7 +8410,7 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/ServiceAccount" + "$ref": "#/definitions/Team" } }, "400": { @@ -8423,11 +8418,23 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } } }, - "/api/v1/service-accounts/{id}": { + "/api/v1/teams/{id}": { "get": { "security": [ { @@ -8437,19 +8444,22 @@ "BearerAuth": [] } ], - "description": "Get a service account by ID", + "description": "Get a team by its ID", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Get service account", - "operationId": "getServiceAccountsID", + "summary": "Get a team", + "operationId": "getTeamsID", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true @@ -8459,7 +8469,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ServiceAccount" + "$ref": "#/definitions/Team" } }, "404": { @@ -8467,10 +8477,16 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } }, - "delete": { + "put": { "security": [ { "ApiKeyAuth": [] @@ -8479,34 +8495,76 @@ "BearerAuth": [] } ], - "description": "Soft-delete a service account", + "description": "Update a team's fields by its ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Delete service account", - "operationId": "deleteServiceAccountsID", + "summary": "Update a team", + "operationId": "putTeamsID", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true - } - ], - "responses": { - "204": { - "description": "No Content" }, - "404": { - "description": "Not Found", + { + "description": "Team update request", + "name": "team", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/UpdateTeamRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/MessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } }, - "patch": { + "delete": { "security": [ { "ApiKeyAuth": [] @@ -8515,7 +8573,7 @@ "BearerAuth": [] } ], - "description": "Update a service account", + "description": "Delete a team by its ID", "consumes": [ "application/json" ], @@ -8523,33 +8581,30 @@ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Update service account", - "operationId": "patchServiceAccountsID", + "summary": "Delete a team", + "operationId": "deleteTeamsID", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true - }, - { - "description": "Update fields", - "name": "account", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UpdateServiceAccountRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ServiceAccount" + "$ref": "#/definitions/MessageResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" } }, "404": { @@ -8557,11 +8612,17 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } } }, - "/api/v1/service-accounts/{id}/api-keys": { + "/api/v1/teams/{id}/members": { "get": { "security": [ { @@ -8571,19 +8632,22 @@ "BearerAuth": [] } ], - "description": "Get all API keys for a service account", + "description": "Get the members of a team", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "List API keys for a service account", - "operationId": "getServiceAccountsIDAPIKeys", + "summary": "List team members", + "operationId": "getTeamsIDMembers", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true @@ -8593,10 +8657,13 @@ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/ServiceAccountAPIKey" - } + "$ref": "#/definitions/ListMembersResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" } } } @@ -8610,7 +8677,7 @@ "BearerAuth": [] } ], - "description": "Create a new API key. The plaintext key is only returned once.", + "description": "Add a user as a member of a team", "consumes": [ "application/json" ], @@ -8618,25 +8685,25 @@ "application/json" ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Create API key for a service account", - "operationId": "postServiceAccountsIDAPIKeys", + "summary": "Add a team member", + "operationId": "postTeamsIDMembers", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true }, { - "description": "API key details", - "name": "key", + "description": "Member addition request", + "name": "member", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateServiceAccountAPIKeyRequest" + "$ref": "#/definitions/AddMemberRequest" } } ], @@ -8644,7 +8711,7 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/ServiceAccountAPIKey" + "$ref": "#/definitions/MessageResponse" } }, "400": { @@ -8652,11 +8719,29 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "Conflict", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } } } } }, - "/api/v1/service-accounts/{id}/api-keys/{keyId}": { + "/api/v1/teams/{id}/members/{userId}": { "delete": { "security": [ { @@ -8666,72 +8751,58 @@ "BearerAuth": [] } ], - "description": "Delete an API key for a service account", + "description": "Remove a user from a team", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], "tags": [ - "service_accounts" + "teams" ], - "summary": "Delete an API key", - "operationId": "deleteServiceAccountsIDAPIKeysKeyID", + "summary": "Remove a team member", + "operationId": "deleteTeamsIDMembersUserID", "parameters": [ { "type": "string", - "description": "Service account ID", + "description": "Team ID", "name": "id", "in": "path", "required": true }, { "type": "string", - "description": "API key ID", - "name": "keyId", + "description": "User ID", + "name": "userId", "in": "path", "required": true } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/MessageResponse" + } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/sso-providers": { - "get": { - "security": [ - { - "ApiKeyAuth": [] }, - { - "BearerAuth": [] - } - ], - "description": "Read-only view of SSO providers wired via server config. Editing is done in config.yaml.", - "produces": [ - "application/json" - ], - "tags": [ - "auth" - ], - "summary": "List configured SSO providers (admin)", - "operationId": "getSsoProviders", - "responses": { - "200": { - "description": "OK", + "500": { + "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/SSOProvidersResponse" + "$ref": "#/definitions/ErrorResponse" } } } } }, - "/api/v1/sso/team-mappings": { - "get": { + "/api/v1/teams/{id}/members/{userId}/convert-to-manual": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -8740,7 +8811,7 @@ "BearerAuth": [] } ], - "description": "Get a list of SSO group to team mappings", + "description": "Convert an SSO-managed team member to a manually managed member", "consumes": [ "application/json" ], @@ -8748,23 +8819,37 @@ "application/json" ], "tags": [ - "sso" + "teams" ], - "summary": "List SSO team mappings", - "operationId": "getSsoTeamMappings", + "summary": "Convert member to manual", + "operationId": "postTeamsIDMembersUserIDConvertToManual", "parameters": [ { "type": "string", - "description": "Filter by SSO provider", - "name": "provider", - "in": "query" + "description": "Team ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "User ID", + "name": "userId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ListSSOMappingsResponse" + "$ref": "#/definitions/MessageResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" } }, "500": { @@ -8774,8 +8859,10 @@ } } } - }, - "post": { + } + }, + "/api/v1/teams/{id}/members/{userId}/role": { + "put": { "security": [ { "ApiKeyAuth": [] @@ -8784,7 +8871,7 @@ "BearerAuth": [] } ], - "description": "Create a new SSO group to team mapping", + "description": "Update the role of a team member", "consumes": [ "application/json" ], @@ -8792,137 +8879,32 @@ "application/json" ], "tags": [ - "sso" + "teams" ], - "summary": "Create an SSO team mapping", - "operationId": "postSsoTeamMappings", - "parameters": [ - { - "description": "SSO mapping creation request", - "name": "mapping", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/CreateSSOMappingRequest" - } - } - ], - "responses": { - "201": { - "description": "Created", - "schema": { - "$ref": "#/definitions/SSOTeamMapping" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/api/v1/sso/team-mappings/{id}": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Get an SSO team mapping by its ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "sso" - ], - "summary": "Get an SSO team mapping", - "operationId": "getSsoTeamMappingsID", + "summary": "Update member role", + "operationId": "putTeamsIDMembersUserIDRole", "parameters": [ { "type": "string", - "description": "SSO mapping ID", + "description": "Team ID", "name": "id", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/SSOTeamMapping" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - }, - "put": { - "security": [ - { - "ApiKeyAuth": [] }, - { - "BearerAuth": [] - } - ], - "description": "Update an SSO team mapping by its ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "sso" - ], - "summary": "Update an SSO team mapping", - "operationId": "putSsoTeamMappingsID", - "parameters": [ { "type": "string", - "description": "SSO mapping ID", - "name": "id", + "description": "User ID", + "name": "userId", "in": "path", "required": true }, { - "description": "SSO mapping update request", - "name": "mapping", + "description": "Role update request", + "name": "role", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/UpdateSSOMappingRequest" + "$ref": "#/definitions/UpdateMemberRoleRequest" } } ], @@ -8952,60 +8934,30 @@ } } } - }, - "delete": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Delete an SSO team mapping by its ID", - "consumes": [ - "application/json" - ], + } + }, + "/api/v1/ui/config": { + "get": { + "description": "Get UI configuration including banner settings", "produces": [ "application/json" ], "tags": [ - "sso" - ], - "summary": "Delete an SSO team mapping", - "operationId": "deleteSsoTeamMappingsID", - "parameters": [ - { - "type": "string", - "description": "SSO mapping ID", - "name": "id", - "in": "path", - "required": true - } + "ui" ], + "summary": "Get UI configuration", + "operationId": "getUIConfig", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/UIConfigResponse" } } } } }, - "/api/v1/teams": { + "/api/v1/users": { "get": { "security": [ { @@ -9015,7 +8967,7 @@ "BearerAuth": [] } ], - "description": "Get a paginated list of teams", + "description": "Get a list of users with optional filtering", "consumes": [ "application/json" ], @@ -9023,10 +8975,10 @@ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "List teams", - "operationId": "getTeams", + "summary": "List users", + "operationId": "getUsers", "parameters": [ { "type": "integer", @@ -9041,13 +8993,35 @@ "description": "Number of items to skip", "name": "offset", "in": "query" + }, + { + "type": "string", + "description": "Search query for username or email", + "name": "query", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "Filter by role IDs", + "name": "role_ids", + "in": "query" + }, + { + "type": "boolean", + "description": "Filter by active status", + "name": "active", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ListTeamsResponse" + "$ref": "#/definitions/ListUsersResponse" } }, "500": { @@ -9067,7 +9041,7 @@ "BearerAuth": [] } ], - "description": "Create a new team", + "description": "Create a new user in the system", "consumes": [ "application/json" ], @@ -9075,32 +9049,32 @@ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Create a team", - "operationId": "postTeams", + "summary": "Create a new user", + "operationId": "postUsers", "parameters": [ { - "description": "Team creation request", - "name": "team", + "description": "User creation request", + "name": "user", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateTeamRequest" + "$ref": "#/definitions/CreateUserInput" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/Team" + "$ref": "#/definitions/User" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/ValidationErrorResponse" } }, "409": { @@ -9108,17 +9082,11 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/teams/{id}": { + "/api/v1/users/apikeys": { "get": { "security": [ { @@ -9128,7 +9096,7 @@ "BearerAuth": [] } ], - "description": "Get a team by its ID", + "description": "Get all API keys for a user", "consumes": [ "application/json" ], @@ -9136,30 +9104,18 @@ "application/json" ], "tags": [ - "teams" - ], - "summary": "Get a team", - "operationId": "getTeamsID", - "parameters": [ - { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - } + "users" ], + "summary": "List API keys", + "operationId": "getUsersApikeys", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/Team" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "type": "array", + "items": { + "$ref": "#/definitions/APIKey" + } } }, "500": { @@ -9170,7 +9126,7 @@ } } }, - "put": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -9179,7 +9135,7 @@ "BearerAuth": [] } ], - "description": "Update a team's fields by its ID", + "description": "Create a new API key for a user", "consumes": [ "application/json" ], @@ -9187,25 +9143,18 @@ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Update a team", - "operationId": "putTeamsID", + "summary": "Create API key", + "operationId": "postUsersApikeys", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Team update request", - "name": "team", + "description": "API key creation request", + "name": "key", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/UpdateTeamRequest" + "$ref": "#/definitions/CreateAPIKeyRequest" } } ], @@ -9213,7 +9162,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" + "$ref": "#/definitions/APIKey" } }, "400": { @@ -9221,33 +9170,11 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } - }, + } + }, + "/api/v1/users/apikeys/{id}": { "delete": { "security": [ { @@ -9257,7 +9184,7 @@ "BearerAuth": [] } ], - "description": "Delete a team by its ID", + "description": "Delete an API key", "consumes": [ "application/json" ], @@ -9265,28 +9192,25 @@ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Delete a team", - "operationId": "deleteTeamsID", + "summary": "Delete API key", + "operationId": "deleteUsersApikeysID", "parameters": [ { "type": "string", - "description": "Team ID", + "description": "API key ID", "name": "id", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/MessageResponse" - } + "204": { + "description": "No Content" }, - "403": { - "description": "Forbidden", + "400": { + "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9296,27 +9220,17 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/teams/{id}/members": { - "get": { + "/api/v1/users/change-password": { + "post": { "security": [ - { - "ApiKeyAuth": [] - }, { "BearerAuth": [] } ], - "description": "Get the members of a team", "consumes": [ "application/json" ], @@ -9324,44 +9238,40 @@ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "List team members", - "operationId": "getTeamsIDMembers", + "summary": "Change the current local user's password", + "operationId": "changeOwnPassword", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true + "description": "Current and new password", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_users.ChangePasswordRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ListMembersResponse" + "$ref": "#/definitions/TokenResponse" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, + } + }, + "/api/v1/users/login": { "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Add a user as a member of a team", + "description": "Authenticate a user with username/email and password", "consumes": [ "application/json" ], @@ -9369,33 +9279,26 @@ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Add a team member", - "operationId": "postTeamsIDMembers", + "summary": "Login user", + "operationId": "postUsersLogin", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Member addition request", - "name": "member", + "description": "Login credentials", + "name": "credentials", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/AddMemberRequest" + "$ref": "#/definitions/LoginRequest" } } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" + "$ref": "#/definitions/TokenResponse" } }, "400": { @@ -9404,20 +9307,8 @@ "$ref": "#/definitions/ErrorResponse" } }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9425,17 +9316,8 @@ } } }, - "/api/v1/teams/{id}/members/{userId}": { - "delete": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Remove a user from a team", + "/api/v1/users/login/password": { + "post": { "consumes": [ "application/json" ], @@ -9443,41 +9325,54 @@ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Remove a team member", - "operationId": "deleteTeamsIDMembersUserID", + "summary": "Change a mandatory password before the second factor", + "operationId": "changeLoginPassword", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true + "description": "Verification request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_users.TOTPRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" + "$ref": "#/definitions/TokenResponse" } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "429": { + "description": "Too Many Requests", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "503": { + "description": "Service Unavailable", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9485,17 +9380,8 @@ } } }, - "/api/v1/teams/{id}/members/{userId}/convert-to-manual": { + "/api/v1/users/login/totp": { "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Convert an SSO-managed team member to a manually managed member", "consumes": [ "application/json" ], @@ -9503,116 +9389,54 @@ "application/json" ], "tags": [ - "teams" + "users" ], - "summary": "Convert member to manual", - "operationId": "postTeamsIDMembersUserIDConvertToManual", + "summary": "Complete local login using a second factor", + "operationId": "verifyTOTPLogin", "parameters": [ { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true + "description": "Verification request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_users.TOTPRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/MessageResponse" + "$ref": "#/definitions/TokenResponse" } }, - "404": { - "description": "Not Found", + "400": { + "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/teams/{id}/members/{userId}/role": { - "put": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Update the role of a team member", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "teams" - ], - "summary": "Update member role", - "operationId": "putTeamsIDMembersUserIDRole", - "parameters": [ - { - "type": "string", - "description": "Team ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "User ID", - "name": "userId", - "in": "path", - "required": true - }, - { - "description": "Role update request", - "name": "role", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UpdateMemberRoleRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/MessageResponse" - } }, - "400": { - "description": "Bad Request", + "403": { + "description": "Forbidden", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "404": { - "description": "Not Found", + "429": { + "description": "Too Many Requests", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "500": { - "description": "Internal Server Error", + "503": { + "description": "Service Unavailable", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9620,38 +9444,8 @@ } } }, - "/api/v1/ui/config": { - "get": { - "description": "Get UI configuration including banner settings", - "produces": [ - "application/json" - ], - "tags": [ - "ui" - ], - "summary": "Get UI configuration", - "operationId": "getUIConfig", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/UIConfigResponse" - } - } - } - } - }, - "/api/v1/users": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Get a list of users with optional filtering", + "/api/v1/users/login/totp/confirm": { + "post": { "consumes": [ "application/json" ], @@ -9661,71 +9455,37 @@ "tags": [ "users" ], - "summary": "List users", - "operationId": "getUsers", + "summary": "Confirm required TOTP enrollment and return recovery codes once", + "operationId": "confirmRequiredTOTP", "parameters": [ { - "type": "integer", - "default": 50, - "description": "Number of items to return", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "default": 0, - "description": "Number of items to skip", - "name": "offset", - "in": "query" - }, - { - "type": "string", - "description": "Search query for username or email", - "name": "query", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "Filter by role IDs", - "name": "role_ids", - "in": "query" - }, - { - "type": "boolean", - "description": "Filter by active status", - "name": "active", - "in": "query" + "description": "Enrollment challenge and code", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1_users.TOTPRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ListUsersResponse" + "$ref": "#/definitions/v1_users.RecoveryResponse" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, + } + }, + "/api/v1/users/login/totp/setup": { "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Create a new user in the system", "consumes": [ "application/json" ], @@ -9735,16 +9495,16 @@ "tags": [ "users" ], - "summary": "Create a new user", - "operationId": "postUsers", + "summary": "Prepare required TOTP enrollment after password login", + "operationId": "setupRequiredTOTP", "parameters": [ { - "description": "User creation request", - "name": "user", + "description": "Enrollment challenge", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateUserInput" + "$ref": "#/definitions/v1_users.TOTPRequest" } } ], @@ -9752,17 +9512,11 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/User" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ValidationErrorResponse" + "$ref": "#/definitions/mfa.SetupResult" } }, - "409": { - "description": "Conflict", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9770,7 +9524,7 @@ } } }, - "/api/v1/users/apikeys": { + "/api/v1/users/me": { "get": { "security": [ { @@ -9780,7 +9534,7 @@ "BearerAuth": [] } ], - "description": "Get all API keys for a user", + "description": "Get detailed information about the currently authenticated user", "consumes": [ "application/json" ], @@ -9790,26 +9544,25 @@ "tags": [ "users" ], - "summary": "List API keys", - "operationId": "getUsersApikeys", + "summary": "Get current user profile", + "operationId": "getUsersMe", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/APIKey" - } + "$ref": "#/definitions/User" } }, - "500": { - "description": "Internal Server Error", + "401": { + "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, + } + }, + "/api/v1/users/oauth/link": { "post": { "security": [ { @@ -9819,7 +9572,7 @@ "BearerAuth": [] } ], - "description": "Create a new API key for a user", + "description": "Link an OAuth account to an existing user", "consumes": [ "application/json" ], @@ -9829,25 +9582,22 @@ "tags": [ "users" ], - "summary": "Create API key", - "operationId": "postUsersApikeys", + "summary": "Link OAuth account", + "operationId": "postUsersOauthLink", "parameters": [ { - "description": "API key creation request", - "name": "key", + "description": "OAuth account link request", + "name": "link", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/CreateAPIKeyRequest" + "$ref": "#/definitions/OAuthLinkRequest" } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/APIKey" - } + "description": "OK" }, "400": { "description": "Bad Request", @@ -9858,7 +9608,7 @@ } } }, - "/api/v1/users/apikeys/{id}": { + "/api/v1/users/oauth/unlink/{id}/{provider}": { "delete": { "security": [ { @@ -9868,7 +9618,7 @@ "BearerAuth": [] } ], - "description": "Delete an API key", + "description": "Unlink an OAuth account from a user", "consumes": [ "application/json" ], @@ -9878,15 +9628,22 @@ "tags": [ "users" ], - "summary": "Delete API key", - "operationId": "deleteUsersApikeysID", + "summary": "Unlink OAuth account", + "operationId": "deleteUsersOauthUnlinkIDProvider", "parameters": [ { "type": "string", - "description": "API key ID", + "description": "User ID", "name": "id", "in": "path", "required": true + }, + { + "type": "string", + "description": "OAuth provider", + "name": "provider", + "in": "path", + "required": true } ], "responses": { @@ -9898,54 +9655,40 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/users/change-password": { + "/api/v1/users/password/require-change/{id}": { "post": { "security": [ { "BearerAuth": [] } ], - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "Change the current local user's password", - "operationId": "changeOwnPassword", + "summary": "Require a local user to change their password at next login", + "operationId": "requirePasswordChange", "parameters": [ { - "description": "Current and new password", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/v1_users.ChangePasswordRequest" - } + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/TokenResponse" - } + "204": { + "description": "No Content" }, - "401": { - "description": "Unauthorized", + "403": { + "description": "Forbidden", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -9953,9 +9696,17 @@ } } }, - "/api/v1/users/login": { - "post": { - "description": "Authenticate a user with username/email and password", + "/api/v1/users/preferences": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BearerAuth": [] + } + ], + "description": "Update preferences for the current user", "consumes": [ "application/json" ], @@ -9965,70 +9716,100 @@ "tags": [ "users" ], - "summary": "Login user", - "operationId": "postUsersLogin", + "summary": "Update user preferences", + "operationId": "putUsersPreferences", "parameters": [ { - "description": "Login credentials", - "name": "credentials", + "description": "User preferences", + "name": "preferences", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/LoginRequest" + "type": "object", + "additionalProperties": true } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/TokenResponse" - } + "description": "OK" }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/users/login/password": { + "/api/v1/users/sign-out-all/{id}": { "post": { - "consumes": [ - "application/json" + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BearerAuth": [] + } ], + "description": "Rejects every token issued to the user before now. Their password and API keys are untouched, so this is the response to a leaked or overexposed token rather than a lost credential.", "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "Change a mandatory password before the second factor", - "operationId": "changeLoginPassword", + "summary": "Sign a user out of all sessions", + "operationId": "postUsersIDSignOutAll", "parameters": [ { - "description": "Verification request", - "name": "request", - "in": "body", - "required": true, + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" + "$ref": "#/definitions/ErrorResponse" } } + } + } + }, + "/api/v1/users/totp": { + "get": { + "security": [ + { + "BearerAuth": [] + }, + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" ], + "tags": [ + "users" + ], + "summary": "Get local two-factor status", + "operationId": "totpStatus", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/TokenResponse" + "$ref": "#/definitions/mfa.Status" } }, "400": { @@ -10062,10 +9843,13 @@ } } } - } - }, - "/api/v1/users/login/totp": { - "post": { + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], "consumes": [ "application/json" ], @@ -10075,8 +9859,8 @@ "tags": [ "users" ], - "summary": "Complete local login using a second factor", - "operationId": "verifyTOTPLogin", + "summary": "Disable TOTP with password and second factor", + "operationId": "disableTOTP", "parameters": [ { "description": "Verification request", @@ -10092,7 +9876,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/TokenResponse" + "$ref": "#/definitions/v1_users.RecoveryResponse" } }, "400": { @@ -10128,8 +9912,13 @@ } } }, - "/api/v1/users/login/totp/confirm": { + "/api/v1/users/totp/confirm": { "post": { + "security": [ + { + "BearerAuth": [] + } + ], "consumes": [ "application/json" ], @@ -10139,11 +9928,11 @@ "tags": [ "users" ], - "summary": "Confirm required TOTP enrollment and return recovery codes once", - "operationId": "confirmRequiredTOTP", + "summary": "Confirm TOTP and return recovery codes once", + "operationId": "confirmTOTP", "parameters": [ { - "description": "Enrollment challenge and code", + "description": "Verification request", "name": "request", "in": "body", "required": true, @@ -10159,48 +9948,32 @@ "$ref": "#/definitions/v1_users.RecoveryResponse" } }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "401": { "description": "Unauthorized", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/users/login/totp/setup": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Prepare required TOTP enrollment after password login", - "operationId": "setupRequiredTOTP", - "parameters": [ - { - "description": "Enrollment challenge", - "name": "request", - "in": "body", - "required": true, + }, + "403": { + "description": "Forbidden", "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" + "$ref": "#/definitions/ErrorResponse" } - } - ], - "responses": { - "200": { - "description": "OK", + }, + "429": { + "description": "Too Many Requests", "schema": { - "$ref": "#/definitions/mfa.SetupResult" + "$ref": "#/definitions/ErrorResponse" } }, - "401": { - "description": "Unauthorized", + "503": { + "description": "Service Unavailable", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10208,55 +9981,44 @@ } } }, - "/api/v1/users/me": { + "/api/v1/users/totp/enrolled": { "get": { "security": [ - { - "ApiKeyAuth": [] - }, { "BearerAuth": [] } ], - "description": "Get detailed information about the currently authenticated user", - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "Get current user profile", - "operationId": "getUsersMe", + "summary": "List users with an enrolled second factor", + "operationId": "listTOTPEnrollment", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/User" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } } } } } }, - "/api/v1/users/oauth/link": { + "/api/v1/users/totp/recovery": { "post": { "security": [ - { - "ApiKeyAuth": [] - }, { "BearerAuth": [] } ], - "description": "Link an OAuth account to an existing user", "consumes": [ "application/json" ], @@ -10266,160 +10028,52 @@ "tags": [ "users" ], - "summary": "Link OAuth account", - "operationId": "postUsersOauthLink", + "summary": "Replace one-use recovery codes", + "operationId": "regenerateRecovery", "parameters": [ { - "description": "OAuth account link request", - "name": "link", + "description": "Verification request", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/OAuthLinkRequest" + "$ref": "#/definitions/v1_users.TOTPRequest" } } ], "responses": { "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request", + "description": "OK", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/v1_users.RecoveryResponse" } - } - } - } - }, - "/api/v1/users/oauth/unlink/{id}/{provider}": { - "delete": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Unlink an OAuth account from a user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Unlink OAuth account", - "operationId": "deleteUsersOauthUnlinkIDProvider", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "OAuth provider", - "name": "provider", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/users/password/require-change/{id}": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Require a local user to change their password at next login", - "operationId": "requirePasswordChange", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } }, "403": { "description": "Forbidden", "schema": { "$ref": "#/definitions/ErrorResponse" } - } - } - } - }, - "/api/v1/users/preferences": { - "put": { - "security": [ - { - "ApiKeyAuth": [] }, - { - "BearerAuth": [] - } - ], - "description": "Update preferences for the current user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Update user preferences", - "operationId": "putUsersPreferences", - "parameters": [ - { - "description": "User preferences", - "name": "preferences", - "in": "body", - "required": true, + "429": { + "description": "Too Many Requests", "schema": { - "type": "object", - "additionalProperties": true + "$ref": "#/definitions/ErrorResponse" } - } - ], - "responses": { - "200": { - "description": "OK" }, - "400": { - "description": "Bad Request", + "503": { + "description": "Service Unavailable", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10427,25 +10081,24 @@ } } }, - "/api/v1/users/sign-out-all/{id}": { - "post": { + "/api/v1/users/totp/reset/{id}": { + "delete": { "security": [ - { - "ApiKeyAuth": [] - }, { "BearerAuth": [] } ], - "description": "Rejects every token issued to the user before now. Their password and API keys are untouched, so this is the response to a leaked or overexposed token rather than a lost credential.", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "Sign a user out of all sessions", - "operationId": "postUsersIDSignOutAll", + "summary": "Administratively reset a local second factor", + "operationId": "resetTOTP", "parameters": [ { "type": "string", @@ -10459,43 +10112,6 @@ "204": { "description": "No Content" }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/api/v1/users/totp": { - "get": { - "security": [ - { - "BearerAuth": [] - }, - { - "ApiKeyAuth": [] - } - ], - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Get local two-factor status", - "operationId": "totpStatus", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/mfa.Status" - } - }, "400": { "description": "Bad Request", "schema": { @@ -10527,8 +10143,10 @@ } } } - }, - "delete": { + } + }, + "/api/v1/users/totp/setup": { + "post": { "security": [ { "BearerAuth": [] @@ -10543,8 +10161,8 @@ "tags": [ "users" ], - "summary": "Disable TOTP with password and second factor", - "operationId": "disableTOTP", + "summary": "Prepare an encrypted TOTP enrollment", + "operationId": "setupTOTP", "parameters": [ { "description": "Verification request", @@ -10560,7 +10178,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1_users.RecoveryResponse" + "$ref": "#/definitions/mfa.SetupResult" } }, "400": { @@ -10596,13 +10214,14 @@ } } }, - "/api/v1/users/totp/confirm": { + "/api/v1/users/update-password": { "post": { "security": [ { "BearerAuth": [] } ], + "description": "Update current user's password", "consumes": [ "application/json" ], @@ -10612,16 +10231,16 @@ "tags": [ "users" ], - "summary": "Confirm TOTP and return recovery codes once", - "operationId": "confirmTOTP", + "summary": "Update user password", + "operationId": "postUsersUpdatePassword", "parameters": [ { - "description": "Verification request", + "description": "Password update request", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" + "$ref": "#/definitions/UpdatePasswordRequest" } } ], @@ -10629,7 +10248,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1_users.RecoveryResponse" + "$ref": "#/definitions/TokenResponse" } }, "400": { @@ -10643,66 +10262,72 @@ "schema": { "$ref": "#/definitions/ErrorResponse" } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "429": { - "description": "Too Many Requests", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "503": { - "description": "Service Unavailable", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } } } } }, - "/api/v1/users/totp/enrolled": { + "/api/v1/users/{id}": { "get": { "security": [ + { + "ApiKeyAuth": [] + }, { "BearerAuth": [] } ], + "description": "Get detailed information about a specific user", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ "users" ], - "summary": "List users with an enrolled second factor", - "operationId": "listTOTPEnrollment", + "summary": "Get a user by ID", + "operationId": "getUsersID", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", "schema": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } + "$ref": "#/definitions/User" } - } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } } - } - }, - "/api/v1/users/totp/recovery": { - "post": { + }, + "put": { "security": [ + { + "ApiKeyAuth": [] + }, { "BearerAuth": [] } ], + "description": "Update user information", "consumes": [ "application/json" ], @@ -10712,16 +10337,23 @@ "tags": [ "users" ], - "summary": "Replace one-use recovery codes", - "operationId": "regenerateRecovery", + "summary": "Update a user", + "operationId": "putUsersID", "parameters": [ { - "description": "Verification request", - "name": "request", + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "User update request", + "name": "user", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" + "$ref": "#/definitions/UpdateUserInput" } } ], @@ -10729,49 +10361,39 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/v1_users.RecoveryResponse" + "$ref": "#/definitions/User" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/ValidationErrorResponse" } }, - "429": { - "description": "Too Many Requests", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "503": { - "description": "Service Unavailable", + "409": { + "description": "Conflict", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - } - }, - "/api/v1/users/totp/reset/{id}": { + }, "delete": { "security": [ + { + "ApiKeyAuth": [] + }, { "BearerAuth": [] } ], + "description": "Delete a user from the system", "consumes": [ "application/json" ], @@ -10781,8 +10403,8 @@ "tags": [ "users" ], - "summary": "Administratively reset a local second factor", - "operationId": "resetTOTP", + "summary": "Delete a user", + "operationId": "deleteUsersID", "parameters": [ { "type": "string", @@ -10796,32 +10418,20 @@ "204": { "description": "No Content" }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "429": { - "description": "Too Many Requests", + "409": { + "description": "Conflict", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "503": { - "description": "Service Unavailable", + "500": { + "description": "Internal Server Error", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10829,40 +10439,66 @@ } } }, - "/api/v1/users/totp/setup": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "consumes": [ + "/auth-providers": { + "get": { + "description": "Returns the enabled auth providers without sensitive data", + "produces": [ "application/json" ], + "tags": [ + "auth" + ], + "summary": "Get auth configuration", + "operationId": "getAuthProviders", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/AuthConfig" + } + } + } + } + }, + "/auth/{provider}/callback": { + "get": { + "description": "Processes the OAuth callback from any provider", "produces": [ "application/json" ], "tags": [ - "users" + "auth" ], - "summary": "Prepare an encrypted TOTP enrollment", - "operationId": "setupTOTP", + "summary": "Handle OAuth callback", + "operationId": "getAuthProviderCallback", "parameters": [ { - "description": "Verification request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/v1_users.TOTPRequest" - } + "type": "string", + "description": "OAuth provider (okta, google, github, etc.)", + "name": "provider", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Authorization code", + "name": "code", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "State parameter for CSRF protection", + "name": "state", + "in": "query", + "required": true } ], "responses": { - "200": { - "description": "OK", + "307": { + "description": "Temporary Redirect", "schema": { - "$ref": "#/definitions/mfa.SetupResult" + "type": "string" } }, "400": { @@ -10871,26 +10507,14 @@ "$ref": "#/definitions/ErrorResponse" } }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "429": { - "description": "Too Many Requests", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "503": { - "description": "Service Unavailable", + "500": { + "description": "Internal Server Error", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10898,51 +10522,41 @@ } } }, - "/api/v1/users/update-password": { - "post": { - "security": [ - { - "BearerAuth": [] - } - ], - "description": "Update current user's password", - "consumes": [ - "application/json" - ], + "/auth/{provider}/login": { + "get": { + "description": "Redirects the user to the OAuth provider for authentication", "produces": [ "application/json" ], "tags": [ - "users" + "auth" ], - "summary": "Update user password", - "operationId": "postUsersUpdatePassword", + "summary": "Initiate OAuth login", + "operationId": "getAuthProviderLogin", "parameters": [ { - "description": "Password update request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UpdatePasswordRequest" - } + "type": "string", + "description": "OAuth provider (okta, google, github, etc.)", + "name": "provider", + "in": "path", + "required": true } ], "responses": { - "200": { - "description": "OK", + "307": { + "description": "Temporary Redirect", "schema": { - "$ref": "#/definitions/TokenResponse" + "type": "string" } }, - "400": { - "description": "Bad Request", + "404": { + "description": "Not Found", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "401": { - "description": "Unauthorized", + "500": { + "description": "Internal Server Error", "schema": { "$ref": "#/definitions/ErrorResponse" } @@ -10950,7 +10564,7 @@ } } }, - "/api/v1/users/{id}": { + "/glossary/export": { "get": { "security": [ { @@ -10960,115 +10574,47 @@ "BearerAuth": [] } ], - "description": "Get detailed information about a specific user", - "consumes": [ - "application/json" - ], + "description": "Every term in the import template's columns, so the file can be edited and imported back with on_existing=update. Cells that a spreadsheet would run as formulas are escaped in CSV.", "produces": [ - "application/json" + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "text/csv" ], "tags": [ - "users" + "glossary" ], - "summary": "Get a user by ID", - "operationId": "getUsersID", + "summary": "Export the glossary", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/User" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - }, - "put": { - "security": [ - { - "ApiKeyAuth": [] + "description": "xlsx (default) or csv", + "name": "format", + "in": "query" }, - { - "BearerAuth": [] - } - ], - "description": "Update user information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Update a user", - "operationId": "putUsersID", - "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "User update request", - "name": "user", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/UpdateUserInput" - } + "description": "Language for labels and help", + "name": "locale", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/User" + "type": "file" } }, "400": { "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ValidationErrorResponse" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", "schema": { "$ref": "#/definitions/ErrorResponse" } } } - }, - "delete": { + } + }, + "/glossary/import": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -11077,112 +10623,43 @@ "BearerAuth": [] } ], - "description": "Delete a user from the system", + "description": "Reads an XLSX or CSV in the template's shape and checks every row. mode=validate (default) writes nothing; mode=apply writes all rows or none, and only when no row has errors. Rows whose name matches a term are skipped unless on_existing=update; on update, empty cells keep the current value.", "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "users" - ], - "summary": "Delete a user", - "operationId": "deleteUsersID", - "parameters": [ - { - "type": "string", - "description": "User ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "409": { - "description": "Conflict", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/auth-providers": { - "get": { - "description": "Returns the enabled auth providers without sensitive data", - "produces": [ - "application/json" - ], - "tags": [ - "auth" + "multipart/form-data" ], - "summary": "Get auth configuration", - "operationId": "getAuthProviders", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/AuthConfig" - } - } - } - } - }, - "/auth/{provider}/callback": { - "get": { - "description": "Processes the OAuth callback from any provider", "produces": [ "application/json" ], "tags": [ - "auth" + "glossary" ], - "summary": "Handle OAuth callback", - "operationId": "getAuthProviderCallback", + "summary": "Import glossary terms from a file", "parameters": [ { - "type": "string", - "description": "OAuth provider (okta, google, github, etc.)", - "name": "provider", - "in": "path", + "type": "file", + "description": "XLSX or CSV file", + "name": "file", + "in": "formData", "required": true }, { "type": "string", - "description": "Authorization code", - "name": "code", - "in": "query", - "required": true + "description": "validate (default) or apply", + "name": "mode", + "in": "query" }, { "type": "string", - "description": "State parameter for CSRF protection", - "name": "state", - "in": "query", - "required": true + "description": "skip (default) or update", + "name": "on_existing", + "in": "query" } ], "responses": { - "307": { - "description": "Temporary Redirect", + "200": { + "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/importer.Result" } }, "400": { @@ -11191,64 +10668,61 @@ "$ref": "#/definitions/ErrorResponse" } }, - "404": { - "description": "Not Found", + "413": { + "description": "Request Entity Too Large", "schema": { "$ref": "#/definitions/ErrorResponse" } }, - "500": { - "description": "Internal Server Error", + "422": { + "description": "Unprocessable Entity", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/importer.Result" } } } } }, - "/auth/{provider}/login": { + "/glossary/import/columns": { "get": { - "description": "Redirects the user to the OAuth provider for authentication", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BearerAuth": [] + } + ], + "description": "The template's columns with label and help in ?locale= (or Accept-Language), type, format, constraints, allowed values and list separator, for building a guide.", "produces": [ "application/json" ], "tags": [ - "auth" + "glossary" ], - "summary": "Initiate OAuth login", - "operationId": "getAuthProviderLogin", + "summary": "Describe the glossary import columns", "parameters": [ { "type": "string", - "description": "OAuth provider (okta, google, github, etc.)", - "name": "provider", - "in": "path", - "required": true + "description": "Language for labels and help", + "name": "locale", + "in": "query" } ], "responses": { - "307": { - "description": "Temporary Redirect", - "schema": { - "type": "string" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "500": { - "description": "Internal Server Error", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/ErrorResponse" + "type": "array", + "items": { + "$ref": "#/definitions/importer.ColumnInfo" + } } } } } }, - "/glossary/export": { + "/glossary/import/template": { "get": { "security": [ { @@ -11258,7 +10732,7 @@ "BearerAuth": [] } ], - "description": "Every term in the import template's columns, so the file can be edited and imported back with on_existing=update. Cells that a spreadsheet would run as formulas are escaped in CSV.", + "description": "An XLSX (with drop-downs, comments and a guide sheet) or CSV whose columns are the term's own fields plus the metamodel profile's glossary_term fields. Headers are stable field IDs; labels follow ?locale= or Accept-Language.", "produces": [ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "text/csv" @@ -11266,7 +10740,7 @@ "tags": [ "glossary" ], - "summary": "Export the glossary", + "summary": "Download the glossary import template", "parameters": [ { "type": "string", @@ -11297,167 +10771,9 @@ } } }, - "/glossary/import": { + "/oauth/token": { "post": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "Reads an XLSX or CSV in the template's shape and checks every row. mode=validate (default) writes nothing; mode=apply writes all rows or none, and only when no row has errors. Rows whose name matches a term are skipped unless on_existing=update; on update, empty cells keep the current value.", - "consumes": [ - "multipart/form-data" - ], - "produces": [ - "application/json" - ], - "tags": [ - "glossary" - ], - "summary": "Import glossary terms from a file", - "parameters": [ - { - "type": "file", - "description": "XLSX or CSV file", - "name": "file", - "in": "formData", - "required": true - }, - { - "type": "string", - "description": "validate (default) or apply", - "name": "mode", - "in": "query" - }, - { - "type": "string", - "description": "skip (default) or update", - "name": "on_existing", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/importer.Result" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "413": { - "description": "Request Entity Too Large", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/importer.Result" - } - } - } - } - }, - "/glossary/import/columns": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "The template's columns with label and help in ?locale= (or Accept-Language), type, format, constraints, allowed values and list separator, for building a guide.", - "produces": [ - "application/json" - ], - "tags": [ - "glossary" - ], - "summary": "Describe the glossary import columns", - "parameters": [ - { - "type": "string", - "description": "Language for labels and help", - "name": "locale", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/importer.ColumnInfo" - } - } - } - } - } - }, - "/glossary/import/template": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "BearerAuth": [] - } - ], - "description": "An XLSX (with drop-downs, comments and a guide sheet) or CSV whose columns are the term's own fields plus the metamodel profile's glossary_term fields. Headers are stable field IDs; labels follow ?locale= or Accept-Language.", - "produces": [ - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "text/csv" - ], - "tags": [ - "glossary" - ], - "summary": "Download the glossary import template", - "parameters": [ - { - "type": "string", - "description": "xlsx (default) or csv", - "name": "format", - "in": "query" - }, - { - "type": "string", - "description": "Language for labels and help", - "name": "locale", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "file" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/ErrorResponse" - } - } - } - } - }, - "/oauth/token": { - "post": { - "description": "Handles authorization_code grants (with PKCE) and token exchange (RFC 8693).\nFor token-exchange, supported subject_token_type values are\nurn:ietf:params:oauth:token-type:id_token and urn:ietf:params:oauth:token-type:access_token.", + "description": "Handles authorization_code grants (with PKCE) and token exchange (RFC 8693).\nFor token-exchange, supported subject_token_type values are\nurn:ietf:params:oauth:token-type:id_token and urn:ietf:params:oauth:token-type:access_token.", "consumes": [ "application/x-www-form-urlencoded" ], @@ -13852,951 +13168,187 @@ "provider": { "type": "string" }, - "provider_user_id": { - "type": "string" - }, - "user_id": { - "type": "string" - }, - "user_info": { - "type": "object", - "additionalProperties": true - } - } - }, - "OwnerRequest": { - "type": "object", - "required": [ - "id", - "type" - ], - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "user", - "team" - ] - } - } - }, - "Permission": { - "type": "object", - "properties": { - "action": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "resource_type": { - "type": "string" - } - } - }, - "PluginRun": { - "type": "object", - "properties": { - "completed_at": { - "type": "string" - }, - "config": { - "$ref": "#/definitions/RawPluginConfig" - }, - "created_by": { - "type": "string" - }, - "error_message": { - "type": "string" - }, - "id": { - "type": "string" - }, - "pipeline_name": { - "type": "string" - }, - "run_id": { - "type": "string" - }, - "source_name": { - "type": "string" - }, - "started_at": { - "type": "string" - }, - "status": { - "$ref": "#/definitions/RunStatus" - }, - "summary": { - "$ref": "#/definitions/RunSummary" - } - } - }, - "PreviewRequest": { - "type": "object", - "properties": { - "limit": { - "type": "integer" - }, - "metadata_field": { - "type": "string" - }, - "pattern_type": { - "type": "string" - }, - "pattern_value": { - "type": "string" - }, - "query_expression": { - "type": "string" - }, - "rule_type": { - "type": "string" - } - } - }, - "PreviewResponse": { - "type": "object", - "properties": { - "column_names": { - "type": "array", - "items": { - "type": "string" - } - }, - "rows": { - "type": "array", - "items": { - "type": "array", - "items": {} - } - }, - "total_rows": { - "type": "integer" - } - } - }, - "ProductImageMeta": { - "type": "object", - "properties": { - "content_type": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "data_product_id": { - "type": "string" - }, - "filename": { - "type": "string" - }, - "id": { - "type": "string" - }, - "purpose": { - "$ref": "#/definitions/ImagePurpose" - }, - "size_bytes": { - "type": "integer" - }, - "url": { - "type": "string" - } - } - }, - "QualityAssetResult": { - "type": "object", - "properties": { - "asset_id": { - "type": "string" - }, - "dimensions": { - "description": "Dimensions are the checks the asset meets, in the order of dimensionOrder; they are written\nto the asset with its score and are not stored with the results, so only an evaluation of\nan asset carries them.", - "type": "array", - "items": { - "type": "string" - } - }, - "domain_id": { - "type": "string" - }, - "issue_count": { - "type": "integer" - }, - "issues": { - "description": "Issues is filled for the last successful run only.", - "type": "array", - "items": { - "$ref": "#/definitions/QualityIssue" - } - }, - "mrn": { - "type": "string" - }, - "name": { - "type": "string" - }, - "quality": { - "type": "number" - }, - "scores": { - "description": "Scores are the score of each quality dimension that applies to the asset, out of 100.", - "type": "object", - "additionalProperties": { - "type": "number", - "format": "float64" - } - }, - "status": { - "enum": [ - "compliant", - "warning", - "noncompliant" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.Status" - } - ] - }, - "stub": { - "description": "Stub marks a placeholder created by lineage: it is counted apart and never stored or scored.", - "type": "boolean" - }, - "type": { - "type": "string" - } - } - }, - "QualityCondition": { - "type": "object", - "properties": { - "days": { - "description": "Days moves the date a date operator compares with, from today or from the given date.", - "type": "integer" - }, - "field": { - "type": "string" - }, - "op": { - "type": "string" - }, - "optional": { - "description": "Optional, in a check, lets an empty field pass instead of failing: nothing to judge.", - "type": "boolean" - }, - "value": { - "description": "Value is what the operator compares with; set and unset take none." - } - } - }, - "QualityCustomRule": { - "type": "object", - "properties": { - "checks": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - }, - "code": { - "description": "Code is the finding code the audit reports, which clients translate; it defaults to a\nsnake_case form of the id.", - "type": "string" - }, - "created_at": { - "type": "string" - }, - "created_by": { - "type": "string" - }, - "description": { - "type": "string" - }, - "descriptionKey": { - "type": "string" - }, - "dimension": { - "description": "Dimension is the quality dimension whose score the rule's checks feed.", - "type": "string", - "enum": [ - "completeness", - "validity", - "consistency", - "timeliness" - ] - }, - "enabled": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "labelKey": { - "type": "string" - }, - "name": { - "description": "Name and Description are text in the language of whoever wrote the rule. A profile rule\nuses LabelKey and DescriptionKey, which resolve through the profile's messages.", - "type": "string" - }, - "severity": { - "description": "Severity is what a finding of the rule counts as: error or warning.", - "type": "string" - }, - "updated_at": { - "type": "string" - }, - "updated_by": { - "type": "string" - }, - "version": { - "type": "integer" - }, - "when": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - } - } - }, - "QualityEvaluateRequest": { - "type": "object", - "properties": { - "asset_ids": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "QualityEvaluateResponse": { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityAssetResult" - } - } - } - }, - "QualityFieldCount": { - "type": "object", - "properties": { - "count": { - "type": "integer" - }, - "field_id": { - "type": "string" - } - } - }, - "QualityFieldError": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "field": { - "type": "string" - } - } - }, - "QualityGroupStat": { - "type": "object", - "properties": { - "count": { - "type": "integer" - }, - "key": { - "type": "string" - }, - "value": { - "type": "number" - } - } - }, - "QualityIssue": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "field_id": { - "type": "string" - }, - "item": { - "description": "Item is the position of the offending entry when the field is a list.", - "type": "integer" - }, - "rule_id": { - "$ref": "#/definitions/quality.RuleID" - }, - "section": { - "type": "string" - }, - "severity": { - "enum": [ - "error", - "warning" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.Severity" - } - ] - } - } - }, - "QualityResultsResponse": { - "type": "object", - "properties": { - "limit": { - "type": "integer" - }, - "offset": { - "type": "integer" - }, - "results": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityAssetResult" - } - }, - "total": { - "type": "integer" - } - } - }, - "QualityRetention": { - "type": "object", - "properties": { - "result_days": { - "type": "integer" - }, - "run_days": { - "type": "integer" - } - } - }, - "QualityRule": { - "type": "object", - "properties": { - "checks": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - }, - "code": { - "description": "Code is the finding code the audit reports, which clients translate; it defaults to a\nsnake_case form of the id.", - "type": "string" - }, - "description": { - "type": "string" - }, - "descriptionKey": { - "type": "string" - }, - "dimension": { - "description": "Dimension is the quality dimension whose score the rule's checks feed.", - "type": "string", - "enum": [ - "completeness", - "validity", - "consistency", - "timeliness" - ] - }, - "id": { - "type": "string" - }, - "labelKey": { - "type": "string" - }, - "name": { - "description": "Name and Description are text in the language of whoever wrote the rule. A profile rule\nuses LabelKey and DescriptionKey, which resolve through the profile's messages.", - "type": "string" - }, - "severity": { - "description": "Severity is what a finding of the rule counts as: error or warning.", - "type": "string" - }, - "when": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - } - } - }, - "QualityRuleError": { - "type": "object", - "properties": { - "problems": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityRuleProblem" - } - } - } - }, - "QualityRuleInfo": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "definition": { - "description": "Definition is what the rule checks, for the rules that declare it.", - "allOf": [ - { - "$ref": "#/definitions/QualityRule" - } - ] - }, - "description": { - "type": "string" - }, - "description_key": { - "type": "string" - }, - "dimension": { - "description": "Dimension is the quality dimension the rule feeds.", - "type": "string", - "enum": [ - "completeness", - "validity", - "consistency", - "timeliness" - ] - }, - "enabled": { - "type": "boolean" - }, - "id": { - "$ref": "#/definitions/quality.RuleID" - }, - "label_key": { - "type": "string" - }, - "name": { - "description": "Name and Description are literal text, of a custom rule; LabelKey and DescriptionKey resolve\nthrough the profile's messages, for a profile rule; a built-in rule has neither and the\nclient names it by its id.", - "type": "string" - }, - "problem": { - "description": "Problem says why a custom rule is not applied: it names a field the profile no longer has.", - "type": "string" - }, - "severity": { - "enum": [ - "error", - "warning" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.Severity" - } - ] - }, - "source": { - "enum": [ - "builtin", - "profile", - "custom" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.RuleSource" - } - ] - }, - "version": { - "description": "Version, for a custom rule, is what to send back with If-Match.", - "type": "integer" - } - } - }, - "QualityRuleProblem": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "path": { - "type": "string" - } - } - }, - "QualityRuleRequest": { - "type": "object", - "properties": { - "checks": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - }, - "code": { - "description": "Code is the finding code the audit reports, which clients translate; it defaults to a\nsnake_case form of the id.", - "type": "string" - }, - "description": { - "type": "string" - }, - "descriptionKey": { - "type": "string" - }, - "dimension": { - "description": "Dimension is the quality dimension whose score the rule's checks feed.", - "type": "string", - "enum": [ - "completeness", - "validity", - "consistency", - "timeliness" - ] - }, - "enabled": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "labelKey": { - "type": "string" - }, - "name": { - "description": "Name and Description are text in the language of whoever wrote the rule. A profile rule\nuses LabelKey and DescriptionKey, which resolve through the profile's messages.", - "type": "string" - }, - "severity": { - "description": "Severity is what a finding of the rule counts as: error or warning.", - "type": "string" - }, - "when": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityCondition" - } - } - } - }, - "QualityRuleSetting": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "severity": { - "enum": [ - "error", - "warning" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.Severity" - } - ] - } - } - }, - "QualityRulesResponse": { - "type": "object", - "properties": { - "rules": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityRuleInfo" - } - } - } - }, - "QualityRun": { - "type": "object", - "properties": { - "custom_rules": { - "description": "CustomRules are the rules people wrote that the run applied, as they were when it started;\nonly a single run read carries them.", - "type": "array", - "items": { - "$ref": "#/definitions/QualityCustomRule" - } - }, - "error": { - "type": "string" - }, - "finished_at": { - "type": "string" - }, - "id": { - "type": "string" - }, - "metamodel_hash": { - "type": "string" - }, - "metamodel_profile": { - "type": "string" - }, - "metamodel_version": { - "type": "integer" - }, - "processed": { - "type": "integer" - }, - "score_conflicts": { - "type": "integer" - }, - "score_failures": { - "type": "integer" - }, - "scores_written": { - "description": "ScoresWritten, ScoreConflicts and ScoreFailures say how writing the scores on the assets\nwent: written, skipped because the asset was edited after it was read, and failed.", - "type": "integer" - }, - "settings": { - "$ref": "#/definitions/QualitySettings" - }, - "settings_version": { - "type": "integer" - }, - "started_at": { - "type": "string" - }, - "status": { - "enum": [ - "running", - "succeeded", - "failed" - ], - "allOf": [ - { - "$ref": "#/definitions/quality.RunStatus" - } - ] - }, - "summary": { - "$ref": "#/definitions/QualitySummary" - }, - "total": { - "type": "integer" - }, - "trigger": { - "type": "string", - "enum": [ - "manual", - "schedule" - ] + "provider_user_id": { + "type": "string" }, - "triggered_by": { + "user_id": { "type": "string" + }, + "user_info": { + "type": "object", + "additionalProperties": true } } }, - "QualityRunConflict": { + "OwnerRequest": { "type": "object", + "required": [ + "id", + "type" + ], "properties": { - "error": { + "id": { "type": "string" }, - "run": { - "$ref": "#/definitions/QualityRun" + "type": { + "type": "string", + "enum": [ + "user", + "team" + ] } } }, - "QualityRunsResponse": { + "Permission": { "type": "object", "properties": { - "limit": { - "type": "integer" + "action": { + "type": "string" }, - "offset": { - "type": "integer" + "description": { + "type": "string" }, - "runs": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityRun" - } + "id": { + "type": "string" }, - "total": { - "type": "integer" + "name": { + "type": "string" + }, + "resource_type": { + "type": "string" } } }, - "QualitySettings": { + "PluginRun": { "type": "object", "properties": { - "batch_size": { - "type": "integer" + "completed_at": { + "type": "string" }, - "max_run_seconds": { - "type": "integer" + "config": { + "$ref": "#/definitions/RawPluginConfig" }, - "retention": { - "$ref": "#/definitions/QualityRetention" + "created_by": { + "type": "string" }, - "rules": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/QualityRuleSetting" - } + "error_message": { + "type": "string" + }, + "id": { + "type": "string" + }, + "pipeline_name": { + "type": "string" }, - "schedule": { - "description": "Schedule is a five-field cron expression; empty means runs are manual only.", + "run_id": { + "type": "string" + }, + "source_name": { "type": "string" }, - "thresholds": { - "$ref": "#/definitions/QualityThresholds" + "started_at": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/RunStatus" }, - "weights": { - "$ref": "#/definitions/QualityWeights" + "summary": { + "$ref": "#/definitions/RunSummary" } } }, - "QualitySettingsResponse": { + "PreviewRequest": { "type": "object", "properties": { - "batch_size": { - "type": "integer" - }, - "max_run_seconds": { + "limit": { "type": "integer" }, - "next_run": { + "metadata_field": { "type": "string" }, - "retention": { - "$ref": "#/definitions/QualityRetention" - }, - "rules": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/QualityRuleSetting" - } - }, - "schedule": { - "description": "Schedule is a five-field cron expression; empty means runs are manual only.", + "pattern_type": { "type": "string" }, - "thresholds": { - "$ref": "#/definitions/QualityThresholds" - }, - "updated_at": { + "pattern_value": { "type": "string" }, - "updated_by": { + "query_expression": { "type": "string" }, - "version": { - "type": "integer" - }, - "weights": { - "$ref": "#/definitions/QualityWeights" + "rule_type": { + "type": "string" } } }, - "QualitySummary": { + "PreviewResponse": { "type": "object", "properties": { - "by_dimension": { - "description": "ByDimension is the mean score of each quality dimension, over the assets it applies to.", + "column_names": { "type": "array", "items": { - "$ref": "#/definitions/QualityGroupStat" + "type": "string" } }, - "by_domain": { - "description": "ByDomain is one more aggregate of the run, not a filter of it; the assets of no domain are\nunder \"unassigned\".", + "rows": { "type": "array", "items": { - "$ref": "#/definitions/QualityGroupStat" + "type": "array", + "items": {} } }, - "by_section": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityGroupStat" - } + "total_rows": { + "type": "integer" + } + } + }, + "ProductImageMeta": { + "type": "object", + "properties": { + "content_type": { + "type": "string" }, - "by_type": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityGroupStat" - } + "created_at": { + "type": "string" }, - "quality": { - "type": "number" + "data_product_id": { + "type": "string" }, - "status_counts": { - "type": "object", - "additionalProperties": { - "type": "integer" - } + "filename": { + "type": "string" }, - "stubs": { - "type": "integer" + "id": { + "type": "string" }, - "top_fields": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityFieldCount" - } + "purpose": { + "$ref": "#/definitions/ImagePurpose" }, - "total_assets": { + "size_bytes": { "type": "integer" }, - "total_issues": { - "type": "integer" + "url": { + "type": "string" } } }, - "QualityThresholds": { + "QualityCondition": { "type": "object", "properties": { - "compliant": { - "type": "number" + "days": { + "description": "Days moves the date a date operator compares with, from today or from the given date.", + "type": "integer" }, - "warning": { - "type": "number" - } - } - }, - "QualityValidationError": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "$ref": "#/definitions/QualityFieldError" - } - } - } - }, - "QualityWeights": { - "type": "object", - "properties": { - "completeness": { - "type": "number" + "field": { + "type": "string" }, - "consistency": { - "type": "number" + "op": { + "type": "string" }, - "timeliness": { - "type": "number" + "optional": { + "description": "Optional, in a check, lets an empty field pass instead of failing: nothing to judge.", + "type": "boolean" }, - "validity": { - "type": "number" + "value": { + "description": "Value is what the operator compares with; set and unset take none." } } }, @@ -16896,6 +15448,57 @@ } } }, + "metamodel.QualityRule": { + "type": "object", + "properties": { + "checks": { + "type": "array", + "items": { + "$ref": "#/definitions/QualityCondition" + } + }, + "code": { + "description": "Code is the finding code the audit reports, which clients translate; it defaults to a\nsnake_case form of the id.", + "type": "string" + }, + "description": { + "type": "string" + }, + "descriptionKey": { + "type": "string" + }, + "dimension": { + "description": "Dimension is the quality dimension whose score the rule's checks feed.", + "type": "string", + "enum": [ + "completeness", + "validity", + "consistency", + "timeliness" + ] + }, + "id": { + "type": "string" + }, + "labelKey": { + "type": "string" + }, + "name": { + "description": "Name and Description are text in the language of whoever wrote the rule. A profile rule\nuses LabelKey and DescriptionKey, which resolve through the profile's messages.", + "type": "string" + }, + "severity": { + "description": "Severity is what a finding of the rule counts as: error or warning.", + "type": "string" + }, + "when": { + "type": "array", + "items": { + "$ref": "#/definitions/QualityCondition" + } + } + } + }, "metamodel.Schema": { "type": "object", "properties": { @@ -16934,7 +15537,7 @@ "description": "QualityRules are the checks the quality audit applies on top of the fields' own validation.", "type": "array", "items": { - "$ref": "#/definitions/QualityRule" + "$ref": "#/definitions/metamodel.QualityRule" } }, "version": { @@ -17162,71 +15765,6 @@ } } }, - "quality.RuleID": { - "type": "string", - "enum": [ - "required", - "validation", - "externalLinkInvalid", - "externalLinkEmpty" - ], - "x-enum-varnames": [ - "RuleRequired", - "RuleValidation", - "RuleExternalLinkInvalid", - "RuleExternalLinkEmpty" - ] - }, - "quality.RuleSource": { - "type": "string", - "enum": [ - "builtin", - "profile", - "custom" - ], - "x-enum-varnames": [ - "SourceBuiltin", - "SourceProfile", - "SourceCustom" - ] - }, - "quality.RunStatus": { - "type": "string", - "enum": [ - "running", - "succeeded", - "failed" - ], - "x-enum-varnames": [ - "RunRunning", - "RunSucceeded", - "RunFailed" - ] - }, - "quality.Severity": { - "type": "string", - "enum": [ - "error", - "warning" - ], - "x-enum-varnames": [ - "SeverityError", - "SeverityWarning" - ] - }, - "quality.Status": { - "type": "string", - "enum": [ - "compliant", - "warning", - "noncompliant" - ], - "x-enum-varnames": [ - "StatusCompliant", - "StatusWarning", - "StatusNoncompliant" - ] - }, "v1_assets.patchFieldsRequest": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 30247aa5..2b4429a9 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1656,54 +1656,6 @@ definitions: url: type: string type: object - QualityAssetResult: - properties: - asset_id: - type: string - dimensions: - description: |- - Dimensions are the checks the asset meets, in the order of dimensionOrder; they are written - to the asset with its score and are not stored with the results, so only an evaluation of - an asset carries them. - items: - type: string - type: array - domain_id: - type: string - issue_count: - type: integer - issues: - description: Issues is filled for the last successful run only. - items: - $ref: '#/definitions/QualityIssue' - type: array - mrn: - type: string - name: - type: string - quality: - type: number - scores: - additionalProperties: - format: float64 - type: number - description: Scores are the score of each quality dimension that applies to - the asset, out of 100. - type: object - status: - allOf: - - $ref: '#/definitions/quality.Status' - enum: - - compliant - - warning - - noncompliant - stub: - description: 'Stub marks a placeholder created by lineage: it is counted apart - and never stored or scored.' - type: boolean - type: - type: string - type: object QualityCondition: properties: days: @@ -1722,1702 +1674,1352 @@ definitions: description: Value is what the operator compares with; set and unset take none. type: object - QualityCustomRule: + QueryCount: properties: - checks: - items: - $ref: '#/definitions/QualityCondition' - type: array - code: - description: |- - Code is the finding code the audit reports, which clients translate; it defaults to a - snake_case form of the id. - type: string - created_at: - type: string - created_by: - type: string - description: + count: + type: integer + query: type: string - descriptionKey: + query_type: type: string - dimension: - description: Dimension is the quality dimension whose score the rule's checks - feed. - enum: - - completeness - - validity - - consistency - - timeliness + type: object + RawPluginConfig: + additionalProperties: true + type: object + RecordRunRequest: + properties: + agent_mrn: type: string - enabled: - type: boolean - id: + ended_at: type: string - labelKey: + error: type: string - name: - description: |- - Name and Description are text in the language of whoever wrote the rule. A profile rule - uses LabelKey and DescriptionKey, which resolve through the profile's messages. + model: type: string - severity: - description: 'Severity is what a finding of the rule counts as: error or warning.' + observed_assets: + items: + type: string + type: array + run_id: type: string - updated_at: + started_at: type: string - updated_by: + status: type: string - version: + tokens_in: type: integer - when: + tokens_out: + type: integer + tool_calls: items: - $ref: '#/definitions/QualityCondition' + $ref: '#/definitions/ToolCallPayload' type: array type: object - QualityEvaluateRequest: + ReindexAcceptedResponse: properties: - asset_ids: - items: - type: string - type: array + message: + example: Reindex started + type: string + status: + example: accepted + type: string type: object - QualityEvaluateResponse: + ReindexStatusResponse: properties: - results: - items: - $ref: '#/definitions/QualityAssetResult' - type: array + es_configured: + type: boolean + running: + type: boolean type: object - QualityFieldCount: + RemoveTermRequest: properties: - count: - type: integer - field_id: + term_id: type: string + required: + - term_id type: object - QualityFieldError: + Result: properties: - code: + description: type: string - field: + id: type: string - type: object - QualityGroupStat: - properties: - count: - type: integer - key: + metadata: + additionalProperties: true + type: object + name: type: string - value: + rank: type: number - type: object - QualityIssue: - properties: - code: - type: string - field_id: + type: + $ref: '#/definitions/ResultType' + updated_at: type: string - item: - description: Item is the position of the offending entry when the field is - a list. - type: integer - rule_id: - $ref: '#/definitions/quality.RuleID' - section: + url: type: string - severity: - allOf: - - $ref: '#/definitions/quality.Severity' - enum: - - error - - warning - type: object - QualityResultsResponse: - properties: - limit: - type: integer - offset: - type: integer - results: - items: - $ref: '#/definitions/QualityAssetResult' - type: array - total: - type: integer - type: object - QualityRetention: - properties: - result_days: - type: integer - run_days: - type: integer type: object - QualityRule: + ResultType: + enum: + - asset + - glossary + - team + - data_product + type: string + x-enum-varnames: + - ResultTypeAsset + - ResultTypeGlossary + - ResultTypeTeam + - ResultTypeDataProduct + Role: properties: - checks: - items: - $ref: '#/definitions/QualityCondition' - type: array - code: - description: |- - Code is the finding code the audit reports, which clients translate; it defaults to a - snake_case form of the id. - type: string - description: + created_at: type: string - descriptionKey: + deleted_at: type: string - dimension: - description: Dimension is the quality dimension whose score the rule's checks - feed. - enum: - - completeness - - validity - - consistency - - timeliness + description: type: string id: type: string - labelKey: - type: string + is_system: + type: boolean name: - description: |- - Name and Description are text in the language of whoever wrote the rule. A profile rule - uses LabelKey and DescriptionKey, which resolve through the profile's messages. - type: string - severity: - description: 'Severity is what a finding of the rule counts as: error or warning.' type: string - when: - items: - $ref: '#/definitions/QualityCondition' - type: array - type: object - QualityRuleError: - properties: - problems: + permissions: items: - $ref: '#/definitions/QualityRuleProblem' + $ref: '#/definitions/RolePermission' type: array + updated_at: + type: string + user_count: + type: integer type: object - QualityRuleInfo: + RolePermission: properties: - code: + action: type: string - definition: - allOf: - - $ref: '#/definitions/QualityRule' - description: Definition is what the rule checks, for the rules that declare - it. description: type: string - description_key: - type: string - dimension: - description: Dimension is the quality dimension the rule feeds. - enum: - - completeness - - validity - - consistency - - timeliness - type: string - enabled: - type: boolean id: - $ref: '#/definitions/quality.RuleID' - label_key: type: string name: - description: |- - Name and Description are literal text, of a custom rule; LabelKey and DescriptionKey resolve - through the profile's messages, for a profile rule; a built-in rule has neither and the - client names it by its id. - type: string - problem: - description: 'Problem says why a custom rule is not applied: it names a field - the profile no longer has.' - type: string - severity: - allOf: - - $ref: '#/definitions/quality.Severity' - enum: - - error - - warning - source: - allOf: - - $ref: '#/definitions/quality.RuleSource' - enum: - - builtin - - profile - - custom - version: - description: Version, for a custom rule, is what to send back with If-Match. - type: integer - type: object - QualityRuleProblem: - properties: - code: type: string - path: + resource_type: type: string type: object - QualityRuleRequest: + RulePreview: properties: - checks: + asset_count: + type: integer + asset_ids: items: - $ref: '#/definitions/QualityCondition' + type: string type: array - code: - description: |- - Code is the finding code the audit reports, which clients translate; it defaults to a - snake_case form of the id. - type: string + errors: + items: + type: string + type: array + type: object + RuleType: + enum: + - query + - metadata_match + type: string + x-enum-varnames: + - RuleTypeQuery + - RuleTypeMetadataMatch + RunCreateAssetRequest: + properties: description: type: string - descriptionKey: - type: string - dimension: - description: Dimension is the quality dimension whose score the rule's checks - feed. - enum: - - completeness - - validity - - consistency - - timeliness - type: string - enabled: - type: boolean - id: - type: string - labelKey: - type: string + external_links: + items: + additionalProperties: + type: string + type: object + type: array + metadata: + additionalProperties: true + type: object name: - description: |- - Name and Description are text in the language of whoever wrote the rule. A profile rule - uses LabelKey and DescriptionKey, which resolve through the profile's messages. type: string - severity: - description: 'Severity is what a finding of the rule counts as: error or warning.' + providers: + items: + type: string + type: array + schema: + additionalProperties: true + type: object + sources: + items: + $ref: '#/definitions/AssetSource' + type: array + tags: + items: + type: string + type: array + terms: + description: Terms are the names of glossary terms assigned to this asset. + items: + type: string + type: array + type: type: string - when: + type: object + RunEntitiesResponse: + properties: + entities: items: - $ref: '#/definitions/QualityCondition' + $ref: '#/definitions/RunEntity' type: array + limit: + type: integer + offset: + type: integer + total: + type: integer type: object - QualityRuleSetting: + RunEntity: properties: - enabled: - type: boolean - severity: - allOf: - - $ref: '#/definitions/quality.Severity' - enum: - - error - - warning + created_at: + type: string + entity_mrn: + type: string + entity_name: + type: string + entity_type: + type: string + error_message: + type: string + id: + type: string + run_id: + type: string + status: + type: string type: object - QualityRulesResponse: + RunEvent: properties: - rules: + eventTime: + type: string + eventType: + type: string + inputs: items: - $ref: '#/definitions/QualityRuleInfo' + $ref: '#/definitions/Dataset' type: array - type: object - QualityRun: - properties: - custom_rules: - description: |- - CustomRules are the rules people wrote that the run applied, as they were when it started; - only a single run read carries them. + job: + $ref: '#/definitions/Job' + outputs: items: - $ref: '#/definitions/QualityCustomRule' + $ref: '#/definitions/Dataset' type: array - error: + producer: type: string - finished_at: + run: + $ref: '#/definitions/LineageRun' + schemaURL: + type: string + type: object + RunHistory: + properties: + duration_ms: + type: integer + end_time: + type: string + event_time: type: string id: type: string - metamodel_hash: + job_name: type: string - metamodel_profile: + job_namespace: type: string - metamodel_version: - type: integer - processed: - type: integer - score_conflicts: - type: integer - score_failures: - type: integer - scores_written: - description: |- - ScoresWritten, ScoreConflicts and ScoreFailures say how writing the scores on the assets - went: written, skipped because the asset was edited after it was read, and failed. - type: integer - settings: - $ref: '#/definitions/QualitySettings' - settings_version: - type: integer - started_at: + run_id: type: string - status: - allOf: - - $ref: '#/definitions/quality.RunStatus' - enum: - - running - - succeeded - - failed - summary: - $ref: '#/definitions/QualitySummary' - total: - type: integer - trigger: - enum: - - manual - - schedule + start_time: type: string - triggered_by: + status: type: string - type: object - QualityRunConflict: - properties: - error: + type: type: string - run: - $ref: '#/definitions/QualityRun' type: object - QualityRunsResponse: + RunHistoryResponse: properties: limit: type: integer offset: type: integer - runs: + run_history: items: - $ref: '#/definitions/QualityRun' + $ref: '#/definitions/RunHistory' type: array total: type: integer type: object - QualitySettings: + RunStatus: + enum: + - running + - completed + - failed + - cancelled + type: string + x-enum-varnames: + - StatusRunning + - StatusCompleted + - StatusFailed + - StatusCancelled + RunSummary: properties: - batch_size: + assets_created: type: integer - max_run_seconds: + assets_deleted: type: integer - retention: - $ref: '#/definitions/QualityRetention' - rules: - additionalProperties: - $ref: '#/definitions/QualityRuleSetting' - type: object - schedule: - description: Schedule is a five-field cron expression; empty means runs are - manual only. - type: string - thresholds: - $ref: '#/definitions/QualityThresholds' - weights: - $ref: '#/definitions/QualityWeights' - type: object - QualitySettingsResponse: - properties: - batch_size: + assets_terms_linked: type: integer - max_run_seconds: + assets_updated: type: integer - next_run: - type: string - retention: - $ref: '#/definitions/QualityRetention' - rules: - additionalProperties: - $ref: '#/definitions/QualityRuleSetting' - type: object - schedule: - description: Schedule is a five-field cron expression; empty means runs are - manual only. - type: string - thresholds: - $ref: '#/definitions/QualityThresholds' - updated_at: - type: string - updated_by: - type: string - version: + documentation_added: type: integer - weights: - $ref: '#/definitions/QualityWeights' - type: object - QualitySummary: - properties: - by_dimension: - description: ByDimension is the mean score of each quality dimension, over - the assets it applies to. - items: - $ref: '#/definitions/QualityGroupStat' - type: array - by_domain: + duration_seconds: + type: integer + errors_count: + type: integer + glossary_terms_created: description: |- - ByDomain is one more aggregate of the run, not a filter of it; the assets of no domain are - under "unassigned". - items: - $ref: '#/definitions/QualityGroupStat' - type: array - by_section: - items: - $ref: '#/definitions/QualityGroupStat' - type: array - by_type: - items: - $ref: '#/definitions/QualityGroupStat' - type: array - quality: - type: number - status_counts: - additionalProperties: - type: integer - type: object - stubs: + Glossary counts are absent from runs that predate them, and from + sources that curate no business terms. type: integer - top_fields: - items: - $ref: '#/definitions/QualityFieldCount' - type: array - total_assets: + glossary_terms_updated: type: integer - total_issues: + lineage_created: + type: integer + lineage_updated: + type: integer + total_entities: type: integer type: object - QualityThresholds: - properties: - compliant: - type: number - warning: - type: number - type: object - QualityValidationError: + RunsResponse: properties: - fields: + runs: items: - $ref: '#/definitions/QualityFieldError' + $ref: '#/definitions/AgentRun' type: array + total: + type: integer type: object - QualityWeights: - properties: - completeness: - type: number - consistency: - type: number - timeliness: - type: number - validity: - type: number - type: object - QueryCount: + SSOProvider: properties: - count: - type: integer - query: + issuer_url: type: string - query_type: + name: + type: string + type: type: string type: object - RawPluginConfig: - additionalProperties: true + SSOProvidersResponse: + properties: + providers: + items: + $ref: '#/definitions/SSOProvider' + type: array type: object - RecordRunRequest: + SSOTeamMapping: properties: - agent_mrn: + created_at: type: string - ended_at: + id: type: string - error: + member_role: type: string - model: + provider: type: string - observed_assets: - items: - type: string - type: array - run_id: + sso_group_name: type: string - started_at: + team_id: type: string - status: + updated_at: type: string - tokens_in: - type: integer - tokens_out: - type: integer - tool_calls: - items: - $ref: '#/definitions/ToolCallPayload' - type: array type: object - ReindexAcceptedResponse: + Schedule: properties: - message: - example: Reindex started + config: + additionalProperties: true + type: object + created_at: type: string - status: - example: accepted + created_by: type: string - type: object - ReindexStatusResponse: - properties: - es_configured: - type: boolean - running: + cron_expression: + type: string + enabled: type: boolean - type: object - RemoveTermRequest: - properties: - term_id: + id: type: string - required: - - term_id - type: object - Result: - properties: - description: + last_run_at: type: string - id: + last_run_status: + type: string + managed_by: type: string - metadata: - additionalProperties: true - type: object name: type: string - rank: - type: number - type: - $ref: '#/definitions/ResultType' - updated_at: + next_run_at: type: string - url: + plugin_id: + type: string + updated_at: type: string type: object - ResultType: - enum: - - asset - - glossary - - team - - data_product - type: string - x-enum-varnames: - - ResultTypeAsset - - ResultTypeGlossary - - ResultTypeTeam - - ResultTypeDataProduct - Role: + SearchOwnersResponse: + properties: + owners: + items: + $ref: '#/definitions/TeamOwner' + type: array + type: object + SearchResponse: + properties: + facets: + $ref: '#/definitions/Facets' + limit: + type: integer + offset: + type: integer + results: + items: + $ref: '#/definitions/Result' + type: array + total: + type: integer + type: object + ServiceAccount: properties: + active: + type: boolean created_at: type: string - deleted_at: + created_by: type: string description: type: string id: type: string - is_system: - type: boolean name: type: string - permissions: + roles: items: - $ref: '#/definitions/RolePermission' + $ref: '#/definitions/Role' type: array updated_at: type: string - user_count: - type: integer type: object - RolePermission: + ServiceAccountAPIKey: properties: - action: + created_at: type: string - description: + expires_at: type: string id: type: string + key: + type: string + last_used_at: + type: string name: type: string - resource_type: + service_account_id: type: string type: object - RulePreview: + StartRunRequest: properties: - asset_count: + config: + $ref: '#/definitions/RawPluginConfig' + pipeline_name: + type: string + source_name: + type: string + required: + - pipeline_name + - source_name + type: object + Stats: + properties: + median_latency_ms: + type: integer + p95_latency_ms: + type: integer + run_count: + type: integer + success_rate: + type: number + tokens_in: + type: integer + tokens_out: type: integer - asset_ids: - items: - type: string - type: array - errors: - items: - type: string - type: array type: object - RuleType: - enum: - - query - - metadata_match - type: string - x-enum-varnames: - - RuleTypeQuery - - RuleTypeMetadataMatch - RunCreateAssetRequest: + TagRequest: + properties: + tag: + type: string + required: + - tag + type: object + Team: properties: + created_at: + type: string + created_by: + type: string + created_via_sso: + type: boolean description: type: string - external_links: - items: - additionalProperties: - type: string - type: object - type: array + id: + type: string metadata: additionalProperties: true type: object name: type: string - providers: - items: - type: string - type: array - schema: - additionalProperties: true - type: object - sources: - items: - $ref: '#/definitions/AssetSource' - type: array + sso_provider: + type: string tags: items: type: string type: array - terms: - description: Terms are the names of glossary terms assigned to this asset. - items: - type: string - type: array - type: + updated_at: type: string type: object - RunEntitiesResponse: - properties: - entities: - items: - $ref: '#/definitions/RunEntity' - type: array - limit: - type: integer - offset: - type: integer - total: - type: integer - type: object - RunEntity: + TeamMemberWithUser: properties: - created_at: + email: type: string - entity_mrn: + id: type: string - entity_name: + joined_at: type: string - entity_type: + name: type: string - error_message: + profile_picture: type: string - id: + role: type: string - run_id: - type: string - status: + source: type: string - type: object - RunEvent: - properties: - eventTime: + sso_provider: type: string - eventType: + team_id: type: string - inputs: - items: - $ref: '#/definitions/Dataset' - type: array - job: - $ref: '#/definitions/Job' - outputs: - items: - $ref: '#/definitions/Dataset' - type: array - producer: + user_id: type: string - run: - $ref: '#/definitions/LineageRun' - schemaURL: + username: type: string type: object - RunHistory: + TeamOwner: properties: - duration_ms: - type: integer - end_time: - type: string - event_time: + email: type: string id: type: string - job_name: + name: type: string - job_namespace: + profile_picture: type: string - run_id: + type: type: string - start_time: + username: type: string - status: + type: object + TokenExchangeResponse: + properties: + access_token: type: string - type: + expires_in: + type: integer + issued_token_type: + type: string + token_type: type: string type: object - RunHistoryResponse: + TokenResponse: properties: - limit: - type: integer - offset: - type: integer - run_history: - items: - $ref: '#/definitions/RunHistory' - type: array - total: + access_token: + type: string + expires_in: type: integer + mfa_token: + type: string + requires_password_change: + type: boolean + requires_totp: + type: boolean + requires_totp_enrollment: + type: boolean + token_type: + type: string type: object - RunStatus: - enum: - - running - - completed - - failed - - cancelled - type: string - x-enum-varnames: - - StatusRunning - - StatusCompleted - - StatusFailed - - StatusCancelled - RunSummary: + ToolCall: properties: - assets_created: - type: integer - assets_deleted: - type: integer - assets_terms_linked: - type: integer - assets_updated: - type: integer - documentation_added: - type: integer - duration_seconds: - type: integer - errors_count: - type: integer - glossary_terms_created: - description: |- - Glossary counts are absent from runs that predate them, and from - sources that curate no business terms. - type: integer - glossary_terms_updated: - type: integer - lineage_created: - type: integer - lineage_updated: + duration_ms: type: integer - total_entities: + ordinal: type: integer + started_at: + type: string + status: + type: string + target_mrn: + type: string + tool_name: + type: string type: object - RunsResponse: + ToolCallPayload: properties: - runs: - items: - $ref: '#/definitions/AgentRun' - type: array - total: + duration_ms: type: integer - type: object - SSOProvider: - properties: - issuer_url: + started_at: type: string - name: + status: type: string - type: + target_mrn: + type: string + tool_name: type: string type: object - SSOProvidersResponse: + TotalAssetsResponse: properties: - providers: - items: - $ref: '#/definitions/SSOProvider' - type: array + count: + type: integer type: object - SSOTeamMapping: + UIConfigResponse: properties: - created_at: - type: string - id: - type: string - member_role: - type: string - provider: - type: string - sso_group_name: - type: string - team_id: + allow_unencrypted: + type: boolean + banner: + $ref: '#/definitions/BannerResponse' + default_language: type: string - updated_at: + domain_landing_url: type: string + encryption_configured: + type: boolean + table_preview_enabled: + type: boolean type: object - Schedule: + UpdateAssetRequest: properties: - config: + description: + type: string + environments: + additionalProperties: + $ref: '#/definitions/Environment' + type: object + external_links: + items: + $ref: '#/definitions/AssetExternalLink' + type: array + metadata: additionalProperties: true type: object - created_at: - type: string - created_by: - type: string - cron_expression: + name: type: string - enabled: - type: boolean - id: + providers: + items: + type: string + type: array + schema: + additionalProperties: + type: string + type: object + sources: + items: + $ref: '#/definitions/AssetSource' + type: array + tags: + items: + type: string + type: array + type: type: string - last_run_at: + user_description: type: string - last_run_status: + type: object + UpdateAssetRuleRequest: + properties: + description: type: string - managed_by: + is_enabled: + type: boolean + links: + items: + $ref: '#/definitions/AssetRuleExternalLink' + type: array + metadata_field: type: string name: type: string - next_run_at: + pattern_type: type: string - plugin_id: + pattern_value: type: string - updated_at: + priority: + type: integer + query_expression: type: string - type: object - SearchOwnersResponse: - properties: - owners: + rule_type: + type: string + term_ids: items: - $ref: '#/definitions/TeamOwner' + type: string type: array type: object - SearchResponse: + UpdateDataProductRequest: properties: - facets: - $ref: '#/definitions/Facets' - limit: - type: integer - offset: - type: integer - results: - items: - $ref: '#/definitions/Result' - type: array - total: - type: integer - type: object - ServiceAccount: - properties: - active: - type: boolean - created_at: - type: string - created_by: - type: string description: type: string - id: - type: string + metadata: + additionalProperties: true + type: object name: type: string - roles: + owners: items: - $ref: '#/definitions/Role' + $ref: '#/definitions/DataProductOwnerRequest' + type: array + tags: + items: + type: string type: array - updated_at: - type: string type: object - ServiceAccountAPIKey: + UpdateMemberRoleRequest: properties: - created_at: + role: type: string - expires_at: + type: object + UpdatePasswordRequest: + properties: + new_password: + minLength: 8 type: string - id: + required: + - new_password + type: object + UpdateSSOMappingRequest: + properties: + member_role: type: string - key: + team_id: type: string - last_used_at: + type: object + UpdateScheduleRequest: + properties: + config: + additionalProperties: true + type: object + cron_expression: type: string + enabled: + type: boolean name: type: string - service_account_id: + plugin_id: type: string type: object - StartRunRequest: + UpdateServiceAccountRequest: properties: - config: - $ref: '#/definitions/RawPluginConfig' - pipeline_name: + active: + type: boolean + description: type: string - source_name: + name: type: string - required: - - pipeline_name - - source_name - type: object - Stats: - properties: - median_latency_ms: - type: integer - p95_latency_ms: - type: integer - run_count: - type: integer - success_rate: - type: number - tokens_in: - type: integer - tokens_out: - type: integer + role_ids: + items: + type: string + type: array type: object - TagRequest: + UpdateTeamRequest: properties: - tag: + description: type: string - required: - - tag + metadata: + additionalProperties: true + type: object + name: + type: string + tags: + items: + type: string + type: array type: object - Team: + UpdateTermRequest: properties: - created_at: - type: string - created_by: + definition: type: string - created_via_sso: - type: boolean description: type: string - id: - type: string metadata: additionalProperties: true type: object name: type: string - sso_provider: + owners: + items: + $ref: '#/definitions/OwnerRequest' + type: array + parent_term_id: type: string tags: + description: Absent leaves the stored tags alone; an empty list clears them. items: type: string type: array - updated_at: - type: string type: object - TeamMemberWithUser: + UpdateUserInput: properties: + active: + type: boolean email: type: string - id: - type: string - joined_at: - type: string name: type: string + password: + minLength: 8 + type: string + preferences: + additionalProperties: true + type: object profile_picture: type: string - role: + role_names: + items: + type: string + minItems: 1 + type: array + type: object + User: + properties: + active: + type: boolean + created_at: type: string - source: + id: type: string - sso_provider: + identities: + items: + $ref: '#/definitions/UserIdentity' + type: array + must_change_password: + type: boolean + name: type: string - team_id: + preferences: + additionalProperties: true + type: object + profile_picture: type: string - user_id: + roles: + items: + $ref: '#/definitions/UserRole' + type: array + sessions_invalidated_at: + description: Tokens issued before this moment are rejected at validation, + so setting it to now signs the user out of every session at once. + type: string + updated_at: type: string username: type: string type: object - TeamOwner: + UserIdentity: properties: - email: + created_at: type: string id: type: string - name: + provider: type: string - profile_picture: + provider_data: + additionalProperties: true + type: object + provider_email: type: string - type: + provider_user_id: type: string - username: + updated_at: + type: string + user_id: type: string type: object - TokenExchangeResponse: + UserRole: properties: - access_token: + description: type: string - expires_in: - type: integer - issued_token_type: + id: type: string - token_type: + name: type: string + permissions: + items: + $ref: '#/definitions/Permission' + type: array type: object - TokenResponse: + ValidateConfigRequest: properties: - access_token: - type: string - expires_in: - type: integer - mfa_token: + config: + additionalProperties: true + type: object + plugin_id: type: string - requires_password_change: - type: boolean - requires_totp: - type: boolean - requires_totp_enrollment: + type: object + ValidateConfigResponse: + properties: + errors: + items: + $ref: '#/definitions/ValidationErrorDetail' + type: array + valid: type: boolean - token_type: - type: string type: object - ToolCall: + ValidationErrorDetail: properties: - duration_ms: - type: integer - ordinal: - type: integer - started_at: - type: string - status: - type: string - target_mrn: + field: type: string - tool_name: + message: type: string type: object - ToolCallPayload: + ValidationErrorResponse: properties: - duration_ms: - type: integer - started_at: + error: type: string - status: + fields: + items: + $ref: '#/definitions/ValidationErrorDetail' + type: array + type: object + domain.AuditEntry: + properties: + action: type: string - target_mrn: + actor: type: string - tool_name: + at: type: string - type: object - TotalAssetsResponse: - properties: - count: - type: integer - type: object - UIConfigResponse: - properties: - allow_unencrypted: - type: boolean - banner: - $ref: '#/definitions/BannerResponse' - default_language: + entity_id: type: string - domain_landing_url: + entity_kind: + type: string + from_domain: + type: string + to_domain: type: string - encryption_configured: - type: boolean - table_preview_enabled: - type: boolean type: object - UpdateAssetRequest: + domain.Domain: properties: + created_at: + type: string + created_by: + type: string + depth: + type: integer description: type: string - environments: - additionalProperties: - $ref: '#/definitions/Environment' - type: object - external_links: - items: - $ref: '#/definitions/AssetExternalLink' - type: array + id: + type: string metadata: - additionalProperties: true + additionalProperties: {} type: object name: type: string - providers: - items: - type: string - type: array - schema: - additionalProperties: - type: string - type: object - sources: - items: - $ref: '#/definitions/AssetSource' - type: array + parent_id: + type: string + path: + type: string + restricted: + type: boolean tags: items: type: string type: array - type: - type: string - user_description: + updated_at: type: string type: object - UpdateAssetRuleRequest: + domain.DomainRef: properties: - description: + id: type: string - is_enabled: - type: boolean - links: - items: - $ref: '#/definitions/AssetRuleExternalLink' - type: array - metadata_field: + path: + description: Path is the chain of names from the root, joined by " / ". type: string - name: + type: object + domain.EnforcementPlan: + properties: + generated_at: type: string - pattern_type: + hash: type: string - pattern_value: + pipelines: + items: + $ref: '#/definitions/domain.PlanPipeline' + type: array + principals: + items: + $ref: '#/definitions/domain.PlanPrincipal' + type: array + state: + $ref: '#/definitions/domain.EnforcementState' + type: object + domain.EnforcementState: + properties: + updated_at: type: string - priority: - type: integer - query_expression: + updated_by: type: string - rule_type: + updated_by_name: + description: |- + UpdatedByName is the user's or service account's name, when the + change was made by one that still exists. type: string - term_ids: - items: - type: string - type: array + write: + type: boolean type: object - UpdateDataProductRequest: + domain.GrantInput: properties: - description: + role: + $ref: '#/definitions/domain.Role' + subject_id: type: string - metadata: - additionalProperties: true + subject_type: + $ref: '#/definitions/domain.SubjectType' + type: object + domain.ImportInput: + properties: + apply: + type: boolean + mapping: + additionalProperties: + type: string type: object - name: + source: type: string - owners: + type: object + domain.ImportReport: + properties: + already_assigned: + type: integer + applied: + type: boolean + mapped: items: - $ref: '#/definitions/DataProductOwnerRequest' + $ref: '#/definitions/domain.ImportValue' type: array - tags: + unmapped: items: - type: string + $ref: '#/definitions/domain.ImportValue' type: array type: object - UpdateMemberRoleRequest: + domain.ImportValue: properties: - role: + count: + type: integer + domain_id: type: string - type: object - UpdatePasswordRequest: - properties: - new_password: - minLength: 8 + kind: + $ref: '#/definitions/domain.Kind' + value: type: string - required: - - new_password type: object - UpdateSSOMappingRequest: + domain.Kind: + enum: + - asset + - data_product + - glossary_term + - ingestion_schedule + type: string + x-enum-varnames: + - KindAsset + - KindDataProduct + - KindGlossaryTerm + - KindIngestionSchedule + domain.PipelineAssignment: properties: - member_role: + assets_in_domain: + type: integer + domain_id: type: string - team_id: + schedule_id: type: string type: object - UpdateScheduleRequest: + domain.PipelineMoveResult: properties: - config: - additionalProperties: true - type: object - cron_expression: + domain_id: type: string - enabled: - type: boolean + moved_assets: + type: integer + type: object + domain.PlanPipeline: + properties: + assets_outside: + type: integer + domain: + $ref: '#/definitions/domain.DomainRef' name: type: string - plugin_id: + schedule_id: type: string type: object - UpdateServiceAccountRequest: + domain.PlanPrincipal: properties: - active: - type: boolean - description: - type: string - name: - type: string - role_ids: + keeps: items: - type: string + $ref: '#/definitions/domain.DomainRef' + type: array + loses: + items: + $ref: '#/definitions/domain.DomainRef' type: array - type: object - UpdateTeamRequest: - properties: - description: - type: string - metadata: - additionalProperties: true - type: object name: type: string - tags: + permissions: items: type: string type: array - type: object - UpdateTermRequest: - properties: - definition: - type: string - description: + subject_id: type: string - metadata: - additionalProperties: true - type: object - name: - type: string - owners: - items: - $ref: '#/definitions/OwnerRequest' - type: array - parent_term_id: - type: string - tags: - description: Absent leaves the stored tags alone; an empty list clears them. - items: - type: string - type: array + subject_type: + $ref: '#/definitions/domain.SubjectType' type: object - UpdateUserInput: + domain.Role: + enum: + - domain_admin + - steward + - reader + type: string + x-enum-varnames: + - RoleDomainAdmin + - RoleSteward + - RoleReader + domain.RoleAssignment: properties: - active: - type: boolean - email: - type: string - name: + created_at: type: string - password: - minLength: 8 + created_by: type: string - preferences: - additionalProperties: true - type: object - profile_picture: + domain_id: type: string - role_names: - items: - type: string - minItems: 1 - type: array - type: object - User: - properties: - active: - type: boolean - created_at: + domain_name: type: string id: type: string - identities: - items: - $ref: '#/definitions/UserIdentity' - type: array - must_change_password: + inherited: type: boolean - name: + role: + $ref: '#/definitions/domain.Role' + subject_id: type: string - preferences: - additionalProperties: true - type: object - profile_picture: + subject_missing: + description: SubjectMissing marks a row whose user, team or service account + was deleted. + type: boolean + subject_name: type: string - roles: + subject_type: + $ref: '#/definitions/domain.SubjectType' + type: object + domain.SubjectType: + enum: + - user + - team + - service_account + type: string + x-enum-varnames: + - SubjectUser + - SubjectTeam + - SubjectServiceAccount + domain.WritableDomains: + properties: + all: + type: boolean + domain_ids: items: - $ref: '#/definitions/UserRole' + type: string type: array - sessions_invalidated_at: - description: Tokens issued before this moment are rejected at validation, - so setting it to now signs the user out of every session at once. - type: string - updated_at: - type: string - username: - type: string + enforced: + type: boolean type: object - UserIdentity: + importer.Action: + enum: + - create + - update + - skip + - error + type: string + x-enum-varnames: + - ActionCreate + - ActionUpdate + - ActionSkip + - ActionError + importer.ColumnInfo: properties: - created_at: - type: string - id: - type: string - provider: - type: string - provider_data: - additionalProperties: true - type: object - provider_email: + format: type: string - provider_user_id: + help: type: string - updated_at: + id: type: string - user_id: + item_type: type: string - type: object - UserRole: - properties: - description: + label: type: string - id: + profile: + type: boolean + required: + type: boolean + separator: type: string - name: + type: type: string - permissions: + validation: + $ref: '#/definitions/metamodel.Constraints' + values: items: - $ref: '#/definitions/Permission' + type: string type: array type: object - ValidateConfigRequest: + importer.Problem: properties: - config: - additionalProperties: true - type: object - plugin_id: + code: type: string - type: object - ValidateConfigResponse: - properties: - errors: - items: - $ref: '#/definitions/ValidationErrorDetail' - type: array - valid: - type: boolean - type: object - ValidationErrorDetail: - properties: - field: + column: type: string message: type: string type: object - ValidationErrorResponse: + importer.Result: properties: - error: - type: string - fields: + applied: + type: boolean + problems: + description: |- + Problems concern the file as a whole, such as a missing column, and + block applying it; Warnings, such as an unknown column, do not. items: - $ref: '#/definitions/ValidationErrorDetail' + $ref: '#/definitions/importer.Problem' + type: array + rows: + items: + $ref: '#/definitions/importer.Row' + type: array + summary: + $ref: '#/definitions/importer.Summary' + warnings: + items: + $ref: '#/definitions/importer.Problem' type: array type: object - domain.AuditEntry: + importer.Row: properties: action: - type: string - actor: - type: string - at: - type: string - entity_id: - type: string - entity_kind: - type: string - from_domain: - type: string - to_domain: - type: string - type: object - domain.Domain: - properties: - created_at: - type: string - created_by: - type: string - depth: + $ref: '#/definitions/importer.Action' + errors: + items: + $ref: '#/definitions/importer.Problem' + type: array + line: type: integer - description: - type: string - id: - type: string - metadata: - additionalProperties: {} - type: object name: type: string - parent_id: - type: string - path: - type: string - restricted: - type: boolean - tags: + warnings: items: - type: string + $ref: '#/definitions/importer.Problem' type: array - updated_at: - type: string - type: object - domain.DomainRef: - properties: - id: - type: string - path: - description: Path is the chain of names from the root, joined by " / ". - type: string type: object - domain.EnforcementPlan: + importer.Summary: properties: - generated_at: - type: string - hash: - type: string - pipelines: - items: - $ref: '#/definitions/domain.PlanPipeline' - type: array - principals: - items: - $ref: '#/definitions/domain.PlanPrincipal' - type: array - state: - $ref: '#/definitions/domain.EnforcementState' - type: object - domain.EnforcementState: - properties: - updated_at: - type: string - updated_by: - type: string - updated_by_name: - description: |- - UpdatedByName is the user's or service account's name, when the - change was made by one that still exists. - type: string - write: - type: boolean - type: object - domain.GrantInput: - properties: - role: - $ref: '#/definitions/domain.Role' - subject_id: - type: string - subject_type: - $ref: '#/definitions/domain.SubjectType' - type: object - domain.ImportInput: - properties: - apply: - type: boolean - mapping: - additionalProperties: - type: string - type: object - source: - type: string - type: object - domain.ImportReport: - properties: - already_assigned: - type: integer - applied: - type: boolean - mapped: - items: - $ref: '#/definitions/domain.ImportValue' - type: array - unmapped: - items: - $ref: '#/definitions/domain.ImportValue' - type: array - type: object - domain.ImportValue: - properties: - count: + create: type: integer - domain_id: - type: string - kind: - $ref: '#/definitions/domain.Kind' - value: - type: string - type: object - domain.Kind: - enum: - - asset - - data_product - - glossary_term - - ingestion_schedule - type: string - x-enum-varnames: - - KindAsset - - KindDataProduct - - KindGlossaryTerm - - KindIngestionSchedule - domain.PipelineAssignment: - properties: - assets_in_domain: + errors: type: integer - domain_id: - type: string - schedule_id: - type: string - type: object - domain.PipelineMoveResult: - properties: - domain_id: - type: string - moved_assets: + skip: type: integer - type: object - domain.PlanPipeline: - properties: - assets_outside: + update: type: integer - domain: - $ref: '#/definitions/domain.DomainRef' - name: - type: string - schedule_id: - type: string type: object - domain.PlanPrincipal: + metamodel.AppliesTo: properties: - keeps: + assetTypes: items: - $ref: '#/definitions/domain.DomainRef' + type: string type: array - loses: + kinds: items: - $ref: '#/definitions/domain.DomainRef' + type: string type: array - name: - type: string - permissions: + termTypes: items: type: string type: array - subject_id: - type: string - subject_type: - $ref: '#/definitions/domain.SubjectType' type: object - domain.Role: - enum: - - domain_admin - - steward - - reader - type: string - x-enum-varnames: - - RoleDomainAdmin - - RoleSteward - - RoleReader - domain.RoleAssignment: + metamodel.Constraints: properties: - created_at: - type: string - created_by: - type: string - domain_id: - type: string - domain_name: - type: string - id: - type: string - inherited: - type: boolean - role: - $ref: '#/definitions/domain.Role' - subject_id: - type: string - subject_missing: - description: SubjectMissing marks a row whose user, team or service account - was deleted. - type: boolean - subject_name: - type: string - subject_type: - $ref: '#/definitions/domain.SubjectType' + maxItems: + type: integer + maxLength: + type: integer + maximum: + type: number + minItems: + type: integer + minLength: + type: integer + minimum: + type: number type: object - domain.SubjectType: - enum: - - user - - team - - service_account - type: string - x-enum-varnames: - - SubjectUser - - SubjectTeam - - SubjectServiceAccount - domain.WritableDomains: + metamodel.Derivation: properties: - all: - type: boolean - domain_ids: - items: + from: + type: string + map: + additionalProperties: type: string - type: array - enforced: - type: boolean + type: object type: object - importer.Action: - enum: - - create - - update - - skip - - error - type: string - x-enum-varnames: - - ActionCreate - - ActionUpdate - - ActionSkip - - ActionError - importer.ColumnInfo: + metamodel.Field: properties: - format: - type: string - help: - type: string + appliesTo: + $ref: '#/definitions/metamodel.AppliesTo' + core: + type: boolean + default: + allOf: + - $ref: '#/definitions/metamodel.Derivation' + description: |- + Default fills an asset field that has no value from the asset's native + type, so every discovery plugin is classified by one table. + derive: + allOf: + - $ref: '#/definitions/metamodel.Derivation' + description: |- + Derive computes an asset field from another enum field of the profile, so + the two can never disagree; writers cannot set it. id: type: string - item_type: - type: string - label: + itemType: type: string - profile: + nullable: type: boolean + presentation: + $ref: '#/definitions/metamodel.Presentation' required: type: boolean - separator: + storage: type: string + system: + description: |- + System marks a field only the platform writes, such as the quality score the audit + computes. The API refuses it with the code `system`, ingestion and whole-asset updates + leave it as it was, and the interface shows it read-only. An asset field bound to metadata. + type: boolean type: type: string validation: @@ -3427,150 +3029,7 @@ definitions: type: string type: array type: object - importer.Problem: - properties: - code: - type: string - column: - type: string - message: - type: string - type: object - importer.Result: - properties: - applied: - type: boolean - problems: - description: |- - Problems concern the file as a whole, such as a missing column, and - block applying it; Warnings, such as an unknown column, do not. - items: - $ref: '#/definitions/importer.Problem' - type: array - rows: - items: - $ref: '#/definitions/importer.Row' - type: array - summary: - $ref: '#/definitions/importer.Summary' - warnings: - items: - $ref: '#/definitions/importer.Problem' - type: array - type: object - importer.Row: - properties: - action: - $ref: '#/definitions/importer.Action' - errors: - items: - $ref: '#/definitions/importer.Problem' - type: array - line: - type: integer - name: - type: string - warnings: - items: - $ref: '#/definitions/importer.Problem' - type: array - type: object - importer.Summary: - properties: - create: - type: integer - errors: - type: integer - skip: - type: integer - update: - type: integer - type: object - metamodel.AppliesTo: - properties: - assetTypes: - items: - type: string - type: array - kinds: - items: - type: string - type: array - termTypes: - items: - type: string - type: array - type: object - metamodel.Constraints: - properties: - maxItems: - type: integer - maxLength: - type: integer - maximum: - type: number - minItems: - type: integer - minLength: - type: integer - minimum: - type: number - type: object - metamodel.Derivation: - properties: - from: - type: string - map: - additionalProperties: - type: string - type: object - type: object - metamodel.Field: - properties: - appliesTo: - $ref: '#/definitions/metamodel.AppliesTo' - core: - type: boolean - default: - allOf: - - $ref: '#/definitions/metamodel.Derivation' - description: |- - Default fills an asset field that has no value from the asset's native - type, so every discovery plugin is classified by one table. - derive: - allOf: - - $ref: '#/definitions/metamodel.Derivation' - description: |- - Derive computes an asset field from another enum field of the profile, so - the two can never disagree; writers cannot set it. - id: - type: string - itemType: - type: string - nullable: - type: boolean - presentation: - $ref: '#/definitions/metamodel.Presentation' - required: - type: boolean - storage: - type: string - system: - description: |- - System marks a field only the platform writes, such as the quality score the audit - computes. The API refuses it with the code `system`, ingestion and whole-asset updates - leave it as it was, and the interface shows it read-only. An asset field bound to metadata. - type: boolean - type: - type: string - validation: - $ref: '#/definitions/metamodel.Constraints' - values: - items: - type: string - type: array - type: object - metamodel.Manual: + metamodel.Manual: properties: provider: type: string @@ -3640,6 +3099,47 @@ definitions: filters keep using the value. type: object type: object + metamodel.QualityRule: + properties: + checks: + items: + $ref: '#/definitions/QualityCondition' + type: array + code: + description: |- + Code is the finding code the audit reports, which clients translate; it defaults to a + snake_case form of the id. + type: string + description: + type: string + descriptionKey: + type: string + dimension: + description: Dimension is the quality dimension whose score the rule's checks + feed. + enum: + - completeness + - validity + - consistency + - timeliness + type: string + id: + type: string + labelKey: + type: string + name: + description: |- + Name and Description are text in the language of whoever wrote the rule. A profile rule + uses LabelKey and DescriptionKey, which resolve through the profile's messages. + type: string + severity: + description: 'Severity is what a finding of the rule counts as: error or warning.' + type: string + when: + items: + $ref: '#/definitions/QualityCondition' + type: array + type: object metamodel.Schema: properties: defaultLocale: @@ -3670,7 +3170,7 @@ definitions: description: QualityRules are the checks the quality audit applies on top of the fields' own validation. items: - $ref: '#/definitions/QualityRule' + $ref: '#/definitions/metamodel.QualityRule' type: array version: type: integer @@ -3823,56 +3323,6 @@ definitions: pattern: type: string type: object - quality.RuleID: - enum: - - required - - validation - - externalLinkInvalid - - externalLinkEmpty - type: string - x-enum-varnames: - - RuleRequired - - RuleValidation - - RuleExternalLinkInvalid - - RuleExternalLinkEmpty - quality.RuleSource: - enum: - - builtin - - profile - - custom - type: string - x-enum-varnames: - - SourceBuiltin - - SourceProfile - - SourceCustom - quality.RunStatus: - enum: - - running - - succeeded - - failed - type: string - x-enum-varnames: - - RunRunning - - RunSucceeded - - RunFailed - quality.Severity: - enum: - - error - - warning - type: string - x-enum-varnames: - - SeverityError - - SeverityWarning - quality.Status: - enum: - - compliant - - warning - - noncompliant - type: string - x-enum-varnames: - - StatusCompliant - - StatusWarning - - StatusNoncompliant v1_assets.patchFieldsRequest: properties: fields: @@ -4073,676 +3523,158 @@ paths: schema: $ref: '#/definitions/ErrorResponse' "403": - description: Forbidden - schema: - $ref: '#/definitions/ErrorResponse' - "409": - description: Conflict - schema: - $ref: '#/definitions/ErrorResponse' - "503": - description: Service Unavailable - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Start search reindex - tags: - - admin - /api/v1/agents/{asset_id}/activity: - get: - operationId: getAgentsAssetIDActivity - parameters: - - description: Agent asset id - in: path - name: asset_id - required: true - type: string - - description: Lookback window (e.g. 24h, 7d). Default 24h. - in: query - name: period - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/ActivityResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Agent activity - tags: - - agents - /api/v1/agents/{asset_id}/runs: - get: - operationId: getAgentsAssetIDRuns - parameters: - - description: Agent asset id - in: path - name: asset_id - required: true - type: string - - description: Lookback window (e.g. 24h, 7d). Default 24h. - in: query - name: period - type: string - - description: Max number of runs to return - in: query - name: limit - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/RunsResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: List agent runs - tags: - - agents - /api/v1/agents/{asset_id}/stats: - get: - operationId: getAgentsAssetIDStats - parameters: - - description: Agent asset id - in: path - name: asset_id - required: true - type: string - - description: Lookback window (e.g. 24h, 7d). Default 24h. - in: query - name: period - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/Stats' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Agent stats - tags: - - agents - /api/v1/agents/runs: - post: - consumes: - - application/json - operationId: postAgentsRuns - parameters: - - description: Agent run record - in: body - name: request - required: true - schema: - $ref: '#/definitions/RecordRunRequest' - produces: - - application/json - responses: - "201": - description: Created - schema: - $ref: '#/definitions/AgentRun' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Record agent run - tags: - - agents - /api/v1/asset-rules/: - post: - consumes: - - application/json - description: Create a new asset rule that applies enrichments to matching assets - operationId: postAssetRules - parameters: - - description: Asset rule creation request - in: body - name: rule - required: true - schema: - $ref: '#/definitions/CreateAssetRuleRequest' - produces: - - application/json - responses: - "201": - description: Created - schema: - $ref: '#/definitions/AssetRule' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "409": - description: Conflict - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Create an asset rule - tags: - - asset-rules - /api/v1/asset-rules/{id}: - delete: - description: Delete an asset rule by ID - operationId: deleteAssetRulesID - parameters: - - description: Asset rule ID - in: path - name: id - required: true - type: string - responses: - "204": - description: No Content - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Delete an asset rule - tags: - - asset-rules - get: - description: Get an asset rule by ID - operationId: getAssetRulesID - parameters: - - description: Asset rule ID - in: path - name: id - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/AssetRule' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Get an asset rule - tags: - - asset-rules - put: - consumes: - - application/json - description: Update an existing asset rule - operationId: putAssetRulesID - parameters: - - description: Asset rule ID - in: path - name: id - required: true - type: string - - description: Asset rule update request - in: body - name: rule - required: true - schema: - $ref: '#/definitions/UpdateAssetRuleRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/AssetRule' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "409": - description: Conflict - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Update an asset rule - tags: - - asset-rules - /api/v1/asset-rules/assets/{id}: - get: - description: Get the list of asset IDs matched by an asset rule - operationId: getAssetRulesAssetsID - parameters: - - description: Asset rule ID - in: path - name: id - required: true - type: string - - default: 50 - description: Number of items to return - in: query - name: limit - type: integer - - default: 0 - description: Number of items to skip - in: query - name: offset - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - additionalProperties: true - type: object - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Get assets matched by a rule - tags: - - asset-rules - /api/v1/asset-rules/list: - get: - description: List all asset rules with pagination - operationId: getAssetRulesList - parameters: - - default: 50 - description: Number of items to return - in: query - name: limit - type: integer - - default: 0 - description: Number of items to skip - in: query - name: offset - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/AssetRuleListResult' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: List asset rules - tags: - - asset-rules - /api/v1/asset-rules/preview: - post: - consumes: - - application/json - description: Preview which assets would match a rule configuration - operationId: postAssetRulesPreview - parameters: - - description: Rule preview request - in: body - name: rule - required: true - schema: - $ref: '#/definitions/PreviewRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/RulePreview' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Preview an asset rule - tags: - - asset-rules - /api/v1/asset-rules/search: - get: - description: Search asset rules by name - operationId: getAssetRulesSearch - parameters: - - description: Search query - in: query - name: query - type: string - - default: 50 - description: Number of items to return - in: query - name: limit - type: integer - - default: 0 - description: Number of items to skip - in: query - name: offset - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/AssetRuleListResult' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Search asset rules - tags: - - asset-rules - /api/v1/assets/: - post: - consumes: - - application/json - description: Create a new asset in the system - operationId: postAssets - parameters: - - description: Asset creation request - in: body - name: asset - required: true - schema: - $ref: '#/definitions/CreateAssetRequest' - produces: - - application/json - responses: - "201": - description: Created - schema: - $ref: '#/definitions/Asset' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/ErrorResponse' - "409": - description: Conflict - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Create a new asset - tags: - - assets - /api/v1/assets/{id}: - delete: - consumes: - - application/json - description: Delete an asset from the system - operationId: deleteAssetsID - parameters: - - description: Asset ID - in: path - name: id - required: true - type: string - produces: - - application/json - responses: - "204": - description: No Content - "404": - description: Not Found + description: Forbidden schema: $ref: '#/definitions/ErrorResponse' "409": description: Conflict schema: $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + "503": + description: Service Unavailable schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete an asset + summary: Start search reindex tags: - - assets + - admin + /api/v1/agents/{asset_id}/activity: get: - consumes: - - application/json - description: Get detailed information about a specific asset - operationId: getAssetsID + operationId: getAgentsAssetIDActivity parameters: - - description: Asset ID + - description: Agent asset id in: path - name: id + name: asset_id required: true type: string + - description: Lookback window (e.g. 24h, 7d). Default 24h. + in: query + name: period + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/Asset' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/ActivityResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get an asset by ID + summary: Agent activity tags: - - assets - patch: - consumes: - - application/json - description: Partial update of governed fields. Absence preserves; null deletes - only when the field is nullable. Requires If-Match. - operationId: patchAssetsID + - agents + /api/v1/agents/{asset_id}/runs: + get: + operationId: getAgentsAssetIDRuns parameters: - - description: Asset ID + - description: Agent asset id in: path - name: id + name: asset_id required: true type: string - - description: Expected asset version - in: header - name: If-Match - required: true + - description: Lookback window (e.g. 24h, 7d). Default 24h. + in: query + name: period type: string - - description: Fields to apply - in: body - name: request - required: true - schema: - $ref: '#/definitions/v1_assets.patchFieldsRequest' + - description: Max number of runs to return + in: query + name: limit + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/Asset' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "412": - description: Precondition Failed - schema: - $ref: '#/definitions/ErrorResponse' - "428": - description: Precondition Required - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/RunsResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Patch governed asset fields + summary: List agent runs tags: - - assets - put: - consumes: - - application/json - description: Update an existing asset's information - operationId: putAssetsID + - agents + /api/v1/agents/{asset_id}/stats: + get: + operationId: getAgentsAssetIDStats parameters: - - description: Asset ID + - description: Agent asset id in: path - name: id + name: asset_id required: true type: string - - description: Asset update request - in: body - name: asset - required: true - schema: - $ref: '#/definitions/UpdateAssetRequest' + - description: Lookback window (e.g. 24h, 7d). Default 24h. + in: query + name: period + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/Asset' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/Stats' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Update an asset + summary: Agent stats tags: - - assets - /api/v1/assets/by-glossary-term/{term_id}: - get: - description: Retrieve all assets associated with a specific glossary term - operationId: getAssetsByGlossaryTermTermID + - agents + /api/v1/agents/runs: + post: + consumes: + - application/json + operationId: postAgentsRuns parameters: - - description: Glossary Term ID - in: path - name: term_id + - description: Agent run record + in: body + name: request required: true - type: string - - default: 20 - description: Maximum number of assets - in: query - name: limit - type: integer - - default: 0 - description: Pagination offset - in: query - name: offset - type: integer + schema: + $ref: '#/definitions/RecordRunRequest' produces: - application/json responses: - "200": - description: OK - schema: - additionalProperties: true - type: object - "500": - description: Internal Server Error + "201": + description: Created schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/AgentRun' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get assets by glossary term + summary: Record agent run tags: - - assets - /api/v1/assets/documentation/: + - agents + /api/v1/asset-rules/: post: consumes: - application/json - description: Create or update documentation for an asset - operationId: postAssetsDocumentation + description: Create a new asset rule that applies enrichments to matching assets + operationId: postAssetRules parameters: - - description: Documentation creation request + - description: Asset rule creation request in: body - name: request + name: rule required: true schema: - $ref: '#/definitions/DocumentationCreateRequest' + $ref: '#/definitions/CreateAssetRuleRequest' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/Documentation' + $ref: '#/definitions/AssetRule' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -4750,18 +3682,43 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Create asset documentation + summary: Create an asset rule tags: - - assets - /api/v1/assets/documentation/{mrn}: + - asset-rules + /api/v1/asset-rules/{id}: + delete: + description: Delete an asset rule by ID + operationId: deleteAssetRulesID + parameters: + - description: Asset rule ID + in: path + name: id + required: true + type: string + responses: + "204": + description: No Content + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: Delete an asset rule + tags: + - asset-rules get: - description: Get documentation for a specific asset - operationId: getAssetsDocumentationMrn + description: Get an asset rule by ID + operationId: getAssetRulesID parameters: - - description: Asset MRN - format: url + - description: Asset rule ID in: path - name: mrn + name: id required: true type: string produces: @@ -4770,9 +3727,7 @@ paths: "200": description: OK schema: - items: - $ref: '#/definitions/Documentation' - type: array + $ref: '#/definitions/AssetRule' "404": description: Not Found schema: @@ -4784,33 +3739,45 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get asset documentation + summary: Get an asset rule tags: - - assets - /api/v1/assets/documentation/batch: - post: + - asset-rules + put: consumes: - application/json - description: Create or update documentation for multiple assets - operationId: postAssetsDocumentationBatch + description: Update an existing asset rule + operationId: putAssetRulesID parameters: - - description: Batch documentation request + - description: Asset rule ID + in: path + name: id + required: true + type: string + - description: Asset rule update request in: body - name: request + name: rule required: true schema: - $ref: '#/definitions/BatchDocumentationRequest' + $ref: '#/definitions/UpdateAssetRuleRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/BatchDocumentationResponse' + $ref: '#/definitions/AssetRule' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -4818,36 +3785,37 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Batch create documentation + summary: Update an asset rule tags: - - assets - /api/v1/assets/lookup/{type}/{service}/{name}: + - asset-rules + /api/v1/asset-rules/assets/{id}: get: - description: Get an asset by its type, service (provider), and name - operationId: getAssetsLookupTypeServiceName + description: Get the list of asset IDs matched by an asset rule + operationId: getAssetRulesAssetsID parameters: - - description: Asset type - in: path - name: type - required: true - type: string - - description: Service/Provider name - in: path - name: service - required: true - type: string - - description: Asset name + - description: Asset rule ID in: path - name: name + name: id required: true type: string + - default: 50 + description: Number of items to return + in: query + name: limit + type: integer + - default: 0 + description: Number of items to skip + in: query + name: offset + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/Asset' + additionalProperties: true + type: object "404": description: Not Found schema: @@ -4859,37 +3827,31 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Lookup asset by type, service, and name + summary: Get assets matched by a rule tags: - - assets - /api/v1/assets/match-pattern/: + - asset-rules + /api/v1/asset-rules/list: get: - description: Find assets matching a pattern - operationId: getAssetsMatchPattern + description: List all asset rules with pagination + operationId: getAssetRulesList parameters: - - description: Asset pattern to match + - default: 50 + description: Number of items to return in: query - name: pattern - required: true - type: string - - description: Asset type + name: limit + type: integer + - default: 0 + description: Number of items to skip in: query - name: type - required: true - type: string + name: offset + type: integer produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/Asset' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/AssetRuleListResult' "500": description: Internal Server Error schema: @@ -4897,33 +3859,31 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Match asset pattern + summary: List asset rules tags: - - assets - /api/v1/assets/my-assets: - get: - description: Get assets owned by the current user or their teams - operationId: getAssetsMyAssets + - asset-rules + /api/v1/asset-rules/preview: + post: + consumes: + - application/json + description: Preview which assets would match a rule configuration + operationId: postAssetRulesPreview parameters: - - default: 20 - description: Limit - in: query - name: limit - type: integer - - default: 0 - description: Offset - in: query - name: offset - type: integer + - description: Rule preview request + in: body + name: rule + required: true + schema: + $ref: '#/definitions/PreviewRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/AssetSearchResponse' - "401": - description: Unauthorized + $ref: '#/definitions/RulePreview' + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' "500": @@ -4933,92 +3893,89 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get user's assets + summary: Preview an asset rule tags: - - assets - /api/v1/assets/preview/{id}: + - asset-rules + /api/v1/asset-rules/search: get: - description: Fetches sample data from the asset's data source. Requires assets:preview - permission. - operationId: getAssetsPreviewID + description: Search asset rules by name + operationId: getAssetRulesSearch parameters: - - description: Asset ID - in: path - name: id - required: true + - description: Search query + in: query + name: query type: string + - default: 50 + description: Number of items to return + in: query + name: limit + type: integer + - default: 0 + description: Number of items to skip + in: query + name: offset + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/PreviewResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "403": - description: Missing assets:preview permission - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/AssetRuleListResult' "500": description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' - "501": - description: Data preview not supported for this asset - schema: - $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get preview data for an asset + summary: Search asset rules tags: - - assets - /api/v1/assets/qualified-name/{name}: - get: + - asset-rules + /api/v1/assets/: + post: consumes: - application/json - description: Get detailed information about a specific asset using its qualified - name - operationId: getAssetsQualifiedNameQualifiedName + description: Create a new asset in the system + operationId: postAssets parameters: - - description: Asset qualified name - in: path - name: name + - description: Asset creation request + in: body + name: asset required: true - type: string + schema: + $ref: '#/definitions/CreateAssetRequest' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: $ref: '#/definitions/Asset' - "404": - description: Not Found + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' + "409": + description: Conflict schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get an asset by qualified name + summary: Create a new asset tags: - assets - /api/v1/assets/references/{id}: - get: - description: For each profile field with the asset control, the assets whose - value names this asset (for example, the rules that apply to a table). - operationId: getAssetReferences + /api/v1/assets/{id}: + delete: + consumes: + - application/json + description: Delete an asset from the system + operationId: deleteAssetsID parameters: - description: Asset ID in: path @@ -5028,16 +3985,16 @@ paths: produces: - application/json responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/AssetReferences' - type: array + "204": + description: No Content "404": description: Not Found schema: $ref: '#/definitions/ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -5045,31 +4002,29 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Assets pointing at an asset + summary: Delete an asset tags: - assets - /api/v1/assets/refs: get: - description: The assets with the given IDs, for showing asset-control values - by name. Unknown IDs are left out. - operationId: getAssetRefs + consumes: + - application/json + description: Get detailed information about a specific asset + operationId: getAssetsID parameters: - - description: Comma-separated asset IDs (at most 100) - in: query - name: ids + - description: Asset ID + in: path + name: id required: true type: string produces: - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/AssetRef' - type: array - "400": - description: Bad Request + responses: + "200": + description: OK + schema: + $ref: '#/definitions/Asset' + "404": + description: Not Found schema: $ref: '#/definitions/ErrorResponse' "500": @@ -5079,31 +4034,39 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Resolve asset IDs + summary: Get an asset by ID tags: - assets - /api/v1/assets/run-history-histogram/{id}: - get: - description: Get histogram data for asset run history over specified period - operationId: getAssetsIDRunHistoryHistogram + patch: + consumes: + - application/json + description: Partial update of governed fields. Absence preserves; null deletes + only when the field is nullable. Requires If-Match. + operationId: patchAssetsID parameters: - description: Asset ID in: path name: id required: true type: string - - default: 30d - description: Time period (7d, 30d, 90d) - in: query - name: period + - description: Expected asset version + in: header + name: If-Match + required: true type: string + - description: Fields to apply + in: body + name: request + required: true + schema: + $ref: '#/definitions/v1_assets.patchFieldsRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/HistogramResponse' + $ref: '#/definitions/Asset' "400": description: Bad Request schema: @@ -5112,43 +4075,44 @@ paths: description: Not Found schema: $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + "412": + description: Precondition Failed + schema: + $ref: '#/definitions/ErrorResponse' + "428": + description: Precondition Required schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get asset run history histogram + summary: Patch governed asset fields tags: - assets - /api/v1/assets/run-history/{id}: - get: - description: Get paginated run history for a specific asset - operationId: getAssetsIDRunHistory + put: + consumes: + - application/json + description: Update an existing asset's information + operationId: putAssetsID parameters: - description: Asset ID in: path name: id required: true type: string - - default: 10 - description: Number of items per page - in: query - name: limit - type: integer - - default: 0 - description: Number of items to skip - in: query - name: offset - type: integer + - description: Asset update request + in: body + name: asset + required: true + schema: + $ref: '#/definitions/UpdateAssetRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/RunHistoryResponse' + $ref: '#/definitions/Asset' "400": description: Bad Request schema: @@ -5164,67 +4128,37 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get asset run history + summary: Update an asset tags: - assets - /api/v1/assets/search: + /api/v1/assets/by-glossary-term/{term_id}: get: - consumes: - - application/json - description: Search for assets using query string and filters - operationId: getAssetsSearch + description: Retrieve all assets associated with a specific glossary term + operationId: getAssetsByGlossaryTermTermID parameters: - - description: Search query - in: query - name: q + - description: Glossary Term ID + in: path + name: term_id + required: true type: string - - collectionFormat: csv - description: Filter by asset types - in: query - items: - type: string - name: types - type: array - - collectionFormat: csv - description: Filter by services - in: query - items: - type: string - name: services - type: array - - collectionFormat: csv - description: Filter by tags - in: query - items: - type: string - name: tags - type: array - - default: 50 - description: Number of items to return + - default: 20 + description: Maximum number of assets in: query name: limit type: integer - default: 0 - description: Number of items to skip + description: Pagination offset in: query name: offset type: integer - - default: false - description: Calculate filter counts - in: query - name: calculateCounts - type: boolean produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/AssetSearchResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' + additionalProperties: true + type: object "500": description: Internal Server Error schema: @@ -5232,60 +4166,29 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Search assets + summary: Get assets by glossary term tags: - assets - /api/v1/assets/suggestions/metadata/fields: - get: - description: Get suggestions for metadata fields and their types - operationId: getAssetsSuggestionsMetadataFields - produces: + /api/v1/assets/documentation/: + post: + consumes: - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/MetadataFieldSuggestion' - type: array - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Get metadata field suggestions - tags: - - assets - /api/v1/assets/suggestions/metadata/values: - get: - description: Get suggestions for values of a specific metadata field - operationId: getAssetsSuggestionsMetadataValues + description: Create or update documentation for an asset + operationId: postAssetsDocumentation parameters: - - description: Metadata field name - in: query - name: field + - description: Documentation creation request + in: body + name: request required: true - type: string - - description: Value prefix to filter by - in: query - name: prefix - type: string - - default: 10 - description: Maximum number of suggestions - in: query - name: limit - type: integer + schema: + $ref: '#/definitions/DocumentationCreateRequest' produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/MetadataValueSuggestion' - type: array + $ref: '#/definitions/Documentation' "400": description: Bad Request schema: @@ -5297,23 +4200,20 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get metadata value suggestions + summary: Create asset documentation tags: - assets - /api/v1/assets/suggestions/tags: + /api/v1/assets/documentation/{mrn}: get: - description: Get suggestions for asset tags - operationId: getAssetsSuggestionsTags + description: Get documentation for a specific asset + operationId: getAssetsDocumentationMrn parameters: - - description: Tag prefix to filter by - in: query - name: prefix + - description: Asset MRN + format: url + in: path + name: mrn + required: true type: string - - default: 10 - description: Maximum number of suggestions - in: query - name: limit - type: integer produces: - application/json responses: @@ -5321,31 +4221,12 @@ paths: description: OK schema: items: - type: string + $ref: '#/definitions/Documentation' type: array - "500": - description: Internal Server Error + "404": + description: Not Found schema: $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Get tag suggestions - tags: - - assets - /api/v1/assets/summary: - get: - consumes: - - application/json - description: Get the total count of assets by type - operationId: getAssetsSummary - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/AssetSummaryResponse' "500": description: Internal Server Error schema: @@ -5353,65 +4234,63 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get asset summary + summary: Get asset documentation tags: - assets - /api/v1/assets/tags/{id}: - delete: + /api/v1/assets/documentation/batch: + post: consumes: - application/json - description: Remove a tag from an existing asset - operationId: deleteAssetsTagsID + description: Create or update documentation for multiple assets + operationId: postAssetsDocumentationBatch parameters: - - description: Asset ID - in: path - name: id - required: true - type: string - - description: Tag to remove + - description: Batch documentation request in: body - name: tag + name: request required: true schema: - $ref: '#/definitions/TagRequest' + $ref: '#/definitions/BatchDocumentationRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/Asset' + $ref: '#/definitions/BatchDocumentationResponse' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Remove tag from asset + summary: Batch create documentation tags: - assets - post: - consumes: - - application/json - description: Add a new tag to an existing asset - operationId: postAssetsTagsID + /api/v1/assets/lookup/{type}/{service}/{name}: + get: + description: Get an asset by its type, service (provider), and name + operationId: getAssetsLookupTypeServiceName parameters: - - description: Asset ID + - description: Asset type in: path - name: id + name: type required: true type: string - - description: Tag to add - in: body - name: tag + - description: Service/Provider name + in: path + name: service required: true - schema: - $ref: '#/definitions/TagRequest' + type: string + - description: Asset name + in: path + name: name + required: true + type: string produces: - application/json responses: @@ -5419,38 +4298,35 @@ paths: description: OK schema: $ref: '#/definitions/Asset' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Add tag to asset + summary: Lookup asset by type, service, and name tags: - assets - /api/v1/assets/terms/{id}: - delete: - consumes: - - application/json - description: Remove a glossary term association from an asset - operationId: deleteAssetsTermsID + /api/v1/assets/match-pattern/: + get: + description: Find assets matching a pattern + operationId: getAssetsMatchPattern parameters: - - description: Asset ID - in: path - name: id + - description: Asset pattern to match + in: query + name: pattern required: true type: string - - description: Term ID to remove - in: body - name: term + - description: Asset type + in: query + name: type required: true - schema: - $ref: '#/definitions/RemoveTermRequest' + type: string produces: - application/json responses: @@ -5458,98 +4334,114 @@ paths: description: OK schema: items: - $ref: '#/definitions/AssetTerm' + $ref: '#/definitions/Asset' type: array "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Remove glossary term from asset + summary: Match asset pattern tags: - assets + /api/v1/assets/my-assets: get: - description: Retrieve all glossary terms associated with an asset - operationId: getAssetsTermsID + description: Get assets owned by the current user or their teams + operationId: getAssetsMyAssets parameters: - - description: Asset ID - in: path - name: id - required: true - type: string + - default: 20 + description: Limit + in: query + name: limit + type: integer + - default: 0 + description: Offset + in: query + name: offset + type: integer produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/AssetTerm' - type: array - "404": - description: Not Found + $ref: '#/definitions/AssetSearchResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get asset's glossary terms + summary: Get user's assets tags: - assets - post: - consumes: - - application/json - description: Associate one or more glossary terms with an asset - operationId: postAssetsTermsID + /api/v1/assets/preview/{id}: + get: + description: Fetches sample data from the asset's data source. Requires assets:preview + permission. + operationId: getAssetsPreviewID parameters: - description: Asset ID in: path name: id required: true type: string - - description: Term IDs to add - in: body - name: terms - required: true - schema: - $ref: '#/definitions/AddTermsRequest' produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/AssetTerm' - type: array + $ref: '#/definitions/PreviewResponse' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' + "403": + description: Missing assets:preview permission + schema: + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' + "501": + description: Data preview not supported for this asset + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Add glossary terms to asset + summary: Get preview data for an asset tags: - assets - /api/v1/domains: + /api/v1/assets/qualified-name/{name}: get: - description: Lists the root domains, or the direct children of parent_id. - operationId: listDomains + consumes: + - application/json + description: Get detailed information about a specific asset using its qualified + name + operationId: getAssetsQualifiedNameQualifiedName parameters: - - description: Parent domain ID - in: query - name: parent_id + - description: Asset qualified name + in: path + name: name + required: true type: string produces: - application/json @@ -5557,63 +4449,64 @@ paths: "200": description: OK schema: - items: - $ref: '#/definitions/domain.Domain' - type: array + $ref: '#/definitions/Asset' "404": description: Not Found schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List domains + summary: Get an asset by qualified name tags: - - domains - post: - consumes: - - application/json - operationId: createDomain + - assets + /api/v1/assets/references/{id}: + get: + description: For each profile field with the asset control, the assets whose + value names this asset (for example, the rules that apply to a table). + operationId: getAssetReferences parameters: - - description: Domain; parent_id null creates a root - in: body - name: domain + - description: Asset ID + in: path + name: id required: true - schema: - $ref: '#/definitions/v1_domains.CreateRequest' + type: string produces: - application/json responses: - "201": - description: Created - schema: - $ref: '#/definitions/domain.Domain' - "400": - description: Bad Request + "200": + description: OK schema: - $ref: '#/definitions/DomainErrorResponse' + items: + $ref: '#/definitions/AssetReferences' + type: array "404": description: Not Found schema: - $ref: '#/definitions/DomainErrorResponse' - "409": - description: Conflict + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Create a domain + summary: Assets pointing at an asset tags: - - domains - /api/v1/domains/{id}: - delete: - description: Only an empty domain without subdomains can be deleted. - operationId: deleteDomain + - assets + /api/v1/assets/refs: + get: + description: The assets with the given IDs, for showing asset-control values + by name. Unknown IDs are left out. + operationId: getAssetRefs parameters: - - description: Domain ID - in: path - name: id + - description: Comma-separated asset IDs (at most 100) + in: query + name: ids required: true type: string produces: @@ -5622,302 +4515,392 @@ paths: "200": description: OK schema: - additionalProperties: - type: string - type: object - "404": - description: Not Found + items: + $ref: '#/definitions/AssetRef' + type: array + "400": + description: Bad Request schema: - $ref: '#/definitions/DomainErrorResponse' - "409": - description: Conflict + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete a domain + summary: Resolve asset IDs tags: - - domains + - assets + /api/v1/assets/run-history-histogram/{id}: get: - operationId: getDomain + description: Get histogram data for asset run history over specified period + operationId: getAssetsIDRunHistoryHistogram parameters: - - description: Domain ID + - description: Asset ID in: path name: id required: true type: string + - default: 30d + description: Time period (7d, 30d, 90d) + in: query + name: period + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.Domain' + $ref: '#/definitions/HistogramResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get a domain + summary: Get asset run history histogram tags: - - domains - put: - consumes: - - application/json - description: Changes only the fields present in the body. - operationId: updateDomain + - assets + /api/v1/assets/run-history/{id}: + get: + description: Get paginated run history for a specific asset + operationId: getAssetsIDRunHistory parameters: - - description: Domain ID + - description: Asset ID in: path name: id required: true type: string - - description: Fields to change - in: body - name: domain - required: true - schema: - $ref: '#/definitions/v1_domains.UpdateRequest' + - default: 10 + description: Number of items per page + in: query + name: limit + type: integer + - default: 0 + description: Number of items to skip + in: query + name: offset + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.Domain' + $ref: '#/definitions/RunHistoryResponse' "400": description: Bad Request schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/DomainErrorResponse' - "409": - description: Conflict + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Update a domain + summary: Get asset run history tags: - - domains - /api/v1/domains/{id}/members: - put: + - assets + /api/v1/assets/search: + get: consumes: - application/json - description: Sets the owning domain of every listed entity, all or none. Requires - the entity kind's manage permission and, under write enforcement, write access - to both the current and the target domain. Every change is audited. - operationId: assignDomainMembers + description: Search for assets using query string and filters + operationId: getAssetsSearch parameters: - - description: Domain ID - in: path - name: id - required: true + - description: Search query + in: query + name: q type: string - - description: Entities to assign - in: body - name: members - required: true - schema: - $ref: '#/definitions/v1_domains.MembersRequest' + - collectionFormat: csv + description: Filter by asset types + in: query + items: + type: string + name: types + type: array + - collectionFormat: csv + description: Filter by services + in: query + items: + type: string + name: services + type: array + - collectionFormat: csv + description: Filter by tags + in: query + items: + type: string + name: tags + type: array + - default: 50 + description: Number of items to return + in: query + name: limit + type: integer + - default: 0 + description: Number of items to skip + in: query + name: offset + type: integer + - default: false + description: Calculate filter counts + in: query + name: calculateCounts + type: boolean produces: - application/json responses: "200": description: OK schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/AssetSearchResponse' "400": description: Bad Request schema: - $ref: '#/definitions/DomainErrorResponse' - "403": - description: Forbidden - schema: - $ref: '#/definitions/DomainErrorResponse' - "404": - description: Not Found + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Assign entities to a domain + summary: Search assets tags: - - domains - /api/v1/domains/{id}/move: - post: - consumes: + - assets + /api/v1/assets/suggestions/metadata/fields: + get: + description: Get suggestions for metadata fields and their types + operationId: getAssetsSuggestionsMetadataFields + produces: - application/json - description: Moves the domain and its whole subtree under a new parent. - operationId: moveDomain + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/MetadataFieldSuggestion' + type: array + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: Get metadata field suggestions + tags: + - assets + /api/v1/assets/suggestions/metadata/values: + get: + description: Get suggestions for values of a specific metadata field + operationId: getAssetsSuggestionsMetadataValues parameters: - - description: Domain ID - in: path - name: id + - description: Metadata field name + in: query + name: field required: true type: string - - description: New parent - in: body - name: move - required: true - schema: - $ref: '#/definitions/v1_domains.MoveRequest' + - description: Value prefix to filter by + in: query + name: prefix + type: string + - default: 10 + description: Maximum number of suggestions + in: query + name: limit + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.Domain' + items: + $ref: '#/definitions/MetadataValueSuggestion' + type: array "400": description: Bad Request schema: - $ref: '#/definitions/DomainErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/DomainErrorResponse' - "409": - description: Conflict + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Move a domain + summary: Get metadata value suggestions tags: - - domains - /api/v1/domains/{id}/roles: - delete: - operationId: revokeDomainRole + - assets + /api/v1/assets/suggestions/tags: + get: + description: Get suggestions for asset tags + operationId: getAssetsSuggestionsTags parameters: - - description: Domain ID - in: path - name: id - required: true - type: string - - description: Role assignment ID + - description: Tag prefix to filter by in: query - name: assignment_id - required: true + name: prefix type: string + - default: 10 + description: Maximum number of suggestions + in: query + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + type: string + type: array + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: Get tag suggestions + tags: + - assets + /api/v1/assets/summary: + get: + consumes: + - application/json + description: Get the total count of assets by type + operationId: getAssetsSummary produces: - application/json responses: "200": description: OK schema: - additionalProperties: - type: string - type: object - "403": - description: Forbidden - schema: - $ref: '#/definitions/DomainErrorResponse' - "404": - description: Not Found + $ref: '#/definitions/AssetSummaryResponse' + "500": + description: Internal Server Error schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Revoke a role on a domain + summary: Get asset summary tags: - - domains - get: - description: Includes the assignments inherited from its ancestors, marked inherited. - operationId: listDomainRoles + - assets + /api/v1/assets/tags/{id}: + delete: + consumes: + - application/json + description: Remove a tag from an existing asset + operationId: deleteAssetsTagsID parameters: - - description: Domain ID + - description: Asset ID in: path name: id required: true type: string + - description: Tag to remove + in: body + name: tag + required: true + schema: + $ref: '#/definitions/TagRequest' produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/domain.RoleAssignment' - type: array + $ref: '#/definitions/Asset' + "400": + description: Bad Request + schema: + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List a domain's role assignments + summary: Remove tag from asset tags: - - domains + - assets post: consumes: - application/json - description: Needs domain_admin on the domain or an ancestor, or global scope. - The role applies to the whole subtree. - operationId: grantDomainRole + description: Add a new tag to an existing asset + operationId: postAssetsTagsID parameters: - - description: Domain ID + - description: Asset ID in: path name: id required: true type: string - - description: Subject and role + - description: Tag to add in: body - name: grant + name: tag required: true schema: - $ref: '#/definitions/domain.GrantInput' + $ref: '#/definitions/TagRequest' produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/domain.RoleAssignment' + $ref: '#/definitions/Asset' "400": description: Bad Request schema: - $ref: '#/definitions/DomainErrorResponse' - "403": - description: Forbidden - schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/DomainErrorResponse' - "409": - description: Conflict - schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Grant a role on a domain + summary: Add tag to asset tags: - - domains - /api/v1/domains/{id}/tree: - get: - description: Returns the domain and all its descendants, shallowest first. - operationId: getDomainTree + - assets + /api/v1/assets/terms/{id}: + delete: + consumes: + - application/json + description: Remove a glossary term association from an asset + operationId: deleteAssetsTermsID parameters: - - description: Domain ID + - description: Asset ID in: path name: id required: true type: string + - description: Term ID to remove + in: body + name: term + required: true + schema: + $ref: '#/definitions/RemoveTermRequest' produces: - application/json responses: @@ -5925,30 +4908,27 @@ paths: description: OK schema: items: - $ref: '#/definitions/domain.Domain' + $ref: '#/definitions/AssetTerm' type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get a domain subtree + summary: Remove glossary term from asset tags: - - domains - /api/v1/domains/audit/{kind}/{id}: + - assets get: - description: Every change of domain recorded for an entity, oldest first. Kind - is asset, data_product, glossary_term, ingestion_schedule or domain. - operationId: getDomainAuditLog + description: Retrieve all glossary terms associated with an asset + operationId: getAssetsTermsID parameters: - - description: Entity kind - in: path - name: kind - required: true - type: string - - description: Entity ID + - description: Asset ID in: path name: id required: true @@ -5960,189 +4940,159 @@ paths: description: OK schema: items: - $ref: '#/definitions/domain.AuditEntry' + $ref: '#/definitions/AssetTerm' type: array + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get an entity's domain history + summary: Get asset's glossary terms tags: - - domains - /api/v1/domains/capabilities: - get: - description: Informative, for hiding actions in a UI; the server checks every - operation again. Pass domain_id, or kind and id of an entity to use its domain. - operationId: getDomainCapabilities + - assets + post: + consumes: + - application/json + description: Associate one or more glossary terms with an asset + operationId: postAssetsTermsID parameters: - - description: Domain ID - in: query - name: domain_id - type: string - - description: Entity kind - enum: - - asset - - data_product - - glossary_term - - ingestion_schedule - in: query - name: kind - type: string - - description: Entity ID - in: query + - description: Asset ID + in: path name: id + required: true type: string + - description: Term IDs to add + in: body + name: terms + required: true + schema: + $ref: '#/definitions/AddTermsRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/v1_domains.Capabilities' + items: + $ref: '#/definitions/AssetTerm' + type: array "400": description: Bad Request schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/DomainErrorResponse' + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: What the caller may do in a domain + summary: Add glossary terms to asset tags: - - domains - /api/v1/domains/enforcement: + - assets + /api/v1/domains: get: - description: Whether writes are scoped by domain. Off, native RBAC alone decides. - operationId: getDomainEnforcement + description: Lists the root domains, or the direct children of parent_id. + operationId: listDomains + parameters: + - description: Parent domain ID + in: query + name: parent_id + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.EnforcementState' + items: + $ref: '#/definitions/domain.Domain' + type: array + "404": + description: Not Found + schema: + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get domain write enforcement state + summary: List domains tags: - domains post: consumes: - application/json - description: Turning it on needs the hash of the current plan; a plan that changed - since it was reviewed is refused with plan_changed. Both directions are audited. - Global scope only. - operationId: setDomainEnforcement + operationId: createDomain parameters: - - description: Target state + - description: Domain; parent_id null creates a root in: body - name: request + name: domain required: true schema: - $ref: '#/definitions/v1_domains.EnforcementRequest' + $ref: '#/definitions/v1_domains.CreateRequest' produces: - application/json responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.EnforcementState' - "403": - description: Forbidden + "201": + description: Created schema: - $ref: '#/definitions/DomainErrorResponse' - "409": - description: Conflict + $ref: '#/definitions/domain.Domain' + "400": + description: Bad Request schema: $ref: '#/definitions/DomainErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Turn domain write enforcement on or off - tags: - - domains - /api/v1/domains/enforcement/plan: - get: - description: Who would lose write access, and where, once writes are scoped - by domain, and which pipelines have assets outside their domain. Its hash - confirms the activation. Global scope only. - operationId: getDomainEnforcementPlan - produces: - - application/json - responses: - "200": - description: OK + "404": + description: Not Found schema: - $ref: '#/definitions/domain.EnforcementPlan' - "403": - description: Forbidden + $ref: '#/definitions/DomainErrorResponse' + "409": + description: Conflict schema: $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Plan domain write enforcement + summary: Create a domain tags: - domains - /api/v1/domains/import: - post: - consumes: - - application/json - description: Maps the values at a metadata path (such as metadata.dgu.domain) - to domains. Only entities still in Unassigned are assigned. A dry run unless - apply is true. Global administrators only. - operationId: importDomainMemberships + /api/v1/domains/{id}: + delete: + description: Only an empty domain without subdomains can be deleted. + operationId: deleteDomain parameters: - - description: Source path, value-to-domain mapping and apply flag - in: body - name: import + - description: Domain ID + in: path + name: id required: true - schema: - $ref: '#/definitions/domain.ImportInput' + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.ImportReport' - "400": - description: Bad Request - schema: - $ref: '#/definitions/DomainErrorResponse' - "403": - description: Forbidden - schema: - $ref: '#/definitions/DomainErrorResponse' + additionalProperties: + type: string + type: object "404": description: Not Found schema: $ref: '#/definitions/DomainErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Import domain memberships from metadata + summary: Delete a domain tags: - domains - /api/v1/domains/of/{kind}/{id}: get: - description: Entities without an explicit domain belong to the Unassigned domain. - operationId: getEntityDomain + operationId: getDomain parameters: - - description: Entity kind - enum: - - asset - - data_product - - glossary_term - - ingestion_schedule - in: path - name: kind - required: true - type: string - - description: Entity ID + - description: Domain ID in: path name: id required: true @@ -6154,76 +5104,87 @@ paths: description: OK schema: $ref: '#/definitions/domain.Domain' - "400": - description: Bad Request + "404": + description: Not Found schema: $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get an entity's domain + summary: Get a domain tags: - domains - /api/v1/domains/pipelines/{scheduleId}/assignment: - get: - description: The domain new assets from this pipeline go to, and how many assets - it ingested are still in that domain. - operationId: getPipelineDomain + put: + consumes: + - application/json + description: Changes only the fields present in the body. + operationId: updateDomain parameters: - - description: Ingestion schedule ID + - description: Domain ID in: path - name: scheduleId + name: id required: true type: string + - description: Fields to change + in: body + name: domain + required: true + schema: + $ref: '#/definitions/v1_domains.UpdateRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.PipelineAssignment' - "403": - description: Forbidden + $ref: '#/definitions/domain.Domain' + "400": + description: Bad Request schema: $ref: '#/definitions/DomainErrorResponse' "404": description: Not Found schema: $ref: '#/definitions/DomainErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get a pipeline's domain + summary: Update a domain tags: - domains + /api/v1/domains/{id}/members: put: consumes: - application/json - description: Sets the domain for the pipeline's new assets. With move_assets, - the assets it already ingested that are still in its previous domain move - too, in the same transaction; assets placed in another domain stay. Moving - assets also requires assets:manage. Under write enforcement the caller must - be able to write in both domains; the change is audited. - operationId: setPipelineDomain + description: Sets the owning domain of every listed entity, all or none. Requires + the entity kind's manage permission and, under write enforcement, write access + to both the current and the target domain. Every change is audited. + operationId: assignDomainMembers parameters: - - description: Ingestion schedule ID + - description: Domain ID in: path - name: scheduleId + name: id required: true type: string - - description: Target domain and whether to move the ingested assets + - description: Entities to assign in: body - name: assignment + name: members required: true schema: - $ref: '#/definitions/v1_domains.PipelineAssignmentRequest' + $ref: '#/definitions/v1_domains.MembersRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.PipelineMoveResult' + additionalProperties: + type: string + type: object "400": description: Bad Request schema: @@ -6239,80 +5200,66 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Change a pipeline's domain - tags: - - domains - /api/v1/domains/writable: - get: - description: For narrowing domain pickers. all is true while enforcement is - off or for global scope; otherwise domain_ids lists every writable domain. - operationId: getWritableDomains - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.WritableDomains' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Domains the caller may write in + summary: Assign entities to a domain tags: - domains - /api/v1/glossary/: + /api/v1/domains/{id}/move: post: consumes: - application/json - description: Create a new glossary term with name, definition, and optional - metadata - operationId: postGlossary + description: Moves the domain and its whole subtree under a new parent. + operationId: moveDomain parameters: - - description: Glossary term to create + - description: Domain ID + in: path + name: id + required: true + type: string + - description: New parent in: body - name: term + name: move required: true schema: - $ref: '#/definitions/CreateTermRequest' + $ref: '#/definitions/v1_domains.MoveRequest' produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/GlossaryTerm' + $ref: '#/definitions/domain.Domain' "400": description: Bad Request schema: - $ref: '#/definitions/ErrorResponse' - "401": - description: Unauthorized + $ref: '#/definitions/DomainErrorResponse' + "404": + description: Not Found schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' "409": description: Conflict schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Create glossary term + summary: Move a domain tags: - - glossary - /api/v1/glossary/{id}: + - domains + /api/v1/domains/{id}/roles: delete: - description: Delete a glossary term by its ID - operationId: deleteGlossaryID + operationId: revokeDomainRole parameters: - - description: Glossary Term ID + - description: Domain ID in: path name: id required: true type: string + - description: Role assignment ID + in: query + name: assignment_id + required: true + type: string produces: - application/json responses: @@ -6322,29 +5269,25 @@ paths: additionalProperties: type: string type: object - "400": - description: Bad Request + "403": + description: Forbidden schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete glossary term + summary: Revoke a role on a domain tags: - - glossary + - domains get: - description: Retrieve a glossary term by its ID - operationId: getGlossaryID + description: Includes the assignments inherited from its ancestors, marked inherited. + operationId: listDomainRoles parameters: - - description: Glossary Term ID + - description: Domain ID in: path name: id required: true @@ -6355,73 +5298,107 @@ paths: "200": description: OK schema: - $ref: '#/definitions/GlossaryTerm' + items: + $ref: '#/definitions/domain.RoleAssignment' + type: array + "404": + description: Not Found + schema: + $ref: '#/definitions/DomainErrorResponse' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: List a domain's role assignments + tags: + - domains + post: + consumes: + - application/json + description: Needs domain_admin on the domain or an ancestor, or global scope. + The role applies to the whole subtree. + operationId: grantDomainRole + parameters: + - description: Domain ID + in: path + name: id + required: true + type: string + - description: Subject and role + in: body + name: grant + required: true + schema: + $ref: '#/definitions/domain.GrantInput' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/domain.RoleAssignment' "400": description: Bad Request schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/DomainErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + $ref: '#/definitions/DomainErrorResponse' + "409": + description: Conflict schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get glossary term + summary: Grant a role on a domain tags: - - glossary - put: - consumes: - - application/json - description: Update an existing glossary term by its ID - operationId: putGlossaryID + - domains + /api/v1/domains/{id}/tree: + get: + description: Returns the domain and all its descendants, shallowest first. + operationId: getDomainTree parameters: - - description: Glossary Term ID + - description: Domain ID in: path name: id required: true type: string - - description: Glossary term update data - in: body - name: term - required: true - schema: - $ref: '#/definitions/UpdateTermRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/GlossaryTerm' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' + items: + $ref: '#/definitions/domain.Domain' + type: array "404": description: Not Found schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Update glossary term + summary: Get a domain subtree tags: - - glossary - /api/v1/glossary/ancestors/{id}: + - domains + /api/v1/domains/audit/{kind}/{id}: get: - description: Retrieve all ancestor terms of a glossary term (parent chain) - operationId: getGlossaryAncestorsID + description: Every change of domain recorded for an entity, oldest first. Kind + is asset, data_product, glossary_term, ingestion_schedule or domain. + operationId: getDomainAuditLog parameters: - - description: Term ID + - description: Entity kind + in: path + name: kind + required: true + type: string + - description: Entity ID in: path name: id required: true @@ -6432,35 +5409,37 @@ paths: "200": description: OK schema: - additionalProperties: true - type: object - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + items: + $ref: '#/definitions/domain.AuditEntry' + type: array security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get ancestor terms + summary: Get an entity's domain history tags: - - glossary - /api/v1/glossary/children/{id}: + - domains + /api/v1/domains/capabilities: get: - description: Retrieve all child terms of a glossary term - operationId: getGlossaryChildrenID + description: Informative, for hiding actions in a UI; the server checks every + operation again. Pass domain_id, or kind and id of an entity to use its domain. + operationId: getDomainCapabilities parameters: - - description: Parent Term ID - in: path + - description: Domain ID + in: query + name: domain_id + type: string + - description: Entity kind + enum: + - asset + - data_product + - glossary_term + - ingestion_schedule + in: query + name: kind + type: string + - description: Entity ID + in: query name: id - required: true type: string produces: - application/json @@ -6468,219 +5447,182 @@ paths: "200": description: OK schema: - additionalProperties: true - type: object + $ref: '#/definitions/v1_domains.Capabilities' "400": description: Bad Request schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get child terms + summary: What the caller may do in a domain tags: - - glossary - /api/v1/glossary/list: + - domains + /api/v1/domains/enforcement: get: - description: Retrieve a paginated list of all glossary terms - operationId: getGlossaryList - parameters: - - default: 20 - description: Maximum number of terms to return - in: query - name: limit - type: integer - - default: 0 - description: Number of terms to skip - in: query - name: offset - type: integer + description: Whether writes are scoped by domain. Off, native RBAC alone decides. + operationId: getDomainEnforcement produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/GlossaryListResult' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/domain.EnforcementState' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List glossary terms + summary: Get domain write enforcement state tags: - - glossary - /api/v1/glossary/references/{id}: - get: - description: For each profile field with the glossary_term control, the live - terms whose value names this term (for example, the acronyms that stand for - it). - operationId: getGlossaryTermReferences + - domains + post: + consumes: + - application/json + description: Turning it on needs the hash of the current plan; a plan that changed + since it was reviewed is refused with plan_changed. Both directions are audited. + Global scope only. + operationId: setDomainEnforcement parameters: - - description: Term ID - in: path - name: id + - description: Target state + in: body + name: request required: true - type: string + schema: + $ref: '#/definitions/v1_domains.EnforcementRequest' produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/GlossaryTermReferences' - type: array - "404": - description: Not Found + $ref: '#/definitions/domain.EnforcementState' + "403": + description: Forbidden schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + $ref: '#/definitions/DomainErrorResponse' + "409": + description: Conflict schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Terms pointing at a term + summary: Turn domain write enforcement on or off tags: - - glossary - /api/v1/glossary/refs: + - domains + /api/v1/domains/enforcement/plan: get: - description: The live terms with the given IDs, for showing glossary_term values - by name. Unknown or deleted IDs are left out. - operationId: getGlossaryTermRefs - parameters: - - description: Comma-separated term IDs (at most 100) - in: query - name: ids - required: true - type: string + description: Who would lose write access, and where, once writes are scoped + by domain, and which pipelines have assets outside their domain. Its hash + confirms the activation. Global scope only. + operationId: getDomainEnforcementPlan produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/GlossaryTermRef' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + $ref: '#/definitions/domain.EnforcementPlan' + "403": + description: Forbidden schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Resolve term IDs + summary: Plan domain write enforcement tags: - - glossary - /api/v1/glossary/search: - get: - description: Search for glossary terms by query string and filters - operationId: getGlossarySearch - parameters: - - description: Search query - in: query - name: q - type: string - - description: Filter by parent term ID - in: query - name: parent_term_id - type: string - - default: 20 - description: Maximum number of terms to return - in: query - name: limit - type: integer - - default: 0 - description: Number of terms to skip - in: query - name: offset - type: integer + - domains + /api/v1/domains/import: + post: + consumes: + - application/json + description: Maps the values at a metadata path (such as metadata.dgu.domain) + to domains. Only entities still in Unassigned are assigned. A dry run unless + apply is true. Global administrators only. + operationId: importDomainMemberships + parameters: + - description: Source path, value-to-domain mapping and apply flag + in: body + name: import + required: true + schema: + $ref: '#/definitions/domain.ImportInput' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/GlossaryListResult' + $ref: '#/definitions/domain.ImportReport' "400": description: Bad Request schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + $ref: '#/definitions/DomainErrorResponse' + "403": + description: Forbidden schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Search glossary terms + summary: Import domain memberships from metadata tags: - - glossary - /api/v1/ingestion/runs: + - domains + /api/v1/domains/of/{kind}/{id}: get: - operationId: getIngestionRuns + description: Entities without an explicit domain belong to the Unassigned domain. + operationId: getEntityDomain parameters: - - description: Filter by schedule ID - in: query - name: schedule_id + - description: Entity kind + enum: + - asset + - data_product + - glossary_term + - ingestion_schedule + in: path + name: kind + required: true type: string - - description: Filter by status - in: query - name: status + - description: Entity ID + in: path + name: id + required: true type: string - - description: Limit - in: query - name: limit - type: integer - - description: Offset - in: query - name: offset - type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/ListJobRunsResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + $ref: '#/definitions/domain.Domain' + "400": + description: Bad Request schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List ingestion job runs + summary: Get an entity's domain tags: - - ingestion - /api/v1/ingestion/runs/{id}: + - domains + /api/v1/domains/pipelines/{scheduleId}/assignment: get: - operationId: getIngestionRunsID + description: The domain new assets from this pipeline go to, and how many assets + it ingested are still in that domain. + operationId: getPipelineDomain parameters: - - description: Job run ID + - description: Ingestion schedule ID in: path - name: id + name: scheduleId required: true type: string produces: @@ -6689,153 +5631,106 @@ paths: "200": description: OK schema: - $ref: '#/definitions/JobRun' - "401": - description: Unauthorized + $ref: '#/definitions/domain.PipelineAssignment' + "403": + description: Forbidden schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get a job run by ID + summary: Get a pipeline's domain tags: - - ingestion - /api/v1/ingestion/runs/{id}/cancel: - post: - operationId: postIngestionRunsIDCancel + - domains + put: + consumes: + - application/json + description: Sets the domain for the pipeline's new assets. With move_assets, + the assets it already ingested that are still in its previous domain move + too, in the same transaction; assets placed in another domain stay. Moving + assets also requires assets:manage. Under write enforcement the caller must + be able to write in both domains; the change is audited. + operationId: setPipelineDomain parameters: - - description: Job run ID + - description: Ingestion schedule ID in: path - name: id + name: scheduleId required: true type: string - responses: - "204": - description: No Content - "401": - description: Unauthorized - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Cancel a running job - tags: - - ingestion - /api/v1/ingestion/runs/{id}/entities: - get: - operationId: getIngestionRunsIDEntities - parameters: - - description: Job run ID - in: path - name: id + - description: Target domain and whether to move the ingested assets + in: body + name: assignment required: true - type: string - - description: Limit - in: query - name: limit - type: integer - - description: Offset - in: query - name: offset - type: integer + schema: + $ref: '#/definitions/v1_domains.PipelineAssignmentRequest' produces: - application/json responses: "200": description: OK schema: - additionalProperties: true - type: object - "401": - description: Unauthorized + $ref: '#/definitions/domain.PipelineMoveResult' + "400": + description: Bad Request schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/DomainErrorResponse' "404": description: Not Found schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/DomainErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get entities for a job run + summary: Change a pipeline's domain tags: - - ingestion - /api/v1/ingestion/schedules: + - domains + /api/v1/domains/writable: get: - operationId: getIngestionSchedules - parameters: - - description: Filter by enabled status - in: query - name: enabled - type: boolean - - description: Limit - in: query - name: limit - type: integer - - description: Offset - in: query - name: offset - type: integer + description: For narrowing domain pickers. all is true while enforcement is + off or for global scope; otherwise domain_ids lists every writable domain. + operationId: getWritableDomains produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/ListSchedulesResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/domain.WritableDomains' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List ingestion schedules + summary: Domains the caller may write in tags: - - ingestion + - domains + /api/v1/glossary/: post: consumes: - application/json - operationId: postIngestionSchedules + description: Create a new glossary term with name, definition, and optional + metadata + operationId: postGlossary parameters: - - description: Schedule configuration + - description: Glossary term to create in: body - name: schedule + name: term required: true schema: - $ref: '#/definitions/CreateScheduleRequest' + $ref: '#/definitions/CreateTermRequest' produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/Schedule' + $ref: '#/definitions/GlossaryTerm' "400": description: Bad Request schema: @@ -6844,6 +5739,10 @@ paths: description: Unauthorized schema: $ref: '#/definitions/ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -6851,23 +5750,30 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Create a new ingestion schedule + summary: Create glossary term tags: - - ingestion - /api/v1/ingestion/schedules/{id}: + - glossary + /api/v1/glossary/{id}: delete: - operationId: deleteIngestionSchedulesID + description: Delete a glossary term by its ID + operationId: deleteGlossaryID parameters: - - description: Schedule ID + - description: Glossary Term ID in: path name: id required: true type: string + produces: + - application/json responses: - "204": - description: No Content - "401": - description: Unauthorized + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' "404": @@ -6881,13 +5787,14 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete an ingestion schedule + summary: Delete glossary term tags: - - ingestion + - glossary get: - operationId: getIngestionSchedulesID + description: Retrieve a glossary term by its ID + operationId: getGlossaryID parameters: - - description: Schedule ID + - description: Glossary Term ID in: path name: id required: true @@ -6898,9 +5805,9 @@ paths: "200": description: OK schema: - $ref: '#/definitions/Schedule' - "401": - description: Unauthorized + $ref: '#/definitions/GlossaryTerm' + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' "404": @@ -6914,40 +5821,37 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get an ingestion schedule by ID + summary: Get glossary term tags: - - ingestion + - glossary put: consumes: - application/json - operationId: putIngestionSchedulesID + description: Update an existing glossary term by its ID + operationId: putGlossaryID parameters: - - description: Schedule ID + - description: Glossary Term ID in: path name: id required: true type: string - - description: Updated schedule configuration + - description: Glossary term update data in: body - name: schedule + name: term required: true schema: - $ref: '#/definitions/UpdateScheduleRequest' + $ref: '#/definitions/UpdateTermRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/Schedule' + $ref: '#/definitions/GlossaryTerm' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: @@ -6959,25 +5863,29 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Update an ingestion schedule + summary: Update glossary term tags: - - ingestion - /api/v1/ingestion/schedules/{id}/trigger: - post: - operationId: postIngestionSchedulesIDTrigger + - glossary + /api/v1/glossary/ancestors/{id}: + get: + description: Retrieve all ancestor terms of a glossary term (parent chain) + operationId: getGlossaryAncestorsID parameters: - - description: Schedule ID + - description: Term ID in: path name: id required: true type: string + produces: + - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/JobRun' - "401": - description: Unauthorized + additionalProperties: true + type: object + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' "404": @@ -6991,64 +5899,67 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Manually trigger an ingestion schedule + summary: Get ancestor terms tags: - - ingestion - /api/v1/ingestion/validate: - post: - consumes: - - application/json - operationId: postIngestionValidate + - glossary + /api/v1/glossary/children/{id}: + get: + description: Retrieve all child terms of a glossary term + operationId: getGlossaryChildrenID parameters: - - description: Config to validate - in: body - name: config + - description: Parent Term ID + in: path + name: id required: true - schema: - $ref: '#/definitions/ValidateConfigRequest' + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/ValidateConfigResponse' + additionalProperties: true + type: object "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "401": - description: Unauthorized + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Validate plugin configuration + summary: Get child terms tags: - - ingestion - /api/v1/lineage: - post: - consumes: - - application/json - description: Process OpenLineage run events and update assets/lineage accordingly - operationId: postLineage + - glossary + /api/v1/glossary/list: + get: + description: Retrieve a paginated list of all glossary terms + operationId: getGlossaryList parameters: - - description: OpenLineage run event - in: body - name: event - required: true - schema: - $ref: '#/definitions/RunEvent' + - default: 20 + description: Maximum number of terms to return + in: query + name: limit + type: integer + - default: 0 + description: Number of terms to skip + in: query + name: offset + type: integer produces: - application/json responses: "200": - description: Event processed successfully - "400": - description: Bad Request + description: OK schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/GlossaryListResult' "500": description: Internal Server Error schema: @@ -7056,52 +5967,30 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Ingest OpenLineage event + summary: List glossary terms tags: - - lineage - /api/v1/lineage/assets/{id}: + - glossary + /api/v1/glossary/references/{id}: get: - consumes: - - application/json - description: Get upstream and downstream lineage for a specific asset - operationId: getLineageAssetsID + description: For each profile field with the glossary_term control, the live + terms whose value names this term (for example, the acronyms that stand for + it). + operationId: getGlossaryTermReferences parameters: - - description: Asset ID - format: uuid + - description: Term ID in: path name: id required: true type: string - - default: 10 - description: Maximum depth of lineage graph - in: query - name: limit - type: integer - - default: both - description: Direction of lineage (upstream, downstream, or both) - enum: - - upstream - - downstream - - both - in: query - name: direction - type: string - - description: Comma separated edge types to leave out, for example CONTAINS - to see data flow without structure - in: query - name: exclude_types - type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/LineageResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' + items: + $ref: '#/definitions/GlossaryTermReferences' + type: array "404": description: Not Found schema: @@ -7113,24 +6002,20 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get asset lineage + summary: Terms pointing at a term tags: - - lineage - /api/v1/lineage/batch: - post: - consumes: - - application/json - description: Create lineage edges in batch - operationId: postLineageBatch + - glossary + /api/v1/glossary/refs: + get: + description: The live terms with the given IDs, for showing glossary_term values + by name. Unknown or deleted IDs are left out. + operationId: getGlossaryTermRefs parameters: - - description: Array of lineage edges to create - in: body - name: edges + - description: Comma-separated term IDs (at most 100) + in: query + name: ids required: true - schema: - items: - $ref: '#/definitions/LineageEdge' - type: array + type: string produces: - application/json responses: @@ -7138,41 +6023,95 @@ paths: description: OK schema: items: - $ref: '#/definitions/BatchLineageResult' + $ref: '#/definitions/GlossaryTermRef' type: array "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: Resolve term IDs + tags: + - glossary + /api/v1/glossary/search: + get: + description: Search for glossary terms by query string and filters + operationId: getGlossarySearch + parameters: + - description: Search query + in: query + name: q + type: string + - description: Filter by parent term ID + in: query + name: parent_term_id + type: string + - default: 20 + description: Maximum number of terms to return + in: query + name: limit + type: integer + - default: 0 + description: Number of terms to skip + in: query + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/GlossaryListResult' + "400": + description: Bad Request + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Batch create lineage edges + summary: Search glossary terms tags: - - lineage - /api/v1/lineage/direct: - post: - consumes: - - application/json - description: Create a direct lineage connection between two assets and returns - the created edge - operationId: postLineageDirect + - glossary + /api/v1/ingestion/runs: + get: + operationId: getIngestionRuns parameters: - - description: Lineage edge to create - in: body - name: edge - required: true - schema: - $ref: '#/definitions/LineageEdge' + - description: Filter by schedule ID + in: query + name: schedule_id + type: string + - description: Filter by status + in: query + name: status + type: string + - description: Limit + in: query + name: limit + type: integer + - description: Offset + in: query + name: offset + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/LineageEdge' - "400": - description: Bad Request + $ref: '#/definitions/ListJobRunsResponse' + "401": + description: Unauthorized schema: $ref: '#/definitions/ErrorResponse' "500": @@ -7182,18 +6121,14 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Create direct lineage + summary: List ingestion job runs tags: - - lineage - /api/v1/lineage/direct/{id}: - delete: - consumes: - - application/json - description: Delete a direct lineage connection by its ID - operationId: deleteLineageDirectID + - ingestion + /api/v1/ingestion/runs/{id}: + get: + operationId: getIngestionRunsID parameters: - - description: Edge ID - format: uuid + - description: Job run ID in: path name: id required: true @@ -7203,8 +6138,14 @@ paths: responses: "200": description: OK - "400": - description: Bad Request + schema: + $ref: '#/definitions/JobRun' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found schema: $ref: '#/definitions/ErrorResponse' "500": @@ -7214,28 +6155,25 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete direct lineage + summary: Get a job run by ID tags: - - lineage - get: - consumes: - - application/json - description: Get a specific direct lineage connection by its ID - operationId: getLineageDirectID + - ingestion + /api/v1/ingestion/runs/{id}/cancel: + post: + operationId: postIngestionRunsIDCancel parameters: - - description: Edge ID - format: uuid + - description: Job run ID in: path name: id required: true type: string - produces: - - application/json responses: - "200": - description: OK + "204": + description: No Content + "401": + description: Unauthorized schema: - $ref: '#/definitions/LineageEdge' + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: @@ -7247,29 +6185,31 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get direct lineage by ID + summary: Cancel a running job tags: - - lineage - /api/v1/mcp: - post: - consumes: - - application/json - description: JSON-RPC 2.0 over the MCP Streamable HTTP transport. Requires assets:view, - glossary:view and teams:view. - operationId: postMcp + - ingestion + /api/v1/ingestion/runs/{id}/entities: + get: + operationId: getIngestionRunsIDEntities parameters: - - description: JSON-RPC 2.0 request - in: body - name: request + - description: Job run ID + in: path + name: id required: true - schema: - additionalProperties: true - type: object + type: string + - description: Limit + in: query + name: limit + type: integer + - description: Offset + in: query + name: offset + type: integer produces: - application/json responses: "200": - description: JSON-RPC 2.0 response + description: OK schema: additionalProperties: true type: object @@ -7277,87 +6217,75 @@ paths: description: Unauthorized schema: $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: MCP endpoint + summary: Get entities for a job run tags: - - mcp - /api/v1/metamodel: + - ingestion + /api/v1/ingestion/schedules: get: - description: Returns the composed native and configured field schema for an - entity kind, led by that kind's native attributes. Clients must not reinterpret - source YAML. - operationId: getMetamodel + operationId: getIngestionSchedules parameters: - - default: asset - description: Entity kind (asset, data_product, glossary_term) + - description: Filter by enabled status in: query - name: kind - type: string + name: enabled + type: boolean + - description: Limit + in: query + name: limit + type: integer + - description: Offset + in: query + name: offset + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/metamodel.Schema' + $ref: '#/definitions/ListSchedulesResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get the effective metamodel schema + summary: List ingestion schedules tags: - - metamodel - /api/v1/metrics: - get: + - ingestion + post: consumes: - application/json - description: Get aggregated metrics for dashboard display - operationId: getMetrics + operationId: postIngestionSchedules parameters: - - description: Start time (ISO 8601) - in: query - name: start - required: true - type: string - - description: End time (ISO 8601) - in: query - name: end + - description: Schedule configuration + in: body + name: schedule required: true - type: string - - collectionFormat: csv - description: Filter by metric names - in: query - items: - type: string - name: metric_names - type: array - - default: avg - description: Aggregation type - enum: - - avg - - sum - - max - - min - in: query - name: aggregation - type: string - - description: Time bucket size - enum: - - 1m - - 5m - - 1h - - 1d - in: query - name: bucket_size - type: string + schema: + $ref: '#/definitions/CreateScheduleRequest' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/GetMetricsResponse' + $ref: '#/definitions/Schedule' "400": description: Bad Request schema: @@ -7366,218 +6294,268 @@ paths: description: Unauthorized schema: $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get metrics for UI + summary: Create a new ingestion schedule tags: - - metrics - /api/v1/metrics/assets/by-owner: - get: - description: Get asset counts grouped by owner - operationId: getMetricsAssetsByOwner - produces: - - application/json + - ingestion + /api/v1/ingestion/schedules/{id}: + delete: + operationId: deleteIngestionSchedulesID + parameters: + - description: Schedule ID + in: path + name: id + required: true + type: string responses: - "200": - description: OK + "204": + description: No Content + "401": + description: Unauthorized schema: - $ref: '#/definitions/AssetsByOwnerResponse' + $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get assets by owner + summary: Delete an ingestion schedule tags: - - metrics - /api/v1/metrics/assets/by-provider: + - ingestion get: - description: Get asset counts grouped by provider - operationId: getMetricsAssetsByProvider + operationId: getIngestionSchedulesID + parameters: + - description: Schedule ID + in: path + name: id + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/AssetsByProviderResponse' + $ref: '#/definitions/Schedule' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get assets by provider + summary: Get an ingestion schedule by ID tags: - - metrics - /api/v1/metrics/assets/by-type: - get: - description: Get asset counts grouped by type - operationId: getMetricsAssetsByType + - ingestion + put: + consumes: + - application/json + operationId: putIngestionSchedulesID + parameters: + - description: Schedule ID + in: path + name: id + required: true + type: string + - description: Updated schedule configuration + in: body + name: schedule + required: true + schema: + $ref: '#/definitions/UpdateScheduleRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/AssetsByTypeResponse' + $ref: '#/definitions/Schedule' + "400": + description: Bad Request + schema: + $ref: '#/definitions/ErrorResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get assets by type + summary: Update an ingestion schedule tags: - - metrics - /api/v1/metrics/assets/total: - get: - description: Get the total number of assets - operationId: getMetricsAssetsTotal - produces: - - application/json + - ingestion + /api/v1/ingestion/schedules/{id}/trigger: + post: + operationId: postIngestionSchedulesIDTrigger + parameters: + - description: Schedule ID + in: path + name: id + required: true + type: string responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/TotalAssetsResponse' + $ref: '#/definitions/JobRun' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get total assets count + summary: Manually trigger an ingestion schedule tags: - - metrics - /api/v1/metrics/assets/with-schemas: - get: - description: Get the count of assets that have schemas defined - operationId: getMetricsAssetsWithSchemas + - ingestion + /api/v1/ingestion/validate: + post: + consumes: + - application/json + operationId: postIngestionValidate + parameters: + - description: Config to validate + in: body + name: config + required: true + schema: + $ref: '#/definitions/ValidateConfigRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/AssetsWithSchemasResponse' + $ref: '#/definitions/ValidateConfigResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/ErrorResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get assets with schemas count + summary: Validate plugin configuration tags: - - metrics - /api/v1/metrics/top-assets: - get: - description: Get the most viewed assets - operationId: getMetricsTopAssets + - ingestion + /api/v1/lineage: + post: + consumes: + - application/json + description: Process OpenLineage run events and update assets/lineage accordingly + operationId: postLineage parameters: - - description: Start time (ISO 8601) - in: query - name: start - required: true - type: string - - description: End time (ISO 8601) - in: query - name: end + - description: OpenLineage run event + in: body + name: event required: true - type: string - - default: 10 - description: Number of results - in: query - name: limit - type: integer + schema: + $ref: '#/definitions/RunEvent' produces: - application/json responses: "200": - description: OK + description: Event processed successfully + "400": + description: Bad Request schema: - items: - $ref: '#/definitions/AssetCount' - type: array + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get top viewed assets + summary: Ingest OpenLineage event tags: - - metrics - /api/v1/metrics/top-queries: + - lineage + /api/v1/lineage/assets/{id}: get: - description: Get the most popular search queries - operationId: getMetricsTopQueries + consumes: + - application/json + description: Get upstream and downstream lineage for a specific asset + operationId: getLineageAssetsID parameters: - - description: Start time (ISO 8601) - in: query - name: start - required: true - type: string - - description: End time (ISO 8601) - in: query - name: end + - description: Asset ID + format: uuid + in: path + name: id required: true type: string - default: 10 - description: Number of results + description: Maximum depth of lineage graph in: query name: limit type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/QueryCount' - type: array - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Get top search queries - tags: - - metrics - /api/v1/owners/search: - get: - consumes: - - application/json - description: Search for asset owners (users and teams) - operationId: getOwnersSearch - parameters: - - description: Search query + - default: both + description: Direction of lineage (upstream, downstream, or both) + enum: + - upstream + - downstream + - both in: query - name: q - required: true + name: direction type: string - - default: 20 - description: Maximum number of results + - description: Comma separated edge types to leave out, for example CONTAINS + to see data flow without structure in: query - name: limit - type: integer + name: exclude_types + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/SearchOwnersResponse' + $ref: '#/definitions/LineageResponse' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + "404": + description: Not Found schema: $ref: '#/definitions/ErrorResponse' - security: - - ApiKeyAuth: [] - - BearerAuth: [] - summary: Search owners - tags: - - owners - /api/v1/permissions: - get: - description: List all defined permissions grouped by resource type - operationId: getPermissions - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/RolePermission' - type: array "500": description: Internal Server Error schema: @@ -7585,92 +6563,68 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List all permissions + summary: Get asset lineage tags: - - roles - /api/v1/pipelines/{pipelineName}: - delete: - description: Delete all resources ever created by a pipeline (across all sources) - operationId: deletePipelinesPipelineName + - lineage + /api/v1/lineage/batch: + post: + consumes: + - application/json + description: Create lineage edges in batch + operationId: postLineageBatch parameters: - - description: Pipeline Name - in: path - name: pipelineName + - description: Array of lineage edges to create + in: body + name: edges required: true - type: string + schema: + items: + $ref: '#/definitions/LineageEdge' + type: array produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/DestroyRunResponse' + items: + $ref: '#/definitions/BatchLineageResult' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Destroy pipeline - tags: - - pipelines - /api/v1/plugins: - get: - operationId: getPlugins - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/ListPluginsResponse' - summary: List registered plugins - tags: - - plugins - /api/v1/plugins/aws/credentials/status: - get: - description: Detects if AWS credentials are available from environment or config - files - operationId: getPluginsAwsCredentialsStatus - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/AWSCredentialStatus' - summary: Get AWS credential detection status + summary: Batch create lineage edges tags: - - plugins - /api/v1/products/: + - lineage + /api/v1/lineage/direct: post: consumes: - application/json - description: Create a new data product with owners and optional membership rules - operationId: postProducts + description: Create a direct lineage connection between two assets and returns + the created edge + operationId: postLineageDirect parameters: - - description: Data product to create + - description: Lineage edge to create in: body - name: product + name: edge required: true schema: - $ref: '#/definitions/CreateDataProductRequest' + $ref: '#/definitions/LineageEdge' produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/DataProduct' + $ref: '#/definitions/LineageEdge' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/ErrorResponse' - "409": - description: Conflict - schema: - $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -7678,15 +6632,18 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Create data product + summary: Create direct lineage tags: - - products - /api/v1/products/{id}: + - lineage + /api/v1/lineage/direct/{id}: delete: - description: Delete a data product by ID - operationId: deleteProductsID + consumes: + - application/json + description: Delete a direct lineage connection by its ID + operationId: deleteLineageDirectID parameters: - - description: Data Product ID + - description: Edge ID + format: uuid in: path name: id required: true @@ -7696,18 +6653,10 @@ paths: responses: "200": description: OK - schema: - additionalProperties: - type: string - type: object "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -7715,14 +6664,17 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete data product + summary: Delete direct lineage tags: - - products + - lineage get: - description: Get a data product by ID - operationId: getProductsID + consumes: + - application/json + description: Get a specific direct lineage connection by its ID + operationId: getLineageDirectID parameters: - - description: Data Product ID + - description: Edge ID + format: uuid in: path name: id required: true @@ -7733,11 +6685,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/DataProduct' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/LineageEdge' "404": description: Not Found schema: @@ -7749,126 +6697,117 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get data product + summary: Get direct lineage by ID tags: - - products - put: + - lineage + /api/v1/mcp: + post: consumes: - application/json - description: Update an existing data product - operationId: putProductsID + description: JSON-RPC 2.0 over the MCP Streamable HTTP transport. Requires assets:view, + glossary:view and teams:view. + operationId: postMcp parameters: - - description: Data Product ID - in: path - name: id - required: true - type: string - - description: Fields to update + - description: JSON-RPC 2.0 request in: body - name: product + name: request required: true schema: - $ref: '#/definitions/UpdateDataProductRequest' + additionalProperties: true + type: object produces: - application/json responses: "200": - description: OK - schema: - $ref: '#/definitions/DataProduct' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "409": - description: Conflict + description: JSON-RPC 2.0 response schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + additionalProperties: true + type: object + "401": + description: Unauthorized schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Update data product + summary: MCP endpoint tags: - - products - /api/v1/products/assets/{id}: + - mcp + /api/v1/metamodel: get: - description: Get the manually added assets of a data product - operationId: getProductsAssetsID + description: Returns the composed native and configured field schema for an + entity kind, led by that kind's native attributes. Clients must not reinterpret + source YAML. + operationId: getMetamodel parameters: - - description: Data Product ID - in: path - name: id - required: true - type: string - - default: 20 - description: Maximum number of assets to return - in: query - name: limit - type: integer - - default: 0 - description: Number of assets to skip + - default: asset + description: Entity kind (asset, data_product, glossary_term) in: query - name: offset - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/DataProductAssetsResult' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + name: kind + type: string + produces: + - application/json + responses: + "200": + description: OK schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/metamodel.Schema' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get data product assets + summary: Get the effective metamodel schema tags: - - products - post: + - metamodel + /api/v1/metrics: + get: consumes: - application/json - description: Manually add assets to a data product - operationId: postProductsAssetsID + description: Get aggregated metrics for dashboard display + operationId: getMetrics parameters: - - description: Data Product ID - in: path - name: id + - description: Start time (ISO 8601) + in: query + name: start required: true type: string - - description: Asset IDs to add - in: body - name: assets + - description: End time (ISO 8601) + in: query + name: end required: true - schema: - $ref: '#/definitions/AddDataProductAssetsRequest' + type: string + - collectionFormat: csv + description: Filter by metric names + in: query + items: + type: string + name: metric_names + type: array + - default: avg + description: Aggregation type + enum: + - avg + - sum + - max + - min + in: query + name: aggregation + type: string + - description: Time bucket size + enum: + - 1m + - 5m + - 1h + - 1d + in: query + name: bucket_size + type: string produces: - application/json responses: "200": description: OK schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/GetMetricsResponse' "400": description: Bad Request schema: @@ -7877,230 +6816,151 @@ paths: description: Unauthorized schema: $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Add data product assets + summary: Get metrics for UI tags: - - products - /api/v1/products/assets/{id}/{assetId}: - delete: - description: Remove a manually added asset from a data product - operationId: deleteProductsAssetsIDAssetID - parameters: - - description: Data Product ID - in: path - name: id - required: true - type: string - - description: Asset ID - in: path - name: assetId - required: true - type: string + - metrics + /api/v1/metrics/assets/by-owner: + get: + description: Get asset counts grouped by owner + operationId: getMetricsAssetsByOwner produces: - application/json responses: "200": description: OK schema: - additionalProperties: - type: string - type: object - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/AssetsByOwnerResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Remove data product asset + summary: Get assets by owner tags: - - products - /api/v1/products/images/{id}: + - metrics + /api/v1/metrics/assets/by-provider: get: - description: List all images for a data product - operationId: getProductsImagesID - parameters: - - description: Data Product ID - in: path - name: id - required: true - type: string + description: Get asset counts grouped by provider + operationId: getMetricsAssetsByProvider produces: - application/json responses: "200": description: OK schema: - additionalProperties: true - type: object - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/AssetsByProviderResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List product images + summary: Get assets by provider tags: - - products - /api/v1/products/images/{id}/{purpose}: - delete: - description: Delete an icon or header image for a data product - operationId: deleteProductsImagesIDPurpose - parameters: - - description: Data Product ID - in: path - name: id - required: true - type: string - - description: Image purpose (icon or header) - in: path - name: purpose - required: true - type: string + - metrics + /api/v1/metrics/assets/by-type: + get: + description: Get asset counts grouped by type + operationId: getMetricsAssetsByType produces: - application/json responses: "200": description: OK schema: - additionalProperties: - type: string - type: object - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/AssetsByTypeResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete product image + summary: Get assets by type tags: - - products + - metrics + /api/v1/metrics/assets/total: get: - description: Get an icon or header image for a data product - operationId: getProductsImagesIDPurpose - parameters: - - description: Data Product ID - in: path - name: id - required: true - type: string - - description: Image purpose (icon or header) - in: path - name: purpose - required: true - type: string + description: Get the total number of assets + operationId: getMetricsAssetsTotal produces: - - image/jpeg - - image/png - - image/gif - - image/webp + - application/json responses: "200": description: OK schema: - type: file - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error + $ref: '#/definitions/TotalAssetsResponse' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: Get total assets count + tags: + - metrics + /api/v1/metrics/assets/with-schemas: + get: + description: Get the count of assets that have schemas defined + operationId: getMetricsAssetsWithSchemas + produces: + - application/json + responses: + "200": + description: OK schema: - $ref: '#/definitions/ErrorResponse' + $ref: '#/definitions/AssetsWithSchemasResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get product image + summary: Get assets with schemas count tags: - - products - post: - consumes: - - multipart/form-data - description: Upload an icon or header image for a data product - operationId: postProductsImagesIDPurpose + - metrics + /api/v1/metrics/top-assets: + get: + description: Get the most viewed assets + operationId: getMetricsTopAssets parameters: - - description: Data Product ID - in: path - name: id + - description: Start time (ISO 8601) + in: query + name: start required: true type: string - - description: Image purpose (icon or header) - in: path - name: purpose + - description: End time (ISO 8601) + in: query + name: end required: true type: string - - description: Image file - in: formData - name: file - required: true - type: file + - default: 10 + description: Number of results + in: query + name: limit + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/ProductImageMeta' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + items: + $ref: '#/definitions/AssetCount' + type: array security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Upload product image + summary: Get top viewed assets tags: - - products - /api/v1/products/list: + - metrics + /api/v1/metrics/top-queries: get: - description: Retrieve a paginated list of data products - operationId: getProductsList + description: Get the most popular search queries + operationId: getMetricsTopQueries parameters: - - default: 20 - description: Maximum number of data products to return + - description: Start time (ISO 8601) in: query - name: limit - type: integer - - default: 0 - description: Number of data products to skip + name: start + required: true + type: string + - description: End time (ISO 8601) in: query - name: offset + name: end + required: true + type: string + - default: 10 + description: Number of results + in: query + name: limit type: integer produces: - application/json @@ -8108,53 +6968,43 @@ paths: "200": description: OK schema: - $ref: '#/definitions/DataProductListResult' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/ErrorResponse' + items: + $ref: '#/definitions/QueryCount' + type: array security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List data products + summary: Get top search queries tags: - - products - /api/v1/products/resolved-assets/{id}: + - metrics + /api/v1/owners/search: get: - description: Get all assets of a data product, both manually added and matched - by rules - operationId: getProductsResolvedAssetsID + consumes: + - application/json + description: Search for asset owners (users and teams) + operationId: getOwnersSearch parameters: - - description: Data Product ID - in: path - name: id + - description: Search query + in: query + name: q required: true type: string - default: 20 - description: Maximum number of assets to return + description: Maximum number of results in: query name: limit type: integer - - default: 0 - description: Number of assets to skip - in: query - name: offset - type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/DataProductResolvedAssets' + $ref: '#/definitions/SearchOwnersResponse' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found - schema: - $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -8162,38 +7012,22 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get resolved data product assets + summary: Search owners tags: - - products - /api/v1/products/rule-preview: - post: - consumes: - - application/json - description: Preview which assets would match a rule configuration - operationId: postProductsRulePreview - parameters: - - description: Rule to preview - in: body - name: rule - required: true - schema: - $ref: '#/definitions/DataProductRuleRequest' - - default: 20 - description: Maximum number of matching assets to return - in: query - name: limit - type: integer + - owners + /api/v1/permissions: + get: + description: List all defined permissions grouped by resource type + operationId: getPermissions produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/DataProductRulePreview' - "400": - description: Bad Request - schema: - $ref: '#/definitions/ErrorResponse' + items: + $ref: '#/definitions/RolePermission' + type: array "500": description: Internal Server Error schema: @@ -8201,17 +7035,17 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Preview data product rule + summary: List all permissions tags: - - products - /api/v1/products/rules/{id}: - get: - description: Get the membership rules of a data product - operationId: getProductsRulesID + - roles + /api/v1/pipelines/{pipelineName}: + delete: + description: Delete all resources ever created by a pipeline (across all sources) + operationId: deletePipelinesPipelineName parameters: - - description: Data Product ID + - description: Pipeline Name in: path - name: id + name: pipelineName required: true type: string produces: @@ -8220,13 +7054,71 @@ paths: "200": description: OK schema: - $ref: '#/definitions/DataProductRulesResponse' + $ref: '#/definitions/DestroyRunResponse' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: Destroy pipeline + tags: + - pipelines + /api/v1/plugins: + get: + operationId: getPlugins + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/ListPluginsResponse' + summary: List registered plugins + tags: + - plugins + /api/v1/plugins/aws/credentials/status: + get: + description: Detects if AWS credentials are available from environment or config + files + operationId: getPluginsAwsCredentialsStatus + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/AWSCredentialStatus' + summary: Get AWS credential detection status + tags: + - plugins + /api/v1/products/: + post: + consumes: + - application/json + description: Create a new data product with owners and optional membership rules + operationId: postProducts + parameters: + - description: Data product to create + in: body + name: product + required: true + schema: + $ref: '#/definitions/CreateDataProductRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/DataProduct' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "404": - description: Not Found + "401": + description: Unauthorized + schema: + $ref: '#/definitions/ErrorResponse' + "409": + description: Conflict schema: $ref: '#/definitions/ErrorResponse' "500": @@ -8236,33 +7128,28 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get data product rules + summary: Create data product tags: - products - post: - consumes: - - application/json - description: Create a membership rule for a data product - operationId: postProductsRulesID + /api/v1/products/{id}: + delete: + description: Delete a data product by ID + operationId: deleteProductsID parameters: - description: Data Product ID in: path name: id required: true type: string - - description: Rule to create - in: body - name: rule - required: true - schema: - $ref: '#/definitions/DataProductRuleRequest' produces: - application/json responses: - "201": - description: Created + "200": + description: OK schema: - $ref: '#/definitions/DataProductRule' + additionalProperties: + type: string + type: object "400": description: Bad Request schema: @@ -8278,33 +7165,25 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Create data product rule + summary: Delete data product tags: - products - /api/v1/products/rules/{id}/{ruleId}: - delete: - description: Delete a membership rule from a data product - operationId: deleteProductsRulesIDRuleID + get: + description: Get a data product by ID + operationId: getProductsID parameters: - description: Data Product ID in: path name: id required: true type: string - - description: Rule ID - in: path - name: ruleId - required: true - type: string produces: - application/json responses: "200": description: OK schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/DataProduct' "400": description: Bad Request schema: @@ -8320,38 +7199,33 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete data product rule + summary: Get data product tags: - products put: consumes: - application/json - description: Update a membership rule of a data product - operationId: putProductsRulesIDRuleID - parameters: - - description: Data Product ID - in: path - name: id - required: true - type: string - - description: Rule ID + description: Update an existing data product + operationId: putProductsID + parameters: + - description: Data Product ID in: path - name: ruleId + name: id required: true type: string - - description: Rule fields to update + - description: Fields to update in: body - name: rule + name: product required: true schema: - $ref: '#/definitions/DataProductRuleRequest' + $ref: '#/definitions/UpdateDataProductRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/DataProductRule' + $ref: '#/definitions/DataProduct' "400": description: Bad Request schema: @@ -8360,6 +7234,10 @@ paths: description: Not Found schema: $ref: '#/definitions/ErrorResponse' + "409": + description: Conflict + schema: + $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -8367,29 +7245,26 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Update data product rule + summary: Update data product tags: - products - /api/v1/products/search: + /api/v1/products/assets/{id}: get: - description: Search data products by name, description, and tags - operationId: getProductsSearch + description: Get the manually added assets of a data product + operationId: getProductsAssetsID parameters: - - description: Search query - in: query - name: q - type: string - - description: Comma-separated list of tags to filter by - in: query - name: tags + - description: Data Product ID + in: path + name: id + required: true type: string - default: 20 - description: Maximum number of data products to return + description: Maximum number of assets to return in: query name: limit type: integer - default: 0 - description: Number of data products to skip + description: Number of assets to skip in: query name: offset type: integer @@ -8399,11 +7274,15 @@ paths: "200": description: OK schema: - $ref: '#/definitions/DataProductListResult' + $ref: '#/definitions/DataProductAssetsResult' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' "500": description: Internal Server Error schema: @@ -8411,32 +7290,35 @@ paths: security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Search data products + summary: Get data product assets tags: - products - /api/v1/quality/evaluate: post: consumes: - application/json - description: 'Judges up to 200 assets as they are, with the current settings, - profile rules and custom rules, and records nothing. It is what a card on - an asset page shows: findings and the checks the asset meets. An id that is - not an asset is left out.' - operationId: evaluateQualityAssets + description: Manually add assets to a data product + operationId: postProductsAssetsID parameters: - - description: Assets + - description: Data Product ID + in: path + name: id + required: true + type: string + - description: Asset IDs to add in: body - name: request + name: assets required: true schema: - $ref: '#/definitions/QualityEvaluateRequest' + $ref: '#/definitions/AddDataProductAssetsRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/QualityEvaluateResponse' + additionalProperties: + type: string + type: object "400": description: Bad Request schema: @@ -8445,182 +7327,266 @@ paths: description: Unauthorized schema: $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden + "404": + description: Not Found schema: $ref: '#/definitions/ErrorResponse' - "422": - description: Unprocessable Entity + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Evaluate assets now + summary: Add data product assets tags: - - quality - /api/v1/quality/rules: - get: - description: 'Every rule the audit applies: the built-in ones, the ones the - metamodel profile declares (read-only here) and the custom ones people wrote. - The severity and on/off of the first two are in the settings; a custom rule - carries its own.' - operationId: listQualityRules + - products + /api/v1/products/assets/{id}/{assetId}: + delete: + description: Remove a manually added asset from a data product + operationId: deleteProductsAssetsIDAssetID + parameters: + - description: Data Product ID + in: path + name: id + required: true + type: string + - description: Asset ID + in: path + name: assetId + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/QualityRulesResponse' - "401": - description: Unauthorized + additionalProperties: + type: string + type: object + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List the quality rules + summary: Remove data product asset tags: - - quality - post: - consumes: - - application/json - description: 'A declarative rule over the fields of the profile: a closed set - of operators, never code. 400 lists every problem with its path. The id is - generated when omitted.' - operationId: createQualityRule + - products + /api/v1/products/images/{id}: + get: + description: List all images for a data product + operationId: getProductsImagesID parameters: - - description: Rule - in: body - name: rule + - description: Data Product ID + in: path + name: id required: true - schema: - $ref: '#/definitions/QualityRuleRequest' + type: string produces: - application/json responses: - "201": - description: Created - schema: - $ref: '#/definitions/QualityCustomRule' - "400": - description: Bad Request + "200": + description: OK schema: - $ref: '#/definitions/QualityRuleError' - "401": - description: Unauthorized + additionalProperties: true + type: object + "404": + description: Not Found schema: $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' - "409": - description: Conflict + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: List product images + tags: + - products + /api/v1/products/images/{id}/{purpose}: + delete: + description: Delete an icon or header image for a data product + operationId: deleteProductsImagesIDPurpose + parameters: + - description: Data Product ID + in: path + name: id + required: true + type: string + - description: Image purpose (icon or header) + in: path + name: purpose + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "404": + description: Not Found schema: $ref: '#/definitions/ErrorResponse' - "422": - description: Unprocessable Entity + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Create a custom quality rule + summary: Delete product image tags: - - quality - /api/v1/quality/rules/{id}: - delete: - operationId: deleteQualityRule + - products + get: + description: Get an icon or header image for a data product + operationId: getProductsImagesIDPurpose parameters: - - description: Rule ID + - description: Data Product ID in: path name: id required: true type: string + - description: Image purpose (icon or header) + in: path + name: purpose + required: true + type: string + produces: + - image/jpeg + - image/png + - image/gif + - image/webp responses: - "204": - description: No Content + "200": + description: OK + schema: + type: file "404": description: Not Found schema: $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Delete a custom quality rule + summary: Get product image tags: - - quality - put: + - products + post: consumes: - - application/json - description: Replaces a custom rule. Requires If-Match with the version read; - 412 when someone changed it first. The rules of the profile cannot be changed - here. - operationId: updateQualityRule + - multipart/form-data + description: Upload an icon or header image for a data product + operationId: postProductsImagesIDPurpose parameters: - - description: Rule ID + - description: Data Product ID in: path name: id required: true type: string - - description: Version read, quoted - in: header - name: If-Match + - description: Image purpose (icon or header) + in: path + name: purpose required: true type: string - - description: Rule - in: body - name: rule + - description: Image file + in: formData + name: file required: true - schema: - $ref: '#/definitions/QualityRuleRequest' + type: file produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/QualityCustomRule' + $ref: '#/definitions/ProductImageMeta' "400": description: Bad Request schema: - $ref: '#/definitions/QualityRuleError' + $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: $ref: '#/definitions/ErrorResponse' - "412": - description: Precondition Failed + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: Upload product image + tags: + - products + /api/v1/products/list: + get: + description: Retrieve a paginated list of data products + operationId: getProductsList + parameters: + - default: 20 + description: Maximum number of data products to return + in: query + name: limit + type: integer + - default: 0 + description: Number of data products to skip + in: query + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK schema: - $ref: '#/definitions/ErrorResponse' - "428": - description: Precondition Required + $ref: '#/definitions/DataProductListResult' + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Change a custom quality rule + summary: List data products tags: - - quality - /api/v1/quality/runs: + - products + /api/v1/products/resolved-assets/{id}: get: - description: Newest first, with the summary of the finished ones. - operationId: listQualityRuns + description: Get all assets of a data product, both manually added and matched + by rules + operationId: getProductsResolvedAssetsID parameters: + - description: Data Product ID + in: path + name: id + required: true + type: string - default: 20 - description: Page size, up to 100 + description: Maximum number of assets to return in: query name: limit type: integer - default: 0 - description: Offset + description: Number of assets to skip in: query name: offset type: integer @@ -8630,62 +7596,70 @@ paths: "200": description: OK schema: - $ref: '#/definitions/QualityRunsResponse' - "401": - description: Unauthorized + $ref: '#/definitions/DataProductResolvedAssets' + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List quality audit runs + summary: Get resolved data product assets tags: - - quality + - products + /api/v1/products/rule-preview: post: - description: 'Audits every asset of the catalog in the background, with the - saved settings and the effective metamodel. One run at a time: a second request - gets 409 with the run in progress.' - operationId: startQualityRun + consumes: + - application/json + description: Preview which assets would match a rule configuration + operationId: postProductsRulePreview + parameters: + - description: Rule to preview + in: body + name: rule + required: true + schema: + $ref: '#/definitions/DataProductRuleRequest' + - default: 20 + description: Maximum number of matching assets to return + in: query + name: limit + type: integer produces: - application/json responses: - "202": - description: Accepted - schema: - $ref: '#/definitions/QualityRun' - "401": - description: Unauthorized + "200": + description: OK schema: - $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden + $ref: '#/definitions/DataProductRulePreview' + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "409": - description: Conflict - schema: - $ref: '#/definitions/QualityRunConflict' - "422": - description: Unprocessable Entity + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Start a quality audit run + summary: Preview data product rule tags: - - quality - /api/v1/quality/runs/{id}: + - products + /api/v1/products/rules/{id}: get: - description: The run with its progress, the settings it used and, once finished, - its summary. - operationId: getQualityRun + description: Get the membership rules of a data product + operationId: getProductsRulesID parameters: - - description: Run ID + - description: Data Product ID in: path name: id required: true @@ -8696,172 +7670,200 @@ paths: "200": description: OK schema: - $ref: '#/definitions/QualityRun' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden + $ref: '#/definitions/DataProductRulesResponse' + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get a quality audit run + summary: Get data product rules tags: - - quality - /api/v1/quality/runs/{id}/results: - get: - description: One entry per audited asset, weakest first. The findings of each - asset are only kept for the last successful run. - operationId: getQualityRunResults + - products + post: + consumes: + - application/json + description: Create a membership rule for a data product + operationId: postProductsRulesID parameters: - - description: Run ID + - description: Data Product ID in: path name: id required: true type: string - - description: compliant, warning or noncompliant - in: query - name: status - type: string - - description: A domain ID, or unassigned - in: query - name: domain - type: string - - description: Asset type - in: query - name: type - type: string - - description: Text in the asset name or MRN - in: query - name: q - type: string - - description: quality (default) or name - in: query - name: sort - type: string - - default: 50 - description: Page size, up to 500 - in: query - name: limit - type: integer - - default: 0 - description: Offset - in: query - name: offset - type: integer + - description: Rule to create + in: body + name: rule + required: true + schema: + $ref: '#/definitions/DataProductRuleRequest' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/QualityResultsResponse' + $ref: '#/definitions/DataProductRule' "400": description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden - schema: - $ref: '#/definitions/ErrorResponse' "404": description: Not Found schema: $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: List the results of a quality audit run + summary: Create data product rule tags: - - quality - /api/v1/quality/settings: - get: - description: The criterion the platform's quality scores are computed with. - Version 0 means the defaults, not yet saved. - operationId: getQualitySettings + - products + /api/v1/products/rules/{id}/{ruleId}: + delete: + description: Delete a membership rule from a data product + operationId: deleteProductsRulesIDRuleID + parameters: + - description: Data Product ID + in: path + name: id + required: true + type: string + - description: Rule ID + in: path + name: ruleId + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/QualitySettingsResponse' - "401": - description: Unauthorized + additionalProperties: + type: string + type: object + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden + "404": + description: Not Found + schema: + $ref: '#/definitions/ErrorResponse' + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Get the quality audit settings + summary: Delete data product rule tags: - - quality + - products put: consumes: - application/json - description: Replaces the settings. Requires If-Match with the version read; - 412 when someone saved first. - operationId: putQualitySettings + description: Update a membership rule of a data product + operationId: putProductsRulesIDRuleID parameters: - - description: Version read, quoted; \ - in: header - name: If-Match + - description: Data Product ID + in: path + name: id required: true type: string - - description: Settings + - description: Rule ID + in: path + name: ruleId + required: true + type: string + - description: Rule fields to update in: body - name: settings + name: rule required: true schema: - $ref: '#/definitions/QualitySettings' + $ref: '#/definitions/DataProductRuleRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/QualitySettingsResponse' + $ref: '#/definitions/DataProductRule' "400": description: Bad Request schema: - $ref: '#/definitions/QualityValidationError' - "401": - description: Unauthorized + $ref: '#/definitions/ErrorResponse' + "404": + description: Not Found schema: $ref: '#/definitions/ErrorResponse' - "403": - description: Forbidden + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' - "412": - description: Precondition Failed + security: + - ApiKeyAuth: [] + - BearerAuth: [] + summary: Update data product rule + tags: + - products + /api/v1/products/search: + get: + description: Search data products by name, description, and tags + operationId: getProductsSearch + parameters: + - description: Search query + in: query + name: q + type: string + - description: Comma-separated list of tags to filter by + in: query + name: tags + type: string + - default: 20 + description: Maximum number of data products to return + in: query + name: limit + type: integer + - default: 0 + description: Number of data products to skip + in: query + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/DataProductListResult' + "400": + description: Bad Request schema: $ref: '#/definitions/ErrorResponse' - "428": - description: Precondition Required + "500": + description: Internal Server Error schema: $ref: '#/definitions/ErrorResponse' security: - ApiKeyAuth: [] - BearerAuth: [] - summary: Change the quality audit settings + summary: Search data products tags: - - quality + - products /api/v1/roles: get: description: List all active roles with user counts and permissions