Cosmos.Impuestos.Contratos 0.20.0-beta

This is a prerelease version of Cosmos.Impuestos.Contratos.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Cosmos.Impuestos.Contratos --version 0.20.0-beta
                    
NuGet\Install-Package Cosmos.Impuestos.Contratos -Version 0.20.0-beta
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cosmos.Impuestos.Contratos" Version="0.20.0-beta" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cosmos.Impuestos.Contratos" Version="0.20.0-beta" />
                    
Directory.Packages.props
<PackageReference Include="Cosmos.Impuestos.Contratos" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cosmos.Impuestos.Contratos --version 0.20.0-beta
                    
#r "nuget: Cosmos.Impuestos.Contratos, 0.20.0-beta"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Cosmos.Impuestos.Contratos@0.20.0-beta
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cosmos.Impuestos.Contratos&version=0.20.0-beta&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Cosmos.Impuestos.Contratos&version=0.20.0-beta&prerelease
                    
Install as a Cake Tool

Cosmos.Impuestos.Contratos

Eventos públicos de integración de Cosmos Impuestos (IPublicEvent). Un consumidor en otro bounded context referencia este paquete y publica/consume estos eventos sobre el bus para integrarse con Impuestos de forma eventual (async request-reply, event-carried state transfer y avisos de cambio).

El paquete distribuye los tipos C# de los contratos. No incluye stubs gRPC: la integración es por eventos sobre el bus de mensajería, no por RPC síncrono.


Instalación

<PackageReference Include="Cosmos.Impuestos.Contratos" Version="0.19.0-beta" />

Depende de Cosmos.EventDriven.Abstractions (IPublicEvent), Cosmos.Types y Cosmos.Types.IdentificacionesLegales.

Cambios incompatibles

Las versiones se listan de la más nueva a la más vieja. Una entrada está acá cuando obliga a shippear código para seguir siendo correcto, compile o no: una remoción, un cambio de forma, o un valor nuevo en un enum sobre el que se discrimina. Por ese último caso una entrada puede ser incompatible sin cambiar ninguna firma — ver «Miembros de enum agregados» al final.

0.20.0-beta — la configuración estándar sale de ediciones publicadas

El estándar fiscal de cada país deja de ser una siembra y pasa a ser una edición inmutable, con número y huella, construida desde el contenido que publica el equipo fiscal. Lo que cambia para quien consume:

  • Códigos internos. Los códigos de clasificaciones, condiciones, regímenes, definiciones y calidades fiscales que viajan en los eventos (las trazas del cálculo) son los internos de la tabla de homologación: GRAVADO_TARIFA_GENERAL en vez de GRAV_19, REGIMEN_TRIBUTARIO en vez de regimenTributario. Quien guarde o compare códigos tiene que migrarlos con esa tabla, que vive en el repositorio de Impuestos, un archivo por catálogo y país: contenido/declarado/ (sección homologacion: código de la fuente → código interno). Los cálculos y perfiles anteriores conservan el nombre de la fuente y se siguen interpretando.
  • Vigencias semiabiertas. Toda vigencia es [desde, hasta): hasta es el primer día en que deja de regir. Un tramo con hasta = desde nunca rigió.
  • Se retira la réplica de clasificaciones por el bus: ClasificacionTributariaPublicada, ClasificacionTributariaDesactivada y ReplicaDeClasificacionesSolicitada, con sus topics. Ningún servicio la consumía: las clasificaciones de un país se leen por HTTP en la API de consultas. Las suscripciones que el Terraform de otros repos crea sobre esos topics quedan sin publicador y se pueden borrar.
  • Configuracion se conserva (Estandar / Personalizado).

Para el front (API HTTP, fuera de este paquete; detalle en el ADR-004 «Contrato afectado»): las excepciones se registran con los endpoints nuevos (decisiones de tratamiento con vigencia, suprimir y cambiar el fin de una tarifa, convenios), la cabecera de un tributo o una clasificación de la edición no se edita (422), desactivar acepta desde, las lecturas traen todos los tramos y marcan las supresiones, y la bandeja de revisión se consulta en GET /bandeja-de-revision/{pais}.

0.19.0-beta — MotivoExclusion gana TarifaNoConfigurada y ConvenioExime

Dos motivos de descarte nuevos, al final del enum, así que los existentes conservan su ordinal. Viajan en LineaDescartada.MotivoExclusion y en CondicionEvaluada.MotivoDescarte. Qué significa cada uno está en la tabla de «Miembros de enum agregados».

Es incompatible aunque no cambie ninguna firma: quien muestra un descarte lo rotula según su motivo, y un motivo que no reconoce cae al rótulo por defecto sin error. El descarte sigue trayendo su Explicacion, que sí nombra la causa; lo que se pierde es el rótulo corto.

En la misma versión, aditivo: TarifaUsada porta ConvenioUsado? Convenio, nullable con default y al final. Viene poblado cuando la tarifa la fijó un convenio para evitar la doble imposición, con el país contraparte (código ISO 3166-1 alfa-2, porque puede ser un país donde el productor no opera), el nombre del convenio y su instrumento normativo. TarifaUsada viaja en la ConfiguracionUsada de RegistroTributarioEntregado y de ConfirmacionTributariaRealizada.

0.18.0-beta — TipoTarifa gana PorMil

Una tarifa cuyo valor se lee por mil. Viaja en TarifaUsada, LineaDesglose y LineaDescartada. Miembro nuevo al final del enum, así que Porcentaje y Especifica conservan su ordinal.

La unidad de la Tarifa depende del tipo, y con PorMil deja de ser una fracción:

TipoTarifa Qué es Tarifa Ejemplo
Porcentaje fracción decimal 0.19 es 19 %
Especifica monto absoluto en la moneda del registro 1900 son 1.900
PorMil el número en ‰, no una fracción 4.14 es 4,14 ‰

Rompe a quien haga switch exhaustivo sin arm por defecto y, más callado, a quien formatee la tarifa según su tipo: el tipo que no reconoce cae al caso por defecto y pierde la unidad sin error, y quien lo trate como Porcentaje (× 100) muestra 4.14 como 414 %. Es ese segundo caso —el que ninguna firma delata— el que la vuelve incompatible y no aditiva.

0.15.0-beta — cierre de la reestructuración a agregados por elemento

Tres cambios en la misma versión.

MotivoRechazoCalculo.AtributoFiscalFaltante → CalidadFiscalFaltante. Conserva su ordinal, así que el wire no cambia y quien deserialice por número no ve nada. Rompe fuente a quien nombre el miembro en código; se arregla con el rename.

ConfiguracionUsada pierde CatalogoId. Viaja en RegistroTributarioEntregado.ConfiguracionUsada y en ConfirmacionTributariaRealizada.ConfiguracionUsada, los dos únicos eventos que la portan; ningún evento de cálculo la lleva. El catálogo por país dejó de existir —la configuración tributaria pasó a un stream por elemento— así que el campo venía viajando Guid.Empty. Es el primer parámetro posicional del record, así que rompe fuente a quien construya una ConfiguracionUsada, y deja de serializar la clave catalogoId para quien la lea.

La misma remoción aplica al response de GET /registros-tributarios/{subDominio}/{transaccionId}, que no lleva versión semántica: ahí la clave desaparece sin más señal que esta nota. No hay sustituto porque no hay dato que sustituir. La procedencia de la configuración —qué stream de tributo, estándar o del tenant, produjo cada línea— no viaja por el bus: se obtiene por ese mismo GET, en configuracionUsada.tributosUsados, que llega nulo en los registros cuya traza no la congeló (los anteriores a la reestructuración).

ConfiguracionTributariaNoEncontrada vuelve a emitirse. Entre el despliegue de la reestructuración y esta versión, un cálculo contra un país sin tributos configurados no rechazaba: publicaba CalculoTributarioRealizado con el desglose vacío, o sea un cálculo que se veía exitoso y no llevaba nada. Vuelve a llegar CalculoTributarioRechazado con ese motivoCodigo y un motivoDetalle que nombra qué configuración falta. No agrega ningún miembro al enum: lo que cambia es que el valor vuelve a llegar. Rompe a quien haya adaptado su código a lo observado en esa ventana, tratando el desglose vacío como respuesta válida. Que el desglose quede vacío sigue siendo un desenlace legítimo cuando la configuración sí está y ningún tributo aplica: ése no rechaza.

0.14.0-beta — Naturaleza gana Provision

La tercera dirección de un tributo frente al valor de la operación. Viaja en LineaDesglose.Naturaleza y LineaDescartada.Naturaleza. Miembro nuevo al final del enum, así que los dos valores existentes conservan su ordinal.

Rompe a quien haga switch exhaustivo sin arm por defecto y, más callado, a quien particione un desglose en dos grupos por naturaleza: una partición binaria deja las provisiones afuera sin error, y es ese segundo caso —el que ninguna firma delata— el que la vuelve incompatible y no aditiva.

La configuración fiscal estándar todavía no declara ningún tributo como provisión, pero el alta y la modificación de tributo sí admiten la naturaleza nueva: una configuración propia puede emitirla en cuanto esta versión esté desplegada del lado del productor. Conviene adoptarla antes de eso, no después.

0.12.0-beta — Explicacion queda en las cinco partes del argumento

{ Efecto, Hechos, Regla, Contraste?, Advertencia? }. Se van Causa y Detalle, la prosa corrida que 0.11.0 conservó deprecada; quien quiera prosa encadena las partes que necesite. Y se va Autoridad, que nunca pudo ser no-nula: ninguna traza congelada porta la fuente normativa de la regla. El día que el catálogo la incorpore, Autoridad vuelve como campo nullable al final — aditivo para quien la lea, pero cambia la firma del constructor, así que quien construya una Explicacion recompila.

Contraste y Advertencia quedan sin valor por omisión: siguen siendo nullables, pero se pasan siempre. Rompe a quien lea Causa, Detalle o Autoridad, y a quien construya una Explicacion. Impuestos no persiste la explicación (la regenera on-read desde la traza congelada), así que no hay migración de este lado; un consumidor que la haya guardado encuentra las claves de más al deserializar.

0.11.0-beta — Explicacion pasa a forma estructurada

De (Causa, Detalle) a { Efecto, Hechos, Regla, Autoridad?, Contraste?, Advertencia? }: el resultado observable para el lector, los hechos que lo fundan, la norma que autoriza el paso de unos a otro, su fuente cuando la traza la conserva, el desenlace alternativo, y el alcance que la explicación no verificó.

Causa y Detalle se conservan deprecados y derivados de esa estructura, para que un consumidor que todavía no la renderice siga recibiendo texto coherente; se remueven en 0.12.0. Rompe a quien construya una Explicacion; no rompe a quien solo la lea.

0.7.0-beta — el país de los eventos públicos pasa a VO validado

Jurisdiccion.Pais (en ClasificacionTributariaPublicada / Desactivada) y ReplicaDeClasificacionesSolicitada.Pais pasan de enum a VO con wire objeto { "codigo": "CO" }. Cambia la forma serializada del campo país — coordinación cross-BC con los consumidores.

0.6.0-beta — la identidad fiscal pasa al tipo compartido IdentificacionLegal

La identificación del emisor y la contraparte deja de ser el modelo local Compartidos.IdentificacionFiscal (país como enum + número plano) y pasa a ser Cosmos.Types.IdentificacionesLegales.IdentificacionLegal (del paquete Cosmos.Types). Afecta a CalculoTributarioSolicitado, SolicitarConfirmacionTributaria y al modelo EntidadFiscal de las respuestas.

Cambia el wire (un consumidor de una versión previa se rompe hasta adoptar este formato):

  • El país viaja como objeto { "codigo": "CO" } (antes era un entero del enum).
  • El número se acompaña de tipo de documento y dígito de verificación, y se valida contra el catálogo del país (tipo país-scoped × número × DV). La igualdad de la identidad recae en (tipo, número, país); el dígito de verificación no participa.

El borde de Impuestos resuelve el perfil por la clave canónica {país}:{tipoDocumento}:{número}, así que el número que se envíe debe corresponder al del alta del perfil (el paquete normaliza el número al construir la identidad).

Miembros de enum agregados

Índice completo de las altas de miembro, que es la clase de cambio que no delata ninguna firma. Ningún alta cambia una firma y todas se agregan al final, así que los valores existentes conservan su ordinal y quien deserialice por número no cambia. Aun así rompen a quien haga switch exhaustivo sin arm por defecto: si ese arm lanza, el mensaje muere en vez de degradarse.

Por eso la columna «Etiqueta» no siempre dice lo mismo que el efecto. Una versión se etiqueta incompatible cuando el alta abre además un modo de rotura que ninguna firma delata —una partición o un formateo por tipo que deja el miembro nuevo afuera sin error—, y aditiva cuando el switch es el único riesgo, porque el consumidor no ramifica por ese enum — pero para un consumidor con switch exhaustivo las dos obligan a shippear código igual. Si tenés un arm por defecto que lanza, tratá las dos filas como incompatibles.

MotivoRechazoCalculo es el caso donde esto pasa más seguido: su conjunto es interno al productor para su observabilidad —el consumidor no ramifica por el código, solo lo registra o muestra el detalle—, así que crece sin coordinación, siempre agregando al final.

Versión Etiqueta Enum Miembro Qué significa
0.19.0-beta incompatible MotivoExclusion TarifaNoConfigurada El tarifario de un tributo que declara cerrada su cobertura no tiene ninguna tarifa, en ninguna vigencia, para el concepto: el concepto no es de su alcance y la línea se descarta en vez de rechazar el cálculo. Cualquier otra tarifa faltante —en un tributo de cobertura abierta, o un hueco de vigencia en un concepto que el tarifario sí incluye— sigue rechazando el cálculo con TarifaNoVigente. Ver 0.19.0-beta arriba.
0.19.0-beta incompatible MotivoExclusion ConvenioExime El convenio para evitar la doble imposición con el país de residencia fiscal del beneficiario fija tarifa cero para la retención. La línea se descarta, y la condición del convenio queda en la traza con este mismo motivo. Ver 0.19.0-beta arriba.
0.18.0-beta incompatible TipoTarifa PorMil Una tarifa cuyo valor se lee por mil. La Tarifa de la línea llega en ‰, no como fracción: 4.14 significa 4,14‰, y quien la trate como porcentaje (× 100) la muestra como 414 %. Viaja en TarifaUsada, LineaDesglose y LineaDescartada. Además del switch, rompe —más callado— a quien formatee la tarifa según su tipo: un tipo que no reconoce cae al caso por defecto y pierde la unidad sin error. Ver 0.18.0-beta arriba.
0.17.0-beta aditiva MotivoRechazoCalculo JurisdiccionNoEncontrada Una ubicación de la transacción (sede emisora, sede de contraparte o lugar de ejecución) no referencia ninguna jurisdicción vigente del país a la fecha, así que el cálculo no se puede computar. Antes ese caso no tenía desenlace: la traducción lanzaba, el mensaje moría en dead-letter y el solicitante esperaba indefinidamente — mismo defecto que 0.13.0-beta arregló para MotivoRechazoEntrega. El defecto está en los datos maestros de jurisdicciones del productor, no en la solicitud: no invita a reintentar sin corregirlos.
0.14.0-beta incompatible Naturaleza Provision La tercera dirección de un tributo frente al valor de la operación (qué es y qué se sigue de ella está en el propio enum, que es su sede). Viaja en LineaDesglose.Naturaleza y LineaDescartada.Naturaleza. Además del switch, rompe —más callado— a quien particione un desglose en dos grupos por naturaleza: la partición binaria deja las provisiones afuera sin error. Ver 0.14.0-beta arriba.
0.13.0-beta aditiva MotivoRechazoEntrega RegistroInexpresable El registro existe y la solicitud era válida, pero porta un valor sin equivalente conocido en un campo que el contrato necesita. Antes ese caso no tenía desenlace: la traducción lanzaba, el mensaje moría en dead-letter y el solicitante esperaba indefinidamente. A diferencia de RegistroNoEncontrado, no invita a reintentar: el defecto está en lo ya persistido del lado del productor.

Otras tres versiones agregaron eventos o campos, no miembros, y son aditivas sin reserva: 0.16.0-beta (evento saliente nuevo PerfilTributarioActualizado; ver «Aviso de cambio del perfil tributario» más abajo), 0.10.0-beta (CalculoTributarioRealizado porta ExplicacionDelCalculo, nullable con default) y 0.8.0-beta (los tres eventos del flujo de cálculo portan un Guid Correlacion, token opaco que el productor devuelve verbatim para que el solicitante descarte respuestas superseded; los mensajes legacy deserializan a Guid.Empty).

Eventos

Namespace: Cosmos.Impuestos.Contratos.Eventos. Modelos compartidos en Cosmos.Impuestos.Contratos.Compartidos; enums en Cosmos.Impuestos.Contratos.Enums.

Evento Dirección Propósito
CalculoTributarioSolicitado entrante Solicita la cotización tributaria de unos conceptos. Impuestos resuelve el contexto y ejecuta el motor sin mutar estado.
CalculoTributarioRealizado saliente Resultado de la cotización (aplicados/descartados), correlacionado por ReferenciaOrigen.
RegistroTributarioSolicitado entrante Solicita confirmar un registro tributario (gravamen/desgravamen).
RegistroTributarioCreado saliente Relay fiel del registro persistido, correlacionado por ReferenciaOrigen.
PerfilTributarioActualizado saliente Aviso de que el perfil tributario de un tercero cambió en algo que afecta el cálculo. No lleva el estado del perfil.

ReferenciaOrigen es una correlación opaca que define el consumidor (p. ej. su identificador de transacción) y que Impuestos eco-devuelve en el evento de respuesta para enrutar el resultado.

Aviso de cambio del perfil tributario

PerfilTributarioActualizado se publica en el topic CanalImpuestos.TopicPerfilTributarioActualizado y lleva tres datos: la identificación del tercero (IdentificacionLegal), el id del perfil y FechaDelCambio. Es un aviso, no una transferencia de estado: no lleva calidades fiscales, actividades económicas ni razón social. Quien reaccione vuelve a pedir el cálculo, y el cálculo lee el perfil vigente.

  • Uno por comando, no uno por cambio: un comando que persiste varios cambios a la vez avisa una sola vez.
  • Solo cuando lo persistido afecta el cálculo. Un cambio de razón social no avisa, tampoco un aseguramiento del perfil que no cambió nada, y un comando rechazado no avisa nunca. La creación del perfil sí avisa: antes de ella el cálculo rechazaba por perfil no encontrado.
  • FechaDelCambio es cuándo quedó persistido el cambio, no la vigencia del dato tributario, que puede ser pasada o futura. Sirve para ordenar avisos, no para decidir desde cuándo rige el perfil.
  • El envelope lleva la identidad de quien originó el cambio: tenant, usuario y membresía de organización.
  • El aviso no reemplaza al recálculo a demanda, por dos razones. Hoy avisan los cambios que entran por la API HTTP, y los que entran por el servidor MCP de Impuestos todavía no. Y la entrega del aviso no está garantizada como atómica con el cambio: un cambio persistido puede quedar sin su aviso.

Consulta de la explicación de una cotización

Una cotización no se persiste como registro, pero deja su traza estructurada mientras la obligación sigue pendiente. La explicación se redacta al leer, con la misma redacción que el registro confirmado.

GET /explicaciones-de-cotizacion/{referenciaOrigen}?correlacion={guid}

referenciaOrigen es la misma referencia opaca con que se solicitó el cálculo, sin reinterpretar; una referencia con / no matchea la ruta y da 404 del ruteo. correlacion es la aplicada por quien consume: la del cálculo cuyo desglose muestra, no la vigente.

Estado Cuándo
200 Hay traza para la referencia y su correlación coincide. El cuerpo es la explicación redactada, con la de las líneas descartadas.
400 Falta correlacion o no es un Guid.
404 No hay traza para la referencia, o la traza guardada es de otra correlación. Los dos casos son indistinguibles a propósito: la consulta falla cerrado y nunca devuelve prosa de un cálculo distinto al que se muestra.

Hay a lo sumo una traza por referencia: recotizar la reemplaza, así que un cliente con una correlación anterior recibe 404 y debe degradar. La traza se elimina, en la medida de lo posible, cuando se confirma el registro tributario de esa referencia (si la eliminación falla la confirmación sigue y la traza puede quedar); desde entonces la explicación se obtiene por GET /registros-tributarios/{subDominio}/{transaccionId}.

Uso

using Cosmos.Impuestos.Contratos.Eventos;

// publicar una solicitud
await bus.PublishAsync(new CalculoTributarioSolicitado(referenciaOrigen, /* … */));

// consumir el resultado
public Task Handle(CalculoTributarioRealizado evento) { /* enrutar por evento.ReferenciaOrigen */ }

El nombre del servicio/cola productor para suscribirse a los eventos entrantes lo define el wiring del consumidor (SuscribirseAServicio).

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Cosmos.Impuestos.Contratos:

Package Downloads
Cosmos.Impuestos.Mensajeria

Extensiones de Wolverine para integrarse con Cosmos Impuestos sobre Azure Service Bus (topología topic-por-evento): publica las solicitudes tributarias a sus topics y, por separado, permite escuchar los resultados y broadcasts de Impuestos por una subscription propia. Publicar y escuchar son capacidades componibles para que un servicio de borde pueda solicitar sin suscribirse a los resultados.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.46.0-beta 144 10/25/2026
0.45.0-beta 74 10/25/2026
0.44.0-beta 72 10/21/2026
0.43.0-beta 104 10/20/2026
0.42.0-beta 118 10/15/2026
0.41.0-beta 163 10/13/2026
0.40.0-beta 119 10/11/2026
0.39.0-beta 96 10/10/2026
0.38.0-beta 84 10/9/2026
0.37.0-beta 186 10/6/2026
0.36.0-beta 89 10/6/2026
0.35.0-beta 67 10/6/2026
0.33.0-beta 71 10/2/2026
0.32.0-beta 195 10/1/2026
0.31.0-beta 108 10/1/2026
0.30.0-beta 65 9/30/2026
0.29.0-beta 61 9/30/2026
0.28.0-beta 65 9/30/2026
0.27.0-beta 248 9/30/2026
0.20.0-beta 69 9/25/2026
Loading failed

0.20.0-beta (incompatible) — la configuración estándar sale de ediciones publicadas. Los códigos de
clasificaciones, condiciones, regímenes, definiciones y calidades fiscales que viajan en los eventos son
los internos de la tabla de homologación (p. ej. GRAVADO_TARIFA_GENERAL en vez de GRAV_19); toda vigencia
es [desde, hasta) con hasta = el primer día en que deja de regir. Se retira la réplica de clasificaciones por el
bus (ClasificacionTributariaPublicada, ClasificacionTributariaDesactivada, ReplicaDeClasificacionesSolicitada y sus
topics), que ningún servicio consumía. Guía de migración en el README.

0.19.0-beta (incompatible) — MotivoExclusion gana TarifaNoConfigurada y ConvenioExime (al final,
ordinales 8 y 9). Viajan en LineaDescartada y CondicionEvaluada. Rompe a quien rotule el descarte según
su motivo: el que no reconoce cae al rótulo por defecto sin error. Aditivo en la misma versión:
TarifaUsada porta ConvenioUsado? Convenio (país contraparte, nombre e instrumento normativo del
convenio que fijó la tarifa), nullable con default.

0.18.0-beta (incompatible) — TipoTarifa gana PorMil (al final, ordinal 2). Su Tarifa llega en ‰
(4.14 = 4,14‰), no como fracción: multiplicarla por cien la muestra como 414 %. Viaja en TarifaUsada,
LineaDesglose y LineaDescartada. Rompe a quien haga switch exhaustivo sin arm por defecto y, sin
error, a quien formatee la tarifa según su tipo: el tipo que no reconoce cae al caso por defecto y
pierde la unidad.

0.17.0-beta (aditiva) — MotivoRechazoCalculo gana JurisdiccionNoEncontrada (al final, ordinal 6).
Un cálculo cuya ubicación no resuelve jurisdicción ahora publica CalculoTributarioRechazado en vez
de morir en dead-letter.

0.16.0-beta (aditiva) — PerfilTributarioActualizado, un evento saliente nuevo con su topic
(CanalImpuestos.TopicPerfilTributarioActualizado).

Avisa que el perfil tributario de un tercero cambió en algo que afecta el cálculo. Lleva solo la
identificación del tercero, el id del perfil y la fecha del cambio: NO lleva el estado del perfil, así
que quien reaccione vuelve a pedir el cálculo. Se emite uno por comando, no uno por cambio. Un cambio de
razón social no avisa, un aseguramiento que no movió nada tampoco, y la creación del perfil sí.
FechaDelCambio es cuándo quedó persistido el cambio, no la vigencia del dato tributario. El aviso no
reemplaza al recálculo a demanda, por dos razones: hoy avisan los cambios que entran por la API HTTP y no
los que entran por el servidor MCP de Impuestos, y la entrega del aviso no está garantizada como atómica
con el cambio.

No cambia ningún tipo existente. Quien venga de 0.14.0-beta o anterior pasa por 0.15.0-beta, que SÍ es
incompatible: ver README.md.

Historial completo de cambios incompatibles, y el índice de los miembros de enum agregados: README.md.