Crescita e Rete
Riassunto in linguaggio semplice. Questo dominio riguarda l'acquisizione attraverso i giocatori che già abbiamo. Ogni utente Playroll ha una lista di amici Steam; quegli amici sono lead. Rispecchiamo quella rete nello shadow graph, le assegniamo un punteggio e portiamo in primo piano gli amici di maggior valore non ancora reclutati nella vista headhunter. Due meccanismi più piccoli — codici invito e referral — regolano e premiano le iscrizioni effettive.
Mappa
shadow_graph — la rete di amici
Il motore di reclutamento. Ogni riga è un arco orientato da un utente
Playroll registrato (source_user_id / source_steam_id) verso uno dei suoi
amici Steam (target_steam_id) che può o meno essere già un utente Playroll.
Ogni arco è univoco su (source_user_id, target_steam_id). Il lato "target"
porta uno snapshot completo di arricchimento di quell'amico, così che la vista
headhunter possa classificarlo senza una seconda chiamata API: target_name,
target_avatar_url, target_profile_url, target_hours, target_games_owned,
target_level, target_profile_public, più due colonne di scoring —
target_tier (whale | regular | casual, default casual, assegnato da
calculate_shadow_tier) e target_yearly_value (il valore stimato del loro
reclutamento).
Il funnel di reclutamento è tracciato inline. recruitment_status è un enum
chiuso:
| Colonna | Significato |
|---|---|
recruitment_status | none (default) → invited → converted. |
invited_at | Quando li abbiamo contattati. |
converted_at | Quando l'amico è diventato un utente Playroll. |
converted_user_id | FK nullable alla riga playroll_users che sono diventati — chiude il ciclo da lead a membro. |
friend_since | Età dell'amicizia riportata da Steam (un timestamp Unix). |
Il grafo aggrega sull'utente sorgente come playroll_users.network_value,
network_whale_count e steam_friend_count — ma questo non è automatico:
viene ricalcolato dalla RPC SECURITY DEFINER update_network_stats(p_user_id)
(nessun trigger la innesca) e conta solo le righe dove
recruitment_status = 'none' (lead ancora aperti) — quindi gli amici
invitati/convertiti escono da network_value.
La vista rete-di-amici / headhunter nelle dashboard è una proiezione di
shadow_graph. Quando qualcuno chiede "chi dovremmo reclutare dopo?", la
risposta è una query su questa tabella ordinata per target_yearly_value dove
recruitment_status = 'none'.
Codici invito — gating della Fase 0
Un pool fisso di codici che regola l'accesso a playroll.gg durante le fasi a
solo invito.
invite_codes— il pool. Ognicodeappartiene a unpool(defaultphase_0), consentemax_usesriscatti (CHECKmax_uses > 0, tracciandousesnell'intervallo0..max_uses), può essere disattivato (active), opzionalmenteexpires_at, e registra chi lo ha coniato (created_by→ un utente).invite_code_consumptions— PK composita(code, user_id), così un utente può consumare un dato codice al massimo una volta. È il log dei successi: la RPCconsume_invite_codecontrollaif exists(...) return 'already'prima di inserire, quindi un successo ripetuto è impossibile e non produce mai una seconda riga. Catturaconsumed_ate il contesto di abuso (ip_hash,user_agent). Nota che il flusso di invito non registra i fallimenti da nessuna parte —consume_invite_coderestituisce semplicemente stringhe sentinella ('already','expired', …) senza scrivere.
consume_invite_code è una RPC SECURITY DEFINER: impone
auth.uid() = p_user_id (altrimenti errore 42501), normalizza il codice, prende
un lock di riga SELECT ... FOR UPDATE, controlla active/scadenza/duplicato/uses < max_uses,
poi atomicamente inserisce il consumo e incrementa invite_codes.uses sotto
quel lock.
redeem_attempt_log non fa parte del flusso di invitoNonostante la somiglianza del nome, redeem_attempt_log supporta il flusso del
codice di attivazione del contributor (edge function redeem-activation-code,
EC-227), non i codici invito. È il log del rate-limiter per quel flusso (per
app_user_id, per ip, per code_hash). È documentato con il dominio
contributor/attivazione, non qui. (app_user_id è un uuid senza vincoli — un
riferimento soft, deliberatamente non una FK.)
Modello di accesso
RLS è attivo su tutte le tabelle di crescita e sono solo service-role:
shadow_graph, invite_codes e invite_code_consumptions portano policy di
deny-anon + deny-authenticated con accesso completo per il service-role.
L'accesso utente avviene solo tramite la RPC consume_invite_code (sopra) — mai
letture dirette delle tabelle.
Referral
Il ciclo di referral vive come colonne su playroll_users anziché come
tabella propria:
referral_code— il codice condivisibile del giocatore stesso.referred_by— il codice (o utente) che lo ha portato dentro.referral_count— quante iscrizioni ha generato.
Combinato con la colonna referrer e le colonne di attribuzione utm_* (vedi
Identità e Accesso), questo è il
quadro completo di come è arrivato un dato giocatore.
Vedi anche: riferimento completo delle colonne per queste tabelle.