docs(handover): vault-steward chain fix (race + cli) — 31/5
Race in audit.log() fixata con transazione + SELECT FOR UPDATE; CLI audit fix LIMIT bug; chain re-anchor entry id 23793. Doc completo in docs/INCOMING_FROM_AGILEHUB_2026_05_31_vault_chain_fix.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
d103e9d88e
commit
f2ee6801e1
@@ -0,0 +1,80 @@
|
||||
# OUTGOING → TUTTI i container DevEnv — Vault audit chain: race fix + CLI fix + storico (2026-05-31)
|
||||
|
||||
> **Da**: AgileHub-side (VIGILE)
|
||||
> **A**: ogni sessione Claude su tutti i dev container.
|
||||
> **Trigger**: findings segnalati dalla sessione TRPG-side + direttiva utente "se devi segnalare aggiornamenti, devi farlo per tutti i dockers dev". Doc forense completa: `/opt/vault-steward/CHAIN_REANCHOR_2026_05_31.md` (host).
|
||||
|
||||
---
|
||||
|
||||
## TL;DR — Cosa ti tocca sapere come sessione dev
|
||||
|
||||
| Cosa | Stato dal 31/5 |
|
||||
|---|---|
|
||||
| `docker exec vault-steward node cli/vault-cli.js audit [--last=N]` | ✅ **ora funziona** (era rotto con `Incorrect arguments to mysqld_stmt_execute`) |
|
||||
| `docker exec vault-steward node cli/vault-cli.js verify-chain` | ⚠️ **mostra ancora `❌ Chain BROKEN at id=257`** — è **storico**, NON panico, NON tampering |
|
||||
| Nuove entry audit (post `id=23793`) | ✅ chain HMAC affidabile per la prima volta |
|
||||
| Le tue letture credenziali via vault wrapper (boot MS) | ✅ funzionano identiche a prima (lato API zero cambiamenti) |
|
||||
|
||||
**Bottom line**: nessun impatto sul tuo lavoro quotidiano. Se fai troubleshooting/audit del vault, leggi sotto.
|
||||
|
||||
---
|
||||
|
||||
## Il bug che è stato chiuso
|
||||
|
||||
Dal **2026-04-25 (boot vault) al 2026-05-31** la funzione `audit.log()` aveva una **race condition concorrente fra writer paralleli** (SELECT prev_hash + INSERT senza transazione → due scritture parallele leggevano lo stesso prev_hash e inserivano entrambe con quello, "vecchio di una posizione"). Risultato: **1645 race break su 23.727 entry** (~7% delle scritture corrompeva il linkage HMAC della chain), ~43 break/giorno sotto carico normale.
|
||||
|
||||
**Smoking gun** (row 257):
|
||||
```
|
||||
Row 256: prev_hash=1822f8… row_hash=a7ced0… 15:52:02.263783
|
||||
Row 257: prev_hash=1822f8… row_hash=6a594e… 15:52:02.266327
|
||||
^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
stesso prev_hash di 256 scritta 2.5 ms dopo
|
||||
```
|
||||
Stesso actor `agile-services-devenv-runtime`, race di 2.5 ms.
|
||||
|
||||
**NON era tampering** (pattern temporale + actor identici = race del codice, non attacco).
|
||||
|
||||
## Il fix (LIVE da 31/5 ~11:23 UTC)
|
||||
|
||||
1. **`audit.log()` riscritta** con transazione + `SELECT ... FOR UPDATE` (serializza writer concorrenti).
|
||||
2. **`db.js`** esporta `getConnection()` per transazioni.
|
||||
3. **`vault-cli.js audit`** fix LIMIT (mysql2 `execute()` non binda LIMIT → interpolazione safe con `parseInt + clamp`).
|
||||
4. **Re-anchor entry**: id **23793** action `audit_chain_reanchor` hash `ea41503cace7828d…` — marker della "nuova chain pulita".
|
||||
|
||||
**Validazione**: stress test 50 letture concorrenti dopo il fix → **0 nuovi race break** (1647 → 1647 invariato). Container ricreato con downtime ~5s, nessun MS in regressione.
|
||||
|
||||
## Cosa significa per te quando vedi `verify-chain → BROKEN at id=257`
|
||||
|
||||
**NON è un attacco in corso.** È il primo dei 1645 race break storici. Per verifiche forensi affidabili:
|
||||
- Le entry `id < 23793` esistono come *record valido* (actor/action/target/success leggibili) ma il chain HMAC non è verificabile come catena unica continua — solo a pezzi fra un break e il successivo.
|
||||
- Le entry `id ≥ 23793` formano una chain HMAC verificabile end-to-end.
|
||||
|
||||
Se vuoi controllare l'integrità della parte recente:
|
||||
```bash
|
||||
docker exec vault-steward node -e "
|
||||
const db = require('/app/db'), audit = require('/app/audit'), fs = require('fs');
|
||||
db.init({ host: process.env.VAULT_DB_HOST, port: 3306, database: 'vault_db',
|
||||
user: 'vault_user', password: fs.readFileSync(process.env.VAULT_DB_PASS_FILE, 'utf8').trim() })
|
||||
.then(() => audit.verifyChain())
|
||||
.then(r => { console.log(r); return db.close(); });
|
||||
"
|
||||
```
|
||||
(o pi ucomodamente `vault-cli.js verify-chain`, ma è in TODO un parametro `--from=<id>` per partire dal reanchor.)
|
||||
|
||||
## File modificati lato host (per chi fa rollback/manutenzione)
|
||||
|
||||
- `/opt/vault-steward/audit.js` — nuova `log()` transazionale (era nell'image, ora bind-mountato).
|
||||
- `/opt/vault-steward/db.js` — aggiunta `getConnection()` (era nell'image, ora bind-mountato).
|
||||
- `/opt/vault-steward/vault-cli.js` — fix LIMIT (già bind-mountato).
|
||||
- Container ricreato con i 2 nuovi `-v` (prima solo `vault-cli.js`+`server.js` erano bind-mounted).
|
||||
- Backup pre-fix in `/opt/vault-steward/backups-pre-chain-fix-20260531-091547/`.
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- Doc forense completa: `/opt/vault-steward/CHAIN_REANCHOR_2026_05_31.md` (200+ righe).
|
||||
- VIGILE audit log: `agile-services/docs/VIGILE_AUDIT_LOG.md` entry `[VAULT-CHAIN-FIX]` 31/5 11:25 UTC.
|
||||
- Standard cross-suite `vault-steward-credential-management` (`hub_standards` id=7): valido + ora con chain HMAC effettivamente reliable.
|
||||
|
||||
---
|
||||
|
||||
**Fine documento.** Lavorate sicuri.
|
||||
Reference in New Issue
Block a user