No description
  • TypeScript 95.2%
  • Shell 3.5%
  • CSS 0.6%
  • JavaScript 0.5%
  • Dockerfile 0.2%
Find a file
Jesse van Mullem e712807387 fix: cPanel-knop - degradeer naar login-page-redirect, geen session-creation
UAPI Session::create_user_session bestaat niet (is een WHM API 1 call,
niet UAPI). Per-account cPanel-tokens kunnen principieel geen sessies
aanmaken - alleen WHM-tokens met reseller/root-scope kunnen dat. Voor
echte one-click is Fase 2 met reseller-token nodig (bewust niet in scope).

Nu: knop opent cPanel-login-page met username vooringevuld in nieuwe tab.
Gebruiker voert zelf wachtwoord/token in (heeft die toch al). Audit-log
behouden. createCpanelUserSession-helper uit src/lib/cpanel.ts verwijderd
(was dead code, vervangen door comment over WHM-vereiste).
2026-05-31 19:43:07 +02:00
deploy HSTS-header in de app + ML-KEM/post-quantum documentatie bij de TLS-config 2026-05-22 16:49:02 +02:00
prisma feat: CMDB - hardware/asset-management met QR-labels + factuur + afschrijving 2026-05-30 20:05:01 +02:00
public Mobile snel-scan-flow voor inkoop-bonnen (/scan) 2026-05-25 15:43:31 +02:00
scripts docs: publish-script voor v1.0.0 release-notes op Forgejo 2026-05-26 22:32:42 +02:00
src fix: cPanel-knop - degradeer naar login-page-redirect, geen session-creation 2026-05-31 19:43:07 +02:00
.dockerignore Add web-based CRM with Coolify deployment 2026-05-18 22:40:57 +02:00
.env.example feat: Mailcow-integratie - "Activeer mail" per domein (M-A + M-B + M-E) 2026-05-30 14:13:33 +02:00
.gitignore chore: CLAUDE.local.md aan gitignore - lokale AI-werkmemory 2026-05-27 08:32:07 +02:00
CHANGELOG.md fix: cPanel-knop - degradeer naar login-page-redirect, geen session-creation 2026-05-31 19:43:07 +02:00
DEPLOY.md Beveiliging & Updates: zelfservice CVE-management 2026-05-24 14:00:17 +02:00
docker-compose.override.yml Fix Coolify port conflict: expose instead of host binding 2026-05-20 13:45:28 +02:00
docker-compose.yaml fix: DATABASE_URL parametriseerbaar in docker-compose.yaml 2026-05-27 12:31:31 +02:00
docker-entrypoint.sh security: ronde 2 - prisma destructive flag prod-gated, logo magic-bytes, dockerfile audit-visible 2026-05-26 19:23:16 +02:00
Dockerfile security: ronde 2 - prisma destructive flag prod-gated, logo magic-bytes, dockerfile audit-visible 2026-05-26 19:23:16 +02:00
HANDLEIDING.md docs: HANDLEIDING.md voor eindgebruikers - alle features + technische uitleg veiligheid 2026-05-26 18:41:58 +02:00
next.config.ts security: RFC-9116 security.txt + Referrer-Policy 'same-origin' 2026-05-26 20:48:56 +02:00
package.json feat: in-CRM QR-scanner voor mobiel - geen native app nodig 2026-05-30 20:46:47 +02:00
postcss.config.mjs Add web-based CRM with Coolify deployment 2026-05-18 22:40:57 +02:00
prisma.config.ts Revert Prisma 7-pogingen — terug naar werkend Prisma 6.19 2026-05-24 15:29:50 +02:00
README.md test: smoke-test auto-deploy-webhook na Coolify-lockdown 2026-05-25 22:45:22 +02:00
tailwind.config.ts Email templates, auto reminders, dark theme, shortcuts and audit log 2026-05-20 15:01:44 +02:00
tsconfig.json Revert Prisma 7-pogingen — terug naar werkend Prisma 6.19 2026-05-24 15:29:50 +02:00

CRM Portaal

Self-hosted CRM, offerte- en factuurpakket voor kleine dienstverleners en VOFs. Eén Docker-container, één klik in Coolify, eigen domein, geen SaaS-fees, alles in je eigen database.


Inhoud

  1. Wat is dit
  2. Snel beginnen
  3. Functies
  4. Architectuur
  5. Configuratie (.env)
  6. Lokaal ontwikkelen
  7. Coolify-deploy
  8. Off-site backup & restore
  9. Beveiliging
  10. Updates & CVE-management
  11. Release Notes · volledige commit-log in CHANGELOG.md
  12. Roadmap

Wat is dit

Een werkende web-app waarin je de hele relatie met je klanten afhandelt — van eerste lead tot betaalde factuur — met digitaal ondertekende offertes en contracten (incl. multi-signer voor VOFs), automatische herinneringen, AI-OCR voor bonnetjes, DNS-beheer en off-site backups.

   Lead → Deal → Offerte (DocuSeal) → Project → Uren → Factuur → Mollie → Betaald
                          ↘ ↗                                       ↘ ↗
                Contracten · Bestanden · Wachtwoordkluis · Assets · DNS
                          ↓
                  Boekhouder-ZIP (maandelijks)  +  Off-site backup (S3, dagelijks)

Doelgroep: ZZP, kleine bureaus, IT-dienstverleners, consultancies, VOFs — iedereen die zonder Moneybird/Hubspot/Pipedrive-abonnement een net CRM & factuurpakket wil hosten.


Snel beginnen

git clone https://code.vanmullemholding.eu/jesse-a/OpenCRM.git crm
cd crm
cp .env.example .env       # vul minimaal AUTH_SECRET en DATABASE_URL in
docker compose up --build  # bouwt + start app + postgres

Open http://localhost:3000. Bij eerste start maakt de container automatisch een ADMIN-account aan met SEED_ADMIN_EMAIL / SEED_ADMIN_PASSWORD. Laat SEED_ADMIN_PASSWORD leeg en de container genereert bij eerste boot een sterk willekeurig wachtwoord dat éénmalig in de Coolify-logs verschijnt — veiliger dan een hardcoded default.


Functies

🎯 Sales & klantbeheer

  • Klanten met contactpersonen, tags, notities, bijlagen, BTW- en KVK-nummer, status (lead/actief/inactief).
  • KVK-lookup bij aanmaken & bewerken: zoek op bedrijfsnaam in het Handelsregister, klik op een resultaat en naam, adres, postcode, plaats en KVK-nummer worden automatisch ingevuld. Twee providers: officiële KVK Zoeken-API of overheid.io OpenKVK (schakel via KVK_PROVIDER).
  • Pijplijn met Kanban-bord (LEAD → QUALIFIED → PROPOSAL → NEGOTIATION → WON/LOST). Sleep deals tussen kolommen.
  • AI-klantsamenvatting in één klik (Claude analyseert geschiedenis, projecten, openstaande facturen, recente activiteit).
  • Asset & licentie-tracking per klant: hardware, software-licenties, domeinen, hosting, certificaten, abonnementen — incl. verloopdatums voor verlengingsherinneringen.
  • Wachtwoordkluis per klant: AES-256-GCM versleutelde credentials (logins, FTP, hosting-paneel). Reveal wordt audit-gelogd inclusief IP en browser; gebruiker krijgt een waarschuwing vóór tonen.
  • NPS-enquête met publieke link per klant; score & toelichting zichtbaar op klantkaart.

📋 Offertes

  • Offertes met regels (omschrijving / aantal / prijs), BTW, valuta, geldigheid, opmerkingen, en optionele projectkoppeling.
  • Productcatalogus — voorgedefinieerde diensten en prijzen die je met één klik aan een offerte toevoegt.
  • AI-offertegenerator: typ “Nieuwe website met blog, ~40 uur design + 60u development” en Claude vult de regels (incl. prijzen uit je catalogus) voor.
  • Versies: maak een nieuwe versie van een afgewezen offerte; alle versies blijven gekoppeld en zichtbaar.
  • PDF met logo, VAN/AAN-kolommen, totalen-blok, opmerkingen-sectie. Apart facturatie-e-mailadres (facturen@…) op de header.
  • Publieke akkoord-link (/q/<token>) voor klanten zonder login — naam invullen, klikken op “Accorderen”, klaar.
  • DocuSeal-integratie met multi-signer-flow voor VOFs:
    • Offertes ≤ €5.000 ex BTW: jij + klant tekenen.
    • Offertes > €5.000 ex BTW: álle vennoten (gemarkeerd als isSigner) plus klant tekenen. Configurabel via constante in src/lib/vof-signers.ts.
    • Sender komt automatisch eerst in de submitter-lijst (DocuSeal mailt op array-volgorde).
    • Webhook vangt status-updates op (completed, declined, expired).
    • "Wachten op handtekening van X, Y + klant" tonen in de UI op basis van live ClouDNS-snapshot.
  • Auto-factuur: zodra een offerte volledig is ondertekend wordt automatisch de bijbehorende factuur opgesteld, een Mollie-betaallink aangemaakt en de mail naar de klant verstuurd.

📃 Contracten

  • Contractbeheer voor SLA, raamovereenkomst, algemene voorwaarden, NDA, licentie, verwerkersovereenkomst en overige.
  • AI-contractgenerator: kies type, vul titel + extra instructies in, en Claude schrijft het volledige contract met genummerde artikelen.
    • Gebruikt expliciete vertegenwoordigers uit User.isSigner-vlag ("te dezen rechtsgeldig vertegenwoordigd door J. van Mullem en G.A. van Mullem") in plaats van een AI-gegokte naam.
    • Strikte taalregels in de prompt voorkomen verzonnen Nederlandse vertalingen (geen "neertijd" meer voor downtime).
  • DocuSeal-ondertekening — altijd multi-signer voor contracten: alle isSigner-users + klant. Ondertekenblok schaalt automatisch (2 partijen in 1 rij, 3-4 in 2×2-grid, 5+ over meerdere pagina's).
  • Looptijd-tracking met startdatum, einddatum, opzegtermijn, contractwaarde, automatische verlenging.

💰 Facturen

  • Facturen met regels, BTW, valuta, vervaldatum, opmerkingen.
  • Multi-currency: EUR, USD, GBP, CHF, NOK, SEK, DKK met wisselkoers naar EUR voor rapportages.
  • PDF met logo, VAN/AAN-kolommen, betaalsectie en QR-code. Aparte facturen@…-adres in header en QR-footer.
  • Mollie-checkout-QR op de PDF: klant scant met telefoon-camera → browser opent Mollie → kiest iDEAL → betaalt. Werkt op alle Nederlandse banken, inclusief ABN AMRO en Rabobank.
  • E-mail verzenden met aanpasbare templates ({{customer}}, {{amount}}, {{dueDate}}, …).
  • Mollie-payment-webhook zet factuur automatisch op PAID en logt de ontvangstdatum.
  • Automatische herinneringen via cronjob: vriendelijke nudge, 2e herinnering, mogelijkheid tot ingebrekestelling-template.
  • Abonnementen / terugkerende facturen (week, maand, kwartaal, jaar) met automatische dagelijkse run en mail naar klant.
  • UBL-export voor PEPPOL-compatibele facturen (gebruikt billingEmail voor supplier-contact).

🧾 Boekhouding

Eigen sidebar-sectie met alle financiële items op één plek.

  • Inkopen met AI-OCR. Sleep één bonnetje of een hele batch tegelijk — Claude leest leverancier, datum, BTW-tarief, factuurnummer en bedrag uit (PDF/JPG/PNG). Categorie wordt automatisch geraden.
  • Bulk-upload: selecteer meerdere bonnen tegelijk, één bron en project voor de hele batch.
  • 📷 Mobile snel-scan-flow (/scan): één tap op de telefoon → achter-camera → preview → AI-OCR → klaar voor fiat. Bereikbaar via:
    • Banner op het dashboard (alleen op mobiele schermen)
    • PWA-shortcut "Scan bon" via long-press op de homescreen-icoon
  • Goedkeuringsworkflow voor inkopen (specifiek voor VOFs):
    • Mail naar alle fiatteurs zodra een nieuwe inkoop is aangemaakt.
    • Magic-link in de mail — fiatteur klikt, ziet de bon, keurt goed of af zonder in te loggen. JWT-token gebonden aan expenseId × approverId, 7 dagen geldig, single-use met DB-record.
    • Status wordt pas APPROVED als élke fiatteur heeft goedgekeurd. Eén afkeuring zet 'm op REJECTED.
    • Bevestigingsmail naar uploader + alle fiatteurs zodra volledige goedkeuring rond is.
    • Knop "Stuur mail opnieuw" in de detail-weergave.
  • Externe verkoopfacturen — facturen die elders zijn opgesteld (Moneybird, Exact, papier). Upload één of meerdere PDFs tegelijk; AI vult factuurnummer, klant, datum, bedragen en BTW automatisch in. Gaan mee in de boekhouder-ZIP zodat alles op één plek samenkomt.
  • Reis-registratie met auto-afstand-calculatie + factuurprijs per km. Doorbelaste ritten verschijnen op de factuur.
  • Boekhouder-ZIP per maand met:
    • samenvatting.txt met totalen en balans (verkoop inkoop)
    • inkopen-YYYY-MM.csv met alle inkopen
    • verkoopfacturen-YYYY-MM.csv met CRM-facturen + externe facturen (kolom bron)
    • ritten-YYYY-MM.csv met alle reisbewegingen
    • bonnetjes/ met originele PDFs van bonnen
    • verkoopfacturen/ met PDFs van alle verkoopfacturen (CRM + extern)
  • Automatisch mailen naar boekhouder met de maand-ZIP als bijlage — e-mail uit Instellingen.
  • Bankafschrift-import (CSV) met automatische match op IBAN, bedrag en factuurnummer. Ongekoppelde transacties worden gemarkeerd voor handmatige behandeling.
  • BTW-aangifte-rapport per kwartaal met te declareren BTW per tarief.

🌐 DNS Beheer

ADMIN-only sidebar-item om domeinnamen aan klanten te koppelen en hun DNS-records rechtstreeks vanuit het CRM te beheren.

  • Live ClouDNS-API: records leven bij ClouDNS, worden bij elke page-load opgehaald (geen DB-sync, geen drift).
  • Ondersteunt A, AAAA, CNAME, MX, TXT, NS met TTL-presets (60s tot 1 dag).
  • Inline edit-forms per record. Mutaties worden audit-gelogd (dns-record-add / dns-record-update / dns-record-delete).
  • Optionele verloopdatum + notitie per domein (handmatig — geen RDAP/WHOIS-koppeling).
  • Op klant-detail-pagina verschijnt een Domeinen-kaart met deeplink naar de DNS-editor.

🏗️ Projecten & uren

  • Projecten gekoppeld aan klanten, met status (PLANNED, ACTIVE, ON_HOLD, COMPLETED, CANCELLED).
  • Tijdregistratie per project, met live timer-widget rechtsboven.
  • Algemene uren (zonder project) ook ondersteund.
  • Doorbelaste uren komen op de factuur.
  • Projectrentabiliteit per project: uren × uurkostprijs vs gefactureerd vs inkopen → marge.
  • iCal-feed per gebruiker zodat afspraken / deadlines in je eigen agenda komen.

📊 Rapportages

  • Maandomzet (12 maanden) en gewonnen deals.
  • Top-klanten op omzet.
  • Uren per medewerker (laatste 30 dagen) + declarabele %.
  • Cashflow-forecast 8 weken vooruit op basis van openstaande facturen en abonnementsruns.
  • Projectrentabiliteit top-10 op marge.

🎨 Productiviteit

  • Cmd+K globale zoekbalk (klanten, projecten, deals, facturen, offertes).
  • Keyboard shortcuts: g + letter om te navigeren, n + letter voor nieuw item, ? voor help.
  • Donker thema met persistente keuze.
  • PWA: installeer als app op telefoon of desktop, met homescreen- shortcuts ("Scan bon", "Uren", "Facturen", "Inkopen", "Dashboard").
  • Audit-log van alle wijzigingen (wie, wat, wanneer) — alleen voor ADMIN.

🤖 AI

Alle AI-functies optioneel; werkt met ANTHROPIC_API_KEY en gebruikt Claude.

  • AI-OCR voor inkoopbonnetjes (PDF + foto) → leverancier, datum, BTW, bedrag, categorie.
  • AI-OCR voor externe verkoopfacturen → factuurnummer, klant, datum, bedragen.
  • AI-offertegenerator op basis van vrije tekst + catalogus.
  • AI-contractgenerator per type (SLA, AV, NDA, …) met expliciete vennoten als vertegenwoordigers.
  • AI-klantsamenvatting per klant.

🔐 Security & admin

  • 2FA / TOTP verplicht voor iedere gebruiker (Authenticator-app + recovery-codes). Geen 2FA = geen toegang tot het CRM (behalve /account om 'm aan te zetten).
  • Actieve sessies-beheer: zie al je ingelogde apparaten (browser, IP, tijdstip, "dit apparaat"-markering), trek ze los of in één klik "overal anders uitloggen".
  • Login-melding bij nieuw apparaat: stabiele device-cookie identificeert bekende browsers; vanaf onbekend apparaat krijg je direct een beveiligingsmail.
  • Rollen + extra vlaggen:
    • ADMIN (alles), MANAGER (schrijven), VIEWER (alleen lezen)
    • isApprover = fiatteur voor inkopen
    • isSigner = ondertekenaar voor multi-signer-flow (contracten + offertes > €5K) — los van fiatteur instelbaar
  • Audit-log van alle write-acties (incl. IP en User-Agent).
  • HTTPS via Coolify reverse-proxy.
  • TLS-hardening: zwakke CBC-ciphers verwijderd, HSTS, post-quantum key exchange (X25519MLKEM768). Configuratie in deploy/traefik-tls-hardening.yaml.
  • CSP/COOP/CORP/Permissions-Policy headers in next.config.ts.
  • Step-up authenticatie voor gevoelige acties: 2FA-disable, TOTP-enrollment, e-mail-wijziging — vereist je huidige wachtwoord met rate-limit per account.
  • Weak-password-blocklist + zxcvbn-achtige checks bij wachtwoord instellen of resetten.
  • DocuSeal-webhook: HMAC-handtekening gevalideerd (5-min freshness tegen replay), ondersteunt hex/base64/timestamp.sig encoding.
  • Mollie-webhook bindt aan stored mollieId (cross-tenant misbruik uitgesloten).
  • Cron-endpoints alleen POST + Authorization: Bearer $CRON_SECRET, timing-safe vergelijking.
  • Security-alert mails bij wachtwoord-reset, 2FA-disable, e-mail- wijziging — gaat naar de eigenaar van het account, niet de actor.

Architectuur

┌───────────────────────────────────────────────────────┐
│ Next.js 16 (App Router, server actions, Turbopack)    │
│  ├─ /app          UI + server actions                 │
│  ├─ /api          REST + webhooks                     │
│  └─ /middleware   Sessie-validatie + public prefixes  │
├───────────────────────────────────────────────────────┤
│ Prisma 6 ORM     →  PostgreSQL 17                     │
│ pdf-lib           →  Facturen, offertes, contracten   │
│ Anthropic SDK     →  Claude AI (OCR + generators)     │
│ Mollie SDK        →  Online betalen (iDEAL etc.)      │
│ nodemailer (SMTP) →  Mail-verzending                  │
│ jszip             →  Boekhouder-ZIP                   │
│ tar + @aws-sdk    →  Off-site backups naar S3         │
│ jose 6 (JWT)      →  Sessions + magic-link tokens     │
│ bcryptjs 3        →  Wachtwoorden                     │
│ otpauth + qrcode  →  TOTP / 2FA                       │
│ DocuSeal API      →  Digitaal ondertekenen            │
│ ClouDNS API       →  DNS-beheer                       │
│ KVK / overheid.io →  Handelsregister-lookup           │
└───────────────────────────────────────────────────────┘
                          │
                          ▼
        ┌─────────────────────────────────────┐
        │ Docker container (Node 24-alpine)    │
        │ docker-entrypoint.sh:                │
        │  1. prisma db push --accept-data-loss│
        │  2. ensure-admin (eenmalig)          │
        │  3. start Next.js (port 3000)        │
        └─────────────────────────────────────┘
                          │
                          ▼
        ┌─────────────────────────────────────┐
        │ Coolify (Traefik + HTTPS + HSTS)     │
        └─────────────────────────────────────┘
                          │
                          ▼  (dagelijks)
        ┌─────────────────────────────────────┐
        │ S3-compatible bucket (DO Spaces,     │
        │ Backblaze B2, Cloudflare R2)         │
        │   - db/crm-<timestamp>.sql.gz        │
        │   - files/uploads-<timestamp>.tar.gz │
        └─────────────────────────────────────┘

Volumes (Docker):

  • /app/data/uploads — alle geuploade bestanden (bonnen, logo, contract-PDFs).
  • PostgreSQL data-volume.

Configuratie (.env)

Minimaal nodig om te starten:

DATABASE_URL="postgresql://user:pass@db:5432/crm"
AUTH_SECRET="genereer-een-string-van-minimaal-32-chars"
APP_URL="https://crm.jouwdomein.nl"
SEED_ADMIN_EMAIL="jij@bedrijf.nl"
SEED_ADMIN_PASSWORD=""           # leeg = container genereert sterk willekeurig wachtwoord
COMPANY_NAME="Jouw Bedrijf"

Optionele blokken (alles wat leeg is, schakelt die feature uit):

# SMTP (onmisbaar voor goedkeurings-mails en factuur-mails)
SMTP_HOST="smtp.eu.mailgun.org"
SMTP_PORT="587"
SMTP_USER="postmaster@…"
SMTP_PASS="…"
MAIL_FROM="CRM <crm@jouwdomein.nl>"
SMTP_SECURE="false"

# Bedrijf — voor PDF-headers en betalingsinstructie
COMPANY_ADDRESS="Vestigingadres 1, 1234 AB Stad"
COMPANY_VAT="NL000000000B00"
COMPANY_IBAN="NL00BANK0000000000"
COMPANY_EMAIL="support@bedrijf.nl"          # algemeen contact (contract-PDF, user-mail-footer)
COMPANY_BILLING_EMAIL="facturen@bedrijf.nl" # facturatie (factuur-PDF, offerte-PDF, UBL)

# Anthropic Claude — AI-OCR + generators
ANTHROPIC_API_KEY="sk-ant-…"
ANTHROPIC_MODEL="claude-sonnet-4-6"

# Mollie — online betalen
MOLLIE_API_KEY="live_… of test_…"

# DocuSeal — digitaal ondertekenen
DOCUSEAL_URL="https://ondertekenen.jouwdomein.nl"
DOCUSEAL_API_KEY="…"
DOCUSEAL_WEBHOOK_SECRET="HMAC-secret-uit-DocuSeal-instellingen"

# ClouDNS — DNS-beheer (auth via account-level)
CLOUDNS_AUTH_ID="12345"
CLOUDNS_AUTH_PASSWORD="…"

# KVK / overheid.io — handelsregister-lookup
KVK_PROVIDER="kvk"           # of "overheid"
KVK_API_KEY=""
KVK_TEST_API_KEY=""          # KVK-sandbox
OVERHEID_API_KEY=""

# Off-site backup (S3-compatibel — DO Spaces, B2, R2, AWS)
S3_BACKUP_ENDPOINT="https://ams3.digitaloceanspaces.com"
S3_BACKUP_BUCKET="mijn-crm-backups"
S3_BACKUP_ACCESS_KEY="…"
S3_BACKUP_SECRET_KEY="…"
S3_BACKUP_REGION="us-east-1"    # DO Spaces negeert dit, AWS niet
S3_BACKUP_PREFIX="crm/"          # optioneel

# Cron-token (beveiligt /api/cron/*)
CRON_SECRET="openssl rand -hex 32 → plak hier"

Lokaal ontwikkelen

# Node 24 + npm
nvm use 24
npm install
docker compose up -d db        # alleen PostgreSQL starten
npm run dev                    # Next.js dev-server op :3000

Database-wijzigingen:

npx prisma db push             # past schema toe (bij dev, no-migration)
npx prisma studio              # browse data

Aanpassen seed-data: prisma/seed.tsnpx prisma db seed.


Coolify-deploy

  1. Coolify → New Resource → Docker Compose.
  2. Verwijs naar deze repo (docker-compose.yaml).
  3. Vul de env-variabelen in (zie boven).
  4. Domeinnaam koppelen → Coolify regelt HTTPS via Traefik.
  5. Persistent volume voor /app/data.
  6. Volg DEPLOY.md voor de uitgebreide stap-voor-stap incl. TLS-hardening, post-quantum key-exchange, en off-site backup setup.

Bij elke deploy draait docker-entrypoint.sh:

  1. prisma db push --accept-data-loss (we breken nooit oudere kolommen, dus de flag is veilig om additieve wijzigingen door te zetten).
  2. node prisma/ensure-admin.mjs (eenmalig ADMIN-account aanmaken).
  3. next start (Next.js standalone build).

Scheduled tasks in Coolify (alle endpoints met header Authorization: Bearer $CRON_SECRET):

Endpoint Frequentie Wat
POST /api/cron/payment-reminders dagelijks 09:00 1e + 2e factuur-herinnering
POST /api/cron/recurring-invoices dagelijks 07:00 Abonnementsfacturen aanmaken + versturen
POST /api/cron/backup dagelijks 03:15 Off-site backup van DB + uploads naar S3
POST /api/cron/security-check dagelijks 06:00 npm audit-run, mailt ADMINs bij HIGH/CRITICAL CVEs

Off-site backup & restore

Ingebouwd. Eén klik in Instellingen → Off-site backup of cron-aanroep naar POST /api/cron/backup dumpt in één keer de PostgreSQL-database en de /app/data/uploads-map naar een S3-compatibele bucket. Streamt direct (pg_dump | gzip | S3 + tar.gz | S3), geen tussenbestand op disk.

Status (datum, OK/FAILED, samenvatting, eventueel foutbericht) is zichtbaar op de instellingen-pagina.

Restore procedure (uitgebreid in DEPLOY.md → Stap 9):

# 1) Stop de app in Coolify; DB-container blijft draaien.
# 2) Wis huidige DB-schema (alleen bij rollback / disaster recovery):
psql "$DATABASE_URL" -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"

# 3) Restore de DB:
gunzip < crm-<timestamp>.sql.gz | psql "$DATABASE_URL"

# 4) Uploads terugzetten:
sudo tar xzf uploads-<timestamp>.tar.gz \
  -C $(docker volume inspect <stack>_app_data --format '{{.Mountpoint}}')
sudo chown -R 1000:1000 .../uploads

# 5) Start de app weer in Coolify.

⚠️ Bewaar AUTH_SECRET apart in je password manager — zonder die zijn versleutelde DB-kolommen (TOTP-secrets, wachtwoordkluis) bij restore onleesbaar.


Beveiliging

  • Auth: bcryptjs (cost 12) voor wachtwoorden, JWT-sessie (7 dagen) via jose 6, HttpOnly cookies. 2FA verplicht voor iedere gebruiker.
  • Sessies-tabel met per-sessie revoke + sessionVersion-bump bij wachtwoord/role-wijzigingen.
  • Device-cookie voor nieuw-apparaat-detectie + login-melding.
  • CSRF: server actions van Next.js valideren herkomst via serverActions.allowedOrigins.
  • Step-up authenticatie met per-account rate-limit voor 2FA-disable, TOTP-enrollment en e-mail-wijziging.
  • Weak-password-blocklist + naam/e-mail-substring-check.
  • DocuSeal-webhook: HMAC-SHA256 + 5-min freshness, constant-time vergelijking.
  • Magic-link goedkeuringen: single-use ondertekende JWT met expenseId × approverId, 7 dagen TTL, DB-record voorkomt replay.
  • Mollie-webhook bindt aan stored mollieId.
  • TLS: alleen AEAD-ciphers (geen CBC); HSTS; ML-KEM post-quantum key-exchange ondersteund.
  • HTTP-headers: CSP, HSTS, X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy (camera/microphone/geolocation uit), COOP same-origin, CORP same-origin.
  • GDPR: audit-log van alle wijzigingen; export-functionaliteit voor klantgegevens.

Periodieke security-review met claude code /security-review.


Updates & CVE-management

Ingebouwde Beveiliging & Updates-pagina (/settings/updates, ADMIN-only):

  • Bij iedere deploy draait scripts/generate-security-report.mjs (in de Dockerfile) → npm audit + npm outdated → result in de image.
  • UI toont per CVE de severity, klikbare advisory-link, CVSS-score en het exacte npm install <pkg>@<safe-version>-commando om 'm te dichten.
  • "Verzamel-commando" om alle CVEs in één klik te genereren.
  • Daily cron (POST /api/cron/security-check) ververst de audit en mailt alle actieve ADMINs zodra er HIGH/CRITICAL CVEs zijn — met de fix-commando's in de mail zelf.
  • Lijst van verouderde packages (major-bumps eerst) met direct npm install <pkg>@latest-snippet per regel.

Werkstroom:

# 1) /settings/updates → kopieer verzamel-commando
npm install <pakketten>

# 2) Test lokaal:
npm run build

# 3) Push:
git commit -am "Security: dicht CVE-..." && git push

# 4) Coolify rebuildt → audit draait opnieuw → teller in UI op 0.

Volledige uitleg in DEPLOY.md → Stap 10. Voor full-automatische update-PRs is Renovate Bot (Gitea/GitLab/GitHub-compatibel) een goede aanvulling.


Release Notes

Functionele samenvatting per versie. Voor de volledige commit-by-commit historie (inclusief minors, fixes, refactors, docs en hotfixes): zie CHANGELOG.md.

Conventie voor toekomstige releases: elke commit krijgt een regel in CHANGELOG.md onder de juiste [Unreleased]-categorie (Added / Changed / Fixed / Security / Removed / Deprecated / Infra). Zodra een nieuwe vX.Y getagged wordt, schuift de [Unreleased]-sectie naar boven onder die versie en wordt een functionele samenvatting toegevoegd aan deze README.

v0.16 (2026-05-24) — DNS Beheer + Mobile scan

  • 🌐 DNS Beheer-module met live ClouDNS-API: domeinen aan klanten koppelen, records (A/AAAA/CNAME/MX/TXT/NS) inline editen, alles audit-gelogd. Sidebar-item onder Beheer.
  • 📷 Mobile snel-scan-flow (/scan): camera → AI-OCR → bon klaar. PWA-shortcut + dashboard-banner alleen op mobiel.
  • Aparte facturatie-e-mail (COMPANY_BILLING_EMAIL / CompanySettings.billingEmail): factuur-PDF, offerte-PDF, factuurmail en UBL gebruiken het apart; contracten en interne mails blijven op email/support@.
  • AI-contracten verbeterd: expliciete vennoten als vertegenwoordigers uit isSigner-vlag (geen "J. Mullem"-verzinsel meer); strikte taalregels voorkomen "neertijd" en andere onbestaande NL-vertalingen.
  • DocuSeal: sender tekent eerst: huidige sender komt vooraan in de submitter-array (was alfabetisch).

v0.15 (2026-05-24) — Multi-signer + Bump-ronde

  • Multi-signer DocuSeal-flow voor VOFs: alle vennoten (isSigner-vlag)
    • klant moeten tekenen op contracten en op offertes > €5.000 ex BTW. Signing-pagina schaalt automatisch (1-2 rij, 3-4 grid, 5+ multipagina). "Wachten op handtekening van X, Y + klant" in de UI met live snapshot.
  • Aparte "Ondertekenaar"-rol (isSigner) los van isApprover — toggle-knop op /users + uitleg-mail bij activeren.
  • Grote dependency-bump: Next 15 → 16, bcryptjs 2 → 3 (ESM), jose 5 → 6, nodemailer 6 → 8, typescript 5 → 6, @anthropic-ai/sdk 0.32 → 0.98, Node 22 → 24 LTS. Prisma blijft op 6.19 (v7-migratie staat open voor een dedicated sessie).

v0.14 (2026-05-24) — Security & ops

  • 2FA verplicht voor iedereen: zonder ingeschakelde 2FA word je naar /account doorgestuurd. Banner totdat 2FA aanstaat.
  • Actieve sessies-beheer + nieuw-apparaat-detectie: zie ingelogde apparaten op je account-pagina, trek ze los, "overal anders uitloggen"- knop. Nieuwe device-cookie + login-melding op onbekend apparaat.
  • Beveiliging & Updates-pagina (/settings/updates): npm audit-snapshot bij elke deploy, daily cron mailt admins bij HIGH/CRITICAL CVEs, met fix-commando's in de mail.
  • Off-site backup naar S3 (DigitalOcean Spaces, B2, R2, AWS) — één knop in Instellingen of POST /api/cron/backup. Streamt DB + uploads direct naar de bucket.
  • TLS-hardening: CBC-ciphers uit, HSTS, post-quantum key-exchange (X25519MLKEM768). Config in deploy/traefik-tls-hardening.yaml.
  • CSP / COOP / CORP / Permissions-Policy strenger.
  • Hardening-ronde: step-up rate-limit, weak-password-blocklist, security-alert mails, extra HTTP-headers.
  • Asset/license & wachtwoordkluis per klant (AES-256-GCM, audit-log met IP/UA bij reveal).

v0.13 (2026-05-22) — Mobile UI & UX

  • Mobiele UI rondom forms, tables en Kanban-scroll opgepoetst (alle 19 tables krijgen overflow-x-auto; Kanban-bord is swipeable met snap-x snap-mandatory).
  • Drawer-z-index-bug op mobiel opgelost (createPortal naar body).
  • Fiatteur-fallback: zelf-uploader mag eigen inkoop nu wél fiatten als hij de enige fiatteur is.

v0.12.1 (2026-05-21) — Hotfixes na security-release

  • Login redirect-loop opgelost (middleware deed optimistic redirect; pagina doet nu zelf DB-validatie).
  • Account-pagina UI bijgewerkt met wachtwoord-velden voor 2FA-disable / TOTP-enrollment / email-change (matched step-up auth uit v0.12).
  • DocuSeal-URL voorbeeld in .env.example naar ondertekenen.je-ma.com.
  • CHANGELOG.md met volledige commit-by-commit historie toegevoegd.

v0.12 (2026-05-21) — Security hardening

  • Pentest-remediatie: 14 HIGH en 15 MEDIUM bevindingen opgelost (volledig rapport in CRM-Portaal-Pentest-Rapport-v0.12.pdf).
  • Per-request DB-revalidatie van sessies + sessionVersion-mechanisme: role-changes, deactivatie en password-wijzigingen werken nu meteen door op álle apparaten.
  • TOTP-secrets versleuteld at-rest (AES-256-GCM, HKDF-key uit AUTH_SECRET).
  • Recovery-codes nu bcrypt-hashed; atomic consumption voorkomt race-reuse.
  • Step-up authenticatie (huidig wachtwoord vereist) voor 2FA-disable, TOTP-enrollment en e-mail-wijziging.
  • Approval-token (fiatteur magic-link) is nu single-use met DB-record en TTL 7 dagen i.p.v. 30; uploader kan eigen inkoop niet meer goedkeuren.
  • DocuSeal-webhook: 5-minuten freshness-check tegen replay-attacks.
  • Mollie-webhook: bindt aan stored mollieId om cross-tenant misbruik uit te sluiten.
  • Cron-endpoints: alleen POST + Authorization: Bearer, geen query-token meer.
  • CSV-export saniteert formula-injectie (= + - @ prefix).
  • Filename-sanitization tegen zip-slip in boekhouder-ZIP.
  • iCal-feed alleen eigen toegewezen taken; facturen + projecten weggehaald.
  • AUTH_SECRET minimaal 32 chars; bcrypt cost 12; wachtwoord-minimum 12; JWT-alg expliciet gepind op HS256.
  • /api/ai/* en /api/travel/quote vereisen nu MANAGER-rol.
  • Server Actions allowedOrigins expliciet gezet.

v0.11 (2026-05-21)

  • PDF-overhaul: factuur en offerte hertekend met VAN/AAN-kolommen, totalen-blok, mooie betaalsectie. Contract-handtekeningen krijgen altijd een eigen laatste pagina.
  • Betaal-QR op factuur via Mollie-checkout-link (werkt op alle banken incl. ABN AMRO en Rabobank). EPC-QR verwijderd omdat te weinig banken het ondersteunen.
  • AI-offertegenerator op /quotes/new.
  • AI-contractgenerator voor SLA / AV / NDA / verwerkersovereenkomst / raamovereenkomst / licentie met directe PDF-opslag.
  • Klantportaal verwijderd — flow paste niet bij de doelgroep (kleine bureaus); functionaliteit verschuift naar magic-link per document waar nodig.
  • Boekhouding-sectie in sidebar met hub-pagina: inkopen, externe verkoopfacturen, bank, BTW-aangifte, maandstaat.
  • Externe verkoopfacturen (model + UI): upload PDFs van Moneybird / Exact / papier, AI vult velden in, gaan mee in boekhouder-ZIP.
  • Bulk-upload voor zowel inkopen als externe verkoopfacturen met parallel AI-OCR.
  • Boekhouder-ZIP uitgebreid met verkoopfacturen (CSV + PDFs van CRM én externe).
  • Auto-mail naar fiatteurs zodra een inkoop wordt aangemaakt, met magic-link voor digitaal goedkeuren zonder login.
  • Bevestigingsmail naar uploader en fiatteurs zodra een inkoop volledig is goedgekeurd en op de inkooplijst staat.

v0.10 (2026-05-20)

  • KVK-lookup bij klant aanmaken/bewerken (KVK Zoeken-API of overheid.io OpenKVK).
  • Productcatalogus — voorgedefinieerde diensten met prijzen, één klik om op offerte / factuur te plaatsen.
  • Multi-currency op offertes en facturen (EUR, USD, GBP, CHF, NOK, SEK, DKK) met wisselkoers naar EUR.
  • Offerte-versies — nieuwe versie van afgewezen offerte, alle versies blijven gekoppeld.
  • BTW-aangifte-rapport per kwartaal.
  • Bankafschrift-import (CSV) met automatische match op IBAN, bedrag en factuurnummer.

v0.9 (2026-05-20)

  • Goedkeuringsworkflow voor inkopen (VOF: beide partners moeten tekenen).
  • Contractbeheer voor SLA, raamovereenkomst, AV, NDA, licentie, verwerkersovereenkomst.
  • DocuSeal-flow ondersteunt nu zowel offertes als contracten.
  • Tweerichtings-ondertekening: ondergetekende eerst, dan klant.
  • Automatische factuur + Mollie-link + mail zodra een offerte volledig is ondertekend.

v0.8 (2026-05-20)

  • Inkopen-module met AI-OCR (Claude vision) voor bonnetjes (PDF + foto).
  • Maand-ZIP met inkopen + bonnen, mailen naar boekhouder.
  • DocuSeal-integratie voor offertes.
  • Projectrentabiliteit en cashflow-forecast in rapportages.
  • UBL-export voor PEPPOL-compatibele facturen.
  • iCal-feed per gebruiker.
  • PWA — installeerbaar op telefoon, manifest + service worker.

v0.7 (2026-05-20)

  • E-mail templates met variabelen ({{customer}}, {{amount}}).
  • Automatische factuur-herinneringen per cronjob.
  • Donker thema met persistente switch.
  • Keyboard shortcuts (g+letter, n+letter, ? voor help).
  • Audit-log viewer voor ADMIN-rol.
  • Settings-pagina met logo-upload.

v0.6 (2026-05-20)

  • Deals pijplijn met Kanban en sleep-functie.
  • Offertes met publieke akkoord-link.
  • Facturen met e-mail + Mollie-betaallink + webhook.
  • AI-assistent voor klantsamenvattingen.
  • Live tijdregistratie met timer-widget.
  • Rapportages met grafieken.
  • Cmd+K globale zoek.
  • TOTP / 2FA voor login.
  • Bijlagen op klanten en projecten.
  • Abonnementen (terugkerende facturen).

v0.5 (2026-05-18)

  • Eerste werkende versie met klanten, projecten, taken, notities en docker-compose deploy voor Coolify.

Roadmap

Praktische, geprioriteerde verbeteringen.

Geld & boekhouding

  • 3-traps aanmaning-flow met wettelijke handelsrente.
  • iDEAL-quicklink voor losse bedragen zonder factuur.
  • Aanbetaling / termijnfacturen (50/50 of 30/40/30 split).
  • Creditfactuur-flow met gekoppelde negatieve factuur.
  • PSD2-bankkoppeling (Ponto / Tink) voor automatische transactie-import.
  • PEPPOL-versturen via Storecove.
  • Moneybird / Snelstart / e-Boekhouden API-koppeling (vervang ZIP-mail).

EU-handel

  • VIES BTW-validatie bij EU-klanten (groen/rood).
  • 0%-tarief BTW-verleggen bij geldige EU-BTW.
  • ICP-aangifte rapport per kwartaal.

Workflow / UX

  • Inbox-dashboard "Wachten op jou": openstaande te-tekenen, te-fiatten, vervalde facturen, etc. op één scherm.
  • Bulk-acties op lijsten (mass-tag, mass-mailen, mass-status).
  • Factureer ongefactureerde uren in één klik per klant of project.
  • Quick-add menu (Cmd+N → kies type → mini-form).
  • Web-push notificaties (PWA) voor contract-getekend / inkoop-fiat / betaling-binnen.

Infrastructuur

  • Prisma 7-migratie (pure TS/WASM-runtime, driver-adapter @prisma/adapter-pg).
  • Outgoing webhooks (n8n/Zapier) bij events (factuur betaald, contract getekend, klant aangemaakt).
  • Renovate Bot voor automatische dependency-PRs.

AI

  • AI-factuur-regels uit gewerkte uren (auto-omschrijvingen).
  • Smart-search via Claude (“open facturen >€2k van Bakkerij Jansen”).
  • AI-mail-antwoord-assistent met klantcontext.
  • Pijplijn-forecast met kans-op-winnen.

DNS-uitbreiding

  • DNSSEC-toggle vanuit het CRM.
  • Bulk-import van een zone-file.
  • WHOIS/RDAP-koppeling voor automatische verloopdatum-sync.

Licentie

Geen open-source licentie expliciet ingesteld. Gebruik voor eigen bedrijfsdoeleinden; voor commerciële herdistributie: vraag het even.

— gemaakt met heel veel git push origin main.