Evaluator
L'evaluator è l'unico che, dopo la consegna, decide se il fornitore viene pagato. Si sceglie alla creazione del job e non cambia più. Lo standard lascia aperto chi sia e come decida: è il punto in cui scontract.ai costruisce il suo catalogo.
Il catalogo
| Evaluator | Cosa verifica | Stato |
|---|---|---|
| SchemaEval | La consegna è JSON e rispetta lo schema del job. Il suo hash coincide con quello sulla chain. | disponibile |
| GitHubEval | La consegna è una pull request unita nel repository del job, dall'autore giusto, con i test verdi. | disponibile |
| TestEval | Codice o dati superano una suite di test fissata alla creazione. | in arrivo |
| QuorumEval | Completa solo con m firme su n evaluator indipendenti. | fase 1 |
| SdiEval | La fattura è accettata su SDI ed è coerente con il job. | fase 2 |
| RegistryEval | Fatti da registri pubblici: stato dell'impresa, DURC, ISTAT. | fase 2 |
| EscalationEval | Una finestra di contestazione, con un arbitro scelto alla creazione. | fase 2 |
GET /v1/evaluators e lo strumento list_evaluators danno l'elenco aggiornato, con gli indirizzi.
L'evaluator può anche essere un indirizzo qualsiasi: un servizio di terzi, un contratto, una persona. Sotto mandato non può essere il fornitore. Non può essere l'agente stesso, salvo che il titolare lo consenta.
SchemaEval
SchemaEval è il più semplice. Controlla tre cose, nell'ordine:
- L'hash
keccak256del contenuto caricato coincide con ildeliverableconsegnato sulla chain. - Il contenuto è JSON.
- Il JSON rispetta lo schema dichiarato nel job, in JSON Schema 2020-12.
Se tutto torna chiama complete, altrimenti reject. Giudica appena il fornitore consegna, e il cron riprova ogni minuto le consegne rimaste in attesa.
La descrizione del job
Per SchemaEval la descrizione del job è un JSON con il brief e lo schema:
{
"brief": "Tre fornitori di imballaggi in Lombardia, con partita IVA",
"schema": {
"type": "object",
"required": ["fornitori"],
"properties": {
"fornitori": {
"type": "array", "minItems": 3,
"items": {
"type": "object", "required": ["nome", "piva"],
"properties": { "nome": { "type": "string" }, "piva": { "type": "string", "pattern": "^[0-9]{11}$" } }
}
}
}
}
}
Lo strumento create_job la costruisce da brief e schema. L'API rifiuta un job per SchemaEval senza schema, perché SchemaEval non potrebbe che respingerlo. La descrizione va sulla chain e non può superare 4 KB.
Uno schema fa bene il suo lavoro quando è preciso: campi obbligatori, formati, numero minimo di elementi. SchemaEval verifica la forma, non la verità. Che le partite IVA esistano davvero lo verificherà RegistryEval.
Il verdetto
Il verdetto è un documento:
{
"evaluator": "SchemaEval", "version": 1, "jobId": "7",
"deliverable": "0x8930...", "esito": "reject",
"motivi": ["/fornitori: Array has too few items (1 < 3)"]
}
Il suo hash va sulla chain come reason di complete o reject. È keccak256 del JSON in forma canonica, con le chiavi in ordine. Chiunque può ricalcolarlo da GET /v1/jobs/:id e confrontarlo con l'evento JobCompleted o JobRejected.
Quanto ci si può fidare
SchemaEval è una chiave del backend di scontract.ai: chi la controlla decide i job che la usano come evaluator. È un evaluator fidato, come l'attestatore di Scontratto. Per i job di valore arriverà QuorumEval, che vuole più firme indipendenti. EscalationEval aggiungerà la contestazione, che lo standard da solo non prevede.
GitHubEval
GitHubEval paga quando il lavoro è entrato nel codice. Serve per taglie su issue e milestone di sviluppo: il cliente fissa repository, issue e sviluppatore, il fornitore consegna il link della pull request, e i soldi passano quando la PR è unita con i test verdi.
La descrizione del job
{
"brief": "Supporto ai pagamenti EURC nel checkout",
"github": {
"repo": "acme/negozio",
"issue": 42,
"author": "mrossi",
"base": "main",
"ci": ["test", "lint"]
}
}
| Campo | Cosa è |
|---|---|
repo |
Il repository, proprietario/nome. Obbligatorio. |
issue |
Facoltativo. La issue che la PR deve chiudere. |
author |
Facoltativo. L'utente GitHub che deve aver aperto la PR. Senza, vale chiunque. |
base |
Facoltativo. Il ramo in cui va unita. Senza, il ramo principale del repository. |
ci |
Facoltativo. true, il predefinito: tutti i controlli verdi. Una lista di nomi: solo quelli contano, e devono esserci. false: la CI non conta. |
Lo strumento create_job la costruisce da brief e github, e sceglie GitHubEval da solo. L'API rifiuta un job per GitHubEval senza un github valido.
La consegna
Il fornitore consegna il link della PR, https://github.com/acme/negozio/pull/57, oppure il JSON { "pr": "https://github.com/..." }.
Cosa controlla
Nell'ordine:
- L'hash del contenuto coincide con il
deliverablesulla chain. - La PR è nel repository del job.
- L'autore e il ramo sono quelli del job.
- La PR è unita.
- Se il job ha una issue, la PR la chiude, con
closes #42,fixes #42oresolves #42nel titolo o nella descrizione, e la issue è chiusa. - I controlli CI sull'ultimo commit della PR sono verdi.
Tre esiti possibili:
| Esito | Quando |
|---|---|
complete |
Tutto torna. Il fornitore incassa. |
reject |
Qualcosa non tornerà più: repository, autore o ramo sbagliati, PR chiusa senza merge, controlli falliti, controlli richiesti assenti. I soldi tornano al cliente. |
| in attesa | Non ancora: la PR è aperta, la issue è aperta, i test girano. GitHubEval ricontrolla ogni cinque minuti, fino alla scadenza del job. Alla scadenza, il rimborso. |
Un merge da solo è un segnale debole: un manutentore può unire una PR con i test rossi. Per questo conviene indicare in ci i controlli che contano.
Quanto ci si può fidare
GitHubEval ha una chiave sua, diversa dal facilitatore e da SchemaEval, e paga il gas del verdetto attraverso il forwarder. Si fida di GitHub: chi può unire nel repository del job decide il pagamento. Per questo il cliente dovrebbe essere, o fidarsi di, chi gestisce il repository. Il verdetto è un documento come quello di SchemaEval, con "evaluator": "GitHubEval".