184 lines
9.4 KiB
Markdown
184 lines
9.4 KiB
Markdown
---
|
|
id: AGD-0019
|
|
ticket: asset-entry-codec-enum-with-metadata
|
|
title: Agenda - Asset Entry Codec as Enum with Metadata
|
|
status: accepted
|
|
created: 2026-04-09
|
|
resolved: 2026-04-09
|
|
decision: DEC-0005
|
|
tags: [asset, runtime, codec, metadata]
|
|
---
|
|
|
|
# Agenda - Asset Entry Codec as Enum with Metadata
|
|
|
|
## Contexto
|
|
|
|
A `DSC-0017` consolidou a normalizacao de `AssetEntry.metadata`, separando campos criticos na raiz e empurrando detalhes tecnicos para subarvores como `codec` e `pipeline`.
|
|
|
|
Isso resolveu a organizacao do contrato, mas nao fechou a representacao tipada de `codec` dentro do runtime. Hoje o dado ainda e percebido mais como JSON dinamico do que como parte explicita do modelo de dominio.
|
|
|
|
O tema desta agenda e decidir se `codec` em `AssetEntry` deve deixar de ser apenas um blob/subarvore e passar a ser um enum tipado, capaz de carregar os metadados pertinentes a cada codec.
|
|
|
|
## Problema
|
|
|
|
Quando `codec` e tratado como JSON generico ou como informacao frouxa em metadados, o runtime perde:
|
|
|
|
- clareza sobre quais codecs existem de fato;
|
|
- validacao estrutural forte por variante;
|
|
- ergonomia para loaders e drivers;
|
|
- separacao nitida entre metadata do banco e metadata do codec.
|
|
|
|
Ao mesmo tempo, tipar `codec` cedo demais ou de forma larga demais pode misturar responsabilidades e transformar o enum em um deposito generico de qualquer detalhe tecnico do asset.
|
|
|
|
## Pontos Criticos
|
|
|
|
1. Limite de responsabilidade.
|
|
`codec` deve carregar apenas dados necessarios para decodificacao, nao toda a metadata do asset.
|
|
|
|
2. Compatibilidade com a normalizacao anterior.
|
|
A agenda nao deve reabrir a decisao de segmentar metadata; ela deve apenas fechar como o segmento `codec` vira modelo tipado no runtime.
|
|
|
|
3. Evolucao de formato.
|
|
O modelo precisa permitir codecs sem payload adicional e codecs com configuracao especifica, sem cair em campos opcionais demais.
|
|
|
|
4. Unknown/forward compatibility.
|
|
Precisamos decidir se codecs desconhecidos falham no parse, se ficam preservados como raw JSON, ou se existe modo hibrido.
|
|
|
|
5. Impacto nos callers.
|
|
A mudanca afeta serializacao/deserializacao, helpers, validacao de cart e ergonomia dos loaders.
|
|
|
|
## Opcoes
|
|
|
|
### Opcao A - Manter `codec` como JSON dinamico
|
|
|
|
- **Abordagem:** manter `codec` como subarvore em `metadata` ou como `serde_json::Value`, usando helpers tipados apenas nos pontos de consumo.
|
|
- **Pro:** menor migracao imediata e maior flexibilidade para formatos experimentais.
|
|
- **Con:** o contrato real continua implicito, com checagens espalhadas e mais risco de drift entre parser e consumidores.
|
|
- **Tradeoff:** adia a decisao de dominio e preserva a ambiguidade exatamente no ponto onde o runtime precisa de semantica forte.
|
|
|
|
### Opcao B - Tornar `codec` um enum tipado com payload por variante
|
|
|
|
- **Abordagem:** introduzir algo como `AssetCodec`, com variantes explicitas (`None`, `Png { ... }`, `Jpeg { ... }`, etc.) carregando apenas os metadados do proprio codec.
|
|
- **Pro:** o runtime ganha exaustividade, parse centralizado e um modelo de dominio mais honesto.
|
|
- **Con:** exige decidir fronteiras claras entre metadata do codec e metadata do banco/asset; tambem aumenta custo de evolucao quando novos codecs surgem.
|
|
- **Tradeoff:** troca flexibilidade irrestrita por contrato forte e melhor ergonomia operacional.
|
|
|
|
### Opcao C - Separar `codec_kind` de um payload opcional tipado
|
|
|
|
- **Abordagem:** usar um enum leve para o tipo de codec e um campo separado para configuracao adicional.
|
|
- **Pro:** reduz acoplamento do discriminante com o payload e pode simplificar alguns formatos.
|
|
- **Con:** reintroduz estados invalidos (`kind` e payload divergentes), exigindo validacao cruzada manual.
|
|
- **Tradeoff:** parece mais flexivel, mas perde a principal vantagem de um tagged enum: coerencia estrutural por construcao.
|
|
|
|
## Sugestao / Recomendacao
|
|
|
|
Seguir com a **Opcao B**.
|
|
|
|
`codec` em `AssetEntry` deveria ser um enum tipado e capaz de carregar os metadados estritamente relativos a ele. Isso fecha melhor o modelo de dominio: o runtime deixa de tratar codec como detalhe textual solto e passa a reconhece-lo como parte semantica do contrato do asset.
|
|
|
|
A recomendacao, no entanto, vem com uma fronteira explicita:
|
|
|
|
- metadata especifica de decodificacao fica dentro do enum do codec;
|
|
- metadata do banco/formato de consumo continua fora dele;
|
|
- metadata editorial ou operacional do asset tambem continua fora dele.
|
|
|
|
Em outras palavras, a discussao nao e "colocar toda metadata dentro de `codec`", e sim "dar ao segmento `codec` uma representacao tipada, exaustiva e com payload por variante quando necessario".
|
|
|
|
Com as respostas atuais, a recomendacao fica mais concreta:
|
|
|
|
- o JSON serializado pelo Studio dentro de `asset.pa` pode manter `codec` como string opaca;
|
|
- o runtime Rust deve desserializar essa string diretamente para um enum em `AssetEntry`;
|
|
- o nome canonico de cada codec no JSON deve seguir o contrato definido pelo runtime, e o Studio/paker deve se conformar exatamente a ele;
|
|
- a variante inicial canonica e apenas `None`;
|
|
- `Raw` deve ser considerada removida do modelo;
|
|
- codec desconhecido no runtime e erro fatal de carregamento e deve impedir a execucao do cartucho;
|
|
- `pipeline` nao deve sobreviver no runtime e pode ser descartado completamente desse lado.
|
|
|
|
## Perguntas em Aberto
|
|
|
|
- Como o modelo evolui quando surgir o primeiro codec real com payload adicional sem perder a separacao entre o discriminante string no JSON e a interpretacao tipada no runtime?
|
|
|
|
## Discussao
|
|
|
|
### Direcao fechada ate aqui
|
|
|
|
1. **Serializacao no Studio**
|
|
O JSON serializado pelo Studio dentro de `asset.pa` deve expor `codec` como string opaca.
|
|
|
|
2. **Desserializacao no runtime**
|
|
O runtime Rust deve carregar essa string diretamente em um enum no proprio `AssetEntry`. O wire format continua string, mas o modelo carregado no runtime passa a ser tipado.
|
|
|
|
3. **Canon do nome**
|
|
O nome textual do codec no JSON nao e arbitrario por produtor. Ele deve seguir exatamente o canon definido pelo contrato. O canon fechado para este tema e `SCREAMING_SNAKE_CASE`, alinhado a `BankType`, e o packer deve seguir esse formato sem aliases livres.
|
|
|
|
4. **Variante inicial**
|
|
O unico codec canonico agora e `None`.
|
|
|
|
5. **Fim de `Raw`**
|
|
`Raw` nao deve mais existir como conceito no modelo.
|
|
|
|
6. **Codecs desconhecidos**
|
|
Nao devem ser empacotados. Se mesmo assim chegarem ao runtime, isso e erro de validacao do `AssetEntry` e o cartucho deve ser fechado antes de seguir.
|
|
|
|
7. **Escopo atual de codecs**
|
|
Como ainda nao existe codec real implementado, a primeira versao do enum pode ser minima e conter apenas `None`.
|
|
|
|
8. **Destino de `pipeline`**
|
|
`pipeline` nao tem valor operacional no runtime atual e pode ser descartado completamente desse lado.
|
|
|
|
### Leitura arquitetural dessas respostas
|
|
|
|
As respostas empurram a agenda para um contrato bem mais estrito do que o texto inicial sugeria:
|
|
|
|
- `codec` existe como conceito de dominio mesmo antes de haver codecs concretos alem de `None`;
|
|
- o JSON de `asset.pa` pode manter um discriminante simples e opaco, enquanto o runtime desserializa isso diretamente para enum e usa esse valor para escolher a interpretacao tipada de `metadata.codec`;
|
|
- a autoridade sobre o spelling do codec pertence ao contrato compartilhado, nao ao Studio isoladamente;
|
|
- o runtime nao deve carregar extensibilidade aberta para codecs desconhecidos;
|
|
- a compatibilidade futura deve ser dirigida pelo Studio e pelo empacotamento, nao por tolerancia dinamica no runtime;
|
|
- `pipeline` deixa de disputar espaco conceitual com `codec` no runtime.
|
|
|
|
Isso favorece um modelo de enum fechado, validado cedo e com semantica fail-fast.
|
|
|
|
## Criterio para Encerrar
|
|
|
|
Esta agenda pode ser encerrada quando houver consenso escrito sobre:
|
|
|
|
- o papel exato de `codec` no modelo de dominio do `AssetEntry`;
|
|
- a fronteira entre payload do codec e restante da metadata;
|
|
- a estrategia para codecs sem metadata adicional e para codecs desconhecidos;
|
|
- o shape string de `codec` no JSON e sua relacao com o enum carregado no runtime e com `metadata.codec`;
|
|
- o proximo passo normativo para transformar isso em decisao sem reabrir `DSC-0017`.
|
|
|
|
## Resolucao Provisoria
|
|
|
|
Ha consenso provisoriamente estabelecido sobre os seguintes pontos:
|
|
|
|
- `codec` deve existir como enum tipado no modelo do runtime;
|
|
- a variante inicial unica e `None`;
|
|
- `Raw` sai do contrato;
|
|
- codecs desconhecidos sao invalidos e devem falhar de forma fatal no carregamento do cartucho;
|
|
- `pipeline` pode ser descartado do runtime;
|
|
- o JSON de `asset.pa` deve serializar `codec` como string opaca;
|
|
- o runtime Rust deve desserializar essa string diretamente para enum no `AssetEntry`;
|
|
- o nome textual do codec no JSON deve seguir `SCREAMING_SNAKE_CASE`, e o Studio deve se conformar exatamente a ele;
|
|
- codec desconhecido deve falhar na validacao do `AssetEntry`, antes de qualquer carga efetiva.
|
|
|
|
O unico ponto em aberto passa a ser a politica de evolucao para o primeiro codec real com payload, preservando a distincao entre:
|
|
|
|
- discriminante string no JSON do asset; e
|
|
- shape tipado de `metadata.codec` no runtime.
|
|
|
|
## Resolucao
|
|
|
|
A agenda fica encerrada com a seguinte orientacao:
|
|
|
|
- `codec` permanece `string` no JSON de `asset.pa`;
|
|
- o runtime Rust deve desserializar essa string diretamente para enum no `AssetEntry`;
|
|
- o nome textual do codec segue `SCREAMING_SNAKE_CASE`, alinhado a `BankType`;
|
|
- `None` e a unica variante inicial;
|
|
- `Raw` sai do contrato;
|
|
- codec desconhecido falha na validacao do `AssetEntry` e fecha o cartucho;
|
|
- `pipeline` e descartado do runtime.
|
|
|
|
A evolucao para codecs com payload adicional fica explicitamente adiada para uma decisao futura motivada por um codec real.
|