# 02 — Regras de domínio (commerce-vc1)

> Fonte de verdade: `docs/blueprint/_BRIEF.md`. Produto aprovado: `docs/sources/PRODUCTS-vc1.md`. Simulações e padrões comerciais: `docs/blueprint/01-BUSINESS-MODEL.md`.
>
> Identificadores em inglês. Prosa em português brasileiro. Enums **exatos** do brief. O que não está no brief/PRODUCTS está marcado `PADRÃO PROPOSTO` e listado em `## Itens para 10-DECISIONS`.
>
> Módulos = schemas PG / bounded contexts: `pricing`, `catalog`, `sales`, `customers`, `telco`, `rating`, `billing`, `fiscal`, `tenancy`, `identity`, `integration`, `audit`.

Cada regra tem: **ID**, **enunciado**, **exemplo**, **onde é aplicada**, **origem**.

---

## 1. Catálogo de regras

### 1.1 Base de preços e faixas

#### RN-001 — Relação VC1→revenda é sempre consumo mínimo
- **Enunciado:** A VC1 não vende pacote fechado para a revenda. Toda revenda ativa contrata uma faixa (`vc1_tier_id`) com `commitment_cents` e tarifas unitárias (DID, canal, minuto `landline_br`, minuto `mobile_br`).
- **Exemplo:** Revenda NetSul na faixa Growth, compromisso R$ 2.000, DID R$ 8,00 — mesmo que use só R$ 88, paga o mínimo (modo `reseller_invoices`) ou abate a falta no repasse (modo `vc1_invoices`).
- **Onde é aplicada:** `tenancy`, `pricing`, `billing`.
- **Origem:** PRODUCTS §1; brief §1.

#### RN-002 — Base de preços versionada
- **Enunciado:** As faixas VC1 existem dentro de `pricing.price_bases` / `price_base_versions` com data de vigência (`effective_at`). Não há “tarifa solta” no plano da plataforma.
- **Exemplo:** Versão `2026-11-01` publicada; rascunho `2026-12-01` ainda não vale para contratos novos.
- **Onde é aplicada:** `pricing` (Filament staff).
- **Origem:** PRODUCTS §8 (resolvido); brief §1.

#### RN-003 — Só a versão publicada vale para contrato novo
- **Enunciado:** `PADRÃO PROPOSTO`: existe no máximo uma versão `published` vigente. Contratos e clones de faixa da revenda leem essa versão. Rascunhos são invisíveis à revenda.
- **Exemplo:** Staff edita rascunho baixando móvel para R$ 0,09; revendas continuam vendo R$ 0,12 até publicar.
- **Onde é aplicada:** `pricing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-01).

#### RN-004 — Publicar torna a versão imutável
- **Enunciado:** `PADRÃO PROPOSTO`: após `published`, a versão não se edita. Correção = nova versão. Quem publica: `vc1_admin`.
- **Exemplo:** Erro de R$ 0,05 vs R$ 0,50 no fixo → nova versão, não UPDATE in-place.
- **Onde é aplicada:** `pricing`, `audit`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-01).

#### RN-005 — Faixa maior, tarifa menor ou igual
- **Enunciado:** `PADRÃO PROPOSTO`: o editor recusa publicar se uma faixa de compromisso maior tiver qualquer unitário **estritamente maior** que uma faixa inferior (não-regressão). Igualdade é permitida.
- **Exemplo:** Starter R$ 1.000 DID R$ 10; Growth R$ 2.000 DID R$ 8 — ok. Growth DID R$ 11 — recusa.
- **Onde é aplicada:** `pricing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-02). PRODUCTS diz “quanto maior o compromisso, menor a tarifa” sem tratar empate.

#### RN-006 — Campos obrigatórios da faixa VC1
- **Enunciado:** Toda `vc1_tiers`: `name`, `min_commitment_cents`, `unit_did_cents`, `unit_channel_cents`, `unit_landline_cents`, `unit_mobile_cents`. Cadência fixa 30/6 (`cadence_min_s=30`, `cadence_inc_s=6`). `fidelity_default_months` opcional.
- **Exemplo:** PRODUCTS §7 usa DID 8, canal 20, fixo 0,05, móvel 0,12 (valores ilustrativos da faixa).
- **Onde é aplicada:** `pricing`.
- **Origem:** PRODUCTS §2.2, §3; brief §1.

#### RN-007 — Faixa contratada não muda sozinha
- **Enunciado:** Consumo real acima do mínimo **não** promove a faixa. Para tarifa menor, a revenda (ou o cliente no plano commitment) aumenta o compromisso e recontraia a faixa.
- **Exemplo:** Revenda compromisso R$ 2.000 consome R$ 2.714 — continua na mesma faixa; fatura R$ 2.714.
- **Onde é aplicada:** `billing`, `catalog`, `tenancy`.
- **Origem:** PRODUCTS §2.3.

#### RN-008 — Efeito de nova base em contratos existentes
- **Enunciado:** `PADRÃO PROPOSTO`: publicar nova versão **não** altera `commitment_cents` nem unitários já gravados na assinatura da revenda. A revenda pode aderir à nova versão no início do próximo ciclo (aceite explícito no painel).
- **Exemplo:** Em 1º de março a VC1 baixa o móvel; NetSul só paga o novo móvel se aderir; senão permanece o snapshot.
- **Onde é aplicada:** `pricing`, `tenancy`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-03).

#### RN-009 — Dinheiro em centavos
- **Enunciado:** Todo valor monetário persiste em `*_cents bigint`. Documentos e UI convertem para R$ com duas casas.
- **Exemplo:** R$ 8,00 → `800`.
- **Onde é aplicada:** todos os schemas.
- **Origem:** brief §3 (convenções).

#### RN-010 — Uma faixa contratada por revenda
- **Enunciado:** `resellers.vc1_tier_id` é único. Não há mix de faixas VC1 na mesma revenda.
- **Exemplo:** NetSul não pode ter DID na Growth e minuto na Scale.
- **Onde é aplicada:** `tenancy`.
- **Origem:** PRODUCTS §1; brief entidades.

---

### 1.2 Faixas da revenda e markup

#### RN-011 — Clone + markup percentual
- **Enunciado:** `pricing.reseller_tier_tables` / `reseller_tier_rows` partem das faixas VC1 vigentes com `markup_pct` definido pela revenda. Unitários resultantes = unitário VC1 × (1 + markup/100), depois edição linha a linha.
- **Exemplo:** Markup 20% sobre DID R$ 8,00 → R$ 9,60; a revenda altera só o móvel para R$ 0,15.
- **Onde é aplicada:** `pricing` (painel revenda).
- **Origem:** PRODUCTS §6.

#### RN-012 — Edição faixa a faixa
- **Enunciado:** Cada linha (`unit_did_cents`, `unit_channel_cents`, `unit_landline_cents`, `unit_mobile_cents`, `min_commitment_cents` de venda) é editável independentemente após o markup.
- **Exemplo:** Linha Starter com markup 20% e DID override R$ 9,00 (abaixo do markup, ainda acima do custo).
- **Onde é aplicada:** `pricing`.
- **Origem:** PRODUCTS §6.

#### RN-013 — Venda abaixo do custo permitida
- **Enunciado:** `unit_*_cents` de venda pode ser menor que o unitário de custo VC1 da faixa **contratada da revenda**. O sistema **não** recusa o save.
- **Exemplo:** Custo móvel R$ 0,12; venda R$ 0,10. Plano grava com flag de margem negativa.
- **Onde é aplicada:** `pricing`, `catalog`.
- **Origem:** PRODUCTS §5.

#### RN-014 — Alerta de margem negativa, sem bloqueio
- **Enunciado:** Ao salvar linha ou plano com sell < cost, gera evento/badge para a revenda e para o staff VC1. Não impede publicação nem o funil.
- **Exemplo:** Plan builder mostra “margem negativa no móvel”; `negative_margin_acknowledged_at` preenchido se a UI exigir ciência (`PADRÃO PROPOSTO` D-DOM-04: exige acknowledge).
- **Onde é aplicada:** `catalog`, `audit`.
- **Origem:** PRODUCTS §5; PADRÃO PROPOSTO no acknowledge.

#### RN-015 — Custo do cliente é sempre a faixa VC1 da revenda
- **Enunciado:** `cost_cents` de um CDR/DID/canal do cliente usa as tarifas da **faixa contratada da revenda com a VC1**, não a linha de venda nem a faixa que o cliente escolheu.
- **Exemplo:** Cliente no “mínimo R$ 5.000” de venda; a revenda está na Growth R$ 2.000. Custo do minuto fixo = R$ 0,05 da Growth, não o da Scale.
- **Onde é aplicada:** `rating`.
- **Origem:** PRODUCTS §2.3 (mínimo da revenda = soma do custo); PLAN rating 2 níveis.

#### RN-016 — Venda do cliente commitment usa a linha da tabela da revenda
- **Enunciado:** `sell_cents` no plano `kind=commitment` usa `reseller_tier_rows` da faixa **travada no plano** (`locked_tier_id`).
- **Exemplo:** Plano “mínimo R$ 1.000” trava a linha Starter de venda (DID R$ 9,60).
- **Onde é aplicada:** `catalog`, `rating`.
- **Origem:** PRODUCTS §2.2.

#### RN-017 — Snapshot na assinatura
- **Enunciado:** `PADRÃO PROPOSTO`: ao contratar, a assinatura grava snapshot dos unitários de venda e do custo vigente. Mudança posterior na tabela da revenda **não** altera assinaturas ativas até o início do ciclo seguinte (e só se a revenda marcar “aplicar novas tarifas”).
- **Exemplo:** Markup sobe de 20% para 30% no dia 12; clientes já ativos só sentem no próximo ciclo se a revenda aplicar.
- **Onde é aplicada:** `customers.subscriptions`, `pricing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-05).

#### RN-018 — Tabela da revenda deve cobrir todas as faixas publicadas
- **Enunciado:** `PADRÃO PROPOSTO`: para cada `vc1_tiers` vigente existe uma `reseller_tier_rows`. Não se apaga linha. Desativar oferta de uma faixa ao cliente = flag `offered=false` na linha, não delete.
- **Exemplo:** VC1 cria faixa Enterprise; o job de publicação cria a linha da revenda com o `markup_pct` padrão da tabela.
- **Onde é aplicada:** `pricing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-06).

---

### 1.3 Planos pacote

#### RN-019 — Preço mensal fechado
- **Enunciado:** `plan.kind=package` exige `sell_price_cents` > 0. Não usa `max(consumo, mínimo)` no cliente.
- **Exemplo:** Avançado R$ 450,00 / mês.
- **Onde é aplicada:** `catalog`.
- **Origem:** PRODUCTS §2.1.

#### RN-020 — Quotas incluídas
- **Enunciado:** `plan_quotas`: `included_dids`, `included_channels`, franquia em segundos. DID/canal dentro do incluído não geram linha unitária.
- **Exemplo:** 2 DIDs e 5 canais inclusos; o 3º DID é extra (RN-026).
- **Onde é aplicada:** `catalog`, `billing`.
- **Origem:** PRODUCTS §2.1.

#### RN-021 — Franquia `separate` ou `pooled`
- **Enunciado:** `plan.franchise_mode=separate` usa `franchise_landline_seconds` e `franchise_mobile_seconds`. `pooled` usa `franchise_total_seconds` (fixo+móvel somados).
- **Exemplo:** Basic 200 min pooled; Avançado 2.000 fixo + 1.500 móvel.
- **Onde é aplicada:** `catalog`, `rating`, `telco`.
- **Origem:** PRODUCTS §2.1. Enum brief: `separate`, `pooled`.

#### RN-022 — Excedente `charge` ou `block` por plano
- **Enunciado:** `plan.overage_policy=charge` continua a originação e cobra o excedente pelas tarifas `overage_*_cents_per_min` do plano (snapshotted na assinatura). `block` esgota franquia → **`TelcoPort.blockOutgoingCalls`** para **toda** a originação da assinatura (padrão). Bloqueio por destino/classe fica **VERIFICAR** (depende de ACL por classe no SipPulse).
- **Exemplo:** Ver simulação 01-BUSINESS-MODEL §7.b (R$ 528 vs R$ 450).
- **Onde é aplicada:** `catalog`, `rating`, `telco`.
- **Origem:** PRODUCTS §2.1. Enum brief: `charge`, `block`.

#### RN-023 — Sobra de minutos expira
- **Enunciado:** Segundos de franquia não usados zeram no fechamento do ciclo. Não há carry-over.
- **Exemplo:** 1.800 de 2.000 min fixo usados → 200 expiram.
- **Onde é aplicada:** `rating.cycles`, `billing`.
- **Origem:** PRODUCTS §2.1.

#### RN-024 — Bloqueio de excedente não muda `subscription.status`
- **Enunciado:** Esgotar franquia com `overage_policy=block` aplica `TelcoPort.blockOutgoingCalls` na assinatura (originação off). A assinatura permanece `active` (ou `trial`). Não usar `blocked_credit` / `blocked_limit`.
- **Exemplo:** Franquia fixo zerada, móvel ainda disponível: o cliente liga para móvel, não para fixo.
- **Onde é aplicada:** `telco`, `rating`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-07) — o enum de subscription não tem `blocked_overage`.

#### RN-025 — Tarifas de excedente
- **Enunciado:** `catalog.plan_versions` armazena `overage_landline_cents_per_min` e `overage_mobile_cents_per_min` (`numeric(12,4)`), copiados para `customers.subscriptions` no snapshot. Se nulos na criação, copiar os unitários da menor faixa ofertada da revenda (D-DOM-08).
- **Exemplo:** Avançado excedente fixo R$ 0,08 / móvel R$ 0,18.
- **Onde é aplicada:** `catalog`, `rating`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-08). PRODUCTS exige tarifa de excedente mas não diz de onde nasce o default.

#### RN-026 — Itens além do incluído
- **Enunciado:** DID ou canal acima de `included_*` cobra o unitário de venda da revenda **pró-rata** (RN-067).
- **Exemplo:** Pacote 2 DIDs; adiciona o 3º no dia 1 → + R$ 9,60 no mês.
- **Onde é aplicada:** `billing`, `catalog`.
- **Origem:** PRODUCTS §6 (pró-rata) + §2.1.

#### RN-027 — Custo VC1 do pacote
- **Enunciado:** O custo da revenda/VC1 no pacote **não** é o preço de venda. `cost_cents` = (DIDs reais × unit DID VC1) + (canais reais × unit canal VC1) + minutos 30/6 nas tarifas VC1 da faixa da revenda.
- **Exemplo:** Pacote R$ 450; custo 2 DID + 5 canais + 1.800×0,05 + 1.200×0,12 = 16+100+90+144 = R$ 350.
- **Onde é aplicada:** `rating`, `billing`.
- **Origem:** PRODUCTS §2.3, §4 (margem = venda − custo).

#### RN-028 — `commitment_cents` nulo no pacote
- **Enunciado:** Plano `package` não tem compromisso de mínimo do cliente. `charged` do cliente = mensalidade + extras + excedente (`charge`).
- **Exemplo:** Consumo interno R$ 80 em minutos inclusos — ainda paga R$ 450.
- **Onde é aplicada:** `catalog`, `billing`.
- **Origem:** PRODUCTS §2.1.

---

### 1.4 Planos consumo mínimo

#### RN-029 — Cobrança `max(consumo, compromisso)`
- **Enunciado:** `charged_cents = max(consumo_cents, commitment_cents)` no ciclo, com consumo = DIDs + canais + minutos (venda, 30/6, pró-rata).
- **Exemplo:** Consumo R$ 780, compromisso R$ 1.000 → cobra R$ 1.000; consumo R$ 1.500 → cobra R$ 1.500 (PRODUCTS §7 e 01-BUSINESS-MODEL §7.a).
- **Onde é aplicada:** `billing`, `rating`.
- **Origem:** PRODUCTS §2.2.

#### RN-030 — Tudo conta
- **Enunciado:** Não existe item “fora do mínimo”. DID, canal e minuto entram em `consumo_cents`.
- **Exemplo:** 10 DID (R$ 80) + 5 canais (R$ 100) + voz R$ 600 = R$ 780.
- **Onde é aplicada:** `rating`.
- **Origem:** PRODUCTS §2.2.

#### RN-031 — Cliente adiciona DID/canal livremente
- **Enunciado:** No `kind=commitment` não há teto de inclusos. Alocação respeita estoque DID, limite de crédito/saldo e bloqueios vigentes.
- **Exemplo:** Cliente no mínimo R$ 1.000 sobe de 10 para 12 DIDs no dia 15 (pró-rata).
- **Onde é aplicada:** `customers`, `telco`.
- **Origem:** PRODUCTS §2.2.

#### RN-032 — `locked_tier_id` obrigatório
- **Enunciado:** O plano trava uma linha `reseller_tier_rows`. Tarifas de venda do ciclo são as dessa linha (snapshot RN-017).
- **Exemplo:** Plano “1k” trava Starter; consumo R$ 3.000 **não** aplica tarifas Growth.
- **Onde é aplicada:** `catalog`.
- **Origem:** PRODUCTS §2.3.

#### RN-033 — Sobra de compromisso não vira franquia
- **Enunciado:** A diferença `compromisso − consumo` quando positiva não se converte em minutos para o ciclo seguinte.
- **Exemplo:** Pagou R$ 1.000, usou R$ 780; mês seguinte a franquia não existe — o consumo recomeça do zero e o piso continua R$ 1.000.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §2.2 (cobrança max); interpretação necessária, alinhada ao texto.

#### RN-034 — Modalidade `prepaid` ou `postpaid`
- **Enunciado:** `payment_mode` no plano (enum brief: `prepaid`, `postpaid`). Pré-pago: carteira. Pós-pago: `credit_limits` 80/100.
- **Exemplo:** Mesmo compromisso R$ 1.000 pode existir em dois planos, um pré e um pós.
- **Onde é aplicada:** `catalog`, `billing`.
- **Origem:** PRODUCTS §2.2.

#### RN-035 — `sell_price_cents` nulo
- **Enunciado:** Plano commitment não tem mensalidade fechada. A fatura nasce do rating + `max()`.
- **Onde é aplicada:** `catalog`.
- **Origem:** PRODUCTS §2.2; PLAN modelo.

---

### 1.5 Pacotes sugeridos

#### RN-036 — VC1 publica templates
- **Enunciado:** `catalog.suggested_packages` são templates da VC1 (`reseller_id` nulo). A revenda **clona** para `catalog.plans`.
- **Exemplo:** Template “Avançado” aparece no builder como “usar sugerido”.
- **Onde é aplicada:** `catalog`.
- **Origem:** PRODUCTS §1; brief §1.

#### RN-037 — Clone independente
- **Enunciado:** `PADRÃO PROPOSTO`: após o clone, editar o template VC1 **não** altera os `plans` já clonados. Editar o plano da revenda **não** altera o template.
- **Exemplo:** VC1 muda o sugerido para 3 DIDs; NetSul que já clonou permanece com 2.
- **Onde é aplicada:** `catalog`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-09). PRODUCTS diz “clonar e editar” sem cascade.

#### RN-038 — Conteúdo dos sugeridos
- **Enunciado:** Basic/Avançado em PRODUCTS §2.1 são ilustrativos (preço “R$ xxx”). Conteúdo real **em aberto**.
- **Exemplo:** Este blueprint não fixa R$ de sugerido.
- **Onde é aplicada:** `catalog` (seed).
- **Origem:** PRODUCTS §8 (em aberto); 01-BUSINESS-MODEL D-BIZ-21.

#### RN-039 — Sugerido pode ser pacote ou commitment
- **Enunciado:** `PADRÃO PROPOSTO`: templates aceitam `kind=package` ou `kind=commitment`.
- **Onde é aplicada:** `catalog`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-10).

---

### 1.6 Teste grátis

#### RN-040 — Definido pela revenda no plano
- **Enunciado:** Cada plano: `trial_enabled`, `trial_days`, franquia de trial (segundos, `separate` ou `pooled` alinhado ao plano). Sem default global obrigatório se `trial_enabled=false`.
- **Exemplo:** Avançado com 7 dias e 100 min pooled; Basic sem trial.
- **Onde é aplicada:** `catalog`, `sales`, `telco`.
- **Origem:** PRODUCTS §6; brief §1.

#### RN-041 — Trial é subscriber temporário
- **Enunciado:** `subscription.status=trial` provisiona tronco via `ProvisioningPort`/`TelcoPort` com `callLimit` e, se houver, teto de minutos de rede de segurança. Não é PABX.
- **Exemplo:** Proposta aceita trial → `insertSubscriber` antes do meSign.
- **Onde é aplicada:** `sales`, `telco`, `integration`.
- **Origem:** PLAN §3.3; brief funil.

#### RN-042 — Trial não gera fatura de cliente
- **Enunciado:** `PADRÃO PROPOSTO`: ciclo em `trial` não emite `invoices` `party=customer` nem entra em `payout`. CDRs de trial são importados para auditoria com `sell_cents=0`.
- **Exemplo:** 40 min no trial não aparecem na primeira fatura paga.
- **Onde é aplicada:** `billing`, `rating`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-11).

#### RN-043 — Custo de trial no mínimo da revenda
- **Enunciado:** `PADRÃO PROPOSTO`: minutos/DID/canal de trial **não** entram no `cost` do mínimo da revenda (absorvidos pela VC1 como CAC). DID de trial deve ser da pool de demo quando possível.
- **Exemplo:** 200 min trial da NetSul não somam no compromisso de R$ 2.000.
- **Onde é aplicada:** `rating`, `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-12).

#### RN-044 — Sem multa de fidelidade no trial
- **Enunciado:** Cancelar ou deixar expirar o trial não gera fidelidade.
- **Exemplo:** Cliente testa 7 dias e recusa — `proposal.lost` / `subscription.cancelled`, multa R$ 0.
- **Onde é aplicada:** `sales`, `billing`.
- **Origem:** 01-BUSINESS-MODEL D-BIZ-05; PRODUCTS não detalha, alinhado a “teste grátis”.

#### RN-045 — Destinos do trial
- **Enunciado:** `PADRÃO PROPOSTO`: trial permite `landline_br` e `mobile_br`; `other` continua bloqueado. Franquia de trial desconta os dois.
- **Onde é aplicada:** `telco`, `rating`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-13).

#### RN-046 — Um trial por cliente por plano (vitalício)
- **Enunciado:** No máximo **um** registro de trial por `(reseller_id, customer_id, plan_id)` — inclusive após `cancelled`/`converted` (não reinicia trial do mesmo plano). `plan_id` denormalizado em `sales.trials`.
- **Exemplo:** CNPJ já testou Avançado — o wizard só oferece contratação paga.
- **Onde é aplicada:** `sales`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-14).

#### RN-047 — Expiração sem aceite
- **Enunciado:** Fim de `trial_days` sem `accepted`/`pending_signature`/`contracted`: `subscription.cancelled`, `TelcoPort` remove originação, proposta `expired` ou `lost` (se marcado pelo vendedor).
- **Exemplo:** Trial acaba sexta; sábado o tronco não origina.
- **Onde é aplicada:** `sales`, `telco`.
- **Origem:** brief `proposal.stage` + PLAN §3.3.

#### RN-048 — Conversão reusa o subscriber
- **Enunciado:** `PADRÃO PROPOSTO`: trial → `active` não recria o assinante SipPulse; promove cota/`callLimit`/DIDs definitivos no mesmo `legacy_id`.
- **Onde é aplicada:** `telco`, `integration`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-15).

---

### 1.7 Fidelidade e cancelamento

#### RN-049 — Fidelidade configurável
- **Enunciado:** `fidelity_months` no plano **ou** herdado da faixa (`fidelity_default_months`). 0 = mensal sem multa. PRODUCTS permite “mensal ou com prazo mínimo”.
- **Exemplo:** Faixa Growth default 12 meses; plano específico da revenda override 0.
- **Onde é aplicada:** `catalog`, `tenancy`.
- **Origem:** PRODUCTS §2.3.

#### RN-050 — Precedência plano > faixa
- **Enunciado:** `PADRÃO PROPOSTO`: se o plano tem `fidelity_months` não nulo, vale o plano; senão a faixa.
- **Onde é aplicada:** `catalog`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-16).

#### RN-051 — Multa de cancelamento antecipado
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-05): multa = `min(meses cheios restantes de fidelidade, fidelity_months) * recorrente`, onde recorrente = `sell_price_cents` do pacote ou `commitment_cents` do mínimo (nunca o consumo real).
- **Exemplo:** Pacote R$ 450, fidelidade 12, cancela no mês 5 → 7 × 450 = R$ 3.150.
- **Onde é aplicada:** `billing`, `customers`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-052 — Aviso de 30 dias após o prazo
- **Enunciado:** `PADRÃO PROPOSTO`: fim da fidelidade → cancelamento com notice 30 dias, sem multa. O notice pode cruzar ciclo: cobra o ciclo em curso cheio (RN-054).
- **Onde é aplicada:** `customers`.
- **Origem:** PADRÃO PROPOSTO (D-BIZ-05).

#### RN-053 — Quem cancela
- **Enunciado:** Cliente `customer_admin` solicita; revenda `reseller_owner`/`reseller_admin` confirma no Produto 02; `vc1_admin` pode cancelar em qualquer modo (auditoria). No `vc1_invoices` o contrato é da VC1: o pedido do cliente **abre** cancelamento, a revenda/VC1 executa.
- **Onde é aplicada:** `customers`, `identity`.
- **Origem:** brief papéis + PRODUCTS §4 (contratada). Detalhe de workflow: PADRÃO PROPOSTO (D-DOM-17).

#### RN-054 — Sem reembolso do ciclo em curso
- **Enunciado:** `PADRÃO PROPOSTO`: cancelamento no dia 20 não devolve 10/30 da mensalidade/mínimo. DID/canal do ciclo não têm crédito.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-18).

#### RN-055 — Efeito imediato na originação
- **Enunciado:** Ao `cancelled`, `TelcoPort` bloqueia originação na hora. DIDs: `PADRÃO PROPOSTO` retenção 7 dias para port-out, depois devolução ao estoque (D-DOM-19).
- **Onde é aplicada:** `telco`, `customers`.
- **Origem:** PADRÃO PROPOSTO no prazo de DID; bloqueio imediato alinhado a PLAN bloqueios.

#### RN-056 — Multa vira linha de fatura
- **Enunciado:** No `vc1_invoices`, multa entra em `invoice_lines` e NFCom. No `reseller_invoices`, entra no `statement` para a revenda cobrar. Não há `payout` da multa (`sell` sem `cost` telco): `PADRÃO PROPOSTO` a multa fica 100% com quem fatura o cliente (VC1 ou revenda) — não entra no Σ(sell−cost) como margem de voz (D-DOM-20).
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO.

---

### 1.8 Tarifação 30/6 e classificação de destino

#### RN-057 — Cadência 30/6
- **Enunciado:** `billed_seconds = 30` se `raw_seconds <= 30`; senão `30 + 6 * ceil((raw_seconds - 30) / 6)`.
- **Exemplo:** 5 s → 30; 30 s → 30; 31 s → 36; 47 s → 48; 125 s → 126 (01-BUSINESS-MODEL §7.h).
- **Onde é aplicada:** `rating`.
- **Origem:** PRODUCTS §3; brief §1.

#### RN-058 — Fixo Brasil preço único
- **Enunciado:** `destination=landline_br` não distingue local vs LD. Um unitário nacional.
- **Exemplo:** São Paulo→Porto Alegre e chamada local usam o mesmo `unit_landline_cents`.
- **Onde é aplicada:** `rating`.
- **Origem:** PRODUCTS §3.

#### RN-059 — Móvel Brasil
- **Enunciado:** `destination=mobile_br` usa `unit_mobile_cents` (custo) / tarifa de venda ou excedente.
- **Onde é aplicada:** `rating`.
- **Origem:** PRODUCTS §3.

#### RN-060 — Destino `other` bloqueado
- **Enunciado:** `PADRÃO PROPOSTO`: originação para `other` é rejeitada na rede (cota/prefixo) e o rating **não** gera `sell_cents` (CDR se existir = auditoria, `blocked`). Sem tarifa internacional no MVP.
- **Exemplo:** Discagem para +1 EUA não completa.
- **Onde é aplicada:** `telco`, `rating`.
- **Origem:** brief enum `destination`; D-BIZ-03.

#### RN-061 — Classificação
- **Enunciado:** `PADRÃO PROPOSTO`: classificador E.164 Brasil — prefixos móveis 6–9 no 9º dígito / listas Anatel vigentes na tabela `rating` de prefixos; demais BR = `landline_br`; fora = `other`. Não reutilizar o `rate_plan` SipPulse como fonte de venda.
- **Onde é aplicada:** `rating`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-21).

#### RN-062 — CDR bruto, não o R$ do switch
- **Enunciado:** O motor lê `billsec` (ou duração equivalente) em `sippulse_reports.cdrs_report` e retarifa no PG. É proibido copiar o valor já tarifado do SipPulse como `sell_cents`.
- **Onde é aplicada:** `rating`, `CdrPort`.
- **Origem:** PLAN P14; brief CdrPort read-only.

#### RN-063 — Rating em dois níveis
- **Enunciado:** Cada `rated_calls` grava `cost_amount_cents` e `sell_amount_cents` (`numeric(14,4)`, faixa VC1 vs plano). Mesma `billed_seconds`.
- **Exemplo:** 48 s móvel, custo 0,12/min, venda 0,144/min.
- **Onde é aplicada:** `rating`.
- **Origem:** PLAN §3.4.

#### RN-064 — Arredondamento na agregação
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-09): **não** aplicar half-up por CDR. `rated_calls` e débitos de carteira permanecem `numeric(14,4)`. Half-up para centavo inteiro só nas **linhas agregadas** de fatura/extrato (classe de destino × assinatura × ciclo; pró-rata no fechamento).
- **Exemplo:** Σ 30 s fixo no ciclo → linha agregada half-up; cada CDR guarda 2,5000 cents, não 3.
- **Onde é aplicada:** `rating`, `billing`.
- **Origem:** D-BIZ-09; revisão rodada 2.

#### RN-065 — Chamada sem duração / não completada
- **Enunciado:** `PADRÃO PROPOSTO`: `raw_seconds = 0` ou não atendida → não gera `rated_calls` cobrável.
- **Onde é aplicada:** `rating`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-22).

#### RN-066 — Fuso e recorte do ciclo
- **Enunciado:** `PADRÃO PROPOSTO`: timezone `America/Sao_Paulo`. CDR pertence ao ciclo da **data/hora de início** da chamada.
- **Exemplo:** Chamada 31/10 23:59 → 01/11 00:04 entra no ciclo de outubro.
- **Onde é aplicada:** `rating`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-23).

---

### 1.9 Pró-rata

#### RN-067 — DID/canal no meio do ciclo
- **Enunciado:** `charged = unit_cents * remaining_days / days_in_month`, `remaining_days` **inclui o dia da ativação**. `days_in_month` = dias calendário daquele mês.
- **Exemplo:** DID R$ 8,00 no dia 15 de mês de 30 dias → 16/30 × 8 = R$ 4,27 (pro-rata; arredondamento half-up só na linha agregada da fatura — D-BIZ-09).
- **Onde é aplicada:** `billing`, `rating`.
- **Origem:** PRODUCTS §6; D-BIZ-11.

#### RN-068 — Minutos não são pró-rata
- **Enunciado:** Voz cobra 30/6 desde o primeiro segundo, independentemente do dia.
- **Onde é aplicada:** `rating`.
- **Origem:** PRODUCTS §3.

#### RN-069 — Remoção no meio do ciclo
- **Enunciado:** `PADRÃO PROPOSTO`: remover DID/canal **não** gera crédito dos dias restantes. O item já pró-rata na ativação permanece.
- **Exemplo:** DID no dia 1 (R$ 8); remove dia 10; ciclo cobra R$ 8.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-24).

#### RN-070 — Pacote iniciado no meio do ciclo
- **Enunciado:** `PADRÃO PROPOSTO`: `sell_price_cents` do pacote também pró-rata pelos dias restantes inclusive o da ativação. Franquia de minutos pró-rata na mesma fração (senão o cliente leva franquia cheia em 16 dias).
- **Exemplo:** Avançado R$ 450, 2.000/1.500 min, ativa dia 15/30 → R$ 240,00 e franquia 1.067 / 800 min (16/30; valores intermediários em numeric(14,4)).
- **Onde é aplicada:** `billing`, `rating`.
- **Origem:** D-BIZ-12; fração da franquia PADRÃO PROPOSTO (D-DOM-25).

#### RN-071 — Uso próprio da revenda
- **Enunciado:** Pró-rata de DID/canal do tronco da revenda segue RN-067 nas tarifas **VC1** da faixa contratada.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §6 aplicado ao uso próprio.

---

### 1.10 Ciclo e fechamento

#### RN-072 — Mês calendário, fecha no dia 1
- **Enunciado:** `PADRÃO PROPOSTO`: `rating.cycles` = `[YYYY-MM-01, próximo mês 01)`. Job de fechamento no dia 1 (America/Sao_Paulo) processa o mês anterior.
- **Exemplo:** Em 1º/nov 00:10 fecha outubro.
- **Onde é aplicada:** `rating`, `billing`.
- **Origem:** D-BIZ-01.

#### RN-073 — Vencimento
- **Enunciado:** `PADRÃO PROPOSTO`: `due_day` por revenda, default **10**. Fatura emitida dia 1 vence dia 10 do mesmo mês (ou próximo dia útil — D-DOM-26: **não** desloca por dia útil no MVP; se dia 10 cair no domingo, permanece dia 10 e o boleto mePay trata).
- **Onde é aplicada:** `billing`.
- **Origem:** D-BIZ-01; detalhe dia útil PADRÃO PROPOSTO.

#### RN-074 — Idempotência
- **Enunciado:** Reexecutar o fechamento do mesmo `cycle` + tenant não duplica `invoices`/`statements`/`payouts`. Usa chave única `(reseller_id, cycle, party, subscription_id)`.
- **Onde é aplicada:** `billing`, `rating`.
- **Origem:** PLAN risco R4 (cobrança dupla) + boa prática; detalhe PADRÃO PROPOSTO (D-DOM-27).

#### RN-075 — Fechamento não reabre
- **Enunciado:** `PADRÃO PROPOSTO`: ciclo `closed` só se ajusta com nota de crédito / `invoice` de ajuste emitida por `vc1_finance`, nunca UPDATE do `charged_cents` original.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-28).

#### RN-076 — Saídas do fechamento segundo `billing_mode`
- **Enunciado:** `vc1_invoices`: `invoices` `party=customer` por assinatura ativa/bloqueada (não trial, não cancelled antes do início do ciclo) + cálculo de `payouts`. `reseller_invoices`: `statements` por cliente + `invoices` `party=reseller`. Ambos os modos: rating de uso próprio.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §4; brief.

#### RN-077 — Assinatura bloqueada ainda fecha
- **Enunciado:** `blocked_*` no ciclo gera fatura/extrato do que foi usado + mensalidade/mínimo (pacote: mensalidade cheia se esteve ativa no dia 1; commitment: `max`). `cancelled` no ciclo: RN-054.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-29), para não “sumir” mínimo.

---

### 1.11 Fatura cliente

#### RN-078 — Só no modo `vc1_invoices`
- **Enunciado:** `billing.invoices` `party=customer` **não** existem para clientes de revenda `reseller_invoices`.
- **Exemplo:** Cliente da NetSul STFC vê no `/app` “cobrado pela sua operadora”, não a fatura VC1.
- **Onde é aplicada:** `billing`, painel cliente.
- **Origem:** PRODUCTS §4; brief.

#### RN-079 — Preço de venda da revenda
- **Enunciado:** Linhas e `charged_cents` usam sell, nunca cost. NFCom idem.
- **Onde é aplicada:** `billing`, `fiscal`.
- **Origem:** PRODUCTS §4.

#### RN-080 — Uma fatura por assinatura por ciclo
- **Enunciado:** `PADRÃO PROPOSTO`: consolidar DID, canal, voz, excedente, pró-rata, portabilidade, multa em um único `invoices` do ciclo. Recarga pré-paga é `payments`/`credit_ledger`, não mistura como segunda fatura de ciclo (pode haver fatura de recarga avulsa se mePay exigir — D-DOM-30: recarga gera `invoice` `issued` imediata além da de ciclo zerada).
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-081 — Pré-pago no fechamento
- **Enunciado:** Todo ciclo aplica `max(consumo, commitment)` (D-BIZ-25). Débitos de uso correm na carteira em near realtime; no fechamento debita `max(0, commitment − consumo_do_ciclo)` da carteira. Recarga **não** substitui esse mínimo futuro — só aumenta saldo. Saldo insuficiente no fechamento → debita até zero + `blocked_credit`. Pacote pré-pago: mensalidade debitada no dia 1 (RN-109).
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-082 — Status comercial
- **Enunciado:** Enum: `draft` → `issued` → `paid` | `overdue` → `paid`; `issued`/`overdue` → `cancelled`; `overdue` → `written_off`. `paid` não volta.
- **Onde é aplicada:** `billing`.
- **Origem:** brief `invoice.status`.

#### RN-083 — Emissão dispara cobrança e NF
- **Enunciado:** Transição `draft`→`issued` (fechamento): cria charge mePay **e** `fiscal_documents` `pending`. A NF só `authorized` após RN-141. A fatura comercial **pode** estar `issued` com NF ainda `imported`.
- **Onde é aplicada:** `billing`, `fiscal`, `PaymentPort`.
- **Origem:** brief NFCom + mePay.

#### RN-084 — Painel cliente
- **Enunciado:** `/app` financeiro lista faturas só se a revenda é `vc1_invoices`. Senão, copy fixo de cobrança pela revenda.
- **Onde é aplicada:** painel cliente.
- **Origem:** PLAN §5.C.

---

### 1.12 Fatura revenda

#### RN-085 — Modo `reseller_invoices`: sempre
- **Enunciado:** `charged_cents = max(Σ cost_cents dos clientes do ciclo + uso próprio, commitment_cents da revenda)`. Inclui custo de clientes inadimplentes **com a revenda** (a VC1 não vê essa inadimplência).
- **Exemplo:** 01-BUSINESS-MODEL §7.c C1: max(1.354, 2.000) = 2.000.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §4; brief.

#### RN-086 — Modo `vc1_invoices`: só se repasse negativo
- **Enunciado:** Se `payout_raw > 0`, não há fatura `party=reseller` naquele ciclo (salvo ajuste manual). Se `payout_raw = 0`, `payout.status=settled_zero` (sem fatura, sem comissão). Se `payout_raw < 0`, `charged_cents = -payout_raw` e `payout.status=netted_to_invoice`.
- **Exemplo:** Brief: margem 300, shortfall 500 → fatura R$ 200.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §4; brief exemplo.

#### RN-087 — NFCom da fatura da revenda
- **Enunciado:** Toda `invoices` `party=reseller` `issued` gera NFCom RLGR (RN-139).
- **Onde é aplicada:** `fiscal`.
- **Origem:** brief §2 (NFCom); PRODUCTS “emite quem fatura”.

#### RN-088 — Linhas da fatura da revenda
- **Enunciado:** `PADRÃO PROPOSTO`: discriminar uso próprio e, no modo `reseller_invoices`, subtotal por cliente (`cost_cents`). No `vc1_invoices` netted, discriminar shortfall e margem negativa agregada.
- **Onde é aplicada:** `billing.invoice_lines`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-31).

#### RN-089 — Custo não pago no `vc1_invoices`
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-06): `cost` de `invoices` customer não `paid` **não** entra no mínimo/shortfall até a baixa.
- **Exemplo:** 01-BUSINESS-MODEL §7.d D3.
- **Onde é aplicada:** `billing`.
- **Origem:** brief §1 (padrão aberto).

---

### 1.13 Extrato no modo `reseller_invoices`

#### RN-090 — Statement não é fatura
- **Enunciado:** `billing.statements` é o rating de **venda** por cliente para a revenda emitir o documento dela. Sem `invoice.status`, sem mePay ao cliente, sem NFCom.
- **Exemplo:** Statement C: R$ 1.000 (max 936, 1.000) com linhas DID/canal/voz.
- **Onde é aplicada:** `billing`.
- **Origem:** brief §1.

#### RN-091 — Imutável após o fechamento
- **Enunciado:** `PADRÃO PROPOSTO`: statement fechado só se corrige com statement de ajuste (novo registro), não overwrite.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-32).

#### RN-092 — Exportação
- **Enunciado:** `PADRÃO PROPOSTO`: PDF (DomPDF) e CSV no painel `reseller_finance`. Não envia e-mail automático ao cliente final (a revenda cobra como quiser).
- **Onde é aplicada:** painel revenda.
- **Origem:** PADRÃO PROPOSTO (D-DOM-33).

---

### 1.14 Repasse e nota de comissão

#### RN-093 — Só `vc1_invoices`
- **Enunciado:** `billing.payouts` não existe para revenda `reseller_invoices`.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §4.

#### RN-094 — Fórmula
- **Enunciado:** `paid_margin_cents` = Σ(sell−cost) de invoices customer `paid` no ciclo (margem negativa já inclusa). `shortfall_cents` = max(0, commitment − cost_paid − own_usage). `negative_margin_cents` = |Σ min(sell−cost,0)| **informativo**. `net_cents` = `paid_margin_cents` − `shortfall_cents`. `payout_raw` = `net_cents`.
- **Exemplo:** 01-BUSINESS-MODEL §7.d D1–D4.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §4; brief exemplo 600→100 e 300→fatura 200.

#### RN-095 — Só o efetivamente recebido
- **Enunciado:** `issued`/`overdue` não entram em `margin_paid`. `written_off` não entra. `cancelled` não entra.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §4.

#### RN-096 — Baixa atrasada
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-10): pagamento no ciclo N+1 de fatura do ciclo N entra no `payout` de N+1, com o `cost` correspondente contando no mínimo de N+1.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-097 — Máquina `payout.status`
- **Enunciado:** `calculating` → se `payout_raw > 0` então `pending_commission_invoice`; se `< 0` então `netted_to_invoice`; se `= 0` então **`settled_zero`** (sem nota de comissão, sem fatura revenda). Demais transições inalteradas.
- **Onde é aplicada:** `billing`.
- **Origem:** brief enum; D-BIZ-07.

#### RN-098 — Nota de comissão
- **Enunciado:** Documento **da revenda** (NFS-e municipal típica, não NFCom RLGR). Upload em `billing.commission_invoices`. Valor deve igualar `payout` (tolerância 0 cents — D-DOM-34). Sem nota, não há `approved`.
- **Onde é aplicada:** `billing`, `vc1_finance`.
- **Origem:** PRODUCTS §4; brief.

#### RN-099 — Pagamento do repasse
- **Enunciado:** `PADRÃO PROPOSTO`: `vc1_finance` registra TED (banco, agência/conta mascarada, comprovante, `paid_at`). mePay payout quando existir (D-BIZ-07).
- **Onde é aplicada:** `billing`.
- **Origem:** brief §2.

#### RN-100 — Um payout por revenda por ciclo
- **Enunciado:** Chave única `(reseller_id, cycle)`. Recalcular só enquanto `calculating`.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-35).

#### RN-101 — Sem split no gateway
- **Enunciado:** mePay recebe 100% na conta VC1 no modo `vc1_invoices`. A revenda nunca é split_recipient.
- **Onde é aplicada:** `PaymentPort`.
- **Origem:** PRODUCTS §4; brief “não existe split”.

---

### 1.15 Crédito pré-pago

#### RN-102 — Carteira por cliente
- **Enunciado:** `billing.credit_wallets` + `credit_ledger` (`deposit|debit|expire|adjust`). Saldo = soma do ledger.
- **Onde é aplicada:** `billing`.
- **Origem:** brief entidades; PRODUCTS §2.2.

#### RN-103 — Recarga pré-paga
- **Enunciado:** `deposit` credita a carteira (qualquer valor `> 0`). Não dispensa o `max(consumo, commitment)` do ciclo nem o débito de fechamento `max(0, commitment − consumo)` (D-BIZ-25). Primeira ativação pode exigir saldo inicial ≥ pró-rata/mensalidade (D-DOM-36).
- **Exemplo:** Mínimo R$ 1.000; recarga R$ 999 recusada.
- **Onde é aplicada:** `billing`, `PaymentPort`.
- **Origem:** PRODUCTS §2.2; recarga seguinte PADRÃO PROPOSTO.

#### RN-104 — Débito do consumo
- **Enunciado:** Cada `rated_calls.sell_amount_cents` e cada alocação de DID/canal (pró-rata) gera `debit`. Bloqueio ao zerar (RN-106).
- **Onde é aplicada:** `billing`, `rating`.
- **Origem:** PRODUCTS §2.2; D-BIZ-13.

#### RN-105 — Saldo não negativo
- **Enunciado:** Débito usa `GREATEST(0, balance − amount)`; residual vira `unrecovered_cents` no ledger (absorvido/reportado). Em seguida `blocked_credit` + quota SipPulse / block telco (D-BIZ-26).
- **Onde é aplicada:** `billing`, `telco`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-106 — Bloqueio no zero
- **Enunciado:** Saldo <= 0 → `blocked_credit` (se precedência permitir) → enforcement telco conforme D-BIZ-26 / D-INT-07: se quota monetária **confirmada**, bloqueio em até **60 s** após o débito; com fallback **90%** + CDR a cada 5 min, SLA = **próximo import CDR (≤ 5 min) + 60 s**. Notifica cliente e revenda.
- **Exemplo:** 01-BUSINESS-MODEL §7.f.
- **Onde é aplicada:** `telco`, `billing`, `NotificationPort`.
- **Origem:** PRODUCTS §2.2.

#### RN-107 — Desbloqueio automático na recarga
- **Enunciado:** `deposit` que deixe saldo > 0 reverte `blocked_credit` **se** nenhum motivo de precedência maior estiver ativo (RN-126).
- **Onde é aplicada:** `billing`, `telco`.
- **Origem:** pedido do operador (desbloqueio automático em pagamento/recarga).

#### RN-108 — Saldo em R$ não expira
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-16): `expire` no ledger aplica-se à **franquia de pacote**, não ao saldo pré-pago em reais. `adjust` só `vc1_finance` com motivo obrigatório em `audit`.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-109 — Pacote pré-pago no dia 1
- **Enunciado:** `PADRÃO PROPOSTO`: no âncora do ciclo, tenta debitar `sell_price_cents` (ou pró-rata no primeiro ciclo). Se saldo insuficiente → `blocked_credit` sem gerar dívida (não emite fatura pós).
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-37).

---

### 1.16 Limite pós-pago 80/100

#### RN-110 — Limite por cliente
- **Enunciado:** `billing.credit_limits` no cliente/assinatura **pós-pago**. Exposição pacote = mensalidade integral dia 1 + extras (DID/canal fora do incluído) + overage `charge`. Plano **commitment** = todos os itens unitários (DID + canal + minutos sell) — alinhado a RN-020/RN-030.
- **Exemplo:** Limite R$ 1.000; exposição 800 → alerta; 1.000 → block. §7.g.
- **Onde é aplicada:** `billing`, `telco`.
- **Origem:** PRODUCTS §6.

#### RN-111 — Alerta 80% para revenda e VC1
- **Enunciado:** `limit_events` `threshold=80` `action=alert`. Notifica staff (`vc1_finance`, `vc1_ops`) **e** revenda (`reseller_admin`, `reseller_finance`). Não bloqueia.
- **Onde é aplicada:** `NotificationPort`, `billing`.
- **Origem:** PRODUCTS §6.

#### RN-112 — Bloqueio 100%
- **Enunciado:** `threshold=100` `action=block` → `blocked_limit` + `TelcoPort`.
- **Onde é aplicada:** `telco`, `billing`.
- **Origem:** PRODUCTS §6.

#### RN-113 — Uma vez por limiar por ciclo
- **Enunciado:** `PADRÃO PROPOSTO`: não reenviar alerta 80% a cada CDR após o primeiro cruzamento no ciclo, salvo se a exposição cair abaixo de 80% e recrossar.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-38).

#### RN-114 — Subir o limite desbloqueia
- **Enunciado:** Se exposição/limite < 100% após aumento, limpa `blocked_limit` (precedência RN-126). Quem sobe: `reseller_owner`, `reseller_admin`, `reseller_finance` nos clientes da revenda; cap opcional da VC1 (D-DOM-39: **sem cap** no MVP).
- **Onde é aplicada:** `billing`, `telco`.
- **Origem:** PRODUCTS §6 + desbloqueio automático.

#### RN-115 — Limite da revenda com a VC1
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-04): revenda pós-paga tem limite próprio. 80% alerta staff+owner; 100% bloqueia **novas ativações** e originação do **uso próprio**. Não cascateia originação dos clientes finais (D-BIZ-19).
- **Onde é aplicada:** `tenancy`, `billing`, `telco`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-116 — Pré-pago ignora este limite
- **Enunciado:** Cliente `prepaid` usa carteira (RN-102+), não `credit_limits` 80/100.
- **Onde é aplicada:** `billing`.
- **Origem:** PRODUCTS §2.2 vs §6.

#### RN-117 — Virada de ciclo
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-18): exposição zera no novo ciclo (exceto DIDs/canais/mensalidade do dia 1). `blocked_limit` não persiste se a nova exposição < 100%, salvo `blocked_overdue`.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO.

---

### 1.17 Bloqueio e desbloqueio

#### RN-118 — Status de assinatura
- **Enunciado:** Enum fechado: `trial`, `active`, `blocked_credit`, `blocked_limit`, `blocked_overdue`, `blocked_manual`, `cancelled`. Um valor por vez.
- **Onde é aplicada:** `customers.subscriptions`.
- **Origem:** brief.

#### RN-119 — Registro de evento
- **Enunciado:** Toda mudança de bloqueio grava `telco.block_events` (motivo, ator, timestamp) e chama `TelcoPort` (`blockSubscriber` / `alterar_status_boqueio`) de forma **idempotente**.
- **Onde é aplicada:** `telco`, `integration`.
- **Origem:** PLAN; brief ports.

#### RN-120 — Precedência de motivo (maior vence)

| Ordem | Status | Significado |
|------:|--------|-------------|
| 1 | `cancelled` | Terminal; originação off; sem desbloqueio para `active` |
| 2 | `blocked_manual` | Trava humana |
| 3 | `blocked_overdue` | Dunning esgotado |
| 4 | `blocked_limit` | Pós-pago 100% |
| 5 | `blocked_credit` | Pré-pago zero |
| 6 | `active` / `trial` | Livre (trial com franquia própria) |

- **Enunciado:** O status persistido é o de **maior** ordem entre os motivos **ativos**. Motivos menores ficam latentes em `block_events` / flags e **reaparecem** quando o maior é limpo.
- **Exemplo:** Cliente 100% e em atraso D+10 → `blocked_overdue`. Paga as faturas mas continua 100% → passa a `blocked_limit`. Recarga não se aplica (é pós).
- **Onde é aplicada:** `customers`, `telco`.
- **Origem:** pedido do operador; detalhe PADRÃO PROPOSTO (D-DOM-40).

#### RN-121 — Quem aplica `blocked_manual`
- **Enunciado:** `vc1_admin`, `vc1_ops` em qualquer assinatura. `reseller_owner`, `reseller_admin` nas assinaturas da própria revenda. `vc1_support` **não** (só leitura/impersonate). `reseller_seller` **não**.
- **Onde é aplicada:** `identity`, `telco`.
- **Origem:** papéis do brief; recorte PADRÃO PROPOSTO (D-DOM-41).

#### RN-122 — Revenda não desfaz bloqueio manual da VC1
- **Enunciado:** `PADRÃO PROPOSTO`: `block_events.actor_role` prefixo `vc1_*` só é revertido por `vc1_admin`/`vc1_ops`.
- **Onde é aplicada:** `telco`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-42).

#### RN-123 — Quem desbloqueia cada motivo

| Motivo | Automático | Manual |
|--------|------------|--------|
| `blocked_credit` | Recarga saldo > 0 | `vc1_finance` `adjust` de carteira |
| `blocked_limit` | Aumento de limite ou nova exposição < 100% | subir limite (RN-114) |
| `blocked_overdue` | Pagamento integral das faturas `overdue` do cliente (ou da revenda, se o bloqueio for da fatura da revenda) | `vc1_finance` via `written_off` **ou** desbloqueio excepcional auditado (D-DOM-43: permitido só `vc1_admin`) |
| `blocked_manual` | Não | Quem tem permissão RN-121/122 |
| `cancelled` | Não | Não (nova assinatura) |

#### RN-124 — Desbloqueio automático em pagamento
- **Enunciado:** Webhook mePay `paid` que zere o conjunto overdue do party dispara reavaliação da precedência e `TelcoPort` unblock se o resultado for `active`.
- **Onde é aplicada:** `billing`, `telco`.
- **Origem:** pedido do operador.

#### RN-125 — Overage `block` é paralelo
- **Enunciado:** Controle por destino (RN-024) convive com a tabela acima. Mesmo `active` pode estar sem originação fixo. Pagamento **não** “desbloqueia” franquia; só o próximo ciclo (franquia nova) ou upgrade de plano.
- **Onde é aplicada:** `telco`.
- **Origem:** PRODUCTS §2.1; D-DOM-07.

#### RN-126 — Reavaliação obrigatória
- **Enunciado:** Qualquer evento (pagamento, recarga, limite, manual, fechamento) recalcula o status pela tabela RN-120 **antes** de chamar unblock. É proibido unblock SOAP se ainda houver motivo maior.
- **Onde é aplicada:** `telco`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-40).

#### RN-127 — Revenda `suspended`
- **Enunciado:** `PADRÃO PROPOSTO`: `reseller.status=suspended` impede novas propostas/`contracted` e o funil público retorna indisponível. Assinaturas existentes: **não** bloqueiam originação só por isso, salvo se o motivo for inadimplência da revenda com a VC1 (aí `blocked_overdue` em **uso próprio**; clientes finais no `vc1_invoices` continuam até dunning próprio; no `reseller_invoices` a VC1 não bloqueia o cliente final por atraso da revenda — bloqueia o tronco da revenda/uso próprio e novas ativações) (D-DOM-44).
- **Onde é aplicada:** `tenancy`, `sales`, `telco`.
- **Origem:** PADRÃO PROPOSTO.

---

### 1.18 Inadimplência (dunning)

#### RN-128 — `issued` → `overdue` no dia seguinte ao vencimento
- **Enunciado:** Se `due_at` passou 00:00 America/Sao_Paulo e não há `paid`, status `overdue`.
- **Onde é aplicada:** `billing`.
- **Origem:** brief `invoice.status`; horário PADRÃO PROPOSTO (D-DOM-23).

#### RN-129 — Calendário de dunning
- **Enunciado:** `PADRÃO PROPOSTO` (D-DOM-45), âncora = `due_at` (e-mail na emissão, alinhado a DOC-12 / `10-DECISIONS`):
  - Na emissão (`issued`): e-mail/SMS com valor, vencimento e link de pagamento.
  - D−3: lembrete antes do vencimento (fatura ainda `issued`).
  - D+0 vencimento: permanece `issued` até 00:00 America/Sao_Paulo do dia seguinte (RN-128).
  - D+1: status `overdue` + aviso de atraso (`NotificationPort`).
  - D+5: aviso com bloqueio **agendado** para D+10 (`dunning_kind=block_warning`).
  - D+10: `blocked_overdue` + `TelcoPort`.
- **Exemplo:** Fatura vence dia 10; lembrete dia 7; overdue dia 11; aviso de bloqueio dia 15; bloqueio dia 20.
- **Onde é aplicada:** `billing`, `telco`, `NotificationPort`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-130 — Sem juros/multa de mora no MVP
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-22): dunning não adiciona linha de juros.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-131 — Write-off
- **Enunciado:** `vc1_finance` / `vc1_admin` → `written_off`. Sai da inadimplência operacional; **não** conta como `paid` para payout (RN-095). Pode desbloquear se era o único motivo (D-DOM-43).
- **Onde é aplicada:** `billing`.
- **Origem:** brief enum; efeito no payout = PRODUCTS “efetivamente recebido”.

#### RN-132 — Dunning da fatura da revenda
- **Enunciado:** O mesmo calendário aplica-se a `party=reseller`. No D+10: `reseller.status` pode ir a `suspended` (D-DOM-46: **sim**, após o bloqueio telco do uso próprio).
- **Onde é aplicada:** `tenancy`, `billing`.
- **Origem:** PADRÃO PROPOSTO.

---

### 1.19 STFC

#### RN-133 — Obrigatório para `reseller_invoices`
- **Enunciado:** Cadastro nesse modo exige `tenancy.stfc_licenses` com número, arquivo, validade futura e `stfc_verified_at` por `vc1_ops` ou `vc1_admin`. Sem isso o modo recusa.
- **Exemplo:** ISP sem outorga só pode nascer `vc1_invoices`.
- **Onde é aplicada:** `tenancy`.
- **Origem:** PRODUCTS §4; brief.

#### RN-134 — Verificação humana
- **Enunciado:** O sistema não consulta Anatel automaticamente no MVP (`PADRÃO PROPOSTO` D-DOM-47). Staff marca verificado após conferir o PDF.
- **Onde é aplicada:** `tenancy`, Filament.
- **Origem:** PADRÃO PROPOSTO.

#### RN-135 — Validade a vencer
- **Enunciado:** `PADRÃO PROPOSTO`: D-30 e D-7 e-mail para `reseller_owner` e `vc1_ops`.
- **Onde é aplicada:** `NotificationPort`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-48).

#### RN-136 — Expirada
- **Enunciado:** Quando `valid_until < today` (**D-0**): (1) fecha o funil de vendas — sem novas propostas, trials ou ativações; (2) tráfego **existente** continua por **30 dias** (grace); (3) em **D+30** sem STFC válida → `reseller.status=suspended`, corte de **uso próprio** e **novas** ativações; clientes finais **seguem originando** até decisão do operador (não há `vc1_invoices` antes da **E5**). Não emite novo `statement`/`reseller_invoices` fechado sem STFC. **Após E5**, o operador pode agendar `pending_billing_mode=vc1_invoices` + aditivo meSign (RN-171); não há troca automática de modo só por STFC expirada.
- **Exemplo:** Validade 15/mar → 16/mar funil off; até 15/abr grace; 16/abr sem renovação → suspended; clientes ativos continuam até ops cortar ou migrar pós-E5.
- **Onde é aplicada:** `tenancy`, `sales`, `telco`.
- **Origem:** Revisão independente rodada 2 (D-DOM-49).

#### RN-137 — Documento falso / reprovação
- **Enunciado:** Se a verificação falha depois de ativa: `suspended` + bloqueio de novas vendas + ticket ops. Não apaga o histórico.
- **Onde é aplicada:** `tenancy`.
- **Origem:** PLAN R8; detalhe PADRÃO PROPOSTO (D-DOM-50).

#### RN-138 — Arquivo privado
- **Enunciado:** PDF da outorga em storage privado (mesmo padrão LGPD da portabilidade). Não URL pública.
- **Onde é aplicada:** `tenancy`.
- **Origem:** brief (não copiar dívida LGPD).

---

### 1.20 NFCom

#### RN-139 — Quando emitir
- **Enunciado:** NFCom modelo 62 **somente** para: (a) `invoices` `party=customer` de revenda `vc1_invoices`; (b) `invoices` `party=reseller` (qualquer modo, quando a fatura existir). **Não** emitir para statements, payouts, notas de comissão, recargas internas sem `invoices`, nem cliente de `reseller_invoices`.
- **Onde é aplicada:** `fiscal`.
- **Origem:** brief §2; PRODUCTS §4; pedido do operador.

#### RN-140 — Emissora RLGR (legal)
- **Enunciado:** Emitente legal **RLGR** CNPJ 57.675.896/0001-26 (ou CNPJ revenda quando a fatura exigir). Caminho técnico: `FiscalPort` → **mePay** → emissor NFCom terceiro (ADR-013). VC1 **não** chama SyncNFe.
- **Onde é aplicada:** `fiscal`.
- **Origem:** brief §2; ADR-013.

#### RN-141 — Fluxo mePay assíncrono
- **Enunciado:** `pending` → `FiscalPort.requestFiscalNote` (mePay) → `requested` → webhook `fiscal.issued` (ou poll fallback) com chave SEFAZ **44 dígitos** → `issued`. Sem chave 44, status máximo `requested`.
- **Onde é aplicada:** `fiscal`.
- **Origem:** ADR-013; mePay `events.md` (fiscal a criar).

#### RN-142 — Não copiar o bug do legado
- **Enunciado:** É proibido marcar `issued` só porque o mePay aceitou a solicitação (HTTP 2xx). Só `fiscal.issued` + chave 44 (ou poll equivalente).
- **Onde é aplicada:** `fiscal`.
- **Origem:** brief §2 (legado SyncNFe); ADR-013.

#### RN-143 — Rejeição
- **Enunciado:** Webhook `fiscal.failed` ou rejeição SEFAZ → `failed`. A `invoice` permanece `issued` (cobrança mePay **não** cancela automaticamente). `fiscal_attempts` registra o código. Staff `vc1_finance` corrige dados e reabre `pending` (nova attempt). Após N=5 falhas (`PADRÃO PROPOSTO` D-DOM-51) alerta ops e **não** loop infinito.
- **Onde é aplicada:** `fiscal`.
- **Origem:** pedido do operador; limite PADRÃO PROPOSTO.

#### RN-144 — Timeout / atraso de emissão
- **Enunciado:** `PADRÃO PROPOSTO`: permanece `requested` e o job retenta poll mePay (backoff). Não marca `issued` por timeout.
- **Onde é aplicada:** `fiscal`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-52); ADR-013.

#### RN-145 — Cancelamento fiscal
- **Enunciado:** `PADRÃO PROPOSTO`: `issued` → `cancelled` só via mePay/emissor (API a mapear), disparado quando a `invoice` comercial vai a `cancelled` **e** ainda não `paid`. Fatura `paid` não cancela NFCom; usa nota de crédito/ajuste (fora do MVP se a API não estiver mapeada — D-DOM-53: no MVP, `paid`+erro fiscal = processo manual finance).
- **Onde é aplicada:** `fiscal`, `billing`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-146 — Valor da NF = `charged_cents`
- **Enunciado:** Divergência de 1 cent recusa o import (guard). Tributação bruta D-BIZ-02.
- **Onde é aplicada:** `fiscal`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-54) + D-BIZ-02.

#### RN-147 — Um fiscal_document por invoice
- **Enunciado:** Tentativas extras são `fiscal_attempts` do mesmo documento, não segundo `fiscal_documents`, salvo cancelamento+reemissão (aí novo registro ligado à mesma invoice).
- **Onde é aplicada:** `fiscal`.
- **Origem:** brief entidades; detalhe PADRÃO PROPOSTO (D-DOM-55).

#### RN-148 — Baixa comercial ≠ autorização fiscal
- **Enunciado:** `invoice.paid` vem do webhook mePay, não do status SEFAZ. Pode existir `paid` + `imported` (atraso de consulta). Dashboard de exceção para `vc1_finance`.
- **Onde é aplicada:** `billing`, `fiscal`.
- **Origem:** ADR-013 (cobrança e fiscal via mePay; ports distintos no domínio, mesmo SaaS).

---

### 1.21 Propostas

#### RN-149 — Estágios
- **Enunciado:** Enum: `draft`, `sent`, `viewed`, `trial_active`, `negotiating`, `accepted`, `pending_signature`, `contracted`, `expired`, `lost`, `cancelled`. Kanban: `lead`, `negotiating`, `won`, `lost` (mapeamento RN-157).
- **Onde é aplicada:** `sales`.
- **Origem:** brief.

#### RN-150 — Preço só no servidor
- **Enunciado:** O wizard e a página pública **não** enviam total. O servidor recalcula a partir do plano + DIDs + canais + pró-rata. Recusar payload com `total_cents` do browser.
- **Exemplo:** Dívida R1 do legado (`wl_label`) não se copia.
- **Onde é aplicada:** `sales`.
- **Origem:** brief §5; PLAN R1; pedido do operador.

#### RN-151 — Snapshot imutável após `sent`
- **Enunciado:** Ao `sent`, grava snapshot de itens, preços, marca, `billing_mode`, texto de contratada, N1 da revenda. Edição = **nova** proposta (o `draft` original não se altera depois de sent — D-DOM-56: clonar para `draft`).
- **Onde é aplicada:** `sales.proposals`.
- **Origem:** pedido do operador; PLAN proposta v2026.

#### RN-152 — PIN de 6 dígitos
- **Enunciado:** Link `/p/{code}` exige PIN de 6 dígitos. Sem PIN na URL.
- **Onde é aplicada:** `sales` público.
- **Origem:** brief §2 (funil sales-mework360).

#### RN-153 — Validade
- **Enunciado:** `PADRÃO PROPOSTO`: 15 dias a partir de `sent`. Job marca `expired` se ainda `sent|viewed|negotiating|trial_active`. Trial em curso **não** expira a proposta até `trial_ends_at` (estende a validade até o fim do trial).
- **Onde é aplicada:** `sales`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-57).

#### RN-154 — Texto contratual segundo o modo
- **Enunciado:** `vc1_invoices`: contratada = VC1; cláusula obrigatória: atendimento nível 1 e gestão comercial **da revenda**. `reseller_invoices`: contratada = revenda.
- **Onde é aplicada:** `sales`, `sales.contracts`.
- **Origem:** PRODUCTS §4.

#### RN-155 — Assinatura meSign
- **Enunciado:** `accepted` → cria envelope `SignaturePort` → `pending_signature`. Webhook `envelope.completed` (HMAC `X-Paco-Signature`) → `contracted`. `envelope.archived` não muda estágio sozinho.
- **Onde é aplicada:** `sales`, `SignaturePort`.
- **Origem:** brief §2.

#### RN-156 — Provisionamento
- **Enunciado:** Trial: provisiona em `trial_active`. Definitivo: em `contracted` (ou promove RN-048). Nunca Fusion. Prefixo 750/850/950 via legado.
- **Onde é aplicada:** `ProvisioningPort`, `TelcoPort`.
- **Origem:** brief; PLAN §3.3.

#### RN-157 — Kanban
- **Enunciado:** `lead` = `draft|sent|viewed|trial_active`. `negotiating` = `negotiating`. `won` = `accepted|pending_signature|contracted`. `lost` = `expired|lost|cancelled`.
- **Onde é aplicada:** painel revenda.
- **Origem:** brief kanban columns.

#### RN-158 — Marca em runtime
- **Enunciado:** Folhas A4 / página pública usam `tenancy.reseller_branding` do `Host`. Sem SCSS compilado por tenant.
- **Onde é aplicada:** `sales`, `tenancy`.
- **Origem:** brief §2.

#### RN-159 — Vendedor não inventa tarifa
- **Enunciado:** `reseller_seller` escolhe plano publicado da revenda e quantidades. Não edita unitários na proposta. Desconto = outro plano, não campo livre (`PADRÃO PROPOSTO` D-DOM-58: sem desconto avulso).
- **Onde é aplicada:** `sales`.
- **Origem:** PADRÃO PROPOSTO + RN-150.

---

### 1.22 Portabilidade

#### RN-160 — Enum proposto
- **Enunciado:** `PADRÃO PROPOSTO` (D-DOM-59) `portability_request.status`: `draft`, `submitted`, `pending_donor`, `accepted`, `rejected`, `completed`, `cancelled`. Brief não definiu enum — este é o canônico até 10-DECISIONS.
- **Onde é aplicada:** `customers.portability_requests`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-161 — Storage privado + TTL
- **Enunciado:** `portability_files` privado, `retained_until`. Proibido pasta pública previsível (dívida LGPD do legado).
- **Onde é aplicada:** `customers`.
- **Origem:** brief §5 R3/LGPD.

#### RN-162 — Quem abre
- **Enunciado:** `customer_admin` ou `reseller_admin`/`reseller_owner` no contexto do cliente, assinatura `trial|active|blocked_*` (não `cancelled`).
- **Onde é aplicada:** `customers`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-60).

#### RN-163 — Taxa
- **Enunciado:** `PADRÃO PROPOSTO` (D-BIZ-24): item avulso na fatura/statement do ciclo da `completed`, tarifa da base de preços. Sem preço na base, o pedido não sai de `draft`.
- **Onde é aplicada:** `billing`, `pricing`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-164 — Conclusão aloca DID
- **Enunciado:** `completed` → `telco.dids` ligado à assinatura + `insertDid`. Pró-rata a partir da data de `completed`.
- **Onde é aplicada:** `telco`, `billing`.
- **Origem:** PLAN marketplace DID.

#### RN-165 — Operação
- **Enunciado:** `vc1_ops` move `submitted` → `pending_donor` → `accepted|rejected`. `rejected` pode voltar a `draft` para novo upload.
- **Onde é aplicada:** Filament ops.
- **Origem:** PADRÃO PROPOSTO (D-DOM-61).

---

### 1.23 Alteração de plano no meio do ciclo

#### RN-166 — Upgrade imediato
- **Enunciado:** `PADRÃO PROPOSTO` (D-DOM-62): **upgrade** = maior `sell_price_cents` (pacote) ou maior `commitment_cents` (mínimo), ou aumento de franquia/canais incluídos. Aplica na hora: cobra-se a **diferença pró-rata** dos dias restantes (inclusive hoje) entre o plano novo e o antigo. Franquias: passam a ser as do plano novo **pró-rata do restante**, somando o já usado no ciclo (se já usou mais que a nova franquia pró-rata, `charge`/`block` do plano **novo** vale imediatamente).
- **Exemplo:** Basic R$ 199 → Avançado R$ 450 no dia 15/30: diferença 251 × 16/30 = R$ 133,87.
- **Onde é aplicada:** `catalog`, `billing`, `customers`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-167 — Downgrade só na virada
- **Enunciado:** `PADRÃO PROPOSTO`: **downgrade** (menor preço/compromisso/franquia) agenda `effective_at` = próximo dia 1. No ciclo corrente permanece o plano antigo.
- **Onde é aplicada:** `customers`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-62).

#### RN-168 — Fidelidade no upgrade/downgrade
- **Enunciado:** `PADRÃO PROPOSTO`: upgrade **mantém** a data-fim da fidelidade original (não reinicia). Downgrade durante fidelidade **recusado** (use cancelamento com multa ou aguarde o prazo).
- **Onde é aplicada:** `customers`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-63).

#### RN-169 — Extra de DID/canal não é mudança de plano
- **Enunciado:** Marketplace de DID/canal no commitment (RN-031) ou além do incluído no pacote (RN-026) não passa por upgrade/downgrade.
- **Onde é aplicada:** `customers`, `telco`.
- **Origem:** PRODUCTS §2.2 / §6.

#### RN-170 — Snapshot
- **Enunciado:** Upgrade grava nova `plan_versions` na assinatura e novo snapshot de tarifas. Histórico de rating do ciclo permanece; linhas a partir de agora usam o novo sell.
- **Onde é aplicada:** `customers`, `rating`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-64).

---

### 1.24 Mudança de `billing_mode` da revenda

#### RN-171 — Só no início do ciclo
- **Enunciado:** `PADRÃO PROPOSTO`: `reseller.billing_mode` não muda em D=2..fim. Staff agenda `pending_billing_mode` + referência de aditivo meSign, efetivado pelo job do dia 1 **antes** de emitir faturas daquele ciclo. STFC expirada **não** altera `billing_mode` automaticamente (RN-136).
- **Exemplo:** Pedido em 12/out → vale 1º/nov.
- **Onde é aplicada:** `tenancy`, `billing`.
- **Origem:** pedido do operador; PADRÃO PROPOSTO (D-DOM-65).

#### RN-172 — Quem muda
- **Enunciado:** Só `vc1_admin`. A revenda consulta, não altera.
- **Onde é aplicada:** `identity`, Filament.
- **Origem:** PRODUCTS §4 (“definido pela VC1 no cadastro”); PADRÃO PROPOSTO para a mudança posterior (D-DOM-66).

#### RN-173 — Guard para `reseller_invoices`
- **Enunciado:** Efetivar esse modo exige STFC verificado e validade cobrindo o ciclo que se inicia. Senão a agenda falha e permanece `vc1_invoices`.
- **Onde é aplicada:** `tenancy`.
- **Origem:** PRODUCTS §4.

#### RN-174 — In-flight
- **Enunciado:** Faturas `issued`/`overdue` do modo antigo **terminam** no modo antigo (mePay/NFCom ou statement já emitido). Payout do ciclo fechado não se recalcula. O novo modo vale para o ciclo que **começa**.
- **Onde é aplicada:** `billing`.
- **Origem:** PADRÃO PROPOSTO (D-DOM-67).

#### RN-175 — Contrato do cliente final
- **Enunciado:** Mudar para `vc1_invoices` exige novo instrumento meSign (contratada VC1) para cada assinatura `active` **antes** do ciclo efetivo, ou a assinatura não é faturada pela VC1 e permanece bloqueada para originação até assinar (`PADRÃO PROPOSTO` D-DOM-68). Mudar para `reseller_invoices` exige a revenda apresentar o contrato dela (upload) ou o sistema gera um aditivo — D-DOM-68 propõe: **aditivo meSign** nos dois sentidos.
- **Onde é aplicada:** `sales`, `customers`.
- **Origem:** PADRÃO PROPOSTO.

#### RN-176 — Venda direta (sem funil público)
- **Enunciado:** Fluxo “novo cliente” no painel cria **proposta interna** + contrato meSign antes de provisionar SIP/DID. Não ativa tronco com `stage` anterior a `contracted` / envelope completed.
- **Onde é aplicada:** `sales`, `customers`, `telco`.
- **Origem:** Revisão independente rodada 1.

#### RN-177 — Reembolso/chargeback pós-repasse
- **Enunciado:** Após `payout.paid`, estornos entram em `billing.payout_adjustments`. Linha negativa no **próximo** payout; se ainda negativo, vira linha na fatura VC1→revenda do ciclo.
- **Onde é aplicada:** `billing`, `PaymentPort`.
- **Origem:** Revisão independente rodada 1.

#### RN-178 — Ordem determinística de rating
- **Enunciado:** CDRs de uma assinatura tarifados em ordem `(started_at, legacy_cdr_id)` sob lock por assinatura (Redis + advisory PG).
- **Onde é aplicada:** `rating`.
- **Origem:** Revisão independente rodada 1 (D-ARQ-17).

---

## 2. Máquinas de estado

Convenção de cada transição: **trigger** / **guard** / **efeitos colaterais**. Enums idênticos ao brief (portabilidade: D-DOM-59).

### 2.1 `reseller.status`

```mermaid
stateDiagram-v2
  [*] --> draft
  draft --> onboarding: start_onboarding
  draft --> terminated: abort
  onboarding --> active: provisioned
  onboarding --> draft: rollback
  onboarding --> terminated: abort
  active --> suspended: suspend
  suspended --> active: resume
  active --> terminated: terminate
  suspended --> terminated: terminate
  terminated --> [*]
```

| Transição | Trigger | Guard | Efeitos |
|-----------|---------|-------|---------|
| `[*]→draft` | `vc1_admin` cria revenda | CNPJ único; slug não reservado (`admin`, `cliente`, `api`, …) | `tenancy.resellers` insert; `audit` |
| `draft→onboarding` | staff inicia wizard | `billing_mode` escolhido; se `reseller_invoices` então STFC verificado | cria Host DNS (`DnsPort`); inicia `ProvisioningPort` projeto legado; notifica ops |
| `onboarding→active` | ops confirma | `legacy_project_id` preenchido; usuário `reseller_owner` existe; Host resolve | e-mail de boas-vindas; funil liga |
| `onboarding→draft` | ops devolve | nenhum cliente `contracted` | não apaga legado sem aprovação operador |
| `active→suspended` | dunning D+10 da fatura da revenda; STFC (RN-137); manual `vc1_admin` | — | funil off (RN-127); `TelcoPort` no uso próprio se inadimplência |
| `suspended→active` | pagamento / STFC renovada / manual | sem fatura `overdue` da revenda; STFC ok se modo exigir | reabre funil; reavalia bloqueios |
| `*→terminated` | `vc1_admin` após notice | sem invoices `issued/overdue` ou write-off feito | cancela subscriptions; DNS permanece X dias (D-DOM-69: 30) |
| `draft/onboarding→terminated` | abort | — | sem provisionar clientes |

### 2.2 `customer.status`

```mermaid
stateDiagram-v2
  [*] --> lead
  lead --> trial: trial_start
  lead --> active: contract_without_trial
  lead --> cancelled: discard
  trial --> active: convert
  trial --> cancelled: trial_expire_or_quit
  active --> suspended: all_subs_blocked
  suspended --> active: any_sub_unblocked
  active --> cancelled: churn
  suspended --> cancelled: churn
  cancelled --> [*]
```

| Transição | Trigger | Guard | Efeitos |
|-----------|---------|-------|---------|
| `lead` | proposta `sent` cria/associa customer | documento válido | — |
| `lead→trial` | proposta `trial_active` | plano `trial_enabled` | `subscription.trial`; provisiona |
| `lead→active` | `contracted` sem trial | meSign completed | provisiona definitivo |
| `trial→active` | `contracted` | — | RN-048 promove subscriber |
| `*→cancelled` | cancelamento RN-053 | multa calculada se couber | `TelcoPort` off; DIDs retenção |
| `active→suspended` | **todas** as subscriptions em `blocked_*` | — | painel cliente mostra bloqueio |
| `suspended→active` | ao menos uma sub `active` | — | — |

### 2.3 `subscription.status`

```mermaid
stateDiagram-v2
  [*] --> trial
  [*] --> active
  trial --> active: convert
  trial --> cancelled: expire_or_quit
  active --> blocked_credit: wallet_zero
  active --> blocked_limit: exposure_100
  active --> blocked_overdue: dunning_d10
  active --> blocked_manual: staff_or_reseller
  blocked_credit --> active: recharge
  blocked_credit --> blocked_manual: staff
  blocked_credit --> blocked_overdue: dunning_d10
  blocked_limit --> active: limit_raised
  blocked_limit --> blocked_overdue: dunning_d10
  blocked_limit --> blocked_manual: staff
  blocked_overdue --> active: paid
  blocked_overdue --> blocked_manual: staff
  blocked_manual --> active: unblock
  blocked_credit --> cancelled: churn
  blocked_limit --> cancelled: churn
  blocked_overdue --> cancelled: churn
  blocked_manual --> cancelled: churn
  active --> cancelled: churn
  cancelled --> [*]
```

Toda transição para `blocked_*` / `cancelled`: `TelcoPort` block + `NotificationPort` + `block_events`. Toda volta a `active`: RN-126 reavalia precedência **antes** do SOAP unblock. `trial` não usa carteira de produção (RN-042). Overage block não aparece nesta máquina (RN-024).

### 2.4 `proposal.stage`

```mermaid
stateDiagram-v2
  [*] --> draft
  draft --> sent: send
  draft --> cancelled: abort
  sent --> viewed: pin_ok
  sent --> expired: validity
  sent --> cancelled: abort
  viewed --> trial_active: start_trial
  viewed --> negotiating: seller_move
  viewed --> accepted: customer_accept
  viewed --> expired: validity
  viewed --> lost: seller_lost
  trial_active --> accepted: customer_accept
  trial_active --> negotiating: seller_move
  trial_active --> expired: trial_end
  trial_active --> lost: seller_lost
  negotiating --> accepted: customer_accept
  negotiating --> lost: seller_lost
  negotiating --> expired: validity
  accepted --> pending_signature: mesign_create
  pending_signature --> contracted: envelope_completed
  pending_signature --> lost: envelope_declined
  contracted --> [*]
```

| Transição | Trigger | Guard | Efeitos |
|-----------|---------|-------|---------|
| `draft→sent` | vendedor envia | preço servidor ok; plano publicado | snapshot imutável; PIN; e-mail; kanban `lead` |
| `sent→viewed` | PIN correto | validade ok | `proposal_events` |
| `viewed→trial_active` | cliente/vendedor inicia trial | `trial_enabled`; RN-046 | `subscription.trial`; `ProvisioningPort` |
| `*→accepted` | aceite na página pública | snapshot íntegro | trava itens |
| `accepted→pending_signature` | sistema | contrato gerado | `SignaturePort` envelope |
| `pending_signature→contracted` | webhook `envelope.completed` HMAC ok | — | `contracts`; provisiona; kanban `won` |
| `*→expired` | job validade / fim trial sem aceite | estágio não terminal ganho | `TelcoPort` se havia trial |
| `*→lost`/`cancelled` | vendedor / admin | não `contracted` | idem trial cleanup |

### 2.5 `invoice.status`

```mermaid
stateDiagram-v2
  [*] --> draft
  draft --> issued: close_cycle
  draft --> cancelled: abort_close
  issued --> paid: mepay_paid
  issued --> overdue: past_due
  issued --> cancelled: cancel_unpaid
  overdue --> paid: mepay_paid
  overdue --> cancelled: cancel_unpaid
  overdue --> written_off: finance_writeoff
  paid --> [*]
  cancelled --> [*]
  written_off --> [*]
```

| Transição | Trigger | Guard | Efeitos |
|-----------|---------|-------|---------|
| `draft→issued` | job dia 1 | cycle open; totais conferidos | mePay charge (se valor > 0); `fiscal_documents.pending` se RN-139 |
| `issued→paid` | webhook mePay | valor integral | RN-124 unblock; entra payout se customer/`vc1_invoices` |
| `issued→overdue` | job D+1 | não pago | dunning RN-129 |
| `overdue→written_off` | `vc1_finance` | motivo obrigatório | RN-131 |
| `issued/overdue→cancelled` | `vc1_finance` | não `paid` | tenta RN-145 cancel NF; estorna charge se existir |

### 2.6 `payout.status`

```mermaid
stateDiagram-v2
  [*] --> calculating
  calculating --> pending_commission_invoice: positive
  calculating --> settled_zero: zero
  calculating --> netted_to_invoice: negative
  pending_commission_invoice --> approved: finance_ok
  approved --> paid: ted_recorded
  netted_to_invoice --> [*]
  paid --> [*]
```

| Transição | Trigger | Guard | Efeitos |
|-----------|---------|-------|---------|
| `calculating` | job pós-fechamento | `billing_mode=vc1_invoices` | aplica RN-094 |
| `→pending_commission_invoice` | `payout_raw > 0` | — | notifica `reseller_finance`; aguarda upload |
| `→settled_zero` | `payout_raw = 0` | — | sem nota de comissão; sem fatura revenda |
| `→netted_to_invoice` | `payout_raw < 0` | — | cria `invoices` `party=reseller`; NFCom; cobrança manual MVP |
| `→approved` | `vc1_finance` | nota valor == payout (D-DOM-34) | fila de TED |
| `→paid` | finance registra TED | comprovante | e-mail; sem `PaymentPort` payout até mePay ter o produto |

### 2.7 `fiscal_document.status`

```mermaid
stateDiagram-v2
  [*] --> pending
  pending --> imported: import_ok
  pending --> rejected: import_fail
  imported --> authorized: consulta_ok
  imported --> rejected: consulta_reject
  rejected --> pending: retry
  authorized --> cancelled: sefaz_cancel
  cancelled --> [*]
```

| Transição | Trigger | Guard | Efeitos |
|-----------|---------|-------|---------|
| `pending→requested` | mePay aceita solicitação fiscal | `charged_cents` bate | grava `mepay_fiscal_request_id` |
| `requested→issued` | webhook `fiscal.issued` + chave **44 dígitos** | chave length=44 | marca emitida; **nunca** só no 2xx inicial |
| `imported→rejected` | SEFAZ rejeita | — | alerta finance; invoice segue `issued` |
| `rejected→pending` | finance corrige | attempts < 5 | nova attempt |
| `issued→cancelled` | cancelamento via mePay/emissor | invoice não `paid` | RN-145 |

### 2.8 `portability_request.status` (PADRÃO PROPOSTO D-DOM-59)

```mermaid
stateDiagram-v2
  [*] --> draft
  draft --> submitted: submit
  draft --> cancelled: abort
  submitted --> pending_donor: ops_send
  submitted --> cancelled: abort
  pending_donor --> accepted: donor_ok
  pending_donor --> rejected: donor_nok
  accepted --> completed: did_inserted
  rejected --> draft: resubmit
  rejected --> cancelled: abort
  completed --> [*]
  cancelled --> [*]
```

| Transição | Trigger | Guard | Efeitos |
|-----------|---------|-------|---------|
| `draft→submitted` | customer/reseller | arquivos privados; preço de taxa existe | notifica `vc1_ops` |
| `submitted→pending_donor` | `vc1_ops` | — | processo Anatel/doadora **fora** do sistema (registro) |
| `pending_donor→accepted` | ops | — | — |
| `accepted→completed` | `TelcoPort.insertDid` ok | — | `dids`; pró-rata; linha de taxa no ciclo |
| `rejected→draft` | novo upload | — | TTL dos arquivos antigos |

### 2.9 Tabela de precedência de bloqueio (assinatura)

Cópia operacional de RN-120 para o implementador:

| Prioridade | Motivo | Originação | Quem desbloqueia | Automático quando |
|-----------:|--------|------------|------------------|-------------------|
| 1 | `cancelled` | off definitiva | ninguém | — |
| 2 | `blocked_manual` (ator VC1) | off | `vc1_admin`, `vc1_ops` | não |
| 3 | `blocked_manual` (ator revenda) | off | revenda admin/owner ou VC1 ops/admin | não |
| 4 | `blocked_overdue` | off | pagamento integral / write-off+admin | webhook `paid` |
| 5 | `blocked_limit` | off | aumento de limite | exposição < 100% |
| 6 | `blocked_credit` | off | recarga / adjust finance | saldo > 0 |
| 7 | overage `block` (paralelo) | off **originação inteira** (`blockOutgoingCalls`) | próximo ciclo / upgrade / recarga franquia | nova franquia |
| 8 | `destination=other` | sempre off | — | — |
| 9 | livre | on | — | `active`/`trial` |

Se dois motivos existem, persiste o de menor número de prioridade (mais grave). SOAP unblock só na linha 9 efetiva.

---

## 3. Matriz de permissões

`PADRÃO PROPOSTO` (D-DOM-41) para o recorte fino; papéis são os do brief. Legenda: **S** = sim; **P** = só o próprio tenant/cliente; **L** = leitura; **—** = não.

| Ação | `vc1_admin` | `vc1_finance` | `vc1_ops` | `vc1_support` | `reseller_owner` | `reseller_admin` | `reseller_finance` | `reseller_seller` | `customer_admin` | `customer_user` |
|------|:-----------:|:-------------:|:---------:|:-------------:|:----------------:|:----------------:|:------------------:|:-----------------:|:----------------:|:---------------:|
| Publicar `price_base` | S | — | — | — | — | — | — | — | — | — |
| Editar rascunho de faixas VC1 | S | L | L | L | — | — | — | — | — | — |
| Cadastrar revenda / `billing_mode` | S | L | L | L | L (próprio) | L | L | — | — | — |
| Verificar STFC | S | — | S | L | upload próprio | upload | L | — | — | — |
| Impersonate revenda | S | — | — | S | — | — | — | — | — | — |
| Impersonate cliente final | S | — | — | S | S (P) | S (P) | — | — | — | — |
| Criar/editar plano | L | L | L | L | S | S | L | L | — | — |
| Clonar pacote sugerido | L | L | L | L | S | S | — | — | — | — |
| Editar `reseller_tier_rows` | L | L | L | L | S | S | L | — | — | — |
| Wizard proposta | L | L | L | L | S | S | — | S | — | — |
| Marcar proposta lost | L | — | — | L | S | S | — | S | — | — |
| Aprovar `payout` | S | S | — | — | — | — | upload nota | — | — | — |
| Registrar TED payout | S | S | — | — | — | — | — | — | — | — |
| Write-off fatura | S | S | — | — | — | — | — | — | — | — |
| Emitir/retentar NFCom | S | S | — | — | — | — | — | — | — | — |
| Definir limite crédito cliente | L | L | L | L | S | S | S | — | L | — |
| Definir limite crédito revenda | S | S | L | L | L próprio | L | L | — | — | — |
| Recarga pré-paga | L | adjust | — | L | S (P) | S (P) | S (P) | — | S (própria, via mePay se `vc1_invoices`) | — |
| `blocked_manual` aplicar | S | — | S | — | S (P) | S (P) | — | — | — | — |
| Desbloquear manual VC1 | S | — | S | — | — | — | — | — | — | — |
| Desbloqueio automático pag/recarga | sist. | sist. | sist. | — | — | — | — | — | paga | — |
| Portabilidade ops | S | — | S | L | abre P | abre P | — | — | abre | — |
| Estoque DID / insertDid | S | — | S | L | solicita P | solicita P | — | — | solicita | — |
| Ver CDR cost+sell | S | S | S | S | S (P) | S (P) | S (P) | L sell | L sell próprio | L sell próprio |
| Ver CDR só sell | — | — | — | — | — | — | — | S (P) | S | S |
| Usuários do tenant | S | — | — | L | S | S | — | — | S próprios | — |
| Branding / slug | S | — | L | L | S | S | — | — | — | — |
| Agendar `billing_mode` | S | L | L | L | L | L | L | — | — | — |
| Encerrar revenda | S | — | — | — | solicita | — | — | — | — | — |
| Credencial SIP / rotacionar senha | L | — | S | L | L P | L P | — | — | S | L |
| API tokens revenda | S | — | — | — | S | S | — | — | — | — |
| Audit log | S | S (fin) | S (ops) | L | L P | L P | L P | — | — | — |

Impersonate gera evento em `audit.audit_log` e **não** permite publicar base de preços nem aprovar payout mesmo se o staff for `vc1_admin` **dentro** da sessão impersonada (`PADRÃO PROPOSTO` D-DOM-70: impersonate é leitura + ações de suporte no contexto da revenda, write financeiro VC1 bloqueado).

---

## Itens para 10-DECISIONS

| ID | Item | Padrão proposto |
|----|------|-----------------|
| D-DOM-01 | Publicação da base de preços | Uma versão `published` vigente; publicada é imutável; só `vc1_admin` publica |
| D-DOM-02 | Não-regressão de tarifas entre faixas | Recusar publicar se faixa de compromisso maior tiver unitário estritamente maior |
| D-DOM-03 | Nova base vs contratos existentes | Não altera snapshot; adesão explícita no próximo ciclo |
| D-DOM-04 | Ciência de margem negativa | Exige `negative_margin_acknowledged_at`; não bloqueia |
| D-DOM-05 | Snapshot de tarifas na assinatura | Sim; tabela nova só no próximo ciclo se a revenda aplicar |
| D-DOM-06 | Linhas da tabela da revenda | Uma linha por faixa VC1; desliga com `offered=false`, não delete |
| D-DOM-07 | Excedente `block` vs status | Não muda `subscription.status`; bloqueio por destino |
| D-DOM-08 | Default da tarifa de excedente | Copia unitários da menor faixa ofertada da revenda se o plano não informar |
| D-DOM-09 | Cascade de suggested_packages | Clone independente; sem cascade |
| D-DOM-10 | Kind dos templates | Aceita `package` e `commitment` |
| D-DOM-11 | Fatura durante trial | Não emite; CDR trial `sell_cents=0` |
| D-DOM-12 | Custo de trial no mínimo da revenda | Não conta (absorvido pela VC1) |
| D-DOM-13 | Destinos do trial | `landline_br` + `mobile_br`; `other` bloqueado |
| D-DOM-14 | Quantidade de trials | Um por `(reseller_id, customer_id, plan_id)` vitalício |
| D-DOM-15 | Conversão trial→pago | Reusa o subscriber SipPulse |
| D-DOM-16 | Fidelidade plano vs faixa | Plano vence se não nulo |
| D-DOM-17 | Workflow de cancelamento | Cliente solicita; revenda/VC1 executa conforme contratada |
| D-DOM-18 | Reembolso do ciclo em curso | Sem reembolso |
| D-DOM-19 | DID após cancelamento | Retenção 7 dias para port-out, depois estoque |
| D-DOM-20 | Multa de fidelidade no payout | Não entra no Σ(sell−cost) de voz; fica com quem fatura o cliente |
| D-DOM-21 | Classificador de destino | Prefixos E.164 BR no PG; não usar rate_plan SipPulse como venda |
| D-DOM-22 | Chamada zero/não atendida | Não cobra |
| D-DOM-23 | Timezone e dono do CDR | `America/Sao_Paulo`; ciclo = início da chamada |
| D-DOM-24 | Remoção de DID/canal no mês | Sem crédito dos dias restantes |
| D-DOM-25 | Franquia de pacote no pró-rata de ativação | Franquia × mesma fração de dias |
| D-DOM-26 | Vencimento em fim de semana | Não desloca (dia 10 permanece 10) |
| D-DOM-27 | Idempotência do fechamento | Chave única por cycle/party/subscription |
| D-DOM-28 | Reabrir ciclo | Proibido; só fatura/nota de ajuste |
| D-DOM-29 | Fechamento de assinatura bloqueada | Gera fatura/extrato normalmente (mínimo/mensalidade) |
| D-DOM-30 | Recarga pré-paga vs fatura de ciclo | Recarga = invoice/charge imediata; ciclo commitment não cobra de novo se a carteira cobriu |
| D-DOM-31 | Detalhamento da fatura da revenda | Uso próprio + subtotal por cliente (ou shortfall/margem no netted) |
| D-DOM-32 | Correção de statement | Novo statement de ajuste, sem overwrite |
| D-DOM-33 | Export do extrato | PDF+CSV; sem e-mail automático ao cliente |
| D-DOM-34 | Tolerância da nota de comissão | 0 cents |
| D-DOM-35 | Cardinalidade do payout | 1 por revenda por ciclo |
| D-DOM-36 | Primeira recarga de pacote pré-pago | ≥ pró-rata da mensalidade de ativação |
| D-DOM-37 | Pacote pré-pago no dia 1 | Debita mensalidade da carteira; se não der, `blocked_credit` sem dívida |
| D-DOM-38 | Repetição do alerta 80% | Uma vez por ciclo até recross |
| D-DOM-39 | Cap VC1 no limite do cliente | Sem cap no MVP |
| D-DOM-40 | Precedência de bloqueio | Tabela RN-120 / §2.9; reavaliar sempre antes do SOAP unblock |
| D-DOM-41 | Recorte fino da matriz | Conforme §3 |
| D-DOM-42 | Unblock manual da VC1 | Só `vc1_admin`/`vc1_ops` |
| D-DOM-43 | Unblock excepcional de overdue | Só `vc1_admin` (além de write-off finance) |
| D-DOM-44 | Revenda `suspended` vs originação dos finais | Não corta finais no `vc1_invoices`; corta uso próprio e novas ativações |
| D-DOM-45 | Dunning | Emissão; D−3; D+1 overdue; D+5 aviso bloqueio D+10; D+10 `blocked_overdue` |
| D-DOM-46 | Atraso da fatura da revenda | D+10 suspende a revenda |
| D-DOM-47 | Validação Anatel STFC | Manual no MVP |
| D-DOM-48 | Alerta de validade STFC | D-30 e D-7 |
| D-DOM-49 | STFC expirada | D-0 funil off; grace 30d; D+30 suspended; sem vc1_invoices auto antes E5 | PADRÃO | 02 §Itens | RN-136 |
| D-DOM-50 | STFC reprovada a posteriori | `suspended` + funil off |
| D-DOM-51 | Retry NFCom | Máx. 5 attempts |
| D-DOM-52 | Timeout emissão mePay | Permanece `requested`; retenta poll; não `issued` |
| D-DOM-53 | Cancelar NFCom de fatura já paga | Manual no MVP |
| D-DOM-54 | Guard de centavos NF vs fatura | Recusa import se divergir 1 cent |
| D-DOM-55 | Cardinalidade fiscal | 1 `fiscal_documents` por invoice; attempts filhas |
| D-DOM-56 | Editar proposta já `sent` | Clonar para novo `draft`; snapshot imutável |
| D-DOM-57 | Validade da proposta | 15 dias a partir de `sent`; trial estende até `trial_ends_at` |
| D-DOM-58 | Desconto avulso na proposta | Inexistente; só via plano |
| D-DOM-59 | Enum de portabilidade | `draft`, `submitted`, `pending_donor`, `accepted`, `rejected`, `completed`, `cancelled` |
| D-DOM-60 | Quem abre portabilidade | `customer_admin` e admin/owner da revenda |
| D-DOM-61 | Ops de portabilidade | `vc1_ops` opera doadora |
| D-DOM-62 | Upgrade/downgrade no ciclo | Upgrade imediato com diferença pró-rata; downgrade só dia 1 |
| D-DOM-63 | Fidelidade no upgrade/downgrade | Upgrade mantém data-fim; downgrade recusado na fidelidade |
| D-DOM-64 | Rating após upgrade | Snapshot novo; CDR futuros no sell novo |
| D-DOM-65 | Mudança de `billing_mode` | Só job do dia 1 (agenda `pending_billing_mode`) |
| D-DOM-66 | Quem agenda o modo | Só `vc1_admin` |
| D-DOM-67 | Faturas in-flight na troca de modo | Terminam no modo antigo |
| D-DOM-68 | Reassinatura na troca de contratada | Aditivo meSign obrigatório; sem assinar, originação bloqueada no ciclo novo |
| D-DOM-69 | DNS após `terminated` | Retém 30 dias |
| D-DOM-70 | Impersonate | Auditado; bloqueia writes financeiros da VC1 (publicar base, aprovar payout) |
