0012 — API CRUD como 2ª camada edge (ao lado de views)¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-08 · Decidido em: 2026-07-08
Contexto. O pacote ingest era um pacote-deus: misturava o pipeline de ingestão XADM
(XadmController /api/v1/xadm → XadmService → XadmApplyService → parser + helpers) com os 13
controllers CRUD REST por-entidade (/api/v1/estoque, /contratos, …). Duas responsabilidades
distintas no mesmo pacote. A decisão 0011 já havia
estabelecido views como uma camada edge (apresentação, acima das features-motor, podendo
orquestrá-las).
Decisão. Extrair os 13 controllers CRUD para um pacote próprio api, classificado como uma
2ª camada edge — ao lado de views:
- Camadas edge (
views= UI Thymeleaf;api= REST CRUD): ficam acima das features-motor e podem depender delas. Ex.: os controllers deapiusam oEscritaPorChaveNaturaldeingest. XadmControllere o pipeline de ingestão permanecem emingest(não é CRUD por-entidade; é o endpoint de ingestão em massa, acoplado aXadmService).- Guarda ArchUnit:
apientra no arrayFEATURES(portantocore/comumnão dependem deapi), mas fora deENGINE_FEATURES— a regra de independência vale só para as 4 features-motor (ingest/powersync/push/export); edges podem depender delas.
Consequências / trade-offs.
ingestfica com uma responsabilidade (a ingestão XADM); a API CRUD tem casa própria.- Aceita-se
api→ingest(o helperEscritaPorChaveNaturalfica emingest) — coerente com a classificação edge. Alternativa preterida: tratarapicomo feature-motor peer e mover o helper paracomum; rejeitada por ser mais movimentação e porque a CRUD por-entidade não "compõe" features como aviewsfaz — é uma superfície de dados, apresentação. - As rotas (
@Controller("/api/v1/…")) não mudam — a extração é reorganização de pacote Java pura, sem mudança de contrato/comportamento (gate: 572 testes verdes). - Surge um segundo caso de "edge depende de engine" não-guardado por regra dedicada (o inverso, engine→edge, hoje não é violado). Uma guarda "engine ⊥ edge" foi deferida (custo×valor).