Modello dati — Panoramica
Questo è il livello di osservabilità dei nostri dati stessi. Finora non c'era un unico posto in cui rispondere a "quali entità ha effettivamente Playroll, e come si collegano?" — dovevi leggere le migrazioni o frugare in Supabase. Questa sezione è quell'unico posto.
È scritta per essere letta in due modi:
- Come PM / non-ingegnere — leggi questa pagina dall'inizio alla fine. Ogni dominio ha una scheda in linguaggio semplice e una riga di glossario. Puoi ignorare le tabelle delle colonne.
- Come ingegnere (zoinkwiz, Vincenzo, Alessio, Marco) — le pagine per-dominio ti danno le colonne chiave e le relazioni; il riferimento completo ti dà ogni colonna, tipo e chiave esterna di tutte le 45 tabelle.
Questo atlante descrive lo schema public live del progetto Supabase di
Playroll (il DB del recorder C++). È generato dal database stesso, non
inventato a mano. La sede canonica dello schema è
playroll-cpp/supabase/migrations — se atterra una migrazione che cambia la
forma qui sotto, è questa sezione che viene aggiornata di pari passo.
Il contributor portal ha un proprio database separato e una propria
pagina Modello dati; l'unico ponte tra
i due è la tabella contributor_status_projection descritta in
Identità e accesso.
Come leggere le mappe
Ogni pagina di dominio disegna un diagramma entità-relazione Mermaid. Due simboli portano tutto il significato:
- Un riquadro è una tabella (un'entità). La sua riga superiore è il nome; le righe sotto di essa sono le colonne che vale la pena conoscere.
- Una linea è una chiave esterna — un puntatore rigido da una tabella all'altra. Il
piede di gallina (la piccola forcella
<) sta sul lato "molti". QuindiELIGIBLE_GAMES ||--o{ LOBBIESsi legge "un eligible game può sostenere molte lobby."
Quando una relazione è per valore anziché una vera chiave esterna (es. una
stringa di stato, o una regola JSON che nomina un tier), lo diciamo in prosa invece di
disegnare una linea — esattamente come fa il modello quests per le regole di audience. Una manciata
di archi sono disegnati verso playroll_users per leggibilità ma fisicamente fanno riferimento ad
auth.users (i due sono 1:1 sullo stesso UUID); le pagine di dominio lo segnalano.
Un'ultima avvertenza che i diagrammi non possono mostrare: la row-level security è abilitata su ogni tabella. Il fatto che una relazione sia disegnata non significa che un client browser possa leggere attraverso di essa — molte tabelle sono raggiungibili solo tramite una edge function o la service key. Ogni pagina di dominio ha una breve nota "modello di accesso"; fidati di quelle più che del diagramma quando ragioni su ciò che l'app può effettivamente leggere.
L'intero ecosistema, a colpo d'occhio
Sei domini, più una manciata di tabelle di supporto. La spina dorsale della registrazione al centro è la cosa che tutto il resto decora — un utente registra una sessione, la sessione produce upload, e identità / catalogo / lobby / crescita pendono tutti da quell'atto.
I sei domini
🟦 Identità e accesso
Chi è un giocatore, e cosa gli è permesso fare. playroll_users è il
fulcro dell'intero database — quasi tutto punta indietro a un utente. Attorno ad esso
stanno l'identità Steam (allowlist, nonce OpenID, arricchimento), due sistemi RBAC separati
(player roles per gli utenti dell'app, CRM roles per lo staff), il ponte verso il contributor-portal
e il log dei consensi append-only.
→ Identità e accesso
🟩 Spina dorsale della registrazione
L'atto fondante del prodotto: registra il gameplay, dimostralo, caricalo. Una
recording_session è l'unità di pagamento e di supporto. Produce s3_uploads
(una riga per file caricato — l'MP4 + CSV + JSON validati, più i sidecar opzionali
_mic.aac / _transcript.json), fa riferimento all'hardware su cui è girata
(device_hw_snapshots), ed è l'input agli stadi di elaborazione GPU pipeline_*. Questa è la spina dorsale su cui si innesta il modello quests.
→ Spina dorsale della registrazione
🟨 Lobby e catalogo
Registrazione co-op, e i giochi che permettiamo. Una lobby è un party che registra
insieme, vincolato a esattamente un gioco. Il catalogo (eligible_games e i suoi
satelliti store / runtime / engine) definisce quali giochi sono registrabili e come
catturarli; user_game_library è la libreria Playnite scansionata di ciascun giocatore.
→ Lobby e catalogo
🟪 Crescita e rete
Come i giocatori portano altri giocatori. Lo shadow_graph è la rete degli amici Steam
dell'utente che alimenta la vista headhunter; gli invite_codes regolano l'accesso
Fase-0; le colonne di referral su playroll_users chiudono il cerchio.
→ Crescita e rete
⬜ Release e notifiche
Far arrivare nuove build e messaggi ai giocatori giusti. Le tabelle app_releases_v2
- rollout sono il cervello degli aggiornamenti scaglionati (track, percentuali, bucket A/B,
override di force-update), auditate per ogni chiamata di resolve. Le tabelle
notification_*sono il sistema di consegna in-app + email con preferenze per-utente e stato di lettura. → Release e notifiche
⬜ Diagnostica (condivisa)
Dirci perché una registrazione è andata storta. nvenc_known_contenders /
nvenc_contender_user_links tracciano quali app di terze parti competono con Playroll per
l'encoder GPU; bug_reports è il canale di segnalazione in-app. Questi sono documentati nelle
pagine Spina dorsale della registrazione e
Release e notifiche accanto a ciò che
diagnosticano.
Vocabolario — una parola, un significato
Le stesse parole vengono riusate liberamente in chat. Ecco cosa significano nei dati:
| Termine | Nel database significa… |
|---|---|
| Utente / giocatore | Una riga in playroll_users, identificata da user_id (un UUID di auth Supabase). L'entità singola più referenziata. |
| Sessione | Una riga in recording_sessions — un tentativo di registrazione da start a stop, identificato da una stringa rec-<epoch-ms>. L'unità di pagamento e di supporto. |
| Set validato | Gli artefatti che il gate di upload richiede per una sessione — MP4, CSV (_input.csv) e JSON (_meta.json). Se la validazione locale blocca, nessuno di essi viene registrato per l'upload (il gate è il punto tutto-o-niente, non l'upload stesso). Ogni file presente atterra poi come una propria riga in s3_uploads. |
| Sidecar | Artefatti opzionali che non condizionano mai la validazione: l'audio del microfono _mic.aac e la trascrizione _transcript.json. Una sessione può quindi avere fino a ~5 artefatti, non 3 — e un sidecar mancante è normale, non un fallimento. |
| Lobby / party | Una riga in lobbies — persone che registrano insieme per un tentativo, vincolate a un singolo gioco. Il "gruppo di N". |
| Eligible game | Una riga in eligible_games — un gioco per cui permettiamo la registrazione, identificato da igdb_id / slug. Il confine rigido contro cui un upload viene controllato. |
| Tier | playroll_users.contributor_tier — il livello di progressione attuale del giocatore (una stringa con default player, non ancora una tabella separata). |
| Track | Un canale di release su cui una build viene pubblicata — l'insieme chiuso `stable |
| Transcript | Il _transcript.json di una sessione — un artefatto di prima classe con la propria generazione GPU-gated, flusso di skip/edit da parte del giocatore e colonne di stato. Vedi Spina dorsale della registrazione → La trascrizione. |
| Contender | Un processo di terze parti visto detenere una sessione NVENC (encoder GPU) mentre Playroll registrava — cioè competizione per l'encoder. |
Indice completo delle tabelle
Tutte le 45 tabelle, raggruppate per il dominio che le possiede. Clicca per arrivare alla pagina di dominio per il diagramma e le colonne chiave, oppure salta al riferimento per ogni colonna.
| Tabella | Dominio | In una riga |
|---|---|---|
playroll_users | Identità | Il fulcro. Una riga per giocatore; 40 colonne che spaziano dall'identità Steam, all'arricchimento, al valore di rete e all'attribuzione. |
steam_id_allowlist | Identità | ID Steam pre-autorizzati. La edge fn di login controlla questa prima di emettere una sessione. |
auth_user_steam_lookup | Identità | Indice steam_id → auth user UUID, mantenuto da trigger. |
steam_openid_nonces | Identità | Nonce di protezione da replay per il sign-in Steam OpenID. |
player_role_catalog | Identità | Catalogo dei player role validi, ordinati per rango. Nuovi ruoli = INSERT, nessuna migrazione. |
player_roles | Identità | Assegnazioni di ruolo per gli utenti dell'app (un giocatore può detenerne diversi). |
crm_user_roles | Identità | RBAC dello staff per il CRM, identificato da email (verificata da Cloudflare Access). |
permissions | Identità | Catalogo delle coppie di permesso (resource, action). |
role_permissions | Identità | Pacchetto Role → permission che la UI admin del CRM modifica. |
device_auth_requests | Identità | Handshake di login device-code legacy (0 righe; soppiantato dal redirect steam-login). |
upload_credentials | Identità | Credenziale per-MAC legacy/inutilizzata (0 righe, nessuno scrittore). |
playroll_user_consents | Identità | Log dei consensi append-only; consent_type a 5 valori (age/tos/privacy/eula/edc_gameplay). |
contributor_status_projection | Identità | Ponte lato-app scritto da redeem-activation-code (stato del link, nessun PII). |
recording_sessions | Spina dorsale | Un tentativo di registrazione; durata canonica + stato di uploadability. |
s3_uploads | Spina dorsale | Una riga per file caricato (MP4/CSV/JSON validati + sidecar opzionali mic/transcript). |
device_hw_snapshots | Spina dorsale | Inventario hardware per-(utente, dispositivo); nuova riga a ogni cambio HW. |
pipeline_sessions | Spina dorsale | Vista della pipeline GPU sugli artefatti S3 di una sessione e sullo stadio di elaborazione. |
pipeline_runs | Spina dorsale | Una riga per esecuzione di pipeline (Prefect flow run) su una sessione. |
nvenc_known_contenders | Diagnostica | Registro delle app di terze parti viste competere per NVENC. |
nvenc_contender_user_links | Diagnostica | Quali utenti hanno visto ciascun contender (conteggio utenti distinti). |
bug_reports | Diagnostica | Segnalazioni di bug in-app con contesto HW/versione. |
lobbies | Lobby | Un party che registra insieme, vincolato a un gioco. |
lobby_participants | Lobby | Chi è in ciascuna lobby + il suo id di sessione. |
lobby_join_events | Lobby | Storico di join/leave (INSERT al join, UPDATE di left_at al leave); guidato da trigger. |
eligible_games | Catalogo | Giochi per cui permettiamo la registrazione (igdb_id / slug). |
game_store_ids | Catalogo | ID per-store (steam/epic/…) per un eligible game. |
game_runtime_profiles | Catalogo | Profilo di cattura per-eseguibile (engine, applicazione delle impostazioni). |
engine_defaults | Catalogo | Specifica delle impostazioni di cattura di default per-engine. |
user_game_library | Catalogo | La libreria Playnite scansionata di ciascun giocatore. |
shadow_graph | Crescita | Amici Steam degli utenti registrati; la rete di reclutamento. |
invite_codes | Crescita | Pool fisso di invite code di Fase-0. |
invite_code_consumptions | Crescita | Una riga per (code, user) — un utente riscatta un dato codice una volta. |
redeem_attempt_log | Crescita* | Log del rate-limiter per il flusso activation-code (EC-227), non gli invite code. (*risiede nell'area activation/contributor nonostante il raggruppamento dell'elenco tabelle.) |
app_releases_v2 | Release | Una build pubblicata (versioni installer + core + UI, note, hash). |
app_rollouts_v2 | Release | Una regola di rollout: track, percentuale, bucket A/B, audience. |
app_rollout_overrides_v2 | Release | Override di pin o force-update per-utente / per-install. |
app_update_resolve_audit_v1 | Release | Una riga per ogni chiamata di resolve "quale aggiornamento ricevo?". |
app_update_resolve_rate_limit | Release | Contatori di rate-limit a finestra fissa per la edge fn di resolve. |
notification_event | Notifiche | Una notifica redatta (categoria, payload, filtro di audience). |
notification_deliveries | Notifiche | Tentativo di consegna per-utente-per-canale + stato. |
notification_state | Notifiche | Stato per-utente letto / scartato / agito per un evento. |
notification_groups | Notifiche | Coorti di targeting nominate (founders, ops, beta…). |
notification_group_members | Notifiche | Appartenenza a quelle coorti. |
notification_user_prefs | Notifiche | Toggle di opt-in per-utente per canale + categoria. |
Oltre alle 45 tabelle, 11 viste proiettano questi dati per VC, supporto e
dashboard (investor_daily_recording_kpis_vc_view, support_recording_sessions,
playroll_users_view, …). Sono elencate con le tabelle che le sostengono nella
pagina di riferimento. Le dashboard che le consumano risiedono
sotto Dashboard → Viste Supabase.