Regras de deck pela API
As regras de deck (Cards) preparam e ajustam os decks NEWAVE e DECOMP. Esta
página mostra como validar e enviar regras, usar Cards do catálogo, definir
perfis e sequências de regras e conferir o deck montado pela API. O conceito de
base e ajustes e o uso no Portal estão em Cards;
os campos do YAML estão na referência do YAML.
Autenticação, Operation e erros comuns estão na
visão geral; os campos de cada rota, na
referência interativa.
Toda regra usada numa sequência é uma referência imutável:
{"tipo": "upload", "id": "rules_0123456789abcdef0123456789abcdef", "sha256": "1111111111111111111111111111111111111111111111111111111111111111"}
Você obtém essa referência enviando um arquivo (POST /deck-rules/uploads) ou
resolvendo um Card do catálogo (POST /deck-rules/catalog/{catalog_id}/resolve).
Validar e enviar
Valide um arquivo sem salvá-lo:
curl -sS -X POST "$MYRIA_API/api/v1/deck-rules/validate" \
-H "Authorization: Bearer $MYRIA_TOKEN" \
-F "expected_document_type=ajuste" \
-F "file=@sensibilidade.yaml;type=application/yaml"
A validação aceita só YAML e sempre responde 200: um YAML inválido volta com
valid: false e a lista errors, cada erro com o caminho como você escreveu
no YAML (por exemplo, montar.decomp.DP.0.periodo). A resposta traz também
sha256, size_bytes, document_type e summary. expected_document_type
é opcional e aceita base ou ajuste. Na API, ajuste é o papel de um Card:
um documento tipo: card tem document_type: "ajuste"; base corresponde a
tipo: base. Essa rota não usa Idempotency-Key.
summary resume o documento na grafia do YAML:
{"avisos": [{"code": "carga_duplicada_newave_decomp", "message": "A carga do DECOMP e formada a partir da carga do NEWAVE; alterar as duas soma a variacao duas vezes.", "newave": "newave.SISTEMA.carga [submercado SE] mes_1 add", "decomp": "decomp.DP.carga [submercado SE] add"}], "versao": 5, "tipo": "card", "titulo": "Carga +1 GW no primeiro mês", "descricao": "...", "command_count": 2, "models": {"decomp": {"DP": 1}, "newave": {"SISTEMA": 1}}, "has_policies": false}
tipo é card ou base, e titulo/descricao são os do documento.
command_count conta as operações depois da expansão do léxico, e models
conta essas operações por modelo e família. has_policies indica se o
documento declara politicas (só uma base pode declarar).
avisos lista o que o Card pode estar aplicando duas vezes. Não é erro: o
upload continua válido, e a tela da rodada pede confirmação antes de pôr o Card
na sequência. Os códigos são carga_duplicada_newave_decomp,
carga_definida_no_dp, cvu_duplicado_newave_decomp e
geracao_duplicada_newave_decomp (veja Blocos do DECOMP formados a partir do
NEWAVE).
Um Card sem nenhuma entrada em montar nem em antes_de_rodar recebe o aviso
card_vazio, com newave e decomp vazios: ele não altera nenhum deck.
Verificar contra a rodada
O esquema não confere usinas, restrições ou meses com um deck. Para conferir o
Card com o deck de uma rodada, envie também study_key e round_key (os dois
juntos; só um deles retorna 400 invalid_payload):
curl -sS -X POST "$MYRIA_API/api/v1/deck-rules/validate" \
-H "Authorization: Bearer $MYRIA_TOKEN" \
-F "study_key=$STUDY_KEY" \
-F "round_key=$ROUND_KEY" \
-F "file=@sensibilidade.yaml;type=application/yaml"
A conferência lê só os cadastros do deck (usinas, UTEs, REEs, submercados, rotas, restrições e horizonte), sem montar nada. O Card entra no fim da sequência salva da rodada: o que a base e os Cards anteriores criam conta como existente. O deck conferido é o de entrada, sobre o qual os Cards são aplicados: o deck de referência do PMO/RV da rodada; sem ele, o da própria rodada e, por fim, o da rodada anterior do mesmo modelo, sempre com o PMO e a revisão da rodada conferida.
Para um Card válido (document_type: "ajuste"), a resposta ganha
verificacao; para uma base ou um YAML inválido, verificacao é null. Sem
study_key/round_key o campo não aparece.
{"verificacao": {"round_key": "acme-12", "valido": false, "erros": 1, "avisos": 1, "modelo": "decomp", "preflight_dos_cards": "apply", "deck": {"disponivel": true, "origem": "rodada", "descricao": "Deck desta rodada", "indisponivel": [], "mensagem": null}, "achados": [{"severidade": "erro", "codigo": "ute_inexistente", "titulo": "Inflexibilidade", "caminho": "montar.decomp.CT.0", "entidade": "UTE 8888", "modelo": "decomp", "mensagem": "UTE 8888 nao existe no cadastro do DECOMP desta rodada", "texto": "Card \"Inflexibilidade\", montar.decomp.CT.0: UTE 8888 nao existe no cadastro do DECOMP desta rodada [ute_inexistente]"}, {"severidade": "aviso", "codigo": "restricao_ausente", "titulo": "Inflexibilidade", "caminho": "montar.decomp.RE.1.RE 447", "entidade": "RE 447", "modelo": "decomp", "mensagem": "RE 447 nao existe no DADGER desta rodada; a entrada sera ignorada nesta rodada", "texto": "..."}]}}
Cada achado traz severidade, codigo, o caminho da entrada como você
escreveu no YAML, a entidade e a mensagem; texto junta tudo numa frase.
valido: false quando há pelo menos um erro.
| Severidade | Quando | Códigos |
|---|---|---|
erro | Entidade de cadastro fora do deck, inclusive em termos de uma restrição criada; RI, IA ou HE alterado sem existir; restrição do DECOMP alterada só pelo nome sem criação nem número que a resolva | uhe_inexistente, ute_inexistente, ree_inexistente, submercado_inexistente, rota_inexistente, restricao_estrutural_ausente, restricao_nome_nao_resolvido |
aviso | Alvo de vigência ausente: a entrada é ignorada nesta rodada | restricao_ausente, restricao_comentada, restricao_eletrica_ausente, agrint_grupo_ausente, periodo_anterior_ao_pmo, periodo_fora_do_horizonte, estagio_fora_do_horizonte, term_mes_fora_do_ano |
aviso | Card sem efeito nesta rodada | card_vazio, sem_efeito_no_modelo (só seções do outro modelo), preflight_desligado (só antes_de_rodar com o Preflight dos Cards em skip) |
deck.disponivel: false quer dizer que não havia deck para ler (ou a leitura
passou do prazo); deck.mensagem explica, e só os avisos de Card sem efeito
são conferidos. deck.indisponivel lista os cadastros que não puderam ser lidos
(por exemplo newave.agrint): o que depende deles fica sem conferência. A
rodada de outra organização ou inexistente retorna 404 not_found.
Na tela da rodada, a mesma conferência roda ao adicionar um Card à sequência e no botão Verificar contra a rodada: erro impede adicionar o Card; aviso pede confirmação.
Para guardar o arquivo e obter a referência, use POST /deck-rules/uploads
com Idempotency-Key:
curl -sS -X POST "$MYRIA_API/api/v1/deck-rules/uploads" \
-H "Authorization: Bearer $MYRIA_TOKEN" \
-H "Idempotency-Key: card-carga-alta-001" \
-F "expected_document_type=ajuste" \
-F "file=@sensibilidade.yaml;type=application/yaml"
O envio aceita YAML (versao: 5) e planilhas Excel de ajustes (.xlsx ou
.xls). O formato é identificado pelo conteúdo e conferido com a extensão.
Uma planilha é convertida para YAML e passa pelas mesmas validações; planilhas
com macros, criptografia ou compressão suspeita são recusadas, e uma planilha
que não seja claramente do modelo suportado retorna
spreadsheet_dialect_ambiguous. O arquivo tem até 2 MiB (413
deck_rules_source_too_large) e nome de até 255 caracteres (400
invalid_original_name). Um documento inválido retorna 422 e não é
guardado.
Os erros próprios de planilhas usam o prefixo spreadsheet_, por exemplo
spreadsheet_dialect_ambiguous, spreadsheet_signature_mismatch,
spreadsheet_macros_not_allowed, spreadsheet_encrypted_not_allowed,
spreadsheet_zip_bomb e spreadsheet_invalid_xlsx. Desde outubro de 2026
esse é o único prefixo emitido para esses erros; se a sua integração compara
códigos de planilha, use esses nomes.
A resposta é 201, com upload (a referência {tipo, id, sha256}),
document_type, original_name, size_bytes, summary e created_at. O
conteúdo não é devolvido. Repetir a chave com o mesmo arquivo devolve a mesma
resposta; com outro arquivo, 409.
Cards do catálogo
GET /deck-rules/catalog lista os Cards visíveis para a organização, com
paginação por cursor. Filtros opcionais:
| Parâmetro | Valores |
|---|---|
model | newave ou decomp |
origin | myria, organization ou study (este exige study_key) |
study_key | Inclui os Cards do estudo. |
q | Busca no título e na descrição. |
Cada item traz catalog_id, title, description, tags, visibility,
role (base ou ajuste, o papel de um Card), models, published_version e
resolved_reference. Se resolved_reference vier preenchido, use-o
diretamente. Se vier null, peça a resolução:
curl -sS -X POST "$MYRIA_API/api/v1/deck-rules/catalog/$CATALOG_ID/resolve" \
-H "Authorization: Bearer $MYRIA_TOKEN" \
-H "Idempotency-Key: resolver-$CATALOG_ID-1"
O pedido não precisa de corpo, exceto para um Card exclusivo de estudo: nesse
caso envie {"study_key": "<study_key>"}. A resposta é 202 Operation. Em succeeded,
result.deck_rules_reference traz a referência {tipo:"upload",id,sha256} e
result.avisos traz os mesmos avisos do envio do Card (lista vazia quando não
há). A
versão publicada do Card é fixada quando o pedido é aceito, então repetir o
pedido não troca de versão.
Perfis
O perfil define a sequência de regras usada por padrão. Há um perfil da organização e um por estudo:
GETePATCH /deck-rules/profile(organização);GETePATCH /studies/{study_key}/deck-rules-profile(estudo).
GET exige studies:read e PATCH, studies:write. A resposta traz
scope, state, revision, ordered_source_items, model_defaults,
phase_policy, phase_policy_provenance e composition_sha256. Sem perfil
salvo, o GET responde state: "implicit" e revision: 0, só com a base do
Myria, sem gravar nada.
O PATCH substitui o perfil inteiro. Exige Idempotency-Key e o número de
revisão que você leu, em expected_revision ou no cabeçalho If-Match. O
primeiro PATCH usa 0 e cria a revisão 1.
{
"expected_revision": 0,
"ordered_source_items": [
{"ordem": 1, "papel": "base", "proveniencia": "oficial", "tipo": "oficial", "modelo": ""},
{"ordem": 2, "papel": "ajuste", "proveniencia": "adicionado", "tipo": "upload",
"id": "rules_0123456789abcdef0123456789abcdef",
"sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"modelo": "decomp"}
],
"model_defaults": {"newave": [1], "decomp": [1, 2]},
"phase_policy": {"source_declared_preflight": "apply"}
}
| Campo | Uso |
|---|---|
ordered_source_items | A sequência completa. ordem começa em 1 e não pula números. Só pode haver uma base, e ela vem primeiro. tipo: "oficial" é a base do Myria e não leva id nem sha256; tipo: "upload" exige a referência. modelo é newave, decomp ou vazio (os dois). |
model_defaults | Para cada modelo, as posições (ordem) usadas por padrão. |
phase_policy | source_declared_preflight: apply (padrão) ou skip. skip ignora só a seção antes_de_rodar dos Cards; o antes_de_rodar da base sempre roda. É o interruptor Ajustes condicionais da sequência no Portal. |
Um número de revisão desatualizado retorna 409, mesmo que o conteúdo enviado
seja igual ao atual. Mudar um perfil não altera rodadas já criadas nem regras
já usadas numa execução.
As primeiras rodadas geradas a partir de uma base externa sem rodada
consumidora recebem o perfil do estudo, com as posições padrão de cada modelo
(model_defaults). Esse perfil inclui o padrão da organização copiado ao criar
o estudo. Continuações com rodada de origem herdam a sequência de Cards dessa
rodada; alterar o perfil depois não substitui essa herança. Se
model_defaults mudar entre a prévia e a criação das primeiras rodadas, gere
uma nova prévia. Na confirmação, reenvie origin_configuration_revision
exatamente como recebido da prévia: esse valor identifica a origem e as
posições padrão vistas na prévia.
skip não permite omitir condições DECOMP que fazem parte de uma criação.
Se um Card cria uma restrição em montar e liga a ela condições no próprio
antes_de_rodar, a operação falha com
source_declared_preflight_required_for_creation e preserva o deck publicado.
As condições da base nunca são afetadas por skip. Validações estruturais e
limites físicos continuam obrigatórios.
Cards da rodada
Cada rodada guarda a sua sequência de Cards: a mesma lista ordered_source_items
dos perfis, com uma revisão por alteração. O padrão do estudo fica no
perfil do estudo.
GET /studies/{study_key}/rodadas/{round_key}/deck-rules exige studies:read e
devolve study_key, round (round_key e name), configuration_revision,
rule_stack (revision, state, origin, study_profile_revision,
composition_sha256 e ordered_source_items), admitted e admitted_at.
state: "open" indica uma revisão que ainda não foi usada numa execução;
admitted, a que foi fixada por uma execução.
PUT na mesma rota exige studies:write e Idempotency-Key e salva a sequência
pelo mesmo caminho da tela, ou seja, uma nova revisão da
configuração da rodada:
curl -sS -X PUT "$MYRIA_API/api/v1/studies/$STUDY_KEY/rodadas/$ROUND_KEY/deck-rules" \
-H "Authorization: Bearer $MYRIA_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: regras-206-001" \
-d '{
"expected_configuration_revision": 0,
"rule_stack": {
"origin": "round",
"ordered_source_items": [
{"ordem": 1, "papel": "base", "proveniencia": "oficial", "tipo": "oficial",
"id": null, "sha256": null, "modelo": ""},
{"ordem": 2, "papel": "ajuste", "proveniencia": "adicionado", "tipo": "upload",
"id": "rules_0123456789abcdef0123456789abcdef",
"sha256": "1111111111111111111111111111111111111111111111111111111111111111",
"modelo": ""}
]
}
}'
expected_configuration_revision é o configuration_revision lido no GET
(0 quando a rodada ainda não tem revisão de configuração). Um número
desatualizado retorna 409 configuration_revision_conflict e nada é
sobrescrito. Para voltar ao perfil do estudo, envie
"rule_stack": {"origin": "study_default"}, sem itens. Numa rodada que já
executou, a sequência usada fica preservada: o PUT abre uma nova revisão, e as
regras novas valem na próxima montagem. RV+ e M+ também herdam os Cards
salvos da origem, e a origem mantém sua sequência salva depois da criação
desses novos períodos. Para aplicar a configuração, use
POST .../configuration/apply.
Prévia do deck montado
POST /studies/{study_key}/rodadas/{round_key}/deck-rules/preview monta o deck
da rodada com as regras atuais, compara com o deck antes das regras e descarta
o resultado, sem publicar nada.
Para DECOMP RV0 formada a partir de um NEWAVE do mesmo estudo, a prévia lê o deck publicado desse NEWAVE em uma versão fixa. A referência entre as rodadas permanece inalterada, e a prévia não executa o NEWAVE.
curl -sS -X POST \
"$MYRIA_API/api/v1/studies/$STUDY_KEY/rodadas/$ROUND_KEY/deck-rules/preview" \
-H "Authorization: Bearer $MYRIA_TOKEN" \
-H "Idempotency-Key: previa-206-r3"
A rota exige studies:read, não tem corpo e exige Idempotency-Key (sem ele,
400 missing_idempotency_key). A resposta é 202 com a Operation. Repetir
a chave devolve o mesmo pedido, sem montar de novo. Depois de mudar as regras
ou a configuração da rodada, use uma chave nova: reaproveitar a anterior
retorna 409 idempotency_key_reused.
A prévia considera a revisão atual das regras, inclusive quando ela foi salva depois de uma montagem anterior. Se a rodada ainda aguarda os volumes de armazenamento (EARM), os outros ajustes, como carga, continuam aparecendo na prévia e na aplicação da configuração; o armazenamento só é ajustado logo antes da execução.
Em succeeded, result.preview traz:
materialized: trueepublished: false;- os SHA-256 do pacote, do plano, das regras e das árvores de entrada e saída;
sources: as regras na ordem aplicada, com a referência de cada uma;files: cada arquivo do deck, com seus blocos e o estado de cada um (created,removed,modifiedouunchanged);summaryediagnostics;scenario, com o deck de partida e o efeito de cada Card (applied,shadowed,outside_horizonouno_op).
Se uma fonte faltar ou divergir, o pedido termina com erro; o Myria não completa valores por conta própria.