Skip to content
Commits on Source (6)
from flask import jsonify, request from flask import jsonify, request
from pydantic import ValidationError from pydantic import ValidationError
from edge_cloud_management_api.managers.log_manager import logger from edge_cloud_management_api.managers.log_manager import logger
from edge_cloud_management_api.services.pi_edge_services import PiEdgeAPIClientFactory from edge_cloud_management_api.services.edge_cloud_services import PiEdgeAPIClientFactory
from edge_cloud_management_api.services.storage_service import get_zone
...@@ -99,6 +100,11 @@ def create_app_instance(): ...@@ -99,6 +100,11 @@ def create_app_instance():
if not app_id or not edge_zone_id : if not app_id or not edge_zone_id :
return jsonify({"error": "Missing required fields: appId, edgeCloudZoneId, or kubernetesCLusterRef"}), 400 return jsonify({"error": "Missing required fields: appId, edgeCloudZoneId, or kubernetesCLusterRef"}), 400
local_zone = get_zone(edge_zone_id)
if not local_zone:
# TODO: apply federation logic
return 'Zone belongs to federated partner OP. Switching to Federation Manager.'
logger.info(f"Preparing to send deployment request to SRM for appId={app_id}") logger.info(f"Preparing to send deployment request to SRM for appId={app_id}")
pi_edge_client_factory = PiEdgeAPIClientFactory() pi_edge_client_factory = PiEdgeAPIClientFactory()
......
from flask import jsonify from flask import jsonify
from pydantic import BaseModel, Field, ValidationError from pydantic import BaseModel, Field, ValidationError
from typing import List from typing import List
from edge_cloud_management_api.configs.env_config import config
from edge_cloud_management_api.managers.log_manager import logger from edge_cloud_management_api.managers.log_manager import logger
from edge_cloud_management_api.services.pi_edge_services import PiEdgeAPIClientFactory from edge_cloud_management_api.services.edge_cloud_services import PiEdgeAPIClientFactory
from edge_cloud_management_api.services.storage_service import insert_zones
pi_edge_factory = PiEdgeAPIClientFactory()
api_client = pi_edge_factory.create_pi_edge_api_client()
zones = api_client.edge_cloud_zones()
for zone in zones:
zone['_id'] = zone.get('edgeCloudZoneId')
insert_zones(zones)
class EdgeCloudZone(BaseModel): class EdgeCloudZone(BaseModel):
edgeCloudZoneId: str = Field(..., description="Unique identifier of the Edge Cloud Zone") edgeCloudZoneId: str = Field(..., description="Unique identifier of the Edge Cloud Zone")
......
from flask import request, jsonify, Response from flask import request, jsonify
import json import logging
import connexion
from requests.exceptions import Timeout, ConnectionError
from edge_cloud_management_api.managers.log_manager import logger
import requests
from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory
# Factory pattern # Factory pattern
factory = FederationManagerClientFactory() factory = FederationManagerClientFactory()
federation_client = factory.create_federation_client() federation_client = factory.create_federation_client()
def handle_response(status_code, title, detail):
return Response(
json.dumps({
"title": title,
"detail": detail,
"status": status_code
}),
status=status_code,
content_type="application/problem+json"
)
def create_federation(): def create_federation():
"""POST /partner - Create federation with partner OP.""" """POST /partner - Create federation with partner OP."""
try:
body = request.get_json()
result = federation_client.post_partner(body)
if "error" in result:
return handle_response(502, "Federation Error", result["error"])
return jsonify(result), 200
except Exception as e:
return handle_response(400, "Bad Request", str(e))
body = request.get_json()
token = __get_token()
response = federation_client.post_partner(body, token)
return jsonify(response)
def get_federation(federationContextId): def get_federation(federationContextId):
"""GET /{federationContextId}/partner - Get federation info.""" """GET /{federationContextId}/partner - Get federation info."""
try:
result = federation_client.get_partner(federationContextId)
if "error" in result:
return handle_response(502, "Federation Error", result["error"])
return jsonify(result), 200
except Exception as e:
return handle_response(400, "Bad Request", str(e))
token = __get_token()
result = federation_client.get_partner(federationContextId, token)
return jsonify(result)
def delete_federation(federationContextId): def delete_federation(federationContextId):
"""DELETE /{federationContextId}/partner - Delete federation.""" """DELETE /{federationContextId}/partner - Delete federation."""
try:
result = federation_client.delete_partner(federationContextId)
if "error" in result:
return handle_response(502, "Federation Error", result["error"])
return jsonify(result), 200
except Exception as e:
return handle_response(400, "Bad Request", str(e))
token = __get_token()
result = federation_client.delete_partner(federationContextId, token)
return jsonify(result)
def get_federation_context_ids(): def get_federation_context_ids():
"""GET /fed-context-id - Fetch federationContextId(s).""" """GET /fed-context-id - Fetch federationContextId(s)."""
try: token = __get_token()
result = federation_client.get_federation_context_ids() response = federation_client.get_federation_context_ids(token)
if "error" in result: return jsonify(response)
return handle_response(502, "Federation Error", result["error"])
return jsonify(result), 200
except Exception as e:
return handle_response(400, "Bad Request", str(e))
def onboard_application_to_partner(federationContextId): def onboard_application_to_partner(federationContextId):
"""POST /{federationContextId}/application/onboarding - Onboard app.""" """POST /{federationContextId}/application/onboarding - Onboard app."""
try:
body = request.get_json() body = request.get_json()
result = federation_client.onboard_application(federationContextId, body) token = __get_token()
if "error" in result: result = federation_client.onboard_application(federationContextId, body, token)
return handle_response(502, "Onboarding Error", result["error"]) return jsonify(result)
return jsonify(result), 202
except Exception as e:
return handle_response(400, "Bad Request", str(e))
def get_onboarded_app(federationContextId, appId): def get_onboarded_app(federationContextId, appId):
"""GET /{federationContextId}/application/onboarding/app/{appId}""" """GET /{federationContextId}/application/onboarding/app/{appId}"""
try:
result = federation_client.get_onboarded_app(federationContextId, appId) token = __get_token()
if "error" in result: result = federation_client.get_onboarded_app(federationContextId, appId, token)
return handle_response(result.get("status_code", 502), "Retrieval Error", result["error"]) return jsonify(result)
return jsonify(result), 200
except Exception as e:
return handle_response(500, "Internal Server Error", str(e))
def delete_onboarded_app(federationContextId, appId): def delete_onboarded_app(federationContextId, appId):
"""DELETE /{federationContextId}/application/onboarding/app/{appId}""" """DELETE /{federationContextId}/application/onboarding/app/{appId}"""
try:
result = federation_client.delete_onboarded_app(federationContextId, appId) token = __get_token()
if "error" in result: result = federation_client.delete_onboarded_app(federationContextId, appId, token)
return handle_response(result.get("status_code", 502), "Deletion Error", result["error"]) return jsonify(result)
return jsonify({"message": f"App {appId} successfully deleted from partner"}), 200
except Exception as e:
return handle_response(500, "Internal Server Error", str(e)) def __get_token():
bearer = connexion.request.headers['Authorization']
token = bearer.split()[1]
return token
from flask import jsonify from flask import jsonify
from pydantic import ValidationError #Field from pydantic import ValidationError #Field
from edge_cloud_management_api.managers.log_manager import logger from edge_cloud_management_api.managers.log_manager import logger
from edge_cloud_management_api.services.pi_edge_services import PiEdgeAPIClientFactory from edge_cloud_management_api.services.edge_cloud_services import PiEdgeAPIClientFactory
def create_qod_session(body: dict): def create_qod_session(body: dict):
""" """
......
import os
from jose import JWTError, jwt
from werkzeug.exceptions import Unauthorized
def decode_token(token:str):
JWT_ISSUER = os.environ.get('JWT_ISSUER')
PUBLIC_KEY = os.environ.get('JWT_PUBLIC_KEY')
try:
return jwt.decode(token, key=PUBLIC_KEY, algorithms=["RS256"], issuer=JWT_ISSUER)
except JWTError as e:
raise Unauthorized from e
def check_oAuth2ClientCredentials(token):
return {'scopes': ['fed-mgmt'], 'uid': 'test_value'}
def validate_scope_oAuth2ClientCredentials(required_scopes, token_scopes):
return set(required_scopes).issubset(set(token_scopes))
...@@ -9,14 +9,12 @@ proxies = { ...@@ -9,14 +9,12 @@ proxies = {
"https": config.HTTP_PROXY, "https": config.HTTP_PROXY,
} }
class PiEdgeAPIClient: class PiEdgeAPIClient:
def __init__(self, base_url, username, password): def __init__(self, base_url, username, password):
self.base_url = base_url self.base_url = base_url
self.username = username self.username = username
self.password = password self.password = password
self.token = None self.token = None
#self.requests_session = self._get_proxy_session(proxies)
def _get_proxy_session(self, session_proxies): def _get_proxy_session(self, session_proxies):
...@@ -340,9 +338,6 @@ class PiEdgeAPIClient: ...@@ -340,9 +338,6 @@ class PiEdgeAPIClient:
logger.info(e.args) logger.info(e.args)
return e.args return e.args
class PiEdgeAPIClientFactory: class PiEdgeAPIClientFactory:
""" """
Factory class to create instances of PiEdgeAPIClient. Factory class to create instances of PiEdgeAPIClient.
......
...@@ -3,27 +3,30 @@ import requests ...@@ -3,27 +3,30 @@ import requests
from requests.exceptions import Timeout, ConnectionError from requests.exceptions import Timeout, ConnectionError
from edge_cloud_management_api.configs.env_config import config from edge_cloud_management_api.configs.env_config import config
from edge_cloud_management_api.managers.log_manager import logger from edge_cloud_management_api.managers.log_manager import logger
from edge_cloud_management_api.services.pi_edge_services import PiEdgeAPIClientFactory from edge_cloud_management_api.services.edge_cloud_services import PiEdgeAPIClientFactory
class FederationManagerClient: class FederationManagerClient:
def __init__(self, base_url=None): def __init__(self, base_url=None):
self.base_url = base_url or config.FEDERATION_MANAGER_HOST self.base_url = base_url or config.FEDERATION_MANAGER_HOST
def _get_headers(self): def _get_headers(self, token):
return { headers = {}
"Content-Type": "application/json", if token is not None:
"Accept": "application/json" headers['Authorization'] = 'Bearer '+token
}
headers['Content-Type'] = 'application/json'
headers['Accept'] = 'application/json'
return headers
def post_partner(self, data: dict): def post_partner(self, data: dict, token: str):
url = f"{self.base_url}/partner" url = f"{self.base_url}/partner"
try: try:
response = requests.post(url, json=data, headers=self._get_headers(), timeout=10) response = requests.post(url, json=data, headers=self._get_headers(token), timeout=10)
response.raise_for_status() response.raise_for_status()
return response.json() return response.json()
except Timeout: except Timeout:
logger.error("POST /partner timed out") logger.error("POST /partner timed out")
return {"error": "Request timed out"} return {"error": "Request timed out"}, 408
except ConnectionError: except ConnectionError:
logger.error("POST /partner connection error") logger.error("POST /partner connection error")
return {"error": "Connection error"} return {"error": "Connection error"}
...@@ -34,10 +37,10 @@ class FederationManagerClient: ...@@ -34,10 +37,10 @@ class FederationManagerClient:
logger.error(f"POST /partner unexpected error: {e}") logger.error(f"POST /partner unexpected error: {e}")
return {"error": str(e)} return {"error": str(e)}
def get_partner(self, federation_context_id: str): def get_partner(self, federation_context_id: str, token: str):
url = f"{self.base_url}/{federation_context_id}/partner" url = f"{self.base_url}/{federation_context_id}/partner"
try: try:
response = requests.get(url, headers=self._get_headers(), timeout=10) response = requests.get(url, headers=self._get_headers(token), timeout=10)
response.raise_for_status() response.raise_for_status()
return response.json() return response.json()
except Timeout: except Timeout:
...@@ -53,10 +56,10 @@ class FederationManagerClient: ...@@ -53,10 +56,10 @@ class FederationManagerClient:
logger.error(f"GET /{id}/partner unexpected error: {e}") logger.error(f"GET /{id}/partner unexpected error: {e}")
return {"error": str(e)} return {"error": str(e)}
def delete_partner(self, federation_context_id: str): def delete_partner(self, federation_context_id: str, token: str):
url = f"{self.base_url}/{federation_context_id}/partner" url = f"{self.base_url}/{federation_context_id}/partner"
try: try:
response = requests.delete(url, headers=self._get_headers(), timeout=10) response = requests.delete(url, headers=self._get_headers(token), timeout=10)
if response.content: if response.content:
return response.json() return response.json()
return {"status": response.status_code} return {"status": response.status_code}
...@@ -73,10 +76,10 @@ class FederationManagerClient: ...@@ -73,10 +76,10 @@ class FederationManagerClient:
logger.error(f"DELETE /{id}/partner unexpected error: {e}") logger.error(f"DELETE /{id}/partner unexpected error: {e}")
return {"error": str(e)} return {"error": str(e)}
def get_federation_context_ids(self): def get_federation_context_ids(self, token: str):
url = f"{self.base_url}/fed-context-id" url = f"{self.base_url}/fed-context-id"
try: try:
response = requests.get(url, headers=self._get_headers(), timeout=10) response = requests.get(url, headers=self._get_headers(token), timeout=10)
response.raise_for_status() response.raise_for_status()
return response.json() return response.json()
except Timeout: except Timeout:
...@@ -87,12 +90,13 @@ class FederationManagerClient: ...@@ -87,12 +90,13 @@ class FederationManagerClient:
return {"error": "Connection error"} return {"error": "Connection error"}
except requests.exceptions.HTTPError as http_err: except requests.exceptions.HTTPError as http_err:
logger.error(f"GET /fed-context-id HTTP error: {http_err}") logger.error(f"GET /fed-context-id HTTP error: {http_err}")
return {"error": str(http_err), "status_code": response.status_code} if response.status_code==404:
return {'erorr': http_err}, 404
except Exception as e: except Exception as e:
logger.error(f"GET /fed-context-id unexpected error: {e}") logger.error(f"GET /fed-context-id unexpected error: {e}")
return {"error": str(e)} return {"error": str(e)}
def onboard_application(self, federation_context_id: str, body: dict): def onboard_application(self, federation_context_id: str, body: dict, token: str):
url = f"{self.base_url}/{federation_context_id}/application/onboarding" url = f"{self.base_url}/{federation_context_id}/application/onboarding"
try: try:
response = requests.post(url, headers=self._get_headers(), json=body, timeout=10) response = requests.post(url, headers=self._get_headers(), json=body, timeout=10)
...@@ -112,10 +116,10 @@ class FederationManagerClient: ...@@ -112,10 +116,10 @@ class FederationManagerClient:
return {"error": str(e)} return {"error": str(e)}
def get_onboarded_app(self, federation_context_id: str, app_id: str): def get_onboarded_app(self, federation_context_id: str, app_id: str, token: str):
url = f"{self.base_url}/{federation_context_id}/application/onboarding/app/{app_id}" url = f"{self.base_url}/{federation_context_id}/application/onboarding/app/{app_id}"
try: try:
response = requests.get(url, headers=self._get_headers(), timeout=10) response = requests.get(url, headers=self._get_headers(token), timeout=10)
response.raise_for_status() response.raise_for_status()
return response.json() return response.json()
except Timeout: except Timeout:
...@@ -131,7 +135,7 @@ class FederationManagerClient: ...@@ -131,7 +135,7 @@ class FederationManagerClient:
logger.error(f"GET onboarded app unexpected error: {e}") logger.error(f"GET onboarded app unexpected error: {e}")
return {"error": str(e), "status_code": 500} return {"error": str(e), "status_code": 500}
def delete_onboarded_app(self, federation_context_id: str, app_id: str): def delete_onboarded_app(self, federation_context_id: str, app_id: str, token: str):
url = f"{self.base_url}/{federation_context_id}/application/onboarding/app/{app_id}" url = f"{self.base_url}/{federation_context_id}/application/onboarding/app/{app_id}"
try: try:
response = requests.delete(url, headers=self._get_headers(), timeout=10) response = requests.delete(url, headers=self._get_headers(), timeout=10)
......
from edge_cloud_management_api.configs.env_config import config
import pymongo
storage_url = mongo_host = config.MONGO_URI
mydb_mongo = 'oeg_storage'
def insert_zones(zone_list: list):
collection = "zones"
myclient = pymongo.MongoClient(storage_url)
mydbmongo = myclient[mydb_mongo]
col = mydbmongo[collection]
col.insert_many(zone_list)
def get_zone(zone_id: str):
collection = "zones"
myclient = pymongo.MongoClient(storage_url)
mydbmongo = myclient[mydb_mongo]
col = mydbmongo[collection]
zone = col.find_one({'_id': zone_id})
return zone
\ No newline at end of file
--- ---
openapi: 3.0.3 openapi: 3.0.3
info: info:
title: Edge Application Management API title: Open Exposure Gateway API
version: 0.9.3-wip version: 1.0.1-wip
description: | description: |
Edge Application Management API allows API consumers to manage the Open Exposure Gateway API allows API consumers to manage the
Life Cycle of an Application and to Discover Edge Cloud Zones. Life Cycle of an Application, Discover Edge Cloud Zones and request Network Resources.
# Overview # Overview
The reference scenario foresees a distributed Telco Edge Cloud where any The reference scenario foresees a distributed Telco Edge Cloud where any
Application Delevoper, known as an Application Provider, can host and Application Delevoper, known as an Application Provider, can host and
...@@ -149,20 +149,12 @@ info: ...@@ -149,20 +149,12 @@ info:
name: Apache 2.0 name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html url: https://www.apache.org/licenses/LICENSE-2.0.html
externalDocs: externalDocs:
description: Product documentation at Camara description: Product documentation at Camara0
url: https://github.com/camaraproject/EdgeCloud url: https://github.com/camaraproject/EdgeCloud
servers: servers:
- url: http://vitrualserver:8080/oeg/1.0.0 - url: http://vitrualserver:8080/oeg/1.0.0
tags:
- name: Application
description: Application and Application Instance Lice Cycle Management
- name: Edge Cloud
description: Edge Cloud Zones Availability
- name: FederationManagement
description: Federation Manager
paths: paths:
/apps: /apps:
post: post:
...@@ -817,17 +809,16 @@ paths: ...@@ -817,17 +809,16 @@ paths:
"405": "405":
description: Method not allowed description: Method not allowed
"404": "404":
<<<<<<< HEAD
description: Session not found
=======
description: Session not found description: Session not found
>>>>>>> f18e931881554973db7ae6241588db6e667dbf10
/partner: /partner:
post: post:
tags: tags:
- FederationManagement - FederationManagement
summary: Creates one direction federation with partner operator platform. summary: Creates one direction federation with partner operator platform.
security:
- oAuth2ClientCredentials:
- fed-mgmt
operationId: edge_cloud_management_api.controllers.federation_manager_controller.create_federation operationId: edge_cloud_management_api.controllers.federation_manager_controller.create_federation
requestBody: requestBody:
content: content:
...@@ -876,14 +867,14 @@ paths: ...@@ -876,14 +867,14 @@ paths:
application/problem+json: application/problem+json:
schema: schema:
$ref: '#/components/schemas/ProblemDetails' $ref: '#/components/schemas/ProblemDetails'
"409": "408":
description: Conflict description: Timeout
content: content:
application/problem+json: application/problem+json:
schema: schema:
$ref: '#/components/schemas/ProblemDetails' $ref: '#/components/schemas/ProblemDetails'
"422": "409":
description: Unprocessable Entity description: Conflict
content: content:
application/problem+json: application/problem+json:
schema: schema:
...@@ -894,20 +885,6 @@ paths: ...@@ -894,20 +885,6 @@ paths:
application/problem+json: application/problem+json:
schema: schema:
$ref: '#/components/schemas/ProblemDetails' $ref: '#/components/schemas/ProblemDetails'
"503":
description: Service Unavailable
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
"520":
description: Web Server Returned an Unknown Error
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
default:
description: Generic Error
callbacks: callbacks:
onPartnerStatusEvent: onPartnerStatusEvent:
'{$request.body#/partnerStatusLink }': '{$request.body#/partnerStatusLink }':
...@@ -1069,6 +1046,9 @@ paths: ...@@ -1069,6 +1046,9 @@ paths:
\ The response shall provide info about the zones offered by the partner,\ \ The response shall provide info about the zones offered by the partner,\
\ partner OP network codes, information about edge discovery and LCM service\ \ partner OP network codes, information about edge discovery and LCM service\
\ etc." \ etc."
security:
- oAuth2ClientCredentials:
- fed-mgmt
operationId: edge_cloud_management_api.controllers.federation_manager_controller.get_federation operationId: edge_cloud_management_api.controllers.federation_manager_controller.get_federation
parameters: parameters:
- name: federationContextId - name: federationContextId
...@@ -1085,12 +1065,6 @@ paths: ...@@ -1085,12 +1065,6 @@ paths:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/inline_response_200_1' $ref: '#/components/schemas/inline_response_200_1'
"400":
description: Bad request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
"401": "401":
description: Unauthorized description: Unauthorized
content: content:
...@@ -1103,42 +1077,19 @@ paths: ...@@ -1103,42 +1077,19 @@ paths:
application/problem+json: application/problem+json:
schema: schema:
$ref: '#/components/schemas/ProblemDetails' $ref: '#/components/schemas/ProblemDetails'
"409":
description: Conflict
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
"422":
description: Unprocessable Entity
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
"500": "500":
description: Internal Server Error description: Internal Server Error
content: content:
application/problem+json: application/problem+json:
schema: schema:
$ref: '#/components/schemas/ProblemDetails' $ref: '#/components/schemas/ProblemDetails'
"503":
description: Service Unavailable
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
"520":
description: Web Server Returned an Unknown Error
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
default:
description: Generic Error
delete: delete:
tags: tags:
- FederationManagement - FederationManagement
summary: Remove existing federation with the partner OP summary: Remove existing federation with the partner OP
security:
- oAuth2ClientCredentials:
- fed-mgmt
operationId: edge_cloud_management_api.controllers.federation_manager_controller.delete_federation operationId: edge_cloud_management_api.controllers.federation_manager_controller.delete_federation
parameters: parameters:
- name: federationContextId - name: federationContextId
...@@ -1151,27 +1102,14 @@ paths: ...@@ -1151,27 +1102,14 @@ paths:
responses: responses:
"200": "200":
description: Federation removed successfully description: Federation removed successfully
"400":
description: Bad request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
"401": "401":
description: Unauthorized description: Unauthorized
content: content:
application/problem+json: application/problem+json:
schema: schema:
$ref: '#/components/schemas/ProblemDetails' $ref: '#/components/schemas/ProblemDetails'
"409": "404":
description: Conflict description: Not Found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
"422":
description: Unprocessable Entity
content: content:
application/problem+json: application/problem+json:
schema: schema:
...@@ -1182,25 +1120,14 @@ paths: ...@@ -1182,25 +1120,14 @@ paths:
application/problem+json: application/problem+json:
schema: schema:
$ref: '#/components/schemas/ProblemDetails' $ref: '#/components/schemas/ProblemDetails'
"503":
description: Service Unavailable
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
"520":
description: Web Server Returned an Uknown Error
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
default:
description: Generic Error
/fed-context-id: /fed-context-id:
get: get:
tags: tags:
- FederationManagement - FederationManagement
summary: Retrieves the existing federationContextId with partner operator platform. summary: Retrieves the existing federationContextId with partner operator platform.
security:
- oAuth2ClientCredentials:
- fed-mgmt
operationId: edge_cloud_management_api.controllers.federation_manager_controller.get_federation_context_ids operationId: edge_cloud_management_api.controllers.federation_manager_controller.get_federation_context_ids
responses: responses:
"200": "200":
...@@ -1245,10 +1172,22 @@ paths: ...@@ -1245,10 +1172,22 @@ paths:
components: components:
# securitySchemes: # securitySchemes:
# openId: # jwt: # arbitrary name for the security scheme
# description: OpenID Provider Configuration Information. # type: http
# type: openIdConnect # scheme: bearer
# openIdConnectUrl: https://example.com/.well-known/openid-configuration # bearerFormat: JWT
# x-bearerInfoFunc: edge_cloud_management_api.controllers.security_controller.decode_token
securitySchemes:
oAuth2ClientCredentials:
type: oauth2
flows:
clientCredentials:
tokenUrl: http://isiath.duckdns.org:8081//realms/federation/protocol/openid-connect/token
scopes:
fed-mgmt: Access to the federation APIs
x-tokenInfoFunc: edge_cloud_management_api.controllers.security_controller.check_oAuth2ClientCredentials
x-scopeValidateFunc: edge_cloud_management_api.controllers.security_controller.validate_scope_oAuth2ClientCredentials
parameters: parameters:
x-correlator: x-correlator:
name: x-correlator name: x-correlator
......
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.26.0 (40646f47)
creationTimestamp: null
labels:
io.kompose.service: oegmongo
name: oegmongo
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: oegmongo
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.26.0 (40646f47)
creationTimestamp: null
labels:
#io.kompose.network/netEMPkub: "true"
io.kompose.service: oegmongo
spec:
containers:
- image: mongo
name: oegmongo
ports:
- containerPort: 27017
resources: {}
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.26.0 (40646f47)
creationTimestamp: null
labels:
io.kompose.service: oegmongo
name: oegmongo
spec:
type: ClusterIP
ports:
- name: "27018"
port: 27018
targetPort: 27017
selector:
io.kompose.service: oegmongo
status:
loadBalancer: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.26.0 (40646f47)
creationTimestamp: null
labels:
io.kompose.service: oegcontroller
name: oegcontroller
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: oegcontroller
strategy: {}
template:
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.26.0 (40646f47)
creationTimestamp: null
labels:
io.kompose.service: oegcontroller
spec:
containers:
- env:
- name: MONGO_URI
value: mongodb://oegmongo/sample_db?authSource=admin
- name: SRM_HOST
value: http://srm:8080/srm/1.0.0
- name: FEDERATION_MANAGER_HOST
value: http://federation-manager:8989
image: ghcr.io/sunriseopenoperatorplatform/oeg/oeg
name: oegcontroller
ports:
- containerPort: 8080
resources: {}
imagePullPolicy: Always
restartPolicy: Always
status: {}
---
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.26.0 (40646f47)
creationTimestamp: null
labels:
io.kompose.service: oeg
name: oeg
spec:
type: NodePort
ports:
- name: "8080"
nodePort: 32414
port: 8080
targetPort: 8080
selector:
io.kompose.service: oegcontroller
status:
loadBalancer: {}
# This file was autogenerated by uv via the following command: # This file was autogenerated by uv via the following command:
# uv export # uv export
#-e . #-e .
a2wsgi==1.10.7 \ a2wsgi==1.10.7
--hash=sha256:6d7c602fb1f9cc6afc6c6d0558d3354f3c7aa281e73e6dc9e001dbfc1d9e80cf \ annotated-types==0.7.0
--hash=sha256:ce462ff7e1daac0bc57183c6f800f09a71c2a7a98ddd5cdeca149e3eabf3338e anyio==4.7.0
annotated-types==0.7.0 \ attrs==24.2.0
--hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ blinker==1.9.0
--hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 cachetools==5.5.0
anyio==4.7.0 \ certifi==2024.8.30
--hash=sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48 \ chardet==5.2.0
--hash=sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352 charset-normalizer==3.4.0
asgiref==3.8.1 \ click==8.1.7
--hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \ colorama==0.4.6
--hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590 connexion==3.1.0
attrs==24.2.0 \ distlib==0.3.9
--hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ dnspython==2.7.0
--hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 filelock==3.16.1
blinker==1.9.0 \ flask==3.1.0
--hash=sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf \ h11==0.14.0
--hash=sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc hatchling==1.26.3
cachetools==5.5.0 \ httpcore==1.0.7
--hash=sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292 \ httptools==0.6.4
--hash=sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a httpx==0.28.1
certifi==2024.8.30 \ idna==3.10
--hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \ inflection==0.5.1
--hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9 iniconfig==2.0.0
chardet==5.2.0 \ itsdangerous==2.2.0
--hash=sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7 \ jinja2==3.1.4
--hash=sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970 jsonschema==4.23.0
charset-normalizer==3.4.0 \ jsonschema-specifications==2024.10.1
--hash=sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6 \ markupsafe==3.0.2
--hash=sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8 \ mongomock==4.3.0
--hash=sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565 \ mypy==1.14.1
--hash=sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64 \ mypy-extensions==1.0.0
--hash=sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e \ packaging==24.2
--hash=sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23 \ pathspec==0.12.1
--hash=sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284 \ platformdirs==4.3.6
--hash=sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b \ pluggy==1.5.0
--hash=sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc \ pydantic==2.10.3
--hash=sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db \ pydantic-core==2.27.1
--hash=sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b \ pymongo==4.10.1
--hash=sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920 \ pyproject-api==1.8.0
--hash=sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7 \ pytest==8.3.4
--hash=sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2 \ python-dotenv==1.0.1
--hash=sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b \ python-multipart==0.0.19
--hash=sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631 \ pytz==2024.2
--hash=sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15 \ pyyaml==6.0.2
--hash=sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250 \ referencing==0.35.1
--hash=sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88 \ requests==2.32.3
--hash=sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d \ rpds-py==0.22.3
--hash=sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90 \ ruff==0.8.2
--hash=sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9 \ sentinels==1.0.0
--hash=sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1 \ sniffio==1.3.1
--hash=sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719 \ starlette==0.41.3
--hash=sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114 \ swagger-ui-bundle==1.1.0
--hash=sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf \ tox==4.23.2
--hash=sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d \ trove-classifiers==2024.10.21.16
--hash=sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed \ typing-extensions==4.12.2
--hash=sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03 \ urllib3==2.2.3
--hash=sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67 \ uvicorn==0.32.1
--hash=sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079 \ uvloop==0.21.0
--hash=sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482 virtualenv==20.28.1
click==8.1.7 \ watchfiles==1.0.0
--hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ websockets==14.1
--hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de werkzeug==3.1.3
colorama==0.4.6 \ python-jose[cryptography]==3.5.0
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ \ No newline at end of file
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
connexion==3.1.0 \
--hash=sha256:66a44580991f53955b6e409a84fa9fa65c7ca4db52dc217b49cd35c201066083 \
--hash=sha256:e92b6d0412eb54b3b69f2516b93d982a06b0e23f6d5c1ab94257c55d365f63ce
distlib==0.3.9 \
--hash=sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87 \
--hash=sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403
dnspython==2.7.0 \
--hash=sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86 \
--hash=sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1
filelock==3.16.1 \
--hash=sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0 \
--hash=sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435
flask==3.1.0 \
--hash=sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac \
--hash=sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136
h11==0.14.0 \
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
--hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761
hatchling==1.26.3 \
--hash=sha256:b672a9c36a601a06c4e88a1abb1330639ee8e721e0535a37536e546a667efc7a \
--hash=sha256:c407e1c6c17b574584a66ae60e8e9a01235ecb6dc61d01559bb936577aaf5846
httpcore==1.0.7 \
--hash=sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c \
--hash=sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd
httptools==0.6.4 \
--hash=sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2 \
--hash=sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8 \
--hash=sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3 \
--hash=sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5 \
--hash=sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0 \
--hash=sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071 \
--hash=sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c \
--hash=sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1 \
--hash=sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44 \
--hash=sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083 \
--hash=sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660 \
--hash=sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970 \
--hash=sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2 \
--hash=sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81 \
--hash=sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f
httpx==0.28.1 \
--hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \
--hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad
idna==3.10 \
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
inflection==0.5.1 \
--hash=sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417 \
--hash=sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2
iniconfig==2.0.0 \
--hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \
--hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
itsdangerous==2.2.0 \
--hash=sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef \
--hash=sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173
jinja2==3.1.4 \
--hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
--hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
jsonschema==4.23.0 \
--hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \
--hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566
jsonschema-specifications==2024.10.1 \
--hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \
--hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf
markupsafe==3.0.2 \
--hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \
--hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \
--hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \
--hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \
--hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \
--hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \
--hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \
--hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \
--hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \
--hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \
--hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \
--hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \
--hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \
--hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \
--hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \
--hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \
--hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \
--hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \
--hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \
--hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \
--hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \
--hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \
--hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \
--hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \
--hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \
--hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \
--hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \
--hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \
--hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \
--hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \
--hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430
mongomock==4.3.0 \
--hash=sha256:32667b79066fabc12d4f17f16a8fd7361b5f4435208b3ba32c226e52212a8c30 \
--hash=sha256:5ef86bd12fc8806c6e7af32f21266c61b6c4ba96096f85129852d1c4fec1327e
mypy==1.14.1 \
--hash=sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd \
--hash=sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14 \
--hash=sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e \
--hash=sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6 \
--hash=sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107 \
--hash=sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11 \
--hash=sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a \
--hash=sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b \
--hash=sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255 \
--hash=sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1 \
--hash=sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9 \
--hash=sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9 \
--hash=sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34 \
--hash=sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89
mypy-extensions==1.0.0 \
--hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
--hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
packaging==24.2 \
--hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \
--hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f
pathspec==0.12.1 \
--hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \
--hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712
platformdirs==4.3.6 \
--hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \
--hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb
pluggy==1.5.0 \
--hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \
--hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669
pydantic==2.10.3 \
--hash=sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d \
--hash=sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9
pydantic-core==2.27.1 \
--hash=sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529 \
--hash=sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc \
--hash=sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c \
--hash=sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac \
--hash=sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2 \
--hash=sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a \
--hash=sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089 \
--hash=sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107 \
--hash=sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf \
--hash=sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5 \
--hash=sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23 \
--hash=sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02 \
--hash=sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235 \
--hash=sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16 \
--hash=sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c \
--hash=sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35 \
--hash=sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737 \
--hash=sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05 \
--hash=sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb \
--hash=sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e \
--hash=sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f \
--hash=sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960 \
--hash=sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08 \
--hash=sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337 \
--hash=sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51 \
--hash=sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381 \
--hash=sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb \
--hash=sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073 \
--hash=sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae
pymongo==4.10.1 \
--hash=sha256:0783e0c8e95397c84e9cf8ab092ab1e5dd7c769aec0ef3a5838ae7173b98dea0 \
--hash=sha256:11280809e5dacaef4971113f0b4ff4696ee94cfdb720019ff4fa4f9635138252 \
--hash=sha256:2e3a593333e20c87415420a4fb76c00b7aae49b6361d2e2205b6fece0563bf40 \
--hash=sha256:45ee87a4e12337353242bc758accc7fb47a2f2d9ecc0382a61e64c8f01e86708 \
--hash=sha256:4924355245a9c79f77b5cda2db36e0f75ece5faf9f84d16014c0a297f6d66786 \
--hash=sha256:544890085d9641f271d4f7a47684450ed4a7344d6b72d5968bfae32203b1bb7c \
--hash=sha256:594dd721b81f301f33e843453638e02d92f63c198358e5a0fa8b8d0b1218dabc \
--hash=sha256:6fb6a72e88df46d1c1040fd32cd2d2c5e58722e5d3e31060a0393f04ad3283de \
--hash=sha256:72e2ace7456167c71cfeca7dcb47bd5dceda7db2231265b80fc625c5e8073186 \
--hash=sha256:7bd26b2aec8ceeb95a5d948d5cc0f62b0eb6d66f3f4230705c1e3d3d2c04ec76 \
--hash=sha256:8ad05eb9c97e4f589ed9e74a00fcaac0d443ccd14f38d1258eb4c39a35dd722b \
--hash=sha256:90bc6912948dfc8c363f4ead54d54a02a15a7fee6cfafb36dc450fc8962d2cb7 \
--hash=sha256:a9de02be53b6bb98efe0b9eda84ffa1ec027fcb23a2de62c4f941d9a2f2f3330 \
--hash=sha256:dcc07b1277e8b4bf4d7382ca133850e323b7ab048b8353af496d050671c7ac52 \
--hash=sha256:e5d55f2a82e5eb23795f724991cac2bffbb1c0f219c0ba3bf73a835f97f1bb2e \
--hash=sha256:e974ab16a60be71a8dfad4e5afccf8dd05d41c758060f5d5bda9a758605d9a5d \
--hash=sha256:ee4c86d8e6872a61f7888fc96577b0ea165eb3bdb0d841962b444fa36001e2bb \
--hash=sha256:fb104c3c2a78d9d85571c8ac90ec4f95bca9b297c6eee5ada71fabf1129e1674 \
--hash=sha256:fbedc4617faa0edf423621bb0b3b8707836687161210d470e69a4184be9ca011
pyproject-api==1.8.0 \
--hash=sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228 \
--hash=sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496
pytest==8.3.4 \
--hash=sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6 \
--hash=sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761
python-dotenv==1.0.1 \
--hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
--hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
python-multipart==0.0.19 \
--hash=sha256:905502ef39050557b7a6af411f454bc19526529ca46ae6831508438890ce12cc \
--hash=sha256:f8d5b0b9c618575bf9df01c684ded1d94a338839bdd8223838afacfb4bb2082d
pytz==2024.2 \
--hash=sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a \
--hash=sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725
pyyaml==6.0.2 \
--hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
--hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \
--hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \
--hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \
--hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \
--hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \
--hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \
--hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \
--hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \
--hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \
--hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \
--hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \
--hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \
--hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \
--hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \
--hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \
--hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \
--hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \
--hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba
referencing==0.35.1 \
--hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \
--hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de
requests==2.32.3 \
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
rpds-py==0.22.3 \
--hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \
--hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \
--hash=sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61 \
--hash=sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5 \
--hash=sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56 \
--hash=sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd \
--hash=sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b \
--hash=sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4 \
--hash=sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d \
--hash=sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1 \
--hash=sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e \
--hash=sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc \
--hash=sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38 \
--hash=sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b \
--hash=sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c \
--hash=sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83 \
--hash=sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1 \
--hash=sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627 \
--hash=sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16 \
--hash=sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45 \
--hash=sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730 \
--hash=sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25 \
--hash=sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7 \
--hash=sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f \
--hash=sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd \
--hash=sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333 \
--hash=sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9 \
--hash=sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4 \
--hash=sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d \
--hash=sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15 \
--hash=sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84 \
--hash=sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e \
--hash=sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf \
--hash=sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b \
--hash=sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2 \
--hash=sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3 \
--hash=sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130 \
--hash=sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b \
--hash=sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de \
--hash=sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e
ruff==0.8.2 \
--hash=sha256:1ca4e3a87496dc07d2427b7dd7ffa88a1e597c28dad65ae6433ecb9f2e4f022f \
--hash=sha256:2aae99ec70abf43372612a838d97bfe77d45146254568d94926e8ed5bbb409ea \
--hash=sha256:32096b41aaf7a5cc095fa45b4167b890e4c8d3fd217603f3634c92a541de7248 \
--hash=sha256:5fe716592ae8a376c2673fdfc1f5c0c193a6d0411f90a496863c99cd9e2ae25d \
--hash=sha256:60f578c11feb1d3d257b2fb043ddb47501ab4816e7e221fbb0077f0d5d4e7b6f \
--hash=sha256:705832cd7d85605cb7858d8a13d75993c8f3ef1397b0831289109e953d833d29 \
--hash=sha256:729850feed82ef2440aa27946ab39c18cb4a8889c1128a6d589ffa028ddcfc22 \
--hash=sha256:81c148825277e737493242b44c5388a300584d73d5774defa9245aaef55448b0 \
--hash=sha256:ac42caaa0411d6a7d9594363294416e0e48fc1279e1b0e948391695db2b3d5b1 \
--hash=sha256:b402ddee3d777683de60ff76da801fa7e5e8a71038f57ee53e903afbcefdaa58 \
--hash=sha256:b84f4f414dda8ac7f75075c1fa0b905ac0ff25361f42e6d5da681a465e0f78e5 \
--hash=sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d \
--hash=sha256:cbd5cf9b0ae8f30eebc7b360171bd50f59ab29d39f06a670b3e4501a36ba5897 \
--hash=sha256:d261d7850c8367704874847d95febc698a950bf061c9475d4a8b7689adc4f7fa \
--hash=sha256:e769083da9439508833cfc7c23e351e1809e67f47c50248250ce1ac52c21fb93 \
--hash=sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5 \
--hash=sha256:f05cdf8d050b30e2ba55c9b09330b51f9f97d36d4673213679b965d25a785f3c \
--hash=sha256:fb88e2a506b70cfbc2de6fae6681c4f944f7dd5f2fe87233a7233d888bad73e8
sentinels==1.0.0 \
--hash=sha256:7be0704d7fe1925e397e92d18669ace2f619c92b5d4eb21a89f31e026f9ff4b1
sniffio==1.3.1 \
--hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
--hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
starlette==0.41.3 \
--hash=sha256:0e4ab3d16522a255be6b28260b938eae2482f98ce5cc934cb08dce8dc3ba5835 \
--hash=sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7
swagger-ui-bundle==1.1.0 \
--hash=sha256:20673c3431c8733d5d1615ecf79d9acf30cff75202acaf21a7d9c7f489714529 \
--hash=sha256:f7526f7bb99923e10594c54247265839bec97e96b0438561ac86faf40d40dd57
tox==4.23.2 \
--hash=sha256:452bc32bb031f2282881a2118923176445bac783ab97c874b8770ab4c3b76c38 \
--hash=sha256:86075e00e555df6e82e74cfc333917f91ecb47ffbc868dcafbd2672e332f4a2c
trove-classifiers==2024.10.21.16 \
--hash=sha256:0fb11f1e995a757807a8ef1c03829fbd4998d817319abcef1f33165750f103be \
--hash=sha256:17cbd055d67d5e9d9de63293a8732943fabc21574e4c7b74edf112b4928cf5f3
typing-extensions==4.12.2 \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
urllib3==2.2.3 \
--hash=sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac \
--hash=sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9
uvicorn==0.32.1 \
--hash=sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e \
--hash=sha256:ee9519c246a72b1c084cea8d3b44ed6026e78a4a309cbedae9c37e4cb9fbb175
uvloop==0.21.0 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' \
--hash=sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f \
--hash=sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c \
--hash=sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3 \
--hash=sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb \
--hash=sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6 \
--hash=sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af \
--hash=sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc \
--hash=sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553 \
--hash=sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d \
--hash=sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc \
--hash=sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281 \
--hash=sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816 \
--hash=sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2
virtualenv==20.28.1 \
--hash=sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb \
--hash=sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329
watchfiles==1.0.0 \
--hash=sha256:1f73c2147a453315d672c1ad907abe6d40324e34a185b51e15624bc793f93cc6 \
--hash=sha256:1ff236d7a3f4b0a42f699a22fc374ba526bc55048a70cbb299661158e1bb5e1f \
--hash=sha256:28fb64b5843d94e2c2483f7b024a1280662a44409bedee8f2f51439767e2d107 \
--hash=sha256:2ac778a460ea22d63c7e6fb0bc0f5b16780ff0b128f7f06e57aaec63bd339285 \
--hash=sha256:37566c844c9ce3b5deb964fe1a23378e575e74b114618d211fbda8f59d7b5dab \
--hash=sha256:487d15927f1b0bd24e7df921913399bb1ab94424c386bea8b267754d698f8f0e \
--hash=sha256:4a3b33c3aefe9067ebd87846806cd5fc0b017ab70d628aaff077ab9abf4d06b3 \
--hash=sha256:533a7cbfe700e09780bb31c06189e39c65f06c7f447326fee707fd02f9a6e945 \
--hash=sha256:53ae447f06f8f29f5ab40140f19abdab822387a7c426a369eb42184b021e97eb \
--hash=sha256:5f75cd42e7e2254117cf37ff0e68c5b3f36c14543756b2da621408349bd9ca7c \
--hash=sha256:8a2127cd68950787ee36753e6d401c8ea368f73beaeb8e54df5516a06d1ecd82 \
--hash=sha256:90004553be36427c3d06ec75b804233f8f816374165d5225b93abd94ba6e7234 \
--hash=sha256:9122b8fdadc5b341315d255ab51d04893f417df4e6c1743b0aac8bf34e96e025 \
--hash=sha256:9272fdbc0e9870dac3b505bce1466d386b4d8d6d2bacf405e603108d50446940 \
--hash=sha256:95de85c254f7fe8cbdf104731f7f87f7f73ae229493bebca3722583160e6b152 \
--hash=sha256:9c01446626574561756067f00b37e6b09c8622b0fc1e9fdbc7cbcea328d4e514 \
--hash=sha256:a2218e78e2c6c07b1634a550095ac2a429026b2d5cbcd49a594f893f2bb8c936 \
--hash=sha256:b46e15c34d4e401e976d6949ad3a74d244600d5c4b88c827a3fdf18691a46359 \
--hash=sha256:b551c465a59596f3d08170bd7e1c532c7260dd90ed8135778038e13c5d48aa81 \
--hash=sha256:bc338ce9f8846543d428260fa0f9a716626963148edc937d71055d01d81e1525 \
--hash=sha256:bedf84835069f51c7b026b3ca04e2e747ea8ed0a77c72006172c72d28c9f69fc \
--hash=sha256:cf517701a4a872417f4e02a136e929537743461f9ec6cdb8184d9a04f4843545 \
--hash=sha256:d562a6114ddafb09c33246c6ace7effa71ca4b6a2324a47f4b09b6445ea78941 \
--hash=sha256:e1ed613ee107269f66c2df631ec0fc8efddacface85314d392a4131abe299f00 \
--hash=sha256:e3750434c83b61abb3163b49c64b04180b85b4dabb29a294513faec57f2ffdb7 \
--hash=sha256:eba98901a2eab909dbd79681190b9049acc650f6111fde1845484a4450761e98
websockets==14.1 \
--hash=sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59 \
--hash=sha256:0d4290d559d68288da9f444089fd82490c8d2744309113fc26e2da6e48b65da6 \
--hash=sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0 \
--hash=sha256:3630b670d5057cd9e08b9c4dab6493670e8e762a24c2c94ef312783870736ab9 \
--hash=sha256:36ebd71db3b89e1f7b1a5deaa341a654852c3518ea7a8ddfdf69cc66acc2db1b \
--hash=sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8 \
--hash=sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4 \
--hash=sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e \
--hash=sha256:5b918d288958dc3fa1c5a0b9aa3256cb2b2b84c54407f4813c45d52267600cd3 \
--hash=sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058 \
--hash=sha256:77569d19a13015e840b81550922056acabc25e3f52782625bc6843cfa034e1da \
--hash=sha256:8149a0f5a72ca36720981418eeffeb5c2729ea55fa179091c81a0910a114a5d2 \
--hash=sha256:836bef7ae338a072e9d1863502026f01b14027250a4545672673057997d5c05a \
--hash=sha256:8621a07991add373c3c5c2cf89e1d277e49dc82ed72c75e3afc74bd0acc446f0 \
--hash=sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d \
--hash=sha256:88cf9163ef674b5be5736a584c999e98daf3aabac6e536e43286eb74c126b9c7 \
--hash=sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f \
--hash=sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a \
--hash=sha256:a3dfff83ca578cada2d19e665e9c8368e1598d4e787422a460ec70e531dbdd58 \
--hash=sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45 \
--hash=sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707 \
--hash=sha256:cf5201a04550136ef870aa60ad3d29d2a59e452a7f96b94193bee6d73b8ad9a9 \
--hash=sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05 \
--hash=sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed
werkzeug==3.1.3 \
--hash=sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e \
--hash=sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746