feat: portability safeguards — signed goldens, HTTP contract suite, committed OpenAPI (Task 6)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
3aae8b67ef
commit
fb2b8ce372
@@ -0,0 +1,55 @@
|
||||
"""Task 6: one-shot generator for `tests/goldens_signed/*.expected.xml` --
|
||||
NOT run automatically by the test suite. Run manually whenever a golden case
|
||||
in the `sowai-fiscal` lib is added/changed (or `tests/fixtures/test_cert.pfx`
|
||||
is rotated), then commit the regenerated files.
|
||||
|
||||
Signs each `sowai_fiscal.goldens/*.input.json` case's `DadosEmissao` (loaded
|
||||
via `sowai_fiscal.golden_helpers.dados_from_json` -- SAME helper the lib's
|
||||
own pre-signature goldens use, so `chave_acesso`/`numero`/`cnf`/`dh_emi` are
|
||||
whatever that JSON already pins, unchanged) with the FIXED test certificate.
|
||||
Deterministic because RSA PKCS#1v1.5 signing has no random padding: the SAME
|
||||
(input XML, private key) pair always produces the SAME signature bytes --
|
||||
this is the byte-exact assertion `tests/test_signed_goldens.py` checks.
|
||||
|
||||
uv run python scripts/generate_signed_goldens.py
|
||||
"""
|
||||
import importlib.resources
|
||||
from pathlib import Path
|
||||
|
||||
from cryptography.hazmat.primitives.serialization import pkcs12
|
||||
from sowai_fiscal.golden_helpers import dados_from_json
|
||||
from sowai_fiscal.xml_builder import build_nfe
|
||||
|
||||
from fiscal_svc.emission.service import _serialize_nfe, sign_nfe_xml
|
||||
|
||||
REPO_DIR = Path(__file__).resolve().parents[1]
|
||||
CERT_PATH = REPO_DIR / "tests" / "fixtures" / "test_cert.pfx"
|
||||
CERT_PASSWORD = "test-cert-password" # must match generate_test_cert.py
|
||||
OUT_DIR = REPO_DIR / "tests" / "goldens_signed"
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if not CERT_PATH.exists():
|
||||
raise SystemExit(
|
||||
f"{CERT_PATH} não existe -- rode scripts/generate_test_cert.py primeiro"
|
||||
)
|
||||
pfx_bytes = CERT_PATH.read_bytes()
|
||||
private_key, cert, _ca_certs = pkcs12.load_key_and_certificates(
|
||||
pfx_bytes, CERT_PASSWORD.encode("utf-8")
|
||||
)
|
||||
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
goldens_dir = Path(str(importlib.resources.files("sowai_fiscal") / "goldens"))
|
||||
for input_path in sorted(goldens_dir.glob("*.input.json")):
|
||||
case = input_path.name.removesuffix(".input.json")
|
||||
dados = dados_from_json(input_path)
|
||||
nfe = build_nfe(dados)
|
||||
xml_str = _serialize_nfe(nfe)
|
||||
xml_assinado = sign_nfe_xml(xml_str, dados.chave_acesso, private_key, cert)
|
||||
out_path = OUT_DIR / f"{case}.expected.xml"
|
||||
out_path.write_text(xml_assinado, encoding="utf-8")
|
||||
print(f"wrote {out_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user