--- 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.