121 —Workflow
Een verouderde site overnemen: de overdracht-audit op één pagina
Je neemt een WordPress-site over van een ander bureau. De code oogt prima. Dan faalt het SSL stilletjes op een server die niemand noemde. Dit is de audit die wij draaien.
Het is woensdagochtend. Een founder stuurt je een Notion-document door met de titel "Overdracht: WordPress-site". Erin: een admin-wachtwoord, een SFTP-login en een Stripe-support-adres dat bounced. Je neemt de opdracht aan. Zes weken later faalt het TLS-certificaat stilletjes omdat de certbot-cron draait op een staging-server waar niemand je over heeft verteld.
Het overnemen van een legacy site van een ander bureau gaat bijna nooit mis op de code. Het gaat mis aan de randen: het registrar-account waarvan de 2FA gekoppeld is aan een telefoonnummer dat inmiddels is afgesloten, de webhook-URL die nog steeds wijst naar de relay van het vorige bureau, de premium plugin waarvan de jaarlijkse key over elf dagen verloopt. Deze post is de audit-checklist van één pagina die wij bij elke overdracht doorlopen. Print hem uit en vul hem in voordat je ook maar één bestand aanraakt.
De vijf domeinen die altijd zoek raken
Elke overdracht heeft hetzelfde holle midden. De repo ligt op tafel; de rest is een schattenjacht. De vijf categorieën hieronder dekken ruwweg 90% van wat er bij overdrachten kwijtraakt: repo's, DNS, mail, betalingen en licenties. Behandel de audit als één zitting (60 tot 90 minuten, idealiter met de vertrekkende partij aan de lijn) in plaats van een traag druppeltje over weken. Mensen vergeten dingen; agenda's verdwijnen; vertrekkende contactpersonen verlaten hun baan en reageren binnen tien dagen al niet meer.
Repo's en de deploy-chain
Begin bij de code, want dat is het makkelijkst te verifiëren. Vraag om de URL, vraag dan welke branch er daadwerkelijk wordt gedeployed. Dat is niet altijd dezelfde.
- Git-host en organisatie (GitHub, GitLab, Bitbucket, self-hosted Gitea)
- Eigendom overgedragen, of op z'n minst een permanente admin-seat op de org
- Branch-protection-rules die momenteel van kracht zijn op
mainofproduction - Deploy keys die nog vermeld staan in
~/.ssh/authorized_keysop de productiemachine - CI-secrets (Actions secrets, GitLab CI-variabelen) en wat elk daarvan precies ontsluit
- Container registry-credentials als er images in het spel zijn
Draai dit op de server voordat je de README vertrouwt:
grep -rE "ssh-(rsa|ed25519)" ~/.ssh/authorized_keys
ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourly
crontab -l
sudo crontab -l
Alles wat je niet herkent log je, je verwijdert het niet, totdat je begrijpt wat het doet. Een cron-job die je in week één hebt afgeschoten, blijkt vaak de nachtelijke database-dump.
DNS, mail en de registrar
De registrar is veruit het meest voorkomende single point of failure. Vaak is dat een andere leverancier dan de hosting (de hosting draait bij GoDaddy, de DNS bij Cloudflare, de mail bij Microsoft 365), en het account is gekoppeld aan degene die het domein in 2014 als eerste registreerde. De helft van de tijd werkt die persoon allang niet meer bij de klant.
- Registrar-login, met 2FA gemigreerd naar een apparaat dat de klant bezit
- Autoritatieve nameservers (draai
dig NSen check tegen de documentatie) - Elke gepubliceerde record: A, AAAA, CNAME, MX, TXT, CAA
- SPF, DKIM en DMARC, alle drie correct uitgelijnd
- Transactionele mailprovider (Postmark, Mailgun, SendGrid) en de API-keys
- Mailbox-wachtwoorden of app-wachtwoorden voor elk adres waar de site vanaf verstuurt
Een vlugge reeks dig-probes vertelt je of de gepubliceerde DNS overeenkomt met de gedocumenteerde intentie:
dig +short MX example.com
dig +short TXT example.com | grep -i spf
dig +short TXT _dmarc.example.com
dig +short TXT default._domainkey.example.com
Als v=spf1 een relay bevat waar je nog nooit van hebt gehoord, vraag dan wie er namens het domein mail verstuurt voordat je het eruit haalt. Agenda-uitnodigingen, password resets en Stripe-bonnetjes lopen vaak via forwarders die het vertrekkende team is vergeten te noemen. De SPF RFC is de referentietekst als je een wijziging moet verdedigen tegenover een verwarde klant.
Betalingen en het webhook-kerkhof
Dit is de sectie waarin de achtergebleven infrastructuur van het vorige bureau de nieuwe klant stilletjes blijft factureren. Webhook-endpoints blijven actief. Connected Stripe-accounts blijven actief. Soms loopt een refund-flow nog steeds via een AWS Lambda die de CTO van het vertrekkende team op een zaterdag in 2021 schreef.
- Eigendom van Stripe, PayPal, Mollie of Adyen overgezet op de juridische entiteit van de klant
- Live en test API-keys geroteerd op de dag van overdracht, niet de ochtend erna
- Elke webhook-endpoint-URL nagelopen, en de host bevestigd
- Stripe Connect connected accounts gereviewd, als het een marktplaats is
- BTW-nummers, fiscale registraties en KYB-documenten op naam van de juiste entiteit
Licentiesleutels en stille verloopdata
Elke verouderde CMS-site draagt een jas van premium plugins, en de meeste van die plugins bellen thuis naar een licentieserver. Verloopt de licentie, dan stoppen de updates. Stoppen de updates, dan stoppen de security-patches. Zes maanden later zit je op een CVE die je niet kunt patchen omdat het bureau dat de seat heeft gekocht is verdwenen en de verleng-pas op naam staat van een ex-medewerker.
- WordPress: ACF Pro, Gravity Forms, WP Rocket, Yoast Premium, WPML
- Drupal: Acquia-abonnementen, betaalde distributies, commerciële modules
- Magento / Adobe Commerce: marketplace-extensions, het Adobe ID, de MAGE keys
- CDN: betaalde Cloudflare-features, Bunny, Fastly
- Monitoring: Sentry, Datadog, Better Stack
- Back-ups: BlogVault, ManageWP, Jetpack VaultPress
Voor elk: vier kolommen. Wie is eigenaar van de seat, op welk e-mailadres staat hij geregistreerd, wanneer wordt hij verlengd, en hoe wordt de verlenging betaald. Opgeslagen creditcards horen vaak bij het bureau, niet bij de klant. Plan de omschakeling vóór de auto-renew afgaat.
Het overzicht op één pagina
Het hele punt van de audit is dat hij op één pagina past. Alles wat langer is wordt gescand; alles wat korter is mist een kolom. Het formaat dat wij gebruiken ziet er ongeveer zo uit:
repos:
host: github.com/clientorg
admin_transferred: yes
ci_secrets_rotated: 2026-06-11
dns:
registrar: gandi.net
registrar_2fa: yubikey-A
nameservers: cloudflare
mail:
mx: google workspace
spf: ok
dkim: rotated 2026-06-11
transactional: postmark (key rotated)
payments:
processor: stripe
webhooks_audited: yes
account_owner: client
licenses:
acf_pro: client@example.com, renews 2027-02
gravity_forms: client@example.com, renews 2027-04
wp_rocket: client@example.com, renews 2026-09
Drie kolommen per regel: wat het is, wie er nu eigenaar van is, wanneer er weer aandacht naartoe moet. Alles wat de audit niet doorstaat gaat op een remediation-lijst met een deadline. Alles wat groen is krijgt een datum.
Wanneer de audit faalt
Je zult gaten vinden. Het vorige bureau beantwoordt je mails over een Cloudflare-account niet. De Stripe-webhook wijst nog steeds naar old-agency.com/relay. De MX-record vermeldt een mailprovider die niemand bij de klant herkent. Behandel deze als bugs met severity-labels:
- P0 (vandaag doen): live betalingsstromen die langs een onbekend endpoint lopen
- P1 (deze week): verlopende TLS-certificaten, mail-authenticatie die faalt
- P2 (deze maand): premium plugin-licenties zonder eigenaar
- P3 (volgend kwartaal): opruimen van ongebruikte CI-secrets en slapende cron-jobs
Het doel van severity-labels is niet om er georganiseerd uit te zien op een Linear-board. Het is om de klant de prijs van een overname helder voor ogen te krijgen: dit is wat er gebeurt als een site zonder checklist van bureau wisselt. Het werk heeft een naam en een prijs.
Live wijzigen terwijl je audit draait
De audit creëert een paradox. Je weet nog niet helemaal hoe de deploy-chain eruitziet, maar de klant wil tegen vrijdag een tekstwijziging op de homepage. Pushen naar een repo die je nog niet volledig in kaart hebt is de snelste manier om iets subtiels te slopen: een cache key, een feature flag, een CDN-purge-hook.
Toen we Pier bouwden liepen we tegen precies dit ding aan bij vrijwel elke klant die we aansloten. Wat er uitkwam was dat elke save standaard versioned is, zodat het ergste scenario tijdens een half-in-kaart-gebrachte overdracht één klik op version history terug naar een werkende staat is. De MySQL editor gedraagt zich net zo: elke UPDATE is een regel in een journaal, geen destructieve actie.
Het kleinste wat je vandaag kunt doen: open een leeg tekstbestand, schrijf de vijf kopjes op (repos, dns, mail, payments, licenses), en stuur het naar je klant als het overdracht-sjabloon dat jullie samen gaan invullen. De rest van de audit volgt vanzelf zodra die pagina op tafel ligt.
— Vragen —
Wat als het vorige bureau weigert het registrar-account over te dragen?
Documenteer de weigering schriftelijk en start dan een ICANN transfer-out op basis van de autoriteit van de klant als geregistreerde houder. Reken op 5 tot 7 dagen en een korte downtime op e-mail.
Hoe roteer ik Stripe-webhooks zonder live betalingen te breken?
Voeg het nieuwe endpoint toe naast het oude, controleer dat het een test-event ontvangt, kijk 24 uur lang naar live verkeer op beide, en zet daarna pas het oude endpoint uit. Nooit verwijderen; uitschakelen, zodat je kunt terugrollen.
Welke premium plugin-licenties hebben de hoogste prioriteit bij een WordPress-overname?
Alles dat authenticatie, betalingen of formulieren raakt: WPML, Gravity Forms, WooCommerce-extensies en ACF Pro. Die breken de site luid en duidelijk zodra updates stilvallen.