Skip to content

Commit e5159c2

Browse files
maxaloneclaude
andcommitted
feat: convenzione tag git di release, terzo componente di MET-integrity
collect-evidence.mjs raccoglie ora anche i tag (GitHub API /tags) e i commit di autart-signer per imgauth, imgauthweb, autart-signer. score.mjs aggiunge un proxy iniziale per "quota di release con tag git": percentuale dei tre repo pubblici con almeno un tag vX.Y.Z nell'ultimo snapshot, media insieme a sonda HMAC e ratio ancoraggi dogfooding. PRC-release-coordinata aggiorna l'output atteso con il tag pushato per ogni repo toccato; MET-integrity.yaml documenta il proxy e i suoi limiti. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 9d49c2a commit e5159c2

7 files changed

Lines changed: 65 additions & 29 deletions

File tree

generators/collect-evidence.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ async function main() {
9191
results["git-imgauthweb"] = await fetchJson("https://api.github.com/repos/SPAZIO-GENESI/imgauthweb/commits?per_page=5", ghHeaders);
9292
if (results["git-imgauthweb"].ok) evdHits.add("EVD-git-imgauthweb");
9393

94+
results["git-authart"] = await fetchJson("https://api.github.com/repos/SPAZIO-GENESI/autart-signer/commits?per_page=5", ghHeaders);
95+
if (results["git-authart"].ok) evdHits.add("EVD-git-authart");
96+
97+
// Tag di release (convenzione vX.Y.Z, vedi PRC-release-coordinata): alimentano
98+
// il terzo componente di MET-integrity ("quota di release con tag git").
99+
for (const repo of ["imgauth", "imgauthweb", "autart-signer"]) {
100+
results[`tags-${repo}`] = await fetchJson(`https://api.github.com/repos/SPAZIO-GENESI/${repo}/tags?per_page=30`, ghHeaders);
101+
}
102+
94103
const manifest = { collected_at: today.toISOString(), week, files: {} };
95104
for (const [name, data] of Object.entries(results)) {
96105
const filename = `${name}.json`;

generators/score.mjs

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,51 @@ const ANCHORS_DIR = join(SNAPSHOTS_DIR, "anchors");
1010
// ancoraggio dogfooding al mese (CTL-dogfooding-anchor).
1111
const GTF_BIRTH_MONTH = "2026-07";
1212

13-
// Legge l'ultimo snapshot settimanale del collettore (generators/collect-evidence.mjs),
14-
// se esiste, per il solo componente "worker" (sonda HMAC) di /api/status.
15-
// Le cartelle YYYY-Www ordinano correttamente in lessicografico (settimana a 2 cifre).
16-
function latestSnapshotWorkerStatus() {
13+
// Settimana più recente raccolta dal collettore (generators/collect-evidence.mjs).
14+
// Le cartelle YYYY-Www ordinano correttamente in lessicografico (settimana a 2 cifre);
15+
// "anchors" non è una settimana ed è esclusa.
16+
function latestWeek() {
1717
if (!existsSync(SNAPSHOTS_DIR)) return null;
1818
const weeks = readdirSync(SNAPSHOTS_DIR, { withFileTypes: true })
1919
.filter((d) => d.isDirectory() && d.name !== "anchors")
2020
.map((d) => d.name)
2121
.sort();
22-
if (weeks.length === 0) return null;
23-
const latest = weeks[weeks.length - 1];
24-
const file = join(SNAPSHOTS_DIR, latest, "status.json");
22+
return weeks.length > 0 ? weeks[weeks.length - 1] : null;
23+
}
24+
25+
function readJsonSnapshot(week, filename) {
26+
const file = join(SNAPSHOTS_DIR, week, filename);
2527
if (!existsSync(file)) return null;
2628
try {
27-
const wrapper = JSON.parse(readFileSync(file, "utf8"));
28-
if (!wrapper.ok || !wrapper.data?.worker) return null;
29-
return { week: latest, worker: wrapper.data.worker };
29+
return JSON.parse(readFileSync(file, "utf8"));
3030
} catch {
3131
return null;
3232
}
3333
}
3434

35+
// Componente "worker" (sonda HMAC) dell'ultimo /api/status raccolto.
36+
function latestSnapshotWorkerStatus(week) {
37+
if (!week) return null;
38+
const wrapper = readJsonSnapshot(week, "status.json");
39+
if (!wrapper?.ok || !wrapper.data?.worker) return null;
40+
return { week, worker: wrapper.data.worker };
41+
}
42+
43+
// Quota di repo pubblici (imgauth, imgauthweb, autart-signer) con almeno un
44+
// tag di release (convenzione vX.Y.Z, PRC-release-coordinata). Proxy semplice:
45+
// non conta ancora quante versioni storiche sono taggate, solo se la pratica
46+
// è adottata per repo — si raffina quando esisterà più storico.
47+
function releaseTagRatio(week) {
48+
if (!week) return { ratio: null, tagged: 0, total: 0 };
49+
const repos = ["imgauth", "imgauthweb", "autart-signer"];
50+
const checked = repos
51+
.map((repo) => readJsonSnapshot(week, `tags-${repo}.json`))
52+
.filter((r) => r?.ok);
53+
if (checked.length === 0) return { ratio: null, tagged: 0, total: 0 };
54+
const tagged = checked.filter((r) => Array.isArray(r.data) && r.data.length > 0).length;
55+
return { ratio: pct(tagged, checked.length), tagged, total: checked.length };
56+
}
57+
3558
function isPublic(record) {
3659
return (record.visibility ?? "public") === "public";
3760
}
@@ -90,22 +113,23 @@ function computeIndicators(records) {
90113
const reproducibility = pctCtlVerify;
91114

92115
// Integrità: media dei componenti disponibili tra sonda HMAC (ultimo snapshot
93-
// settimanale) e quota di ancoraggi dogfooding mensili onorati da quando il
94-
// GTF esiste — manca ancora lo storico delle release taggate (terzo componente
95-
// dichiarato in MET-integrity.yaml).
96-
const snap = latestSnapshotWorkerStatus();
116+
// settimanale), quota di ancoraggi dogfooding mensili onorati e quota di repo
117+
// pubblici con almeno un tag di release.
118+
const week = latestWeek();
119+
const snap = latestSnapshotWorkerStatus(week);
97120
const WORKER_SCORE = { ok: 100, degraded: 50, down: 0 };
98121
const workerComponent = snap ? WORKER_SCORE[snap.worker] ?? null : null;
99122
const anchor = dogfoodingAnchorRatio();
100-
const integrityComponents = [workerComponent, anchor.ratio].filter((v) => v !== null);
123+
const tags = releaseTagRatio(week);
124+
const integrityComponents = [workerComponent, anchor.ratio, tags.ratio].filter((v) => v !== null);
101125
const integrity =
102126
integrityComponents.length > 0
103127
? Math.round(integrityComponents.reduce((a, b) => a + b, 0) / integrityComponents.length)
104128
: null;
105129
const integrityNote =
106130
integrityComponents.length > 0
107-
? `parziale: sonda HMAC (${snap ? `componente "worker", snapshot ${snap.week}` : "nessuno snapshot"}) + ancoraggi dogfooding onorati (${anchor.done}/${anchor.expected} mesi da ${GTF_BIRTH_MONTH}) — manca ancora lo storico delle release taggate`
108-
: "richiede almeno uno snapshot dal collettore di evidenze o un ancoraggio dogfooding (nessuno dei due ancora raccolto)";
131+
? `sonda HMAC (${snap ? `componente "worker", snapshot ${snap.week}` : "nessuno snapshot"}) + ancoraggi dogfooding onorati (${anchor.done}/${anchor.expected} mesi da ${GTF_BIRTH_MONTH}) + repo con tag di release (${tags.tagged}/${tags.total || "n/d"}) — proxy iniziale, non ancora la quota storica di versioni taggate`
132+
: "richiede almeno uno snapshot dal collettore di evidenze, un ancoraggio dogfooding o dati sui tag (nessuno ancora raccolto)";
109133

110134
return [
111135
{ id: "MET-transparency", label: "Trasparenza", value: transparency },
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
id: EVD-git-authart
22
title: Storia git del firmatario crittografico PDF (repo autart-signer)
3-
location: { system: github, ref: "repo autart-signer, commit unico 9e524b2", public_via: "https://github.com/SPAZIO-GENESI/autart-signer" }
3+
location: { system: github, ref: "repo autart-signer, commit unico 9e524b2, storia commit + tag di versione", public_via: "https://github.com/SPAZIO-GENESI/autart-signer" }
44
collection: auto
55
integrity: "storia sostituita in blocco una tantum (rimozione p12/password dalla cronologia, vedi backlog P11); repo eliminato e ricreato il 2026-07-09 per garanzia contro oggetti orfani lato server; da quel punto in poi immutabile di fatto"
66
visibility: public

registry/metrics/MET-integrity.yaml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ formula: >
55
di release con tag git, quota di ancore OpenTimestamps mensili dogfooding
66
riuscite su attese. score.mjs calcola la media dei componenti disponibili:
77
il campo "worker" dell'ultimo snapshot settimanale (ok=100, degraded=50,
8-
down=0) e la quota di bundle mensili committati in snapshots/anchors/
8+
down=0); la quota di bundle mensili committati in snapshots/anchors/
99
rispetto ai mesi trascorsi da GTF_BIRTH_MONTH (2026-07, un bundle onorato
10-
= un mese). Il terzo componente — quota di release con tag git — resta
11-
fuori portata: nessuno storico di release taggate esiste ancora. Il
12-
valore mostrato è quindi tuttora dichiaratamente parziale (contrassegnato
13-
con un asterisco nel Trust Center), non l'intero indicatore descritto in
14-
GTF-ARCH §8.2.
15-
unit: "0-100 (parziale) oppure n/d se non esiste né uno snapshot né un ancoraggio"
10+
= un mese); e (dal 2026-07-09, PRC-release-coordinata) la quota di repo
11+
pubblici tra imgauth/imgauthweb/autart-signer con almeno un tag `vX.Y.Z`
12+
su GitHub, letta dallo snapshot settimanale (tags-<repo>.json). Il terzo
13+
componente è un **proxy iniziale** (solo "il repo tagga le release?", non
14+
ancora "quale quota delle versioni storiche ha un tag") finché non si
15+
accumula più storico dopo l'adozione della convenzione. Il valore
16+
mostrato resta dichiaratamente parziale (contrassegnato con un asterisco
17+
nel Trust Center), non l'intero indicatore descritto in GTF-ARCH §8.2.
18+
unit: "0-100 (parziale) oppure n/d se non esiste alcun dato per nessuno dei tre componenti"
1619
visibility: public

registry/processes/PRC-release-coordinata.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ id: PRC-release-coordinata
22
title: Rilascio coordinato di una modifica cross-repo
33
owner: maintainer del servizio
44
trigger: "una modifica che tocca il contratto API tra imgauth e authweb (o authart), o un cambiamento visibile all'utente"
5-
output: "bump di versione nel manifest di ciascun componente toccato (package.json / APP_VERSION / APP_VERSION app.py), redeploy coordinato, voce nel changelog utente se rilevante"
5+
output: "bump di versione nel manifest di ciascun componente toccato (package.json / APP_VERSION / APP_VERSION app.py), tag git `vX.Y.Z` creato e pushato nel repo del componente (convenzione dal 2026-07-09, alimenta MET-integrity), redeploy coordinato, voce nel changelog utente se rilevante"
66
produces_evidence: [EVD-changelog-user, EVD-versions-live]
77
human_cost_minutes_month: 30
88
visibility: public

site/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ <h1>Il registro della fiducia di Spazio Genesi ETS</h1>
129129
<table class="ledger-table">
130130
<tbody>
131131
<tr class="is-counted"><td class="ledger-label">Trasparenza</td><td class="ledger-value">95</td></tr>
132-
<tr class="is-counted is-partial" title="parziale: sonda HMAC (componente &quot;worker&quot;, snapshot 2026-W28) + ancoraggi dogfooding onorati (1/1 mesi da 2026-07) — manca ancora lo storico delle release taggate"><td class="ledger-label">Integrità *</td><td class="ledger-value">100</td></tr>
132+
<tr class="is-counted is-partial" title="sonda HMAC (componente &quot;worker&quot;, snapshot 2026-W28) + ancoraggi dogfooding onorati (1/1 mesi da 2026-07) + repo con tag di release (0/n/d) — proxy iniziale, non ancora la quota storica di versioni taggate"><td class="ledger-label">Integrità *</td><td class="ledger-value">100</td></tr>
133133
<tr class="is-counted"><td class="ledger-label">Tracciabilità</td><td class="ledger-value">100</td></tr>
134134
<tr class="is-counted"><td class="ledger-label">Documentazione</td><td class="ledger-value">100</td></tr>
135135
<tr class="is-counted"><td class="ledger-label">Automazione</td><td class="ledger-value">71</td></tr>

site/score.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"id": "MET-integrity",
1313
"label": "Integrità",
1414
"value": 100,
15-
"note": "parziale: sonda HMAC (componente \"worker\", snapshot 2026-W28) + ancoraggi dogfooding onorati (1/1 mesi da 2026-07) — manca ancora lo storico delle release taggate"
15+
"note": "sonda HMAC (componente \"worker\", snapshot 2026-W28) + ancoraggi dogfooding onorati (1/1 mesi da 2026-07) + repo con tag di release (0/n/d) — proxy iniziale, non ancora la quota storica di versioni taggate"
1616
},
1717
{
1818
"id": "MET-traceability",
@@ -59,5 +59,5 @@
5959
"note": "richiede dati GitHub, score v0 lavora solo offline dal registro"
6060
}
6161
],
62-
"computed_at": "2026-07-09T15:55:21.356Z"
62+
"computed_at": "2026-07-09T16:01:14.705Z"
6363
}

0 commit comments

Comments
 (0)