The complete public schema — every column of all 45 tables, the 11 views, and
the one enum. The domain pages explain why ; this page is the what . Use it as
a lookup.
PK = primary key · FK → = foreign key to table.column · N in the
Null column = the column is nullable. Types are the live Postgres types. This
page is generated from the database and reflects the schema as deployed; when a
migration changes a table, regenerate the affected section.
Row-level security is enabled on
all 45 tables A column being listed here does not mean a browser client can read it. Many
tables are service-role-only / deny-all (reachable only via edge functions or the
service key) — e.g. crm_user_roles, player_roles, steam_id_allowlist,
device_auth_requests, upload_credentials, all four growth tables,
lobby_join_events, permissions/role_permissions. The domain pages note the
RLS posture per area; treat the relationships here as logical, not as a read grant.
Enums
Enum Values game_storesteam · epic · gog · microsoft · other · riot · rockstar
Identity & Access
→ domain page: Identity & Access
playroll_users
The hub. Keyed by user_id (Supabase auth UUID).
Column Type Null Notes user_iduuid PK , FK → auth.users.id (ON DELETE CASCADE)display_nametext N avatar_urltext N steam_idtext N UNIQUEdiscord_idtext N UNIQUEdiscord_usernametext N contributor_tiertext Current program tier (value, not FK); default player. credits_earnednumeric credits_claimednumeric created_attimestamptz updated_attimestamptz steam_usernametext N steam_avatar_urltext N steam_hoursinteger N Steam enrichment ↓ steam_games_ownedinteger N steam_levelinteger N steam_profile_publicboolean N steam_account_createdbigint N Unix ts steam_account_age_daysinteger N Trigger-computed (playroll_users_fill_steam_age). steam_vac_bannedboolean N steam_vac_bans_countinteger N steam_game_bans_countinteger N steam_days_since_last_baninteger N steam_enriched_attimestamptz N steam_friend_countinteger steam_friends_publicboolean N friends_fetched_attimestamptz N network_valueinteger Rolled up from shadow_graph. network_whale_countinteger countrytext N Attribution ↓ languagetext N utm_sourcetext N utm_mediumtext N utm_campaigntext N referrertext N device_typetext N referral_codetext N referred_bytext N referral_countinteger priority_scoreinteger
steam_id_allowlist
Column Type Null Notes steam_idtext PK roletext FK → player_role_catalog.role; default pioneer.notetext N added_attimestamptz added_bytext N enabledboolean
auth_user_steam_lookup
Column Type Null Notes steam_idtext PK user_iduuid FK → auth.users.id; UNIQUE. Maintained by auth_user_steam_lookup_sync_trg.created_attimestamptz updated_attimestamptz
steam_openid_nonces
Column Type Null Notes noncetext PK seen_attimestamptz
player_role_catalog
Column Type Null Notes roletext PK rankinteger Higher = more access. descriptiontext N created_attimestamptz
player_roles
Column Type Null Notes iduuid PK user_iduuid FK → playroll_users.user_idroletext FK → player_role_catalog.rolegranted_attimestamptz granted_bytext N
crm_user_roles
Staff RBAC, keyed by email.
Column Type Null Notes emailtext PK roletext CHECK admin / cm / vc / sales. Links by value to role_permissions.role. granted_attimestamptz granted_bytext N notestext N
permissions
Column Type Null Notes idinteger PK resourcetext actiontext CHECK read / write. descriptiontext N created_attimestamptz
role_permissions
Column Type Null Notes roletext permission_idinteger FK → permissions.idgranted_bytext N granted_attimestamptz
device_auth_requests
Legacy / superseded — 0 rows, deny-all RLS, replaced by the steam-login redirect flow.
Column Type Null Notes device_codetext PK statustext Default pending. access_tokentext N refresh_tokentext N user_iduuid N No FK. user_profilejsonb N created_attimestamptz completed_attimestamptz N expires_attimestamptz Default now() + 10 min.
upload_credentials
Legacy / unused — 0 rows, no writer, deny-all RLS (service-key only).
Column Type Null Notes mac_hashtext PK user_idtext UNIQUE (text, not a uuid FK to playroll_users).created_attimestamptz last_used_attimestamptz N is_activeboolean
playroll_user_consents
Append-only consent log (no revoked column; withdrawals are new rows).
Column Type Null Notes iduuid PK user_iduuid FK → auth.users.id (not playroll_users).consent_typetext CHECK age_confirmation / tos / privacy / eula / edc_gameplay. versiontext accepted_attimestamptz countrytext N metadatajsonb {action:'withdrawal'} marks a revocation.ip_addressinet N user_agenttext N
contributor_status_projection
App-side projection written by redeem-activation-code. No PII. (The portal owns the source table contributor_app_links.)
Column Type Null Notes app_user_iduuid PK , FK → auth.users.id (ON DELETE CASCADE).contributor_iduuid link_statustext CHECK verified (only value). source_link_iduuid steam_idtext N linked_attimestamptz source_updated_attimestamptz last_synced_attimestamptz
Recording Spine
→ domain page: Recording Spine
recording_sessions
Keyed by a text session_id (rec-<epoch-ms>).
Column Type Null Notes session_idtext PK user_idtext game_nametext N chunk_countinteger N statustext Default uploading. client_ended_attimestamptz N server_verified_attimestamptz N created_attimestamptz N updated_attimestamptz N Trigger-maintained. detected_resolutionjsonb N game_slugtext N recording_started_attimestamptz N recording_ended_attimestamptz N duration_secondsbigint N Canonical recording clock. CHECK ≥ 0.required_artifact_modetext CHECK mp4_csv_json (default) / mp4_csv. modetext Recording lane: quest (default) / free_play (EC-475). Populated end-to-end once the upload writer carries the lane; see Recording lanes . uploadability_statustext N CHECK uploadable / blocked / NULL. block_reasontext N lobby_iduuid N By value — no FK (lobby binding enforced by trigger). hw_snapshot_iduuid N FK → device_hw_snapshots.idcore_versiontext N ui_versiontext N installer_versiontext N transcript_expectedboolean Set true at session end iff _mic.aac exists (EC-407). transcript_skippedboolean Client-writable via scoped GRANT + RLS (EC-409). dismissedboolean Client-writable "hide from Activity" (EC-411).
s3_uploads
One row per uploaded file. Links to a session by value on session_id.
Column Type Null Notes iduuid PK s3_keytext s3_buckettext Default playroll-captures. user_idtext upload_yearinteger Partition key upload_monthinteger CHECK 1–12. upload_dayinteger CHECK 1–31. session_idtext Joins to recording_sessions.session_id (value). chunk_dirtext N filenametext file_typetext mp4 / csv / json / ogg (legacy).size_bytesbigint N etagtext N uploaded_attimestamptz statustext CHECK uploaded (default) / processing / completed / failed. lobby_iduuid N FK → lobbies.id (NOT VALID).recording_started_attimestamptz N recording_ended_attimestamptz N game_slugtext N Checked by the s3_uploads_enforce_lobby_game_match trigger (lobby-tagged only). artifact_kindtext N No CHECK; derived from suffix: video/input/meta/transcript; NULL = unclassified (EC-289).
device_hw_snapshots
Dedup key (user_id, hw_fingerprint).
Column Type Null Notes iduuid PK created_attimestamptz updated_attimestamptz user_idtext hw_fingerprinttext cpu_modeltext N cpu_architecturetext N logical_processorsinteger N physical_memory_mibbigint N os_releasetext N primary_gpu_vendortext N primary_gpu_nametext N primary_gpu_drivertext N primary_gpu_driver_nvidiatext N snapshotjsonb Full HW blob. sourcetext ui_login (login edge fn, dominant) / core_meta_json (upload Lambda); default core_meta_json.
pipeline_sessions
Composite PK (session_id, environment) — one row per session per environment.
Column Type Null Notes session_idtext PK (with environment)environmenttext PK (with session_id); CHECK dev / prod (default prod).user_idtext game_slugtext N s3_prefixtext stagesmallint Default 0. statustext CHECK pending (default) / processing / verified / failed. mp4_keytext N csv_keytext N ogg_keytext N size_bytes_totalbigint N errortext N created_attimestamptz verified_attimestamptz N
pipeline_runs
Column Type Null Notes run_iduuid PK pipeline_nametext session_idtext N user_idtext N trigger_typetext Default manual. created_bytext Default prefect-ui. statustext CHECK running (default) / pass / fail / skipped. steps_executedtext[] N step_durations_sjsonb N params_usedjsonb N output_prefixtext N error_detailtext N prefect_flow_run_idtext N started_attimestamptz completed_attimestamptz N
nvenc_known_contenders
Column Type Null Notes process_nametext PK first_seentimestamptz last_seentimestamptz total_eventsbigint total_usersinteger sample_codecstext[] sample_resolutionstext[]
nvenc_contender_user_links
Column Type Null Notes process_nametext FK → nvenc_known_contenders.process_nameuser_idtext first_seentimestamptz last_seentimestamptz
bug_reports
Column Type Null Notes iduuid PK created_attimestamptz user_iduuid steam_idtext N hw_configjsonb installer_versiontext N ui_versiontext N core_versiontext N titletext CHECK length 1–200. descriptiontext CHECK length 1–10000. statustext CHECK logged (default) / in_progress / fixed / verified / wont_fix. categorytext CHECK ui / recording / performance / onboarding / other. imagestext[] linear_tickettext N Auto-filled by bug_reports_to_linear trigger (AFTER INSERT). updated_attimestamptz steam_usernametext N connectionjsonb N electron_runtimejsonb N
Lobby & Catalog
→ domain page: Lobby & Catalog
lobbies
Column Type Null Notes iduuid PK lobby_codetext creator_idtext game_slugtext FK → eligible_games.slug (ON UPDATE CASCADE / ON DELETE RESTRICT).statustext CHECK active (default) / closed / expired. max_playersinteger CHECK 2–16 (default 16). created_attimestamptz expires_attimestamptz
lobby_participants
Composite PK (lobby_id, user_id) — current membership.
Column Type Null Notes lobby_iduuid PK (with user_id); FK → lobbies.iduser_idtext PK (with lobby_id)joined_attimestamptz session_idtext N Joins to recording_sessions. server_recording_started_attimestamptz N
lobby_join_events
Append-mostly history. INSERT on join; leave UPDATEs left_at (no new row). Driven by triggers on lobby_participants.
Column Type Null Notes idbigint PK lobby_iduuid FK → lobbies.iduser_idtext joined_attimestamptz left_attimestamptz N Stamped on leave. sourcetext Default participant_insert.
eligible_games
Column Type Null Notes igdb_idinteger PK slugtext display_nametext enabledboolean N cover_urltext N created_attimestamptz N updated_attimestamptz N tokensjsonb Match tokens for library detection; NOT NULL, default {}.
game_store_ids
Column Type Null Notes iduuid PK igdb_idinteger FK → eligible_games.igdb_id (ON DELETE CASCADE).storegame_store Enum (steam/epic/gog/microsoft/riot/rockstar/other). store_idtext
game_runtime_profiles
Column Type Null Notes iduuid PK game_store_iduuid FK → game_store_ids.idexe_nametext platformtext N notestext N enginetext N FK → engine_defaults.enginesettings_overridejsonb N settings_enforcementjsonb
engine_defaults
Column Type Null Notes enginetext PK settings_specjsonb created_attimestamptz updated_attimestamptz
user_game_library
Column Type Null Notes iduuid PK user_iduuid playnite_iduuid plugin_iduuid N providertext provider_game_idtext N nametext is_installedboolean N is_hiddenboolean N is_favoriteboolean N playtime_secondsbigint N play_countbigint N last_played_attimestamptz N executablesjsonb N genresjsonb N developersjsonb N publishersjsonb N release_datetext N cover_image_urltext N platformtext N install_size_bytesbigint N game_registry_igdb_idinteger N FK → eligible_games.igdb_idsynced_attimestamptz N created_attimestamptz N updated_attimestamptz N
Growth & Network
→ domain page: Growth & Network
shadow_graph
Column Type Null Notes iduuid PK source_user_iduuid FK → playroll_users.user_idsource_steam_idtext target_steam_idtext target_nametext N target_avatar_urltext N target_profile_urltext N target_hoursinteger N target_games_ownedinteger N target_levelinteger N target_profile_publicboolean N target_tiertext CHECK whale / regular / casual (default casual). target_yearly_valueinteger Recruitment-value score. recruitment_statustext CHECK none (default) / invited / converted. invited_attimestamptz N converted_attimestamptz N converted_user_iduuid N FK → playroll_users.user_id (no cascade).friend_sincebigint N created_attimestamptz updated_attimestamptz UNIQUE edge: (source_user_id, target_steam_id).
invite_codes
Column Type Null Notes codetext PK pooltext Default phase_0. max_usesinteger CHECK > 0 (default 1). usesinteger CHECK 0 ≤ uses ≤ max_uses. activeboolean notestext N created_byuuid N FK → playroll_users.user_idcreated_attimestamptz expires_attimestamptz N
invite_code_consumptions
Composite PK (code, user_id) — a user consumes a given code at most once.
Column Type Null Notes codetext PK (with user_id); FK → invite_codes.codeuser_iduuid PK (with code); FK → playroll_users.user_idconsumed_attimestamptz ip_hashtext N user_agenttext N
redeem_attempt_log
Rate-limiter log for the contributor activation-code flow (redeem-activation-code, EC-227) — not invite codes. app_user_id is an unconstrained uuid (soft reference, no FK).
Column Type Null Notes idbigint PK app_user_iduuid No FK. iptext N code_hashtext N successboolean Default false. attimestamptz
Releases
→ domain page: Releases & Notifications
app_releases_v2
Column Type Null Notes idbigint PK release_keytext installer_versiontext core_versiontext ui_versiontext download_urltext installer_sha256text N release_notestext N metadatajsonb Default {}. created_attimestamptz release_tracktext CHECK stable / dev / test (no beta). release_notes_technicaltext N release_notes_user_facingtext N
app_rollouts_v2
Column Type Null Notes iduuid PK nametext release_idbigint FK → app_releases_v2.idenabledboolean priorityinteger tracktext force_updateboolean percentageinteger experiment_keytext N ab_buckettext N include_user_idsuuid[] exclude_user_idsuuid[] include_install_idstext[] starts_attimestamptz ends_attimestamptz N created_attimestamptz updated_attimestamptz
app_rollout_overrides_v2
Column Type Null Notes iduuid PK target_typetext target_idtext release_idbigint FK → app_releases_v2.idenabledboolean force_updateboolean reasontext N expires_attimestamptz N created_attimestamptz
app_update_resolve_audit_v1
One row per resolve call (25 columns).
Column Type Null Notes idbigint PK created_attimestamptz install_idtext N user_iduuid N request_tracktext N installed_installer_versiontext N installed_core_versiontext N installed_ui_versiontext N installed_tracktext N Source for user_current_track. track_ordertext[] assignment_sourcetext rollout / override / default assignment_tracktext N rollout_iduuid N override_iduuid N buckettext N experiment_keytext N target_release_idbigint N target_installer_versiontext N target_core_versiontext N target_ui_versiontext N update_availableboolean update_requiredboolean force_updateboolean reasontext N resolver_versiontext
app_update_resolve_rate_limit
Column Type Null Notes ip_sha256bytea PK (with window_start)window_starttimestamptz 60s-aligned window. request_countinteger last_seen_attimestamptz
Notifications
→ domain page: Releases & Notifications
notification_event
Column Type Null Notes iduuid PK categorytext typetext urgency_tiertext payloadjsonb ctajsonb N sourcetext localetext allowed_channelstext[] audience_filterjsonb Resolved by resolve_audience(). recipient_countinteger created_attimestamptz expires_attimestamptz N
notification_deliveries
Column Type Null Notes iduuid PK event_iduuid FK → notification_event.iduser_iduuid channeltext statustext error_codetext N queued_attimestamptz sent_attimestamptz N
notification_state
Column Type Null Notes event_iduuid FK → notification_event.iduser_iduuid read_attimestamptz N dismissed_attimestamptz N acted_attimestamptz N created_attimestamptz
notification_groups
Column Type Null Notes iduuid PK slugtext nametext descriptiontext N created_byuuid N created_attimestamptz
notification_group_members
Column Type Null Notes group_iduuid FK → notification_groups.iduser_iduuid added_attimestamptz added_byuuid N
notification_user_prefs
Column Type Null Notes user_iduuid PK enable_payment_and_validationboolean enable_app_update_and_termsboolean enable_catalog_and_announcementsboolean enable_soundboolean enable_emailboolean updated_attimestamptz
Views
Eleven views project the tables above for specific consumers. They are
security_invoker where they expose row-scoped data, so RLS on the underlying
tables still governs visibility.
View Backed by Purpose playroll_users_viewplayroll_users + auth.usersCanonical user read projection (profile + auth email). investor_daily_recording_kpis_vc_viewrecording_sessionsVC/investor-safe daily KPIs from canonical duration. No PII. daily_upload_statss3_uploadsDaily upload volumes. upload_summary_by_users3_uploads + playroll_usersPer-user upload summary, identity-first. player_recording_sessionsrecording_sessionsPer-player session listing. session_completion_statusrecording_sessionsCompletion/terminal-state rollup per session. complete_tripletss3_uploadsLegacy — requires mp4 + ogg + csv (no JSON term). OGG removed in EC-173 → matches only historical rows, not the modern validated set.support_recording_sessionsrecording_sessions + s3_uploadsSupport/tester session view (canonical duration + file evidence). support_recording_filess3_uploadsSupport file-level view (who uploaded each file, keys, URLs, status). support_player_upload_summaryrecording_sessions + s3_uploadsSupport player lookup summary. user_current_trackapp_update_resolve_audit_v1Per-user current release track; feeds resolve_audience() app_track filter.
The dashboards that consume these views are documented under
Dashboards → Supabase Views and the
Database → Monitoring Views page.
How this page is regenerated
This reference mirrors the live schema. To refresh it after a migration, the
shape comes from three queries against the Playroll Supabase project
(information_schema / pg_catalog): the table+column list, the foreign-key
list, and the enum list. Re-run those, diff against the tables above, and update
the affected section in the same change that ships the migration — per the
workspace rule that playroll-docs is kept in sync with schema changes.