mc2-harness canale di distribuzione

mc2-harness release 20260928-35

Il kit che fa lavorare gli agenti AI (Claude e gli altri) nel tuo progetto, con le tue regole e la tua knowledge base.

Cos'è un tenant, in due righe

Un tenant è il tuo spazio privato nella knowledge base: i tuoi documenti e le tue regole per l'agente. Solo chi ha la tua chiave può leggerli o modificarli. In più ogni tenant legge le regole comuni a tutti, il "Playbook di Sistema".

Il kit harness è il framework operativo che installi nel tuo progetto: fa lavorare l'agente con le tue regole e la tua knowledge base.

Il progetto usa tre tipi di cartelle, con ruoli diversi e separati:

CartellaCosa contieneA cosa serve
Radicevars.yaml, .env (la tua chiave privata), release/ ospita la configurazione di progetto e la gestione del kit. Non la tocchi quasi mai.
CWD di lavoro
<radice>/cwd
istruzioni per l'agente (AGENTS.md), script operativi (bin/), cache di sessione è da qui che lanci l'agente. L'agente opera dentro questa cartella e legge la configurazione a ../. Viene ricreata a ogni aggiornamento: non salvarci niente.
Sorgentii repository di codice del progetto (anche più di uno) il lavoro vero. Stanno fuori dalla cartella cwd e li autorizzi tu all'avvio dell'agente.

Struttura consigliata:

/home/max/projects/progetto-x/ ├── vars.yaml ← variabili: tenant_id, harness_root_dir, kb_url, source_dirs ├── .env ← segreti: KB_API_KEY (mai tracciato su git) ├── release/ ← gestione kit: bin/wrapper.sh, release.zip, .version ├── cwd/ ← CWD di runtime: AGENTS.md, bin/, cache/ (da qui lanci l'agente) └── sources/ ├── backend/ ← repository └── frontend/ ← repository
Attenzione — due credenziali da remoto: da una macchina fuori dall'home-server servono due credenziali, non una sola: la chiave API del tenant e un access token OAuth2 machine-to-machine. Dettagli al passo Accesso remoto (S2S).
Setup del tuo tenant, passo per passo

Passo 1 — Scegli tre cose

CosaEsempioRegole
Nome del tenantprogetto-xminuscole, numeri e trattini, niente spazi
Radice del progetto/home/max/projects/progetto-xuna cartella dedicata, NON un repository git
Sorgenti/home/max/projects/progetto-x/sources/backend, .../frontendi repository esistenti, quanti vuoi

Passo 2 — Provisioning e richiesta chiavi

Chiedi all'amministratore dell'infrastruttura (o a una sessione harness amministrativa su home-server):

crea il tenant progetto-x con radice /home/max/projects/progetto-x e sorgenti /home/max/projects/progetto-x/sources/backend e .../frontend

L'amministratore esegue il provisioning:

  • genera la chiave API con lo strumento di mc2-embed: python3 src/mc2_embed/tools/new_api_key.py --name harness-progetto-x --tenant progetto-x;
  • registra lo SHA-256 della chiave nel segreto Doppler MC2_EMBED_API_KEYS e sincronizza il servizio (job Jenkins hs-secrets-sync);
  • pubblica il tenant e la Knowledge Base di base con il job tenant-publish (o bin/harness.py tenant create);
  • crea o consegna i file vars.yaml e .env per la radice del tuo progetto.

Nei file di progetto troverai:

# vars.yaml nella radice del progetto tenant_id: "progetto-x" harness_root_dir: "/home/max/projects/progetto-x" kb_url: "http://127.0.0.1:8080" harness_url: "https://harness.oci.mcsquared.it" source_dirs: - "/home/max/projects/progetto-x/sources/backend" - "/home/max/projects/progetto-x/sources/frontend" # .env nella radice del progetto (MAI committare o condividere) KB_API_KEY="mc2e_..." # Eventuali credenziali di dominio (es. Jira, se utilizzate dal tenant): # JIRA_URL="https://azienda.atlassian.net" # JIRA_USERNAME="utente@azienda.com" # JIRA_TOKEN="api_token..."

Passo 3 — Installa il kit (due comandi)

Prerequisiti: bash, curl, unzip, python3 con PyYAML. Apri un terminale nella radice:

cd /home/max/projects/progetto-x curl -fsSL https://harness.oci.mcsquared.it/harness/bootstrap.sh -o bootstrap.sh && bash bootstrap.sh

Alla fine leggi Bootstrap completato: nella radice trovi release/ (il kit installato e wrapper) e cwd/ (la CWD di runtime dell'agente). Lo script scarica il bundle, ne verifica l'integrità SHA-256 e si autocancella. La chiave API NON viaggia verso il server di distribuzione.

Passo 4 — Usa l'agente

cd /home/max/projects/progetto-x/cwd claude --add-dir /home/max/projects/progetto-x/sources/backend \ --add-dir /home/max/projects/progetto-x/sources/frontend

Si parte sempre da cwd/: lì l'agente trova AGENTS.md e gli strumenti per scaricare a runtime regole e conoscenza dal server. L'agente accede a ../vars.yaml e ../.env senza esporre segreti in sessione. Ogni --add-dir autorizza un repository sorgente: senza, l'agente non può accedere ai file. Con altri agenti (agy, opencode, ...) si usa l'opzione equivalente.

Passo 5 — Riempi la tua knowledge base (facoltativo)

All'inizio il tenant è vuoto. Dentro l'agente del progetto chiedi, per esempio:

indicizza nella KB la documentazione che c'è in sources/backend/docs

L'agente la carica nel tuo tenant. Da lì puoi chiedergli cose come "cosa dice la KB su…".

Accesso remoto (S2S): le due chiavi

Da una macchina fuori dall'home-server, la sola chiave API non basta: il servizio mc2-embed è pubblicato dietro oauth2-proxy, che protegge l'accesso con un login. Una richiesta priva di sessione o di un token riconosciuto riceve 401 dal proxy, prima ancora di arrivare a mc2-embed e alla verifica della chiave API.

Servono quindi due credenziali indipendenti, con ruoli diversi:

CredenzialeA cosa serveChi la validaDurata
X-API-Keyidentifica il tenant e il ruolo (quali dati puoi leggere/scrivere)mc2-embedfino a rigenerazione manuale
Authorization: Bearer <access token>attraversa oauth2-proxy come chiamata "macchina", senza login interattivooauth2-proxy~1 ora, il kit lo rigenera da solo ad ogni comando

Le due chiavi sono indipendenti: la prima non funziona senza la seconda (il proxy blocca prima), la seconda non funziona senza la prima (il servizio rifiuta senza chiave applicativa valida).

S2S — Passo 1: chiave API (una tantum, la fa l'amministratore)

È lo stesso passo di provisioning già descritto sopra. L'amministratore, dal repository mc2-embed, esegue:

python3 src/mc2_embed/tools/new_api_key.py --name harness-progetto-x --tenant progetto-x

Il comando stampa la chiave una sola volta (formato mc2e_...) e la voce YAML da registrare. La chiave in chiaro va nel tuo .env come KB_API_KEY; il suo hash SHA-256 va nel segreto Doppler MC2_EMBED_API_KEYS, applicato con il job Jenkins hs-secrets-sync. Fino a qui, nulla cambia rispetto all'uso locale sull'home-server.

S2S — Passo 2: client OAuth2 machine-to-machine (una tantum, la fa l'amministratore)

Questa parte è nuova rispetto all'accesso locale e serve solo per l'uso da remoto. L'autenticazione per le macchine usa il grant client credentials (standard OAuth2, RFC 6749 §4.4): due stringhe, nessun token da firmare, nessuna libreria crittografica da installare. L'amministratore dell'infrastruttura:

  1. crea un App Client dedicato alle macchine nell'authorization server del cluster, con il grant client_credentials abilitato;
  2. ne annota client_id e client_secret generati;
  3. ti consegna le due stringhe in modo sicuro — mai per email o chat in chiaro: come segreto allegato a un canale cifrato, o tramite un secret manager condiviso.

Conserva client_secret come faresti con KB_API_KEY: nel tuo .env, fuori da git, mai incollato in una chat o in un ticket.

S2S — Passo 3: configurare il tenant (una tantum, lo fai tu)

Nel tuo .env, oltre a KB_API_KEY, aggiungi le tre variabili che il kit usa per ottenere l'access token:

# .env nella radice del progetto KB_API_KEY="mc2e_..." COGNITO_TOKEN_URL="https://<dominio-authorization-server>/oauth2/token" COGNITO_CLIENT_ID="<client_id dell'App Client macchina>" COGNITO_CLIENT_SECRET="<client_secret dell'App Client macchina>"

Con queste tre variabili presenti, harness.py ottiene da solo un nuovo access token ad ogni comando (version-check, pb, kb, ...): non c'è nulla da rigenerare a mano, nessun comando aggiuntivo prima di lanciare l'agente. Se sei sull'home-server (kb_url: http://127.0.0.1:8080) non le configuri affatto: oauth2-proxy non è mai davanti a quell'indirizzo, la sola X-API-Key basta come oggi.

Verifica manuale, se vuoi controllare le credenziali prima di lanciare l'agente:

TOKEN=$(curl -s -X POST "$COGNITO_TOKEN_URL" \ --data-urlencode "grant_type=client_credentials" \ --data-urlencode "client_id=$COGNITO_CLIENT_ID" \ --data-urlencode "client_secret=$COGNITO_CLIENT_SECRET" \ | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])") curl -H "Authorization: Bearer $TOKEN" \ -H "X-API-Key: $KB_API_KEY" \ https://embed.hs.mcsquared.it/stats

Una risposta 200 con JSON conferma che entrambe le credenziali sono valide. Una pagina HTML di login al posto del JSON significa che il token è scaduto, mancante, o il client non è abilitato al grant client_credentials.

Nota: il kit harness fa questo scambio automaticamente ad ogni comando: il passo con curl sopra serve solo per diagnosticare un 401 o verificare le credenziali prima di lanciare l'agente.

S2S — Trappole comuni

SintomoCausa
401 ("pagina di login, non mc2-embed") — messaggio esplicito del kitCOGNITO_TOKEN_URL/COGNITO_CLIENT_ID/COGNITO_CLIENT_SECRET assenti, sbagliati, o il client non ha il grant client_credentials: la richiesta non ha nemmeno raggiunto mc2-embed
401 con corpo JSON ("Header X-API-Key assente o non riconosciuto")l'access token è valido (hai superato il proxy) ma la chiave API manca o è sbagliata
403 ("non puo' leggere il tenant")entrambe le credenziali sono valide, ma la chiave API appartiene a un tenant diverso da quello che stai richiedendo
COGNITO_TOKEN_URL configurato ma COGNITO_CLIENT_ID/COGNITO_CLIENT_SECRET assentihai impostato solo una delle tre variabili nel .env: servono tutte e tre insieme, o nessuna
Tenere tutto aggiornato

Dalla radice del progetto:

./release/bin/wrapper.sh upgrade

Oppure da dentro cwd/:

../release/bin/wrapper.sh upgrade

Se c'è una versione nuova del kit viene scaricata e la cartella cwd/ viene rigenerata mantenendo release/overrides/ e release/addons/. Se è già aggiornato non fa nulla.

Le tre regole d'oro
  1. Il file .env è la tua chiave. Non condividerlo, non incollarlo in chat, non metterlo su git: la radice NON è un repository, tienila fuori da git.
  2. Hai perso la chiave o temi che l'abbia vista qualcuno? Chiedi di rigenerare la chiave di progetto-x: la vecchia smette di funzionare e la nuova finisce nel .env.
  3. Non salvare niente in cwd/: a ogni aggiornamento viene ricreata da zero. Il lavoro sta nei sorgenti; eventuali personalizzazioni stabili vanno in release/overrides/ o release/addons/.
Se qualcosa va storto
MessaggioCosa significaCosa fare
Modulo Python PyYAML assentemanca un componente Pythonsudo apt install python3-yaml, poi rilancia il passo 3
vars.yaml non trovato / .env non trovatoil passo 2 non è ancora fatto, o sei nella cartella sbagliataentra nella radice, o richiedi il passo 2
HTTP 401chiave mancante o sbagliatachiedi di rigenerare la chiave
HTTP 403 … non puo' leggere il tenantla chiave appartiene a un altro tenantcontrolla tenant_id in vars.yaml
l'agente dice che non può leggere un sorgenteil repository non è autorizzatorilancia l'agente con --add-dir per quella cartella (passo 4)
impostazioni dell'agente sparite dopo un aggiornamentoerano salvate in cwd/, che viene ricreatasalvale nelle impostazioni utente dell'agente (per Claude: ~/.claude/settings.json) o in release/overrides/
l'agente non trova nulla nella KBtenant vuotopasso 5
funziona sull'home-server ma non su un altro PC (401, "pagina di login, non mc2-embed")manca la seconda credenziale per l'accesso remoto (client OAuth2 machine-to-machine)vedi Accesso remoto (S2S)
Contenuti di questo server