--- id: 0033b title: Vendoring de funciones Python por enricher status: completed priority: high created: 2026-05-02 completed: 2026-05-03 depends_on: [0033] --- ## Objetivo Para que el `.exe` Windows sea portable a cualquier PC, los enrichers con `lang: python` no pueden importar de `/python/functions/` en runtime. Cada enricher copia las funciones del registry que declara en `uses_functions` a `/_vendored/` durante el build, y `run.py` importa de ahi. ## Implementacion ### 1. Script `tools/vendor_enricher_python.sh` Recibe `` y ``. Lee `uses_functions` del manifest, filtra los IDs `*_py_*`, resuelve `file_path` desde `registry.db`, copia el `.py` a `_vendored//.py` y crea `__init__.py` por dominio. Genera `.vendor.lock` con ` ` por linea. Idempotente: si el sha256 de origen coincide con el del lock, no copia. ### 2. Adaptacion de `run.py` Cada enricher con `lang: python` que use funciones del registry cambia el import: ```python # antes sys.path.insert(0, os.path.join(registry_root, "python", "functions")) from cybersecurity.cybersecurity import normalize_url # despues sys.path.insert(0, os.path.join(os.path.dirname(__file__), "_vendored")) from cybersecurity.normalize_url import normalize_url ``` ### 3. .gitignore Anadir `_vendored/` y `.vendor.lock` al `.gitignore` del repo (o de cada app). Son artefactos de build, regenerables. ### 4. Hook al build `/compile` (o el script de freeze del 0033) recorre `apps//enrichers/*/manifest.yaml`. Para cada manifest con `lang: python`, ejecuta `vendor_enricher_python.sh`. ## Tests - Test unit del script bash: dado un manifest con dos `uses_functions` Python conocidas, verificar que `_vendored/` queda con la estructura correcta y `.vendor.lock` lista los hashes. - Test e2e: `fetch_webpage` (lang: python) ejecuta correctamente con registry_root vacio en el ctx tras vendoring. ## Definicion de hecho - `tools/vendor_enricher_python.sh` existe y es idempotente. - Cada enricher Python del proyecto tiene `_vendored/` poblado y funciona sin `registry_root` en runtime. - El binario zippeado a Desktop arranca enrichers Python sin acceso al fn_registry.