Passa al contenuto principale

Architettura CLI

La CLI è organizzata come un package (src/zenzic/cli/) invece di un singolo modulo. Ogni file gestisce un dominio di responsabilità.


Mappa dei Moduli

ModuloResponsabilità
_shared.pySingleton console, singleton _ui, configure_console() e tutte le utility cross-comando (_build_exclusion_manager, _output_json_findings, _render_link_error, ecc.)
_check.pySub-app Typer check_app + sette comandi check *; helper privati re-esportati da _governance.py, _target_resolver.py e _command_setup.py
_command_setup.pyFactory setup_command() — consolida la scoperta del repo root, il caricamento config, la risoluzione del target e la costruzione dell'exclusion manager usati da tutti i comandi check
_clean.pySub-app Typer clean_app + comando clean assets
_config_explain.pyComando explain + surface di introspezione della genealogia config e delle regole
_governance.pySub-app Typer config_app + comandi del profilo di governance + helper per i filtri per-file-ignore e directory-policy (_apply_per_file_ignores, _apply_directory_policies)
_guard.pySub-app Typer guard_app + comandi scan / init per il fast secret guard
_inspect.pySub-app Typer inspect_app + comandi capabilities, codes e routes
_lab.pyComando lab + showcase interattivo di scenari
_metadata.pySingle source of truth per i pannelli help root, il raggruppamento dei comandi e il testo di short help
_standalone.pyComandi score, diff e init + i loro helper privati
_target_resolver.py_resolve_target() e _apply_target() — helper per la ricerca del path e il patching della config, condivisi dai comandi check e dal comando lab
__init__.pySurface di re-export pubblica consumata da main.pynon aggiungere logica qui

main.py è la factory di registrazione Typer unificata. I nuovi comandi top-level e le sub-app devono essere registrati lì, e i metadati dell'help root devono rimanere allineati con _metadata.py.


Il Visual State Manager

_shared.py è il solo proprietario di tutto lo stato della console e UI. Questa è la regola architetturale più critica nel layer CLI:

DIVIETO: Nessun modulo comando può istanziare Console() o una classe UI custom direttamente. Tutto l'output deve passare attraverso get_ui() e get_console() da _shared.py.

# ✅ Corretto — in qualsiasi modulo _check.py / _clean.py / _standalone.py
from . import _shared
_shared.get_ui().print_header(__version__)
_shared.get_console().print("output")

# ❌ VIETATO — non farlo mai in un modulo comando
from rich.console import Console
from mypackage.ui import LegacyInterfaceV1
console = Console(...) # rompe lo stato condiviso
ui = LegacyInterfaceV1(console) # crea un'istanza orfana

Per il razionale di design dietro la condivisione dello stato dell'interfaccia utente, vedere ADR 004 — Stato della Console Unificato.

Convenzioni output UI:

  • Usa sempre ZenzicPalette.DIM per testo dim/secondario — mai il tag Rich raw [dim].
  • Spaziatura verticale: compatta (stile Ruff). Nessuna riga vuota tra le singole righe del footer. Usa i separatori Rule() solo per dividere le sezioni principali del report.
  • I nuovi simboli devono essere aggiunti a _EMOJI in zenzic/core/ui.py prima dell'uso — mai Unicode literal inline.

Aggiungere Comandi CLI

Per istruzioni passo-passo su come aggiungere comandi o nuove sub-app alla CLI, vedere Scrivere un Nuovo Check — Cablaggio CLI.


Codici di Uscita

La CLI termina con uno di quattro codici. Questi sono frozen — non aggiungere nuovi codici di uscita senza una decisione architetturale esplicita:

CodiceSignificato
0Tutti i check superati
1Problemi di qualità trovati
2SECURITY — credenziale esposta rilevata
3SECURITY — traversal del path di sistema rilevato

PLUGIN_FORBIDDEN_EXITS garantisce che gli adapter di terze parti non possano emettere codici di uscita al di fuori di questo insieme. Vedi il riferimento Adapter API per il contratto completo.