PyNFSeNacionalGT 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. pynfsenacionalgt-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +50 -0
  2. pynfsenacionalgt-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. pynfsenacionalgt-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +36 -0
  4. pynfsenacionalgt-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  5. pynfsenacionalgt-0.1.0/.github/workflows/ci.yml +55 -0
  6. pynfsenacionalgt-0.1.0/.github/workflows/release.yml +28 -0
  7. pynfsenacionalgt-0.1.0/.gitignore +51 -0
  8. pynfsenacionalgt-0.1.0/CHANGELOG.md +34 -0
  9. pynfsenacionalgt-0.1.0/CLAUDE.md +91 -0
  10. pynfsenacionalgt-0.1.0/CODE_OF_CONDUCT.md +31 -0
  11. pynfsenacionalgt-0.1.0/CONTRIBUTING.md +55 -0
  12. pynfsenacionalgt-0.1.0/LICENSE +21 -0
  13. pynfsenacionalgt-0.1.0/PKG-INFO +301 -0
  14. pynfsenacionalgt-0.1.0/README.md +248 -0
  15. pynfsenacionalgt-0.1.0/SECURITY.md +35 -0
  16. pynfsenacionalgt-0.1.0/docs/conhecimento-fiscal.md +214 -0
  17. pynfsenacionalgt-0.1.0/docs/roadmap.md +63 -0
  18. pynfsenacionalgt-0.1.0/examples/config-exemplo.json +36 -0
  19. pynfsenacionalgt-0.1.0/examples/config-exemplo.jsonc +48 -0
  20. pynfsenacionalgt-0.1.0/examples/emitir_exemplo.py +26 -0
  21. pynfsenacionalgt-0.1.0/pyproject.toml +84 -0
  22. pynfsenacionalgt-0.1.0/requirements-dev.txt +913 -0
  23. pynfsenacionalgt-0.1.0/src/pynfsenacional/__init__.py +26 -0
  24. pynfsenacionalgt-0.1.0/src/pynfsenacional/assinatura.py +46 -0
  25. pynfsenacionalgt-0.1.0/src/pynfsenacional/certificado.py +149 -0
  26. pynfsenacionalgt-0.1.0/src/pynfsenacional/cli.py +83 -0
  27. pynfsenacionalgt-0.1.0/src/pynfsenacional/config.py +229 -0
  28. pynfsenacionalgt-0.1.0/src/pynfsenacional/danfse.py +34 -0
  29. pynfsenacionalgt-0.1.0/src/pynfsenacional/documentos.py +43 -0
  30. pynfsenacionalgt-0.1.0/src/pynfsenacional/dps.py +136 -0
  31. pynfsenacionalgt-0.1.0/src/pynfsenacional/emissor.py +150 -0
  32. pynfsenacionalgt-0.1.0/src/pynfsenacional/relogio.py +41 -0
  33. pynfsenacionalgt-0.1.0/src/pynfsenacional/sefin.py +181 -0
  34. pynfsenacionalgt-0.1.0/tests/conftest.py +79 -0
  35. pynfsenacionalgt-0.1.0/tests/golden/gabarito_config.json +26 -0
  36. pynfsenacionalgt-0.1.0/tests/golden/gabarito_dps_assinado.xml +18 -0
  37. pynfsenacionalgt-0.1.0/tests/golden/regenerar_gabarito.sh +52 -0
  38. pynfsenacionalgt-0.1.0/tests/test_certificado.py +61 -0
  39. pynfsenacionalgt-0.1.0/tests/test_cli.py +67 -0
  40. pynfsenacionalgt-0.1.0/tests/test_danfse.py +57 -0
  41. pynfsenacionalgt-0.1.0/tests/test_dps.py +103 -0
  42. pynfsenacionalgt-0.1.0/tests/test_emissor.py +74 -0
  43. pynfsenacionalgt-0.1.0/tests/test_golden.py +128 -0
  44. pynfsenacionalgt-0.1.0/tests/test_sefin.py +109 -0
  45. pynfsenacionalgt-0.1.0/tests/test_smoke.py +46 -0
  46. pynfsenacionalgt-0.1.0/tests/test_validacao.py +142 -0
@@ -0,0 +1,50 @@
1
+ name: 🐞 Reportar um bug
2
+ description: Algo não funcionou como esperado
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Obrigado por reportar! ⚠️ **NÃO cole dados reais** — nada de certificados (`.pfx`), senhas,
9
+ CNPJ/CPF ou XML/PDF de notas reais. Reproduza com dados **fictícios** (ex.: CNPJ `11222333000181`).
10
+ Para **vulnerabilidades de segurança**, use o canal privado (ver `SECURITY.md`), não esta issue.
11
+ - type: textarea
12
+ id: o-que-aconteceu
13
+ attributes:
14
+ label: O que aconteceu?
15
+ description: Descreva o problema e o que você esperava que acontecesse.
16
+ validations:
17
+ required: true
18
+ - type: textarea
19
+ id: reproduzir
20
+ attributes:
21
+ label: Como reproduzir
22
+ description: Passos / trecho de código mínimo (com dados fictícios).
23
+ render: python
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: erro
28
+ attributes:
29
+ label: Mensagem de erro / E-code do SEFIN
30
+ description: Cole o traceback ou o código de erro (ex.: E0312). Remova qualquer dado real.
31
+ render: text
32
+ - type: input
33
+ id: versao
34
+ attributes:
35
+ label: Versão do PyNFSeNacional
36
+ placeholder: "0.1.0.dev0"
37
+ validations:
38
+ required: true
39
+ - type: input
40
+ id: python
41
+ attributes:
42
+ label: Versão do Python
43
+ placeholder: "3.12"
44
+ validations:
45
+ required: true
46
+ - type: dropdown
47
+ id: ambiente
48
+ attributes:
49
+ label: Ambiente
50
+ options: ["homologacao", "producao", "não cheguei a enviar (validação/local)"]
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: 🔒 Vulnerabilidade de segurança
4
+ url: https://github.com/Gomes343/PyNFSeNacional/security/advisories/new
5
+ about: Reporte em PRIVADO (não abra issue pública). Ver SECURITY.md.
6
+ - name: 💬 Dúvidas e discussões
7
+ url: https://github.com/Gomes343/PyNFSeNacional/discussions
8
+ about: Para perguntas de uso, ideias e ajuda da comunidade.
@@ -0,0 +1,36 @@
1
+ name: 💡 Sugerir uma melhoria
2
+ description: Propor um recurso, suporte a município/regime, ou melhoria
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: textarea
6
+ id: problema
7
+ attributes:
8
+ label: Qual problema isso resolve?
9
+ description: O contexto fiscal/operacional por trás da ideia.
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: proposta
14
+ attributes:
15
+ label: Proposta
16
+ description: O que você gostaria que o pacote fizesse.
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: alternativas
21
+ attributes:
22
+ label: Alternativas consideradas
23
+ - type: dropdown
24
+ id: area
25
+ attributes:
26
+ label: Área
27
+ options:
28
+ - "Emissão (DPS/assinatura/transporte)"
29
+ - "DANFSe (PDF)"
30
+ - "Validação fiscal / E-codes"
31
+ - "Suporte a município/regime"
32
+ - "Eventos (cancelamento)"
33
+ - "IBS/CBS (reforma tributária)"
34
+ - "CLI / DX"
35
+ - "Documentação"
36
+ - "Outro"
@@ -0,0 +1,17 @@
1
+ <!-- Obrigado pela contribuição! Preencha o que se aplica. -->
2
+
3
+ ## O que muda e por quê
4
+
5
+ <!-- Descreva a mudança e a motivação (o "porquê", não só o "como"). -->
6
+
7
+ ## Como testei
8
+
9
+ <!-- pytest / emissão em homologação / etc. Use sempre dados fictícios. -->
10
+
11
+ ## Checklist
12
+
13
+ - [ ] `ruff check .`, `mypy` e `pytest` passam localmente
14
+ - [ ] **Nenhum** dado sensível no diff (certificado, senha, `.env`, CNPJ/CPF ou nota real)
15
+ - [ ] Regra fiscal nova documentada em `docs/conhecimento-fiscal.md` (se aplicável)
16
+ - [ ] Mexeu em DPS/assinatura? O *golden* foi atualizado e o motivo está explicado (se aplicável)
17
+ - [ ] Atualizei o `CHANGELOG.md` (se for mudança relevante ao usuário)
@@ -0,0 +1,55 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master, main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install (package + dev)
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install -e ".[dev]"
30
+
31
+ - name: Lint (ruff)
32
+ run: ruff check .
33
+
34
+ - name: Type-check (mypy)
35
+ run: mypy
36
+
37
+ - name: Tests (pytest)
38
+ # requires_cert: precisa de um .pfx real — roda só localmente, nunca no CI.
39
+ run: pytest -m "not requires_cert"
40
+
41
+ lock:
42
+ # Verifica que o lock com hashes instala de forma reproduzível (ambiente canônico).
43
+ runs-on: ubuntu-latest
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+ - uses: actions/setup-python@v5
47
+ with:
48
+ python-version: "3.14"
49
+ - name: Install from locked requirements
50
+ run: |
51
+ python -m pip install --upgrade pip
52
+ pip install --require-hashes -r requirements-dev.txt
53
+ pip install -e . --no-deps
54
+ - name: Smoke
55
+ run: pytest -m "not requires_cert and not golden"
@@ -0,0 +1,28 @@
1
+ name: Release
2
+
3
+ # Publica no PyPI ao empurrar uma tag vX.Y.Z. Usa Trusted Publishing (OIDC) —
4
+ # sem token/segredo no repo: configurar o publisher confiável no PyPI antes.
5
+ on:
6
+ push:
7
+ tags: ["v*"]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ build-publish:
14
+ runs-on: ubuntu-latest
15
+ environment: pypi
16
+ permissions:
17
+ id-token: write # OIDC para o Trusted Publishing do PyPI
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.12"
23
+ - name: Build (sdist + wheel)
24
+ run: |
25
+ python -m pip install --upgrade pip build
26
+ python -m build
27
+ - name: Publish to PyPI
28
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,51 @@
1
+ # ── Segredos e dados de cliente (NUNCA versionar) ─────────────────────────────
2
+ # Certificados A1 ICP-Brasil e qualquer material criptográfico
3
+ *.pfx
4
+ *.p12
5
+ *.pem
6
+ *.key
7
+ *.crt
8
+ *.cer
9
+ *.der
10
+ *.jks
11
+ *.keystore
12
+ certs/
13
+ # Configs reais de cliente (contêm CNPJ, senha do certificado, etc.)
14
+ config/
15
+ !examples/config-exemplo.jsonc
16
+ !examples/config-exemplo.json
17
+ # Variáveis de ambiente e segredos (.env, secrets.env, *.env, etc.)
18
+ .env
19
+ .env.*
20
+ *.env
21
+ secrets*
22
+
23
+ # ── Saídas de emissão (XML/PDF/contadores) ────────────────────────────────────
24
+ out/
25
+ *.xml
26
+ *.pdf
27
+ !docs/**/*.pdf
28
+ # Gabarito de teste (XML assinado pela referência PHP, cert de teste descartável — sem
29
+ # chave privada, sem dado real): versionado de propósito p/ o golden rodar no CI.
30
+ !tests/golden/*.xml
31
+
32
+ # ── Python ────────────────────────────────────────────────────────────────────
33
+ __pycache__/
34
+ *.py[cod]
35
+ *.egg-info/
36
+ .eggs/
37
+ build/
38
+ dist/
39
+ .venv/
40
+ venv/
41
+ env/
42
+ .pytest_cache/
43
+ .ruff_cache/
44
+ .mypy_cache/
45
+ .coverage
46
+ htmlcov/
47
+
48
+ # ── Editores / SO ─────────────────────────────────────────────────────────────
49
+ .vscode/
50
+ .idea/
51
+ .DS_Store
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ Formato baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/);
4
+ versionamento [SemVer](https://semver.org/lang/pt-BR/).
5
+
6
+ ## [0.1.0] - 2026-06-24
7
+
8
+ ### Adicionado
9
+ - **Emissão ponta a ponta** de NFS-e pela API SEFIN Nacional (DPS):
10
+ `config` → `certificado` → `montar_dps` → `assinar` → **transporte mTLS** → `Nota`.
11
+ - `dps.montar_dps`/`id_dps`: montagem da DPS (lxml, ordem do XSD AnexoI) com a lógica
12
+ fiscal dos E-codes; o C14N do `infDPS` bate **byte a byte** com a referência PHP.
13
+ - `assinatura.assinar_dps`: XMLDSIG enveloped (RSA-SHA1) via `erpbrasil.assinatura` —
14
+ mesmo `DigestValue` do gabarito de referência.
15
+ - `sefin.SefinClient`: transporte mTLS (`requests-pkcs12`, PKCS#12 direto), `POST /nfse`
16
+ (gzip+base64), `verificarDps` (idempotência) e mapeamento de E-codes. **Emissão real validada
17
+ em homologação** (certificado A1 real, Simples Nacional/RJ: nNFSe + chave de 50 díg + DANFSe).
18
+ - Correção **E1229**: o XML assinado precisa do prolog `<?xml encoding="UTF-8"?>` (o SEFIN rejeita
19
+ sem ele) — `assinar_dps` reserializa com `xml_declaration=True`.
20
+ - `danfse.render`: DANFSe local (PDF) via `BrazilFiscalReport` ≥ 1.0 — **dependência opcional**
21
+ (`pip install "PyNFSeNacionalGT[danfse]"`); o núcleo de emissão não a puxa (import lazy).
22
+ - `config.validar`/`validar_tomador`: portão de validação fiscal (E0312/E0712/E1235…,
23
+ CPF/CNPJ mód-11) + loader tolerante (`ConfigError`).
24
+ - `Certificado`: leitura do `.pfx` A1 via `cryptography` (+ fallback de cifra legada §9).
25
+ - CLI `nfse-nacional emitir` (`--pdf`, `--xml-out`, `--verbose`); logging com redação
26
+ (nunca loga senha do `.pfx` nem o XML com dados do tomador).
27
+ - Reprodutibilidade: lock com hashes (`requirements-dev.txt`), `mypy --strict`, CI em
28
+ matriz 3.10–3.14, golden harness (`tests/golden/`).
29
+
30
+ ### Limitações conhecidas / próximas versões
31
+ - Reportar upstream o classifier de licença errado da BrazilFiscalReport (LICENSE/README=LGPL-3.0,
32
+ mas o classifier do pyproject diz AGPL-3.0).
33
+ - Tomador estrangeiro/sem documento; não-optantes (Lucro Presumido/Real); eventos
34
+ (cancelamento); IBS/CBS (reforma tributária).
@@ -0,0 +1,91 @@
1
+ # CLAUDE.md — PyNFSeNacional
2
+
3
+ > Guia de desenvolvimento deste repositório. **Antes de qualquer tarefa, leia
4
+ > [`docs/conhecimento-fiscal.md`](docs/conhecimento-fiscal.md)** — é onde mora a regra fiscal
5
+ > (estrutura da DPS, E-codes, numeração, DANFSe). E o [`docs/roadmap.md`](docs/roadmap.md) para o
6
+ > escopo e a ordem de build.
7
+
8
+ ## O que é
9
+
10
+ Pacote Python público (MIT) que emite **NFS-e pela API SEFIN Nacional** (DPS) e gera o **DANFSe
11
+ localmente**. Vai para GitHub/PyPI. Feito por um contador, para a comunidade que vai bater na
12
+ obrigatoriedade nacional (~set/2026).
13
+
14
+ ## Origem
15
+
16
+ - Este projeto **porta para Python puro** o conhecimento de uma **implementação de referência em
17
+ PHP** (privada, fora deste repositório) que já emite em produção.
18
+ - Essa referência serve de **gabarito**: ao montar/assinar a DPS aqui, a saída é comparada byte a
19
+ byte com a dela (ver `tests/golden/` e o roadmap), desriscando o ponto mais delicado
20
+ (canonicalização XMLDSIG). O mantenedor aponta a referência via env `NFSE_PHP_REF` só ao
21
+ regenerar o gabarito; o CI usa o XML já versionado e não precisa dela.
22
+ - Este repo é **autocontido e público** — **nada** de certificado, config real ou segredo entra no
23
+ git (ver `.gitignore`). Dados de exemplo são fictícios.
24
+
25
+ ## Princípio central: integrar, não reinventar
26
+
27
+ Não reimplementar criptografia. Cada peça tem uma lib madura do ecossistema fiscal Python; nós
28
+ costuramos e escrevemos só o que falta (transporte ao SEFIN + acabamento). Mapa no roadmap.
29
+
30
+ | Peça | Lib | Módulo |
31
+ |---|---|---|
32
+ | Montar/serializar XML da DPS | `lxml` | `dps.py` |
33
+ | Assinar XMLDSIG | `erpbrasil.assinatura` | `assinatura.py` |
34
+ | Ler `.pfx` A1 | `cryptography` | `certificado.py` |
35
+ | Transporte mTLS SEFIN | `requests` + próprio | `sefin.py` |
36
+ | DANFSe (PDF) | `BrazilFiscalReport` | `danfse.py` |
37
+ | Orquestração + CLI | — | `emissor.py`, `cli.py` |
38
+
39
+ ## Estrutura
40
+
41
+ ```
42
+ src/pynfsenacional/ # o pacote (config/cert/dps/assinatura/sefin/danfse/cli — pipeline completo)
43
+ docs/ # conhecimento-fiscal.md (regra) + roadmap.md (plano)
44
+ examples/ # config-exemplo.jsonc (fictício) + emitir_exemplo.py
45
+ tests/ # smoke + (futuro) testes de DPS/assinatura contra gabarito
46
+ ```
47
+
48
+ ## Como desenvolver
49
+
50
+ ```bash
51
+ python -m venv .venv && source .venv/bin/activate
52
+ pip install -e ".[dev]"
53
+ pytest # smoke
54
+ ruff check . # lint
55
+ ```
56
+
57
+ ## Estado atual
58
+
59
+ **Alpha — pipeline completo.** Todas as peças estão implementadas; `Emissor.emitir()` roda
60
+ ponta a ponta: **validar → montar DPS → assinar → transporte mTLS → Nota** (+ `nota.danfse()`).
61
+
62
+ - `config.py` — dataclasses + `validar()` (E-codes) + loader tolerante. ✅
63
+ - `certificado.py` — leitura do `.pfx` via `cryptography` (+ fallback cifra legada §9). ✅
64
+ - `dps.py` — `montar_dps`/`id_dps`; o C14N do `infDPS` bate **byte-a-byte** com o PHP (golden). ✅
65
+ - `assinatura.py` — `assinar_dps` via `erpbrasil.assinatura`; mesmo `DigestValue` do gabarito. ✅
66
+ - `sefin.py` — transporte mTLS (`requests-pkcs12`, P12 direto), `POST /nfse`, `verificarDps`.
67
+ **mTLS validado ao vivo** em homologação (handshake + `HEAD /dps`, read-only). ✅
68
+ - `danfse.py` — DANFSe local via `BrazilFiscalReport` ≥ 1.0 (validado com XML de NFS-e real). ✅
69
+ - `cli.py` — `nfse-nacional emitir` (`--pdf`/`--xml-out`/`--verbose`); logging com redação. ✅
70
+
71
+ **Emissão real VALIDADA em homologação** (24/06): com um certificado A1 real (Simples Nacional, RJ) o
72
+ SEFIN devolveu o `nNFSe` + a chave de 50 díg e o DANFSe foi gerado localmente. (No caminho, corrigido o
73
+ **E1229**: faltava o prolog `<?xml encoding="UTF-8"?>` no XML assinado.)
74
+
75
+ **DANFSe é dependência OPCIONAL** (`pip install PyNFSeNacionalGT[danfse]`): o núcleo de emissão usa só
76
+ deps permissivas; a `BrazilFiscalReport` (LGPL-3.0 pelo LICENSE/README upstream — o classifier AGPL do
77
+ pyproject deles parece engano) só entra para gerar o PDF. Import lazy em `danfse.py`.
78
+
79
+ **Falta (pré-publicação):** (1) criar o repo no GitHub + reservar o nome no PyPI; (2) endurecimento a
80
+ partir de emissões reais; (3) reportar o classifier de licença errado upstream.
81
+
82
+ Tooling: `pip install -e ".[dev]"` (deps instalam no 3.10–3.14), lock com hashes
83
+ (`requirements-dev.txt`), CI (`.github/workflows/ci.yml`), release por tag (`release.yml`).
84
+ Testes: `pytest` (67, +2 skip locais), `ruff check .`, `mypy --strict` — tudo verde.
85
+
86
+ ## Regras
87
+
88
+ - **Nunca** commitar `.pfx`, `config/` real, `.env`, XML/PDF de nota real.
89
+ - Toda regra fiscal nova vai **primeiro** para `docs/conhecimento-fiscal.md`, depois para o código.
90
+ - Ao implementar DPS/assinatura: **diffar contra o gabarito PHP** antes de mandar pro SEFIN.
91
+ - Mensagem de commit termina com a linha de co-autoria do Claude Code quando aplicável.
@@ -0,0 +1,31 @@
1
+ # Código de Conduta
2
+
3
+ ## Nosso compromisso
4
+
5
+ No interesse de promover um ambiente aberto e acolhedor, nós, como contribuidores e mantenedores,
6
+ nos comprometemos a fazer da participação neste projeto uma experiência livre de assédio para todos —
7
+ independentemente de idade, identidade ou expressão de gênero, deficiência, etnia, nível de
8
+ experiência, nacionalidade, aparência, raça, religião ou orientação sexual.
9
+
10
+ ## Nossos padrões
11
+
12
+ Exemplos de comportamento que contribuem para um ambiente positivo:
13
+
14
+ - usar linguagem acolhedora e inclusiva;
15
+ - respeitar pontos de vista e experiências diferentes;
16
+ - aceitar críticas construtivas com elegância;
17
+ - focar no que é melhor para a comunidade.
18
+
19
+ Comportamentos inaceitáveis incluem assédio, comentários depreciativos, ataques pessoais ou políticos,
20
+ e divulgação de informação privada de terceiros sem permissão.
21
+
22
+ ## Aplicação
23
+
24
+ Casos de comportamento abusivo ou inaceitável podem ser reportados de forma privada ao mantenedor
25
+ através do GitHub ([@Gomes343](https://github.com/Gomes343)) ou pelo canal de
26
+ **Security Advisories** do repositório. Todas as queixas serão analisadas e investigadas, resultando
27
+ em uma resposta apropriada às circunstâncias.
28
+
29
+ ## Atribuição
30
+
31
+ Adaptado do [Contributor Covenant](https://www.contributor-covenant.org), versão 2.1.
@@ -0,0 +1,55 @@
1
+ # Como contribuir
2
+
3
+ Obrigado pelo interesse! Este é um projeto da comunidade fiscal Python brasileira. Toda ajuda é
4
+ bem-vinda — relatos de erro, melhorias de documentação, suporte a mais municípios/regimes, testes.
5
+
6
+ ## Antes de tudo: regra de ouro 🔒
7
+
8
+ **NUNCA** inclua material sensível em commits, issues ou PRs:
9
+
10
+ - certificados A1 (`.pfx`/`.p12`/`.pem`/`.key`), senhas, `.env`, tokens;
11
+ - CNPJ/CPF, nomes ou XML/PDF de **notas reais**.
12
+
13
+ O [`.gitignore`](.gitignore) já bloqueia esses padrões; os dados de exemplo e fixtures são **fictícios**.
14
+ Se precisar reproduzir um problema, **anonimize** (use CNPJ/CPF de teste, ex.: `11222333000181`).
15
+
16
+ ## Ambiente de desenvolvimento
17
+
18
+ ```bash
19
+ git clone https://github.com/Gomes343/PyNFSeNacional.git
20
+ cd PyNFSeNacional
21
+ python -m venv .venv && source .venv/bin/activate
22
+ pip install -e ".[dev]" # dev já inclui o extra [danfse]
23
+ ```
24
+
25
+ ## Antes de abrir o PR
26
+
27
+ Tudo precisa passar (é o que a CI roda, na matriz 3.10–3.14):
28
+
29
+ ```bash
30
+ ruff check . # lint + ordenação de imports
31
+ mypy # tipos (strict)
32
+ pytest # testes (inclui o golden contra a referência)
33
+ ```
34
+
35
+ - **Regra fiscal nova** vai **primeiro** para [`docs/conhecimento-fiscal.md`](docs/conhecimento-fiscal.md),
36
+ depois para o código (o porquê fiscal precisa estar documentado).
37
+ - Mexeu na **montagem da DPS ou na assinatura**? O *golden* (`tests/golden/`) compara a saída ao
38
+ gabarito de referência byte a byte. Se a mudança for legítima, regenere com
39
+ `bash tests/golden/regenerar_gabarito.sh` e explique o porquê no PR.
40
+ - Mantenha o **núcleo de emissão sem dependências pesadas**; PDF/extras ficam atrás de `[danfse]`.
41
+
42
+ ## Estilo de commit
43
+
44
+ Mensagens em **português**, no imperativo, dizendo **o quê** e **por quê** (não só o "como").
45
+ Um assunto curto + corpo quando precisar de contexto.
46
+
47
+ ## Pull Requests
48
+
49
+ 1. Crie um branch a partir de `main`.
50
+ 2. Mantenha o PR focado num assunto.
51
+ 3. Descreva o **porquê**, como testou, e marque itens do checklist do template.
52
+ 4. CI verde é pré-requisito de merge.
53
+
54
+ Dúvidas? Abra uma [issue](https://github.com/Gomes343/PyNFSeNacional/issues) — de preferência antes de
55
+ um PR grande, para alinharmos a abordagem.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Murilo Gomes Teixeira
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.