🧩 feat(shared): definir fronteiras de dados e configuracao da fase 4
Formaliza os contratos compartilhados para leitura operacional, estrategia de relatorios e configuracao funcional governada entre admin e product. Tambem separa explicitamente o runtime do bot de atendimento do runtime de geracao de tools, detalha quais configuracoes do bot entram sob governanca administrativa e documenta as regras de publicacao, rollback e leitura sem acoplar o hot path do atendimento.feat/self-evolving-tools-foundation
parent
bd662f35fa
commit
5ca21b598f
@ -0,0 +1,108 @@
|
||||
# Configuracoes Do Bot Governadas Pelo Admin
|
||||
|
||||
## Objetivo
|
||||
|
||||
Definir exatamente quais configuracoes do bot de atendimento entram sob governanca do `orquestrador-admin`.
|
||||
|
||||
Esta etapa detalha, em nivel de campo, a parte do runtime do bot que pode ser consultada por `colaborador` e alterada por `diretor`.
|
||||
|
||||
## Decisao
|
||||
|
||||
O `admin` governa apenas configuracoes funcionais do bot de atendimento.
|
||||
|
||||
Isso inclui:
|
||||
|
||||
- escolha do modelo homologado usado no atendimento
|
||||
- politicas de resposta do bot
|
||||
- politicas de uso de tools
|
||||
- politicas de fallback e handoff humano
|
||||
- politicas operacionais por canal
|
||||
|
||||
Essa fronteira fica formalizada em `shared/contracts/bot_governed_configuration.py`.
|
||||
|
||||
## Configuracoes governadas
|
||||
|
||||
### 1. Selecao de modelo do bot
|
||||
|
||||
Campos governados:
|
||||
|
||||
- `provider`
|
||||
- `model_name`
|
||||
|
||||
Esses campos definem qual modelo homologado responde ao cliente final.
|
||||
|
||||
### 2. Geracao de resposta
|
||||
|
||||
Campos governados:
|
||||
|
||||
- `temperature`
|
||||
- `max_output_tokens`
|
||||
- `prompt_profile_ref`
|
||||
|
||||
Esses campos controlam o perfil funcional da resposta, sem expor o painel a segredos ou internals de infraestrutura.
|
||||
|
||||
### 3. Uso de tools
|
||||
|
||||
Campos governados:
|
||||
|
||||
- `tool_policy_ref`
|
||||
- `max_tool_calls_per_turn`
|
||||
- `confirmation_policy`
|
||||
|
||||
Esses campos definem como o bot pode usar tools e quando precisa de confirmacao antes de acao critica.
|
||||
|
||||
### 4. Fallback e handoff
|
||||
|
||||
Campos governados:
|
||||
|
||||
- `fallback_mode`
|
||||
- `handoff_enabled`
|
||||
- `handoff_intents`
|
||||
|
||||
Esses campos governam quando o fluxo segue fallback controlado e quando encaminha para atendimento humano.
|
||||
|
||||
### 5. Operacao por canal
|
||||
|
||||
Campos governados:
|
||||
|
||||
- `enabled`
|
||||
- `maintenance_mode`
|
||||
- `default_route`
|
||||
- `operation_window_ref`
|
||||
|
||||
Esses campos permitem controlar disponibilidade e comportamento funcional por canal homologado.
|
||||
|
||||
## O que nao entra como configuracao do bot
|
||||
|
||||
As seguintes superficies ficam fora desta governanca:
|
||||
|
||||
- configuracao de modelo para geracao de tools
|
||||
- credenciais de provedor e segredos
|
||||
- conteudo bruto de prompt sensivel
|
||||
- variaveis de ambiente e infraestrutura
|
||||
- implementacao interna das tools
|
||||
- alteracao direta em tabelas operacionais do `product`
|
||||
|
||||
## Regras obrigatorias
|
||||
|
||||
### 1. Leitura por `colaborador`, alteracao por `diretor`
|
||||
|
||||
- `colaborador` consulta via `view_system`
|
||||
- `diretor` consulta e altera via `manage_settings`
|
||||
|
||||
### 2. Sem escrita direta no runtime do produto
|
||||
|
||||
O painel registra estado desejado e governado.
|
||||
O `product` consome apenas configuracao publicada, versionada e auditavel.
|
||||
|
||||
### 3. Separacao do runtime de geracao
|
||||
|
||||
O runtime usado para gerar tools continua em trilha propria.
|
||||
Ele nao deve ser tratado como configuracao do bot de atendimento.
|
||||
|
||||
## Consequencias positivas
|
||||
|
||||
- deixa a tela de configuracao do bot mais clara e segura
|
||||
- evita que a UI misture atendimento com geracao de tools
|
||||
- preserva a governanca de publicacao entre `admin` e `product`
|
||||
- prepara a proxima etapa de rotas administrativas para configuracao funcional do sistema
|
||||
@ -0,0 +1,197 @@
|
||||
# Escopo De Configuracao Funcional Governada No Admin
|
||||
|
||||
## Objetivo
|
||||
|
||||
Definir quais configuracoes funcionais o `orquestrador-admin` pode consultar e alterar sem transformar o painel em uma superficie de mudanca irrestrita do runtime do `orquestrador-product`.
|
||||
|
||||
Esta etapa fixa a **fronteira funcional de configuracao**.
|
||||
As telas e rotas especificas da fase 4 vao consumir esse contrato depois.
|
||||
|
||||
## Decisao
|
||||
|
||||
O `admin` pode consultar um conjunto governado de configuracoes funcionais do sistema.
|
||||
Dessas configuracoes, apenas o papel `diretor` pode alterar o estado desejado.
|
||||
O papel `colaborador` fica com leitura para acompanhamento operacional do sistema.
|
||||
|
||||
A fronteira compartilhada inicial fica em `shared/contracts/system_functional_configuration.py`.
|
||||
O detalhamento especifico do que o painel governa no bot de atendimento fica em `docs/architecture/admin-bot-governed-configuration-scope.md`.`r`nA separacao entre o runtime de atendimento e o runtime de geracao de tools fica em `docs/architecture/admin-model-runtime-separation.md`.
|
||||
|
||||
## O que entra na fronteira administrativa
|
||||
|
||||
As primeiras configuracoes funcionais aprovadas para o painel sao:
|
||||
|
||||
1. `allowed_model_catalog`
|
||||
2. `atendimento_runtime_profile`
|
||||
3. `tool_generation_runtime_profile`
|
||||
4. `bot_behavior_policy`
|
||||
5. `channel_operation_policy`
|
||||
6. `published_runtime_state`
|
||||
|
||||
### 1. `allowed_model_catalog`
|
||||
|
||||
Superficie somente leitura usada para o painel saber quais modelos estao homologados pela plataforma.
|
||||
|
||||
Serve para:
|
||||
|
||||
- montar listas de selecao na tela administrativa
|
||||
- impedir configuracao de modelo fora do catalogo permitido
|
||||
- diferenciar modelos liberados para atendimento e para geracao de tools
|
||||
|
||||
Nao serve para:
|
||||
|
||||
- cadastrar credenciais de provedor
|
||||
- alterar limites de infraestrutura
|
||||
- homologar modelo novo diretamente pela UI
|
||||
|
||||
### 2. `atendimento_runtime_profile`
|
||||
|
||||
Configuracao funcional governada do modelo do bot que atende o cliente final.
|
||||
|
||||
Inclui:
|
||||
|
||||
- provedor selecionado
|
||||
- modelo selecionado
|
||||
- temperatura
|
||||
- limite de saida
|
||||
- referencia de prompt publicada
|
||||
- referencia de politica de tools
|
||||
|
||||
Regra:
|
||||
|
||||
- `colaborador` consulta
|
||||
- `diretor` altera
|
||||
|
||||
### 3. `tool_generation_runtime_profile`
|
||||
|
||||
Configuracao funcional governada do modelo usado para gerar e validar novas tools.
|
||||
|
||||
Inclui:
|
||||
|
||||
- provedor selecionado
|
||||
- modelo selecionado
|
||||
- perfil de raciocinio
|
||||
- limite de saida
|
||||
- referencia de politica de validacao
|
||||
|
||||
Regra obrigatoria:
|
||||
|
||||
- esse perfil e separado do perfil de atendimento
|
||||
- trocar o modelo de geracao nao troca automaticamente o modelo do bot
|
||||
|
||||
### 4. `bot_behavior_policy`
|
||||
|
||||
Politicas funcionais do fluxo do bot.
|
||||
|
||||
Inclui:
|
||||
|
||||
- modo de fallback
|
||||
- handoff para humano
|
||||
- intencoes que forcam escalonamento
|
||||
- limite de chamadas de tool por turno
|
||||
- politica de confirmacao para acao critica
|
||||
|
||||
Essa configuracao existe para o painel governar o comportamento funcional do atendimento, e nao o codigo interno do orquestrador.
|
||||
|
||||
### 5. `channel_operation_policy`
|
||||
|
||||
Politicas funcionais por canal.
|
||||
|
||||
Inclui:
|
||||
|
||||
- canal habilitado ou desabilitado
|
||||
- modo de manutencao
|
||||
- rota funcional padrao
|
||||
- referencia da janela operacional
|
||||
|
||||
Essa superficie permite governar disponibilidade funcional sem dar acesso a infraestrutura bruta.
|
||||
|
||||
### 6. `published_runtime_state`
|
||||
|
||||
Superficie somente leitura do estado efetivo publicado no `product`.
|
||||
|
||||
Inclui:
|
||||
|
||||
- escopo configurado
|
||||
- versao ativa
|
||||
- quem publicou
|
||||
- quando publicou
|
||||
- quando o produto aplicou a mudanca
|
||||
|
||||
Serve para:
|
||||
|
||||
- auditoria
|
||||
- transparencia na dashboard
|
||||
- comparacao entre estado desejado no admin e estado efetivo no produto
|
||||
|
||||
## O que fica fora da fronteira administrativa
|
||||
|
||||
As seguintes superficies nao entram como configuracao funcional alteravel no painel:
|
||||
|
||||
- segredos e credenciais de provedor
|
||||
- API keys
|
||||
- strings de conexao com banco
|
||||
- variaveis de ambiente de deploy
|
||||
- configuracao de autoscaling e infraestrutura
|
||||
- schema de banco operacional
|
||||
- payloads tecnicos internos de execucao
|
||||
- alteracao direta em tabelas operacionais do `product`
|
||||
|
||||
## Regras obrigatorias
|
||||
|
||||
### 1. Leitura ampla, escrita governada
|
||||
|
||||
A leitura dessas configuracoes nasce sob `view_system`.
|
||||
|
||||
Consequencia pratica:
|
||||
|
||||
- `colaborador` pode consultar a configuracao funcional vigente
|
||||
- `diretor` tambem consulta
|
||||
- apenas `diretor` altera configuracoes governadas com `manage_settings`
|
||||
|
||||
### 2. Sem escrita direta no produto
|
||||
|
||||
O painel administrativo nao escreve diretamente no runtime do `product` durante uma request de UI.
|
||||
|
||||
A fronteira correta eh:
|
||||
|
||||
- o `admin` registra estado funcional desejado
|
||||
- o estado e versionado, auditado e aprovado
|
||||
- o `product` consome apenas configuracao publicada
|
||||
|
||||
### 3. Separacao entre atendimento e geracao de tools
|
||||
|
||||
Os dois runtimes precisam continuar independentes.
|
||||
|
||||
Portanto:
|
||||
|
||||
- o modelo do atendimento vive em `atendimento_runtime_profile`
|
||||
- o modelo de geracao vive em `tool_generation_runtime_profile`
|
||||
- cada perfil pode ter rollout, auditoria e fallback proprios
|
||||
|
||||
### 4. Estado efetivo precisa ser observavel
|
||||
|
||||
Toda configuracao governada precisa gerar uma superficie de consulta sobre o estado efetivo publicado no `product`.
|
||||
|
||||
Consequencia pratica:
|
||||
|
||||
- a dashboard administrativa consegue mostrar o que esta ativo de verdade
|
||||
- o sistema evita divergencia silenciosa entre desejo do admin e runtime do produto
|
||||
|
||||
## Consequencias positivas
|
||||
|
||||
- permite escolher modelo do bot pelo painel sem expor segredos de infraestrutura
|
||||
- prepara a tela de configuracoes do sistema para `diretor`
|
||||
- mantem `colaborador` com visibilidade do fluxo do bot e do estado vigente
|
||||
- reforca a separacao entre governanca administrativa e hot path do atendimento
|
||||
- prepara versionamento e auditoria das configuracoes antes da integracao completa entre `admin` e `product`
|
||||
|
||||
## Proximos passos naturais
|
||||
|
||||
- criar rotas administrativas para configuracao funcional do sistema
|
||||
- criar tela administrativa de configuracoes do sistema
|
||||
- criar superficie visual para estado publicado e versoes ativas
|
||||
- definir publicacao e consumo dessas configuracoes entre `admin` e `product`
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
# Separacao Entre Modelo Do Atendimento E Modelo De Geracao De Tools
|
||||
|
||||
## Objetivo
|
||||
|
||||
Definir a fronteira entre o runtime de modelo usado no atendimento ao cliente e o runtime de modelo usado para gerar e validar novas tools.
|
||||
|
||||
Esta etapa consolida uma regra importante da arquitetura: os dois perfis de modelo nao podem compartilhar configuracao nem ciclo de publicacao.
|
||||
|
||||
## Decisao
|
||||
|
||||
O sistema passa a tratar esses runtimes como perfis independentes.
|
||||
|
||||
Perfis:
|
||||
|
||||
1. `atendimento_runtime_profile`
|
||||
2. `tool_generation_runtime_profile`
|
||||
|
||||
A separacao formal fica em `shared/contracts/model_runtime_separation.py`.
|
||||
|
||||
## Regras obrigatorias
|
||||
|
||||
### 1. Configuracoes distintas
|
||||
|
||||
Cada runtime possui sua propria `config_key`.
|
||||
|
||||
Portanto:
|
||||
|
||||
- o atendimento usa `atendimento_runtime_profile`
|
||||
- a geracao de tools usa `tool_generation_runtime_profile`
|
||||
- uma mudanca de configuracao nunca reutiliza a mesma chave para os dois contextos
|
||||
|
||||
### 2. Catalogos com alvo separado
|
||||
|
||||
Os modelos homologados precisam carregar o alvo funcional correto.
|
||||
|
||||
Portanto:
|
||||
|
||||
- modelos homologados para atendimento entram sob `runtime_target = atendimento`
|
||||
- modelos homologados para geracao entram sob `runtime_target = tool_generation`
|
||||
- um modelo pode existir nos dois catalogos, mas a selecao continua independente
|
||||
|
||||
### 3. Publicacao independente
|
||||
|
||||
Os dois runtimes possuem publicacao independente.
|
||||
|
||||
Consequencia pratica:
|
||||
|
||||
- publicar uma mudanca no atendimento nao publica a geracao de tools
|
||||
- publicar uma mudanca na geracao de tools nao muda o bot que responde ao cliente
|
||||
- cada perfil pode ter sua propria auditoria e versao ativa
|
||||
|
||||
### 4. Rollback independente
|
||||
|
||||
Cada runtime precisa poder voltar ao estado anterior sem afetar o outro.
|
||||
|
||||
Consequencia pratica:
|
||||
|
||||
- rollback do atendimento nao mexe no runtime de geracao
|
||||
- rollback da geracao nao mexe no atendimento em producao
|
||||
|
||||
### 5. Sem propagacao implicita
|
||||
|
||||
Nao e permitido que uma alteracao em um runtime seja espelhada automaticamente no outro.
|
||||
|
||||
Isso impede:
|
||||
|
||||
- trocar o modelo do bot e, por efeito colateral, trocar o modelo de geracao
|
||||
- usar defaults compartilhados para empurrar mudancas silenciosas nos dois fluxos
|
||||
- misturar SLO, custo e risco do atendimento com o pipeline de tools
|
||||
|
||||
## Responsabilidade por runtime
|
||||
|
||||
### Atendimento
|
||||
|
||||
- alvo funcional: responder ao cliente final
|
||||
- servico consumidor: `product`
|
||||
- impacto direto: experiencia do atendimento e fluxo conversacional
|
||||
|
||||
### Geracao de tools
|
||||
|
||||
- alvo funcional: gerar e validar novas tools
|
||||
- servico consumidor: `admin`
|
||||
- impacto direto: pipeline de governanca, geracao e validacao
|
||||
|
||||
## Consequencias positivas
|
||||
|
||||
- protege o atendimento de experimentos de geracao de codigo
|
||||
- permite escolher modelos diferentes para custo, latencia e qualidade em cada fluxo
|
||||
- simplifica auditoria e rollback de configuracao
|
||||
- prepara as futuras telas e rotas de configuracao do sistema sem ambiguidade
|
||||
@ -0,0 +1,299 @@
|
||||
# Escopo De Dados Operacionais Do Product Visiveis No Admin
|
||||
|
||||
## Objetivo
|
||||
|
||||
Definir, de forma explicita, quais dados operacionais do `orquestrador-product` podem ser consultados pelo `orquestrador-admin` na fase inicial de relatorios e configuracao.
|
||||
|
||||
Esta definicao cobre o **que** o admin pode ler.
|
||||
A estrategia de leitura desses dados sem acoplar o hot path do atendimento fica detalhada em `docs/architecture/admin-report-reading-strategy.md`.
|
||||
A materializacao concreta desses relatorios fica detalhada em `docs/architecture/admin-report-materialization-strategy.md`.
|
||||
|
||||
## Principios obrigatorios
|
||||
|
||||
1. O `product` continua sendo a fonte operacional primaria.
|
||||
2. O `admin` nasce com acesso de leitura orientado a relatorios, nunca como escritor direto dessas tabelas.
|
||||
3. O hot path do atendimento nao deve depender de consulta online ao `admin`.
|
||||
4. Dados de identidade do cliente final, texto livre e segredos operacionais nao entram automaticamente na fronteira administrativa.
|
||||
5. Sempre que um indicador puder ser atendido por agregado, o agregado deve ser preferido a leitura detalhada.
|
||||
|
||||
## Datasets permitidos nesta fase
|
||||
|
||||
O contrato compartilhado correspondente fica em `shared/contracts/product_operational_data.py`.
|
||||
|
||||
### 1. Estoque comercial
|
||||
|
||||
Fonte atual:
|
||||
|
||||
- `vehicles`
|
||||
|
||||
Uso administrativo esperado:
|
||||
|
||||
- disponibilidade comercial
|
||||
- distribuicao por categoria
|
||||
- faixa de preco
|
||||
- entrada de novos itens no estoque
|
||||
|
||||
Campos permitidos:
|
||||
|
||||
- `id`
|
||||
- `modelo`
|
||||
- `categoria`
|
||||
- `preco`
|
||||
- `created_at`
|
||||
|
||||
### 2. Pedidos de venda
|
||||
|
||||
Fonte atual:
|
||||
|
||||
- `orders`
|
||||
|
||||
Uso administrativo esperado:
|
||||
|
||||
- volume de pedidos
|
||||
- pedidos ativos e cancelados
|
||||
- ticket medio
|
||||
- cancelamentos por periodo
|
||||
|
||||
Campos permitidos:
|
||||
|
||||
- `numero_pedido`
|
||||
- `vehicle_id`
|
||||
- `modelo_veiculo`
|
||||
- `valor_veiculo`
|
||||
- `status`
|
||||
- `motivo_cancelamento`
|
||||
- `data_cancelamento`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Campos bloqueados:
|
||||
|
||||
- `user_id`
|
||||
- `cpf`
|
||||
|
||||
### 3. Agenda de revisoes
|
||||
|
||||
Fonte atual:
|
||||
|
||||
- `review_schedules`
|
||||
|
||||
Uso administrativo esperado:
|
||||
|
||||
- ocupacao de slots
|
||||
- revisoes agendadas por periodo
|
||||
- taxa de cancelamento
|
||||
- fila operacional da oficina
|
||||
|
||||
Campos permitidos:
|
||||
|
||||
- `protocolo`
|
||||
- `placa`
|
||||
- `data_hora`
|
||||
- `status`
|
||||
- `created_at`
|
||||
|
||||
Campos bloqueados:
|
||||
|
||||
- `user_id`
|
||||
|
||||
### 4. Frota de locacao
|
||||
|
||||
Fonte atual:
|
||||
|
||||
- `rental_vehicles`
|
||||
|
||||
Uso administrativo esperado:
|
||||
|
||||
- disponibilidade da frota
|
||||
- status operacional por categoria
|
||||
- tarifa diaria vigente
|
||||
|
||||
Campos permitidos:
|
||||
|
||||
- `id`
|
||||
- `placa`
|
||||
- `modelo`
|
||||
- `categoria`
|
||||
- `ano`
|
||||
- `valor_diaria`
|
||||
- `status`
|
||||
- `created_at`
|
||||
|
||||
### 5. Contratos de locacao
|
||||
|
||||
Fonte atual:
|
||||
|
||||
- `rental_contracts`
|
||||
|
||||
Uso administrativo esperado:
|
||||
|
||||
- contratos ativos e encerrados
|
||||
- devolucoes em atraso
|
||||
- receita prevista versus receita final
|
||||
- ocupacao da frota no tempo
|
||||
|
||||
Campos permitidos:
|
||||
|
||||
- `contrato_numero`
|
||||
- `rental_vehicle_id`
|
||||
- `placa`
|
||||
- `modelo_veiculo`
|
||||
- `categoria`
|
||||
- `data_inicio`
|
||||
- `data_fim_prevista`
|
||||
- `data_devolucao`
|
||||
- `valor_diaria`
|
||||
- `valor_previsto`
|
||||
- `valor_final`
|
||||
- `status`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Campos bloqueados:
|
||||
|
||||
- `user_id`
|
||||
- `cpf`
|
||||
- `observacoes`
|
||||
|
||||
### 6. Pagamentos de locacao
|
||||
|
||||
Fonte atual:
|
||||
|
||||
- `rental_payments`
|
||||
|
||||
Uso administrativo esperado:
|
||||
|
||||
- arrecadacao por periodo
|
||||
- pagamentos conciliados por contrato
|
||||
- inadimplencia operacional
|
||||
|
||||
Campos permitidos:
|
||||
|
||||
- `protocolo`
|
||||
- `contrato_numero`
|
||||
- `placa`
|
||||
- `valor`
|
||||
- `data_pagamento`
|
||||
- `created_at`
|
||||
|
||||
Campos bloqueados:
|
||||
|
||||
- `user_id`
|
||||
- `rental_contract_id`
|
||||
- `favorecido`
|
||||
- `identificador_comprovante`
|
||||
- `observacoes`
|
||||
|
||||
### 7. Telemetria conversacional
|
||||
|
||||
Fonte atual:
|
||||
|
||||
- `conversation_turns`
|
||||
|
||||
Uso administrativo esperado:
|
||||
|
||||
- volume de atendimento
|
||||
- latencia por turno
|
||||
- distribuicao por dominio
|
||||
- uso de tools
|
||||
- falhas operacionais por status
|
||||
|
||||
Campos permitidos:
|
||||
|
||||
- `request_id`
|
||||
- `conversation_id`
|
||||
- `channel`
|
||||
- `turn_status`
|
||||
- `intent`
|
||||
- `domain`
|
||||
- `action`
|
||||
- `tool_name`
|
||||
- `elapsed_ms`
|
||||
- `started_at`
|
||||
- `completed_at`
|
||||
|
||||
Campos bloqueados:
|
||||
|
||||
- `user_id`
|
||||
- `external_id`
|
||||
- `username`
|
||||
- `user_message`
|
||||
- `assistant_response`
|
||||
- `tool_arguments`
|
||||
- `error_detail`
|
||||
|
||||
### 8. Entregas de integracao
|
||||
|
||||
Fonte atual:
|
||||
|
||||
- `integration_deliveries`
|
||||
|
||||
Uso administrativo esperado:
|
||||
|
||||
- taxa de sucesso por provedor
|
||||
- volume de eventos entregues
|
||||
- entregas pendentes ou com falha
|
||||
- tentativas de reenvio
|
||||
|
||||
Campos permitidos:
|
||||
|
||||
- `route_id`
|
||||
- `event_type`
|
||||
- `provider`
|
||||
- `status`
|
||||
- `attempts`
|
||||
- `dispatched_at`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Campos bloqueados:
|
||||
|
||||
- `payload_json`
|
||||
- `recipient_email`
|
||||
- `recipient_name`
|
||||
- `rendered_subject`
|
||||
- `rendered_body`
|
||||
- `provider_message_id`
|
||||
- `last_error`
|
||||
|
||||
## Fontes fora do escopo administrativo nesta fase
|
||||
|
||||
O admin **nao** deve consultar diretamente, nesta fase:
|
||||
|
||||
- `customers`
|
||||
- `users`
|
||||
- stores de estado conversacional de hot path
|
||||
- payloads brutos de tools e mensagens do usuario
|
||||
- comprovantes e identificadores sensiveis de pagamento
|
||||
- configuracoes internas de provedor e credenciais
|
||||
|
||||
## Regra de autorizacao
|
||||
|
||||
A leitura desses dados nasce amarrada a `view_reports`.
|
||||
|
||||
Consequencia pratica:
|
||||
|
||||
- `colaborador` pode consultar os dados operacionais liberados para relatorio
|
||||
- `diretor` herda essa leitura e acumula as etapas de aprovacao e configuracao
|
||||
- permissao adicional sera exigida apenas quando a consulta implicar governanca, aprovacao ou configuracao
|
||||
|
||||
## Decisao tomada nesta etapa
|
||||
|
||||
O `admin` pode consultar apenas datasets operacionais explicitamente declarados em contrato compartilhado e sempre em modo somente leitura.
|
||||
|
||||
A fronteira inicial favorece relatorios de:
|
||||
|
||||
- vendas
|
||||
- arrecadacao
|
||||
- operacao
|
||||
- telemetria de atendimento
|
||||
- entregas de integracao
|
||||
|
||||
## Decisao de materializacao relacionada
|
||||
|
||||
Para esses datasets, a fase inicial escolhe:
|
||||
|
||||
- `etl_incremental` como estrategia de sincronizacao
|
||||
- `snapshot_table` no lado administrativo como persistencia de leitura
|
||||
- `dedicated_view` sobre os snapshots como superficie de consulta para APIs e UI
|
||||
- nenhuma replica operacional do banco do produto no dashboard administrativo
|
||||
@ -0,0 +1,128 @@
|
||||
# Estrategia De Materializacao Dos Relatorios Administrativos
|
||||
|
||||
## Objetivo
|
||||
|
||||
Escolher como os relatorios administrativos vao materializar o read model definido para a fase 4.
|
||||
|
||||
A decisao precisava fechar quatro alternativas candidatas:
|
||||
|
||||
- replica
|
||||
- ETL
|
||||
- snapshots
|
||||
- views dedicadas
|
||||
|
||||
## Decisao
|
||||
|
||||
A fase inicial de relatorios do `orquestrador-admin` vai usar a seguinte composicao:
|
||||
|
||||
1. `etl_incremental` como mecanismo de sincronizacao
|
||||
2. `snapshot_table` no lado administrativo como persistencia de leitura
|
||||
3. `dedicated_view` sobre os snapshots como superficie de consulta para APIs e UI
|
||||
4. nenhuma replica operacional do banco do `product` para abrir dashboards administrativos
|
||||
|
||||
Em resumo:
|
||||
|
||||
- **nao** usar replica como mecanismo primario da fase inicial
|
||||
- **sim** usar ETL incremental
|
||||
- **sim** persistir snapshots sanitizados
|
||||
- **sim** expor views dedicadas sobre esses snapshots
|
||||
|
||||
## Por que nao comecar por replica
|
||||
|
||||
Replica isolaria menos do que parece.
|
||||
Ela ainda manteria o admin muito proximo do schema operacional live, incentivando query ad hoc, joins pesados e acoplamento ao desenho interno do `product`.
|
||||
|
||||
Tambem traria custo operacional cedo demais:
|
||||
|
||||
- infraestrutura adicional
|
||||
- observabilidade de replicacao
|
||||
- risco de leitura errada por atraso ou schema drift
|
||||
- falsa sensacao de que qualquer tabela do produto pode virar dashboard
|
||||
|
||||
Para a fase inicial, replica aumenta a superficie tecnica sem resolver a necessidade principal, que eh governar exatamente **o que** sai do produto e **como** isso chega ao admin.
|
||||
|
||||
## Por que ETL incremental
|
||||
|
||||
ETL incremental encaixa melhor no que ja decidimos para o sistema:
|
||||
|
||||
- preserva o hot path do atendimento
|
||||
- permite sanitizacao e minimizacao antes do dado chegar ao admin
|
||||
- suporta watermark, cursor e reprocessamento controlado
|
||||
- facilita auditoria do ciclo de consolidacao
|
||||
- prepara evolucao futura para jobs, workers ou pipelines por evento
|
||||
|
||||
O ETL aqui nao precisa nascer grande.
|
||||
Ele pode comecar como job incremental simples e evoluir sem quebrar o contrato do painel.
|
||||
|
||||
## Por que snapshots
|
||||
|
||||
Snapshots sao a melhor base inicial de persistencia para relatorios administrativos porque:
|
||||
|
||||
- congelam um recorte coerente do dataset consolidado
|
||||
- permitem metadados como `generated_at`, `source_watermark` e `dataset_version`
|
||||
- reduzem risco de consultas inconsistentes durante sincronizacao
|
||||
- simplificam retry, backfill e comparacao entre execucoes
|
||||
|
||||
Na pratica, os snapshots pertencem ao contexto administrativo, nao ao banco operacional do produto.
|
||||
|
||||
## Por que views dedicadas
|
||||
|
||||
Views dedicadas ficam por cima dos snapshots para desacoplar a UI e as APIs do formato bruto de consolidacao.
|
||||
|
||||
Elas permitem:
|
||||
|
||||
- esconder colunas tecnicas de ETL
|
||||
- estabilizar o contrato consumido pelos relatorios
|
||||
- organizar uma view por caso de uso de negocio
|
||||
- evoluir agregacoes e joins internos sem quebrar a tela
|
||||
|
||||
Regra importante:
|
||||
|
||||
- essas views sao dedicadas ao contexto administrativo
|
||||
- elas nao apontam para tabelas live do produto
|
||||
- elas leem apenas snapshots ja sanitizados
|
||||
|
||||
## Fluxo alvo
|
||||
|
||||
```text
|
||||
product operational tables
|
||||
|
|
||||
v
|
||||
etl_incremental boundary
|
||||
|
|
||||
v
|
||||
admin snapshot tables
|
||||
|
|
||||
v
|
||||
admin dedicated views
|
||||
|
|
||||
v
|
||||
admin report routes and dashboard
|
||||
```
|
||||
|
||||
## Regras obrigatorias
|
||||
|
||||
1. O painel nunca consulta replica ou tabela live do produto durante request web.
|
||||
2. O ETL incremental so exporta datasets e campos aprovados em contrato compartilhado.
|
||||
3. Cada snapshot precisa carregar watermark e timestamp de geracao.
|
||||
4. Cada view dedicada existe para um caso de uso de relatorio, nunca como espelho generico do schema operacional.
|
||||
5. Escrita administrativa em tabela operacional do produto continua proibida.
|
||||
|
||||
## Consequencias praticas para a fase 4
|
||||
|
||||
Com essa decisao, os proximos itens da fase ficam orientados assim:
|
||||
|
||||
- rotas administrativas de relatorio devem ler views dedicadas do admin
|
||||
- relatorios de vendas, arrecadacao e operacao devem nascer sobre snapshots sanitizados
|
||||
- a UI deve exibir frescor e estado da ultima consolidacao
|
||||
- qualquer refresh manual conversa com a camada de sincronizacao, nao com o banco operacional live
|
||||
|
||||
## Evolucao futura permitida
|
||||
|
||||
Se no futuro houver escala suficiente para replica, ela pode entrar como **fonte de extração** do ETL, e nao como backend direto do dashboard.
|
||||
|
||||
Ou seja:
|
||||
|
||||
- replica pode aparecer depois como detalhe de implementacao
|
||||
- o contrato do painel continua o mesmo
|
||||
- a fronteira principal segue sendo ETL -> snapshots -> views dedicadas
|
||||
@ -0,0 +1,154 @@
|
||||
# Estrategia De Leitura De Relatorios Sem Acoplar O Hot Path
|
||||
|
||||
## Objetivo
|
||||
|
||||
Definir como o `orquestrador-admin` deve ler dados operacionais para relatorios sem transformar o `orquestrador-product` em backend sincrono de dashboard.
|
||||
|
||||
Esta etapa fixa a **topologia de leitura**.
|
||||
A materializacao concreta dessa topologia foi definida em `docs/architecture/admin-report-materialization-strategy.md`.
|
||||
|
||||
## Decisao
|
||||
|
||||
Os relatorios administrativos devem ser servidos a partir de um **read model administrativo assincrono**.
|
||||
|
||||
Em outras palavras:
|
||||
|
||||
1. O `product` continua escrevendo o estado operacional primario.
|
||||
2. Uma camada de sincronizacao fora do hot path materializa dados de leitura para relatorio.
|
||||
3. O `admin` consulta apenas esse read model, nunca as tabelas operacionais live do `product` em uma request web do painel.
|
||||
|
||||
## Topologia alvo
|
||||
|
||||
```text
|
||||
product operational writes
|
||||
|
|
||||
v
|
||||
sync/export boundary outside hot path
|
||||
|
|
||||
v
|
||||
admin reporting read model
|
||||
|
|
||||
v
|
||||
admin report APIs and dashboard
|
||||
```
|
||||
|
||||
## Regras obrigatorias
|
||||
|
||||
### 1. Sem query direta do painel no banco operacional do produto
|
||||
|
||||
Nao e permitido que uma rota web do painel administrativo execute consultas pesadas ou agregacoes diretamente nas tabelas operacionais do `product`.
|
||||
|
||||
Isso inclui:
|
||||
|
||||
- scans amplos em `orders`, `rental_contracts`, `rental_payments`, `conversation_turns`
|
||||
- joins ad hoc para dashboard em tempo de request
|
||||
- leituras que disputem lock, cache ou I/O com o atendimento
|
||||
|
||||
### 2. Leitura eventual, nao transacional
|
||||
|
||||
O painel administrativo deve operar com **consistencia eventual**.
|
||||
|
||||
Consequencia pratica:
|
||||
|
||||
- relatorios mostram o dado consolidado mais recente disponivel
|
||||
- a UI deve exibir metadados de frescor, como `updated_at`, `generated_at` ou `source_watermark`
|
||||
- o sistema nao promete refletir cada evento operacional no mesmo instante em que ele acontece
|
||||
|
||||
### 3. Materializacao fora do hot path
|
||||
|
||||
Toda consolidacao, enriquecimento, agregacao ou recorte temporal deve acontecer em processo assincrono.
|
||||
|
||||
Exemplos validos de processo assincrono:
|
||||
|
||||
- job agendado
|
||||
- worker orientado a eventos
|
||||
- pipeline incremental por cursor
|
||||
- rotina batch com watermark
|
||||
|
||||
### 4. Read model proprio do admin
|
||||
|
||||
O `admin` deve ter sua propria superficie de leitura para relatorios.
|
||||
|
||||
Essa superficie pode morar:
|
||||
|
||||
- no banco administrativo
|
||||
- em um schema analitico separado
|
||||
- em tabelas materializadas especificas para relatorio
|
||||
|
||||
O importante nesta etapa nao e o lugar fisico, e sim a regra:
|
||||
|
||||
- a query do painel le um read model pronto
|
||||
- a transformacao do dado acontece antes da request do usuario interno
|
||||
|
||||
### 5. Escrita administrativa continua proibida
|
||||
|
||||
A estrategia de leitura nao muda a fronteira de escrita.
|
||||
|
||||
Portanto:
|
||||
|
||||
- o `admin` nao escreve diretamente nas tabelas operacionais do `product`
|
||||
- qualquer acao de governanca que altere operacao deve seguir fluxo proprio, versionado e auditavel
|
||||
|
||||
## Responsabilidades por servico
|
||||
|
||||
### `orquestrador-product`
|
||||
|
||||
Responsavel por:
|
||||
|
||||
- persistir o estado operacional primario
|
||||
- manter ids tecnicos, timestamps e chaves publicas necessarias para reconciliacao
|
||||
- expor uma fronteira segura para exportacao ou sincronizacao
|
||||
- continuar respondendo ao atendimento sem depender do `admin`
|
||||
|
||||
### `orquestrador-admin`
|
||||
|
||||
Responsavel por:
|
||||
|
||||
- armazenar ou consultar o read model de relatorio
|
||||
- servir rotas administrativas de relatorio
|
||||
- informar frescor e origem do dado para a UI
|
||||
- aplicar filtros e agregacoes sobre a superficie de leitura consolidada
|
||||
|
||||
## O que a UI deve assumir
|
||||
|
||||
As telas administrativas de relatorio devem nascer com a expectativa de dado consolidado e nao de espelho instantaneo do operacional.
|
||||
|
||||
Consequencia pratica:
|
||||
|
||||
- cada relatorio deve carregar carimbo de atualizacao
|
||||
- um refresh manual dispara no maximo uma rotina de sincronizacao, nunca uma query pesada live no produto
|
||||
- empty states e avisos de defasagem fazem parte do contrato visual
|
||||
|
||||
## Padrao de frescor inicial
|
||||
|
||||
Enquanto a implementacao completa nao chega, os datasets operacionais ficam classificados em metas de frescor no contrato compartilhado:
|
||||
|
||||
- `near_real_time` para vendas, revisoes e locacao
|
||||
- `intra_hour` para estoque, telemetria e entregas de integracao
|
||||
|
||||
Essas metas servem para orientar UX, monitoracao e futuras implementacoes da sincronizacao.
|
||||
Elas nao significam leitura live do banco operacional.
|
||||
|
||||
## O que fica explicitamente proibido
|
||||
|
||||
- dashboard administrativo consultando `product` por HTTP sincrono a cada abertura de pagina
|
||||
- admin executando agregacao pesada em banco primario de atendimento durante request web
|
||||
- relatorios dependendo de lock em tabela operacional para responder ao usuario interno
|
||||
- uso de payload bruto e PII fora do contrato compartilhado de dados operacionais
|
||||
|
||||
## Consequencias positivas
|
||||
|
||||
- protege latencia do atendimento
|
||||
- reduz risco de regressao operacional por carga analitica
|
||||
- permite evoluir relatorios com independencia do runtime conversacional
|
||||
- facilita observabilidade de frescor e falha da sincronizacao
|
||||
- prepara o terreno para ETL incremental, snapshots sanitizados e views dedicadas sem quebrar o painel
|
||||
|
||||
## Decisao complementar ja tomada
|
||||
|
||||
A topologia acima agora foi materializada assim:
|
||||
|
||||
- `etl_incremental` como fronteira de sincronizacao
|
||||
- `snapshot_table` no admin para persistencia de leitura
|
||||
- `dedicated_view` sobre snapshots para servir APIs e dashboard
|
||||
- sem replica operacional do banco do produto nesta fase
|
||||
@ -0,0 +1,151 @@
|
||||
"""Define quais configuracoes do bot ficam sob governanca administrativa."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from shared.contracts.access_control import AdminPermission
|
||||
|
||||
|
||||
class BotGovernanceArea(str, Enum):
|
||||
MODEL_SELECTION = "model_selection"
|
||||
RESPONSE_GENERATION = "response_generation"
|
||||
TOOL_USAGE = "tool_usage"
|
||||
FALLBACK_AND_HANDOFF = "fallback_and_handoff"
|
||||
CHANNEL_OPERATION = "channel_operation"
|
||||
|
||||
|
||||
class BotGovernanceMutability(str, Enum):
|
||||
DIRECTOR_GOVERNED = "director_governed"
|
||||
|
||||
|
||||
class BotGovernedSettingContract(BaseModel):
|
||||
setting_key: str
|
||||
parent_config_key: str
|
||||
field_name: str
|
||||
area: BotGovernanceArea
|
||||
description: str
|
||||
read_permission: AdminPermission = AdminPermission.VIEW_SYSTEM
|
||||
write_permission: AdminPermission = AdminPermission.MANAGE_SETTINGS
|
||||
mutability: BotGovernanceMutability = BotGovernanceMutability.DIRECTOR_GOVERNED
|
||||
versioned_publication_required: bool = True
|
||||
direct_product_write_allowed: bool = False
|
||||
|
||||
|
||||
BOT_GOVERNED_SETTINGS: tuple[BotGovernedSettingContract, ...] = (
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_model_provider",
|
||||
parent_config_key="atendimento_runtime_profile",
|
||||
field_name="provider",
|
||||
area=BotGovernanceArea.MODEL_SELECTION,
|
||||
description="Provedor do modelo usado pelo bot de atendimento.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_model_name",
|
||||
parent_config_key="atendimento_runtime_profile",
|
||||
field_name="model_name",
|
||||
area=BotGovernanceArea.MODEL_SELECTION,
|
||||
description="Modelo selecionado para responder ao cliente final.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_temperature",
|
||||
parent_config_key="atendimento_runtime_profile",
|
||||
field_name="temperature",
|
||||
area=BotGovernanceArea.RESPONSE_GENERATION,
|
||||
description="Temperatura aplicada nas respostas do bot.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_max_output_tokens",
|
||||
parent_config_key="atendimento_runtime_profile",
|
||||
field_name="max_output_tokens",
|
||||
area=BotGovernanceArea.RESPONSE_GENERATION,
|
||||
description="Limite de saida usado no runtime de atendimento.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_prompt_profile_ref",
|
||||
parent_config_key="atendimento_runtime_profile",
|
||||
field_name="prompt_profile_ref",
|
||||
area=BotGovernanceArea.RESPONSE_GENERATION,
|
||||
description="Referencia do perfil de prompt publicado para o bot.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_tool_policy_ref",
|
||||
parent_config_key="atendimento_runtime_profile",
|
||||
field_name="tool_policy_ref",
|
||||
area=BotGovernanceArea.TOOL_USAGE,
|
||||
description="Referencia da politica de uso de tools pelo bot.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_fallback_mode",
|
||||
parent_config_key="bot_behavior_policy",
|
||||
field_name="fallback_mode",
|
||||
area=BotGovernanceArea.FALLBACK_AND_HANDOFF,
|
||||
description="Modo funcional de fallback quando o bot nao conclui a tarefa.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_handoff_enabled",
|
||||
parent_config_key="bot_behavior_policy",
|
||||
field_name="handoff_enabled",
|
||||
area=BotGovernanceArea.FALLBACK_AND_HANDOFF,
|
||||
description="Habilita o encaminhamento para atendimento humano.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_handoff_intents",
|
||||
parent_config_key="bot_behavior_policy",
|
||||
field_name="handoff_intents",
|
||||
area=BotGovernanceArea.FALLBACK_AND_HANDOFF,
|
||||
description="Lista de intencoes que exigem handoff humano.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_max_tool_calls_per_turn",
|
||||
parent_config_key="bot_behavior_policy",
|
||||
field_name="max_tool_calls_per_turn",
|
||||
area=BotGovernanceArea.TOOL_USAGE,
|
||||
description="Limite de chamadas de tools por turno conversacional.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="bot_confirmation_policy",
|
||||
parent_config_key="bot_behavior_policy",
|
||||
field_name="confirmation_policy",
|
||||
area=BotGovernanceArea.TOOL_USAGE,
|
||||
description="Politica de confirmacao antes de acao critica no fluxo.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="channel_enabled",
|
||||
parent_config_key="channel_operation_policy",
|
||||
field_name="enabled",
|
||||
area=BotGovernanceArea.CHANNEL_OPERATION,
|
||||
description="Habilita ou desabilita o bot em um canal homologado.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="channel_maintenance_mode",
|
||||
parent_config_key="channel_operation_policy",
|
||||
field_name="maintenance_mode",
|
||||
area=BotGovernanceArea.CHANNEL_OPERATION,
|
||||
description="Liga manutencao controlada em um canal do bot.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="channel_default_route",
|
||||
parent_config_key="channel_operation_policy",
|
||||
field_name="default_route",
|
||||
area=BotGovernanceArea.CHANNEL_OPERATION,
|
||||
description="Define a rota funcional padrao por canal.",
|
||||
),
|
||||
BotGovernedSettingContract(
|
||||
setting_key="channel_operation_window_ref",
|
||||
parent_config_key="channel_operation_policy",
|
||||
field_name="operation_window_ref",
|
||||
area=BotGovernanceArea.CHANNEL_OPERATION,
|
||||
description="Referencia a janela operacional aplicada por canal.",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def get_bot_governed_setting(setting_key: str) -> BotGovernedSettingContract | None:
|
||||
normalized = str(setting_key or "").strip().lower()
|
||||
for setting in BOT_GOVERNED_SETTINGS:
|
||||
if setting.setting_key == normalized:
|
||||
return setting
|
||||
return None
|
||||
@ -0,0 +1,85 @@
|
||||
"""Define a separacao entre runtime de atendimento e runtime de geracao de tools."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from shared.contracts.access_control import AdminPermission
|
||||
from shared.contracts.tool_publication import ServiceName
|
||||
|
||||
|
||||
class ModelRuntimeTarget(str, Enum):
|
||||
ATENDIMENTO = "atendimento"
|
||||
TOOL_GENERATION = "tool_generation"
|
||||
|
||||
|
||||
class ModelRuntimePurpose(str, Enum):
|
||||
CUSTOMER_RESPONSE = "customer_response"
|
||||
TOOL_GENERATION_AND_VALIDATION = "tool_generation_and_validation"
|
||||
|
||||
|
||||
class ModelRuntimeSeparationRule(str, Enum):
|
||||
SEPARATE_CONFIG_KEYS = "separate_config_keys"
|
||||
SEPARATE_CATALOG_TARGETS = "separate_catalog_targets"
|
||||
INDEPENDENT_PUBLICATION = "independent_publication"
|
||||
INDEPENDENT_ROLLBACK = "independent_rollback"
|
||||
NO_IMPLICIT_PROPAGATION = "no_implicit_propagation"
|
||||
|
||||
|
||||
class ModelRuntimeSeparationContract(BaseModel):
|
||||
runtime_target: ModelRuntimeTarget
|
||||
config_key: str
|
||||
catalog_runtime_target: ModelRuntimeTarget
|
||||
purpose: ModelRuntimePurpose
|
||||
consumed_by_service: ServiceName
|
||||
description: str
|
||||
read_permission: AdminPermission = AdminPermission.VIEW_SYSTEM
|
||||
write_permission: AdminPermission = AdminPermission.MANAGE_SETTINGS
|
||||
published_independently: bool = True
|
||||
rollback_independently: bool = True
|
||||
cross_target_propagation_allowed: bool = False
|
||||
affects_customer_response: bool = False
|
||||
can_generate_code: bool = False
|
||||
|
||||
|
||||
MODEL_RUNTIME_PROFILES: tuple[ModelRuntimeSeparationContract, ...] = (
|
||||
ModelRuntimeSeparationContract(
|
||||
runtime_target=ModelRuntimeTarget.ATENDIMENTO,
|
||||
config_key="atendimento_runtime_profile",
|
||||
catalog_runtime_target=ModelRuntimeTarget.ATENDIMENTO,
|
||||
purpose=ModelRuntimePurpose.CUSTOMER_RESPONSE,
|
||||
consumed_by_service=ServiceName.PRODUCT,
|
||||
description="Runtime do modelo que responde ao cliente final no fluxo de atendimento.",
|
||||
affects_customer_response=True,
|
||||
can_generate_code=False,
|
||||
),
|
||||
ModelRuntimeSeparationContract(
|
||||
runtime_target=ModelRuntimeTarget.TOOL_GENERATION,
|
||||
config_key="tool_generation_runtime_profile",
|
||||
catalog_runtime_target=ModelRuntimeTarget.TOOL_GENERATION,
|
||||
purpose=ModelRuntimePurpose.TOOL_GENERATION_AND_VALIDATION,
|
||||
consumed_by_service=ServiceName.ADMIN,
|
||||
description="Runtime do modelo usado para gerar e validar novas tools no contexto administrativo.",
|
||||
affects_customer_response=False,
|
||||
can_generate_code=True,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
MODEL_RUNTIME_SEPARATION_RULES: tuple[ModelRuntimeSeparationRule, ...] = (
|
||||
ModelRuntimeSeparationRule.SEPARATE_CONFIG_KEYS,
|
||||
ModelRuntimeSeparationRule.SEPARATE_CATALOG_TARGETS,
|
||||
ModelRuntimeSeparationRule.INDEPENDENT_PUBLICATION,
|
||||
ModelRuntimeSeparationRule.INDEPENDENT_ROLLBACK,
|
||||
ModelRuntimeSeparationRule.NO_IMPLICIT_PROPAGATION,
|
||||
)
|
||||
|
||||
|
||||
def get_model_runtime_contract(runtime_target: ModelRuntimeTarget | str) -> ModelRuntimeSeparationContract | None:
|
||||
normalized = str(runtime_target or "").strip().lower()
|
||||
for runtime_contract in MODEL_RUNTIME_PROFILES:
|
||||
if runtime_contract.runtime_target.value == normalized:
|
||||
return runtime_contract
|
||||
return None
|
||||
@ -0,0 +1,375 @@
|
||||
"""Define o escopo de leitura operacional do admin sobre o servico de produto."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from shared.contracts.access_control import AdminPermission
|
||||
|
||||
|
||||
class OperationalDataDomain(str, Enum):
|
||||
INVENTORY = "inventory"
|
||||
SALES = "sales"
|
||||
REVIEW = "review"
|
||||
RENTAL = "rental"
|
||||
CONVERSATION = "conversation"
|
||||
INTEGRATION = "integration"
|
||||
|
||||
|
||||
class OperationalDataSensitivity(str, Enum):
|
||||
OPERATIONAL = "operational"
|
||||
INTERNAL_IDENTIFIER = "internal_identifier"
|
||||
CUSTOMER_IDENTIFIER = "customer_identifier"
|
||||
FREE_TEXT = "free_text"
|
||||
SECRET = "secret"
|
||||
|
||||
|
||||
class OperationalReadGranularity(str, Enum):
|
||||
AGGREGATE = "aggregate"
|
||||
RECORD = "record"
|
||||
|
||||
|
||||
class OperationalReadModel(str, Enum):
|
||||
ADMIN_READ_MODEL = "admin_read_model"
|
||||
|
||||
|
||||
class OperationalConsistencyModel(str, Enum):
|
||||
EVENTUAL = "eventual"
|
||||
|
||||
|
||||
class OperationalFreshnessTarget(str, Enum):
|
||||
NEAR_REAL_TIME = "near_real_time"
|
||||
INTRA_HOUR = "intra_hour"
|
||||
INTRA_DAY = "intra_day"
|
||||
|
||||
|
||||
class OperationalSyncStrategy(str, Enum):
|
||||
ETL_INCREMENTAL = "etl_incremental"
|
||||
|
||||
|
||||
class OperationalStorageShape(str, Enum):
|
||||
SNAPSHOT_TABLE = "snapshot_table"
|
||||
|
||||
|
||||
class OperationalQuerySurface(str, Enum):
|
||||
DEDICATED_VIEW = "dedicated_view"
|
||||
|
||||
|
||||
class OperationalFieldContract(BaseModel):
|
||||
name: str
|
||||
description: str
|
||||
sensitivity: OperationalDataSensitivity = OperationalDataSensitivity.OPERATIONAL
|
||||
|
||||
|
||||
class OperationalDatasetContract(BaseModel):
|
||||
dataset_key: str
|
||||
domain: OperationalDataDomain
|
||||
description: str
|
||||
source_table: str
|
||||
read_permission: AdminPermission = AdminPermission.VIEW_REPORTS
|
||||
report_read_model: OperationalReadModel = OperationalReadModel.ADMIN_READ_MODEL
|
||||
consistency_model: OperationalConsistencyModel = OperationalConsistencyModel.EVENTUAL
|
||||
sync_strategy: OperationalSyncStrategy = OperationalSyncStrategy.ETL_INCREMENTAL
|
||||
storage_shape: OperationalStorageShape = OperationalStorageShape.SNAPSHOT_TABLE
|
||||
query_surface: OperationalQuerySurface = OperationalQuerySurface.DEDICATED_VIEW
|
||||
uses_product_replica: bool = False
|
||||
direct_product_query_allowed: bool = False
|
||||
freshness_target: OperationalFreshnessTarget = OperationalFreshnessTarget.INTRA_HOUR
|
||||
allowed_granularities: tuple[OperationalReadGranularity, ...] = Field(
|
||||
default=(
|
||||
OperationalReadGranularity.AGGREGATE,
|
||||
OperationalReadGranularity.RECORD,
|
||||
)
|
||||
)
|
||||
write_allowed: bool = False
|
||||
allowed_fields: tuple[OperationalFieldContract, ...]
|
||||
blocked_fields: tuple[OperationalFieldContract, ...] = Field(default_factory=tuple)
|
||||
|
||||
|
||||
PRODUCT_OPERATIONAL_DATASETS: tuple[OperationalDatasetContract, ...] = (
|
||||
OperationalDatasetContract(
|
||||
dataset_key="vehicle_inventory",
|
||||
domain=OperationalDataDomain.INVENTORY,
|
||||
description="Estoque operacional de veiculos disponiveis para atendimento comercial.",
|
||||
source_table="vehicles",
|
||||
freshness_target=OperationalFreshnessTarget.INTRA_HOUR,
|
||||
allowed_fields=(
|
||||
OperationalFieldContract(name="id", description="Identificador tecnico do veiculo."),
|
||||
OperationalFieldContract(name="modelo", description="Modelo comercial do veiculo."),
|
||||
OperationalFieldContract(name="categoria", description="Categoria comercial do veiculo."),
|
||||
OperationalFieldContract(name="preco", description="Preco anunciado no estoque."),
|
||||
OperationalFieldContract(name="created_at", description="Data de entrada do registro no estoque."),
|
||||
),
|
||||
),
|
||||
OperationalDatasetContract(
|
||||
dataset_key="sales_orders",
|
||||
domain=OperationalDataDomain.SALES,
|
||||
description="Pedidos de venda usados para operacao, conversao e cancelamentos.",
|
||||
source_table="orders",
|
||||
freshness_target=OperationalFreshnessTarget.NEAR_REAL_TIME,
|
||||
allowed_fields=(
|
||||
OperationalFieldContract(name="numero_pedido", description="Numero publico do pedido."),
|
||||
OperationalFieldContract(name="vehicle_id", description="Veiculo associado ao pedido."),
|
||||
OperationalFieldContract(name="modelo_veiculo", description="Modelo comercial reservado no pedido."),
|
||||
OperationalFieldContract(name="valor_veiculo", description="Valor negociado do veiculo."),
|
||||
OperationalFieldContract(name="status", description="Status operacional do pedido."),
|
||||
OperationalFieldContract(name="motivo_cancelamento", description="Motivo operacional do cancelamento."),
|
||||
OperationalFieldContract(name="data_cancelamento", description="Momento em que o pedido foi cancelado."),
|
||||
OperationalFieldContract(name="created_at", description="Data de criacao do pedido."),
|
||||
OperationalFieldContract(name="updated_at", description="Data da ultima atualizacao do pedido."),
|
||||
),
|
||||
blocked_fields=(
|
||||
OperationalFieldContract(
|
||||
name="user_id",
|
||||
description="Identificador interno do usuario final no produto.",
|
||||
sensitivity=OperationalDataSensitivity.INTERNAL_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="cpf",
|
||||
description="Identificador civil do cliente final.",
|
||||
sensitivity=OperationalDataSensitivity.CUSTOMER_IDENTIFIER,
|
||||
),
|
||||
),
|
||||
),
|
||||
OperationalDatasetContract(
|
||||
dataset_key="review_schedules",
|
||||
domain=OperationalDataDomain.REVIEW,
|
||||
description="Agenda operacional de revisoes e disponibilidade de slots.",
|
||||
source_table="review_schedules",
|
||||
freshness_target=OperationalFreshnessTarget.NEAR_REAL_TIME,
|
||||
allowed_fields=(
|
||||
OperationalFieldContract(name="protocolo", description="Protocolo publico do agendamento."),
|
||||
OperationalFieldContract(name="placa", description="Placa do veiculo agendado."),
|
||||
OperationalFieldContract(name="data_hora", description="Data e hora do slot de revisao."),
|
||||
OperationalFieldContract(name="status", description="Status operacional do agendamento."),
|
||||
OperationalFieldContract(name="created_at", description="Data de criacao do agendamento."),
|
||||
),
|
||||
blocked_fields=(
|
||||
OperationalFieldContract(
|
||||
name="user_id",
|
||||
description="Identificador interno do usuario final no produto.",
|
||||
sensitivity=OperationalDataSensitivity.INTERNAL_IDENTIFIER,
|
||||
),
|
||||
),
|
||||
),
|
||||
OperationalDatasetContract(
|
||||
dataset_key="rental_fleet",
|
||||
domain=OperationalDataDomain.RENTAL,
|
||||
description="Frota operacional de locacao disponivel para consulta administrativa.",
|
||||
source_table="rental_vehicles",
|
||||
freshness_target=OperationalFreshnessTarget.NEAR_REAL_TIME,
|
||||
allowed_fields=(
|
||||
OperationalFieldContract(name="id", description="Identificador tecnico do veiculo de locacao."),
|
||||
OperationalFieldContract(name="placa", description="Placa do veiculo de locacao."),
|
||||
OperationalFieldContract(name="modelo", description="Modelo do veiculo de locacao."),
|
||||
OperationalFieldContract(name="categoria", description="Categoria comercial da locacao."),
|
||||
OperationalFieldContract(name="ano", description="Ano de fabricacao do veiculo."),
|
||||
OperationalFieldContract(name="valor_diaria", description="Valor de diaria vigente."),
|
||||
OperationalFieldContract(name="status", description="Status operacional do veiculo na frota."),
|
||||
OperationalFieldContract(name="created_at", description="Data de cadastro do veiculo na frota."),
|
||||
),
|
||||
),
|
||||
OperationalDatasetContract(
|
||||
dataset_key="rental_contracts",
|
||||
domain=OperationalDataDomain.RENTAL,
|
||||
description="Contratos de locacao usados para operacao, retorno e inadimplencia.",
|
||||
source_table="rental_contracts",
|
||||
freshness_target=OperationalFreshnessTarget.NEAR_REAL_TIME,
|
||||
allowed_fields=(
|
||||
OperationalFieldContract(name="contrato_numero", description="Numero publico do contrato."),
|
||||
OperationalFieldContract(name="rental_vehicle_id", description="Identificador tecnico do veiculo locado."),
|
||||
OperationalFieldContract(name="placa", description="Placa do veiculo vinculado ao contrato."),
|
||||
OperationalFieldContract(name="modelo_veiculo", description="Modelo do veiculo locado."),
|
||||
OperationalFieldContract(name="categoria", description="Categoria da locacao."),
|
||||
OperationalFieldContract(name="data_inicio", description="Inicio da locacao."),
|
||||
OperationalFieldContract(name="data_fim_prevista", description="Fim previsto da locacao."),
|
||||
OperationalFieldContract(name="data_devolucao", description="Momento efetivo da devolucao."),
|
||||
OperationalFieldContract(name="valor_diaria", description="Valor unitario da diaria."),
|
||||
OperationalFieldContract(name="valor_previsto", description="Valor previsto ao abrir o contrato."),
|
||||
OperationalFieldContract(name="valor_final", description="Valor final consolidado da locacao."),
|
||||
OperationalFieldContract(name="status", description="Status operacional do contrato."),
|
||||
OperationalFieldContract(name="created_at", description="Data de criacao do contrato."),
|
||||
OperationalFieldContract(name="updated_at", description="Data da ultima atualizacao do contrato."),
|
||||
),
|
||||
blocked_fields=(
|
||||
OperationalFieldContract(
|
||||
name="user_id",
|
||||
description="Identificador interno do usuario final no produto.",
|
||||
sensitivity=OperationalDataSensitivity.INTERNAL_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="cpf",
|
||||
description="Identificador civil do cliente final.",
|
||||
sensitivity=OperationalDataSensitivity.CUSTOMER_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="observacoes",
|
||||
description="Campo livre informado durante a operacao de locacao.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
),
|
||||
),
|
||||
OperationalDatasetContract(
|
||||
dataset_key="rental_payments",
|
||||
domain=OperationalDataDomain.RENTAL,
|
||||
description="Pagamentos de locacao usados para arrecadacao e conciliacao operacional.",
|
||||
source_table="rental_payments",
|
||||
freshness_target=OperationalFreshnessTarget.NEAR_REAL_TIME,
|
||||
allowed_fields=(
|
||||
OperationalFieldContract(name="protocolo", description="Protocolo publico do pagamento."),
|
||||
OperationalFieldContract(name="contrato_numero", description="Contrato associado ao pagamento."),
|
||||
OperationalFieldContract(name="placa", description="Placa vinculada ao contrato pago."),
|
||||
OperationalFieldContract(name="valor", description="Valor liquidado no pagamento."),
|
||||
OperationalFieldContract(name="data_pagamento", description="Momento do pagamento."),
|
||||
OperationalFieldContract(name="created_at", description="Data de registro do pagamento."),
|
||||
),
|
||||
blocked_fields=(
|
||||
OperationalFieldContract(
|
||||
name="user_id",
|
||||
description="Identificador interno do usuario final no produto.",
|
||||
sensitivity=OperationalDataSensitivity.INTERNAL_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="rental_contract_id",
|
||||
description="Chave tecnica interna do contrato no banco operacional.",
|
||||
sensitivity=OperationalDataSensitivity.INTERNAL_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="favorecido",
|
||||
description="Nome textual do favorecido no comprovante.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="identificador_comprovante",
|
||||
description="Identificador do comprovante de pagamento.",
|
||||
sensitivity=OperationalDataSensitivity.SECRET,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="observacoes",
|
||||
description="Campo livre informado durante o pagamento.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
),
|
||||
),
|
||||
OperationalDatasetContract(
|
||||
dataset_key="conversation_turns",
|
||||
domain=OperationalDataDomain.CONVERSATION,
|
||||
description="Telemetria operacional das conversas para eficiencia, erro e uso de tools.",
|
||||
source_table="conversation_turns",
|
||||
freshness_target=OperationalFreshnessTarget.INTRA_HOUR,
|
||||
allowed_fields=(
|
||||
OperationalFieldContract(name="request_id", description="Identificador tecnico do turno processado."),
|
||||
OperationalFieldContract(name="conversation_id", description="Identificador tecnico da conversa."),
|
||||
OperationalFieldContract(name="channel", description="Canal do atendimento."),
|
||||
OperationalFieldContract(name="turn_status", description="Status do turno conversacional."),
|
||||
OperationalFieldContract(name="intent", description="Intencao classificada para o turno."),
|
||||
OperationalFieldContract(name="domain", description="Dominio operacional associado ao turno."),
|
||||
OperationalFieldContract(name="action", description="Acao tomada pelo orquestrador."),
|
||||
OperationalFieldContract(name="tool_name", description="Tool chamada durante o turno."),
|
||||
OperationalFieldContract(name="elapsed_ms", description="Tempo de processamento do turno em milissegundos."),
|
||||
OperationalFieldContract(name="started_at", description="Inicio do processamento do turno."),
|
||||
OperationalFieldContract(name="completed_at", description="Fim do processamento do turno."),
|
||||
),
|
||||
blocked_fields=(
|
||||
OperationalFieldContract(
|
||||
name="user_id",
|
||||
description="Identificador interno do usuario final no produto.",
|
||||
sensitivity=OperationalDataSensitivity.INTERNAL_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="external_id",
|
||||
description="Identificador externo do usuario final no canal.",
|
||||
sensitivity=OperationalDataSensitivity.CUSTOMER_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="username",
|
||||
description="Username do usuario final no canal.",
|
||||
sensitivity=OperationalDataSensitivity.CUSTOMER_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="user_message",
|
||||
description="Mensagem original do usuario final.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="assistant_response",
|
||||
description="Resposta textual completa enviada ao usuario final.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="tool_arguments",
|
||||
description="Payload bruto dos argumentos enviados para tools.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="error_detail",
|
||||
description="Detalhe bruto de erro que pode carregar contexto sensivel.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
),
|
||||
),
|
||||
OperationalDatasetContract(
|
||||
dataset_key="integration_deliveries",
|
||||
domain=OperationalDataDomain.INTEGRATION,
|
||||
description="Entrega operacional de eventos para provedores externos e observabilidade de falhas.",
|
||||
source_table="integration_deliveries",
|
||||
freshness_target=OperationalFreshnessTarget.INTRA_HOUR,
|
||||
allowed_fields=(
|
||||
OperationalFieldContract(name="route_id", description="Rota interna que originou a entrega."),
|
||||
OperationalFieldContract(name="event_type", description="Tipo de evento entregue."),
|
||||
OperationalFieldContract(name="provider", description="Provedor de integracao usado na entrega."),
|
||||
OperationalFieldContract(name="status", description="Status atual da entrega."),
|
||||
OperationalFieldContract(name="attempts", description="Quantidade de tentativas realizadas."),
|
||||
OperationalFieldContract(name="dispatched_at", description="Momento do disparo da entrega."),
|
||||
OperationalFieldContract(name="created_at", description="Data de criacao do registro de entrega."),
|
||||
OperationalFieldContract(name="updated_at", description="Data da ultima atualizacao da entrega."),
|
||||
),
|
||||
blocked_fields=(
|
||||
OperationalFieldContract(
|
||||
name="payload_json",
|
||||
description="Payload bruto do evento entregue.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="recipient_email",
|
||||
description="Email do destinatario final da integracao.",
|
||||
sensitivity=OperationalDataSensitivity.CUSTOMER_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="recipient_name",
|
||||
description="Nome do destinatario final da integracao.",
|
||||
sensitivity=OperationalDataSensitivity.CUSTOMER_IDENTIFIER,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="rendered_subject",
|
||||
description="Assunto renderizado da mensagem enviada.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="rendered_body",
|
||||
description="Corpo renderizado da mensagem enviada.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="provider_message_id",
|
||||
description="Identificador bruto devolvido pelo provedor externo.",
|
||||
sensitivity=OperationalDataSensitivity.SECRET,
|
||||
),
|
||||
OperationalFieldContract(
|
||||
name="last_error",
|
||||
description="Detalhe textual do ultimo erro de entrega.",
|
||||
sensitivity=OperationalDataSensitivity.FREE_TEXT,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def get_operational_dataset(dataset_key: str) -> OperationalDatasetContract | None:
|
||||
normalized = str(dataset_key or "").strip().lower()
|
||||
for dataset in PRODUCT_OPERATIONAL_DATASETS:
|
||||
if dataset.dataset_key == normalized:
|
||||
return dataset
|
||||
return None
|
||||
@ -0,0 +1,258 @@
|
||||
"""Define o escopo de configuracao funcional governada entre admin e product."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from shared.contracts.access_control import AdminPermission
|
||||
|
||||
|
||||
class FunctionalConfigurationDomain(str, Enum):
|
||||
MODEL_CATALOG = "model_catalog"
|
||||
ATENDIMENTO_RUNTIME = "atendimento_runtime"
|
||||
TOOL_GENERATION_RUNTIME = "tool_generation_runtime"
|
||||
BOT_POLICY = "bot_policy"
|
||||
CHANNEL_OPERATION = "channel_operation"
|
||||
CONFIG_PUBLICATION = "config_publication"
|
||||
|
||||
|
||||
class FunctionalConfigurationMutability(str, Enum):
|
||||
READ_ONLY = "read_only"
|
||||
DIRECTOR_GOVERNED = "director_governed"
|
||||
|
||||
|
||||
class FunctionalConfigurationSource(str, Enum):
|
||||
PLATFORM_CATALOG = "platform_catalog"
|
||||
ADMIN_GOVERNED_STATE = "admin_governed_state"
|
||||
PRODUCT_EFFECTIVE_STATE = "product_effective_state"
|
||||
|
||||
|
||||
class FunctionalConfigurationPropagation(str, Enum):
|
||||
OBSERVATION_ONLY = "observation_only"
|
||||
VERSIONED_PUBLICATION = "versioned_publication"
|
||||
|
||||
|
||||
class FunctionalConfigurationFieldContract(BaseModel):
|
||||
name: str
|
||||
description: str
|
||||
writable: bool = True
|
||||
secret: bool = False
|
||||
|
||||
|
||||
class FunctionalConfigurationContract(BaseModel):
|
||||
config_key: str
|
||||
domain: FunctionalConfigurationDomain
|
||||
description: str
|
||||
source: FunctionalConfigurationSource
|
||||
read_permission: AdminPermission = AdminPermission.VIEW_SYSTEM
|
||||
write_permission: AdminPermission | None = AdminPermission.MANAGE_SETTINGS
|
||||
mutability: FunctionalConfigurationMutability = FunctionalConfigurationMutability.DIRECTOR_GOVERNED
|
||||
propagation: FunctionalConfigurationPropagation = (
|
||||
FunctionalConfigurationPropagation.VERSIONED_PUBLICATION
|
||||
)
|
||||
affects_product_runtime: bool = True
|
||||
direct_product_write_allowed: bool = False
|
||||
fields: tuple[FunctionalConfigurationFieldContract, ...]
|
||||
|
||||
|
||||
SYSTEM_FUNCTIONAL_CONFIGURATIONS: tuple[FunctionalConfigurationContract, ...] = (
|
||||
FunctionalConfigurationContract(
|
||||
config_key="allowed_model_catalog",
|
||||
domain=FunctionalConfigurationDomain.MODEL_CATALOG,
|
||||
description="Catalogo de modelos liberados pela plataforma para atendimento e geracao de tools.",
|
||||
source=FunctionalConfigurationSource.PLATFORM_CATALOG,
|
||||
write_permission=None,
|
||||
mutability=FunctionalConfigurationMutability.READ_ONLY,
|
||||
propagation=FunctionalConfigurationPropagation.OBSERVATION_ONLY,
|
||||
affects_product_runtime=False,
|
||||
fields=(
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="runtime_target",
|
||||
description="Destino funcional do modelo, como atendimento ou geracao de tools.",
|
||||
writable=False,
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="provider",
|
||||
description="Provedor homologado para o modelo.",
|
||||
writable=False,
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="model_name",
|
||||
description="Nome tecnico do modelo liberado.",
|
||||
writable=False,
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="capability_tags",
|
||||
description="Capacidades suportadas pelo modelo homologado.",
|
||||
writable=False,
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="status",
|
||||
description="Estado de homologacao do modelo no catalogo da plataforma.",
|
||||
writable=False,
|
||||
),
|
||||
),
|
||||
),
|
||||
FunctionalConfigurationContract(
|
||||
config_key="atendimento_runtime_profile",
|
||||
domain=FunctionalConfigurationDomain.ATENDIMENTO_RUNTIME,
|
||||
description="Perfil funcional ativo para o bot de atendimento no servico de produto.",
|
||||
source=FunctionalConfigurationSource.ADMIN_GOVERNED_STATE,
|
||||
fields=(
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="provider",
|
||||
description="Provedor selecionado para o atendimento.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="model_name",
|
||||
description="Modelo selecionado para o atendimento.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="temperature",
|
||||
description="Temperatura aplicada nas respostas do atendimento.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="max_output_tokens",
|
||||
description="Limite de saida usado pelo atendimento.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="prompt_profile_ref",
|
||||
description="Referencia da estrategia de prompt publicada para o atendimento.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="tool_policy_ref",
|
||||
description="Referencia da politica de uso de tools pelo atendimento.",
|
||||
),
|
||||
),
|
||||
),
|
||||
FunctionalConfigurationContract(
|
||||
config_key="tool_generation_runtime_profile",
|
||||
domain=FunctionalConfigurationDomain.TOOL_GENERATION_RUNTIME,
|
||||
description="Perfil funcional usado para geracao e validacao automatica de novas tools.",
|
||||
source=FunctionalConfigurationSource.ADMIN_GOVERNED_STATE,
|
||||
fields=(
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="provider",
|
||||
description="Provedor selecionado para a geracao de tools.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="model_name",
|
||||
description="Modelo selecionado para a geracao de tools.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="reasoning_profile",
|
||||
description="Perfil de raciocinio aprovado para geracao de codigo.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="max_output_tokens",
|
||||
description="Limite de saida usado na geracao de tools.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="validation_profile_ref",
|
||||
description="Referencia da politica de validacao automatica de tools.",
|
||||
),
|
||||
),
|
||||
),
|
||||
FunctionalConfigurationContract(
|
||||
config_key="bot_behavior_policy",
|
||||
domain=FunctionalConfigurationDomain.BOT_POLICY,
|
||||
description="Politicas funcionais do fluxo do bot para fallback, handoff e uso de tools.",
|
||||
source=FunctionalConfigurationSource.ADMIN_GOVERNED_STATE,
|
||||
fields=(
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="fallback_mode",
|
||||
description="Modo funcional de fallback quando o bot nao conclui a tarefa.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="handoff_enabled",
|
||||
description="Sinaliza se o fluxo pode encaminhar para atendimento humano.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="handoff_intents",
|
||||
description="Lista de intencoes que forcam handoff humano.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="max_tool_calls_per_turn",
|
||||
description="Limite de chamadas de tools por turno de atendimento.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="confirmation_policy",
|
||||
description="Politica de confirmacao antes de acao critica no fluxo.",
|
||||
),
|
||||
),
|
||||
),
|
||||
FunctionalConfigurationContract(
|
||||
config_key="channel_operation_policy",
|
||||
domain=FunctionalConfigurationDomain.CHANNEL_OPERATION,
|
||||
description="Politicas funcionais por canal, incluindo habilitacao, manutencao e janela operacional.",
|
||||
source=FunctionalConfigurationSource.ADMIN_GOVERNED_STATE,
|
||||
fields=(
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="channel",
|
||||
description="Canal operacional ao qual a politica se aplica.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="enabled",
|
||||
description="Indica se o canal esta habilitado para atendimento.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="maintenance_mode",
|
||||
description="Sinaliza se o canal esta em manutencao controlada.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="default_route",
|
||||
description="Rota funcional padrao usada pelo canal.",
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="operation_window_ref",
|
||||
description="Referencia da janela operacional aplicada ao canal.",
|
||||
),
|
||||
),
|
||||
),
|
||||
FunctionalConfigurationContract(
|
||||
config_key="published_runtime_state",
|
||||
domain=FunctionalConfigurationDomain.CONFIG_PUBLICATION,
|
||||
description="Estado efetivo publicado no produto para auditoria de versao e aplicacao runtime.",
|
||||
source=FunctionalConfigurationSource.PRODUCT_EFFECTIVE_STATE,
|
||||
write_permission=None,
|
||||
mutability=FunctionalConfigurationMutability.READ_ONLY,
|
||||
propagation=FunctionalConfigurationPropagation.OBSERVATION_ONLY,
|
||||
fields=(
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="config_scope",
|
||||
description="Escopo funcional da configuracao publicada.",
|
||||
writable=False,
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="active_version",
|
||||
description="Versao funcional atualmente ativa no produto.",
|
||||
writable=False,
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="published_by",
|
||||
description="Identificador administrativo de quem publicou a configuracao.",
|
||||
writable=False,
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="published_at",
|
||||
description="Momento da ultima publicacao governada.",
|
||||
writable=False,
|
||||
),
|
||||
FunctionalConfigurationFieldContract(
|
||||
name="applied_at",
|
||||
description="Momento em que o produto aplicou a configuracao em runtime.",
|
||||
writable=False,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def get_functional_configuration(config_key: str) -> FunctionalConfigurationContract | None:
|
||||
normalized = str(config_key or "").strip().lower()
|
||||
for configuration in SYSTEM_FUNCTIONAL_CONFIGURATIONS:
|
||||
if configuration.config_key == normalized:
|
||||
return configuration
|
||||
return None
|
||||
Loading…
Reference in New Issue