feat: product enrichment observability, lab KB study, benchmark, copy + local-Hub E2E, docs; 1.3.0

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
gti
2026-09-25 19:26:13 -03:00
co-authored by Claude Sonnet 5
parent 5deebea14e
commit 4fc83a33d5
38 changed files with 1282 additions and 60 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ def test_health_is_unavailable_when_database_is_down():
def test_version_endpoint_reports_release_and_fiscal_versions():
body = TestClient(create_app(database_probe=lambda: True)).get("/version").json()
assert body["version"] == "1.2.5" and body["api_compat"] == "1.0" and body["engine_version"] and body["decision_version"]
assert body["version"] == "1.3.0" and body["api_compat"] == "1.0" and body["engine_version"] and body["decision_version"]
def test_production_refuses_the_dev_token(monkeypatch):
@@ -94,3 +94,67 @@ def test_features_route_is_admin_only_csrf_and_audited():
assert "INSTALLATION_FEATURES" in [e.action for e in s.scalars(select(AuditEvent))]
page = client.get(f"/agents/{agent_id}")
assert "Funcionalidades" in page.text and "Enriquecimento" in page.text
def test_dashboard_shows_sources_without_tokens_and_official_freshness(monkeypatch):
from central.app.enrichment import observability, providers
monkeypatch.setattr(observability, "build_providers", lambda _s: providers.build_providers(type("S", (), {"cosmos_token": "SEGREDO-NAO-VAZAR", "allow_paid_providers": False})()))
client, agent_id, _ = _panel_client()
page = client.get("/").text
assert "Fontes de produtos" in page and "cosmos" in page and "configurado: sim" in page and "upcitemdb" in page and "openfoodfacts" in page
assert "SEGREDO-NAO-VAZAR" not in page and "Fontes oficiais" in page and "NCM (Siscomex)" in page
def _second_agent(engine, mode="ENABLED", corrector=True):
from central.app.auth import token_hash
from central.app.models import Agent, Tenant
with Session(engine) as s:
first = s.scalars(select(Installation)).first()
agent = Agent(tenant_id=first.tenant_id, name="second", token_hash=token_hash("second-token"), enabled=True)
s.add(agent)
s.flush()
s.add(Installation(agent_id=agent.id, tenant_id=first.tenant_id, installation_id="00000000-0000-4000-8000-0000000000bb", display_name="B", features_configured=True, corrector_enabled=corrector, enrichment_mode=mode))
s.commit()
return {"Authorization": "Bearer second-token"}
def test_same_product_in_another_installation_costs_zero_extra_provider_requests(monkeypatch):
client, engine = setup(monkeypatch)
h2 = _second_agent(engine)
providers = enrich_api.PROVIDERS_OVERRIDE
first = resolve(client)
calls_after_first = [p.calls for p in providers]
second = client.post("/v1/products/resolve", json={"product_code": "X9", "gtin": G1, "description": "REFRIGERANTE COLA LATA 350ML", "current": {}}, headers=h2).json()
assert [p.calls for p in providers] == calls_after_first # other installation: served by KB, zero external calls
assert second["state"] == "EXACT_GTIN_VERIFIED" and second["fields"]["CLASSIFICACAO_FISCAL"]["value"] == first["fields"]["CLASSIFICACAO_FISCAL"]["value"]
with Session(engine) as s:
assert {r.installation_id for r in s.scalars(select(ProductEnrichment))} == {1, 2}
def test_installations_are_isolated_by_their_own_feature_flags(monkeypatch):
client, engine = setup(monkeypatch, "DISABLED")
h2 = _second_agent(engine, "ENABLED")
assert resolve(client)["state"] == "FEATURE_DISABLED"
body = client.post("/v1/products/resolve", json={"product_code": "N1", "gtin": G1, "description": "REFRIGERANTE COLA LATA 350ML", "current": {}}, headers=h2).json()
assert body["state"] != "FEATURE_DISABLED" and body["fields"]["CLASSIFICACAO_FISCAL"]["status"] == "AUTO_FILL_SAFE"
def test_quota_exhausted_gives_pending_state_and_retry_time_through_the_api(monkeypatch):
client, engine = setup(monkeypatch)
monkeypatch.setattr(enrich_api, "PROVIDERS_OVERRIDE", [Fake("cosmos", COSMOS(), True, daily_limit=1)])
resolve(client, "A1", G1)
body = resolve(client, "A2", G4, "OUTRO PRODUTO")
assert body["state"] == "PENDING_PROVIDER_QUOTA" and body["retry_at"]
with Session(engine) as s:
row = s.scalars(select(ProductEnrichment).where(ProductEnrichment.product_code == "A2")).one()
assert row.status == "PENDING" and row.next_attempt_at is not None
assert s.scalars(select(BlockedProduct).where(BlockedProduct.reason_code == "PENDING_PROVIDER_QUOTA")).one().field == "ENRICHMENT"
def test_corrector_switch_off_stops_jobs_but_not_enrichment(monkeypatch):
client, engine = setup(monkeypatch)
with Session(engine) as s:
s.scalars(select(Installation)).one().corrector_enabled = False
s.commit()
assert client.get("/v1/jobs/next", headers=H).json() is None
assert resolve(client)["state"] != "FEATURE_DISABLED"
@@ -223,7 +223,7 @@ def test_cosmos_without_token_is_not_configured_and_costs_nothing(env):
def test_paid_provider_guard():
class S: allow_paid_providers = False; cosmos_token = None
assert [p.name for p in build_providers(S())] == ["cosmos", "upcitemdb", "openfoodfacts"]
assert [p.name for p in build_providers(S())] == ["cosmos", "upcitemdb", "openfoodfacts", "openproductsfacts", "openbeautyfacts"]
# ---- provider contract tests against recorded fixtures (httpx.MockTransport, no network) ----------------------------------------------------------