VRP - Catalogo dei Database

Stato: 2026-07-10. Elenco di TUTTI i database della piattaforma: tabelle,

scopo, credenziali, migrazioni, + accesso CLI e utenti del server. Modello di

riferimento in VRP_B200_architettura. Un solo

server MariaDB.

Regola d'oro

possibili (stesso server).

password, in cassaforte): l'utente di default della CLI (vv_backup via

~/.my.cnf) e' in sola-lettura e vede solo photo e vittrosviaggi.

Dettagli in "Accesso da riga di comando (CLI)" e "Utenti del server MariaDB".

I database

vrp_auth [ESISTE - identita' condivisa + sessioni/azioni]

Identita' unica di piattaforma (login UNICO) + ruoli per-servizio + registro

accessi/azioni. Letto via vrp_db('vrp_auth'). Tabelle e vista:

id [PK], username [UNIQUE], email, pass_hash (password_hash), display_name,

motto (06/09/2026), avatar, is_active (0=disattivato), created_at,

last_login_at. Letta da vrp_login/vrp_current_user.

📌 avatar e motto sono il corrente; i precedenti stanno in user_storia.

cambio. id [PK], user_id [FK->users.id, CASCADE], cosa ENUM('avatar','motto'),

valore (nome del file oppure testo), ritirato_il, ritirato_da (chi ha fatto

il cambio: il padrone o un admin). UNA tabella per due cose perche' e' lo stesso

mestiere; UNA data sola perche' il "da quando" e' il ritirato_il della riga

precedente. Registro che si APPENDE e non si rilegge mai per sapere "chi sono

adesso" -> non puo' nascere una seconda verita'.

Scritta/letta da vrp_user_ritira() / vrp_user_storia() (lib/vrp_auth.php).

id [PK], user_id [FK->users.id, CASCADE], nome, brani (chiavi

<scaffale>/<file> separate da |, in ordine - stesso idioma di post.musica),

creata_il, cambiata_il; UNIQUE(user_id,nome) -> salvare con lo stesso

nome AGGIORNA. Sta qui perche' e' appesa a un utente e il JukeBox non ha un DB

suo (come vrw_import). Si LEGGE da tutti, ospiti compresi; la SCRIVE solo il

padrone (o un admin).

ogni servizio. user_id+service [PK composta], role (es. admin/editor/viewer/

registrato/amik_nat), granted_at. Un utente ha piu' righe (una per servizio).

Letta da vrp_current_user -> roles[service]=role.

php_sid, user_id [FK->users.id, NULL=ospite], ip, user_agent, service,

version, action, detail, started_at, last_activity, ended_at.

Due tipi di riga: (1) CICLO-SESSIONE action in login/logout/timeout, la riga viva

si aggiorna via UPDATE (vrp_login/vrp_logout/vrp_session_check); (2) EVENTO

(azione utente) action in upload/download/delete/create_dir/... con detail umano

("caricato il file X"), INSERT nuova via vrp_insert_action (lib vrp_action.php).

display_name leggibili. La legge la pagina Admin Sessioni (pages/sessioni.php,

filtri username/action, colonne configurabili incl. detail). Suffisso _h=vista umana.

SELECT/INSERT/UPDATE/DELETE -> le DDL le lancia root).

⚠️ Il root di MariaDB qui NON e' unix_socket: vuole la sua password (cassaforte

KeePass VittRos.kdbx). sudo mysql non basta e da' `Access denied ... (using

password: NO); il comando giusto e' mariadb -u root -p <db> < file.sql`.

Ultima DDL: docs/VRP_ddl_20260906_motto_avatar_playlist.sql (06/09/2026).

vittrosviaggi [ESISTE - VRV, diario]

Contenuti del diario. Tabelle principali:

Parentela dei post (colonne di post, spiegate anche nei loro COMMENT,

quindi visibili con SHOW FULL COLUMNS FROM post):

colonnafamigliadomanda a cui risponde
parent_idLINGUAda chi sono stato tradotto (padre immediato)
source_idLINGUAa che famiglia appartengo (il capostipite)
gemello_idANWchi e' il mio gemello di variante opposta
varianteANWsono tessile o naturista

parent_id e source_id coincidono sempre, perche' si traduce solo

dall'italiano e gli alberi sono profondi un livello. Si separerebbero solo

traducendo *da una traduzione* (it -> en -> is): l'islandese avrebbe

parent=en ma source=it. Mai successo finora.

Si tengono tutte e due per un motivo solo: **il capostipite puo' portare

source_id** (punta a se stesso), parent_id no. Quindi la famiglia

intera, radice compresa, si legge in una query piatta senza ricorsione:

SELECT * FROM post WHERE source_id = 117; -- le 6 lingue delle Olimpiadi

source_id e' una scorciatoia (indice denormalizzato), non un secondo

concetto. La usano visualizza_post.php (selettore di lingua), le tre viste

vw_post_effective*, ajax/create_translation.php.

*Invarianti* da mantenere quando si creano o spostano post:

1. ogni figlio ha source_id valorizzato e uguale a quello del padre;

2. ogni capostipite con almeno un figlio ha source_id = id;

3. nessun source_id/gemello_id punta a un post inesistente;

4. gemello_id e' reciproco (se A punta a B, B punta ad A);

5. un post singolo puo' avere source_id NULL: il codice usa il fallback

source_id ?: id.

Query di controllo (devono dare tutte 0):

SELECT COUNT(*) FROM post WHERE parent_id IS NOT NULL AND source_id IS NULL;

SELECT COUNT(*) FROM post p WHERE p.source_id IS NULL

AND EXISTS (SELECT 1 FROM post c WHERE c.parent_id = p.id);

SELECT COUNT(*) FROM post p WHERE p.source_id IS NOT NULL

AND NOT EXISTS (SELECT 1 FROM post q WHERE q.id = p.source_id);

SELECT COUNT(*) FROM post p WHERE p.gemello_id IS NOT NULL

AND NOT EXISTS (SELECT 1 FROM post q WHERE q.id = p.gemello_id);

SELECT COUNT(*) FROM post c JOIN post p ON p.id = c.parent_id

WHERE c.source_id <> p.source_id;

*Riparazione 27/07/2026* su vittrosviaggi_lab (backup preso prima): 23

source_id mancanti riempiti (tutti da NULL, nessuna sovrascrittura), 1

source_id fantasma azzerato (post 65 -> 1), 2 gemello_id fantasma

azzerati (post 19 -> 156, post 58 -> 155: quei gemelli non esistono; se

servono, vanno ricreati). Il selettore di lingua era rotto: 14 traduzioni

su 17 non venivano trovate. **PRODUZIONE (vittrosviaggi) riparata lo

stesso giorno** (26 modifiche, 0 sovrascritture, backup prima): riverificato

il 29/07, figli orfani = 0 e il post 117 rende 6 lingue (prima 1).

*CR aperta*: rinominare source_id in famiglia_id (il nome dice

"sorgente" ma il significato e' "famiglia"). Non fatto subito: tocca tre

viste e mezza dozzina di file per zero funzionalita' in piu'.

cofanetto + cofanetto_post [CREATE 29/07/2026, solo lab]

Terzo livello, sopra la famiglia-lingue: raggruppa post diversi per tema

(una serie, un'annata di viaggi). La famiglia ha un capostipite naturale (il

post italiano), il cofanetto no -> ha una riga propria con un nome.

COFANETTO "L'inchiesta sui fazzoletti scomparsi" <- cofanetto

+-- FAMIGLIA Ep.1 (125) --> en, de... <- cofanetto_post

+-- FAMIGLIA Ep.2 (124) --> ...

*Decisione di disegno*: il cofanetto lega famiglie, non post. La riga di

cofanetto_post punta al capostipite (famiglia_id = source_id ?: id,

invariante 5 qui sopra), non alla singola lingua. Conseguenza pratica: il

visore disegna la barretta "prec / cofanetto / succ" risolvendo ogni voce

nella lingua in lettura, con ripiego sull'originale se quella puntata non e'

tradotta. La barretta cucita a mano nel contenuto (25/07) aveva invece i

link agli ID italiani -> da una traduzione si rimbalzava in italiano.

Nessun cofanetto_id dentro post: due tabelle nuove, zero ALTER sul

tavolo dove lavora Elena (vedi la regola sui DDL a fine documento).

cofanetto

post disegnato a mano (il 167); se NULL l'indice lo genera il visore.

cofanetto_post

sta in un solo cofanetto (cosi' "prec/succ" non e' mai ambiguo).

Query di controllo (devono dare tutte 0):

SELECT COUNT(*) FROM cofanetto_post cp

WHERE NOT EXISTS (SELECT 1 FROM post p WHERE p.id = cp.famiglia_id);

SELECT COUNT(*) FROM cofanetto_post cp JOIN post p ON p.id = cp.famiglia_id

WHERE p.source_id IS NOT NULL AND p.source_id <> p.id; -- non capostipite

Indice di un cofanetto in una lingua (query base del visore):

SELECT cp.ordine, COALESCE(t.id, o.id) AS post_id

FROM cofanetto_post cp

JOIN post o ON o.id = cp.famiglia_id

LEFT JOIN post t ON COALESCE(t.source_id,t.id) = cp.famiglia_id

AND t.lingua = :lang

WHERE cp.cofanetto_id = :c ORDER BY cp.ordine;

*Primo contenuto* (29/07): cofanetto 1 = il Pentateuco dei fazzoletti,

famiglie 125/124/158/165/166 in ordine 1..5, copertina 167, categoria 2.

fuori dai release). Il VRV storico usa ancora meta/secrets.local.json.

lenostre [ESISTE - indice foto, 35.022 righe]

Indice delle foto dell'archivio leNostre.

larghezza, altezza, orientation, lat, lon, scattata_il, bytes,

mtime, hash_md5, indicizzata_il.

ln_reindex_target) + popola_foto_index.php. Ogni mutazione FS lo riallinea.

foto f. Oggi = foto con in piu' la colonna calcolata tipo`

('foto'|'video', dedotta dall'estensione del nome). Tutte le 35k righe sono

'foto': i video del disco NON sono ancora indicizzati (scelta 10/08: solo foto

per ora). E' il SEAM per i video futuri -> il codice NUOVO del VRN legge

media e ramifica su tipo; quando i video entreranno nell'indice, la vista

li assorbe senza cambiare i consumatori. Vista MERGE (usa ix_cartella).

Il codice ESISTENTE (vrn_foto_search) resta su foto finche' non si fanno i

video sul serio. Dettagli in vrv_port/09_riconversione_lenostre50.md.

photo [ESISTE - LEGACY, da dismettere]

Solo tabelle utente di leNostre50: users, user_h, user_history,

user_history_sav. -> Migrare gli utenti in vrp_auth, poi dismettere.

(NB: si chiama "photo" ma NON contiene foto: quelle sono in lenostre.)

vv_tmp [ESISTE - da verificare]

Scopo da verificare (temporaneo?).

vrs / share [SERVIZIO VIVO - dati in vittrosviaggi]

Il servizio Share (/lab/public/share/, lib platform/lib/vrs.php) e' in produzione nel

lab. I dati vivono in vittrosviaggi, letti via DB vrv. Modello = due tabelle + i file su

disco (share_storage/dirs/<dir_id>/<filename_stored>); le miniature NON si copiano (al volo

via vrp_img, cappello thumb.php). Cancellazione HARD (rimuove file+tupla).

madre; NULL/radice=root_dir_id 1), name, owner_user_id (proprietario, per i permessi),

created_at, updated_at, is_deleted (colonna soft-delete presente ma oggi si cancella

hard). L'albero e' "ognuno sa il padre".

filename_original (nome mostrato all'utente), filename_stored (nome sul disco, con

suffisso _N anti-collisione), mime_type, size_bytes, owner_user_id, created_at,

updated_at, is_deleted. I due nomi servono perche' due utenti possono caricare "foto.jpg".

Azioni loggate nel registro (vrp_insert_action('vrs',...)): create_dir, upload, download,

delete (file e cartella). Da valutare (non urgente) se estrarre in un DB dedicato vrs.

registro azioni utente [FATTO 09/07 - opzione A]

Log DB di "chi ha fatto cosa/quando" in italiano. SCELTA: opzione A = riga nella sessions

(colonna detail aggiunta, action='upload'/'delete'/...) mostrata nella pagina Sessioni coi

filtri. Funzione vrp_insert_action(service,action,detail) in platform/lib/vrp_action.php

(riusa vrp_insert, non-bloccante). Agganciata nello share (create_dir/upload/download/delete).

DA FARE: agganci import-foto/crea-post + bottone Purge nella pagina Admin (svuota le

righe-evento vecchie; distinto dal logrotate, che tocca i file di log non il DB).

Credenziali (da centralizzare)

Stato attuale: i segreti dei DB usati dalla piattaforma sono TUTTI nel posto STABILE

/srv/http/vittrosviaggi_shared/secrets/ (fuori dai release che ruotano), puntati da

env.json (registro db) e letti da platform/lib/vrp_db.php:

Il VRV storico (fuori piattaforma) usa ancora meta/secrets.local.json.

LEZIONE APPRESA (02/07): le creds di lenostre stavano in vv_work/testing/

(un release DEV). Ritirando vv_work col B500, il path si e' rotto e wiz_foto

e' andato giu'. I segreti/config NON vanno in un release che ruota: spostati

nello shared stabile. Lavoro-piattaforma: un solo punto in platform/boot/,

letto da vrp_db.php.

Accesso da riga di comando (CLI)

Attenzione: root NON e' piu' passwordless. Tre modi, in ordine d'uso:

1. mariadb (senza argomenti) -> entra come vv_backup grazie a

~/.my.cnf (utente unix vitti): sola-lettura su photo e vittrosviaggi,

e show databases mostra SOLO quei due (+ information_schema). Comodo per

sbirciare il diario; NON vede vrp_auth/lenostre e non scrive.

2. root (vede tutto, DDL) -> mariadb -u root -p e incolla la password

dalla cassaforte (KeePass VittRos.kdbx). ATTENZIONE: mariadb -u root

SENZA -p FALLISCE ("Access denied ... using password: YES") perche' il

password= di ~/.my.cnf (di vv_backup) viene iniettato lo stesso; il -p

sulla riga di comando lo scavalca. Il -p (senza valore attaccato) chiede la

password in modo NASCOSTO: non finisce ne' in ps ne' nella history. NON

usare mai -p<password> attaccato (finirebbe in chiaro).

3. Da script/PHP -> mai root: usa gli utenti-app via i secrets in

/srv/http/vittrosviaggi_shared/secrets/ (letti da vrp_db()). Es.:

require '.../platform/boot/3_2_1_Go.php'; vrp_row('vrp_auth', "SELECT ...");

E' il percorso collaudato (ogni servizio col suo utente, un DB ciascuno).

Piu' utenti in ~/.my.cnf (dal 10/07): oltre al [client] di default

(vv_backup), il file ha gruppi extra selezionabili con --defaults-group-suffix:

mariadb --defaults-group-suffix=vitti -> utente vitti (scrive su

vittrosviaggi); mariadb --defaults-group-suffix=mig -> utente vviaggi_mig

(DDL su vittrosviaggi). Le password stanno in chiaro nel file (mode 600, e in

cassaforte).

Utenti del server MariaDB

Ricognizione 2026-07-10 (letta da mysql.user come root). 16 utenti + il

mariadb.sys di sistema. Le PASSWORD non stanno qui (solo in cassaforte e nei

secrets): qui utente, host, privilegi e SCOPO.

In uso - NON toccare

Utente@hostPrivilegiServe a
root@localhost / 127.0.0.1 / ::1ALL + GRANT OPTIONamministrazione, DDL. Pwd in cassaforte KeePass VittRos.kdbx
vrp_auth_app@localhostS/I/U/D su vrp_authidentita' + sessioni/azioni della piattaforma (secrets db_vrp_auth.php)
vviaggi_app@localhostS/I/U/D + CREATE TEMP/LOCK/SHOW VIEW/EVENT/TRIGGER su vittrosviaggiapp VRV/diario + share (secrets db_vrv.php)
lenostre_app@localhostS/I/U/D su lenostre.* ; S/I/U/D su photo.users + photo.user_historyindice foto + utenti legacy leNostre50 (secrets db_lenostre.php, db_photo.php)
vv_backup@localhostSELECT/LOCK/SHOW VIEW/EVENT/TRIGGER su photo + vittrosviaggibackup / lettura di comodo; e' il DEFAULT di ~/.my.cnf
vviaggi_mig@localhostS/I/U/D/CREATE/DROP/INDEX/ALTER/CREATE VIEW/SHOW VIEW/TRIGGER su vittrosviaggiutente di MIGRAZIONE del DB VRV (DDL senza root)
vitti@localhostS/I/U/D/CREATE/DROP/INDEX/ALTER/CREATE TEMP/LOCK/EVENT/TRIGGER su vittrosviaggiutente personale di vitti sul diario (NON e' il default: quello e' vv_backup)
mariadb.sys@localhostUSAGE + SELECT/DELETE su mysql.global_privutente di sistema MariaDB, sempre presente. NON si tocca

Relitti / da rivedere

Utente@hostCosa puo'Verdetto
wordpress_user@localhostALL su wordpress.*WordPress non esiste piu' su manG3 (0 wp-config, 0 codice, verif. 10/07) -> DROP sicuro
lella@localhostALL su wordpress.*account *MySQL* di WordPress, NON il login-app di Elena (quello e' un record in vrp_auth, via vrp_auth_app) -> DROP sicuro, Elena non ne risente
SantUtto@localhost / 127.0.0.1 / ::1quasi-super (SUPER, FILE, CREATE USER, PROCESS, RELOAD...) senza GRANT OPTIONereditato dai tempi del NAS (~2 anni fa); non citato in codice/secrets (verif. 10/07) -> DROP sicuro
backup@localhostRO su photo + vittrosviaggi (come vv_backup, un filo diverso)PREDECESSORE di vv_backup; il cron vv_backup_sacro.sh usa vv_backup via .my.cnf, non questo (verif. 10/07) -> DROP sicuro
vitti_user@%ALL su *.* + GRANT OPTION da QUALSIASI host + ALL su vitti_user\_%.** SUPERUTENTE REMOTO * stile pannello-hosting, raggiungibile da ovunque; non usato da niente (verif. 10/07) -> DROP consigliato (o restringere l'host da % a localhost)

Pulizia pronta (10/07, la lancia root): prima un backup dei grant in un file

protetto fuori dal web, poi i DROP:

DROP USER 'SantUtto'@'localhost','SantUtto'@'127.0.0.1','SantUtto'@'::1';
DROP USER 'lella'@'localhost';
DROP USER 'wordpress_user'@'localhost';
DROP USER 'backup'@'localhost';
DROP USER 'vitti_user'@'%';   -- consigliato (superuser remoto)
FLUSH PRIVILEGES;

Nota sicurezza (CHIUSA 10/07): prima 7 utenti condividevano lo STESSO

hash-password (una sola password debole riusata). Dopo i DROP dei relitti

restavano vitti, vv_backup, vviaggi_mig su quella password -> **RUOTATE

10/07**, ora 3 password forti DISTINTE (32 char, non-umane) via ALTER USER,

allineate in ~/.my.cnf (gruppi) e in cassaforte. root, vrp_auth_app,

vviaggi_app, lenostre_app avevano gia' password proprie.

Migrazioni previste

1. vrp_auth: unificare utenti VRV + leNostre50 (delicato: ruoli, chi-puo-cosa).

2. dismettere photo dopo la migrazione utenti.

3. (eventuale) estrarre share in vrs.