Passa al contenuto principale

Operations

Questa pagina riassume come eseguire e gestire il repo attuale del Contributor Portal.

Sviluppo Locale

Installazione ed esecuzione:

npm install
npm run dev

Il dev server di Vite usa di default:

http://localhost:5173

Ambiente browser richiesto:

VITE_SUPABASE_URL
VITE_SUPABASE_PUBLISHABLE_KEY

Ambiente locale server-only:

SUPABASE_SECRET_KEY
SUPABASE_SERVICE_ROLE_KEY
SUPABASE_ACCESS_TOKEN
CONTRIBUTOR_LINK_INTENT_SECRET
PLAYROLL_APP_SUPABASE_URL
PLAYROLL_APP_SUPABASE_SERVICE_ROLE_KEY

Non esporre chiavi server-only attraverso variabili VITE_ o codice React. Vite include nel bundle del browser tutte le variabili VITE_.

Progetto Supabase

URL Supabase attualmente documentato:

https://xlsjwlmsqonllvtyplml.supabase.co

URL Supabase correlato dell'app Playroll:

https://vtyolotvuvlbvqbgbzde.supabase.co

Allowlist auth di produzione:

Site URL:
https://playroll.extrinsiccognition.com

Redirect URLs:
https://playroll.extrinsiccognition.com/**
http://127.0.0.1:5173/**
http://localhost:5173/**

L'app usa il login email Supabase PKCE. Evita i fragment hash in emailRedirectTo; gli hash possono interferire con il parsing del callback e i token impliciti espongono valori sensibili nel fragment dell'URL.

Template Email di Auth

Supabase invia email diverse per utenti nuovi ed esistenti:

new email address -> Confirm signup
existing user -> Magic Link

Entrambi i template devono rimanere brandizzati:

supabase/email-templates/confirm-signup.html
supabase/email-templates/magic-link.html

Script di deployment:

npm run deploy:auth-email
npm run deploy:smtp

Deployment del rate-limit di auth:

npm run deploy:auth-rate-limits

Deployment dello Schema

Applica il deployment completo dello schema configurato:

npm run deploy:schema

Applica una singola migrazione:

SUPABASE_MIGRATION_FILE=supabase/migrations/<file>.sql npm run deploy:schema

L'identity link richiede migrazioni in entrambi i progetti Supabase:

# App project: playroll_supa_new / vtyolotvuvlbvqbgbzde
$env:SUPABASE_PROJECT_REF = 'vtyolotvuvlbvqbgbzde'
$env:SUPABASE_MIGRATION_FILE = 'C:\EC\playroll-cpp\supabase\migrations\20260511160000_add_contributor_status_projection.sql'
npm run deploy:schema

# Portal project: playroll_contributor_portal / xlsjwlmsqonllvtyplml
$env:SUPABASE_PROJECT_REF = 'xlsjwlmsqonllvtyplml'
$env:SUPABASE_MIGRATION_FILE = 'supabase/migrations/20260511161000_add_contributor_app_links.sql'
npm run deploy:schema

Shortcut utili:

npm run deploy:schema:validation-payout
npm run deploy:schema:time-milestones
npm run deploy:schema:payout-receiving
npm run deploy:schema:payout-iban-validation

Cloudflare Pages

Impostazioni Pages di produzione:

Project name: playroll-contributor-portal
Production branch: main
Build command: npm run build
Build output directory: dist
Custom domain: playroll.extrinsiccognition.com

Prima creazione del progetto:

npm run pages:create

Deploy:

npm run deploy:pages

npm run deploy:pages esegue prima la build, poi lancia il deploy di Wrangler Pages.

Edge Function

Deploy del creatore di intent lato app da C:\EC\playroll-cpp:

npx -y supabase@latest functions deploy create-contributor-link-intent \
--project-ref vtyolotvuvlbvqbgbzde \
--no-verify-jwt

Deploy dell'attivatore lato portale da C:\EC\playroll-contributor-portal:

npx -y supabase@latest functions deploy activate-contributor-app-link \
--project-ref xlsjwlmsqonllvtyplml \
--no-verify-jwt

Secret richiesti dalle function del progetto app:

CONTRIBUTOR_LINK_INTENT_SECRET
CONTRIBUTOR_PORTAL_URL

Secret richiesti dalle function del progetto portale:

CONTRIBUTOR_LINK_INTENT_SECRET
PLAYROLL_APP_SUPABASE_URL
PLAYROLL_APP_SUPABASE_SERVICE_ROLE_KEY

CONTRIBUTOR_LINK_INTENT_SECRET deve essere identico in entrambi i progetti. Conserva questi valori nei secret di progetto Supabase o in file di ambiente locali/server ignorati. Non committarli mai.

Preflight di Produzione

Prima di esporre il portale al pubblico:

  • npm run build ha successo.
  • Cloudflare Pages ha solo variabili d'ambiente browser-safe.
  • Le Site URL e Redirect URL di auth Supabase includono URL di produzione e dev locale.
  • I template di confirm signup e magic-link sono entrambi personalizzati.
  • Le pagine pubbliche di privacy/legali risolvono sotto /legal/.
  • La public application resta aperta; non limitarla agli utenti EC-domain.
  • Le admin/review surface, se aggiunte in futuro, sono separate e ristrette all'EC-domain.
  • Le migrazioni di schema sono applicate nell'ordine atteso.
  • Le policy RLS richiedono ancora righe authenticated proprie per scritture/letture del contributor.
  • La validazione IBAN SEPA esiste sia nel browser sia nel database.
  • Le email di conferma del receiving-method tornano con payout_confirm_token=<single-use 64-char hex token>; il portale consuma il token tramite la RPC SECURITY DEFINER confirm_payout_receiving_method_with_token. Il flag nudo payout_confirm=1 non è più accettato (audit 2026-05-16, EC-231 M1).
  • Gli app identity link possono essere creati soltanto attraverso intent firmato e gate di attivazione del portale.
  • create-contributor-link-intent e activate-contributor-app-link restituiscono request_id in caso di errore.

Controlli di Runbook

L'insert di una application deve fallire a meno che:

auth_user_id = auth.uid()
submitted email = verified Supabase email
email_verified_at is not null
status = new
source in playroll_public_page or playroll_referral_link

L'insert di onboarding deve fallire a meno che:

auth_user_id = auth.uid()
submitted email = verified Supabase email
city is a known ISTAT comune
required acceptances are true

Un receiving-method SEPA non deve diventare pagabile finché:

payout_receiving_methods.status = confirmed
payout_receiving_methods.email_confirmation_status = confirmed

I casi di manual review devono restare bloccati per il payout automatico finché un sistema ops/pagamento non approva un'alternativa supportata al di fuori di questo repo.

Le chiamate non autenticate alle function devono fallire, ma dimostrano che le function deployate sono live:

POST https://vtyolotvuvlbvqbgbzde.supabase.co/functions/v1/create-contributor-link-intent
-> 401 missing_authorization with request_id

POST https://xlsjwlmsqonllvtyplml.supabase.co/functions/v1/activate-contributor-app-link
-> 401 missing_authorization with request_id

Il dominio custom deve rispondere 200 e servire l'ultimo bundle buildato:

GET https://playroll.extrinsiccognition.com