Supabase koppelen: echte database en echte login

Dit is fase 2. Alle code staat klaar en is lokaal getest op PostgreSQL (zie STATUS.md). Wat nog ontbreekt is een Supabase-project van jezelf. Dat maak je zelf aan: DV Software vraagt nooit om sleutels in een chat of in de broncode.

Kosten: het gratis plan van Supabase is genoeg om te testen (2 projecten; een gratis project pauzeert na een week zonder gebruik). Voor echte klanten: Pro, ± $25 per maand.

Stap 1 – Project aanmaken (± 5 minuten)

  1. Maak een account op https://supabase.com en kies New project.
  2. Regio: Central EU (Frankfurt) of een andere EU-regio (AVG).
  3. Bewaar het databasewachtwoord in je wachtwoordmanager.

Stap 2 – Schema uitvoeren

  1. Open in het project SQL Editor → New query.
  2. Plak de volledige inhoud van supabase/migrations/0001_init.sql en klik Run.
  3. Controleer onder Table Editor dat de tabellen er staan (tenants, app_users, pages, …), en onder Authentication → Policies dat RLS overal aan staat.

Stap 3 – Login instellen

In Authentication:

  • Sign In / Providers → Email: aan. Zet Allow new users to sign up uit: alleen mensen die jij (of een klant-eigenaar) uitnodigt krijgen een account.
  • URL Configuration: Site URL = het adres van het platform (lokaal http://localhost:3000); voeg bij Redirect URLs toe: http://localhost:3000/auth/confirm (en later je echte domein, bijv. https://app.dvsoftware.nl/auth/confirm). Handigst is een jokerteken: http://localhost:3000/**, zodat ook links met extra gegevens (?next=…) passen.
  • E-mail: de ingebouwde e-mail van Supabase is alleen bedoeld om te testen en heeft een lage limiet. Koppel voor echt gebruik je Resend-account via SMTP Settings.

Stap 4 – Sleutels in .env.local

Kopieer .env.example naar .env.local en vul in (niets hiervan in een chat plakken):

Variabele Waar te vinden
DATA_BACKEND=postgres –
DATABASE_URL Knop Connect → Transaction pooler (poort 6543), met je databasewachtwoord
AUTH_MODE=supabase –
SUPABASE_URL Project Settings → API: Project URL
SUPABASE_PUBLISHABLE_KEY Project Settings → API Keys: publishable key (of de oude anon key)
SUPABASE_SECRET_KEY idem: secret key (of de oude service_role key). Geeft volledige toegang: nooit delen
APP_URL http://localhost:3000 (lokaal) of je echte adres
SESSION_SECRET zie .env.example
DATABASE_SSL_CA Project Settings → Database → SSL Configuration → Download certificate; zet het bestand als certs/supabase-ca.crt in de projectmap. Zet daar ook Enforce SSL aan

Controleer daarna alles in één keer (er worden geen sleutels getoond):

npm run check:supabase

Stap 5 – Jezelf platformbeheerder maken

Snelste manier (stuurt een uitnodiging en koppelt het account):

npm run admin:create -- jij@jouwdomein.nl "Jouw Naam"

Of handmatig:

  1. Authentication → Users → Add user → Send invitation met je eigen e-mailadres. Kopieer daarna de User UID van die gebruiker.
  2. Voer in de SQL Editor uit (vul je UID, naam en e-mail in):
insert into public.app_users (id, tenant_id, data) values (
  '<USER UID>', null,
  jsonb_build_object('name', 'Jouw naam', 'email', 'jij@jouwdomein.nl',
    'role', 'platform_admin', 'active', true, 'lastActive', now())
);
  1. Open de link uit de uitnodigingsmail, stel een wachtwoord in en je komt in Platformbeheer. Daar maak je klanten aan; de eigenaar van elke klant krijgt automatisch een uitnodiging per e-mail en kan daarna zelf collega's uitnodigen.

De database is dan leeg: geen demoklanten. Wil je de demodata toch in Supabase zien, gebruik dan een apart testproject. Zet daar tijdelijk AUTH_MODE leeg en klik in Platformbeheer op Demo resetten. Doe dit nooit in het project met echte klanten.

Hoe de beveiliging werkt

  • Elke actie van een ingelogde gebruiker draait in de database als rol authenticated met zijn gebruikers-id. De RLS-policies laten alleen rijen van de eigen klant zien en weigeren schrijven buiten de eigen klant.
  • Een klant kan zijn eigen pakket, functies, facturatie of AI-verbruik niet wijzigen, ook niet bij een fout in de app (databasetrigger).
  • Bezoekers van websites hebben geen databasetoegang: formulieren lopen via de server.
  • Integratietokens staan in een tabel waar geen enkele gebruiker bij kan.

Dit alles is getest met npm test (bestand tests/pg-rls.test.ts) op een echte PostgreSQL-database in het geheugen.

Wat nog niet getest is

  • Echte e-mails (uitnodiging, inloglink, wachtwoord vergeten) en het inloggen zelf.
  • Afbeeldingen uploaden staat nog op de lokale schijf; Supabase Storage is de volgende stap en nodig voordat de app op Vercel kan draaien.