{
  "components": {
    "schemas": {
      "AIToolDetail": {
        "properties": {
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "endpoint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Endpoint"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Method"
          },
          "parameters": {
            "title": "Parameters"
          },
          "plugin_description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Description"
          },
          "plugin_display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Display Name"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "plugin_name": {
            "title": "Plugin Name",
            "type": "string"
          },
          "required_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Required Tier"
          },
          "response_format": {
            "title": "Response Format"
          },
          "tool_name": {
            "title": "Tool Name",
            "type": "string"
          },
          "type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Type"
          }
        },
        "required": [
          "id",
          "tool_name",
          "type",
          "description",
          "endpoint",
          "method",
          "parameters",
          "response_format",
          "required_tier",
          "active",
          "plugin_id",
          "plugin_name",
          "plugin_display_name",
          "plugin_description"
        ],
        "title": "AIToolDetail",
        "type": "object"
      },
      "AIToolItem": {
        "description": "One tool in ``GET /tools``: a plugin tool plus its plugin's name.",
        "properties": {
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "endpoint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Endpoint"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Method"
          },
          "parameters": {
            "title": "Parameters"
          },
          "plugin_display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Display Name"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "plugin_name": {
            "title": "Plugin Name",
            "type": "string"
          },
          "required_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Required Tier"
          },
          "response_format": {
            "title": "Response Format"
          },
          "tool_name": {
            "title": "Tool Name",
            "type": "string"
          },
          "type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Type"
          }
        },
        "required": [
          "id",
          "tool_name",
          "type",
          "description",
          "endpoint",
          "method",
          "parameters",
          "response_format",
          "required_tier",
          "active",
          "plugin_id",
          "plugin_name",
          "plugin_display_name"
        ],
        "title": "AIToolItem",
        "type": "object"
      },
      "AIToolListResponse": {
        "description": "Predates the shared ``PaginatedList`` envelope (#501).",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "tools": {
            "items": {
              "$ref": "#/components/schemas/AIToolItem"
            },
            "title": "Tools",
            "type": "array"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "tools",
          "count",
          "total",
          "limit",
          "offset"
        ],
        "title": "AIToolListResponse",
        "type": "object"
      },
      "AIToolsDeactivateResponse": {
        "properties": {
          "success": {
            "title": "Success",
            "type": "boolean"
          },
          "tools_deactivated": {
            "title": "Tools Deactivated",
            "type": "integer"
          }
        },
        "required": [
          "success",
          "tools_deactivated"
        ],
        "title": "AIToolsDeactivateResponse",
        "type": "object"
      },
      "AIToolsResponse": {
        "properties": {
          "tools": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Tools",
            "type": "array"
          }
        },
        "required": [
          "tools"
        ],
        "title": "AIToolsResponse",
        "type": "object"
      },
      "AIToolsSyncRequest": {
        "description": "Request model for syncing AI tools from plugin manifest",
        "properties": {
          "manifest": {
            "additionalProperties": true,
            "title": "Manifest",
            "type": "object"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "plugin_name": {
            "title": "Plugin Name",
            "type": "string"
          }
        },
        "required": [
          "plugin_name",
          "plugin_id",
          "manifest"
        ],
        "title": "AIToolsSyncRequest",
        "type": "object"
      },
      "AIToolsSyncResponse": {
        "description": "``POST /sync``. A manifest with no ``ai_tools`` section returns only\n``success``/``tools_imported``/``message``, so the other keys are unset\nthere and dropped (``response_model_exclude_unset``).",
        "properties": {
          "errors": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Errors"
          },
          "message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Message"
          },
          "success": {
            "title": "Success",
            "type": "boolean"
          },
          "tools_deactivated": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tools Deactivated"
          },
          "tools_imported": {
            "title": "Tools Imported",
            "type": "integer"
          }
        },
        "required": [
          "success",
          "tools_imported"
        ],
        "title": "AIToolsSyncResponse",
        "type": "object"
      },
      "ActivatedLicense": {
        "description": "``core.licensing.create_license``. The datetimes are naive UTC.",
        "properties": {
          "activated_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Activated By"
          },
          "active": {
            "title": "Active",
            "type": "boolean"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "license_key_masked": {
            "title": "License Key Masked",
            "type": "string"
          },
          "plugin_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "string"
              }
            ],
            "title": "Plugin Id"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          },
          "trial_expires_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial Expires At"
          },
          "valid_from": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Valid From"
          },
          "valid_until": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Valid Until"
          }
        },
        "required": [
          "id",
          "tenant_id",
          "activated_by",
          "plugin_id",
          "tier",
          "license_key_masked",
          "valid_from",
          "valid_until",
          "trial_expires_at",
          "active"
        ],
        "title": "ActivatedLicense",
        "type": "object"
      },
      "AddDependencyResponse": {
        "properties": {
          "depends_on": {
            "title": "Depends On",
            "type": "string"
          },
          "depends_on_type": {
            "title": "Depends On Type",
            "type": "string"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "type": {
            "title": "Type",
            "type": "string"
          },
          "version_constraint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Version Constraint"
          }
        },
        "required": [
          "status",
          "plugin_id",
          "depends_on",
          "type",
          "version_constraint",
          "depends_on_type"
        ],
        "title": "AddDependencyResponse",
        "type": "object"
      },
      "AuditLogEntry": {
        "properties": {
          "action": {
            "title": "Action",
            "type": "string"
          },
          "actor_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Actor Id"
          },
          "after_state": {
            "anyOf": [
              {},
              {
                "type": "null"
              }
            ],
            "title": "After State"
          },
          "before_state": {
            "anyOf": [
              {},
              {
                "type": "null"
              }
            ],
            "title": "Before State"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "ip_address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Address"
          },
          "scope_org_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scope Org Id"
          },
          "scope_type": {
            "default": "legacy",
            "title": "Scope Type",
            "type": "string"
          },
          "target_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Target Id"
          },
          "target_type": {
            "title": "Target Type",
            "type": "string"
          },
          "user_agent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Agent"
          }
        },
        "required": [
          "id",
          "action",
          "target_type"
        ],
        "title": "AuditLogEntry",
        "type": "object"
      },
      "AuditLogListResponse": {
        "properties": {
          "entries": {
            "items": {
              "$ref": "#/components/schemas/AuditLogEntry"
            },
            "title": "Entries",
            "type": "array"
          },
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "entries",
          "total",
          "limit",
          "offset"
        ],
        "title": "AuditLogListResponse",
        "type": "object"
      },
      "BulkInviteCreate": {
        "description": "Body for `POST /v1/invites/bulk` (#1654) -- the team-invite equivalent\nof `routes/organizations.py`'s `OrgBulkInviteCreate`. All invited emails\nshare the same `team_id`/`team_role`/`max_uses`.",
        "properties": {
          "emails": {
            "items": {
              "format": "email",
              "type": "string"
            },
            "maxItems": 100,
            "minItems": 1,
            "title": "Emails",
            "type": "array"
          },
          "max_uses": {
            "default": 1,
            "maximum": 1000.0,
            "minimum": 1.0,
            "title": "Max Uses",
            "type": "integer"
          },
          "team_id": {
            "title": "Team Id",
            "type": "integer"
          },
          "team_role": {
            "default": "member",
            "title": "Team Role",
            "type": "string"
          }
        },
        "required": [
          "emails",
          "team_id"
        ],
        "title": "BulkInviteCreate",
        "type": "object"
      },
      "BulkInviteResponse": {
        "properties": {
          "created_count": {
            "title": "Created Count",
            "type": "integer"
          },
          "failed_count": {
            "title": "Failed Count",
            "type": "integer"
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/BulkInviteResultItem"
            },
            "title": "Results",
            "type": "array"
          }
        },
        "required": [
          "results",
          "created_count",
          "failed_count"
        ],
        "title": "BulkInviteResponse",
        "type": "object"
      },
      "BulkInviteResultItem": {
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "invite": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InviteOut"
              },
              {
                "type": "null"
              }
            ]
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "rule": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rule"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "email",
          "status"
        ],
        "title": "BulkInviteResultItem",
        "type": "object"
      },
      "BulkOrgInviteResponse": {
        "properties": {
          "created_count": {
            "title": "Created Count",
            "type": "integer"
          },
          "failed_count": {
            "title": "Failed Count",
            "type": "integer"
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/BulkOrgInviteResultItem"
            },
            "title": "Results",
            "type": "array"
          }
        },
        "required": [
          "results",
          "created_count",
          "failed_count"
        ],
        "title": "BulkOrgInviteResponse",
        "type": "object"
      },
      "BulkOrgInviteResultItem": {
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "invite": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/OrgInviteOut"
              },
              {
                "type": "null"
              }
            ]
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "rule": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rule"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "email",
          "status"
        ],
        "title": "BulkOrgInviteResultItem",
        "type": "object"
      },
      "BulkRoleAssignRequest": {
        "description": "Body for `POST /{org_id}/members/bulk-roles` (#1654): assign ONE\nrole, optionally time-boxed, to a LIST of user ids in one request.",
        "properties": {
          "expires_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "role_id": {
            "title": "Role Id",
            "type": "integer"
          },
          "user_ids": {
            "items": {
              "type": "integer"
            },
            "maxItems": 500,
            "minItems": 1,
            "title": "User Ids",
            "type": "array"
          }
        },
        "required": [
          "user_ids",
          "role_id"
        ],
        "title": "BulkRoleAssignRequest",
        "type": "object"
      },
      "BulkRoleAssignResponse": {
        "properties": {
          "assigned_count": {
            "title": "Assigned Count",
            "type": "integer"
          },
          "failed_count": {
            "title": "Failed Count",
            "type": "integer"
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/BulkRoleAssignResultItem"
            },
            "title": "Results",
            "type": "array"
          }
        },
        "required": [
          "results",
          "assigned_count",
          "failed_count"
        ],
        "title": "BulkRoleAssignResponse",
        "type": "object"
      },
      "BulkRoleAssignResultItem": {
        "properties": {
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          }
        },
        "required": [
          "user_id",
          "status"
        ],
        "title": "BulkRoleAssignResultItem",
        "type": "object"
      },
      "BundleRequiredResponse": {
        "properties": {
          "bundle": {
            "title": "Bundle",
            "type": "string"
          },
          "confirmed": {
            "title": "Confirmed",
            "type": "boolean"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "required": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Required"
          },
          "requiring_plugins": {
            "items": {
              "type": "string"
            },
            "title": "Requiring Plugins",
            "type": "array"
          }
        },
        "required": [
          "bundle",
          "confirmed",
          "required",
          "requiring_plugins",
          "reason"
        ],
        "title": "BundleRequiredResponse",
        "type": "object"
      },
      "CapabilitiesResponse": {
        "properties": {
          "email_verification": {
            "title": "Email Verification",
            "type": "boolean"
          },
          "password_reset_email": {
            "title": "Password Reset Email",
            "type": "boolean"
          },
          "password_reset_link_minutes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Password Reset Link Minutes"
          },
          "registration_mode": {
            "title": "Registration Mode",
            "type": "string"
          },
          "self_serve_personal_orgs": {
            "default": false,
            "title": "Self Serve Personal Orgs",
            "type": "boolean"
          }
        },
        "required": [
          "password_reset_email",
          "email_verification",
          "registration_mode"
        ],
        "title": "CapabilitiesResponse",
        "type": "object"
      },
      "ChangePasswordRequest": {
        "properties": {
          "current_password": {
            "minLength": 1,
            "title": "Current Password",
            "type": "string"
          },
          "new_password": {
            "minLength": 8,
            "title": "New Password",
            "type": "string"
          }
        },
        "required": [
          "current_password",
          "new_password"
        ],
        "title": "ChangePasswordRequest",
        "type": "object"
      },
      "ChatFeedback": {
        "description": "An anonymous end user rating one chat response (#1583).\n\n``turn_id`` is the id the ``/message`` response handed back for that response;\n``rating`` is thumbs up/down, with an optional short free-text ``comment``. The\nsession is taken from the anonymous token — never the body — so a caller cannot\nrate on behalf of another session.",
        "properties": {
          "comment": {
            "anyOf": [
              {
                "maxLength": 2000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Comment"
          },
          "conversation_id": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Conversation Id"
          },
          "rating": {
            "pattern": "^(up|down)$",
            "title": "Rating",
            "type": "string"
          },
          "turn_id": {
            "minimum": 1.0,
            "title": "Turn Id",
            "type": "integer"
          }
        },
        "required": [
          "turn_id",
          "rating"
        ],
        "title": "ChatFeedback",
        "type": "object"
      },
      "ChatMessage": {
        "properties": {
          "conversation_id": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Conversation Id"
          },
          "question": {
            "maxLength": 8000,
            "minLength": 1,
            "title": "Question",
            "type": "string"
          }
        },
        "required": [
          "question"
        ],
        "title": "ChatMessage",
        "type": "object"
      },
      "CheckoutRequest": {
        "properties": {
          "tier": {
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "tier"
        ],
        "title": "CheckoutRequest",
        "type": "object"
      },
      "CheckoutResponse": {
        "properties": {
          "checkout_url": {
            "title": "Checkout Url",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "checkout_url",
          "tier"
        ],
        "title": "CheckoutResponse",
        "type": "object"
      },
      "ChildGroupIdRequest": {
        "properties": {
          "child_group_id": {
            "title": "Child Group Id",
            "type": "integer"
          }
        },
        "required": [
          "child_group_id"
        ],
        "title": "ChildGroupIdRequest",
        "type": "object"
      },
      "CollectionTriggeredResponse": {
        "properties": {
          "message": {
            "title": "Message",
            "type": "string"
          },
          "note": {
            "title": "Note",
            "type": "string"
          },
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "title": "Timestamp",
            "type": "string"
          },
          "triggered_by": {
            "title": "Triggered By",
            "type": "string"
          }
        },
        "required": [
          "message",
          "plugin",
          "status",
          "triggered_by",
          "timestamp",
          "note"
        ],
        "title": "CollectionTriggeredResponse",
        "type": "object"
      },
      "DependencyResolutionResponse": {
        "description": "``core.dependency_resolution.build_resolution_report``.",
        "properties": {
          "nodes": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Nodes",
            "type": "array"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "resolve_failures": {
            "items": {
              "type": "string"
            },
            "title": "Resolve Failures",
            "type": "array"
          },
          "resolves": {
            "title": "Resolves",
            "type": "boolean"
          },
          "verdict": {
            "title": "Verdict",
            "type": "string"
          }
        },
        "required": [
          "plugin_id",
          "resolves",
          "resolve_failures",
          "nodes",
          "verdict",
          "reason"
        ],
        "title": "DependencyResolutionResponse",
        "type": "object"
      },
      "DependencyType": {
        "description": "Allowed plugin-dependency relationship types.\n\nTyping the route param with this enum makes FastAPI reject an invalid value with a\n422 (listing the allowed values in /docs) instead of the old free string that only\nfailed deep in add_dependency as a caught ValueError → 400 (#143).",
        "enum": [
          "requires",
          "suggests",
          "conflicts_with"
        ],
        "title": "DependencyType",
        "type": "string"
      },
      "DependsOnType": {
        "description": "Which Neo4j node label `depends_on` resolves to (#1626).\n\nTyped the same way as DependencyType above: FastAPI rejects an invalid value\nwith a 422 instead of it reaching Neo4jClient.add_dependency's own ValueError\n-> 400 fallback.",
        "enum": [
          "plugin",
          "bundle"
        ],
        "title": "DependsOnType",
        "type": "string"
      },
      "DistributionType": {
        "description": "Plugin distribution types",
        "enum": [
          "git",
          "docker",
          "hybrid"
        ],
        "title": "DistributionType",
        "type": "string"
      },
      "EffectivePermissionEntry": {
        "properties": {
          "permission_group_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Permission Group Id"
          },
          "permission_group_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Permission Group Name"
          },
          "permission_key": {
            "title": "Permission Key",
            "type": "string"
          },
          "role_id": {
            "title": "Role Id",
            "type": "integer"
          },
          "role_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Role Name"
          },
          "via_ancestor_organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Via Ancestor Organization Id"
          }
        },
        "required": [
          "permission_key",
          "role_id"
        ],
        "title": "EffectivePermissionEntry",
        "type": "object"
      },
      "EffectivePermissionsResponse": {
        "properties": {
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "permissions": {
            "items": {
              "$ref": "#/components/schemas/EffectivePermissionEntry"
            },
            "title": "Permissions",
            "type": "array"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          }
        },
        "required": [
          "organization_id",
          "user_id",
          "permissions"
        ],
        "title": "EffectivePermissionsResponse",
        "type": "object"
      },
      "EndpointCreate": {
        "properties": {
          "allowed_origins": {
            "anyOf": [
              {
                "maxLength": 2000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Allowed Origins"
          },
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "pipeline_id": {
            "maxLength": 255,
            "minLength": 1,
            "title": "Pipeline Id",
            "type": "string"
          },
          "rag_config": {
            "additionalProperties": true,
            "title": "Rag Config",
            "type": "object"
          },
          "rate_limit_per_minute": {
            "default": 20,
            "maximum": 600.0,
            "minimum": 1.0,
            "title": "Rate Limit Per Minute",
            "type": "integer"
          },
          "slug": {
            "maxLength": 120,
            "minLength": 1,
            "pattern": "^[a-zA-Z0-9._-]+$",
            "title": "Slug",
            "type": "string"
          }
        },
        "required": [
          "name",
          "slug",
          "pipeline_id"
        ],
        "title": "EndpointCreate",
        "type": "object"
      },
      "EndpointUpdate": {
        "properties": {
          "allowed_origins": {
            "anyOf": [
              {
                "maxLength": 2000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Allowed Origins"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 200,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "pipeline_id": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pipeline Id"
          },
          "rag_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rag Config"
          },
          "rate_limit_per_minute": {
            "anyOf": [
              {
                "maximum": 600.0,
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rate Limit Per Minute"
          }
        },
        "title": "EndpointUpdate",
        "type": "object"
      },
      "GraphHealthResponse": {
        "description": "Returned via ``JSONResponse``, so a 503 carries it too.",
        "properties": {
          "checks": {
            "additionalProperties": {
              "type": "string"
            },
            "title": "Checks",
            "type": "object"
          },
          "database": {
            "title": "Database",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status",
          "database",
          "checks"
        ],
        "title": "GraphHealthResponse",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "ImportRequest": {
        "description": "Import body: the exported ``bundle`` plus a conflict ``policy`` for colliding\nids/names (``skip`` keeps existing rows, ``rename`` imports collisions as fresh\ncopies, ``fail`` aborts on any collision — all non-destructive).",
        "properties": {
          "bundle": {
            "additionalProperties": true,
            "title": "Bundle",
            "type": "object"
          },
          "policy": {
            "default": "skip",
            "title": "Policy",
            "type": "string"
          }
        },
        "required": [
          "bundle"
        ],
        "title": "ImportRequest",
        "type": "object"
      },
      "InstallSource": {
        "description": "How a plugin was installed: ``vendored`` (a code plugin shipped with the\nregistry and loaded from its plugins directory), ``git`` (fetched with\n``POST /v1/plugins/install-from-git`` or last re-fetched with\n``refresh-from-git``) or ``manifest`` (uploaded to\n``POST /v1/plugins/install``).",
        "enum": [
          "vendored",
          "git",
          "manifest"
        ],
        "title": "InstallSource",
        "type": "string"
      },
      "InstallationResponse": {
        "description": "Model for installation response",
        "properties": {
          "config_json": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Config Json"
          },
          "current_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "enabled": {
            "title": "Enabled",
            "type": "boolean"
          },
          "id": {
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
            "title": "Id",
            "type": "string"
          },
          "installed_at": {
            "format": "date-time",
            "title": "Installed At",
            "type": "string"
          },
          "last_updated_at": {
            "format": "date-time",
            "title": "Last Updated At",
            "type": "string"
          },
          "pinned_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pinned Version"
          },
          "plugin_id": {
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
            "title": "Plugin Id",
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/InstallationStatus"
          },
          "update_available": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Update Available"
          },
          "user_id": {
            "title": "User Id",
            "type": "string"
          },
          "version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Version"
          }
        },
        "required": [
          "id",
          "user_id",
          "plugin_id",
          "version",
          "status",
          "enabled",
          "config_json",
          "installed_at",
          "last_updated_at"
        ],
        "title": "InstallationResponse",
        "type": "object"
      },
      "InstallationStatus": {
        "description": "Installation status",
        "enum": [
          "installing",
          "installed",
          "failed",
          "uninstalled"
        ],
        "title": "InstallationStatus",
        "type": "string"
      },
      "InstalledPluginSummary": {
        "description": "One row of `GET /v1/marketplace/installations/me` (#402) -- an\ninstallation joined with its plugin's metadata, so the client doesn't need\nan N+1 fetch per installed plugin just to show a name/description.",
        "properties": {
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author"
          },
          "base_tier": {
            "title": "Base Tier",
            "type": "string"
          },
          "category_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Id"
          },
          "current_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "display_name": {
            "title": "Display Name",
            "type": "string"
          },
          "enabled": {
            "title": "Enabled",
            "type": "boolean"
          },
          "installation_id": {
            "title": "Installation Id",
            "type": "string"
          },
          "installed_at": {
            "format": "date-time",
            "title": "Installed At",
            "type": "string"
          },
          "last_updated_at": {
            "format": "date-time",
            "title": "Last Updated At",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "origin": {
            "$ref": "#/components/schemas/PluginOrigin",
            "default": "first_party",
            "description": "Catalog origin of the installed plugin: `first_party` (glossary first-party) or `submitted` (glossary community)."
          },
          "pinned_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Version this installation is pinned to, or null when not pinned. Bulk/automatic updates skip a pinned installation.",
            "title": "Pinned Version"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "pricing_model": {
            "title": "Pricing Model",
            "type": "string"
          },
          "repository_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The plugin's source repository URL, when it has one.",
            "title": "Repository Url"
          },
          "requires_services": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Requires Services",
            "type": "array"
          },
          "status": {
            "$ref": "#/components/schemas/InstallationStatus"
          },
          "update_available": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "True when current_version is newer than version (semantic-version order). Null when either is unknown or they can't be ordered.",
            "title": "Update Available"
          },
          "version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Version installed (#2199); null for an installation that predates version recording.",
            "title": "Version"
          }
        },
        "required": [
          "installation_id",
          "plugin_id",
          "version",
          "status",
          "enabled",
          "installed_at",
          "last_updated_at",
          "name",
          "display_name",
          "description",
          "current_version",
          "pricing_model",
          "base_tier",
          "category_id",
          "author"
        ],
        "title": "InstalledPluginSummary",
        "type": "object"
      },
      "InviteCreate": {
        "properties": {
          "email": {
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "max_uses": {
            "default": 1,
            "maximum": 1000.0,
            "minimum": 1.0,
            "title": "Max Uses",
            "type": "integer"
          },
          "team_id": {
            "title": "Team Id",
            "type": "integer"
          },
          "team_role": {
            "default": "member",
            "title": "Team Role",
            "type": "string"
          }
        },
        "required": [
          "email",
          "team_id"
        ],
        "title": "InviteCreate",
        "type": "object"
      },
      "InviteInfo": {
        "properties": {
          "can_create_account": {
            "default": false,
            "title": "Can Create Account",
            "type": "boolean"
          },
          "email": {
            "description": "The invited address, MASKED (e.g. 'j***@example.com') when the invite is email-bound (see email_bound); an empty string for a shareable/unbound link, whose address the invitee needn't use. Never the full address.",
            "title": "Email",
            "type": "string"
          },
          "email_bound": {
            "default": false,
            "description": "True when registering/redeeming must use the invited address (single-use invites and owner/admin org invites): the client asks for it in full and the server verifies it; `email` then carries the masked hint. False for a shareable link (`email` is '').",
            "title": "Email Bound",
            "type": "boolean"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "invited_by_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The inviter's username, for 'X invited you' copy -- never their id or email. Set only while the invite is pending and unexpired AND email-bound (single recipient); null for shareable/multi-use links, for accepted, revoked or expired invites, and when the username looks like an email address.",
            "title": "Invited By Name"
          },
          "org_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Org Name"
          },
          "org_role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Org Role"
          },
          "organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Id"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "team_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Team Id"
          },
          "team_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Team Name"
          },
          "team_role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Team Role"
          }
        },
        "required": [
          "id",
          "email",
          "status"
        ],
        "title": "InviteInfo",
        "type": "object"
      },
      "InviteListResponse": {
        "properties": {
          "invites": {
            "items": {
              "$ref": "#/components/schemas/InviteOut"
            },
            "title": "Invites",
            "type": "array"
          },
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "invites",
          "total",
          "limit",
          "offset"
        ],
        "title": "InviteListResponse",
        "type": "object"
      },
      "InviteOut": {
        "properties": {
          "can_create_account": {
            "default": false,
            "title": "Can Create Account",
            "type": "boolean"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "email": {
            "title": "Email",
            "type": "string"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "invited_by": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Invited By"
          },
          "max_uses": {
            "default": 1,
            "title": "Max Uses",
            "type": "integer"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "team_id": {
            "title": "Team Id",
            "type": "integer"
          },
          "team_role": {
            "title": "Team Role",
            "type": "string"
          },
          "token": {
            "title": "Token",
            "type": "string"
          },
          "uses": {
            "default": 0,
            "title": "Uses",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "email",
          "team_id",
          "team_role",
          "token",
          "status"
        ],
        "title": "InviteOut",
        "type": "object"
      },
      "LicenseActivateRequest": {
        "description": "Request model for license activation.\n\nNo user_id field -- identity comes from the JWT (`sub`), same as\ninstallations.py's install/uninstall (#147/C7). A caller-supplied user_id\nused to let any authenticated user activate (or silently overwrite) a\nlicense for ANY other account; there is still no payment/entitlement\ncheck behind this endpoint, so this closes the cross-account grant, not\nthe \"is self-service tier activation free\" question (see the issue\ntracking that gap).",
        "properties": {
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "plugin_id",
          "tier"
        ],
        "title": "LicenseActivateRequest",
        "type": "object"
      },
      "LicenseActivateResponse": {
        "properties": {
          "license": {
            "$ref": "#/components/schemas/ActivatedLicense"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status",
          "license"
        ],
        "title": "LicenseActivateResponse",
        "type": "object"
      },
      "LicenseKeyResponse": {
        "description": "``GET /licenses/{license_id}/key`` (#1951) -- the ONE response that carries\na full license key. ``signed_license`` is the Ed25519 ``mlv1.`` token for\noffline activation; always ``null`` until the platform issues signed licenses\n(``core/signed_license.py`` is verification-only today, no signing key is\nconfigured).",
        "properties": {
          "license_id": {
            "title": "License Id",
            "type": "string"
          },
          "license_key": {
            "title": "License Key",
            "type": "string"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "signed_license": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signed License"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "license_id",
          "tenant_id",
          "plugin_id",
          "tier",
          "license_key"
        ],
        "title": "LicenseKeyResponse",
        "type": "object"
      },
      "LicenseListResponse": {
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "licenses": {
            "items": {
              "$ref": "#/components/schemas/TenantLicense"
            },
            "title": "Licenses",
            "type": "array"
          }
        },
        "required": [
          "licenses",
          "count"
        ],
        "title": "LicenseListResponse",
        "type": "object"
      },
      "LicenseLookupResponse": {
        "properties": {
          "active": {
            "title": "Active",
            "type": "boolean"
          },
          "license_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "License Tier"
          },
          "org_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Org Tier"
          },
          "tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier"
          }
        },
        "required": [
          "tier",
          "active"
        ],
        "title": "LicenseLookupResponse",
        "type": "object"
      },
      "LicenseRotateResponse": {
        "properties": {
          "license": {
            "$ref": "#/components/schemas/RotatedLicense"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status",
          "license"
        ],
        "title": "LicenseRotateResponse",
        "type": "object"
      },
      "LicenseTier": {
        "description": "Canonical license tiers, ordered free < community < pro < enterprise.",
        "enum": [
          "free",
          "community",
          "pro",
          "enterprise"
        ],
        "title": "LicenseTier",
        "type": "string"
      },
      "LicenseValidateRequest": {
        "description": "Request model for license validation",
        "properties": {
          "license_key": {
            "title": "License Key",
            "type": "string"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          }
        },
        "required": [
          "license_key",
          "plugin_id"
        ],
        "title": "LicenseValidateRequest",
        "type": "object"
      },
      "LicenseValidationRequest": {
        "description": "License validation request (tool-access check). #622 re-key: the license\nsubject is the ORGANIZATION (tenant_id), not the individual user.",
        "properties": {
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          },
          "tool_name": {
            "title": "Tool Name",
            "type": "string"
          }
        },
        "required": [
          "tenant_id",
          "tool_name"
        ],
        "title": "LicenseValidationRequest",
        "type": "object"
      },
      "LicenseValidationResponse": {
        "description": "``core.licensing.validate_license``. An invalid key returns only\n``valid``/``reason`` (plus ``valid_until`` when it expired). Unset keys are\ndropped (``response_model_exclude_unset``), so no nulls are added.",
        "properties": {
          "full_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Full Tier"
          },
          "plugin_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Id"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier"
          },
          "trial_expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial Expires At"
          },
          "usage_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Usage Count"
          },
          "user_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          },
          "valid": {
            "title": "Valid",
            "type": "boolean"
          },
          "valid_until": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Valid Until"
          }
        },
        "required": [
          "valid"
        ],
        "title": "LicenseValidationResponse",
        "type": "object"
      },
      "LoginRequest": {
        "properties": {
          "password": {
            "minLength": 1,
            "title": "Password",
            "type": "string"
          },
          "username": {
            "minLength": 1,
            "title": "Username",
            "type": "string"
          }
        },
        "required": [
          "username",
          "password"
        ],
        "title": "LoginRequest",
        "type": "object"
      },
      "MarketplacePluginListResponse": {
        "description": "Model for plugin list response.\n\nCarries the platform-standard ``limit``/``offset``/``total`` fields (#147/C6)\nalongside the original ``page``/``page_size``/``total_pages`` — a superset, so\nexisting page-based clients keep working while new clients use limit/offset.",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "limit": {
            "default": 0,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "title": "Offset",
            "type": "integer"
          },
          "page": {
            "title": "Page",
            "type": "integer"
          },
          "page_size": {
            "title": "Page Size",
            "type": "integer"
          },
          "plugins": {
            "items": {
              "$ref": "#/components/schemas/PluginResponse"
            },
            "title": "Plugins",
            "type": "array"
          },
          "total": {
            "default": 0,
            "title": "Total",
            "type": "integer"
          },
          "total_pages": {
            "title": "Total Pages",
            "type": "integer"
          }
        },
        "required": [
          "plugins",
          "count",
          "page",
          "page_size",
          "total_pages"
        ],
        "title": "PluginListResponse",
        "type": "object"
      },
      "MemberAdd": {
        "description": "Exactly one of `user_id`/`email` must be given (#1072). `email` lets a\nteam_admin who isn't also an instance admin add an existing colleague\ndirectly -- `GET /v1/auth/users` (the only way to discover a numeric\nuser_id) is instance-admin-gated, so `user_id` alone made this control\nunusable for the overwhelming majority of team_admins. #2285: for a\ncaller who is not a Platform Admin, either form only reaches accounts the\nteam's org already has or manages (see ``add_team_member_route``).",
        "properties": {
          "email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "team_role": {
            "default": "member",
            "title": "Team Role",
            "type": "string"
          },
          "user_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          }
        },
        "title": "MemberAdd",
        "type": "object"
      },
      "MemberRoleAssignmentOut": {
        "properties": {
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "granted_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Granted At"
          },
          "granted_by": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Granted By"
          },
          "is_expired": {
            "title": "Is Expired",
            "type": "boolean"
          },
          "role_id": {
            "title": "Role Id",
            "type": "integer"
          },
          "role_name": {
            "title": "Role Name",
            "type": "string"
          },
          "scope": {
            "title": "Scope",
            "type": "string"
          }
        },
        "required": [
          "role_id",
          "role_name",
          "scope",
          "is_expired"
        ],
        "title": "MemberRoleAssignmentOut",
        "type": "object"
      },
      "MemberRoleAssignmentsResponse": {
        "properties": {
          "assignments": {
            "items": {
              "$ref": "#/components/schemas/MemberRoleAssignmentOut"
            },
            "title": "Assignments",
            "type": "array"
          }
        },
        "required": [
          "assignments"
        ],
        "title": "MemberRoleAssignmentsResponse",
        "type": "object"
      },
      "MemberRoleUpdate": {
        "properties": {
          "team_role": {
            "title": "Team Role",
            "type": "string"
          }
        },
        "required": [
          "team_role"
        ],
        "title": "MemberRoleUpdate",
        "type": "object"
      },
      "MessageResponse": {
        "properties": {
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "message"
        ],
        "title": "MessageResponse",
        "type": "object"
      },
      "MyInstallationsResponse": {
        "description": "Response for GET /v1/marketplace/installations/me.",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "installations": {
            "items": {
              "$ref": "#/components/schemas/InstalledPluginSummary"
            },
            "title": "Installations",
            "type": "array"
          }
        },
        "required": [
          "installations",
          "count"
        ],
        "title": "MyInstallationsResponse",
        "type": "object"
      },
      "MyOrgItem": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "is_home": {
            "title": "Is Home",
            "type": "boolean"
          },
          "kind": {
            "anyOf": [
              {
                "enum": [
                  "personal",
                  "standard"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Organization kind: `personal` (the workspace a self-service signup creates, and its sub-organizations) or `standard`. A sub-organization always has its parent's kind. In `invite`/`closed` registration mode only the owners/admins of a `standard` organization (or a Platform Admin) can issue invites that create new accounts. Read-only; a Platform Admin converts with `POST /v1/organizations/{org_id}/convert`.",
            "title": "Kind"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "org_role": {
            "title": "Org Role",
            "type": "string"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "org_role",
          "is_home"
        ],
        "title": "MyOrgItem",
        "type": "object"
      },
      "MyOrgsResponse": {
        "properties": {
          "active_organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active Organization Id"
          },
          "organizations": {
            "items": {
              "$ref": "#/components/schemas/MyOrgItem"
            },
            "title": "Organizations",
            "type": "array"
          }
        },
        "required": [
          "organizations"
        ],
        "title": "MyOrgsResponse",
        "type": "object"
      },
      "OrgBulkInviteCreate": {
        "description": "Body for `POST /{org_id}/invites/bulk` (#1654). All invited emails\nshare the same `org_role`/`max_uses` -- a single grant-authority question\nto answer once for the whole batch, not the same question asked N times.",
        "properties": {
          "emails": {
            "items": {
              "format": "email",
              "type": "string"
            },
            "maxItems": 100,
            "minItems": 1,
            "title": "Emails",
            "type": "array"
          },
          "max_uses": {
            "default": 1,
            "maximum": 1000.0,
            "minimum": 1.0,
            "title": "Max Uses",
            "type": "integer"
          },
          "org_role": {
            "default": "member",
            "title": "Org Role",
            "type": "string"
          }
        },
        "required": [
          "emails"
        ],
        "title": "OrgBulkInviteCreate",
        "type": "object"
      },
      "OrgConvertRequest": {
        "description": "Body of `POST /v1/organizations/{org_id}/convert`.",
        "properties": {
          "reason": {
            "description": "Why the organization is being converted, recorded in the `ORG_KIND_CHANGED` audit row. Required; surrounding whitespace is trimmed, then it must be 1-500 characters.",
            "maxLength": 500,
            "minLength": 1,
            "title": "Reason",
            "type": "string"
          },
          "to": {
            "description": "The kind to convert to. Only `standard` is accepted: conversion is one-way, so `personal` is refused with 409.",
            "enum": [
              "personal",
              "standard"
            ],
            "title": "To",
            "type": "string"
          }
        },
        "required": [
          "to",
          "reason"
        ],
        "title": "OrgConvertRequest",
        "type": "object"
      },
      "OrgCreateRequest": {
        "properties": {
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "owner_user_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Owner User Id"
          },
          "slug": {
            "maxLength": 100,
            "minLength": 1,
            "pattern": "^[a-zA-Z0-9._-]+$",
            "title": "Slug",
            "type": "string"
          }
        },
        "required": [
          "name",
          "slug"
        ],
        "title": "OrgCreateRequest",
        "type": "object"
      },
      "OrgDeleteAccepted": {
        "description": "202 body of ``DELETE /v1/organizations/{id}`` (#1805): the org is already\ngone; its data is being purged asynchronously by ``purge_job``.",
        "properties": {
          "deleted": {
            "default": true,
            "title": "Deleted",
            "type": "boolean"
          },
          "irreversible": {
            "default": true,
            "title": "Irreversible",
            "type": "boolean"
          },
          "not_yet_purged": {
            "items": {
              "type": "string"
            },
            "title": "Not Yet Purged",
            "type": "array"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "purge_job": {
            "$ref": "#/components/schemas/OrgPurgeJobRef"
          },
          "warning": {
            "title": "Warning",
            "type": "string"
          }
        },
        "required": [
          "organization_id",
          "warning",
          "purge_job",
          "not_yet_purged"
        ],
        "title": "OrgDeleteAccepted",
        "type": "object"
      },
      "OrgDetailOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "created_via": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "How the organization was created. One of: `signup` (a self-service signup workspace), `platform_admin` (created by a Platform Admin), `owner` (created by the owner of an organization whose plan allows more), `suborg` (created under a parent organization); `conversion` and `import` are reserved. New values may be added: treat an unknown value as an unknown creation path. Read-only and never changed afterwards (a conversion to `standard` changes `kind`, not this). Null for organizations created before it was recorded.",
            "title": "Created Via"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "entitlement_mode": {
            "default": "independent",
            "title": "Entitlement Mode",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "kind": {
            "anyOf": [
              {
                "enum": [
                  "personal",
                  "standard"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Organization kind: `personal` (the workspace a self-service signup creates, and its sub-organizations) or `standard`. A sub-organization always has its parent's kind. In `invite`/`closed` registration mode only the owners/admins of a `standard` organization (or a Platform Admin) can issue invites that create new accounts. Read-only; a Platform Admin converts with `POST /v1/organizations/{org_id}/convert`.",
            "title": "Kind"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "parent_organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Organization Id"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          }
        },
        "required": [
          "id",
          "name",
          "slug"
        ],
        "title": "OrgDetailOut",
        "type": "object"
      },
      "OrgEntitlementOut": {
        "properties": {
          "entitlement_mode": {
            "title": "Entitlement Mode",
            "type": "string"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "resolved_organization_id": {
            "title": "Resolved Organization Id",
            "type": "integer"
          }
        },
        "required": [
          "organization_id",
          "resolved_organization_id",
          "entitlement_mode"
        ],
        "title": "OrgEntitlementOut",
        "type": "object"
      },
      "OrgEntitlementResponse": {
        "properties": {
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "tenant_id",
          "tier"
        ],
        "title": "OrgEntitlementResponse",
        "type": "object"
      },
      "OrgInviteCreate": {
        "properties": {
          "email": {
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "max_uses": {
            "default": 1,
            "maximum": 1000.0,
            "minimum": 1.0,
            "title": "Max Uses",
            "type": "integer"
          },
          "org_role": {
            "default": "member",
            "title": "Org Role",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "title": "OrgInviteCreate",
        "type": "object"
      },
      "OrgInviteOut": {
        "properties": {
          "can_create_account": {
            "default": false,
            "title": "Can Create Account",
            "type": "boolean"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "email": {
            "title": "Email",
            "type": "string"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "max_uses": {
            "default": 1,
            "title": "Max Uses",
            "type": "integer"
          },
          "org_role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Org Role"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "token": {
            "title": "Token",
            "type": "string"
          },
          "uses": {
            "default": 0,
            "title": "Uses",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "email",
          "token",
          "status"
        ],
        "title": "OrgInviteOut",
        "type": "object"
      },
      "OrgInvitesResponse": {
        "properties": {
          "invites": {
            "items": {
              "$ref": "#/components/schemas/OrgInviteOut"
            },
            "title": "Invites",
            "type": "array"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "invites",
          "total"
        ],
        "title": "OrgInvitesResponse",
        "type": "object"
      },
      "OrgLimitOut": {
        "properties": {
          "behaviour": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Behaviour"
          },
          "clamped": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Clamped"
          },
          "key": {
            "title": "Key",
            "type": "string"
          },
          "kind": {
            "enum": [
              "count",
              "behaviour",
              "flag",
              "knob",
              "thresholds"
            ],
            "title": "Kind",
            "type": "string"
          },
          "override_scope": {
            "anyOf": [
              {
                "enum": [
                  "organization",
                  "tier",
                  "all_tiers"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Override Scope"
          },
          "restricted_by": {
            "anyOf": [
              {
                "const": "org_kind",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Restricted By"
          },
          "source": {
            "anyOf": [
              {
                "enum": [
                  "tier_default",
                  "operator_override",
                  "license"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source"
          },
          "value": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "integer"
              },
              {
                "type": "string"
              },
              {
                "items": {
                  "type": "integer"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Value"
          }
        },
        "required": [
          "key",
          "kind"
        ],
        "title": "OrgLimitOut",
        "type": "object"
      },
      "OrgLimitOverrideClear": {
        "properties": {
          "reason": {
            "maxLength": 500,
            "minLength": 1,
            "title": "Reason",
            "type": "string"
          }
        },
        "required": [
          "reason"
        ],
        "title": "OrgLimitOverrideClear",
        "type": "object"
      },
      "OrgLimitOverrideSet": {
        "properties": {
          "reason": {
            "maxLength": 500,
            "minLength": 1,
            "title": "Reason",
            "type": "string"
          },
          "value": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "integer"
              },
              {
                "type": "string"
              },
              {
                "items": {
                  "type": "integer"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "The override; null means unlimited (counts only).",
            "title": "Value"
          }
        },
        "required": [
          "value",
          "reason"
        ],
        "title": "OrgLimitOverrideSet",
        "type": "object"
      },
      "OrgLimitsOut": {
        "properties": {
          "enforced": {
            "title": "Enforced",
            "type": "boolean"
          },
          "entitlement_root_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Entitlement Root Id"
          },
          "limits": {
            "items": {
              "$ref": "#/components/schemas/OrgLimitOut"
            },
            "title": "Limits",
            "type": "array"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "seats": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/OrgSeatsOut"
              },
              {
                "type": "null"
              }
            ]
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          },
          "view": {
            "enum": [
              "full",
              "member"
            ],
            "title": "View",
            "type": "string"
          }
        },
        "required": [
          "organization_id",
          "view",
          "tier",
          "enforced",
          "limits"
        ],
        "title": "OrgLimitsOut",
        "type": "object"
      },
      "OrgListItem": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "created_by": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created By"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "kind": {
            "anyOf": [
              {
                "enum": [
                  "personal",
                  "standard"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Organization kind: `personal` (the workspace a self-service signup creates, and its sub-organizations) or `standard`. A sub-organization always has its parent's kind. In `invite`/`closed` registration mode only the owners/admins of a `standard` organization (or a Platform Admin) can issue invites that create new accounts. Read-only; a Platform Admin converts with `POST /v1/organizations/{org_id}/convert`.",
            "title": "Kind"
          },
          "member_count": {
            "title": "Member Count",
            "type": "integer"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "member_count"
        ],
        "title": "OrgListItem",
        "type": "object"
      },
      "OrgListResponse": {
        "properties": {
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "organizations": {
            "items": {
              "$ref": "#/components/schemas/OrgListItem"
            },
            "title": "Organizations",
            "type": "array"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "organizations",
          "total",
          "limit",
          "offset"
        ],
        "title": "OrgListResponse",
        "type": "object"
      },
      "OrgMemberAccountStatusOut": {
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "is_oidc_linked": {
            "title": "Is Oidc Linked",
            "type": "boolean"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          },
          "username": {
            "title": "Username",
            "type": "string"
          }
        },
        "required": [
          "organization_id",
          "user_id",
          "username",
          "email",
          "is_active",
          "is_oidc_linked"
        ],
        "title": "OrgMemberAccountStatusOut",
        "type": "object"
      },
      "OrgMemberAccountStatusRequest": {
        "properties": {
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          }
        },
        "required": [
          "is_active"
        ],
        "title": "OrgMemberAccountStatusRequest",
        "type": "object"
      },
      "OrgMemberAddRequest": {
        "properties": {
          "org_role": {
            "default": "member",
            "title": "Org Role",
            "type": "string"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          }
        },
        "required": [
          "user_id"
        ],
        "title": "OrgMemberAddRequest",
        "type": "object"
      },
      "OrgMemberItem": {
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          },
          "is_home": {
            "title": "Is Home",
            "type": "boolean"
          },
          "org_role": {
            "title": "Org Role",
            "type": "string"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          },
          "username": {
            "title": "Username",
            "type": "string"
          }
        },
        "required": [
          "user_id",
          "username",
          "email",
          "org_role",
          "is_home"
        ],
        "title": "OrgMemberItem",
        "type": "object"
      },
      "OrgMemberListItem": {
        "description": "One row of ``GET /{org_id}/members`` (#1853, ADR\ntenant-scoped-user-administration Decision 3): the account state and\nwhat the CALLER could do about it, so the client can show actions per\npermission without learning anything about other tenants.",
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "is_home": {
            "title": "Is Home",
            "type": "boolean"
          },
          "is_oidc_linked": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "null unless managed_by_caller (not disclosed)",
            "title": "Is Oidc Linked"
          },
          "managed_by_caller": {
            "title": "Managed By Caller",
            "type": "boolean"
          },
          "must_change_password": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "null unless managed_by_caller (not disclosed)",
            "title": "Must Change Password"
          },
          "org_role": {
            "title": "Org Role",
            "type": "string"
          },
          "outside_allowed_domains": {
            "default": false,
            "title": "Outside Allowed Domains",
            "type": "boolean"
          },
          "resettable_by_caller": {
            "title": "Resettable By Caller",
            "type": "boolean"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          },
          "username": {
            "title": "Username",
            "type": "string"
          }
        },
        "required": [
          "user_id",
          "username",
          "email",
          "org_role",
          "is_home",
          "is_active",
          "managed_by_caller",
          "resettable_by_caller"
        ],
        "title": "OrgMemberListItem",
        "type": "object"
      },
      "OrgMemberPasswordResetRequest": {
        "properties": {
          "mode": {
            "enum": [
              "set",
              "generate"
            ],
            "title": "Mode",
            "type": "string"
          },
          "new_password": {
            "anyOf": [
              {
                "minLength": 8,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "New Password"
          }
        },
        "required": [
          "mode"
        ],
        "title": "OrgMemberPasswordResetRequest",
        "type": "object"
      },
      "OrgMemberPasswordResetResponse": {
        "properties": {
          "mode": {
            "enum": [
              "set",
              "generate"
            ],
            "title": "Mode",
            "type": "string"
          },
          "must_change_password": {
            "default": true,
            "title": "Must Change Password",
            "type": "boolean"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "temporary_password": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Temporary Password"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          }
        },
        "required": [
          "organization_id",
          "user_id",
          "mode"
        ],
        "title": "OrgMemberPasswordResetResponse",
        "type": "object"
      },
      "OrgMembersResponse": {
        "properties": {
          "members": {
            "items": {
              "$ref": "#/components/schemas/OrgMemberListItem"
            },
            "title": "Members",
            "type": "array"
          }
        },
        "required": [
          "members"
        ],
        "title": "OrgMembersResponse",
        "type": "object"
      },
      "OrgMeteringSummary": {
        "description": "Aggregate metering/entitlement summary across a subtree (#1650's\n\"rolled-up subtree reporting\" decision). **Stubbed**: the token-usage\nledger this should aggregate (minder#1645) is NOT landed yet (confirmed\nopen at the time of this PR) -- ``total_input_tokens``/\n``total_output_tokens`` are always ``None`` until that ledger exists and\nthis is wired to it. Tracked as an explicit follow-up, not silently\nguessed at.",
        "properties": {
          "note": {
            "default": "Token-usage/metering aggregation is stubbed: the token-usage ledger it aggregates is not yet landed.",
            "title": "Note",
            "type": "string"
          },
          "organization_count": {
            "title": "Organization Count",
            "type": "integer"
          },
          "stubbed": {
            "default": true,
            "title": "Stubbed",
            "type": "boolean"
          },
          "total_input_tokens": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Total Input Tokens"
          },
          "total_output_tokens": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Total Output Tokens"
          }
        },
        "required": [
          "organization_count"
        ],
        "title": "OrgMeteringSummary",
        "type": "object"
      },
      "OrgMove": {
        "description": "Body for `POST /{org_id}/move` (#1650). `new_parent_organization_id =\nNone` detaches the organization to top-level -- the delete default's\nmirror image.",
        "properties": {
          "new_parent_organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "New Parent Organization Id"
          }
        },
        "title": "OrgMove",
        "type": "object"
      },
      "OrgOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "created_via": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "How the organization was created. One of: `signup` (a self-service signup workspace), `platform_admin` (created by a Platform Admin), `owner` (created by the owner of an organization whose plan allows more), `suborg` (created under a parent organization); `conversion` and `import` are reserved. New values may be added: treat an unknown value as an unknown creation path. Read-only and never changed afterwards (a conversion to `standard` changes `kind`, not this). Null for organizations created before it was recorded.",
            "title": "Created Via"
          },
          "default_team_id": {
            "title": "Default Team Id",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "kind": {
            "anyOf": [
              {
                "enum": [
                  "personal",
                  "standard"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Organization kind: `personal` (the workspace a self-service signup creates, and its sub-organizations) or `standard`. A sub-organization always has its parent's kind. In `invite`/`closed` registration mode only the owners/admins of a `standard` organization (or a Platform Admin) can issue invites that create new accounts. Read-only; a Platform Admin converts with `POST /v1/organizations/{org_id}/convert`.",
            "title": "Kind"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "owner_user_id": {
            "title": "Owner User Id",
            "type": "integer"
          },
          "parent_organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Organization Id"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "owner_user_id",
          "default_team_id"
        ],
        "title": "OrgOut",
        "type": "object"
      },
      "OrgPolicyKnobOut": {
        "properties": {
          "available": {
            "title": "Available",
            "type": "boolean"
          },
          "available_on": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Available On"
          },
          "default": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              },
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default"
          },
          "effective": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              },
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Effective"
          },
          "grandfathered": {
            "title": "Grandfathered",
            "type": "boolean"
          },
          "key": {
            "enum": [
              "invite_policy",
              "allow_account_creating_invites",
              "allowed_email_domains",
              "team_admins_may_create_accounts",
              "require_2fa"
            ],
            "title": "Key",
            "type": "string"
          },
          "locked_reason": {
            "anyOf": [
              {
                "enum": [
                  "tier",
                  "org_kind",
                  "operator",
                  "license"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Locked Reason"
          },
          "source": {
            "enum": [
              "default",
              "organization",
              "parent"
            ],
            "title": "Source",
            "type": "string"
          },
          "value": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              },
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Value"
          }
        },
        "required": [
          "key",
          "available",
          "source",
          "grandfathered"
        ],
        "title": "OrgPolicyKnobOut",
        "type": "object"
      },
      "OrgPolicyOut": {
        "properties": {
          "knobs": {
            "items": {
              "$ref": "#/components/schemas/OrgPolicyKnobOut"
            },
            "title": "Knobs",
            "type": "array"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "parent_organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Organization Id"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "organization_id",
          "tier",
          "knobs"
        ],
        "title": "OrgPolicyOut",
        "type": "object"
      },
      "OrgPolicyPatch": {
        "additionalProperties": false,
        "description": "Only the fields present change. ``null`` resets a knob: it is\ninherited from the parent again (the default on a root org); an empty\n``allowed_email_domains`` list too. An explicit value equal to the\ndefault is kept (on a sub-org it tightens a looser parent).",
        "properties": {
          "allow_account_creating_invites": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Allow Account Creating Invites"
          },
          "allowed_email_domains": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "maxItems": 100,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Allowed Email Domains"
          },
          "invite_policy": {
            "anyOf": [
              {
                "enum": [
                  "admins",
                  "members"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Invite Policy"
          },
          "require_2fa": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Require 2Fa"
          },
          "team_admins_may_create_accounts": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Team Admins May Create Accounts"
          }
        },
        "title": "OrgPolicyPatch",
        "type": "object"
      },
      "OrgPurgeJobList": {
        "properties": {
          "jobs": {
            "items": {
              "$ref": "#/components/schemas/OrgPurgeJobOut"
            },
            "title": "Jobs",
            "type": "array"
          }
        },
        "required": [
          "jobs"
        ],
        "title": "OrgPurgeJobList",
        "type": "object"
      },
      "OrgPurgeJobOut": {
        "additionalProperties": true,
        "properties": {
          "attempts": {
            "title": "Attempts",
            "type": "integer"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "finished_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Finished At"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Error"
          },
          "next_attempt_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Attempt At"
          },
          "not_covered": {
            "items": {
              "type": "string"
            },
            "title": "Not Covered",
            "type": "array"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "organization_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Name"
          },
          "resweep_after": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resweep After"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "stores": {
            "additionalProperties": true,
            "title": "Stores",
            "type": "object"
          },
          "sweep": {
            "title": "Sweep",
            "type": "integer"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "tenant_id",
          "organization_id",
          "status",
          "sweep",
          "attempts",
          "stores",
          "not_covered"
        ],
        "title": "OrgPurgeJobOut",
        "type": "object"
      },
      "OrgPurgeJobRef": {
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "tenant_id"
        ],
        "title": "OrgPurgeJobRef",
        "type": "object"
      },
      "OrgSeatsOut": {
        "description": "Seats of the org's entitlement root (#2227).",
        "properties": {
          "behaviour": {
            "enum": [
              "hard",
              "soft",
              "soft_then_hard"
            ],
            "title": "Behaviour",
            "type": "string"
          },
          "entitlement_root_id": {
            "title": "Entitlement Root Id",
            "type": "integer"
          },
          "max": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "reserved": {
            "title": "Reserved",
            "type": "integer"
          },
          "source": {
            "enum": [
              "tier_default",
              "operator_override",
              "license"
            ],
            "title": "Source",
            "type": "string"
          },
          "state": {
            "enum": [
              "unlimited",
              "ok",
              "warning",
              "at_limit",
              "over_limit"
            ],
            "title": "State",
            "type": "string"
          },
          "used": {
            "title": "Used",
            "type": "integer"
          }
        },
        "required": [
          "organization_id",
          "entitlement_root_id",
          "used",
          "reserved",
          "behaviour",
          "source",
          "state"
        ],
        "title": "OrgSeatsOut",
        "type": "object"
      },
      "OrgSubtreeItem": {
        "properties": {
          "depth": {
            "title": "Depth",
            "type": "integer"
          },
          "entitlement_mode": {
            "title": "Entitlement Mode",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "parent_organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Organization Id"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "entitlement_mode",
          "depth"
        ],
        "title": "OrgSubtreeItem",
        "type": "object"
      },
      "OrgSubtreeResponse": {
        "properties": {
          "descendants": {
            "items": {
              "$ref": "#/components/schemas/OrgSubtreeItem"
            },
            "title": "Descendants",
            "type": "array"
          },
          "metering_summary": {
            "$ref": "#/components/schemas/OrgMeteringSummary"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          }
        },
        "required": [
          "organization_id",
          "descendants",
          "metering_summary"
        ],
        "title": "OrgSubtreeResponse",
        "type": "object"
      },
      "OrgSwitchRequest": {
        "properties": {
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          }
        },
        "required": [
          "organization_id"
        ],
        "title": "OrgSwitchRequest",
        "type": "object"
      },
      "OrgUpdateRequest": {
        "description": "PATCH body (#1503, extended by #1650) — every field optional, only\nwhat's supplied is changed. At least one field must be present (an empty\nPATCH is almost certainly a client bug, not a legitimate no-op request).",
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 10000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "entitlement_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Entitlement Mode"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 200,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "title": "OrgUpdateRequest",
        "type": "object"
      },
      "PasswordResetAccepted": {
        "properties": {
          "detail": {
            "default": "If an account exists for that address, we've sent instructions.",
            "title": "Detail",
            "type": "string"
          }
        },
        "title": "PasswordResetAccepted",
        "type": "object"
      },
      "PasswordResetConfirmBody": {
        "properties": {
          "new_password": {
            "minLength": 8,
            "title": "New Password",
            "type": "string"
          },
          "token": {
            "maxLength": 128,
            "minLength": 1,
            "title": "Token",
            "type": "string"
          }
        },
        "required": [
          "token",
          "new_password"
        ],
        "title": "PasswordResetConfirmBody",
        "type": "object"
      },
      "PasswordResetRequest": {
        "properties": {
          "mode": {
            "enum": [
              "set",
              "generate"
            ],
            "title": "Mode",
            "type": "string"
          },
          "new_password": {
            "anyOf": [
              {
                "minLength": 8,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "New Password"
          }
        },
        "required": [
          "mode"
        ],
        "title": "PasswordResetRequest",
        "type": "object"
      },
      "PasswordResetRequestBody": {
        "properties": {
          "email": {
            "maxLength": 320,
            "minLength": 3,
            "title": "Email",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "title": "PasswordResetRequestBody",
        "type": "object"
      },
      "PasswordResetResponse": {
        "properties": {
          "mode": {
            "enum": [
              "set",
              "generate"
            ],
            "title": "Mode",
            "type": "string"
          },
          "must_change_password": {
            "default": true,
            "title": "Must Change Password",
            "type": "boolean"
          },
          "temporary_password": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Temporary Password"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          }
        },
        "required": [
          "user_id",
          "mode"
        ],
        "title": "PasswordResetResponse",
        "type": "object"
      },
      "PermissionGroupCreateRequest": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "name": {
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "PermissionGroupCreateRequest",
        "type": "object"
      },
      "PermissionGroupIdRequest": {
        "properties": {
          "permission_group_id": {
            "title": "Permission Group Id",
            "type": "integer"
          }
        },
        "required": [
          "permission_group_id"
        ],
        "title": "PermissionGroupIdRequest",
        "type": "object"
      },
      "PermissionGroupOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "is_system": {
            "title": "Is System",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Id"
          },
          "permissions": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Permissions",
            "type": "array"
          }
        },
        "required": [
          "id",
          "name",
          "is_system"
        ],
        "title": "PermissionGroupOut",
        "type": "object"
      },
      "PermissionGroupsResponse": {
        "properties": {
          "permission_groups": {
            "items": {
              "$ref": "#/components/schemas/PermissionGroupOut"
            },
            "title": "Permission Groups",
            "type": "array"
          }
        },
        "required": [
          "permission_groups"
        ],
        "title": "PermissionGroupsResponse",
        "type": "object"
      },
      "PermissionKeyRequest": {
        "properties": {
          "permission_key": {
            "title": "Permission Key",
            "type": "string"
          }
        },
        "required": [
          "permission_key"
        ],
        "title": "PermissionKeyRequest",
        "type": "object"
      },
      "PersonalOrgOut": {
        "description": "`POST /v1/organizations/personal` (#2234): the new workspace and a\nfresh token that carries it as the caller's tenant.",
        "properties": {
          "access_token": {
            "title": "Access Token",
            "type": "string"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "created_via": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "How the organization was created. One of: `signup` (a self-service signup workspace), `platform_admin` (created by a Platform Admin), `owner` (created by the owner of an organization whose plan allows more), `suborg` (created under a parent organization); `conversion` and `import` are reserved. New values may be added: treat an unknown value as an unknown creation path. Read-only and never changed afterwards (a conversion to `standard` changes `kind`, not this). Null for organizations created before it was recorded.",
            "title": "Created Via"
          },
          "default_team_id": {
            "title": "Default Team Id",
            "type": "integer"
          },
          "expires_in": {
            "title": "Expires In",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "kind": {
            "anyOf": [
              {
                "enum": [
                  "personal",
                  "standard"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Organization kind: `personal` (the workspace a self-service signup creates, and its sub-organizations) or `standard`. A sub-organization always has its parent's kind. In `invite`/`closed` registration mode only the owners/admins of a `standard` organization (or a Platform Admin) can issue invites that create new accounts. Read-only; a Platform Admin converts with `POST /v1/organizations/{org_id}/convert`.",
            "title": "Kind"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "owner_user_id": {
            "title": "Owner User Id",
            "type": "integer"
          },
          "parent_organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Organization Id"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          },
          "token_type": {
            "default": "bearer",
            "title": "Token Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "owner_user_id",
          "default_team_id",
          "access_token",
          "expires_in"
        ],
        "title": "PersonalOrgOut",
        "type": "object"
      },
      "PinVersionRequest": {
        "description": "Body of ``PUT /v1/marketplace/installations/{installation_id}/pin``.",
        "properties": {
          "version": {
            "description": "A recorded version of the installed plugin (see /versions).",
            "maxLength": 50,
            "minLength": 1,
            "title": "Version",
            "type": "string"
          }
        },
        "required": [
          "version"
        ],
        "title": "PinVersionRequest",
        "type": "object"
      },
      "PlatformAdminClaimRequest": {
        "properties": {
          "code": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Code",
            "type": "string"
          }
        },
        "required": [
          "code"
        ],
        "title": "PlatformAdminClaimRequest",
        "type": "object"
      },
      "PlatformAdminClaimResponse": {
        "properties": {
          "granted": {
            "default": true,
            "title": "Granted",
            "type": "boolean"
          },
          "refresh_required": {
            "default": true,
            "title": "Refresh Required",
            "type": "boolean"
          }
        },
        "title": "PlatformAdminClaimResponse",
        "type": "object"
      },
      "PlatformAdminClaimStatus": {
        "properties": {
          "setup_code_required": {
            "title": "Setup Code Required",
            "type": "boolean"
          }
        },
        "required": [
          "setup_code_required"
        ],
        "title": "PlatformAdminClaimStatus",
        "type": "object"
      },
      "PluginAIToolItem": {
        "description": "One tool in ``GET /plugins/{plugin_id}/tools``.",
        "properties": {
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "endpoint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Endpoint"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Method"
          },
          "parameters": {
            "title": "Parameters"
          },
          "required_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Required Tier"
          },
          "response_format": {
            "title": "Response Format"
          },
          "tool_name": {
            "title": "Tool Name",
            "type": "string"
          },
          "type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Type"
          }
        },
        "required": [
          "id",
          "tool_name",
          "type",
          "description",
          "endpoint",
          "method",
          "parameters",
          "response_format",
          "required_tier",
          "active"
        ],
        "title": "PluginAIToolItem",
        "type": "object"
      },
      "PluginAIToolsResponse": {
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "plugin_name": {
            "title": "Plugin Name",
            "type": "string"
          },
          "tools": {
            "items": {
              "$ref": "#/components/schemas/PluginAIToolItem"
            },
            "title": "Tools",
            "type": "array"
          }
        },
        "required": [
          "plugin_id",
          "plugin_name",
          "tools",
          "count"
        ],
        "title": "PluginAIToolsResponse",
        "type": "object"
      },
      "PluginActionEnvelope": {
        "properties": {
          "action": {
            "title": "Action",
            "type": "string"
          },
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "result": {
            "description": "The plugin action's own return value.",
            "title": "Result"
          }
        },
        "required": [
          "plugin",
          "action",
          "result"
        ],
        "title": "PluginActionEnvelope",
        "type": "object"
      },
      "PluginConfigResponse": {
        "properties": {
          "api_version": {
            "title": "Api Version",
            "type": "string"
          },
          "capabilities": {
            "items": {
              "type": "string"
            },
            "title": "Capabilities",
            "type": "array"
          },
          "configurable": {
            "title": "Configurable",
            "type": "boolean"
          },
          "display": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display"
          },
          "json_schema": {
            "additionalProperties": true,
            "title": "Json Schema",
            "type": "object"
          },
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "requires": {
            "$ref": "#/components/schemas/PluginRequires"
          },
          "schema": {
            "items": {},
            "title": "Schema",
            "type": "array"
          },
          "ui_schema": {
            "additionalProperties": true,
            "title": "Ui Schema",
            "type": "object"
          },
          "values": {
            "additionalProperties": true,
            "title": "Values",
            "type": "object"
          }
        },
        "required": [
          "plugin",
          "configurable",
          "schema",
          "json_schema",
          "ui_schema",
          "values",
          "requires",
          "capabilities",
          "api_version"
        ],
        "title": "PluginConfigResponse",
        "type": "object"
      },
      "PluginConfigUpdateResponse": {
        "properties": {
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "updated": {
            "items": {
              "type": "string"
            },
            "title": "Updated",
            "type": "array"
          },
          "values": {
            "additionalProperties": true,
            "title": "Values",
            "type": "object"
          }
        },
        "required": [
          "plugin",
          "updated",
          "values"
        ],
        "title": "PluginConfigUpdateResponse",
        "type": "object"
      },
      "PluginConflictsResponse": {
        "properties": {
          "conflict_count": {
            "title": "Conflict Count",
            "type": "integer"
          },
          "conflicts": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Conflicts",
            "type": "array"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          }
        },
        "required": [
          "plugin_id",
          "conflicts",
          "conflict_count"
        ],
        "title": "PluginConflictsResponse",
        "type": "object"
      },
      "PluginCreate": {
        "description": "Model for creating a new plugin",
        "properties": {
          "author": {
            "maxLength": 100,
            "title": "Author",
            "type": "string"
          },
          "author_email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Email"
          },
          "base_tier": {
            "default": "community",
            "title": "Base Tier",
            "type": "string"
          },
          "category_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Id"
          },
          "current_version": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "developer_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Developer Id"
          },
          "display_name": {
            "maxLength": 200,
            "minLength": 1,
            "title": "Display Name",
            "type": "string"
          },
          "distribution_type": {
            "$ref": "#/components/schemas/DistributionType",
            "default": "git"
          },
          "docker_image": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Docker Image"
          },
          "manifest": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "The plugin manifest (JSON object) for reviewers to inspect. Data only: never executed. At most 64 KiB (compact UTF-8 JSON) and 32 levels deep. The userinfo (user:password@) of every URL in any string value or key is removed, including URLs inside free text. Can only change while the submission is a draft or rejected.",
            "title": "Manifest"
          },
          "name": {
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "pricing_model": {
            "$ref": "#/components/schemas/PricingModel",
            "default": "free"
          },
          "repository_url": {
            "anyOf": [
              {
                "format": "uri",
                "maxLength": 2083,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Repository Url"
          },
          "requires_services": {
            "items": {
              "type": "string"
            },
            "title": "Requires Services",
            "type": "array"
          },
          "screenshots": {
            "items": {
              "format": "uri",
              "maxLength": 2083,
              "minLength": 1,
              "type": "string"
            },
            "maxItems": 10,
            "title": "Screenshots",
            "type": "array"
          }
        },
        "required": [
          "name",
          "display_name",
          "author"
        ],
        "title": "PluginCreate",
        "type": "object"
      },
      "PluginDependenciesResponse": {
        "properties": {
          "dependencies": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Dependencies",
            "type": "array"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "possibly_truncated": {
            "title": "Possibly Truncated",
            "type": "boolean"
          },
          "total_count": {
            "title": "Total Count",
            "type": "integer"
          }
        },
        "required": [
          "plugin_id",
          "dependencies",
          "total_count",
          "possibly_truncated"
        ],
        "title": "PluginDependenciesResponse",
        "type": "object"
      },
      "PluginDetail": {
        "additionalProperties": true,
        "description": "``PluginInfo``, plus -- only when the plugin has a loaded instance -- its\nclient-facing surface (#1264): ``display`` (dict or null), ``requires``\n(``{services, optional_services, bundles}``), ``capabilities`` (overrides\nthe stored list) and ``api_version``. ``extra=\"allow\"`` so those additive,\ninstance-only keys pass through without appearing as nulls when absent.",
        "properties": {
          "author": {
            "title": "Author",
            "type": "string"
          },
          "capabilities": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Capabilities",
            "type": "array"
          },
          "configurable": {
            "default": false,
            "description": "Whether the running plugin declares a config schema, i.e. whether GET /v1/plugins/{name}/config has fields to edit. Computed from the loaded instance at request time; false when it isn't loaded.",
            "title": "Configurable",
            "type": "boolean"
          },
          "data_sources": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Data Sources",
            "type": "array"
          },
          "databases": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Databases",
            "type": "array"
          },
          "dependencies": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Dependencies",
            "type": "array"
          },
          "description": {
            "title": "Description",
            "type": "string"
          },
          "enabled": {
            "default": false,
            "title": "Enabled",
            "type": "boolean"
          },
          "health_status": {
            "default": "unknown",
            "title": "Health Status",
            "type": "string"
          },
          "install_source": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstallSource"
              },
              {
                "type": "null"
              }
            ],
            "description": "How the plugin was installed: `vendored` (code plugin loaded from PLUGINS_PATH), `git` (install-from-git) or `manifest` (manifest upload). Null only for a row written since the last boot by a path that doesn't record it; the next boot backfills it."
          },
          "last_health_check": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Health Check"
          },
          "marketplace_plugin_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Id of the marketplace catalog row this plugin is linked to, when it has one. Join on this, never on the plugin name.",
            "title": "Marketplace Plugin Id"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "registered_at": {
            "title": "Registered At",
            "type": "string"
          },
          "repository_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Source repository of a `git` install, without credentials, query or fragment. Null for every other install source.",
            "title": "Repository Url"
          },
          "status": {
            "default": "registered",
            "title": "Status",
            "type": "string"
          },
          "version": {
            "title": "Version",
            "type": "string"
          }
        },
        "required": [
          "name",
          "version",
          "description",
          "author",
          "registered_at"
        ],
        "title": "PluginDetail",
        "type": "object"
      },
      "PluginEnableResponse": {
        "properties": {
          "auto_enabled_dependencies": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ]
            },
            "title": "Auto Enabled Dependencies",
            "type": "array"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status",
          "plugin_id",
          "auto_enabled_dependencies"
        ],
        "title": "PluginEnableResponse",
        "type": "object"
      },
      "PluginInfo": {
        "description": "Plugin information",
        "properties": {
          "author": {
            "title": "Author",
            "type": "string"
          },
          "capabilities": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Capabilities",
            "type": "array"
          },
          "configurable": {
            "default": false,
            "description": "Whether the running plugin declares a config schema, i.e. whether GET /v1/plugins/{name}/config has fields to edit. Computed from the loaded instance at request time; false when it isn't loaded.",
            "title": "Configurable",
            "type": "boolean"
          },
          "data_sources": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Data Sources",
            "type": "array"
          },
          "databases": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Databases",
            "type": "array"
          },
          "dependencies": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Dependencies",
            "type": "array"
          },
          "description": {
            "title": "Description",
            "type": "string"
          },
          "enabled": {
            "default": false,
            "title": "Enabled",
            "type": "boolean"
          },
          "health_status": {
            "default": "unknown",
            "title": "Health Status",
            "type": "string"
          },
          "install_source": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InstallSource"
              },
              {
                "type": "null"
              }
            ],
            "description": "How the plugin was installed: `vendored` (code plugin loaded from PLUGINS_PATH), `git` (install-from-git) or `manifest` (manifest upload). Null only for a row written since the last boot by a path that doesn't record it; the next boot backfills it."
          },
          "last_health_check": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Health Check"
          },
          "marketplace_plugin_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Id of the marketplace catalog row this plugin is linked to, when it has one. Join on this, never on the plugin name.",
            "title": "Marketplace Plugin Id"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "registered_at": {
            "title": "Registered At",
            "type": "string"
          },
          "repository_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Source repository of a `git` install, without credentials, query or fragment. Null for every other install source.",
            "title": "Repository Url"
          },
          "status": {
            "default": "registered",
            "title": "Status",
            "type": "string"
          },
          "version": {
            "title": "Version",
            "type": "string"
          }
        },
        "required": [
          "name",
          "version",
          "description",
          "author",
          "registered_at"
        ],
        "title": "PluginInfo",
        "type": "object"
      },
      "PluginInstallResponse": {
        "properties": {
          "message": {
            "title": "Message",
            "type": "string"
          },
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "webhook_path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Path"
          }
        },
        "required": [
          "message",
          "plugin"
        ],
        "title": "PluginInstallResponse",
        "type": "object"
      },
      "PluginInstallationItem": {
        "properties": {
          "current_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "installed_at": {
            "title": "Installed At",
            "type": "string"
          },
          "pinned_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pinned Version"
          },
          "plugin_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "string"
              }
            ],
            "title": "Plugin Id"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status"
          },
          "update_available": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Update Available"
          },
          "user_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          },
          "version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Version"
          }
        },
        "required": [
          "id",
          "user_id",
          "plugin_id",
          "version",
          "status",
          "enabled",
          "installed_at"
        ],
        "title": "PluginInstallationItem",
        "type": "object"
      },
      "PluginInstallationsResponse": {
        "description": "Predates the shared ``PaginatedList`` envelope (#501).",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "installations": {
            "items": {
              "$ref": "#/components/schemas/PluginInstallationItem"
            },
            "title": "Installations",
            "type": "array"
          },
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "installations",
          "count",
          "total",
          "limit",
          "offset"
        ],
        "title": "PluginInstallationsResponse",
        "type": "object"
      },
      "PluginLicenseUpdateResponse": {
        "properties": {
          "license_key_masked": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "License Key Masked"
          },
          "license_tier": {
            "title": "License Tier",
            "type": "string"
          },
          "plugin_name": {
            "title": "Plugin Name",
            "type": "string"
          },
          "updated_at": {
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "plugin_name",
          "license_tier",
          "updated_at"
        ],
        "title": "PluginLicenseUpdateResponse",
        "type": "object"
      },
      "PluginOrigin": {
        "description": "Where a catalog listing came from. ``first_party`` (glossary:\nfirst-party) listings are created by the plugin registry for the code\nplugins it ships (auto-approved); ``submitted`` (glossary: community)\nlistings are developer submissions that go through review.",
        "enum": [
          "first_party",
          "submitted"
        ],
        "title": "PluginOrigin",
        "type": "string"
      },
      "PluginRatingsResponse": {
        "description": "GET /v1/marketplace/plugins/{plugin_id}/ratings -- the plugin's current\naggregate (same fields already shown on PluginResponse) plus the individual\nreviews, newest first.",
        "properties": {
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "rating_average": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating Average"
          },
          "rating_count": {
            "title": "Rating Count",
            "type": "integer"
          },
          "ratings": {
            "items": {
              "$ref": "#/components/schemas/RatingResponse"
            },
            "title": "Ratings",
            "type": "array"
          }
        },
        "required": [
          "plugin_id",
          "rating_average",
          "rating_count",
          "ratings"
        ],
        "title": "PluginRatingsResponse",
        "type": "object"
      },
      "PluginRecommendationsResponse": {
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "installed_plugins": {
            "items": {
              "type": "string"
            },
            "title": "Installed Plugins",
            "type": "array"
          },
          "recommendations": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Recommendations",
            "type": "array"
          }
        },
        "required": [
          "installed_plugins",
          "recommendations",
          "count"
        ],
        "title": "PluginRecommendationsResponse",
        "type": "object"
      },
      "PluginRegistryPluginListResponse": {
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "plugins": {
            "items": {
              "$ref": "#/components/schemas/PluginInfo"
            },
            "title": "Plugins",
            "type": "array"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "plugins",
          "count",
          "total",
          "limit",
          "offset"
        ],
        "title": "PluginListResponse",
        "type": "object"
      },
      "PluginRepositoryListResponse": {
        "description": "GET /v1/marketplace/repositories -- a page of source repositories.\n\nMirrors PluginListResponse's dual pagination envelope (canonical\n``limit``/``offset``/``total`` plus the deprecated ``page`` fields) so\nclients paginate repositories exactly as they already paginate plugins.",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "limit": {
            "default": 0,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "title": "Offset",
            "type": "integer"
          },
          "page": {
            "default": 1,
            "title": "Page",
            "type": "integer"
          },
          "page_size": {
            "default": 0,
            "title": "Page Size",
            "type": "integer"
          },
          "repositories": {
            "items": {
              "$ref": "#/components/schemas/PluginRepositoryResponse"
            },
            "title": "Repositories",
            "type": "array"
          },
          "total": {
            "default": 0,
            "title": "Total",
            "type": "integer"
          },
          "total_pages": {
            "default": 0,
            "title": "Total Pages",
            "type": "integer"
          }
        },
        "required": [
          "repositories",
          "count"
        ],
        "title": "PluginRepositoryListResponse",
        "type": "object"
      },
      "PluginRepositoryResponse": {
        "description": "One plugin source repository grouping zero or more plugins.",
        "properties": {
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "id": {
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "owner": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Owner"
          },
          "plugin_count": {
            "default": 0,
            "minimum": 0.0,
            "title": "Plugin Count",
            "type": "integer"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          },
          "source_url": {
            "anyOf": [
              {
                "format": "uri",
                "maxLength": 2083,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "slug",
          "name",
          "created_at",
          "updated_at"
        ],
        "title": "PluginRepositoryResponse",
        "type": "object"
      },
      "PluginRequires": {
        "properties": {
          "bundles": {
            "items": {
              "type": "string"
            },
            "title": "Bundles",
            "type": "array"
          },
          "optional_services": {
            "items": {
              "type": "string"
            },
            "title": "Optional Services",
            "type": "array"
          },
          "services": {
            "items": {
              "type": "string"
            },
            "title": "Services",
            "type": "array"
          }
        },
        "required": [
          "services",
          "optional_services",
          "bundles"
        ],
        "title": "PluginRequires",
        "type": "object"
      },
      "PluginResourceItemEnvelope": {
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "resource": {
            "title": "Resource",
            "type": "string"
          },
          "result": {
            "description": "The plugin resource's own item payload.",
            "title": "Result"
          }
        },
        "required": [
          "plugin",
          "resource",
          "id",
          "result"
        ],
        "title": "PluginResourceItemEnvelope",
        "type": "object"
      },
      "PluginResourceListEnvelope": {
        "properties": {
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "resource": {
            "title": "Resource",
            "type": "string"
          },
          "result": {
            "description": "The plugin resource's own list payload.",
            "title": "Result"
          }
        },
        "required": [
          "plugin",
          "resource",
          "result"
        ],
        "title": "PluginResourceListEnvelope",
        "type": "object"
      },
      "PluginResponse": {
        "description": "Model for plugin response",
        "properties": {
          "author": {
            "title": "Author",
            "type": "string"
          },
          "author_email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Email"
          },
          "base_tier": {
            "title": "Base Tier",
            "type": "string"
          },
          "category_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Id"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "current_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "developer_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Developer Id"
          },
          "display_name": {
            "title": "Display Name",
            "type": "string"
          },
          "distribution_type": {
            "$ref": "#/components/schemas/DistributionType"
          },
          "docker_image": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Docker Image"
          },
          "download_count": {
            "minimum": 0.0,
            "title": "Download Count",
            "type": "integer"
          },
          "featured": {
            "title": "Featured",
            "type": "boolean"
          },
          "id": {
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "origin": {
            "default": "first_party",
            "title": "Origin",
            "type": "string"
          },
          "pricing_model": {
            "$ref": "#/components/schemas/PricingModel"
          },
          "published_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Published At"
          },
          "rating_average": {
            "anyOf": [
              {
                "maximum": 5.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating Average"
          },
          "rating_count": {
            "minimum": 0.0,
            "title": "Rating Count",
            "type": "integer"
          },
          "repository_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Repository Id"
          },
          "repository_url": {
            "anyOf": [
              {
                "format": "uri",
                "maxLength": 2083,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Repository Url"
          },
          "requires_services": {
            "items": {
              "type": "string"
            },
            "title": "Requires Services",
            "type": "array"
          },
          "review_notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Notes"
          },
          "reviewed_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed At"
          },
          "reviewed_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed By"
          },
          "screenshots": {
            "items": {
              "format": "uri",
              "maxLength": 2083,
              "minLength": 1,
              "type": "string"
            },
            "title": "Screenshots",
            "type": "array"
          },
          "status": {
            "$ref": "#/components/schemas/PluginStatus"
          },
          "submitted_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Submitted At"
          },
          "submitted_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Submitted By"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "display_name",
          "description",
          "author",
          "author_email",
          "repository_url",
          "distribution_type",
          "docker_image",
          "current_version",
          "pricing_model",
          "base_tier",
          "status",
          "featured",
          "download_count",
          "rating_count",
          "created_at",
          "updated_at",
          "published_at"
        ],
        "title": "PluginResponse",
        "type": "object"
      },
      "PluginSemanticMatch": {
        "description": "One semantically-ranked plugin-catalog match (#1683).\n\nDeliberately a compact projection of the catalog row (not the full\nPluginResponse): this is consumed by the orchestrator's ``find_plugin`` AI\ntool, whose result is JSON-serialised straight into the model's context, so\nit carries only the fields a \"does a plugin for X already exist?\" answer\nneeds plus the similarity ``score``.",
        "properties": {
          "author": {
            "default": "",
            "title": "Author",
            "type": "string"
          },
          "base_tier": {
            "default": "",
            "title": "Base Tier",
            "type": "string"
          },
          "description": {
            "default": "",
            "title": "Description",
            "type": "string"
          },
          "display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "plugin_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Id"
          },
          "score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Score"
          }
        },
        "title": "PluginSemanticMatch",
        "type": "object"
      },
      "PluginSemanticSearchResponse": {
        "description": "Response for GET /v1/marketplace/plugins/semantic-search (#1683).",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "matches": {
            "items": {
              "$ref": "#/components/schemas/PluginSemanticMatch"
            },
            "title": "Matches",
            "type": "array"
          },
          "query": {
            "title": "Query",
            "type": "string"
          }
        },
        "required": [
          "query",
          "count"
        ],
        "title": "PluginSemanticSearchResponse",
        "type": "object"
      },
      "PluginStateChangeResponse": {
        "description": "Uninstall and disable replies.",
        "properties": {
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status",
          "plugin_id"
        ],
        "title": "PluginStateChangeResponse",
        "type": "object"
      },
      "PluginStatus": {
        "description": "Plugin status in marketplace.\n\n#402 submission lifecycle: DRAFT -> SUBMITTED -> IN_REVIEW -> APPROVED\n(publicly visible) / REJECTED (with notes; may resubmit) ; ARCHIVED (delist).\nAPPROVED is the publicly-visible state (existing read paths key on it);\nPENDING is the legacy pre-#402 value, kept for back-compat.",
        "enum": [
          "draft",
          "submitted",
          "in_review",
          "pending",
          "approved",
          "rejected",
          "archived"
        ],
        "title": "PluginStatus",
        "type": "string"
      },
      "PluginTierResponse": {
        "properties": {
          "plugin_name": {
            "title": "Plugin Name",
            "type": "string"
          },
          "required_tier": {
            "title": "Required Tier",
            "type": "string"
          }
        },
        "required": [
          "plugin_name",
          "required_tier"
        ],
        "title": "PluginTierResponse",
        "type": "object"
      },
      "PluginUpdate": {
        "description": "Model for updating a plugin",
        "properties": {
          "author": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author"
          },
          "base_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Base Tier"
          },
          "current_version": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "display_name": {
            "anyOf": [
              {
                "maxLength": 200,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "featured": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Featured"
          },
          "manifest": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Manifest"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 100,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "pricing_model": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PricingModel"
              },
              {
                "type": "null"
              }
            ]
          },
          "requires_services": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Requires Services"
          },
          "screenshots": {
            "anyOf": [
              {
                "items": {
                  "format": "uri",
                  "maxLength": 2083,
                  "minLength": 1,
                  "type": "string"
                },
                "maxItems": 10,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Screenshots"
          },
          "status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PluginStatus"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "title": "PluginUpdate",
        "type": "object"
      },
      "PluginVersionListResponse": {
        "description": "``GET /v1/marketplace/plugins/{plugin_id}/versions`` (#2199): every\nrecorded version, newest first by semantic version (versions that aren't\nsemantic versions follow, newest first by ``created_at``).",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "current_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "versions": {
            "items": {
              "$ref": "#/components/schemas/PluginVersionResponse"
            },
            "title": "Versions",
            "type": "array"
          }
        },
        "required": [
          "plugin_id",
          "versions",
          "count"
        ],
        "title": "PluginVersionListResponse",
        "type": "object"
      },
      "PluginVersionResponse": {
        "description": "One published version of a plugin (#2199). ``changelog``,\n``download_url``, ``size_bytes`` and ``checksum`` are null until the\nversion's source provides them.",
        "properties": {
          "changelog": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Changelog"
          },
          "checksum": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Checksum"
          },
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "download_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Artifact URL, without credentials.",
            "title": "Download Url"
          },
          "size_bytes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Size Bytes"
          },
          "version": {
            "title": "Version",
            "type": "string"
          }
        },
        "required": [
          "version"
        ],
        "title": "PluginVersionResponse",
        "type": "object"
      },
      "PortalResponse": {
        "properties": {
          "portal_url": {
            "title": "Portal Url",
            "type": "string"
          }
        },
        "required": [
          "portal_url"
        ],
        "title": "PortalResponse",
        "type": "object"
      },
      "PricingModel": {
        "description": "Pricing model types",
        "enum": [
          "free",
          "paid",
          "freemium"
        ],
        "title": "PricingModel",
        "type": "string"
      },
      "ProfileResponse": {
        "properties": {
          "can_create_workspace": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether POST /v1/organizations/personal would create a personal workspace for this account now: it has none, the installation lets accounts create their own and the free-organization limit allows it.",
            "title": "Can Create Workspace"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "preferences": {
            "additionalProperties": true,
            "title": "Preferences",
            "type": "object"
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          },
          "workspace_state": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "`ready` once the account belongs to an organization; `none` while it has no workspace yet (its token reaches only sign-in, profile, invite redemption and workspace creation); `pending_request` (reserved: set by access requests, #2235) while a request to join an organization is open. Null when it could not be determined.",
            "title": "Workspace State"
          }
        },
        "required": [
          "user_id"
        ],
        "title": "ProfileResponse",
        "type": "object"
      },
      "ProfileUpdateRequest": {
        "properties": {
          "display_name": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "preferences": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Preferences"
          }
        },
        "title": "ProfileUpdateRequest",
        "type": "object"
      },
      "RatingCreate": {
        "description": "Body for POST /v1/marketplace/plugins/{plugin_id}/ratings. 1-5 stars,\nmatching marketplace_plugins.rating_average's DECIMAL(3,2) ge=0/le=5.0\nrange (models/plugin.py) -- a whole-star scale, the common convention for\nthis kind of review.",
        "properties": {
          "rating": {
            "maximum": 5.0,
            "minimum": 1.0,
            "title": "Rating",
            "type": "integer"
          },
          "review_text": {
            "anyOf": [
              {
                "maxLength": 4000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Text"
          }
        },
        "required": [
          "rating"
        ],
        "title": "RatingCreate",
        "type": "object"
      },
      "RatingResponse": {
        "description": "One user's rating/review on a plugin.",
        "properties": {
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "rating": {
            "title": "Rating",
            "type": "integer"
          },
          "review_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Text"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          },
          "user_id": {
            "title": "User Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "plugin_id",
          "user_id",
          "rating",
          "review_text",
          "created_at",
          "updated_at"
        ],
        "title": "RatingResponse",
        "type": "object"
      },
      "RedeemResponse": {
        "properties": {
          "access_token": {
            "title": "Access Token",
            "type": "string"
          },
          "expires_in": {
            "title": "Expires In",
            "type": "integer"
          },
          "org_role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Org Role"
          },
          "organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Id"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "team_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Team Id"
          },
          "team_role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Team Role"
          }
        },
        "required": [
          "status",
          "access_token",
          "expires_in"
        ],
        "title": "RedeemResponse",
        "type": "object"
      },
      "RegisterRequest": {
        "properties": {
          "email": {
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "invite_token": {
            "anyOf": [
              {
                "maxLength": 128,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Invite Token"
          },
          "password": {
            "minLength": 8,
            "title": "Password",
            "type": "string"
          },
          "username": {
            "maxLength": 50,
            "minLength": 1,
            "pattern": "^[A-Za-z0-9_.-]+$",
            "title": "Username",
            "type": "string"
          }
        },
        "required": [
          "username",
          "email",
          "password"
        ],
        "title": "RegisterRequest",
        "type": "object"
      },
      "RegisterResponse": {
        "properties": {
          "message": {
            "default": "User created successfully",
            "title": "Message",
            "type": "string"
          },
          "organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The new account's home organization: the invite's organization (for a team invite, the team's organization) or, for a token-less `open` signup, the personal organization just created for it. The first token's `tenant_id`. Null when the account has no home organization yet.",
            "title": "Organization Id"
          },
          "team_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The team a team invite added the account to; null otherwise.",
            "title": "Team Id"
          },
          "user": {
            "$ref": "#/components/schemas/UserOut"
          }
        },
        "required": [
          "user"
        ],
        "title": "RegisterResponse",
        "type": "object"
      },
      "RequiredBundlesResponse": {
        "properties": {
          "confirmed": {
            "title": "Confirmed",
            "type": "boolean"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "required_bundles": {
            "items": {
              "type": "string"
            },
            "title": "Required Bundles",
            "type": "array"
          },
          "requiring_plugins": {
            "additionalProperties": {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            "title": "Requiring Plugins",
            "type": "object"
          }
        },
        "required": [
          "confirmed",
          "required_bundles",
          "requiring_plugins",
          "reason"
        ],
        "title": "RequiredBundlesResponse",
        "type": "object"
      },
      "ReviewActionRequest": {
        "description": "Optional reviewer notes for a transition (required on reject).",
        "properties": {
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          }
        },
        "title": "ReviewActionRequest",
        "type": "object"
      },
      "ReviewQueueListResponse": {
        "description": "The admin review queue (#2214): a plugin list page whose entries carry\nthe submitter's and reviewer's usernames.",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "limit": {
            "default": 0,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "title": "Offset",
            "type": "integer"
          },
          "page": {
            "title": "Page",
            "type": "integer"
          },
          "page_size": {
            "title": "Page Size",
            "type": "integer"
          },
          "plugins": {
            "items": {
              "$ref": "#/components/schemas/ReviewerPluginResponse"
            },
            "title": "Plugins",
            "type": "array"
          },
          "total": {
            "default": 0,
            "title": "Total",
            "type": "integer"
          },
          "total_pages": {
            "title": "Total Pages",
            "type": "integer"
          }
        },
        "required": [
          "plugins",
          "count",
          "page",
          "page_size",
          "total_pages"
        ],
        "title": "ReviewQueueListResponse",
        "type": "object"
      },
      "ReviewerPluginResponse": {
        "description": "A listing as the submission review routes return it (#2214): the catalog\nfields plus the usernames behind ``submitted_by`` / ``reviewed_by``.\n\nThe names are filled only for an admin (the review queue, and the\nsubmission detail); null for the submission's own developer, for an\nunknown/deleted account, or when the account directory can't be reached.\nNever an e-mail address. The public catalog never uses this model.",
        "properties": {
          "author": {
            "title": "Author",
            "type": "string"
          },
          "author_email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Email"
          },
          "base_tier": {
            "title": "Base Tier",
            "type": "string"
          },
          "category_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Id"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "current_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "developer_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Developer Id"
          },
          "display_name": {
            "title": "Display Name",
            "type": "string"
          },
          "distribution_type": {
            "$ref": "#/components/schemas/DistributionType"
          },
          "docker_image": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Docker Image"
          },
          "download_count": {
            "minimum": 0.0,
            "title": "Download Count",
            "type": "integer"
          },
          "featured": {
            "title": "Featured",
            "type": "boolean"
          },
          "id": {
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "origin": {
            "default": "first_party",
            "title": "Origin",
            "type": "string"
          },
          "pricing_model": {
            "$ref": "#/components/schemas/PricingModel"
          },
          "published_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Published At"
          },
          "rating_average": {
            "anyOf": [
              {
                "maximum": 5.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating Average"
          },
          "rating_count": {
            "minimum": 0.0,
            "title": "Rating Count",
            "type": "integer"
          },
          "repository_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Repository Id"
          },
          "repository_url": {
            "anyOf": [
              {
                "format": "uri",
                "maxLength": 2083,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Repository Url"
          },
          "requires_services": {
            "items": {
              "type": "string"
            },
            "title": "Requires Services",
            "type": "array"
          },
          "review_notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Notes"
          },
          "reviewed_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed At"
          },
          "reviewed_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed By"
          },
          "reviewed_by_username": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed By Username"
          },
          "screenshots": {
            "items": {
              "format": "uri",
              "maxLength": 2083,
              "minLength": 1,
              "type": "string"
            },
            "title": "Screenshots",
            "type": "array"
          },
          "status": {
            "$ref": "#/components/schemas/PluginStatus"
          },
          "submitted_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Submitted At"
          },
          "submitted_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Submitted By"
          },
          "submitted_by_username": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Submitted By Username"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "display_name",
          "description",
          "author",
          "author_email",
          "repository_url",
          "distribution_type",
          "docker_image",
          "current_version",
          "pricing_model",
          "base_tier",
          "status",
          "featured",
          "download_count",
          "rating_count",
          "created_at",
          "updated_at",
          "published_at"
        ],
        "title": "ReviewerPluginResponse",
        "type": "object"
      },
      "RoleAssignRequest": {
        "properties": {
          "expires_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "role_id": {
            "title": "Role Id",
            "type": "integer"
          }
        },
        "required": [
          "role_id"
        ],
        "title": "RoleAssignRequest",
        "type": "object"
      },
      "RoleAssignmentOut": {
        "properties": {
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "granted_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Granted At"
          },
          "granted_by": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Granted By"
          },
          "role_id": {
            "title": "Role Id",
            "type": "integer"
          },
          "role_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Role Name"
          }
        },
        "required": [
          "role_id"
        ],
        "title": "RoleAssignmentOut",
        "type": "object"
      },
      "RoleChangeRequest": {
        "properties": {
          "role": {
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "role"
        ],
        "title": "RoleChangeRequest",
        "type": "object"
      },
      "RoleCreateRequest": {
        "properties": {
          "name": {
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "scope": {
            "default": "organization",
            "title": "Scope",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "RoleCreateRequest",
        "type": "object"
      },
      "RoleOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "is_system": {
            "title": "Is System",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "organization_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Id"
          },
          "permissions": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Permissions",
            "type": "array"
          },
          "scope": {
            "title": "Scope",
            "type": "string"
          }
        },
        "required": [
          "id",
          "scope",
          "name",
          "is_system"
        ],
        "title": "RoleOut",
        "type": "object"
      },
      "RolesResponse": {
        "properties": {
          "roles": {
            "items": {
              "$ref": "#/components/schemas/RoleOut"
            },
            "title": "Roles",
            "type": "array"
          }
        },
        "required": [
          "roles"
        ],
        "title": "RolesResponse",
        "type": "object"
      },
      "RotatedLicense": {
        "properties": {
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "license_key_masked": {
            "title": "License Key Masked",
            "type": "string"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "id",
          "tenant_id",
          "plugin_id",
          "tier",
          "active",
          "license_key_masked"
        ],
        "title": "RotatedLicense",
        "type": "object"
      },
      "SecretKeysResponse": {
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "secret_keys": {
            "items": {
              "type": "string"
            },
            "title": "Secret Keys",
            "type": "array"
          }
        },
        "required": [
          "plugin",
          "secret_keys",
          "count"
        ],
        "title": "SecretKeysResponse",
        "type": "object"
      },
      "SecretStatusResponse": {
        "properties": {
          "plugin": {
            "title": "Plugin",
            "type": "string"
          },
          "secret_key": {
            "title": "Secret Key",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "plugin",
          "secret_key",
          "status"
        ],
        "title": "SecretStatusResponse",
        "type": "object"
      },
      "StatusChangeRequest": {
        "properties": {
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          }
        },
        "required": [
          "is_active"
        ],
        "title": "StatusChangeRequest",
        "type": "object"
      },
      "SubOrgCreateRequest": {
        "description": "Body for `POST /{org_id}/suborganizations` (#1650) -- creates a new\norganization with `parent_organization_id` set to `org_id`. Structurally\nidentical to `OrgCreateRequest` (a separate model rather than reusing it\nso the two routes' request shapes can evolve independently -- e.g. this\none never needs an instance-admin-only field).",
        "properties": {
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "owner_user_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Owner User Id"
          },
          "slug": {
            "maxLength": 100,
            "minLength": 1,
            "pattern": "^[a-zA-Z0-9._-]+$",
            "title": "Slug",
            "type": "string"
          }
        },
        "required": [
          "name",
          "slug"
        ],
        "title": "SubOrgCreateRequest",
        "type": "object"
      },
      "SubmissionDetailResponse": {
        "description": "One submission for review (#2214): the catalog fields plus the manifest\nthe developer submitted (null if none was supplied).",
        "properties": {
          "author": {
            "title": "Author",
            "type": "string"
          },
          "author_email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Email"
          },
          "base_tier": {
            "title": "Base Tier",
            "type": "string"
          },
          "category_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Id"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "current_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Version"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "developer_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Developer Id"
          },
          "display_name": {
            "title": "Display Name",
            "type": "string"
          },
          "distribution_type": {
            "$ref": "#/components/schemas/DistributionType"
          },
          "docker_image": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Docker Image"
          },
          "download_count": {
            "minimum": 0.0,
            "title": "Download Count",
            "type": "integer"
          },
          "featured": {
            "title": "Featured",
            "type": "boolean"
          },
          "id": {
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
            "title": "Id",
            "type": "string"
          },
          "manifest": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Manifest"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "origin": {
            "default": "first_party",
            "title": "Origin",
            "type": "string"
          },
          "pricing_model": {
            "$ref": "#/components/schemas/PricingModel"
          },
          "published_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Published At"
          },
          "rating_average": {
            "anyOf": [
              {
                "maximum": 5.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating Average"
          },
          "rating_count": {
            "minimum": 0.0,
            "title": "Rating Count",
            "type": "integer"
          },
          "repository_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Repository Id"
          },
          "repository_url": {
            "anyOf": [
              {
                "format": "uri",
                "maxLength": 2083,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Repository Url"
          },
          "requires_services": {
            "items": {
              "type": "string"
            },
            "title": "Requires Services",
            "type": "array"
          },
          "review_notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Notes"
          },
          "reviewed_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed At"
          },
          "reviewed_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed By"
          },
          "reviewed_by_username": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed By Username"
          },
          "screenshots": {
            "items": {
              "format": "uri",
              "maxLength": 2083,
              "minLength": 1,
              "type": "string"
            },
            "title": "Screenshots",
            "type": "array"
          },
          "status": {
            "$ref": "#/components/schemas/PluginStatus"
          },
          "submitted_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Submitted At"
          },
          "submitted_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Submitted By"
          },
          "submitted_by_username": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Submitted By Username"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "display_name",
          "description",
          "author",
          "author_email",
          "repository_url",
          "distribution_type",
          "docker_image",
          "current_version",
          "pricing_model",
          "base_tier",
          "status",
          "featured",
          "download_count",
          "rating_count",
          "created_at",
          "updated_at",
          "published_at"
        ],
        "title": "SubmissionDetailResponse",
        "type": "object"
      },
      "SubmissionHistoryEntry": {
        "description": "One recorded status transition of a submission (#2214), from\n``marketplace_plugin_reviews``.",
        "properties": {
          "actor": {
            "title": "Actor",
            "type": "string"
          },
          "actor_role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Actor Role"
          },
          "actor_username": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Actor Username"
          },
          "created_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "from_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "From Status"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "to_status": {
            "title": "To Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "to_status",
          "actor"
        ],
        "title": "SubmissionHistoryEntry",
        "type": "object"
      },
      "SubmissionHistoryResponse": {
        "description": "A page of a submission's review history, oldest first (#2214).",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "entries": {
            "items": {
              "$ref": "#/components/schemas/SubmissionHistoryEntry"
            },
            "title": "Entries",
            "type": "array"
          },
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "plugin_id",
          "entries",
          "count",
          "total",
          "limit",
          "offset"
        ],
        "title": "SubmissionHistoryResponse",
        "type": "object"
      },
      "SubscriptionResponse": {
        "properties": {
          "baseline": {
            "title": "Baseline",
            "type": "boolean"
          },
          "can_manage": {
            "title": "Can Manage",
            "type": "boolean"
          },
          "manageable": {
            "title": "Manageable",
            "type": "boolean"
          },
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          },
          "valid_until": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Valid Until"
          }
        },
        "required": [
          "tenant_id",
          "tier",
          "baseline",
          "status",
          "valid_until",
          "provider",
          "manageable",
          "can_manage"
        ],
        "title": "SubscriptionResponse",
        "type": "object"
      },
      "TeamCreate": {
        "description": "#2287: the team belongs to the caller's active organization (the org\ntheir token is acting in), never one named in the body. ``parent_team_id``\nmakes it a sub-team of a team in that same org.",
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "name": {
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "parent_team_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Team Id"
          }
        },
        "required": [
          "name"
        ],
        "title": "TeamCreate",
        "type": "object"
      },
      "TeamCreateOut": {
        "description": "Extends TeamOut with a fresh JWT for the creator (#1148, mirrors\n#1071's invite-redeem fix): the token this request was authenticated\nwith necessarily predates the caller's own new team_admin membership,\nand /v1/auth/refresh deliberately never re-derives `teams` (matching\n`role`'s existing staleness-until-next-login design) -- so without this,\nthe creator could not even share their OWN new team's content until an\nunrelated full logout/login.",
        "properties": {
          "access_token": {
            "title": "Access Token",
            "type": "string"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "created_by": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created By"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "expires_in": {
            "title": "Expires In",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "member_count": {
            "title": "Member Count",
            "type": "integer"
          },
          "membership_mode": {
            "default": "independent",
            "title": "Membership Mode",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "parent_team_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Team Id"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          }
        },
        "required": [
          "id",
          "name",
          "member_count",
          "access_token",
          "expires_in"
        ],
        "title": "TeamCreateOut",
        "type": "object"
      },
      "TeamDetailOut": {
        "properties": {
          "caller_can_manage": {
            "default": false,
            "description": "True when the caller may manage this team's members (team admin, delegated team or organization authority, or Platform Admin)",
            "title": "Caller Can Manage",
            "type": "boolean"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "created_by": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created By"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "emails_visible": {
            "default": true,
            "description": "False when the caller may not see members' email addresses; each member's email is then an empty string",
            "title": "Emails Visible",
            "type": "boolean"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "members": {
            "items": {
              "$ref": "#/components/schemas/TeamMemberOut"
            },
            "title": "Members",
            "type": "array"
          },
          "membership_mode": {
            "default": "independent",
            "title": "Membership Mode",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "parent_team_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Team Id"
          },
          "roster_visible": {
            "default": true,
            "description": "False when the caller may not see this team's roster; members is then empty",
            "title": "Roster Visible",
            "type": "boolean"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          }
        },
        "required": [
          "id",
          "name",
          "members"
        ],
        "title": "TeamDetailOut",
        "type": "object"
      },
      "TeamListResponse": {
        "properties": {
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "teams": {
            "items": {
              "$ref": "#/components/schemas/TeamOut"
            },
            "title": "Teams",
            "type": "array"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "teams",
          "total",
          "limit",
          "offset"
        ],
        "title": "TeamListResponse",
        "type": "object"
      },
      "TeamMemberOut": {
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          },
          "joined_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Joined At"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          },
          "team_role": {
            "title": "Team Role",
            "type": "string"
          },
          "user_id": {
            "title": "User Id",
            "type": "integer"
          },
          "username": {
            "title": "Username",
            "type": "string"
          }
        },
        "required": [
          "user_id",
          "username",
          "email",
          "team_role"
        ],
        "title": "TeamMemberOut",
        "type": "object"
      },
      "TeamMove": {
        "description": "Body for `POST /{team_id}/move` (#1651). `new_parent_team_id = None`\ndetaches the team to top-level -- the delete default's mirror image.",
        "properties": {
          "new_parent_team_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "New Parent Team Id"
          }
        },
        "title": "TeamMove",
        "type": "object"
      },
      "TeamOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "created_by": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created By"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "member_count": {
            "title": "Member Count",
            "type": "integer"
          },
          "membership_mode": {
            "default": "independent",
            "title": "Membership Mode",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "parent_team_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Team Id"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          }
        },
        "required": [
          "id",
          "name",
          "member_count"
        ],
        "title": "TeamOut",
        "type": "object"
      },
      "TeamUpdate": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "membership_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Membership Mode"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 100,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "title": "TeamUpdate",
        "type": "object"
      },
      "TenantLicense": {
        "description": "One row of ``core.licensing.get_tenant_licenses``.",
        "properties": {
          "activated_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Activated By"
          },
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "effective_tier": {
            "title": "Effective Tier",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "license_key_masked": {
            "title": "License Key Masked",
            "type": "string"
          },
          "plugin_display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Display Name"
          },
          "plugin_id": {
            "title": "Plugin Id",
            "type": "string"
          },
          "plugin_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Name"
          },
          "tenant_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tenant Id"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          },
          "trial_expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial Expires At"
          },
          "usage_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Usage Count"
          },
          "valid_from": {
            "title": "Valid From",
            "type": "string"
          },
          "valid_until": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Valid Until"
          }
        },
        "required": [
          "id",
          "tenant_id",
          "activated_by",
          "plugin_id",
          "plugin_name",
          "plugin_display_name",
          "tier",
          "effective_tier",
          "license_key_masked",
          "valid_from",
          "valid_until",
          "trial_expires_at",
          "active",
          "usage_count",
          "last_used_at"
        ],
        "title": "TenantLicense",
        "type": "object"
      },
      "TokenResponse": {
        "properties": {
          "access_token": {
            "title": "Access Token",
            "type": "string"
          },
          "expires_in": {
            "title": "Expires In",
            "type": "integer"
          },
          "token_type": {
            "default": "bearer",
            "title": "Token Type",
            "type": "string"
          },
          "user": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/UserOut"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "access_token",
          "expires_in"
        ],
        "title": "TokenResponse",
        "type": "object"
      },
      "ToolDiscoveryResponse": {
        "description": "Tool discovery response (paginated, #147/C6).",
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "limit": {
            "default": 0,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "title": "Offset",
            "type": "integer"
          },
          "tools": {
            "items": {
              "$ref": "#/components/schemas/ToolSchema"
            },
            "title": "Tools",
            "type": "array"
          },
          "total": {
            "default": 0,
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "tools",
          "count"
        ],
        "title": "ToolDiscoveryResponse",
        "type": "object"
      },
      "ToolExecutionRequest": {
        "description": "Tool execution request. There is deliberately no caller-supplied user_id:\nthe license/tier check must run against the VERIFIED caller (the JWT ``sub`` in\nroutes/tools.py), never a client-controlled field.",
        "properties": {
          "parameters": {
            "additionalProperties": true,
            "title": "Parameters",
            "type": "object"
          }
        },
        "title": "ToolExecutionRequest",
        "type": "object"
      },
      "ToolExecutionResponse": {
        "description": "Tool execution response.",
        "properties": {
          "execution_time": {
            "title": "Execution Time",
            "type": "number"
          },
          "plugin_name": {
            "title": "Plugin Name",
            "type": "string"
          },
          "result": {
            "title": "Result"
          },
          "tier_required": {
            "title": "Tier Required",
            "type": "string"
          },
          "tool_name": {
            "title": "Tool Name",
            "type": "string"
          }
        },
        "required": [
          "tool_name",
          "plugin_name",
          "result",
          "execution_time",
          "tier_required"
        ],
        "title": "ToolExecutionResponse",
        "type": "object"
      },
      "ToolParameter": {
        "description": "Tool parameter definition.",
        "properties": {
          "default": {
            "anyOf": [
              {},
              {
                "type": "null"
              }
            ],
            "title": "Default"
          },
          "description": {
            "title": "Description",
            "type": "string"
          },
          "enum": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enum"
          },
          "required": {
            "default": false,
            "title": "Required",
            "type": "boolean"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "description"
        ],
        "title": "ToolParameter",
        "type": "object"
      },
      "ToolSchema": {
        "description": "A single AI tool's declared schema.",
        "properties": {
          "description": {
            "title": "Description",
            "type": "string"
          },
          "endpoint": {
            "title": "Endpoint",
            "type": "string"
          },
          "method": {
            "title": "Method",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "parameters": {
            "additionalProperties": {
              "$ref": "#/components/schemas/ToolParameter"
            },
            "title": "Parameters",
            "type": "object"
          },
          "required_tier": {
            "title": "Required Tier",
            "type": "string"
          },
          "response_format": {
            "additionalProperties": true,
            "title": "Response Format",
            "type": "object"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "name",
          "description",
          "type",
          "parameters",
          "response_format",
          "endpoint",
          "method",
          "required_tier"
        ],
        "title": "ToolSchema",
        "type": "object"
      },
      "UpdateLicenseRequest": {
        "description": "Update a plugin's required license tier (+ optional key).",
        "properties": {
          "license_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "License Key"
          },
          "license_tier": {
            "$ref": "#/components/schemas/LicenseTier"
          }
        },
        "required": [
          "license_tier"
        ],
        "title": "UpdateLicenseRequest",
        "type": "object"
      },
      "UserListItem": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "email": {
            "title": "Email",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "is_oidc_linked": {
            "title": "Is Oidc Linked",
            "type": "boolean"
          },
          "memberships": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/UserMembership"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Memberships"
          },
          "role": {
            "title": "Role",
            "type": "string"
          },
          "username": {
            "title": "Username",
            "type": "string"
          }
        },
        "required": [
          "id",
          "username",
          "email",
          "role",
          "is_active",
          "is_oidc_linked"
        ],
        "title": "UserListItem",
        "type": "object"
      },
      "UserListResponse": {
        "properties": {
          "limit": {
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "title": "Offset",
            "type": "integer"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          },
          "users": {
            "items": {
              "$ref": "#/components/schemas/UserListItem"
            },
            "title": "Users",
            "type": "array"
          }
        },
        "required": [
          "users",
          "total",
          "limit",
          "offset"
        ],
        "title": "UserListResponse",
        "type": "object"
      },
      "UserMembership": {
        "properties": {
          "is_home": {
            "title": "Is Home",
            "type": "boolean"
          },
          "org_role": {
            "title": "Org Role",
            "type": "string"
          },
          "organization_id": {
            "title": "Organization Id",
            "type": "integer"
          },
          "slug": {
            "title": "Slug",
            "type": "string"
          },
          "suspended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suspended At"
          }
        },
        "required": [
          "organization_id",
          "slug",
          "org_role",
          "is_home"
        ],
        "title": "UserMembership",
        "type": "object"
      },
      "UserOut": {
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "email": {
            "title": "Email",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "integer"
          },
          "must_change_password": {
            "default": false,
            "title": "Must Change Password",
            "type": "boolean"
          },
          "role": {
            "title": "Role",
            "type": "string"
          },
          "username": {
            "title": "Username",
            "type": "string"
          }
        },
        "required": [
          "id",
          "username",
          "email",
          "role"
        ],
        "title": "UserOut",
        "type": "object"
      },
      "ValidateLicenseRequest": {
        "description": "Validate-license request. The key lives in the body, not the URL query, so a\nsecret isn't logged in access logs / proxies (#147/C7).",
        "properties": {
          "license_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "License Key"
          }
        },
        "title": "ValidateLicenseRequest",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "WebhookReloadResponse": {
        "properties": {
          "message": {
            "title": "Message",
            "type": "string"
          },
          "registered_routes": {
            "items": {
              "type": "string"
            },
            "title": "Registered Routes",
            "type": "array"
          },
          "webhook_path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Path"
          }
        },
        "required": [
          "message",
          "registered_routes"
        ],
        "title": "WebhookReloadResponse",
        "type": "object"
      },
      "models__tool_execution__LicenseValidationResponse": {
        "description": "License validation response (tool-access check).",
        "properties": {
          "allowed": {
            "title": "Allowed",
            "type": "boolean"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "tier_required": {
            "title": "Tier Required",
            "type": "string"
          },
          "user_tier": {
            "title": "User Tier",
            "type": "string"
          }
        },
        "required": [
          "allowed",
          "tier_required",
          "user_tier"
        ],
        "title": "LicenseValidationResponse",
        "type": "object"
      },
      "routes__licensing__LicenseValidationResponse": {
        "properties": {
          "message": {
            "title": "Message",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          },
          "valid": {
            "title": "Valid",
            "type": "boolean"
          }
        },
        "required": [
          "valid",
          "tier",
          "message"
        ],
        "title": "LicenseValidationResponse",
        "type": "object"
      }
    }
  },
  "info": {
    "description": "Client-facing contract of the Minder API Gateway: the gateway's own routes plus the concrete marketplace and plugin-registry routes it proxies, at the paths the gateway exposes them.",
    "title": "Minder API Gateway",
    "version": "snapshot"
  },
  "openapi": "3.1.0",
  "paths": {
    "/health": {
      "get": {
        "description": "Health check with phase-aware downstream dependency status.",
        "operationId": "health_check_health_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Health Check"
      }
    },
    "/metrics": {
      "get": {
        "description": "Prometheus metrics endpoint",
        "operationId": "metrics_metrics_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Metrics"
      }
    },
    "/public/chat/{slug}/feedback": {
      "post": {
        "description": "Leave feedback (thumbs up/down + optional text) on one chat response.\n\nSame trust boundary as ``/message``: the anonymous session token is validated\nand scope-checked against THIS endpoint (a token for endpoint A can't rate on\nendpoint B), the per-endpoint rate limit applies, and the feedback is written\nonly through the internal service call to rag-pipeline — which re-verifies the\nrated turn is the session's OWN before storing (a session can't rate another\nsession's turns; a mismatch is a 404). The rating is the session's alone: its\nid comes from the token, never the request body.",
        "operationId": "post_public_feedback_public_chat__slug__feedback_post",
        "parameters": [
          {
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatFeedback"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Post Public Feedback",
        "tags": [
          "Public Chat"
        ]
      }
    },
    "/public/chat/{slug}/message": {
      "post": {
        "description": "Send a chat message on an anonymous session.\n\nValidates the session token's scope against this endpoint, enforces the\nper-endpoint rate limit, then runs ONLY the endpoint's bound pipeline (its\nKB[s]) via an internal service call to rag-pipeline, persisting the turn under\nthe endpoint's anonymous-session namespace. The anon token reaches nothing\nelse in the tenant.",
        "operationId": "post_public_message_public_chat__slug__message_post",
        "parameters": [
          {
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatMessage"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Post Public Message",
        "tags": [
          "Public Chat"
        ]
      }
    },
    "/public/chat/{slug}/session": {
      "post": {
        "description": "Start an anonymous chat session against a public endpoint.\n\nReturns a short-lived signed anonymous session token scoped to THIS endpoint\n+ its tenant. Rate-limited per endpoint so session minting can't be abused to\nfan out load. No Minder account is created or required.",
        "operationId": "start_public_session_public_chat__slug__session_post",
        "parameters": [
          {
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Start Public Session",
        "tags": [
          "Public Chat"
        ]
      }
    },
    "/v1/ai/{path}": {
      "get": {
        "description": "Proxy /v1/ai/* to the orchestrator service. Orchestrator's own routes\nalready carry the full `/v1/ai/...` prefix (like plugin_registry/marketplace),\nso forward the full path back, not just `path`.\n\nDeliberately NOT gated by `_require_jwt_for_writes`, unlike every other\nproxy route here: these routes had their own deliberately fine-grained,\nNON-blanket auth model when they lived natively on api-gateway, and that\nbehavior must not change on extraction. `GET /v1/ai/functions/definitions`\nand `GET /v1/ai/tools/openapi.json` are unauthenticated on purpose\n(OpenWebUI's Tool Server can't attach a JWT to its discovery fetch);\n`POST /v1/ai/functions/{name}` (execute_function) is a pure pass-through\nwith no gateway-level requirement -- it forwards whatever Authorization\nheader the caller sent to the tool's own endpoint, which enforces its own\nauth per-action (some plugin actions are deliberately open, #254); only\n`POST /v1/ai/chat/completions` requires a JWT, enforced by orchestrator's\nown route dependency, unchanged since before the extraction. Adding\n`_require_jwt_for_writes` here would newly block unauthenticated tool\nexecution for open actions -- a real regression, not a hardening.\n\nLong timeout: the multi-turn tool loop and model inference can run well\npast the shared client's 30s default (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_orchestrator_v1_ai__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Orchestrator"
      },
      "post": {
        "description": "Proxy /v1/ai/* to the orchestrator service. Orchestrator's own routes\nalready carry the full `/v1/ai/...` prefix (like plugin_registry/marketplace),\nso forward the full path back, not just `path`.\n\nDeliberately NOT gated by `_require_jwt_for_writes`, unlike every other\nproxy route here: these routes had their own deliberately fine-grained,\nNON-blanket auth model when they lived natively on api-gateway, and that\nbehavior must not change on extraction. `GET /v1/ai/functions/definitions`\nand `GET /v1/ai/tools/openapi.json` are unauthenticated on purpose\n(OpenWebUI's Tool Server can't attach a JWT to its discovery fetch);\n`POST /v1/ai/functions/{name}` (execute_function) is a pure pass-through\nwith no gateway-level requirement -- it forwards whatever Authorization\nheader the caller sent to the tool's own endpoint, which enforces its own\nauth per-action (some plugin actions are deliberately open, #254); only\n`POST /v1/ai/chat/completions` requires a JWT, enforced by orchestrator's\nown route dependency, unchanged since before the extraction. Adding\n`_require_jwt_for_writes` here would newly block unauthenticated tool\nexecution for open actions -- a real regression, not a hardening.\n\nLong timeout: the multi-turn tool loop and model inference can run well\npast the shared client's 30s default (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_orchestrator_v1_ai__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Orchestrator"
      }
    },
    "/v1/audit-logs": {
      "get": {
        "description": "List audit entries, newest first, paginated. Instance-admin only.\n\nOptional filters: actor_id, action (e.g. ROLE_CHANGE), target_type,\nscope_type (org / platform / self / legacy).",
        "operationId": "get_audit_logs_v1_audit_logs_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "actor_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Actor Id"
            }
          },
          {
            "in": "query",
            "name": "action",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Action"
            }
          },
          {
            "in": "query",
            "name": "target_type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Target Type"
            }
          },
          {
            "in": "query",
            "name": "scope_type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^(org|platform|self|legacy)$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Scope Type"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Audit Logs",
        "tags": [
          "Audit"
        ]
      }
    },
    "/v1/auth/capabilities": {
      "get": {
        "description": "What the sign-in page may offer. Public; booleans, the registration\nmode and the reset-link lifetime only (no other configuration detail).",
        "operationId": "auth_capabilities_v1_auth_capabilities_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CapabilitiesResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Auth Capabilities",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/change-password": {
      "post": {
        "description": "Change the caller's OWN local password (#1776).\n\nAuthenticated: the account is taken from the JWT ``sub`` claim, never from\nthe body, so there is no way to address another user's password here. The\ncurrent password must be re-supplied (a stolen/borrowed bearer token alone\nmust not be enough to lock the owner out). SSO-linked (Authelia) accounts\nget 409 -- their credential is managed in the Authelia portal, not here.\n\n#1991: the change revokes EVERY existing session of the account (a session\nopened with the old, possibly stolen, password must not survive it),\nincluding the token this request carried. So the response is 200 with a\nreplacement ``access_token`` (the ``/refresh`` shape) minted for the new\nsession generation: the caller stays signed in on this device by adopting\nit. It was ``204`` with no body before; a client that ignores the body is\nsigned out by its next request.\n\n#2075: if the replacement token can't be minted AFTER the change has\ncommitted, the answer is 401 \"Password changed ... sign in again\" -- the\nnew password is in effect and every session (this one too) is revoked, so\nthe caller signs in again with it. Never an unhandled 500.",
        "operationId": "change_password_v1_auth_change_password_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Change Password",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/login": {
      "post": {
        "description": "Verify credentials (bcrypt) against PostgreSQL and return a JWT.",
        "operationId": "login_v1_auth_login_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Login",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/oidc/callback": {
      "get": {
        "description": "Finish the Authelia SSO redirect: verify the round-tripped state,\nexchange the code for an ID token, verify it, provision/link the Minder\nuser, then hand the browser off to the client with a Minder JWT -- same\nshape /v1/auth/login issues, so no downstream service needs to change.",
        "operationId": "oidc_callback_v1_auth_oidc_callback_get",
        "parameters": [
          {
            "in": "query",
            "name": "code",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Code"
            }
          },
          {
            "in": "query",
            "name": "state",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "State"
            }
          },
          {
            "in": "query",
            "name": "error",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Error"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Oidc Callback",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/oidc/login": {
      "get": {
        "description": "Start the Authelia SSO redirect -- the platform's single login entry\npoint (#<issue>). state/nonce are round-tripped through short-lived\nhttponly cookies rather than server-side session storage: this is pure\nCSRF/replay defense for one redirect, not a session (the actual session\nis the Minder JWT oidc_callback mints below, same as local login).\n\n#2134: an optional client nonce `cnonce` is bound the same way (httponly\ncookie set here, at the start of the login) and echoed back only in the\nfinal client redirect's fragment. The callback never reads it from its own\nquery string. Without `cnonce` the flow is unchanged (older clients).",
        "operationId": "oidc_login_v1_auth_oidc_login_get",
        "parameters": [
          {
            "in": "query",
            "name": "cnonce",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cnonce"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Oidc Login",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/password-reset/confirm": {
      "post": {
        "description": "Set a new password with a reset token (from the link's fragment, POSTed\nby the client on an explicit submit). Revokes every session; the user then\nsigns in with the new password (no auto-login).",
        "operationId": "password_reset_confirm_v1_auth_password_reset_confirm_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordResetConfirmBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Password Reset Confirm",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/password-reset/request": {
      "post": {
        "description": "Ask for a reset link. Always the same 202, whether or not the address\nhas an account, is SSO-linked, deactivated, undeliverable, privileged or\nover a limit -- the outcome is only ever visible to operators (audit,\nmetrics). No bcrypt, no SMTP: mail is queued and sent by the worker.",
        "operationId": "password_reset_request_v1_auth_password_reset_request_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordResetRequestBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasswordResetAccepted"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Password Reset Request",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/platform-admin/claim": {
      "get": {
        "description": "Whether the caller should be offered \"Enter the setup code from your\nserver\" (#2005): true only for an active instance admin on an upgraded\nself-host that has no Platform Admin yet. Never returns the code.",
        "operationId": "platform_admin_claim_status_v1_auth_platform_admin_claim_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAdminClaimStatus"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Platform Admin Claim Status",
        "tags": [
          "Authentication"
        ]
      },
      "post": {
        "description": "Claim Platform Admin with the one-time setup code printed on the server\n(#2005). On success, refresh the token (POST /v1/auth/refresh) to pick up\nthe ``is_platform_admin`` claim. Refused attempts are audited and\nrate-limited (per user and per IP) and capped per user per issued code.",
        "operationId": "platform_admin_claim_v1_auth_platform_admin_claim_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlatformAdminClaimRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAdminClaimResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Platform Admin Claim",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/refresh": {
      "post": {
        "description": "Refresh a JWT from a valid bearer token (sent in the Authorization header).\n\n#1167: re-validates against the DB rather than blindly renewing. The account\nkill-switch must actually work -- a user disabled (`is_active = false`) or\ndeleted after login can no longer refresh (401), instead of keeping access\nindefinitely by refreshing within each expiry window. While we're hitting the\nDB, `role` and `teams` are re-derived from current state too, so an admin\ndemotion or team membership change propagates on the next refresh instead of\nonly on a full re-login (this supersedes the old deliberate staleness).",
        "operationId": "refresh_token_v1_auth_refresh_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Refresh Token",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/register": {
      "post": {
        "description": "Register a new user (username/email/password, min 8 chars). 201 on success.\n\nAlways creates a \"user\"-role account (#474) -- admin is only ever granted via\nAuthelia OIDC group membership, never self-assignable through this endpoint.\n\n#1073/#2002: gated by INSTANCE_REGISTRATION_MODE (`open`, `invite` or\n`closed`; config `sso_only` means `closed`, an unknown value stops startup).\n`closed` disables local self-registration entirely (SSO-only) -> 403.\n`invite` requires a valid, unexpired, unused `invite_token`: no token ->\n403 `invite_required`; an unknown, revoked, used-up or expired one -> 403\n`invite_invalid`; an invite that may not create an account right now ->\n403 `invite_cannot_create_account` (it can still be redeemed from an\nexisting account); an email-bound invite for another address -> 403\n`invite_email_mismatch`. An invite creates an account only if its org (a\nteam invite: the team's org) is not suspended and its issuer is a Platform\nAdmin, or an owner/admin of that org (#2186) while the org is `standard`\nor the mode is `open` (#2191). The account is created and the invite\nconsumed (team/org membership + one use) in ONE transaction. `open` lets\nanyone register; a token, if given, is honoured the same way.\n\n#2187: an account created through an invite (any mode) gets the invite's\norg -- a team invite: the team's org -- as its home org and NO personal\norg. A token-less `open` signup gets its own `personal` org (#2191)\nwhile `SELF_SERVE_PERSONAL_ORGS` resolves true (#2234; unset = true in\n`open`); otherwise the account has no organization yet\n(`workspace_state: none` on `GET /v1/profile/me`). The\nresponse's `organization_id`/`team_id` say where the client should land\n(the home org the first token carries; null when there is none).",
        "operationId": "register_v1_auth_register_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegisterResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Register",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/v1/auth/users": {
      "get": {
        "description": "List users across every tenant, paginated. Platform Admin only (#1850).\n\n``?org_id=`` restricts the page to that org's members (ADR Decision 3);\neach item carries all of the user's ``memberships``. There is deliberately\nno caller-scoped variant: org admins use ``GET /v1/organizations/{org_id}/\nmembers``, so this URL never returns different populations per caller.",
        "operationId": "get_users_v1_auth_users_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "org_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Org Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Users",
        "tags": [
          "User Management"
        ]
      }
    },
    "/v1/auth/users/{user_id}/reset-password": {
      "post": {
        "description": "Reset another user's LOCAL password (#1776). Platform Admin only (#1850).\n\n``mode: \"set\"`` takes the admin's ``new_password``; ``mode: \"generate\"``\nreturns a strong server-generated ``temporary_password`` exactly once. Either\nway the user must change it on next login (``must_change_password``) and all\nof their existing sessions stop refreshing (see core.auth).\n\nSame authorization scope as the #1803 status endpoint: a DB-rechecked\nPlatform Admin. Anyone else -- an org admin, or a legacy ``role = 'admin'``\nwithout ``is_platform_admin`` -- gets 403 pointing at the org-scoped reset\nroute. Callers can't reset themselves here (use /v1/auth/change-password);\nSSO-linked accounts get 409 (their credential lives in the IdP).",
        "operationId": "reset_user_password_v1_auth_users__user_id__reset_password_post",
        "parameters": [
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordResetRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasswordResetResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Reset User Password",
        "tags": [
          "User Management"
        ]
      }
    },
    "/v1/auth/users/{user_id}/role": {
      "patch": {
        "description": "Change a user's instance role. Platform Admin only (#1850); the instance\nrole no longer implies ``is_platform_admin`` (ADR Decision 4).\n\nRejects OIDC-linked accounts with a 409 (see core.auth.update_user_role's\ndocstring) -- their `role` is rewritten on every OIDC login (from Authelia\ngroup membership on a self-host, always 'user' in SaaS mode, #1849), so\nthis endpoint would silently be undone otherwise.",
        "operationId": "change_user_role_v1_auth_users__user_id__role_patch",
        "parameters": [
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleChangeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserListItem"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Change User Role",
        "tags": [
          "User Management"
        ]
      }
    },
    "/v1/auth/users/{user_id}/status": {
      "patch": {
        "description": "Deactivate (``is_active: false``) or reactivate an account (#1803).\n\nPlatform Admin only (#1850, ADR Decision 1): the path, request and response\nshape are unchanged, but a non-platform caller -- including a legacy\n``role = 'admin'`` without ``is_platform_admin`` -- gets 403 pointing at the\norg-scoped ``PATCH /v1/organizations/{org_id}/members/{user_id}/account-status``\nrather than this route silently changing meaning per caller.\n\nA soft, reversible removal: the account can no longer sign in (password or\nSSO) or refresh its token, but its row and data stay intact. Already-issued\naccess tokens are refused on every request too (#1933,\n``core.token_liveness``), and deactivation stamps ``sessions_revoked_at`` so\nreactivating doesn't revive them.\n\nA caller can't deactivate their own account here (self-lockout; ask another\nPlatform Admin), and neither the last active Platform Admin (#1850), the\nlast remaining active instance admin, nor the only active owner of any\norganization can be deactivated at all (409 from core.auth.set_user_active;\nthe org last-owner guard is shared with the org-scoped route, #1935).",
        "operationId": "change_user_status_v1_auth_users__user_id__status_patch",
        "parameters": [
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StatusChangeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserListItem"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Change User Status",
        "tags": [
          "User Management"
        ]
      }
    },
    "/v1/backups": {
      "get": {
        "description": "Proxy /v1/backups (list archives, enqueue a backup job) to Platform\nOps -- also admin-gated downstream, but a POST here now carries the\ngateway's own JWT-for-writes check (#1325) for consistency with the other\nwrite-capable proxy routes; GET stays open (Authelia's job, #15).",
        "operationId": "proxy_to_backups_root_v1_backups_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Proxy To Backups Root"
      },
      "post": {
        "description": "Proxy /v1/backups (list archives, enqueue a backup job) to Platform\nOps -- also admin-gated downstream, but a POST here now carries the\ngateway's own JWT-for-writes check (#1325) for consistency with the other\nwrite-capable proxy routes; GET stays open (Authelia's job, #15).",
        "operationId": "proxy_to_backups_root_v1_backups_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Proxy To Backups Root"
      }
    },
    "/v1/backups/{path}": {
      "get": {
        "description": "Proxy /v1/backups/* (job listing/status, enqueue a restore job) to\nPlatform Ops -- also admin-gated downstream; a POST (e.g. enqueue a\nrestore) now carries the gateway JWT-for-writes check (#1325) like the\nother write routes.",
        "operationId": "proxy_to_backups_v1_backups__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Backups"
      },
      "post": {
        "description": "Proxy /v1/backups/* (job listing/status, enqueue a restore job) to\nPlatform Ops -- also admin-gated downstream; a POST (e.g. enqueue a\nrestore) now carries the gateway JWT-for-writes check (#1325) like the\nother write routes.",
        "operationId": "proxy_to_backups_v1_backups__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Backups"
      }
    },
    "/v1/billing/checkout": {
      "post": {
        "description": "Create a LemonSqueezy hosted checkout for the caller's org to buy ``tier``.\nReturns the checkout URL for the client to redirect to. Needs billing-manage\nauthority (#2036). Limited to 10 calls per minute per caller (429 beyond\nthat, #2365). The checkout URL expires after 24 hours (#2365). 422 when the\ncaller's tenant isn't an organization (e.g. a service token).",
        "operationId": "create_checkout_v1_billing_checkout_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Checkout",
        "tags": [
          "Billing"
        ]
      }
    },
    "/v1/billing/portal": {
      "post": {
        "description": "Return the LemonSqueezy customer-portal URL for the caller's org's current\nsubscription (manage/cancel/update payment). Needs billing-manage authority\n(#2036) -- the portal can cancel the org's subscription.",
        "operationId": "billing_portal_v1_billing_portal_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Billing Portal",
        "tags": [
          "Billing"
        ]
      }
    },
    "/v1/billing/subscription": {
      "get": {
        "description": "The caller org's current billing state: the tier that ACTUALLY applies right\nnow (``effective_tier`` — active + unexpired, else the free baseline), the raw\nentitlement's status/renewal/provider, and whether it's self-manageable via the\ncustomer portal.\n\nAlways 200 — an org with no billing event on file is a first-class state\n(``tier`` = baseline, ``status`` = None, ``manageable`` = false), not a 404. No\nprovider config is required to read this (unlike checkout/portal), so the client\ncan always render the current plan. Needs billing-view authority (#2036).",
        "operationId": "get_subscription_v1_billing_subscription_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Subscription",
        "tags": [
          "Billing"
        ]
      }
    },
    "/v1/bundles": {
      "get": {
        "description": "Proxy GET /v1/bundles to Platform Ops",
        "operationId": "list_bundles_v1_bundles_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Bundles"
      }
    },
    "/v1/bundles/{path}": {
      "get": {
        "description": "Proxy /v1/bundles/* (enable/disable/reconcile) to Platform Ops.\nPlatform Ops's own routes already carry the full `/v1/bundles/...`\nprefix, so forward the full path back, not just `path` (writes require JWT).",
        "operationId": "proxy_to_bundles_v1_bundles__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Bundles"
      },
      "post": {
        "description": "Proxy /v1/bundles/* (enable/disable/reconcile) to Platform Ops.\nPlatform Ops's own routes already carry the full `/v1/bundles/...`\nprefix, so forward the full path back, not just `path` (writes require JWT).",
        "operationId": "proxy_to_bundles_v1_bundles__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Bundles"
      }
    },
    "/v1/containers/{path}": {
      "get": {
        "description": "Proxy /v1/containers/* (recent container logs, for the Status page) to\nPlatform Ops -- JWT-gated there (not here), since a log read is\nsensitive but this route only carries GETs, which _require_jwt_for_writes\nnever gates.",
        "operationId": "proxy_to_containers_v1_containers__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Containers"
      }
    },
    "/v1/conversations/{path}": {
      "delete": {
        "description": "Proxy /v1/conversations/* to RAG Pipeline.\n\nThe conversation-history endpoints (e.g. GET /v1/conversations/mine, #934)\nlive on rag-pipeline under their own /v1/conversations/* path, not nested\nunder /v1/rag/* -- a conversation isn't scoped to a pipeline (see\nlist_my_conversations' own docstring), so it gets its own top-level proxy\nroute here rather than being folded into proxy_to_rag_pipeline above.\nWithout this, the client's Conversations page 404s at the gateway before\never reaching rag-pipeline -- caught on a live deployment, not by unit tests\n(which mock the client's fetch layer and never exercise real routing).",
        "operationId": "proxy_to_conversations_v1_conversations__path__delete",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Conversations"
      },
      "get": {
        "description": "Proxy /v1/conversations/* to RAG Pipeline.\n\nThe conversation-history endpoints (e.g. GET /v1/conversations/mine, #934)\nlive on rag-pipeline under their own /v1/conversations/* path, not nested\nunder /v1/rag/* -- a conversation isn't scoped to a pipeline (see\nlist_my_conversations' own docstring), so it gets its own top-level proxy\nroute here rather than being folded into proxy_to_rag_pipeline above.\nWithout this, the client's Conversations page 404s at the gateway before\never reaching rag-pipeline -- caught on a live deployment, not by unit tests\n(which mock the client's fetch layer and never exercise real routing).",
        "operationId": "proxy_to_conversations_v1_conversations__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Conversations"
      },
      "patch": {
        "description": "Proxy /v1/conversations/* to RAG Pipeline.\n\nThe conversation-history endpoints (e.g. GET /v1/conversations/mine, #934)\nlive on rag-pipeline under their own /v1/conversations/* path, not nested\nunder /v1/rag/* -- a conversation isn't scoped to a pipeline (see\nlist_my_conversations' own docstring), so it gets its own top-level proxy\nroute here rather than being folded into proxy_to_rag_pipeline above.\nWithout this, the client's Conversations page 404s at the gateway before\never reaching rag-pipeline -- caught on a live deployment, not by unit tests\n(which mock the client's fetch layer and never exercise real routing).",
        "operationId": "proxy_to_conversations_v1_conversations__path__patch",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Conversations"
      },
      "post": {
        "description": "Proxy /v1/conversations/* to RAG Pipeline.\n\nThe conversation-history endpoints (e.g. GET /v1/conversations/mine, #934)\nlive on rag-pipeline under their own /v1/conversations/* path, not nested\nunder /v1/rag/* -- a conversation isn't scoped to a pipeline (see\nlist_my_conversations' own docstring), so it gets its own top-level proxy\nroute here rather than being folded into proxy_to_rag_pipeline above.\nWithout this, the client's Conversations page 404s at the gateway before\never reaching rag-pipeline -- caught on a live deployment, not by unit tests\n(which mock the client's fetch layer and never exercise real routing).",
        "operationId": "proxy_to_conversations_v1_conversations__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Conversations"
      },
      "put": {
        "description": "Proxy /v1/conversations/* to RAG Pipeline.\n\nThe conversation-history endpoints (e.g. GET /v1/conversations/mine, #934)\nlive on rag-pipeline under their own /v1/conversations/* path, not nested\nunder /v1/rag/* -- a conversation isn't scoped to a pipeline (see\nlist_my_conversations' own docstring), so it gets its own top-level proxy\nroute here rather than being folded into proxy_to_rag_pipeline above.\nWithout this, the client's Conversations page 404s at the gateway before\never reaching rag-pipeline -- caught on a live deployment, not by unit tests\n(which mock the client's fetch layer and never exercise real routing).",
        "operationId": "proxy_to_conversations_v1_conversations__path__put",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Conversations"
      }
    },
    "/v1/entitlements/capabilities/{tenant_id}": {
      "get": {
        "description": "Whether `tenant_id` is entitled to `capability` (#1642), for another\nINTERNAL service to consult -- the cross-service counterpart of this\nmodule's own `core/entitlements.py`'s `require_capability`, which only\nexists as a FastAPI dependency gating THIS service's own routes and can't\nbe invoked directly by a sibling service (e.g. marketplace's\n`core/dependency_resolution.py`, whose per-node `entitled` field needs\nexactly this answer).\n\nMirrors marketplace's `GET /v1/marketplace/entitlements/{tenant_id}`\n(the reverse-direction call this module's own `get_org_tier` makes) --\nsame shape, same reasoning: service-token-only, since this exposes a\ncapability decision for an arbitrary `tenant_id` that a regular user must\nnever be able to query for another org.\n\nAlways 200 for an authenticated service caller: `org_has_capability`\nitself never raises, and with `CAPABILITY_TIER_MAP` still empty (#1447\nundecided) it always resolves `True` -- this route adds no restriction of\nits own beyond that check, and needs no changes when the map is later\npopulated (that's the entire point of the seam).",
        "operationId": "get_capability_entitlement_v1_entitlements_capabilities__tenant_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "tenant_id",
            "required": true,
            "schema": {
              "title": "Tenant Id",
              "type": "string"
            }
          },
          {
            "description": "capability_key()-formed key, e.g. 'plugin:<slug>' or 'bundle:<name>'",
            "in": "query",
            "name": "capability",
            "required": true,
            "schema": {
              "description": "capability_key()-formed key, e.g. 'plugin:<slug>' or 'bundle:<name>'",
              "title": "Capability",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Capability Entitlement",
        "tags": [
          "Entitlements"
        ]
      }
    },
    "/v1/graph-rag/{path}": {
      "delete": {
        "description": "Proxy /v1/graph-rag/* to the Graph RAG service's own /v1/* routes (writes\nrequire JWT). Graph RAG's real paths are unprefixed (`/v1/extract`,\n`/v1/construct-graph`, `/v1/retrieve`, `/v1/entity-context`,\n`/v1/graph/document/{id}`) -- the gateway adds the `graph-rag/` segment so\nthis doesn't collide with marketplace's own `/v1/graph/*` proxy above.\n\nLong timeout: construct-graph runs spaCy NER + several Neo4j writes per\ndocument (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_graph_rag_v1_graph_rag__path__delete",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Graph Rag"
      },
      "get": {
        "description": "Proxy /v1/graph-rag/* to the Graph RAG service's own /v1/* routes (writes\nrequire JWT). Graph RAG's real paths are unprefixed (`/v1/extract`,\n`/v1/construct-graph`, `/v1/retrieve`, `/v1/entity-context`,\n`/v1/graph/document/{id}`) -- the gateway adds the `graph-rag/` segment so\nthis doesn't collide with marketplace's own `/v1/graph/*` proxy above.\n\nLong timeout: construct-graph runs spaCy NER + several Neo4j writes per\ndocument (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_graph_rag_v1_graph_rag__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Graph Rag"
      },
      "patch": {
        "description": "Proxy /v1/graph-rag/* to the Graph RAG service's own /v1/* routes (writes\nrequire JWT). Graph RAG's real paths are unprefixed (`/v1/extract`,\n`/v1/construct-graph`, `/v1/retrieve`, `/v1/entity-context`,\n`/v1/graph/document/{id}`) -- the gateway adds the `graph-rag/` segment so\nthis doesn't collide with marketplace's own `/v1/graph/*` proxy above.\n\nLong timeout: construct-graph runs spaCy NER + several Neo4j writes per\ndocument (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_graph_rag_v1_graph_rag__path__patch",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Graph Rag"
      },
      "post": {
        "description": "Proxy /v1/graph-rag/* to the Graph RAG service's own /v1/* routes (writes\nrequire JWT). Graph RAG's real paths are unprefixed (`/v1/extract`,\n`/v1/construct-graph`, `/v1/retrieve`, `/v1/entity-context`,\n`/v1/graph/document/{id}`) -- the gateway adds the `graph-rag/` segment so\nthis doesn't collide with marketplace's own `/v1/graph/*` proxy above.\n\nLong timeout: construct-graph runs spaCy NER + several Neo4j writes per\ndocument (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_graph_rag_v1_graph_rag__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Graph Rag"
      },
      "put": {
        "description": "Proxy /v1/graph-rag/* to the Graph RAG service's own /v1/* routes (writes\nrequire JWT). Graph RAG's real paths are unprefixed (`/v1/extract`,\n`/v1/construct-graph`, `/v1/retrieve`, `/v1/entity-context`,\n`/v1/graph/document/{id}`) -- the gateway adds the `graph-rag/` segment so\nthis doesn't collide with marketplace's own `/v1/graph/*` proxy above.\n\nLong timeout: construct-graph runs spaCy NER + several Neo4j writes per\ndocument (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_graph_rag_v1_graph_rag__path__put",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Graph Rag"
      }
    },
    "/v1/graph/bundles/required": {
      "get": {
        "description": "The Dependency Resolver's batched answer (#1634 sec 7) for the WHOLE\nBundle vocabulary at once (#1635, ADR sec 12) -- what the reconciler/\ncontroller's own periodic recompute-then-converge loop calls once per\ntick. `bundle_currently_required` above already runs this exact same full\ncomputation internally (`resolve_required_bundles` is never scoped to one\nname); this route just returns the WHOLE answer instead of filtering it\ndown, so the reconciler's periodic call is ONE round trip, never one per\nBundle.\n\nSame failure/uncertainty contract as the per-name route: `confirmed: false`\nmeans the computation itself could not be completed (Neo4j/PostgreSQL\nunreachable, a timeout, a malformed response, or the traversal reaching\nthe configured depth cap). The reconciler MUST treat this exactly like\n\"nothing newly confirmed required\" (ADR sec 10/26.4: leave\n`effective_enabled` unchanged everywhere, never write a computed `false`),\nnever as a green light to deactivate anything. Admin/service-gated, same\nconvention as every other route in this module.",
        "operationId": "all_currently_required_bundles_v1_graph_bundles_required_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequiredBundlesResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "All Currently Required Bundles",
        "tags": [
          "graph-dependencies"
        ]
      }
    },
    "/v1/graph/bundles/{name}/required": {
      "get": {
        "description": "Live, on-demand answer (#1634, ADR bundle-reconciliation-and-admission.md\nsec 7/21 row 7/26.23) to: is `name` currently required by at least one\nenabled plugin, transitively, via the DEPENDS_ON graph?\n\nComputed FRESH on every call -- via the same Dependency Resolver\n(`core.dependency_resolution.resolve_required_bundles`) the (not-yet-built)\nreconciler will use for its own periodic recompute -- never a cached or\nperiodic value. This is what plugin-registry's ``POST /v1/bundles/{name}/\ndisable`` calls over HTTP (it has no Neo4j/PostgreSQL access of its own) to\nreject a disable-while-required request live.\n\n``confirmed: false`` means the computation itself could not be completed\n(Neo4j/PostgreSQL unreachable, a timeout, a malformed response, or the\ntraversal reaching the configured depth cap) -- the caller MUST treat this\nexactly like ``required: true`` (reject the disable), never as a green\nlight (ADR sec 10/26.4-5). Admin/service-gated (#1157), same convention as\n`add_plugin_dependency` below -- plugin-registry's own service token is\naccepted alongside a real admin user.",
        "operationId": "bundle_currently_required_v1_graph_bundles__name__required_get",
        "parameters": [
          {
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "title": "Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BundleRequiredResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Bundle Currently Required",
        "tags": [
          "graph-dependencies"
        ]
      }
    },
    "/v1/graph/conflicts/{plugin_id}": {
      "get": {
        "description": "Find plugins that conflict with the given plugin\n\nArgs:\n    plugin_id: Plugin to check\n\nReturns:\n    List of conflicting plugins",
        "operationId": "get_plugin_conflicts_v1_graph_conflicts__plugin_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginConflictsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Conflicts",
        "tags": [
          "graph-dependencies"
        ]
      }
    },
    "/v1/graph/dependencies": {
      "post": {
        "description": "Add a dependency relationship between a plugin and another plugin OR a bundle.\n\nArgs:\n    plugin_id: Plugin that has the dependency\n    depends_on: id of the thing that is required -- a plugin id, or (when\n        `depends_on_type=\"bundle\"`) a bundle name (e.g. \"graph-rag\", #1626)\n    dependency_type: Type of relationship (requires, suggests, conflicts_with)\n    plugin_name / depends_on_name: best-effort display names, used ONLY\n        if the graph doesn't already have a node for that plugin (see\n        Neo4jClient.add_dependency's ON CREATE SET) -- neither node is\n        guaranteed to exist yet when this is called (#484).\n    version_constraint: optional PEP 440-style constraint (e.g.\n        \">=1.2,<2.0\") on the required version of `depends_on` (#1625),\n        stored as edge metadata -- see Neo4jClient.add_dependency.\n    depends_on_type: \"plugin\" (default) or \"bundle\" (#1626) -- lets a\n        plugin declare \"I require the `graph-rag` bundle\" as a first-class\n        dependency, enforced by management.py's `_ensure_dependencies_\n        enabled` alongside its existing plugin-enabled check. An unknown\n        bundle name (not in `shared.bundle_graph.KNOWN_BUNDLES`) is\n        rejected -- see Neo4jClient.add_dependency's ValueError -> 400\n        mapping below.\n\nReturns:\n    Success status\n\nAdmin/service-gated (#1157): the plugin-dependency graph is a single,\nplatform-wide control (management.py's #748 enforcement reads it on every\nenable/disable/install), so a non-admin user must not be able to write\nedges into it -- mirrors the admin gate on the sibling ai_tools.py catalog\nwrites (#1141). The trusted internal service token is still accepted:\nplugin-registry's own automated sync populates real edges here (e.g.\n\"network requires telegraf\") at plugin-load time, with no user session in\nhand (#484).",
        "operationId": "add_plugin_dependency_v1_graph_dependencies_post",
        "parameters": [
          {
            "in": "query",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "depends_on",
            "required": true,
            "schema": {
              "title": "Depends On",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "dependency_type",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/DependencyType",
              "default": "requires"
            }
          },
          {
            "in": "query",
            "name": "plugin_name",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Plugin Name"
            }
          },
          {
            "in": "query",
            "name": "depends_on_name",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Depends On Name"
            }
          },
          {
            "in": "query",
            "name": "version_constraint",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Version Constraint"
            }
          },
          {
            "in": "query",
            "name": "depends_on_type",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/DependsOnType",
              "default": "plugin"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddDependencyResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Add Plugin Dependency",
        "tags": [
          "graph-dependencies"
        ]
      }
    },
    "/v1/graph/dependencies/{plugin_id}": {
      "get": {
        "description": "Get all dependencies for a plugin (direct and transitive)\n\nArgs:\n    plugin_id: Plugin identifier\n\nReturns:\n    List of dependencies with depth information, plus `possibly_truncated`\n    (#1633): true if the traversal reached `MAX_DEPENDENCY_DEPTH`, meaning\n    real dependencies beyond that depth may be missing from this list --\n    the result should be treated as informational/uncertain, not a\n    confirmed complete answer, in that case.",
        "operationId": "get_plugin_dependencies_v1_graph_dependencies__plugin_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginDependenciesResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Dependencies",
        "tags": [
          "graph-dependencies"
        ]
      }
    },
    "/v1/graph/dependencies/{plugin_id}/resolve": {
      "get": {
        "description": "Structured dependency resolution report for `plugin_id` (#1628).\n\nUnlike `GET /dependencies/{plugin_id}` (the raw dependency-chain listing),\nthis walks that same chain and composes it into three separately-readable\nparts:\n\n- ``resolves``: purely structural graph health (no unresolved cycle, every\n  declared version constraint at least parses) -- independent of whether\n  anything is actually usable right now.\n- ``nodes``: per-node readiness -- ``installed``/``compatible``/``enabled``\n  for plugin nodes; for bundle nodes, TWO independent signals never\n  conflated (#1636, ADR bundle-reconciliation-and-admission.md sec\n  20/26.18): ``enabled`` (desired state, #1626) and ``healthy``/\n  ``healthy_reason`` (runtime reality -- a live Docker running+healthcheck\n  query, #1636) -- plus ``entitled`` (see below).\n- ``entitled``: a capability-check seam per node (`plugin:<slug>` /\n  `bundle:<name>`, #1624's convention), calling through to api-gateway's\n  real (still empty) `CAPABILITY_TIER_MAP` (#1642). Always ``True`` today\n  -- #1624/#1447 haven't decided real entitlement policy yet.\n\n``verdict`` is ``READY`` iff `resolves` is true AND every node's every\ndimension is true, else ``BLOCKED`` with ``reason`` naming the first\nfailing node/dimension.\n\nReadiness is scoped to the CALLER's own installations (`current_user`),\nsame as `management.py`'s install/enable checks -- which call this exact\nsame builder (`core.dependency_resolution.build_resolution_report`), so\nthere is one source of truth for these checks, not two.",
        "operationId": "resolve_plugin_dependencies_v1_graph_dependencies__plugin_id__resolve_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DependencyResolutionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Resolve Plugin Dependencies",
        "tags": [
          "graph-dependencies"
        ]
      }
    },
    "/v1/graph/health": {
      "get": {
        "description": "Check if Neo4j graph database is accessible.\n\nUses shared.health.evaluate_dependencies (the same convention as this\nservice's own root /health) instead of an ad-hoc try/except: that gets a\nreal 503 on failure for free (the previous version always returned 200,\neven when unhealthy -- misleading to monitoring) and bounds/formats the\ndriver exception the same safe way (type name + message, truncated to\n200 chars) rather than returning the raw, unbounded exception text to an\nexternal caller (CodeQL py/stack-trace-exposure). Takes `neo4j` via\nDepends(get_neo4j_client), matching every sibling route in this file\n(the previous version called get_neo4j_client() directly, the only route\nhere that did -- inconsistent, and untestable via this file's own\ndependency_overrides-based test fixture).",
        "operationId": "graph_health_check_v1_graph_health_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphHealthResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphHealthResponse"
                }
              }
            },
            "description": "Neo4j is down"
          }
        },
        "summary": "Graph Health Check",
        "tags": [
          "graph-dependencies"
        ]
      }
    },
    "/v1/graph/recommendations": {
      "post": {
        "description": "Get plugin recommendations based on installed plugins\n\nUses collaborative filtering to suggest plugins that are\ncommonly used together with installed ones.\n\nArgs:\n    installed_plugins: List of installed plugin IDs\n    limit: Maximum number of recommendations\n\nReturns:\n    List of recommended plugins with relevance scores",
        "operationId": "get_plugin_recommendations_v1_graph_recommendations_post",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 5,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "items": {
                  "type": "string"
                },
                "title": "Installed Plugins",
                "type": "array"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginRecommendationsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Recommendations",
        "tags": [
          "graph-dependencies"
        ]
      }
    },
    "/v1/invites": {
      "get": {
        "operationId": "list_invites_route_v1_invites_get",
        "parameters": [
          {
            "in": "query",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Invites Route",
        "tags": [
          "Invites"
        ]
      },
      "post": {
        "operationId": "create_invite_route_v1_invites_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InviteCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Invite Route",
        "tags": [
          "Invites"
        ]
      }
    },
    "/v1/invites/bulk": {
      "post": {
        "description": "Bulk team invite (#1654): invite MULTIPLE emails to the SAME team, at\nthe same `team_role`/`max_uses`, in one request -- by calling\n`create_invite` (the EXACT singular mechanism) once per email, never\nreimplementing invite creation. Authorization is checked ONCE for the\nwhole batch (`team_id`/`team_role` are fixed for the batch).\n\nSame partial-failure convention as `routes/organizations.py`'s\n`bulk_create_org_invites_route` (see its docstring for the full\nrationale): one bad email never aborts the rest, and this always returns\n`207 Multi-Status` with a per-email outcome.",
        "operationId": "bulk_create_invites_route_v1_invites_bulk_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkInviteCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "207": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkInviteResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Bulk Create Invites Route",
        "tags": [
          "Invites"
        ]
      }
    },
    "/v1/invites/by-token/{token}": {
      "get": {
        "description": "Public invite lookup for the landing page. The bound email comes back\nmasked (#2186) -- see core.invites.get_invite_info.",
        "operationId": "get_invite_info_route_v1_invites_by_token__token__get",
        "parameters": [
          {
            "in": "path",
            "name": "token",
            "required": true,
            "schema": {
              "title": "Token",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteInfo"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Invite Info Route",
        "tags": [
          "Invites"
        ]
      }
    },
    "/v1/invites/by-token/{token}/redeem": {
      "post": {
        "description": "Redeem a pending invite, adding the caller to the invite's team.\n\n#1071: also mints a fresh JWT with an up-to-date `teams` claim. The token\nthis request was authenticated with was necessarily issued before this\nexact membership change, and `/v1/auth/refresh` deliberately never\nre-derives `teams` (matching `role`'s existing staleness-until-next-login\nbehavior) -- so without this, the caller would have no way to access the\nteam's `visibility=\"team\"` content until an unrelated full logout/login.",
        "operationId": "redeem_invite_route_v1_invites_by_token__token__redeem_post",
        "parameters": [
          {
            "in": "path",
            "name": "token",
            "required": true,
            "schema": {
              "title": "Token",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RedeemResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Redeem Invite Route",
        "tags": [
          "Invites"
        ]
      }
    },
    "/v1/invites/{invite_id}/revoke": {
      "post": {
        "operationId": "revoke_invite_route_v1_invites__invite_id__revoke_post",
        "parameters": [
          {
            "in": "path",
            "name": "invite_id",
            "required": true,
            "schema": {
              "title": "Invite Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke Invite Route",
        "tags": [
          "Invites"
        ]
      }
    },
    "/v1/licensing/plugins/{plugin_name}/license": {
      "patch": {
        "description": "Update a plugin's required license tier/key (admin/service-gated).\n\nA plugin's *required* tier is a global, security-relevant policy: a\nnon-admin could otherwise downgrade a paid plugin's tier to defeat the\n#47 fail-closed license gate, or raise it to deny the plugin to\neveryone. Admin-gated to match the sibling marketplace licensing routes\n(#622/#919) and the #1140-#1146 admin-gate sweep (#1155).",
        "operationId": "update_plugin_license_endpoint_v1_licensing_plugins__plugin_name__license_patch",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLicenseRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginLicenseUpdateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Plugin License Endpoint",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/licensing/plugins/{plugin_name}/license/tier": {
      "get": {
        "description": "Get a plugin's required license tier.",
        "operationId": "get_plugin_tier_v1_licensing_plugins__plugin_name__license_tier_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginTierResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Tier",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/licensing/plugins/{plugin_name}/license/validate": {
      "post": {
        "description": "Validate a plugin license key against the plugin's required tier.",
        "operationId": "validate_plugin_license_v1_licensing_plugins__plugin_name__license_validate_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidateLicenseRequest",
                "default": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/routes__licensing__LicenseValidationResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Validate Plugin License",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/marketplace/ai/plugins/{plugin_id}/tools": {
      "delete": {
        "description": "Deactivate all AI tools for a plugin, platform-wide, for every user.\n\nCalled when a plugin is disabled or uninstalled. Admin/service-only (matches\nthe gate already used for other platform-wide destructive actions, e.g.\nmodel pull/delete, bundle disable) -- this is not scoped to the caller's own\ninstallation, so a plain authenticated user must not be able to kill a\npopular plugin's tool availability for everyone.",
        "operationId": "deactivate_plugin_tools_v1_marketplace_ai_plugins__plugin_id__tools_delete",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIToolsDeactivateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Deactivate Plugin Tools",
        "tags": [
          "AI Tools"
        ]
      },
      "get": {
        "description": "Get all AI tools for a specific plugin",
        "operationId": "get_plugin_ai_tools_v1_marketplace_ai_plugins__plugin_id__tools_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginAIToolsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Ai Tools",
        "tags": [
          "AI Tools"
        ]
      }
    },
    "/v1/marketplace/ai/sync": {
      "post": {
        "description": "Sync AI tools from plugin manifest\n\nThis endpoint is called by the plugin registry when a plugin is loaded.\nIt automatically imports/updates AI tools defined in the plugin's manifest.yml.\n\nAdmin/service-only (found missing in a fresh security re-audit, matches\ndeactivate_plugin_tools below): `request.plugin_name`/`plugin_id` are\ncaller-supplied and NOT validated against anything the caller owns --\nthis writes `marketplace_ai_tools` rows that plugin-registry's\ncore/tool_execution.py later dispatches, string-keyed purely by\n`plugin_name`. A bare authenticated user (get_current_user_or_service\nbefore this) could otherwise register a fake tool naming an EXISTING,\nalready-running first-party plugin (e.g. \"telegraf\") with an `endpoint`\npointing at one of that real plugin's own ACTIONS methods, then invoke\nit via the AI-tool-execution path to run that method on the real\ninstance -- bypassing ACTIONS/ADMIN_ONLY_ACTIONS entirely, since\ntool_execution.py's dispatch never checked the plugin-registry's own\nadmin-only gate (see that module's own fix for the same root issue).\n\nArgs:\n    request: Sync request with plugin_name, plugin_id, and manifest\n\nReturns:\n    Sync result with tools imported/updated",
        "operationId": "sync_ai_tools_v1_marketplace_ai_sync_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AIToolsSyncRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIToolsSyncResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Sync Ai Tools",
        "tags": [
          "AI Tools"
        ]
      }
    },
    "/v1/marketplace/ai/tools": {
      "get": {
        "description": "List all AI tools from all plugins (paginated, #147/C6)\n\nArgs:\n    active_only: Only return active tools\n    tier: Filter by required tier\n    tool_name: Filter to an exact tool name -- plugin-state-manager's\n        validate_tool_access relies on this to look up a SPECIFIC tool's\n        required_tier; without it, an unrecognized query param is silently\n        dropped by FastAPI and the caller's `tools[0]` picks up whatever\n        tool this list's default ordering happens to return first,\n        checking an arbitrary tool's tier instead of the one actually\n        being invoked.\n    plugin_name: Filter to one plugin's tools -- #1322: plugin-registry's\n        action routes (``/v1/plugins/{plugin_name}/actions/{action}``) only\n        know ``(plugin_name, action)``, not a catalog ``tool_name`` (which is\n        unique only per-plugin, schema.sql: ``UNIQUE(plugin_id, tool_name)``),\n        so resolving a tool for tier enforcement there must scope by plugin\n        first, then match the action, rather than searching the whole catalog.\n    limit/offset: Pagination window",
        "operationId": "list_all_ai_tools_v1_marketplace_ai_tools_get",
        "parameters": [
          {
            "in": "query",
            "name": "active_only",
            "required": false,
            "schema": {
              "default": true,
              "title": "Active Only",
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "tier",
            "required": false,
            "schema": {
              "title": "Tier",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "tool_name",
            "required": false,
            "schema": {
              "title": "Tool Name",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "plugin_name",
            "required": false,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIToolListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List All Ai Tools",
        "tags": [
          "AI Tools"
        ]
      }
    },
    "/v1/marketplace/ai/tools/{tool_name}": {
      "get": {
        "description": "Get details for a specific AI tool.\n\ntool_name is unique per-plugin (schema.sql: UNIQUE(plugin_id, tool_name)),\nNOT globally -- two different plugins can legitimately register the same\ntool name. Filters to active tools (a deactivated tool must not be served\nas live to plugin-state-manager's execution/license-check callers, which\nresolve a tool by this exact endpoint) and orders deterministically so a\nsame-name collision across plugins doesn't return a different plugin's\ntool on every query depending on Postgres's own row order.",
        "operationId": "get_ai_tool_details_v1_marketplace_ai_tools__tool_name__get",
        "parameters": [
          {
            "in": "path",
            "name": "tool_name",
            "required": true,
            "schema": {
              "title": "Tool Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIToolDetail"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Ai Tool Details",
        "tags": [
          "AI Tools"
        ]
      }
    },
    "/v1/marketplace/entitlements/{tenant_id}": {
      "get": {
        "description": "An org's effective entitlement tier, for another INTERNAL service to consult\nwhen gating a product-level (non-plugin) capability (#1295/#1447).\n\nService-token-only (never a plain user JWT, even an org admin's) -- this exposes\nanother tenant's billing tier by id, which a regular caller should never be able\nto query for an arbitrary ``tenant_id``. ``/v1/billing/subscription`` already\ncovers \"my own org's tier\" for an authenticated user; this route is the\ncross-service equivalent for a caller that already knows which tenant it's\nasking about (e.g. api-gateway, resolving the tenant of the request it's\ncurrently handling).\n\nAlways 200 for a syntactically-valid tenant_id, mirroring ``effective_tier``'s\nown \"no billing event on file -> baseline, not a 404\" posture.",
        "operationId": "get_org_entitlement_v1_marketplace_entitlements__tenant_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "tenant_id",
            "required": true,
            "schema": {
              "title": "Tenant Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgEntitlementResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Org Entitlement",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/marketplace/installations/me": {
      "get": {
        "description": "List the authenticated user's currently-installed plugins, across all\nplugins, with plugin metadata inlined so the client needs no per-plugin\nfollow-up fetch just to show a name/description (#402).\n\nEach entry carries the installed ``version``, the catalog's\n``current_version``, an ``update_available`` hint and the\n``pinned_version`` (#2199).",
        "operationId": "get_my_installations_v1_marketplace_installations_me_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MyInstallationsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get My Installations",
        "tags": [
          "Plugin Management"
        ]
      }
    },
    "/v1/marketplace/installations/{installation_id}/pin": {
      "delete": {
        "description": "Remove an installation's version pin (#2199). Same access rule and\naudit as pinning; unpinning an installation that isn't pinned is a no-op.",
        "operationId": "unpin_installation_v1_marketplace_installations__installation_id__pin_delete",
        "parameters": [
          {
            "in": "path",
            "name": "installation_id",
            "required": true,
            "schema": {
              "title": "Installation Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstalledPluginSummary"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Unpin Installation",
        "tags": [
          "Plugin Management"
        ]
      },
      "put": {
        "description": "Pin an installation to one of its plugin's published versions (#2199).\n\nBulk and automatic updates (phase B, #2371) skip a pinned installation; a\n`blocked` security advisory (#2083) still overrides the pin. Only the\ninstallation's owner or a Platform Admin may pin it; anyone else (an org\nadmin and a service token included) gets 404, the same as an unknown id.\n422 when ``version`` isn't one of the plugin's published\nversions (``GET /v1/marketplace/plugins/{plugin_id}/versions``), 409 when\nthe plugin isn't installed. Audited (actor, org, old and new pin); 503 when\nthe audit entry can't be written, and then nothing changes. Pinning the\nversion already pinned is a no-op.",
        "operationId": "pin_installation_v1_marketplace_installations__installation_id__pin_put",
        "parameters": [
          {
            "in": "path",
            "name": "installation_id",
            "required": true,
            "schema": {
              "title": "Installation Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PinVersionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstalledPluginSummary"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Pin Installation",
        "tags": [
          "Plugin Management"
        ]
      }
    },
    "/v1/marketplace/licenses": {
      "get": {
        "description": "Get all licenses owned by the caller's ORGANIZATION (#622 re-key).\n\nLicenses belong to the tenant, so any member sees the org's full set (they\ninherit them). Scoped to the caller's JWT ``tenant_id`` -- never another\norg's records. Keys are masked even for the owning org (#1880).",
        "operationId": "list_licenses_v1_marketplace_licenses_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Licenses",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/marketplace/licenses/activate": {
      "post": {
        "description": "Activate a plugin license for the caller's ORGANIZATION, gated on the org's\npaid entitlement (#622 Phase 1 -- real enforcement, replacing the 0a admin\nstop-gap).\n\nThe license belongs to the tenant (``tenant_id`` from the JWT), so every member\nof the org inherits it. The requested tier must be covered by the org's paid\nentitlement (``org_is_entitled`` -> per-org tier from the billing webhook; for\nan ``inherit`` org, its nearest independent ancestor's, #2331) --\na plain member can self-serve any plugin up to what the org has PAID for, but\ncan no longer mint enterprise for free. The internal service principal bypasses\nthe entitlement check (internal provisioning/sync); everyone else, admins\nincluded, is held to the org's plan -- an org admin can't exceed the tenant's\nentitlement either. A caller with no ``tenant_id`` gets 401 (resolve_tenant_id).",
        "operationId": "activate_license_v1_marketplace_licenses_activate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LicenseActivateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseActivateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Activate License",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/marketplace/licenses/lookup": {
      "get": {
        "description": "Service/admin-only: the tier a SPECIFIC organization's currently-active\nlicense for a SPECIFIC plugin actually confers, if any (#919, #622 re-key to\ntenant): the license's trial-aware effective tier capped at the org's\neffective entitlement (#2035).\n\nUsed by plugin-state-manager's tool-tier enforcement to check a caller's org\nentitlement. Now keyed on ``tenant_id`` (the license subject) -- the caller's\nplugin-registry passes the JWT tenant, so every org member is gated by their\norg's license, not a per-user one. Admin/service only: a regular user must\nnever probe another tenant's license status.",
        "operationId": "lookup_tenant_license_v1_marketplace_licenses_lookup_get",
        "parameters": [
          {
            "in": "query",
            "name": "tenant_id",
            "required": true,
            "schema": {
              "title": "Tenant Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseLookupResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Lookup Tenant License",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/marketplace/licenses/validate": {
      "post": {
        "description": "Validate a license key",
        "operationId": "validate_license_endpoint_v1_marketplace_licenses_validate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LicenseValidateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseValidationResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Validate License Endpoint",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/marketplace/licenses/{license_id}/key": {
      "get": {
        "description": "The full license key (+ signed license, when issued) for self-hosted /\noffline activation (#1951). Owners and billing managers of the owning org,\nor a Platform Admin. Every call is audited; the response is ``no-store``.",
        "operationId": "reveal_license_key_endpoint_v1_marketplace_licenses__license_id__key_get",
        "parameters": [
          {
            "in": "path",
            "name": "license_id",
            "required": true,
            "schema": {
              "title": "License Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseKeyResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Reveal License Key Endpoint",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/marketplace/licenses/{license_id}/rotate": {
      "post": {
        "description": "Issue a new key for the license and invalidate the old one (#1951) --\n``/validate`` rejects the old key from this point on. Same authorization,\naudit and rate limit as the reveal route; the response is masked (fetch the\nnew key through ``GET /{license_id}/key``).",
        "operationId": "rotate_license_key_endpoint_v1_marketplace_licenses__license_id__rotate_post",
        "parameters": [
          {
            "in": "path",
            "name": "license_id",
            "required": true,
            "schema": {
              "title": "License Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseRotateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Rotate License Key Endpoint",
        "tags": [
          "Licensing"
        ]
      }
    },
    "/v1/marketplace/plugins": {
      "get": {
        "description": "List all plugins in marketplace\n\nArgs:\n    limit: Page size (canonical, platform-standard)\n    offset: Items to skip (canonical, platform-standard)\n    page: Deprecated — page number (1-indexed); use limit/offset\n    page_size: Deprecated — items per page; use limit/offset\n    category: Filter by category\n    pricing_model: Filter by pricing model\n    status: Filter by status (default: approved). Non-admin/service callers\n        are always clamped to the public catalog regardless of what they\n        pass here — see submissions.py for a developer's own submissions.\n    origin: Filter by catalog origin (``first_party`` = glossary\n        first-party | ``submitted`` = glossary community), so a client can\n        page one source server-side instead of filtering only the pages it\n        has loaded (#2206).",
        "operationId": "list_plugins_v1_marketplace_plugins_get",
        "parameters": [
          {
            "description": "Page size (canonical)",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maximum": 100,
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Page size (canonical)",
              "title": "Limit"
            }
          },
          {
            "description": "Items to skip (canonical)",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Items to skip (canonical)",
              "title": "Offset"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 10,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "category",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Category"
            }
          },
          {
            "in": "query",
            "name": "pricing_model",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Pricing Model"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "default": "approved",
              "title": "Status"
            }
          },
          {
            "description": "Only plugins of this catalog origin; all when omitted. `first_party` = glossary first-party, `submitted` = glossary community.",
            "in": "query",
            "name": "origin",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/PluginOrigin"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only plugins of this catalog origin; all when omitted. `first_party` = glossary first-party, `submitted` = glossary community.",
              "title": "Origin"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarketplacePluginListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Plugins",
        "tags": [
          "Marketplace"
        ]
      },
      "post": {
        "description": "Create a new plugin in marketplace.\n\nTwo distinct callers (#402):\n- the plugin registry (internal **service** token) auto-registering a\n  first-party module plugin → created `approved` + `origin='first_party'`,\n  as before (these bypass human review by design).\n- a **user** JWT (a developer) → created as a `draft` submission\n  (`origin='submitted'`, `submitted_by=<sub>`) that must go through the\n  review flow (routes/submissions.py) before it can become visible. This\n  closes the prior gap where ANY authenticated user could POST a listing\n  that was silently auto-approved and publicly visible immediately.",
        "operationId": "create_plugin_v1_marketplace_plugins_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PluginCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Plugin",
        "tags": [
          "Marketplace"
        ]
      }
    },
    "/v1/marketplace/plugins/featured": {
      "get": {
        "description": "Get featured plugins",
        "operationId": "get_featured_plugins_v1_marketplace_plugins_featured_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 50,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarketplacePluginListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Featured Plugins",
        "tags": [
          "Marketplace"
        ]
      }
    },
    "/v1/marketplace/plugins/search": {
      "get": {
        "description": "Search plugins by name or description, optionally within one origin",
        "operationId": "search_plugins_v1_marketplace_plugins_search_get",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "minLength": 1,
              "title": "Q",
              "type": "string"
            }
          },
          {
            "description": "Page size (canonical)",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maximum": 100,
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Page size (canonical)",
              "title": "Limit"
            }
          },
          {
            "description": "Items to skip (canonical)",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Items to skip (canonical)",
              "title": "Offset"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 10,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          },
          {
            "description": "Only plugins of this catalog origin; all when omitted. `first_party` = glossary first-party, `submitted` = glossary community.",
            "in": "query",
            "name": "origin",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/PluginOrigin"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only plugins of this catalog origin; all when omitted. `first_party` = glossary first-party, `submitted` = glossary community.",
              "title": "Origin"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarketplacePluginListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Search Plugins",
        "tags": [
          "Marketplace"
        ]
      }
    },
    "/v1/marketplace/plugins/semantic-search": {
      "get": {
        "description": "Semantically search the plugin catalog (#1683).\n\nAn ADDITIVE complement to the keyword ``/plugins/search`` endpoint (which is\nleft untouched): this embeds ``query`` and ranks catalog entries by vector\nsimilarity, so a plugin whose wording differs from the query (\"procure-flow\"\nvs. \"purchase-order approval routing\") is still found. Backs the\norchestrator's ``find_plugin`` AI tool.\n\nRead-only and public, exactly like the keyword search. Degrades gracefully:\nif the embedding backend or Qdrant is unreachable it returns an empty match\nlist (HTTP 200), never an error -- a chat tool call must not break because\nthe vector store is momentarily down.",
        "operationId": "semantic_search_plugins_v1_marketplace_plugins_semantic_search_get",
        "parameters": [
          {
            "description": "Natural-language query",
            "in": "query",
            "name": "query",
            "required": true,
            "schema": {
              "description": "Natural-language query",
              "minLength": 1,
              "title": "Query",
              "type": "string"
            }
          },
          {
            "description": "Max ranked matches",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "description": "Max ranked matches",
              "maximum": 50,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginSemanticSearchResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Semantic Search Plugins",
        "tags": [
          "Marketplace"
        ]
      }
    },
    "/v1/marketplace/plugins/{plugin_id}": {
      "get": {
        "description": "Get plugin by ID.\n\nA non-public status (draft/submitted/in_review/rejected/archived) is only\nvisible to an admin/service caller or the submission's own developer —\notherwise this is the same unauthenticated-leak class of bug as the\n`status` query param on the list endpoint above (#402 follow-up): the\nid itself isn't secret (it's returned from the create/submit responses),\nso hiding it from listings alone isn't enough.",
        "operationId": "get_plugin_v1_marketplace_plugins__plugin_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin",
        "tags": [
          "Marketplace"
        ]
      },
      "put": {
        "description": "Partially update a plugin's marketplace metadata.\n\nOnly the fields present in the body are changed (the `PluginUpdate` model existed\nbut had no route — #147). 404 if the plugin is unknown, 422 if the body is empty.\n\n`status` is not updatable via PUT by anyone (#939) — it moves only through\nthe review state machine at /v1/marketplace/submissions/*.\n\nNon-admin/non-service callers (a submission's own developer) may only edit\ntheir own `draft`/`rejected` submission, and never `featured` — otherwise a\ndeveloper could feature their own listing or edit anyone else's, bypassing\nthe review workflow (#402 follow-up).",
        "operationId": "update_plugin_v1_marketplace_plugins__plugin_id__put",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PluginUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Plugin",
        "tags": [
          "Marketplace"
        ]
      }
    },
    "/v1/marketplace/plugins/{plugin_id}/disable": {
      "post": {
        "description": "Disable the authenticated user's plugin (identity from JWT, #147/C7).\n\n#748: rejected with 409 if another of this user's plugins is enabled and\ndirectly depends on this one (Neo4j DEPENDS_ON graph). enable_plugin's own\ntransitive auto-enable keeps the invariant \"an enabled plugin's every\ndependency is enabled\" true going forward, so a direct (one-hop) check\nhere is sufficient to catch a violation regardless of how deep the real\ndependency chain goes -- if some plugin two hops up were enabled, its own\ndirect dependency (one hop up from this one) would already have been\nauto-enabled alongside it, and IT is what this check catches.",
        "operationId": "disable_plugin_v1_marketplace_plugins__plugin_id__disable_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginStateChangeResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Disable Plugin",
        "tags": [
          "Plugin Management"
        ]
      }
    },
    "/v1/marketplace/plugins/{plugin_id}/enable": {
      "post": {
        "description": "Enable the authenticated user's plugin (identity from JWT, #147/C7).\n\n#748: the plugin dependency graph (Neo4j DEPENDS_ON) used to be purely\ninformational -- a real runtime dependency (e.g. \"network\" reads\nplugin_instances[\"telegraf\"] directly) could be silently unmet with zero\nwarning. This resolves the FULL transitive dependency chain and makes\nsure every one of them is enabled for this user first. A dependency this\nuser never installed at all can't be silently auto-installed on their\nbehalf (that would bypass their own install choice) -- rejected with a\nclear error naming it instead.",
        "operationId": "enable_plugin_v1_marketplace_plugins__plugin_id__enable_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginEnableResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Enable Plugin",
        "tags": [
          "Plugin Management"
        ]
      }
    },
    "/v1/marketplace/plugins/{plugin_id}/install": {
      "post": {
        "description": "Install a plugin for the authenticated user.\n\nThe user identity comes from the JWT (`sub`) — it used to be a redundant `user_id`\nin the request body/query that duplicated the authenticated principal (#147/C7).\n\nplugin_id is str()-cast before InstallationResponse construction: asyncpg returns\nUUID columns as uuid.UUID objects, and InstallationResponse.plugin_id is a `str`\nfield -- pydantic v2 does not coerce UUID -> str, so this 500'd on response\nserialization for every install until fixed (#402, found on a live deployment).\n\n#892: install used to unconditionally set `enabled=TRUE` on both branches\nbelow, completely bypassing #748's dependency enforcement -- the single\nmost common real-world path (install a plugin) could land an enabled\nplugin whose dependency was never installed, the exact invariant #748\nexists to prevent. Both branches now write the row with `enabled=FALSE`\nfirst, run the SAME `_ensure_dependencies_enabled` check `/enable`\nalready runs, and only flip to `enabled=TRUE` if it passes -- 409ing\n(naming the missing dependency) otherwise, same as `/enable`. The common\ncase (no unmet dependency) still lands enabled immediately, unchanged.\nA 409 here leaves the row installed-but-disabled rather than rolling\nback the install entirely -- once the missing dependency is installed,\nthe same install call (or a plain `/enable`) completes it.",
        "operationId": "install_plugin_v1_marketplace_plugins__plugin_id__install_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstallationResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Install Plugin",
        "tags": [
          "Plugin Management"
        ]
      }
    },
    "/v1/marketplace/plugins/{plugin_id}/installations": {
      "get": {
        "description": "Get a plugin's installations, paginated (#147/C6).\n\nPlatform Admin or the internal service token only (#2390).\n``marketplace_installations`` has no tenant column (#2091), so this list\nspans every tenant; ``role == \"admin\"`` is an ORG admin (#1317) and gets\n403. The Platform Admin claim is confirmed against the DB flag through\napi-gateway; 503 when that can't be answered.",
        "operationId": "get_plugin_installations_v1_marketplace_plugins__plugin_id__installations_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginInstallationsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Installations",
        "tags": [
          "Plugin Management"
        ]
      }
    },
    "/v1/marketplace/plugins/{plugin_id}/ratings": {
      "get": {
        "description": "The plugin's current aggregate plus its individual reviews, newest first.",
        "operationId": "list_ratings_v1_marketplace_plugins__plugin_id__ratings_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginRatingsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Ratings",
        "tags": [
          "Plugin Ratings"
        ]
      },
      "post": {
        "description": "Submit or update the caller's own rating/review for a plugin.\n\nGated on having installed the plugin at some point (ANY row in\nmarketplace_installations for this user+plugin, regardless of current\nstatus) -- matches how most real app-store review systems work (only\npeople who actually used it can review), while still letting someone who\ntried it and later uninstalled keep or update their review rather than\nlosing that gate retroactively.\n\nOne review per user per plugin: a second submission UPDATES the existing\nrow (upsert) rather than rejecting -- friendlier than a 409, matches \"edit\nyour review\" being the normal expectation on every real review system.",
        "operationId": "submit_rating_v1_marketplace_plugins__plugin_id__ratings_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RatingCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RatingResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Submit Rating",
        "tags": [
          "Plugin Ratings"
        ]
      }
    },
    "/v1/marketplace/plugins/{plugin_id}/uninstall": {
      "delete": {
        "description": "Uninstall the authenticated user's plugin (identity from JWT, #147/C7).",
        "operationId": "uninstall_plugin_v1_marketplace_plugins__plugin_id__uninstall_delete",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginStateChangeResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Uninstall Plugin",
        "tags": [
          "Plugin Management"
        ]
      }
    },
    "/v1/marketplace/plugins/{plugin_id}/versions": {
      "get": {
        "description": "Every recorded version of a plugin (#2199), newest first.\n\nOrdered by semantic-version precedence; versions that aren't semantic\nversions come after them, newest first by when they were recorded.\nReadable by whoever may read the plugin itself (``GET /plugins/{id}``):\nanyone for a published plugin; for a draft or an unpublished submission,\nonly its developer or an admin (anyone else gets 404).",
        "operationId": "list_plugin_versions_v1_marketplace_plugins__plugin_id__versions_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginVersionListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Plugin Versions",
        "tags": [
          "Marketplace"
        ]
      }
    },
    "/v1/marketplace/repositories": {
      "get": {
        "description": "List plugin source repositories, each with its live linked-plugin count.\n\nPublic and read-only, mirroring ``/v1/marketplace/plugins`` pagination\n(canonical ``limit``/``offset`` with deprecated ``page``/``page_size``\nfallback).",
        "operationId": "list_repositories_v1_marketplace_repositories_get",
        "parameters": [
          {
            "description": "Page size (canonical)",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maximum": 100,
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Page size (canonical)",
              "title": "Limit"
            }
          },
          {
            "description": "Items to skip (canonical)",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Items to skip (canonical)",
              "title": "Offset"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 10,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginRepositoryListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Repositories",
        "tags": [
          "Plugin Repositories"
        ]
      }
    },
    "/v1/marketplace/repositories/{repository_id}": {
      "get": {
        "description": "Get one plugin source repository by id (404 if unknown).",
        "operationId": "get_repository_v1_marketplace_repositories__repository_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "repository_id",
            "required": true,
            "schema": {
              "title": "Repository Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginRepositoryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Repository",
        "tags": [
          "Plugin Repositories"
        ]
      }
    },
    "/v1/marketplace/repositories/{repository_id}/plugins": {
      "get": {
        "description": "List the plugins that belong to one source repository (404 if the\nrepository is unknown).\n\nReturns the same ``PluginListResponse`` shape as the main plugin listing, so\na client renders a repository's plugins with the existing plugin card.",
        "operationId": "list_repository_plugins_v1_marketplace_repositories__repository_id__plugins_get",
        "parameters": [
          {
            "in": "path",
            "name": "repository_id",
            "required": true,
            "schema": {
              "title": "Repository Id",
              "type": "string"
            }
          },
          {
            "description": "Page size (canonical)",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maximum": 100,
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Page size (canonical)",
              "title": "Limit"
            }
          },
          {
            "description": "Items to skip (canonical)",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Items to skip (canonical)",
              "title": "Offset"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 10,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarketplacePluginListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Repository Plugins",
        "tags": [
          "Plugin Repositories"
        ]
      }
    },
    "/v1/marketplace/submissions": {
      "get": {
        "description": "Admin review queue: submissions in a given status (default ``submitted``),\noldest-first so the longest-waiting is reviewed next.",
        "operationId": "review_queue_v1_marketplace_submissions_get",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "default": "submitted",
              "title": "Status",
              "type": "string"
            }
          },
          {
            "description": "Page size (canonical)",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maximum": 100,
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Page size (canonical)",
              "title": "Limit"
            }
          },
          {
            "description": "Items to skip (canonical)",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Items to skip (canonical)",
              "title": "Offset"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 10,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReviewQueueListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Review Queue",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/marketplace/submissions/mine": {
      "get": {
        "description": "List the caller's own submissions (any status), newest first — scoped to\nthe JWT ``sub`` so one developer can't see another's drafts/rejections.",
        "operationId": "my_submissions_v1_marketplace_submissions_mine_get",
        "parameters": [
          {
            "description": "Page size (canonical)",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maximum": 100,
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Page size (canonical)",
              "title": "Limit"
            }
          },
          {
            "description": "Items to skip (canonical)",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Items to skip (canonical)",
              "title": "Offset"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "deprecated": true,
            "description": "Deprecated: use limit/offset",
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 10,
              "deprecated": true,
              "description": "Deprecated: use limit/offset",
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarketplacePluginListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "My Submissions",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/marketplace/submissions/{plugin_id}": {
      "get": {
        "description": "One submission with the manifest its developer submitted (#2214).\n\nAn admin sees any submission, with the submitter's and last reviewer's\nusernames. The submission's own developer sees their own (so they can read\nback the stored manifest), without the account names. Anyone else gets the\nsame 404 as an unknown id, so another developer's submission isn't revealed.\nThe manifest is JSON data: it is never executed, and credentials in its URLs\nare removed.",
        "operationId": "submission_detail_v1_marketplace_submissions__plugin_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionDetailResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Submission Detail",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/marketplace/submissions/{plugin_id}/approve": {
      "post": {
        "description": "Admin: approve an ``in_review`` submission → ``approved`` (publicly\nvisible via the existing catalog read paths).",
        "operationId": "approve_submission_v1_marketplace_submissions__plugin_id__approve_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Approve Submission",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/marketplace/submissions/{plugin_id}/archive": {
      "post": {
        "description": "Admin/service: archive (delist) an ``approved`` plugin.",
        "operationId": "archive_submission_v1_marketplace_submissions__plugin_id__archive_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Archive Submission",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/marketplace/submissions/{plugin_id}/claim": {
      "post": {
        "description": "Admin: take a ``submitted`` submission into ``in_review`` (records the\nreviewer).",
        "operationId": "claim_review_v1_marketplace_submissions__plugin_id__claim_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Claim Review",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/marketplace/submissions/{plugin_id}/history": {
      "get": {
        "description": "Admin: every recorded status transition of a submission, oldest first\n(#2214), from the append-only ``marketplace_plugin_reviews`` audit trail.\nEach entry has the from/to status, the actor (and their username when\nknown), their role, the notes and the time. Paged with ``limit``/``offset``;\n``total`` is the full count. 404 for an unknown submission.",
        "operationId": "submission_history_v1_marketplace_submissions__plugin_id__history_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          },
          {
            "description": "Page size",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "description": "Page size",
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Items to skip",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "description": "Items to skip",
              "maximum": 100000,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionHistoryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Submission History",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/marketplace/submissions/{plugin_id}/reject": {
      "post": {
        "description": "Admin: reject a ``submitted``/``in_review`` submission (feedback\n**required** so the developer knows what to fix before resubmitting).",
        "operationId": "reject_submission_v1_marketplace_submissions__plugin_id__reject_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReviewActionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Reject Submission",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/marketplace/submissions/{plugin_id}/submit": {
      "post": {
        "description": "Developer action: move an own ``draft``/``rejected`` submission to\n``submitted`` (into the review queue). Only the submission's owner (or an\nadmin/service) may submit it; a non-owner gets 404 (same message as an\nunknown id — no reason to reveal another tenant's submission exists).",
        "operationId": "submit_for_review_v1_marketplace_submissions__plugin_id__submit_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Submit For Review",
        "tags": [
          "Submissions"
        ]
      }
    },
    "/v1/model-providers": {
      "get": {
        "description": "List (GET) or register (POST) the caller's org's model providers -- the\nCloud Providers (BYOK) page's collection endpoint (#2043).\n\nmodel-management's provider vault lives under its own `/v1/model-providers`\nprefix (routes/providers.py), not under `/v1/models`, so without this route\nthe page 404'd at the gateway before ever reaching the service. Forwarded\nwhole. Auth is the same as every other proxied route: writes need a JWT here,\nand proxy_request verifies any Bearer credential (signature + session\nliveness, #1933) before forwarding it; model-management's own\norg-admin gate still decides who may read or change the vault.",
        "operationId": "model_providers_root_v1_model_providers_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Model Providers Root"
      },
      "post": {
        "description": "List (GET) or register (POST) the caller's org's model providers -- the\nCloud Providers (BYOK) page's collection endpoint (#2043).\n\nmodel-management's provider vault lives under its own `/v1/model-providers`\nprefix (routes/providers.py), not under `/v1/models`, so without this route\nthe page 404'd at the gateway before ever reaching the service. Forwarded\nwhole. Auth is the same as every other proxied route: writes need a JWT here,\nand proxy_request verifies any Bearer credential (signature + session\nliveness, #1933) before forwarding it; model-management's own\norg-admin gate still decides who may read or change the vault.",
        "operationId": "model_providers_root_v1_model_providers_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Model Providers Root"
      }
    },
    "/v1/model-providers/{path}": {
      "delete": {
        "description": "Proxy `/v1/model-providers/*` (presets, usage, `{id}`, `{id}/test`,\nrotate, ...) to model-management's same path (#2043; writes require JWT).\n\nLong timeout: `{id}/test` makes a live call to the remote provider, and\ngenerate/chat run inference (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_providers_v1_model_providers__path__delete",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Providers"
      },
      "get": {
        "description": "Proxy `/v1/model-providers/*` (presets, usage, `{id}`, `{id}/test`,\nrotate, ...) to model-management's same path (#2043; writes require JWT).\n\nLong timeout: `{id}/test` makes a live call to the remote provider, and\ngenerate/chat run inference (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_providers_v1_model_providers__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Providers"
      },
      "patch": {
        "description": "Proxy `/v1/model-providers/*` (presets, usage, `{id}`, `{id}/test`,\nrotate, ...) to model-management's same path (#2043; writes require JWT).\n\nLong timeout: `{id}/test` makes a live call to the remote provider, and\ngenerate/chat run inference (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_providers_v1_model_providers__path__patch",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Providers"
      },
      "post": {
        "description": "Proxy `/v1/model-providers/*` (presets, usage, `{id}`, `{id}/test`,\nrotate, ...) to model-management's same path (#2043; writes require JWT).\n\nLong timeout: `{id}/test` makes a live call to the remote provider, and\ngenerate/chat run inference (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_providers_v1_model_providers__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Providers"
      },
      "put": {
        "description": "Proxy `/v1/model-providers/*` (presets, usage, `{id}`, `{id}/test`,\nrotate, ...) to model-management's same path (#2043; writes require JWT).\n\nLong timeout: `{id}/test` makes a live call to the remote provider, and\ngenerate/chat run inference (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_providers_v1_model_providers__path__put",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Providers"
      }
    },
    "/v1/models": {
      "get": {
        "description": "List (GET) or pull (POST) models.\n\nForwarded to model-management's canonical `/v1/models` (#2043) -- not its\ndeprecated unversioned `/models` alias, which this route used to target (the\n#147/C1 fix for the old `/v1/models/models` doubling). model-management\nserves every models route under both paths, so this is behaviour-preserving\nand lets the alias be retired without breaking the gateway.\n\nLong timeout: a model pull (POST) blocks on a synchronous, non-streamed\nOllama download that routinely takes minutes for multi-GB models (see\n_LONG_OPERATION_TIMEOUT).",
        "operationId": "model_management_root_v1_models_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Model Management Root"
      },
      "post": {
        "description": "List (GET) or pull (POST) models.\n\nForwarded to model-management's canonical `/v1/models` (#2043) -- not its\ndeprecated unversioned `/models` alias, which this route used to target (the\n#147/C1 fix for the old `/v1/models/models` doubling). model-management\nserves every models route under both paths, so this is behaviour-preserving\nand lets the alias be retired without breaking the gateway.\n\nLong timeout: a model pull (POST) blocks on a synchronous, non-streamed\nOllama download that routinely takes minutes for multi-GB models (see\n_LONG_OPERATION_TIMEOUT).",
        "operationId": "model_management_root_v1_models_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Model Management Root"
      }
    },
    "/v1/models/{path}": {
      "delete": {
        "description": "Proxy `/v1/models/{id}[/...]` to the service's canonical\n`/v1/models/{id}[/...]` (writes require JWT) -- not the deprecated `/models`\nalias (#2043; see model_management_root).\n\nLong timeout: `.../test` runs blocking LLM inference and a delete can take a\nwhile freeing a large model's disk space (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_management_v1_models__path__delete",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Management"
      },
      "get": {
        "description": "Proxy `/v1/models/{id}[/...]` to the service's canonical\n`/v1/models/{id}[/...]` (writes require JWT) -- not the deprecated `/models`\nalias (#2043; see model_management_root).\n\nLong timeout: `.../test` runs blocking LLM inference and a delete can take a\nwhile freeing a large model's disk space (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_management_v1_models__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Management"
      },
      "patch": {
        "description": "Proxy `/v1/models/{id}[/...]` to the service's canonical\n`/v1/models/{id}[/...]` (writes require JWT) -- not the deprecated `/models`\nalias (#2043; see model_management_root).\n\nLong timeout: `.../test` runs blocking LLM inference and a delete can take a\nwhile freeing a large model's disk space (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_management_v1_models__path__patch",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Management"
      },
      "post": {
        "description": "Proxy `/v1/models/{id}[/...]` to the service's canonical\n`/v1/models/{id}[/...]` (writes require JWT) -- not the deprecated `/models`\nalias (#2043; see model_management_root).\n\nLong timeout: `.../test` runs blocking LLM inference and a delete can take a\nwhile freeing a large model's disk space (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_management_v1_models__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Management"
      },
      "put": {
        "description": "Proxy `/v1/models/{id}[/...]` to the service's canonical\n`/v1/models/{id}[/...]` (writes require JWT) -- not the deprecated `/models`\nalias (#2043; see model_management_root).\n\nLong timeout: `.../test` runs blocking LLM inference and a delete can take a\nwhile freeing a large model's disk space (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_model_management_v1_models__path__put",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Model Management"
      }
    },
    "/v1/org-purge-jobs": {
      "get": {
        "operationId": "list_org_purge_jobs_v1_org_purge_jobs_get",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgPurgeJobList"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Org Purge Jobs",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/org-purge-jobs/{job_id}": {
      "get": {
        "operationId": "get_org_purge_job_v1_org_purge_jobs__job_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgPurgeJobOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Org Purge Job",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/org-purge-jobs/{job_id}/retry": {
      "post": {
        "description": "Re-queue a ``failed`` job now with a fresh attempt budget; stores that\nalready succeeded are not re-run. 409 if the job is running or done.",
        "operationId": "retry_org_purge_job_v1_org_purge_jobs__job_id__retry_post",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgPurgeJobOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Retry Org Purge Job",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations": {
      "get": {
        "description": "List organizations with member counts. Admin-only (platform-operator view).",
        "operationId": "list_organizations_route_v1_organizations_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Organizations Route",
        "tags": [
          "Organizations"
        ]
      },
      "post": {
        "description": "Provision a new TOP-LEVEL organization + its primary owner + a default\nteam, atomically (#2231; onboarding ADR D6, D9, edge case 6).\n\nA Platform Admin may create one for any owner (`owner_user_id`, default\nthe caller): `created_via = platform_admin`. Anyone else must own an\nactive top-level organization whose plan allows another, and becomes the\nnew organization's owner (`owner_user_id`, if given, must be the caller):\n`created_via = owner`. The new organization is `standard` and starts on\nthe baseline plan until its own checkout. The owner's\n`top_level_orgs` and `owned_free_orgs` limits apply: over a `hard` one,\n`403` with `reason: entitlement` and the limit's fields; over a `soft`\none (community), allowed and audited `ORG_LIMIT_SOFT_EXCEEDED`. Owning no\norganization is a `403` too. Rate-limited per account. `409` on a taken\nslug. Sub-organizations: `POST /{org_id}/suborganizations`.",
        "operationId": "create_organization_route_v1_organizations_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Organization Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/mine": {
      "get": {
        "description": "The organizations the CALLER belongs to, for the org switcher and the\nwhich-org-am-I indicator. Any authenticated user — distinct from ``GET \"\"``\n(admin-only, all orgs on the instance). A user with no org membership yet gets\nan empty list (pre-backfill / orgless), which the client renders as no\nswitcher rather than an error.",
        "operationId": "list_my_organizations_v1_organizations_mine_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MyOrgsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List My Organizations",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/personal": {
      "post": {
        "description": "Create my workspace (#2234; onboarding ADR Decision 3, edge case 4):\nan account that belongs to no organization creates its own `personal`\norganization, becomes its owner, and gets a fresh token whose tenant is\nthe new organization.\n\nAllowed only while `SELF_SERVE_PERSONAL_ORGS` resolves true (unset: true\nin `open` registration mode), else `403` with `reason:\ninstallation_policy`; `409` `workspace_exists` once the account belongs\nto any organization; the free-organization limit (`owned_free_orgs` of\nthe baseline plan) applies, `403` with `reason: entitlement` over a hard\nlimit. Rate-limited per account. `GET /v1/profile/me` reports\n`can_create_workspace`.",
        "operationId": "create_personal_organization_route_v1_organizations_personal_post",
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalOrgOut"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Create Personal Organization Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/switch": {
      "post": {
        "description": "Switch the caller's ACTIVE tenant context to another org they belong to.\n\nRe-mints their JWT with ``active_tenant_id`` set to the target (their home\n``tenant_id`` is unchanged), so subsequent requests read AND write in that org's\ncontext (``resolve_active_tenant_id`` / ``resolve_tenant_id`` both key on the\nactive tenant, as does the RLS session GUC). Member-only: 403 if the caller\nisn't a member of the target. Any authenticated USER may call this (not\nadmin-gated) — it only ever moves them between orgs they already belong to.",
        "operationId": "switch_organization_v1_organizations_switch_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgSwitchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Switch Organization",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}": {
      "delete": {
        "description": "Deleting an organization is IRREVERSIBLE. The organization is removed immediately and a background job permanently purges its data from every service; there is no grace period and no undo. The organization export (GET /v1/organizations/{id}/export) does NOT include document or vector payloads, knowledge-graph data or uploaded files, so exporting first does not make a deletion recoverable. Requires `confirm=<organization slug>` matching the target exactly (400 otherwise). The `default` organization can never be deleted (409). `reparent_children_to` must have the children's kind: a sub-organization has its parent's kind (409 `org_kind_mismatch`).",
        "operationId": "delete_organization_route_v1_organizations__org_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "reparent_children_to",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Reparent Children To"
            }
          },
          {
            "description": "Must equal the organization's slug exactly -- an explicit acknowledgement that deletion is irreversible.",
            "in": "query",
            "name": "confirm",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Must equal the organization's slug exactly -- an explicit acknowledgement that deletion is irreversible.",
              "title": "Confirm"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgDeleteAccepted"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Organization Route",
        "tags": [
          "Organizations"
        ]
      },
      "patch": {
        "description": "Edit an org's own name/description (#1503) and, since #1650, its own\n`entitlement_mode`. Same authority as managing its membership: the org's\nown owner/admin, or an instance/platform admin — `_require_org_manage`\nalready encodes exactly that, reused as-is rather than inventing a\nparallel check for a different org-mutating action.",
        "operationId": "update_organization_route_v1_organizations__org_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgDetailOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Organization Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/audit-logs": {
      "get": {
        "description": "The org audit view (#1851): entries scoped to ``org_id`` or any of its\nsub-organizations (``scope_type = 'org'``), newest first, paginated. A\ndelegated action appears under its TARGET org, with the ancestor it was\ndelegated from in ``after_state.delegated_via``. Platform, self and\npre-#1851 (``legacy``) entries are not included -- see the module\ndocstring. Requires ``org.audit.view`` on the org (or Platform Admin).",
        "operationId": "get_org_audit_logs_v1_organizations__org_id__audit_logs_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "actor_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Actor Id"
            }
          },
          {
            "in": "query",
            "name": "action",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Action"
            }
          },
          {
            "in": "query",
            "name": "target_type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Target Type"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Org Audit Logs",
        "tags": [
          "Audit"
        ]
      }
    },
    "/v1/organizations/{org_id}/convert": {
      "post": {
        "description": "Convert an organization's kind (#2191, #2230). Only `personal` ->\n`standard` exists: afterwards the org's owners/admins can issue invites\nthat create new accounts even in `invite`/`closed` registration mode.\nConversion is one-way: `\"to\": \"personal\"` is refused with 409.\n\nPlatform Admin only (the claim re-checked against the database): this is\nthe operator vetting a self-served tenant, so neither the org's own owner\nnor an ancestor org's admin may do it (403). Converts the whole subtree:\nevery `personal` sub-organization becomes `standard` too. A personal\nsub-organization whose parent is still personal can't be converted on its\nown (409 `org_kind_mismatch`): convert the top personal organization.\n\nA change is audited once, in the same transaction, as `ORG_KIND_CHANGED`\non the target, with `from`, `to`, the `reason`, `via: platform_admin` and\nthe converted descendants' ids. Idempotent: an org that is already\n`standard` with no personal sub-organization is returned unchanged (200,\nno audit row). 404 for an unknown org. The active owners are e-mailed.\nThe setup CLI (`org convert`) and a paid upgrade call the same\n`core.organizations.convert_organization`.",
        "operationId": "convert_organization_route_v1_organizations__org_id__convert_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgConvertRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgDetailOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Convert Organization Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/entitlement": {
      "get": {
        "description": "The org's effective entitlement, resolved fresh on every call (#1650) --\nsee `core.organizations.effective_entitlement`. Member-only (or platform\nadmin), matching the subtree endpoint's own visibility gate.",
        "operationId": "get_organization_entitlement_route_v1_organizations__org_id__entitlement_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgEntitlementOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Organization Entitlement Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/export": {
      "get": {
        "description": "Export the caller's own org as a downloadable JSON bundle (#1506).\n\nOwner/admin of the org (or an instance/platform admin) only. The response is the\nbundle itself, served as an attachment so a browser downloads it directly.",
        "operationId": "export_organization_data_v1_organizations__org_id__export_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Export Organization Data",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/import": {
      "post": {
        "description": "Import a bundle into the caller's own org (#1506). Owner/admin of the org (or an\ninstance/platform admin) only. Returns a report of what was imported and every\nconflict that was resolved (skipped / renamed / unresolved member).",
        "operationId": "import_organization_data_v1_organizations__org_id__import_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Import Organization Data",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/invites": {
      "get": {
        "description": "Pending/spent invites for an org. Owner/admin (or Platform Admin) only.",
        "operationId": "list_org_invites_route_v1_organizations__org_id__invites_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgInvitesResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Org Invites Route",
        "tags": [
          "Organizations"
        ]
      },
      "post": {
        "description": "Invite a user to an org by email (#1209). Owner/admin of the org (or an\ninstance/platform admin, or -- #1652 -- an ancestor org's holder of\n``org.members.manage`` via delegated hierarchical authority) only.\nRedeeming the token joins the org directly.\n\n#2228: under the org's ``invite_policy = members`` any active member may\nalso invite, single-use at the ``member`` role, and outside ``open``\nmode only an address that already has an account (403 ``reason:\norg_policy``, ``rule: invite_policy``). An address off the org's\nallowed email domains is refused with 422 (``rule:\nallowed_email_domains``); with account-creating invites switched off,\nan invite for an address without an account is refused in ``invite``\nmode (403, ``rule: allow_account_creating_invites``).",
        "operationId": "create_org_invite_route_v1_organizations__org_id__invites_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgInviteCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgInviteOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Org Invite Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/invites/bulk": {
      "post": {
        "description": "Bulk org invite (#1654): invite MULTIPLE emails, all at the same\n`org_role`/`max_uses`, in one request -- by calling `create_org_invite`\n(the EXACT singular mechanism -- #1209, #1652) once per email, never\nreimplementing invite creation. Authorization is evaluated ONCE for the\nwhole batch (every email shares the same `org_role`, so there is exactly\none grant-authority question to answer, not N identical ones).\n\n**Partial-failure convention (judgment call -- no prior bulk-with-\npartial-failure precedent existed in this codebase before this issue):**\none invalid/failing email does NOT abort the batch. Every email is\nattempted independently and this always returns `207 Multi-Status` with a\nper-email outcome (`created` or `failed` + reason) -- HTTP already\ndefines `207` for exactly this \"some items succeeded, some didn't\" shape,\nso this reuses that standard meaning rather than inventing a bespoke\nconvention or an all-or-nothing 4xx/2xx choice that would either abandon\n4 good emails over 1 bad one, or hide a real per-email failure behind a\nblanket 201.\n\n#2228: the org policy applies per row as on the singular route; a row it\nrefuses fails with ``reason: org_policy`` and its ``rule``.",
        "operationId": "bulk_create_org_invites_route_v1_organizations__org_id__invites_bulk_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgBulkInviteCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "207": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkOrgInviteResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Bulk Create Org Invites Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/invites/{invite_id}/revoke": {
      "post": {
        "description": "Revoke an org invite. Verifies the invite belongs to this org (so a caller\ncan't revoke another org's invite by guessing ids), then owner/admin-gates.",
        "operationId": "revoke_org_invite_route_v1_organizations__org_id__invites__invite_id__revoke_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "invite_id",
            "required": true,
            "schema": {
              "title": "Invite Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgInviteOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke Org Invite Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/limits": {
      "get": {
        "description": "Every onboarding limit of the org (#2226), resolved at its entitlement\nroot: tier default, then operator override, bounded by the licensed\nvalue (strictest wins). Each item says which `source` applied.\n\n`view: full` (every limit with `source`, `override_scope`, `clamped` and\n`entitlement_root_id`) for a caller with `org.members.manage` on the org\n(direct or delegated from an ancestor) and for a Platform Admin (any org;\n404 for an unknown one). An ordinary active member gets `view: member`:\nthe org-policy knobs' availability only. A suspended member or an\noutsider gets 403, whether or not the org exists. `enforced` is false\nwhile the gateway runs limits in shadow mode. The full view also carries\n`seats` (as `GET …/seats`, #2227).",
        "operationId": "get_organization_limits_route_v1_organizations__org_id__limits_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgLimitsOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Organization Limits Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/limits/{key}": {
      "delete": {
        "description": "Remove a per-org operator override (#2226): the installation override\nor tier default applies again. Platform Admin only; audited\n`ORG_LIMIT_OVERRIDE_SET` with `cleared: true` (no row when there was no\noverride); the JSON body carries the `reason`. Same 404/409 as setting\none.",
        "operationId": "clear_organization_limit_route_v1_organizations__org_id__limits__key__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "key",
            "required": true,
            "schema": {
              "title": "Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgLimitOverrideClear"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgLimitsOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Clear Organization Limit Route",
        "tags": [
          "Organizations"
        ]
      },
      "put": {
        "description": "Set a per-org operator override (#2226). Platform Admin only (403).\nThe override replaces the tier default and the installation override for\nthis org; a licensed value still bounds it (the response shows the\neffective value, `clamped` when the license or tier tightened it).\nAudited `ORG_LIMIT_OVERRIDE_SET` with the reason. 404 for an unknown org\nor key, 409 on an org that inherits its entitlement, 422 for a value of\nthe wrong kind or out of bounds.",
        "operationId": "set_organization_limit_route_v1_organizations__org_id__limits__key__put",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "key",
            "required": true,
            "schema": {
              "title": "Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgLimitOverrideSet"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgLimitsOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Organization Limit Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/members": {
      "get": {
        "description": "Members of an org, for a caller holding ``org.members.view`` on it, an\nancestor-org manager (delegated ``org.members.manage``) or a Platform\nAdmin (#1853; see ``_require_org_members_view``).\n403 otherwise -- org membership is itself tenant-scoped information.\n\nEach item carries the org-visible state (``is_active``, ``suspended_at``)\nand two booleans about the caller, from\n``core.account_admin.org_member_account_flags``: ``managed_by_caller``\n(the caller is verified for account management in this org, as the reset\nroute verifies it, and ``managed_by(member, org_id)``) and\n``resettable_by_caller`` (the org reset-password route would accept it).\nBoth are false for a caller who may only view the roster.\nThe account-global ``is_oidc_linked`` / ``must_change_password`` are\nreturned only where ``managed_by_caller`` is true and are null otherwise:\nfor a viewer, or for an account that also lives outside this org's tree,\nthey would describe the account beyond this tenant. All of it is a hint;\nthe action routes re-check everything.",
        "operationId": "list_organization_members_route_v1_organizations__org_id__members_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgMembersResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Organization Members Route",
        "tags": [
          "Organizations"
        ]
      },
      "post": {
        "description": "Add a user to an org, or change their role (upsert). Allowed for the org's\nown owner/admin as well as instance/platform admins (#1208), or -- #1652 --\nan ancestor org's holder of ``org.members.manage``, without needing their\nown separate membership in ``org_id``.\n\n#1934 (ADR tenant-scoped-user-administration Decision 1): a caller who is\nnot a Platform Admin may only change the role of a user who is already a\nmember of ``org_id``, or directly add a user ``org_id`` already manages\n(``managed_by``: an account wholly inside this org's tree). Any other\nuser gets the same 404 as an id that doesn't exist, and nothing is\nwritten; users from elsewhere join by accepting an invite. A Platform\nAdmin keeps direct add for any user, and an orgless user added this way\ngets this org as home. The home flag of an existing membership is never\nchanged (see ``core.organizations.add_org_member``).\n\n#2309: changing the role of a member who is currently an owner or admin\nneeds owner-level authority (``org.roles.manage`` in this org, directly\nor delegated from an ancestor; a Platform Admin always has it) -- 403\nwith detail ``requires_owner`` otherwise. A change that would demote the\norg's last active owner is refused with 409 and detail ``last_owner``,\nyourself included: promote another member to owner first. Both are\nchecked inside the write's transaction. Lowering your own role needs no\nowner authority.",
        "operationId": "add_organization_member_route_v1_organizations__org_id__members_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgMemberAddRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Add Organization Member Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/bulk-roles": {
      "post": {
        "description": "Bulk role assignment (#1654): grant ONE custom role (#1897),\noptionally time-boxed, to a LIST of user ids in one request -- by calling\n`assign_org_role` (the EXACT singular mechanism `assign_org_role_route`\nitself calls) once per user id, never reimplementing assignment.\nAuthorization -- `org.members.manage` (`_require_members_manage`) AND the\ngrant-authority superset rule against the SPECIFIC role being granted\n(`_require_can_grant_role`) -- is evaluated ONCE for the whole batch,\nexactly mirroring the singular endpoint's own two checks (this endpoint\ndoes NOT add #1652 delegated-authority support beyond what\n`_require_members_manage` itself already does -- it has none today,\nunlike `routes/organizations.py`'s member-management gates -- so bulk\nstays byte-identical in authorization shape to the singular route).\n\nSame partial-failure convention as the bulk-invite routes (see\n`routes/organizations.py`'s `bulk_create_org_invites_route` docstring):\none user id that isn't a member of `org_id` (or any other per-row\nfailure) does NOT abort the rest of the batch -- always `207\nMulti-Status` with a per-user-id outcome.",
        "operationId": "bulk_assign_org_role_route_v1_organizations__org_id__members_bulk_roles_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkRoleAssignRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "207": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkRoleAssignResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Bulk Assign Org Role Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}": {
      "delete": {
        "description": "Remove a user from an org. Allowed for the org's own owner/admin as well\nas instance/platform admins (#1208). Refuses to remove the org's LAST owner —\nthat would leave it unadministrable — mirroring the last-admin guard on user\nroles.\n\n#1648: the last-owner guard below is a structural invariant (\"is this the\nonly holder of the owner ROLE\"), independent of any single permission --\nper the ADR and #1647's seed-derivation notes, it intentionally stays\nreading ``organization_members.org_role`` directly (since #2309 inside the\ndelete's transaction, ``core.organizations._another_active_owner_conn``)\nrather than being reshaped into a permission check, unaffected by\nthis cutover. `_require_org_manage` above is the piece that moved to the\npermission resolver.\n\n#2309: removing an owner or admin needs owner-level authority\n(``org.roles.manage`` in this org, directly or delegated; a Platform\nAdmin always has it) -- 403 with detail ``requires_owner`` otherwise;\nleaving yourself needs none. Removing the org's last active, unsuspended\nowner is 409 with detail ``last_owner`` (promote another member to owner\nfirst); the detail used to be prose. Every check runs inside the delete's\ntransaction.",
        "operationId": "remove_organization_member_route_v1_organizations__org_id__members__user_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Remove Organization Member Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}/account-status": {
      "patch": {
        "description": "Deactivate (``is_active: false``) or reactivate a MANAGED account (#1852).\n\nAccount-global, unlike suspend (which only affects this org): the account\ncan no longer sign in anywhere and its sessions stop refreshing. 403\nunless the account is managed by this org; acting on an admin or owner\nneeds owner-level authority. 409 for your own account, or when the target\nis the last active owner of an organization.",
        "operationId": "set_org_member_account_status_route_v1_organizations__org_id__members__user_id__account_status_patch",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgMemberAccountStatusRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgMemberAccountStatusOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Org Member Account Status Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}/effective-permissions": {
      "get": {
        "description": "The resolved-permissions view (#1649) -- for every permission the\nmember effectively holds (via a non-expired ``organization_member_roles``\ngrant), name the role and (if applicable) the permission group it came\nfrom. See ``core.authorization.get_org_effective_permissions_detailed``\nfor exactly how each entry is derived.",
        "operationId": "get_effective_permissions_route_v1_organizations__org_id__members__user_id__effective_permissions_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EffectivePermissionsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Effective Permissions Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}/reset-password": {
      "post": {
        "description": "Reset a MANAGED member's local password (#1852).\n\nSame request/response contract as ``POST /v1/auth/users/{id}/reset-password``\n(#1776): ``mode: \"set\"`` takes ``new_password``; ``mode: \"generate\"``\nreturns a server-generated ``temporary_password`` exactly once. The user\nmust change it on next login and all their sessions stop refreshing.\n\n403 unless the account is managed by this org; admins may reset members,\nowners may also reset admins, and no one may reset an owner here. SSO\naccounts get 409; resetting yourself gets 409 (use change-password).",
        "operationId": "reset_org_member_password_route_v1_organizations__org_id__members__user_id__reset_password_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgMemberPasswordResetRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgMemberPasswordResetResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Reset Org Member Password Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}/restore-role": {
      "post": {
        "description": "Apply ONE member's preserved original role from a past import (#1506 follow-up).\n\n``apply_org_import`` always downgrades an imported member to plain ``member`` (a\ndeliberate anti-escalation default that never changes) but PRESERVES the bundle's\noriginally-claimed role for reference. This is the governed, later, separate\naction that reapplies it — deliberately ONE member per call, never a bulk\n\"restore everyone\": a bulk restore would just re-trust the unreviewed bundle\nwholesale, exactly the risk the import downgrade exists to prevent.\n\nRequires the SAME authority as export/import (org owner/admin, or an instance/\nplatform admin) PLUS the normal role-grant rank check — an org ``admin`` still\ncannot restore a member to ``owner``, mirroring the add-member route's guard.\n404 if this member has no preserved role to restore (never imported, or already\na plain member the bundle never claimed otherwise). Every actual restoration is\naudited.\n\n#2309: a restore is a role change and carries the member-add route's guards,\nchecked inside the write's transaction against the member's CURRENT role:\nchanging the role of a current owner or admin needs owner-level authority\n(403 ``requires_owner``; a Platform Admin always has it), demoting the org's\nlast active owner is 409 ``last_owner``, and a demotion revokes the member's\nsessions. A preserved role restores once: a repeat is 409 ``already_restored``.",
        "operationId": "restore_organization_member_role_v1_organizations__org_id__members__user_id__restore_role_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Restore Organization Member Role",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}/roles": {
      "get": {
        "operationId": "list_member_role_assignments_route_v1_organizations__org_id__members__user_id__roles_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberRoleAssignmentsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Member Role Assignments Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      },
      "post": {
        "description": "Grant a CUSTOM role to a member, optionally time-boxed via\n``expires_at`` (#1649). A system role is rejected with 422 (#1897): it is\nset through the membership's ``org_role`` instead. Requires\n``org.members.manage`` (the same base authority as adding/removing a\nmember) AND the grant-authority superset rule against the SPECIFIC role\nbeing granted.",
        "operationId": "assign_org_role_route_v1_organizations__org_id__members__user_id__roles_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleAssignRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleAssignmentOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Assign Org Role Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}/roles/{role_id}": {
      "delete": {
        "operationId": "revoke_org_role_route_v1_organizations__org_id__members__user_id__roles__role_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "role_id",
            "required": true,
            "schema": {
              "title": "Role Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke Org Role Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}/suspend": {
      "post": {
        "description": "Suspend an INDIVIDUAL member's access within `org_id` (#1654) -- the\n`organization_members` row stays, membership is not removed, still\nvisible in `GET /{org_id}/members`. Distinct from\n`POST /{org_id}/suspend` (#1650), which suspends the WHOLE org for every\nmember -- see `core.organizations.suspend_org_member`'s docstring for the\nprecise, documented definition of what \"blocks active use\" means here.\n\nRefuses (409) suspending the caller's OWN membership -- a suspended\nmember's effective permissions drop to zero (see\n`core.authorization._org_role_ids_conn`), including `org.members.suspend`\nitself, so a self-suspend could only ever be undone by a Platform Admin;\nthis is the same self-lockout-prevention spirit as the last-owner guard\nbelow, just applied to the caller specifically rather than a role count.\nAlso refuses suspending the org's LAST owner, mirroring\n`remove_organization_member_route`'s identical guard -- suspending every\nowner leaves the org exactly as unadministrable as removing them would.\n\n#2309: suspending an owner or admin needs owner-level authority\n(``org.roles.manage`` in this org, directly or delegated; a Platform\nAdmin always has it) -- 403 with detail ``requires_owner`` otherwise.\nSuspending the org's last active, unsuspended owner is 409 with detail\n``last_owner`` (promote another member to owner first); the detail used\nto be prose. Every check runs inside the suspension's transaction.",
        "operationId": "suspend_organization_member_route_v1_organizations__org_id__members__user_id__suspend_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgMemberItem"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Suspend Organization Member Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/members/{user_id}/unsuspend": {
      "post": {
        "description": "Reverse `suspend_organization_member_route`. See\n`core.organizations.unsuspend_org_member`.\n\n404 when the user is not a member of this organization. #2309:\nunsuspending an owner or admin needs owner-level authority\n(``org.roles.manage`` in this org, directly or delegated; a Platform\nAdmin always has it) -- 403 with detail ``requires_owner`` otherwise.\n\n#2227: a suspended membership holds no seat, so unsuspending takes one:\nrefused with 409 ``reason: seat_limit`` at a hard limit.",
        "operationId": "unsuspend_organization_member_route_v1_organizations__org_id__members__user_id__unsuspend_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgMemberItem"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Unsuspend Organization Member Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/move": {
      "post": {
        "description": "Re-parent `org_id` (or detach it to top-level if\n`new_parent_organization_id` is None). #1650: DUAL authority -- the\ncaller must hold `org.suborgs.manage` on BOTH the organization being\nmoved and the destination parent organization (or be a Platform Admin),\nidentical in shape to `core.teams`'s `move_team` one level down.\n\n#2191: a sub-organization has its parent's kind, so a move under a parent\nof another kind is refused with 409 `org_kind_mismatch` (a personal tree\nbecomes standard only through `POST /{org_id}/convert`). Detaching to\ntop-level keeps the kind.",
        "operationId": "move_organization_route_v1_organizations__org_id__move_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgMove"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgDetailOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Move Organization Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/permission-groups": {
      "get": {
        "operationId": "list_permission_groups_route_v1_organizations__org_id__permission_groups_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermissionGroupsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Permission Groups Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      },
      "post": {
        "operationId": "create_permission_group_route_v1_organizations__org_id__permission_groups_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PermissionGroupCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermissionGroupOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Permission Group Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/permission-groups/{group_id}": {
      "delete": {
        "operationId": "delete_permission_group_route_v1_organizations__org_id__permission_groups__group_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "group_id",
            "required": true,
            "schema": {
              "title": "Group Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Permission Group Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      },
      "get": {
        "operationId": "get_permission_group_route_v1_organizations__org_id__permission_groups__group_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "group_id",
            "required": true,
            "schema": {
              "title": "Group Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermissionGroupOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Permission Group Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/permission-groups/{group_id}/children": {
      "post": {
        "operationId": "add_group_child_route_v1_organizations__org_id__permission_groups__group_id__children_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "group_id",
            "required": true,
            "schema": {
              "title": "Group Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChildGroupIdRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Add Group Child Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/permission-groups/{group_id}/children/{child_group_id}": {
      "delete": {
        "operationId": "remove_group_child_route_v1_organizations__org_id__permission_groups__group_id__children__child_group_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "group_id",
            "required": true,
            "schema": {
              "title": "Group Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "child_group_id",
            "required": true,
            "schema": {
              "title": "Child Group Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Remove Group Child Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/permission-groups/{group_id}/permissions": {
      "post": {
        "operationId": "add_group_permission_route_v1_organizations__org_id__permission_groups__group_id__permissions_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "group_id",
            "required": true,
            "schema": {
              "title": "Group Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PermissionKeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Add Group Permission Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/permission-groups/{group_id}/permissions/{permission_key}": {
      "delete": {
        "operationId": "remove_group_permission_route_v1_organizations__org_id__permission_groups__group_id__permissions__permission_key__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "group_id",
            "required": true,
            "schema": {
              "title": "Group Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "permission_key",
            "required": true,
            "schema": {
              "title": "Permission Key",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Remove Group Permission Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/policy": {
      "get": {
        "description": "The org's onboarding policy (#2228): each knob's own `value` (null =\nnot set), the `effective` value enforced (the stricter of the org's and\nevery ancestor's), its `default`, whether the org may set it now\n(`available`; else `locked_reason` and, for `tier`, `available_on`),\n`source` (`default` | `organization` | `parent`) and `grandfathered`\n(set while available, unavailable now: still enforced, can only be\nreset). For the org's active members, `org.settings.manage` holders\n(direct or delegated) and Platform Admins; 403 otherwise.",
        "operationId": "get_organization_policy_route_v1_organizations__org_id__policy_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgPolicyOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Organization Policy Route",
        "tags": [
          "Organizations"
        ]
      },
      "patch": {
        "description": "Change the org's onboarding policy (#2228). Requires\n`org.settings.manage` (direct or delegated from an ancestor) or a\nPlatform Admin. Only the fields sent change; `null` resets a knob (it is\ninherited from the parent organization again, the default on a root\norg).\n\n* `invite_policy`: `admins` (default) or `members` (members may also\n  invite EXISTING accounts, single-use, at the member role);\n* `allow_account_creating_invites` (default true; switching it off is\n  always allowed);\n* `allowed_email_domains`: normalised (IDNA, lower-case), exact match;\n* `team_admins_may_create_accounts`: needs a non-empty allowed-domain\n  list (here or on a parent), else 422 `reason: org_policy`;\n* `require_2fa`: stored only (enforcement is #2241).\n\n403 `reason: entitlement`, `feature: policy.<knob>` for a change to a\nknob the org may not set now (a reset to the default is always\nallowed). 422 for an invalid domain. Audited `ORG_POLICY_UPDATED`.",
        "operationId": "update_organization_policy_route_v1_organizations__org_id__policy_patch",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrgPolicyPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgPolicyOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Organization Policy Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/roles": {
      "get": {
        "description": "Every role VISIBLE/usable from ``org_id`` for ``scope`` -- system\nroles, this org's own, and every ancestor's (#1649's descendant-org\nvisibility rule).",
        "operationId": "list_roles_route_v1_organizations__org_id__roles_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "scope",
            "required": false,
            "schema": {
              "default": "organization",
              "title": "Scope",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RolesResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Roles Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      },
      "post": {
        "operationId": "create_role_route_v1_organizations__org_id__roles_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Role Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/roles/{role_id}": {
      "delete": {
        "operationId": "delete_role_route_v1_organizations__org_id__roles__role_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "role_id",
            "required": true,
            "schema": {
              "title": "Role Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Role Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      },
      "get": {
        "operationId": "get_role_route_v1_organizations__org_id__roles__role_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "role_id",
            "required": true,
            "schema": {
              "title": "Role Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Role Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/roles/{role_id}/permission-groups": {
      "post": {
        "operationId": "add_role_permission_group_route_v1_organizations__org_id__roles__role_id__permission_groups_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "role_id",
            "required": true,
            "schema": {
              "title": "Role Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PermissionGroupIdRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Add Role Permission Group Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/roles/{role_id}/permission-groups/{group_id}": {
      "delete": {
        "operationId": "remove_role_permission_group_route_v1_organizations__org_id__roles__role_id__permission_groups__group_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "role_id",
            "required": true,
            "schema": {
              "title": "Role Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "group_id",
            "required": true,
            "schema": {
              "title": "Group Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Remove Role Permission Group Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/roles/{role_id}/permissions": {
      "post": {
        "operationId": "add_role_permission_route_v1_organizations__org_id__roles__role_id__permissions_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "role_id",
            "required": true,
            "schema": {
              "title": "Role Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PermissionKeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Add Role Permission Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/roles/{role_id}/permissions/{permission_key}": {
      "delete": {
        "operationId": "remove_role_permission_route_v1_organizations__org_id__roles__role_id__permissions__permission_key__delete",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "role_id",
            "required": true,
            "schema": {
              "title": "Role Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "permission_key",
            "required": true,
            "schema": {
              "title": "Permission Key",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Remove Role Permission Route",
        "tags": [
          "Roles & Permission Groups"
        ]
      }
    },
    "/v1/organizations/{org_id}/seats": {
      "get": {
        "description": "Seat usage of the org's entitlement root (#2227): `used` (active\naccounts with a non-suspended membership anywhere in the root's\n`inherit` tree, each person once), `reserved` (pending single-use\ninvites for addresses not yet seated), the resolved `max` (null =\nunlimited), its `behaviour` and `source`, and `state` (`over_limit`\ndrives the admin banner). Service accounts, API keys and Platform Admins\nacting cross-tenant never take a seat.\n\nFor a caller with `org.members.manage` on the org (direct or delegated)\nand a Platform Admin (any org; 404 for an unknown one) only: seat numbers\nleak the org's size, so an ordinary member, a suspended member and an\noutsider get 403.",
        "operationId": "get_organization_seats_route_v1_organizations__org_id__seats_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgSeatsOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Organization Seats Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/suborganizations": {
      "post": {
        "description": "Create a new organization with `parent_organization_id = org_id` (#1650)\n-- recursively, with NO special-casing between a root and an already-nested\n`org_id` (the same `provision_organization` call either way). Requires\n`org.suborgs.create` on `org_id` (or an instance/platform admin, or #1652\ndelegated hierarchical authority from a real ancestor grant), and\n(#2231) a tier on `org_id`'s entitlement root that allows\nsub-organizations: otherwise `403` with `reason: entitlement` and\n`limit: suborgs_allowed`, for a Platform Admin too.",
        "operationId": "create_suborganization_route_v1_organizations__org_id__suborganizations_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubOrgCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Suborganization Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/subtree": {
      "get": {
        "description": "The FULL descendant subtree of `org_id` (not just direct children),\nplus an aggregate metering/entitlement summary (#1650, \"rolled-up subtree\nreporting\"). Member-only (or platform admin), since a subtree listing is\nitself tenant-scoped information about the caller's own org.",
        "operationId": "get_organization_subtree_route_v1_organizations__org_id__subtree_get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgSubtreeResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Organization Subtree Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/suspend": {
      "post": {
        "description": "Suspend an organization (#1650) -- see `core.organizations.suspend_organization`\nfor the precise, documented definition of what \"blocks active use\" means\nhere.",
        "operationId": "suspend_organization_route_v1_organizations__org_id__suspend_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgDetailOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Suspend Organization Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/organizations/{org_id}/unsuspend": {
      "post": {
        "operationId": "unsuspend_organization_route_v1_organizations__org_id__unsuspend_post",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "title": "Org Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgDetailOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Unsuspend Organization Route",
        "tags": [
          "Organizations"
        ]
      }
    },
    "/v1/plugins": {
      "get": {
        "description": "List all registered plugins (public endpoint), paginated (#147/C6).\n\nServed at both /v1/plugins and the legacy /plugins directly — the old /plugins\nused a 301 redirect, which drops the method/body on non-GET clients (#147).",
        "operationId": "list_plugins_v1_plugins_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginRegistryPluginListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Plugins",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/ai/tools": {
      "get": {
        "description": "Aggregate OpenAI-compatible tool definitions from all active plugins.\n\nTools come from a module plugin's in-code ``AI_TOOLS`` class attribute AND/OR\na manifest's ``ai_tools`` — so module plugins (telegraf, network) can now\nadvertise function-calling tools, not just manifest plugins (#60).",
        "operationId": "get_all_ai_tools_v1_plugins_ai_tools_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIToolsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get All Ai Tools",
        "tags": [
          "AI Tools"
        ]
      }
    },
    "/v1/plugins/install": {
      "post": {
        "description": "Install a plugin from a manifest (manifest-based, no code execution).\n\nAdmin-only (#1143): this registers a plugin into the single, platform-wide\nplugins_db/webhook_routes state for every tenant -- there is no per-user\nscoping concept for a plugin's existence at all, unlike e.g. /config's\nreal per-owner overlay. Matches this service's own bundles.py precedent\nfor equally-consequential platform-wide actions.",
        "operationId": "install_plugin_v1_plugins_install_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginInstallResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Install Plugin",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/install-from-git": {
      "post": {
        "description": "Install a manifest/webhook plugin by fetching it from an arbitrary git\nrepo -- no image rebuild (#1578, epic #1514; implements the #1577 decided\nmodel).\n\nTRUST MODEL (decided, #1577): third-party plugins are manifest+webhook\nONLY. This shallow-clones the repo to a throwaway temp dir, reads and\nstrictly validates ONLY the plugin manifest, and registers it through the\nexact same manifest/webhook path as an uploaded manifest. Fetched repo\ncode is NEVER imported or executed in-process -- the first-party in-process\ncode-plugin loader (core/plugin_loader.py) is a separate, untouched path.\n\nAdmin-only (#1143), platform-wide, same as /install. Body (JSON):\n  {\"repo_url\": \"https://...\", \"ref\": \"main\"?, \"subpath\": \"plugins/x\"?,\n   \"token\": \"<PAT>\"?}\nA private-repo token is used for the fetch and, on success, persisted\nENCRYPTED via the secrets vault (#1719) keyed per tenant + plugin, so the\nplugin can later be re-fetched (see refresh-from-git) without re-supplying\nit. The token is NEVER logged and never returned in any response.",
        "operationId": "install_plugin_from_git_v1_plugins_install_from_git_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginInstallResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Install Plugin From Git",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/reload-webhook": {
      "post": {
        "description": "Re-register a plugin's trigger from an uploaded manifest: a webhook\nroute, or -- #1680 -- a fresh ManifestTriggerRuntime for a schedule/poll\ntrigger.\n\nAdmin-only (#1143): repoints an EXISTING, already-installed plugin's\ntrigger from caller-uploaded manifest content.",
        "operationId": "reload_plugin_webhook_v1_plugins_reload_webhook_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookReloadResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Reload Plugin Webhook",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/schema": {
      "get": {
        "description": "The manifest-plugin JSON Schema (Draft-07). Fetch this and validate a\nplugin manifest against it directly -- no auth, no assumption of a running\ninstance beyond this registry being reachable. Returns the JSON Schema\ndocument as-is (it carries its own ``$schema``/``title``).",
        "operationId": "get_manifest_schema_v1_plugins_schema_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Manifest Schema V1 Plugins Schema Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Manifest Schema"
      }
    },
    "/v1/plugins/{plugin_name}": {
      "delete": {
        "description": "Uninstall a plugin. Admin-only (#1143): permanently removes it\nplatform-wide, for every tenant.",
        "operationId": "uninstall_plugin_v1_plugins__plugin_name__delete",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Uninstall Plugin",
        "tags": [
          "Plugins"
        ]
      },
      "get": {
        "description": "Get plugin details",
        "operationId": "get_plugin_v1_plugins__plugin_name__get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginDetail"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/actions/{action}": {
      "get": {
        "description": "Invoke a WHITELISTED read-only action on a running plugin, unauthenticated\nFOR FREE-TIER tools.\n\nOnly methods in the plugin's READ_ONLY_ACTIONS (a declared subset of ACTIONS)\nare reachable here — mutating actions (e.g. \"refresh\") stay POST-only and\nJWT-gated via invoke_plugin_action below. Query params are passed as keyword\nargs (GET has no body). #254: read-only data tools like get_crypto_price were\ngated behind the same JWT requirement as mutating actions purely because all\nactions shared one POST route; this gives them an unauthenticated path that\nmatches their actual semantics.\n\n#1322: this route enforced no license tier at all, so a paid-tier read tool\nwas reachable for free with NO JWT. A tool the catalog doesn't tier above\ncommunity stays fully anonymous (unchanged). A tool tiered above community\nneeds a caller identity to check a tier against at all, so it 401s with no\ntoken, and 403s for an insufficient tier — otherwise \"no token\" would be\nindistinguishable from \"free tier\", defeating the gate entirely.",
        "operationId": "invoke_plugin_read_action_v1_plugins__plugin_name__actions__action__get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "action",
            "required": true,
            "schema": {
              "title": "Action",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginActionEnvelope"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Invoke Plugin Read Action",
        "tags": [
          "Plugins"
        ]
      },
      "post": {
        "description": "Invoke a WHITELISTED action on a running plugin (the write/execute path).\n\nOnly methods a plugin explicitly exposes via its ``ACTIONS`` set are callable\n— no arbitrary method access. A JSON-object body is passed as keyword args.\nReads still use /collect + /analysis; this is for state-changing actions such\nas the telegraf plugin's config management.",
        "operationId": "invoke_plugin_action_v1_plugins__plugin_name__actions__action__post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "action",
            "required": true,
            "schema": {
              "title": "Action",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginActionEnvelope"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Invoke Plugin Action",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/analysis": {
      "get": {
        "description": "Return the plugin's ``analyze()`` output verbatim.\n\nThe registry does NOT reshape the result — each plugin owns its own\nanalysis schema (per the plugin contract, reads go through\n``/analysis`` → ``analyze()``). Consumers that want a plugin-specific\nview read the fields that plugin documents.\n\nAnonymous unless the plugin declares a paid AI tool on ``/analysis``;\nthat needs a license tier, checked like an action route's.",
        "operationId": "get_plugin_analysis_v1_plugins__plugin_name__analysis_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Plugin Analysis V1 Plugins  Plugin Name  Analysis Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Analysis",
        "tags": [
          "AI Tools"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/collect": {
      "post": {
        "description": "Manually trigger a plugin's background data collection.\n\nDispatches through the same ``collect_plugin_data`` the hourly\nscheduler uses (#1034) rather than calling the plugin instance's\n``collect_data()`` directly — that raw call skipped both the\nfingerprint-dedup loop shared-data plugins rely on AND the per-owner\niteration ``PRIVATE_PER_USER`` plugins (e.g. ``portfolio``) rely on,\nrunning a single collection under whatever config happened to be\nleft on the shared instance rather than every real subscriber's own\nconfig. For a ``PRIVATE_PER_USER`` plugin this also scopes the\ntriggered run to the CALLER's own owner_id only — any authenticated\nuser could otherwise force a collection cycle across every other\ntenant's private data with no relationship to it at all.",
        "operationId": "trigger_plugin_collection_v1_plugins__plugin_name__collect_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionTriggeredResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Trigger Plugin Collection",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/config": {
      "get": {
        "description": "Return a plugin's config schema + current effective values (secrets masked).\n\nEffective = declared defaults → env → persisted (API-set) overrides. A UI can\nrender `schema` as a form and show `values` as the live config.\n\nJWT-gated (like the PUT): config can carry secret-typed fields, and masking\ndepends on the schema author flagging them — so it must not be readable by an\nunauthenticated caller (secrets shouldn't ride the platform's GET-open policy).",
        "operationId": "get_plugin_config_v1_plugins__plugin_name__config_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginConfigResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Config",
        "tags": [
          "Plugins"
        ]
      },
      "put": {
        "description": "Update a plugin's config (JWT-gated): validate → persist → apply live.\n\nBody is a JSON object of {key: value} for keys in the plugin's CONFIG_SCHEMA.\nMerges over existing persisted overrides, applies via apply_config (no restart).",
        "operationId": "update_plugin_config_v1_plugins__plugin_name__config_put",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginConfigUpdateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Plugin Config",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/disable": {
      "post": {
        "description": "Disable a plugin. Admin-only (#1143): toggles availability\nplatform-wide, for every tenant.",
        "operationId": "disable_plugin_v1_plugins__plugin_name__disable_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Disable Plugin",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/enable": {
      "post": {
        "description": "Enable a plugin. Admin-only (#1143): toggles availability\nplatform-wide, for every tenant.",
        "operationId": "enable_plugin_v1_plugins__plugin_name__enable_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Enable Plugin",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/health": {
      "get": {
        "description": "Get plugin health status",
        "operationId": "get_plugin_health_v1_plugins__plugin_name__health_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "The plugin's own health_check() result, or a {name, health_status, last_health_check, message} fallback when no instance is loaded."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Health",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/refresh-from-git": {
      "post": {
        "description": "Re-fetch an already-installed manifest/webhook plugin from git and apply\nthe fresh manifest in place (#1719 — the deferred half of #1578).\n\nAdmin-only, platform-wide. Body (JSON):\n  {\"repo_url\": \"https://...\", \"ref\": \"main\"?, \"subpath\": \"plugins/x\"?,\n   \"token\": \"<PAT>\"?}\nFor a PRIVATE repo the caller need NOT re-supply the token: when ``token`` is\nomitted, the one persisted (encrypted) at install time is used. If a fresh\n``token`` IS supplied it is used for this fetch AND re-persisted (rotation).\nThe token is never logged or returned. The re-fetched manifest's name must\nmatch ``plugin_name`` (a refresh updates a plugin in place; it does not\nrename or replace it with a different plugin).",
        "operationId": "refresh_plugin_from_git_v1_plugins__plugin_name__refresh_from_git_post",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginInstallResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Refresh Plugin From Git",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/secrets": {
      "get": {
        "description": "List the NAMES of secrets configured for this plugin in the caller's\nscope -- never the values. Write-only surface: there is no plaintext\nread-back; a plugin reads its own decrypted creds through the scoped SDK\npath, not this API.",
        "operationId": "list_secrets_v1_plugins__plugin_name__secrets_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretKeysResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Secrets",
        "tags": [
          "Plugin Secrets"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/secrets/{secret_key}": {
      "delete": {
        "description": "Delete one named secret for this plugin in the caller's scope. 404 if no\nsuch secret is set (nothing to delete).",
        "operationId": "delete_secret_v1_plugins__plugin_name__secrets__secret_key__delete",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "secret_key",
            "required": true,
            "schema": {
              "title": "Secret Key",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretStatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Secret",
        "tags": [
          "Plugin Secrets"
        ]
      },
      "put": {
        "description": "Set/update one named secret (encrypted at rest) for this plugin in the\ncaller's scope. Body: ``{\"value\": \"<plaintext>\"}``. The response never\nechoes the value -- only confirmation metadata.",
        "operationId": "set_secret_v1_plugins__plugin_name__secrets__secret_key__put",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "secret_key",
            "required": true,
            "schema": {
              "title": "Secret Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": true,
                "title": "Body",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretStatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Secret",
        "tags": [
          "Plugin Secrets"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/{resource_name}": {
      "get": {
        "description": "List a plugin-declared RESOURCES collection: query params besides\n``limit``/``cursor`` are passed through as ``filters`` -- a plugin\nimplements pagination/filtering once in its own ``list()``, with no\nhand-rolled parsing inside a single action (#1677).",
        "operationId": "list_plugin_resource_v1_plugins__plugin_name___resource_name__get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "resource_name",
            "required": true,
            "schema": {
              "title": "Resource Name",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResourceListEnvelope"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Plugin Resource",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/plugins/{plugin_name}/{resource_name}/{item_id}": {
      "get": {
        "description": "Get a single item from a plugin-declared resource by id (#1677).\nSame gating as ``list_plugin_resource`` above.",
        "operationId": "get_plugin_resource_v1_plugins__plugin_name___resource_name___item_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_name",
            "required": true,
            "schema": {
              "title": "Plugin Name",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "resource_name",
            "required": true,
            "schema": {
              "title": "Resource Name",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "item_id",
            "required": true,
            "schema": {
              "title": "Item Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginResourceItemEnvelope"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugin Resource",
        "tags": [
          "Plugins"
        ]
      }
    },
    "/v1/profile/me": {
      "get": {
        "description": "Return the authenticated caller's own Minder profile/preferences.\n\nA user who has never edited anything reads back an empty default profile\n(display_name null, preferences {}), so the client can always render the form.\n\n#2234: also `workspace_state` and `can_create_workspace`, so the client can\nshow the \"No workspace yet\" page to an account without an organization.",
        "operationId": "get_my_profile_v1_profile_me_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get My Profile",
        "tags": [
          "User Profile"
        ]
      },
      "patch": {
        "description": "Edit the authenticated caller's own Minder profile/preferences (partial).\n\nOnly supplied fields change. `preferences`, when supplied, REPLACES the\nstored blob (predictable semantics). Rejects an entirely-empty PATCH and an\noversized preferences blob.",
        "operationId": "update_my_profile_v1_profile_me_patch",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update My Profile",
        "tags": [
          "User Profile"
        ]
      }
    },
    "/v1/public-chat/endpoints": {
      "get": {
        "description": "List the caller's org's public chat endpoints (tenant-scoped).",
        "operationId": "list_public_endpoints_v1_public_chat_endpoints_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Public Endpoints",
        "tags": [
          "Public Chat"
        ]
      },
      "post": {
        "description": "Create a public chat endpoint in the caller's own org.",
        "operationId": "create_public_endpoint_v1_public_chat_endpoints_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EndpointCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Public Endpoint",
        "tags": [
          "Public Chat"
        ]
      }
    },
    "/v1/public-chat/endpoints/{endpoint_id}": {
      "delete": {
        "description": "Delete an endpoint the caller's org owns (404 if it isn't theirs).",
        "operationId": "delete_public_endpoint_v1_public_chat_endpoints__endpoint_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Public Endpoint",
        "tags": [
          "Public Chat"
        ]
      },
      "get": {
        "description": "Fetch one endpoint the caller's org owns (404 if it isn't theirs).",
        "operationId": "get_public_endpoint_v1_public_chat_endpoints__endpoint_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Public Endpoint",
        "tags": [
          "Public Chat"
        ]
      },
      "patch": {
        "description": "Partially update an endpoint the caller's org owns.",
        "operationId": "update_public_endpoint_v1_public_chat_endpoints__endpoint_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EndpointUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Public Endpoint",
        "tags": [
          "Public Chat"
        ]
      }
    },
    "/v1/public-chat/endpoints/{endpoint_id}/conversations": {
      "get": {
        "description": "List the anonymous conversations/sessions for an endpoint the caller owns.\n\nPaginated, most-recently-active first. 404 if the endpoint isn't in the\ncaller's tenant, so an admin only ever sees their own org's conversations.",
        "operationId": "list_endpoint_conversations_v1_public_chat_endpoints__endpoint_id__conversations_get",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Endpoint Conversations",
        "tags": [
          "Public Chat"
        ]
      }
    },
    "/v1/public-chat/endpoints/{endpoint_id}/conversations/{session_id}": {
      "get": {
        "description": "Read a single anonymous conversation's turns for an owned endpoint.\n\n404 if the endpoint isn't the caller's tenant's, and 404 (from rag-pipeline)\nif the session isn't one of that endpoint+tenant's — a caller can never read a\nconversation outside their own tenant.",
        "operationId": "get_endpoint_conversation_v1_public_chat_endpoints__endpoint_id__conversations__session_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "max_turns",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Max Turns",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Endpoint Conversation",
        "tags": [
          "Public Chat"
        ]
      }
    },
    "/v1/public-chat/endpoints/{endpoint_id}/feedback": {
      "get": {
        "description": "Aggregate thumbs up/down totals for an owned endpoint's responses (#1583).\n\nThe per-turn feedback is already folded into the conversation-detail read\nabove; this is the at-a-glance summary. 404 if the endpoint isn't in the\ncaller's tenant, so an admin only ever sees their own org's feedback. The\nendpoint's own ``tenant_id`` is passed to rag-pipeline for the DB-layer\ntenant filter — never a value the caller could forge.",
        "operationId": "get_endpoint_feedback_v1_public_chat_endpoints__endpoint_id__feedback_get",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Endpoint Feedback",
        "tags": [
          "Public Chat"
        ]
      }
    },
    "/v1/rag/{path}": {
      "delete": {
        "description": "Proxy all /v1/rag/* requests to RAG Pipeline service (writes require JWT).\n\nLong timeout: document ingestion/embedding can run well past the shared\nclient's 30s default (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_rag_pipeline_v1_rag__path__delete",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Rag Pipeline"
      },
      "get": {
        "description": "Proxy all /v1/rag/* requests to RAG Pipeline service (writes require JWT).\n\nLong timeout: document ingestion/embedding can run well past the shared\nclient's 30s default (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_rag_pipeline_v1_rag__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Rag Pipeline"
      },
      "patch": {
        "description": "Proxy all /v1/rag/* requests to RAG Pipeline service (writes require JWT).\n\nLong timeout: document ingestion/embedding can run well past the shared\nclient's 30s default (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_rag_pipeline_v1_rag__path__patch",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Rag Pipeline"
      },
      "post": {
        "description": "Proxy all /v1/rag/* requests to RAG Pipeline service (writes require JWT).\n\nLong timeout: document ingestion/embedding can run well past the shared\nclient's 30s default (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_rag_pipeline_v1_rag__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Rag Pipeline"
      },
      "put": {
        "description": "Proxy all /v1/rag/* requests to RAG Pipeline service (writes require JWT).\n\nLong timeout: document ingestion/embedding can run well past the shared\nclient's 30s default (see _LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_rag_pipeline_v1_rag__path__put",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Rag Pipeline"
      }
    },
    "/v1/status": {
      "get": {
        "description": "Aggregate health across every core service for the client's Status page\n(#platform-status). No single-service /health today crosses the browser --\neach is internal-docker-network only -- so this is the one endpoint a\nbrowser can actually reach to see the whole fleet at once. `version` is\neach service's own hardcoded string, not derived from the deployed image\ntag -- a \"reported version,\" not a deployment-tracking signal.",
        "operationId": "fleet_status_v1_status_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Fleet Status"
      }
    },
    "/v1/stt": {
      "post": {
        "description": "Proxy POST /v1/stt (no trailing path) -- multipart audio upload, same\nroot-route need as /v1/tts above.\n\nLong timeout: see proxy_to_stt.",
        "operationId": "stt_root_v1_stt_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Stt Root"
      }
    },
    "/v1/stt/{path}": {
      "get": {
        "description": "Proxy /v1/stt/* to the TTS/STT service (writes require JWT).\n\nLong timeout: transcribing longer audio can take a while (see\n_LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_stt_v1_stt__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Stt"
      },
      "post": {
        "description": "Proxy /v1/stt/* to the TTS/STT service (writes require JWT).\n\nLong timeout: transcribing longer audio can take a while (see\n_LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_stt_v1_stt__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Stt"
      }
    },
    "/v1/teams": {
      "get": {
        "description": "List the teams of the caller's active organization (switching\norganization changes the list), plus any team with no organization that\nthe caller belongs to. A caller who is not an active member of their\nactive organization gets an empty list. A Platform Admin lists every\norganization's teams (#2311).",
        "operationId": "list_teams_route_v1_teams_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Teams Route",
        "tags": [
          "Teams"
        ]
      },
      "post": {
        "description": "Create a team; the caller becomes its team_admin. Also mints a fresh\nJWT (#1148) since the caller's existing token necessarily predates this\nexact membership change -- see TeamCreateOut's docstring.\n\n#2287: the team belongs to the caller's ACTIVE organization, resolved\nexactly as every other create stamps its tenant\n(``shared.tenancy.resolve_tenant_id``: ``active_tenant_id``, else the\nhome ``tenant_id``). Any active member of that org may create a team in\nit (the RBAC ADR's \"any authenticated user can create a team\", now inside\ntheir tenant); the membership is re-checked against the DB, so a stale\nor forged active org, or a suspended membership, gets a 403 and nothing\nis written. A Platform Admin may create in whatever org they are acting\nin. A caller with no org at all gets a 403 (not the shared helper's 401,\nwhich would end the client's session).\n\nWith ``parent_team_id`` the team is a sub-team: the caller needs\n``team.subteams.manage`` on the parent (directly or delegated from an\nancestor team, #1652), and the parent must be in the same active org.",
        "operationId": "create_team_route_v1_teams_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamCreateOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Team Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}": {
      "delete": {
        "operationId": "delete_team_route_v1_teams__team_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "reparent_children_to",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Reparent Children To"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Team Route",
        "tags": [
          "Teams"
        ]
      },
      "get": {
        "description": "Team detail. A team the caller can't list (another organization, or\ntheir active one when they aren't an active member of it) is 404, the\nsame as a team that doesn't exist (#2311).\n\nThe roster is returned to the team's members and admins, holders of\n``org.members.view`` in the team's organization, and Platform Admins;\notherwise ``members`` is empty and ``roster_visible`` is false. Member\nemails are returned to team admins, organization managers\n(``org.members.manage``) and Platform Admins; otherwise each ``email`` is\nan empty string and ``emails_visible`` is false.",
        "operationId": "get_team_route_v1_teams__team_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamDetailOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Team Route",
        "tags": [
          "Teams"
        ]
      },
      "patch": {
        "operationId": "update_team_route_v1_teams__team_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Team Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/export": {
      "get": {
        "description": "Export the caller's own team as a downloadable JSON bundle (#1507).\n\nteam_admin of the team (or an instance/platform admin) only. Contains the team's\nroster and its team-shared KBs/pipelines — see the module note for what is scoped\nout. Served as an attachment so a browser downloads it directly.",
        "operationId": "export_team_data_v1_teams__team_id__export_get",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Export Team Data",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/import": {
      "post": {
        "description": "Import a bundle into the caller's own team (#1507). team_admin of the team (or an\ninstance/platform admin) only. Every imported KB/pipeline is stamped to THIS team\n(team_id + visibility='team' + the team's org tenant), so an import can never write\noutside the caller's own team. Returns a report of what was imported and every\nconflict resolved.",
        "operationId": "import_team_data_v1_teams__team_id__import_post",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Import Team Data",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/members": {
      "post": {
        "description": "Add a user to a team, by ``user_id`` or by ``email`` (#1072). Allowed\nfor the team's admins (``team.members.manage``), an ancestor team's\nholder of it (#1652), and Platform Admins.\n\n#2285 (ADR tenant-scoped-user-administration): a caller who is not a\nPlatform Admin may only add a user who is already a member of the team's\norg, or whom that org manages (``managed_by``: an account wholly inside\nthe org's tree). Any other user, an id that doesn't exist and an email no\naccount has all get the same 404, and nothing is written (no team or org\nmembership); users from elsewhere join by accepting an invite. A\nPlatform Admin keeps direct add for any user, and an unknown email tells\nthem so.",
        "operationId": "add_team_member_route_v1_teams__team_id__members_post",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MemberAdd"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamMemberOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Add Team Member Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/members/{user_id}": {
      "delete": {
        "operationId": "remove_team_member_route_v1_teams__team_id__members__user_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Remove Team Member Route",
        "tags": [
          "Teams"
        ]
      },
      "patch": {
        "operationId": "update_team_member_route_v1_teams__team_id__members__user_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MemberRoleUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamMemberOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Team Member Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/members/{user_id}/suspend": {
      "post": {
        "description": "Suspend an INDIVIDUAL team member's access within `team_id` (#1654) --\nthe `team_members` row stays, membership is not removed, still visible\nvia `GET /{team_id}`. Distinct from `POST /{team_id}/suspend` (#1651),\nwhich suspends the WHOLE team for every member -- see\n`core.teams.suspend_team_member`'s docstring for the precise definition\nof what \"blocks active use\" means here.\n\nRefuses (409) suspending the caller's OWN membership (self-lockout\nprevention -- a suspended member's effective permissions drop to zero,\nincluding `team.members.suspend` itself). Applies the EXACT same\nlast-admin guard `remove_team_member_route` does -- so suspending the\nteam's last ACTIVE `team_admin` is refused (409) the same way removing\nthem would be. #2312: the guard runs inside the suspension's transaction\nand counts only active, unsuspended team_admins; a Platform Admin is\nexempt.",
        "operationId": "suspend_team_member_route_v1_teams__team_id__members__user_id__suspend_post",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamMemberOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Suspend Team Member Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/members/{user_id}/unsuspend": {
      "post": {
        "description": "Reverse `suspend_team_member_route`. See\n`core.teams.unsuspend_team_member`.",
        "operationId": "unsuspend_team_member_route_v1_teams__team_id__members__user_id__unsuspend_post",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamMemberOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Unsuspend Team Member Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/move": {
      "post": {
        "description": "Re-parent `team_id` (or detach it to top-level if\n`new_parent_team_id` is None). #1651: DUAL authority -- the caller must\nhold `team.subteams.manage` on BOTH the team being moved and the\ndestination parent team (or be an instance admin), identical in shape to\nwhat #1650 does for organization move, one level down.\n\n#2313: taking a team away from its CURRENT parent (a detach, or a move\nelsewhere) also needs `team.subteams.manage` on that parent, since it\nends the parent's delegated oversight of the team. The parent-side checks\nare repeated by ``move_team`` against the locked rows.",
        "operationId": "move_team_route_v1_teams__team_id__move_post",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamMove"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Move Team Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/suspend": {
      "post": {
        "description": "Suspend a team (#1651) -- see `core/teams.py`'s `suspend_team` for the\nprecise, documented definition of what \"blocks active use\" means here.",
        "operationId": "suspend_team_route_v1_teams__team_id__suspend_post",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Suspend Team Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/teams/{team_id}/unsuspend": {
      "post": {
        "operationId": "unsuspend_team_route_v1_teams__team_id__unsuspend_post",
        "parameters": [
          {
            "in": "path",
            "name": "team_id",
            "required": true,
            "schema": {
              "title": "Team Id",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Unsuspend Team Route",
        "tags": [
          "Teams"
        ]
      }
    },
    "/v1/tools": {
      "get": {
        "description": "List all available AI tools (paginated).",
        "operationId": "list_all_tools_v1_tools_get",
        "parameters": [
          {
            "in": "query",
            "name": "active_only",
            "required": false,
            "schema": {
              "default": true,
              "title": "Active Only",
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "tier",
            "required": false,
            "schema": {
              "title": "Tier",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolDiscoveryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List All Tools",
        "tags": [
          "Tools"
        ]
      }
    },
    "/v1/tools/plugins/{plugin_id}/tools": {
      "get": {
        "description": "List all tools for a specific plugin (by marketplace UUID).",
        "operationId": "list_plugin_tools_v1_tools_plugins__plugin_id__tools_get",
        "parameters": [
          {
            "in": "path",
            "name": "plugin_id",
            "required": true,
            "schema": {
              "title": "Plugin Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolDiscoveryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Plugin Tools",
        "tags": [
          "Tools"
        ]
      }
    },
    "/v1/tools/validate": {
      "post": {
        "description": "Validate whether a caller's org tier grants access to a tool.\n\n#1322: authenticated + tenant-scoped. This route used to be UNGATED and\ntrusted the body ``tenant_id``, letting anyone enumerate any org's tool\nentitlements. Now only the platform operator / internal service principal\n(which legitimately cross tenants) may pass an arbitrary ``tenant_id``;\nevery other caller must ask about their OWN JWT tenant.",
        "operationId": "validate_tool_license_v1_tools_validate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LicenseValidationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/models__tool_execution__LicenseValidationResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Validate Tool License",
        "tags": [
          "Tools"
        ]
      }
    },
    "/v1/tools/{tool_name}": {
      "get": {
        "description": "Get details for a specific tool.",
        "operationId": "get_tool_details_v1_tools__tool_name__get",
        "parameters": [
          {
            "in": "path",
            "name": "tool_name",
            "required": true,
            "schema": {
              "title": "Tool Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolDiscoveryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Tool Details",
        "tags": [
          "Tools"
        ]
      }
    },
    "/v1/tools/{tool_name}/execute": {
      "post": {
        "description": "Execute an AI tool. The license/tier check runs against the VERIFIED\ncaller's ORGANIZATION (the JWT ``tenant_id``, #622 re-key), not a\nclient-suppliable field.",
        "operationId": "execute_tool_endpoint_v1_tools__tool_name__execute_post",
        "parameters": [
          {
            "in": "path",
            "name": "tool_name",
            "required": true,
            "schema": {
              "title": "Tool Name",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToolExecutionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolExecutionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Execute Tool Endpoint",
        "tags": [
          "Tools"
        ]
      }
    },
    "/v1/tts": {
      "post": {
        "description": "Proxy POST /v1/tts (no trailing path) -- {path:path} above requires at\nleast one path segment after /v1/tts/, so the bare synthesis call needs its\nown route, mirroring the /v1/models root-route pattern.\n\nLong timeout: see proxy_to_tts.",
        "operationId": "tts_root_v1_tts_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Tts Root"
      }
    },
    "/v1/tts/{path}": {
      "get": {
        "description": "Proxy /v1/tts/* to the TTS/STT service (writes require JWT). Synthesis\n(`POST /v1/tts`) returns binary WAV/MP3, not JSON -- proxy_request already\npasses non-JSON bodies through raw.\n\nLong timeout: synthesizing longer text can take a while (see\n_LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_tts_v1_tts__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Tts"
      },
      "post": {
        "description": "Proxy /v1/tts/* to the TTS/STT service (writes require JWT). Synthesis\n(`POST /v1/tts`) returns binary WAV/MP3, not JSON -- proxy_request already\npasses non-JSON bodies through raw.\n\nLong timeout: synthesizing longer text can take a while (see\n_LONG_OPERATION_TIMEOUT).",
        "operationId": "proxy_to_tts_v1_tts__path__post",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Proxy To Tts"
      }
    }
  }
}
