You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
orquestrador/admin_app/services/system_service.py

263 lines
11 KiB
Python

from admin_app.core import AdminCredentialStrategy, AdminSecurityService
from admin_app.db.write_governance import (
build_admin_write_governance_payload,
build_admin_write_governance_source_payload,
)
from admin_app.core.settings import AdminSettings
from shared.contracts import (
BOT_GOVERNED_SETTINGS,
FunctionalConfigurationPropagation,
MODEL_RUNTIME_PROFILES,
MODEL_RUNTIME_SEPARATION_RULES,
SYSTEM_FUNCTIONAL_CONFIGURATIONS,
get_functional_configuration,
)
class SystemService:
def __init__(
self,
settings: AdminSettings,
security_service: AdminSecurityService | None = None,
):
self.settings = settings
self.security_service = security_service or AdminSecurityService(settings)
def build_root_payload(self) -> dict:
return {
"service": "orquestrador-admin",
"status": "ok",
"message": "Servico administrativo inicializado.",
"environment": self.settings.admin_environment,
}
def build_health_payload(self) -> dict:
return {
"service": "orquestrador-admin",
"status": "ok",
"version": self.settings.admin_version,
}
def build_system_info_payload(self) -> dict:
return {
"service": "orquestrador-admin",
"app_name": self.settings.admin_app_name,
"environment": self.settings.admin_environment,
"version": self.settings.admin_version,
"api_prefix": self.settings.admin_api_prefix,
"debug": self.settings.admin_debug,
}
def build_runtime_configuration_payload(self) -> dict:
return {
"application": {
"app_name": self.settings.admin_app_name,
"environment": self.settings.admin_environment,
"version": self.settings.admin_version,
"api_prefix": self.settings.admin_api_prefix,
"debug": self.settings.admin_debug,
},
"database": {
"host": self.settings.admin_db_host,
"port": self.settings.admin_db_port,
"name": self.settings.admin_db_name,
"cloud_sql_configured": bool(self.settings.admin_db_cloud_sql_connection_name),
},
}
def build_security_configuration_payload(self) -> AdminCredentialStrategy:
return self.security_service.build_credential_strategy()
def build_model_runtime_separation_payload(self) -> dict:
atendimento_configuration = get_functional_configuration("atendimento_runtime_profile")
tool_generation_configuration = get_functional_configuration("tool_generation_runtime_profile")
if atendimento_configuration is None or tool_generation_configuration is None:
raise RuntimeError("Shared functional configuration contracts are not available.")
return {
"runtime_profiles": [
self._serialize_model_runtime_profile(runtime_profile)
for runtime_profile in MODEL_RUNTIME_PROFILES
],
"separation_rules": list(MODEL_RUNTIME_SEPARATION_RULES),
"atendimento_runtime_configuration": self._serialize_functional_configuration(
atendimento_configuration
),
"tool_generation_runtime_configuration": self._serialize_functional_configuration(
tool_generation_configuration
),
"bot_governed_parent_config_keys": sorted(
{setting.parent_config_key for setting in BOT_GOVERNED_SETTINGS}
),
}
def build_functional_configuration_catalog_payload(self) -> dict:
return {
"mode": "shared_contract_bootstrap",
"configurations": [
self._serialize_functional_configuration(configuration)
for configuration in SYSTEM_FUNCTIONAL_CONFIGURATIONS
],
"bot_governed_parent_config_keys": sorted(
{setting.parent_config_key for setting in BOT_GOVERNED_SETTINGS}
),
"next_steps": [
"Persistir estado funcional governado no admin antes da publicacao para o produto.",
"Adicionar versionamento, auditoria e aprovacao humana para configuracoes alteraveis.",
"Conectar o estado desejado do admin ao estado efetivo publicado no product.",
],
}
def get_functional_configuration_payload(self, config_key: str) -> dict | None:
configuration = get_functional_configuration(config_key)
if configuration is None:
return None
linked_bot_settings = [
self._serialize_bot_governed_setting(setting)
for setting in BOT_GOVERNED_SETTINGS
if setting.parent_config_key == configuration.config_key
]
related_runtime_profile = next(
(
self._serialize_model_runtime_profile(runtime_profile)
for runtime_profile in MODEL_RUNTIME_PROFILES
if runtime_profile.config_key == configuration.config_key
),
None,
)
return {
"configuration": self._serialize_functional_configuration(configuration),
"linked_bot_settings": linked_bot_settings,
"related_runtime_profile": related_runtime_profile,
"managed_by_bot_governance": bool(linked_bot_settings),
}
def build_bot_governed_configuration_payload(self) -> dict:
ordered_settings = sorted(
BOT_GOVERNED_SETTINGS,
key=lambda setting: (setting.parent_config_key, setting.area.value, setting.setting_key),
)
return {
"parent_config_keys": sorted(
{setting.parent_config_key for setting in BOT_GOVERNED_SETTINGS}
),
"settings": [
self._serialize_bot_governed_setting(setting)
for setting in ordered_settings
],
}
def build_write_governance_payload(self) -> dict:
payload = build_admin_write_governance_payload()
payload["governed_configuration_keys"] = sorted(
configuration.config_key
for configuration in SYSTEM_FUNCTIONAL_CONFIGURATIONS
if configuration.propagation == FunctionalConfigurationPropagation.VERSIONED_PUBLICATION
)
return payload
def build_configuration_sources_payload(self) -> list[dict]:
return [
{
"key": "application",
"source": "env",
"mutable": False,
"description": "Metadados principais do admin runtime vindos de AdminSettings.",
},
{
"key": "database",
"source": "env",
"mutable": False,
"description": "Conexao administrativa derivada das variaveis de ambiente do servico.",
},
{
"key": "security",
"source": "env",
"mutable": False,
"description": "Politicas de senha, token e bootstrap lidas do runtime administrativo.",
},
{
"key": "panel_session",
"source": "runtime",
"mutable": False,
"description": "Cookies e sessao web do painel derivam da configuracao ativa do admin.",
},
{
"key": "functional_configuration_contracts",
"source": "shared_contract",
"mutable": False,
"description": "Catalogo compartilhado das configuracoes funcionais governadas entre admin e product.",
},
{
"key": "bot_governed_configuration_contracts",
"source": "shared_contract",
"mutable": False,
"description": "Regras compartilhadas dos campos do bot que ficam sob governanca administrativa.",
},
{
"key": "model_runtime_separation",
"source": "shared_contract",
"mutable": False,
"description": "Contratos compartilhados que separam o runtime do atendimento do runtime de geracao de tools.",
},
build_admin_write_governance_source_payload(),
]
@staticmethod
def _serialize_model_runtime_profile(runtime_profile) -> dict:
return {
"runtime_target": runtime_profile.runtime_target,
"config_key": runtime_profile.config_key,
"catalog_runtime_target": runtime_profile.catalog_runtime_target,
"purpose": runtime_profile.purpose,
"consumed_by_service": runtime_profile.consumed_by_service,
"description": runtime_profile.description,
"read_permission": runtime_profile.read_permission,
"write_permission": runtime_profile.write_permission,
"published_independently": runtime_profile.published_independently,
"rollback_independently": runtime_profile.rollback_independently,
"cross_target_propagation_allowed": runtime_profile.cross_target_propagation_allowed,
"affects_customer_response": runtime_profile.affects_customer_response,
"can_generate_code": runtime_profile.can_generate_code,
}
@staticmethod
def _serialize_functional_configuration(configuration) -> dict:
return {
"config_key": configuration.config_key,
"domain": configuration.domain,
"description": configuration.description,
"source": configuration.source,
"read_permission": configuration.read_permission,
"write_permission": configuration.write_permission,
"mutability": configuration.mutability,
"propagation": configuration.propagation,
"affects_product_runtime": configuration.affects_product_runtime,
"direct_product_write_allowed": configuration.direct_product_write_allowed,
"fields": [
{
"name": field.name,
"description": field.description,
"writable": field.writable,
"secret": field.secret,
}
for field in configuration.fields
],
}
@staticmethod
def _serialize_bot_governed_setting(setting) -> dict:
return {
"setting_key": setting.setting_key,
"parent_config_key": setting.parent_config_key,
"field_name": setting.field_name,
"area": setting.area,
"description": setting.description,
"read_permission": setting.read_permission,
"write_permission": setting.write_permission,
"mutability": setting.mutability,
"versioned_publication_required": setting.versioned_publication_required,
"direct_product_write_allowed": setting.direct_product_write_allowed,
}