Blog

AI heeft de database verwijderd: een herstelplan van 7 minuten

Markdown

Wat je moet doen nadat gegevens zijn verwijderd: stop de agent, leg het incident vast en gebruik git reflog, PITR, snapshots en bestandsherstel. Voorbeelden en beveiligingsmaatregelen.

Lees het volledige artikel

Belangrijkste punten

Een AI-agent heeft zojuist je database, bestanden of je volledige productieomgeving verwijderd. De eerste 7 minuten bepalen of je je gegevens terughaalt of ze voorgoed kwijtraakt. Dit draaiboek geeft je specifieke opdrachten voor elke minuut. Stop eerst de agent, leg daarna het incident vast en herstel vervolgens je gegevens. Geen paniek — volg de checklist.

Praktische informatie over werken met Ailoot vind je in de documentatie.

Wat je in de eerste minuut moet doen: STOP, raak niet in paniek

Belangrijkste punten

Stop de destructieve schrijver direct, inclusief een kindproces dat doorgaat nadat de agent stopt. Herstart niet en beëindig geen ongerelateerde processen die verwijderde bestanden open kunnen houden. Herstelbaarheid is niet gegarandeerd: overschrijven en SSD-discard/TRIM kunnen herstel onmogelijk maken. Bewaar bewijs en overlevende gegevens op een apart gecontroleerd apparaat voordat je de beschadigde kopie wijzigt.

Als dit jou overkomt, is het eerste wat je moet doen de agent stoppen. Probeer zijn acties niet zelf ongedaan te maken, zeg niet dat hij “alles moet herstellen” en voer geen nieuwe prompts uit. Elke volgende actie van de agent kan de schijfblokken overschrijven waar je gegevens mogelijk nog staan.

  1. Sluit de terminal van de agent

    Onderbreek de gevaarlijke opdracht onmiddellijk met Ctrl+C; wacht niet tot verwijderen klaar is. De agent stoppen stopt niet noodzakelijk kindopdrachten, externe taken of databasequery’s. Identificeer de echte schrijver en stop of annuleer die actie; escaleer beëindiging als gegevensvernietiging doorgaat. Houd ongerelateerde processen met mogelijk herstelbare open bestanden actief.

  2. Start je laptop NIET opnieuw op

    Verwijderde gegevens kunnen herstelbaar blijven, maar opslag, databasegedrag, SSD-discard/TRIM en latere schrijfacties bepalen dat. Beperk schrijven op het getroffen volume; neem niet aan dat de bytes nog bestaan.

  3. Sluit geen open processen

    Behoud ongerelateerde processen die verwijderde bestanden openhouden, omdat herstel via hun bestandsdescriptors mogelijk kan zijn. Dit geldt niet voor de destructieve schrijver: stop die eerst. Laat verwijderen niet doorgaan alleen om een open handle te bewaren.

  4. Start een schermopname

    Leg exacte tijd, getroffen paden en zichtbare opdrachtuitvoer vast. Bewaar opnamen of gekopieerde logs op een apart gecontroleerd apparaat, niet op het beschadigde volume. Bewaar daar overlevende gevolgde, ongevolgde en genegeerde bestanden en Git-metadata vóór herstelpogingen.

Daarna heb je 6 minuten om te herstellen. Aan de slag.

Minuut 2–3: leg precies vast wat er misging

Belangrijkste punten

Stel eerst een diagnose en herstel daarna. Zonder precies te weten “wat, door wie, wanneer en met welke opdrachten is verwijderd”, herstel je blind en kun je gegevens beschadigen die nog intact zijn. Open een nieuw terminalvenster (niet het venster waarin de agent draait) en voer git status, git log --since en ps aux | grep claude uit. Kopieer onmiddellijk de map ~/.claude/projects/ — die bevat het volledige sessielogboek van de agent en kan helpen bij het herstel.

Open een nieuw terminalvenster. Niet het venster waarin de agent draait — een ander venster. Voer deze drie opdrachten achter elkaar uit.

1. Leg precies vast wat er in de git-repository is veranderd:

git status
git log --since="30 minutes ago" --all --oneline

Een verwijderd gevolgd bestand kan nog in de index of een commit bestaan. Bewaar vóór elke herstelactie de huidige werkboom, inclusief ongevolgde en genegeerde bestanden; ter plaatse herstellen kan overlevende bewerkingen overschrijven. Bekijk en herstel in een afzonderlijke kopie.

2. Controleer welke agentprocessen actief zijn:

ps aux | grep -i claude
ps aux | grep -i cursor

Identificeer welk proces nog gevaarlijke schrijfacties uitvoert; een passende naam alleen is niet genoeg. Stop die schrijver en controleer dat hij gestopt is. Behoud ongerelateerde processen met bruikbare open bestanden; mislukt rustig stoppen en gaat vernietiging door, dan kan geforceerd beëindigen nodig zijn.

3. Bewaar het sessielogboek van de agent:

Claude Code slaat JSONL-sessies op in ~/.claude/projects/. Cursor slaat ze op in ~/.cursor/. Maak nu meteen een kopie:

cp -r ~/.claude/projects /external/incident-evidence/claude-projects

Vervang /external/incident-evidence/ door een bestaande bewijsmap op een apart gecontroleerd aangekoppeld apparaat. Schrijf de back-up niet naar het getroffen volume en overschrijf geen bestaand bewijs. Deze map bevat het letterlijke gesprek met de agent: welke opdrachten hij uitvoerde, wat hij antwoordde en in welke volgorde. Dit is je belangrijkste bron om het incident te onderzoeken en mogelijk verwijderde bestanden uit zijn context terug te halen (zie stap 4).

Minuut 4: git reflog — je beste kans

Belangrijkste punten

Reflog kan commits vinden die uit branchgeschiedenis verdwenen, maar bewaart geen ongecommitte werkboombestanden. Bewaar eerst overlevende gegevens en Git-metadata op een apart apparaat, bekijk daarna de gekopieerde repository en herstel een gecontroleerde commit in een aparte worktree. Begin nooit met het resetten van de beschadigde werkboom.

git reflog registreert lokale referentieverplaatsingen zolang vermeldingen behouden blijven. Verloop en opschonen verschillen en onbereikbare objecten kunnen worden verwijderd; het is geen gegarandeerd archief van elke oude commit. Voer de herstelstappen hieronder uit vanuit een bewaarde repositorykopie op het aparte apparaat.

Stap 1. Bekijk het logboek:

git reflog --all

Je krijgt een lijst zoals deze:

1a2b3c4 HEAD@{0}: reset: moving to HEAD~3
9z8y7x6 HEAD@{1}: commit: working version of the dashboard
5w4v3u2 HEAD@{2}: commit: added admin panel

Zoek naar het punt vóór de agent de schade veroorzaakte. Elke regel is een “snapshot” van de toestand van de repository op dat moment.

Stap 2. Herstel naar een aparte werkboom:

Voer dit na het kopiëren van repository en al het overlevende werk naar een apart apparaat uit vanuit die bewaarde repositorykopie. Vervang de waarde door de exacte in reflog gecontroleerde commit-SHA en kies een ongebruikte branch en bestemming:

RECOVERY_COMMIT='replace-with-verified-commit-sha'
git worktree add -b recovery-check ../recovery-check "$RECOVERY_COMMIT"

Bekijk herstelde bestanden in ../recovery-check en vergelijk met bewaarde ongecommitte bestanden voordat je iets terugkopieert. De opdracht checkt de gekozen commit apart uit en reset de beschadigde werkboom niet. Gekoppelde worktrees delen de Git-objectopslag van de gekopieerde repository; dit is dus een herstelwerkplek, geen onafhankelijke back-up. Zie de officiële git-worktree-documentatie.

Als reflog ook is opgeschoond (de agent heeft git gc uitgevoerd):

git fsck --lost-found

Deze opdracht vindt “verloren” commits en blobs (bestandsobjecten) die niet meer aan een branch zijn gekoppeld. Ze verschijnen in .git/lost-found/commit/ en .git/lost-found/other/. Zo herstel je daar een bestand uit:

git cat-file -p <SHA1-blob> > recovered-file.ext

Wanneer git reflog niet helpt:

  • Het bestand stond alleen in de werkboom, zonder commit of stash → reflog kan het niet vinden
  • Er zijn meer dan 90 dagen verstreken (de standaardwaarde van gc.reflogExpire) en git gc is uitgevoerd
  • De volledige repository is verwijderd (rm -rf .git) — dan heb je Time Machine of een snapshot nodig

Minuut 5: herstel de database vanuit een back-up

Belangrijkste punten

Met PostgreSQL Point-In-Time Recovery (PITR) kun je een database herstellen naar een willekeurige seconde binnen een periode van 7–35 dagen. Dit werkt met Yandex Cloud Managed Postgres, AWS RDS, Supabase Pro en met een lokale pg_dump-cronjob in Coolify. Belangrijk is dat PITR vóór het incident ingeschakeld moet zijn; je kunt dit niet met terugwerkende kracht doen. Herstel altijd naar een nieuwe instantie, nooit boven op een actieve database, zodat het terugzetten niet nog meer gegevens vernietigt. Was PITR niet ingeschakeld, gebruik dan de meest recente snapshot.

De database is verwijderd met DROP DATABASE, DROP TABLE of DELETE FROM ... WHERE ... (zonder WHERE-clausule). Wat moet je doen?

Stap 1. Controleer of je provider PITR aanbiedt:

ProviderPITR-periodeHerstelopdracht
AWS RDS1–35 dagen (instelbaar)aws rds restore-db-instance-to-point-in-time --restore-time 2026-05-28T14:30:00Z
Yandex Cloud Managed Postgres7 dagen (standaard)Herstel vanuit back-up in de console + geef het tijdstip op
Supabase Pro7 dagen (alleen Pro+)UI: Database → Backups → Restore
Coolify + lokale pg_dumpVolgens het cron-schemapg_restore -d new_db backup.dump

Stap 2. Herstel naar een nieuwe instantie, niet naar de oude:

Herstel nooit over een actieve database heen. Maak een nieuwe instantie op basis van de back-up en schakel de applicatie er vervolgens naartoe over. Als er iets misgaat, kun je DNS terugzetten.

Stap 3. Was PITR niet ingeschakeld, gebruik dan de meest recente snapshot:

# AWS RDS, snapshots weergeven:
aws rds describe-db-snapshots --db-instance-identifier my-db

# Herstellen vanuit een snapshot:
aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier my-db-restored \
  --db-snapshot-identifier rds:my-db-2026-05-28-12-00

Let op bij Supabase, iets waar veel mensen in 2026 door werden verrast: als PITR is ingeschakeld, worden er geen dagelijkse back-ups meer gemaakt. Dat is contra-intuïtief; je kunt daardoor helemaal geen back-ups meer hebben. Controleer in Dashboard → Database → Backups of PITR actief is EN of je een snapshot hebt om te herstellen.

Minuut 6: Time Machine, lsof en schijfsnapshots

Belangrijkste punten

Als bestanden van de schijf zijn verwijderd — niet uit git of een database — zijn er drie praktische herstelmethoden. Gebruik op macOS Time Machine met uurlijkse snapshots (als de laptop verbonden was met een Time Capsule of externe schijf). Voer op Linux sudo lsof | grep deleted uit — daarmee kun je bestanden terughalen die een proces nog open heeft staan (95% kans); kopieer ze via /proc/PID/fd/N. Maak in kritieke gevallen met dd een snapshot van de hele partitie en herstel daarna met extundelete of photorec.

macOS — Time Machine:

# Snapshots weergeven:
tmutil listbackups

# Een bestand herstellen vanuit de meest recente back-up:
tmutil restore /Volumes/Backup/.../my-project/file.tsx ~/projects/my-project/file.tsx

Time Machine maakt elk uur snapshots, bewaart uurlijkse snapshots een dag, dagelijkse snapshots een week en wekelijkse snapshots voor onbepaalde tijd. Als je laptop verbonden is met een Time Capsule of externe schijf, staat je project er met een nauwkeurigheid van een uur op.

Linux — het bestand is verwijderd, maar een proces heeft het nog open:

# Alle “verwijderde” bestanden vinden die een proces nog open heeft:
sudo lsof | grep deleted

# Je krijgt regels zoals deze:
# node 12345 user 24w REG 8,1 4096 1234567 /path/to/deleted/file.txt (deleted)

# Het bestand rechtstreeks kopiëren vanuit /proc/PID/fd/N:
sudo cp /proc/12345/fd/24 ~/recovered-file.txt

De kans op succes is ~95% als het proces niet is gesloten. Werkt op ext4, xfs en btrfs.

macOS — equivalent met lsof:

lsof | grep deleted

Het bestand kopiëren is lastiger (er is geen /proc/), maar het kan met lldb:

lldb -p 12345
(lldb) memory read --outfile recovered.txt --binary 0xADDRESS 0xSIZE

Snapshot van de volledige schijf (Linux, laatste redmiddel):

sudo dd if=/dev/sda1 of=/external/disk-image.img bs=4M status=progress

Hiermee sla je de volledige partitie op als een image. Herstel de gegevens vervolgens met extundelete of photorec. De kans op herstel hangt af van hoeveel er sinds de verwijdering naar de schijf is geschreven. Als er niets is geschreven, is de kans 80–90%. Als de schijf al een uur in gebruik is, is die 20–30%.

Minuut 7: wat als er geen back-up is

Belangrijkste punten

Geen back-up, een lege git reflog en de schijf is al overschreven met nieuwe gegevens. Er blijven twee laatste redmiddelen over: neem contact op met de ondersteuning van je provider (AWS, Yandex Cloud en Google Cloud herstellen periodiek gegevens uit hun interne opslag) of herstel via S3-versioning (als dit was ingeschakeld, zijn alle versies fysiek aanwezig).

Optie 1 — ondersteuning van de provider:

AWS, Yandex Cloud, Google Cloud en DigitalOcean herstellen periodiek gegevens uit hun interne opslag, zelfs na een ramp bij een klant, vooral bij betaalde abonnementen. Open een supportticket, geef het exacte tijdstip van het incident door en voeg screenshots van de situatie toe. Dit lukt het vaakst bij grote providers die zelf automatische back-ups bewaren. De kans is 40–60%; de reactietijd is 24–72 uur.

Optie 2 — S3-versioning:

Stonden bestanden in S3 (of Yandex Object Storage) en was versioning ingeschakeld, dan bestaan alle versies fysiek; ze zijn alleen als “verwijderd” gemarkeerd.

# AWS — versies weergeven:
aws s3api list-object-versions --bucket my-bucket --prefix files/

# Een versie herstellen:
aws s3api copy-object \
  --bucket my-bucket \
  --copy-source my-bucket/files/data.json?versionId=ABC123 \
  --key files/data.json

Belangrijke kanttekening: Claude Code bewaart sessies niet voor altijd — oude JSONL-bestanden worden na enkele weken automatisch verwijderd. Kopieer ~/.claude/projects/ eenmaal per week met een eenvoudige cronjob naar een externe schijf om ervoor te zorgen dat je bij een ramp een maand JSONL-geschiedenis hebt:

# In crontab, elke zondag om 03:00:
0 3 * * 0 rsync -av ~/.claude/projects/ /external/claude-history-backup/

Dit is gratis en redt je wanneer “alles weg is, er geen back-up is en reflog leeg is”.

7 regels om te voorkomen dat dit ooit nog gebeurt

Belangrijkste punten

Zeven regels die voorkomen dat een AI-agent je database of code verwijdert. Gebruik Plan Mode vóór destructieve handelingen. Gebruik geteste hooks om geselecteerde gevaarlijke opdrachtteksten te herkennen, naast afgedwongen machtigingsgrenzen. Geef de agent een alleen-lezen databasegebruiker. Commit automatisch na elke bestandsbewerking. Gebruik voor experimenten een geïsoleerde sandboxmap. Maak elk uur schijfsnapshots met restic. Archiveer JSONL-sessies op een externe schijf.

1. Plan Mode vóór elke destructieve handeling. In Claude Code:

claude --plan

De agent maakt een plan voordat hij handelt. Je leest het, ziet DROP TABLE users en annuleert. Zonder Plan Mode beslist de agent zelf en voert hij de actie in milliseconden uit. Lees meer in de handleiding voor Plan Mode in Claude Code.

2. Hooks als extra struikeldraad. Gebruik een geteste PreToolUse-hook die event-JSON van stdin leest en bij een gedetecteerde riskante actie met 2 eindigt. Het volledige voorbeeld hieronder dekt Bash, Write en Edit; het is geen beveiligingsgrens en kan indirecte acties missen. Houd databaserechten en sandbox beperkt.

3. Alleen-lezen DB-gebruiker voor de agent. Maak een aparte gebruiker aan voor de agent die geen rechten heeft voor DROP, TRUNCATE of DELETE:

CREATE USER claude_readonly WITH PASSWORD 'xxx';
GRANT CONNECT ON DATABASE myapp TO claude_readonly;
GRANT USAGE ON SCHEMA public TO claude_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO claude_readonly;

Schakel handmatig over naar een andere gebruiker wanneer de agent echt moet schrijven. Voor dagelijkse taken zoals gegevensanalyse, rapporten en dashboards is een alleen-lezen gebruiker voldoende.

4. Bewaar gecontroleerde wijzigingen in Git. Een PostToolUse-hook in .claude/settings.json kan na Write en Edit een herinnering tonen:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "printf '%s\\n' 'Bekijk de diff en commit alleen de afgesproken bestanden handmatig.' >&2"
          }
        ]
      }
    ]
  }
}

Dit voorbeeld toont alleen een herinnering; het zet geen bestanden klaar en maakt geen commits. Bekijk de diff en commit alleen de afgesproken bestanden handmatig. De reflog bewaart geen wijzigingen die niet zijn gecommit.

5. Sandboxproject voor experimenten. Laat de agent nooit werken in een project met echte klantgegevens. Maak een aparte map ~/sandbox-projects/ met een kopie van het project en synthetische gegevens. Probeer daarin een nieuwe prompt, agent of MCP-server uit. Gaat er iets mis, dan is er geen schade.

6. Elk uur schijfsnapshots met restic.

# Installeren:
brew install restic  # macOS
sudo apt install restic  # Linux

# Repository aanmaken:
restic init --repo /external/backups

# Het huidige project back-uppen:
restic --repo /external/backups backup ~/projects

# Een cronjob voor elk uur instellen:
crontab -e
# Toevoegen:
0 * * * * restic --repo /external/backups backup ~/projects

Zeven dagen aan uurlijkse back-ups, vier weken aan dagelijkse back-ups — en je kunt altijd teruggaan naar elk punt in het verleden. Dit is gratis en kost 10 minuten om in te stellen.

7. Archiveer Claude Code JSONL-sessies. Dit is hierboven al genoemd, maar we herhalen het als afzonderlijke regel: plan een wekelijkse rsync van ~/.claude/projects/ naar een externe schijf. Het is gratis en kost één regel in crontab.

Kant-en-klare hooks om gevaarlijke opdrachten te blokkeren

Belangrijkste punten

Het voorbeeld hieronder is een PreToolUse-struikeldraad voor geselecteerde Bash-opdrachtteksten en gevoelige Write-/Edit-paden. Het leest stdin-JSON en geeft bij matches exitcode 2. Het kan indirecte of verborgen acties missen en vult daarom sandbox en beperkte inloggegevens aan. Voeg de hook samen met bestaande configuratie en test gedrag vóór gebruik.

Voeg deze vermelding samen met .claude/settings.json zonder bestaande hooks te vervangen:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash|Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/check-risk.py\""
          }
        ]
      }
    ]
  }
}

Maak .claude/hooks/check-risk.py met dit Python 3-script:

import json
import re
import sys
from pathlib import Path

try:
    event = json.load(sys.stdin)
    tool = event["tool_name"]
    data = event["tool_input"]
    blocked = False
    if tool == "Bash":
        command = data["command"]
        blocked = bool(re.search(
            r"drop\s+(database|table)|truncate\s+table|"
            r"delete\s+from.*where\s+1|rm\s+-rf|"
            r"git\s+reset\s+--hard|git\s+push.*(--force|-f)|"
            r"chmod\s+-R\s+777",
            command, re.IGNORECASE | re.DOTALL))
    elif tool in ("Write", "Edit"):
        path = Path(data["file_path"]).resolve()
        blocked = (".git" in path.parts or path.name.startswith(
            (".env", "credentials", "secrets")))
except (ValueError, KeyError, TypeError, OSError):
    print("BLOCKED: invalid hook input", file=sys.stderr)
    sys.exit(2)

if blocked:
    print("BLOCKED: high-risk command or sensitive path", file=sys.stderr)
    sys.exit(2)
sys.exit(0)

De hook leest het gedocumenteerde JSON-event van stdin, controleert tool_input.command of tool_input.file_path en eindigt bij een match met 2. Hij controleert Write én Edit. Test een onschuldige toegestane en een geblokkeerde fixture vóór gebruik en controleer dat Python en het ingestelde script werkelijk starten.

Dit is een tekstuele struikeldraad: hij kan herordende vlaggen, scripts, aliassen, verborgen opdrachten, andere tools en indirecte schrijfacties missen en onschuldige geciteerde voorbeelden afwijzen. Hij geeft of verwijdert geen OS-/databaserechten. Houd productie-inloggegevens buiten de agentomgeving, gebruik een alleen-leesdatabaserol en afgedwongen sandbox en bescherm de hookconfiguratie tegen bewerking. Zie de officiële referentie voor hookinvoer en exitcodes.

Beoordeel een bedoelde uitzonderingsactie en voer die buiten de agent uit met het passende beperkte account. Een shellomgevingsvariabele is geen gedocumenteerde interface om hooks uit te schakelen en hooks beheersen geen gewone terminalopdrachten.

Volgende stap: een checklist van 7 minuten om te bewaren

Belangrijkste punten

Sla deze gids nu op als bladwijzer. Als er een ramp gebeurt, open je de pagina en volg je de checklist met 10 punten in volgorde. Dat bespaart je 30 minuten paniek en voorkomt dat je per ongeluk gegevens overschrijft die misschien nog te herstellen zijn. Kom na het herstel terug en stel de 7 preventieve regels in, zodat er volgende week niet opnieuw een ramp gebeurt.

Checklist: “AI heeft het verwijderd — wat moet ik doen?”

  1. Stop de echte destructieve schrijver onmiddellijk; controleer dat kind- of externe acties zijn gestopt
  2. Herstart niet; behoud ongerelateerde processen die verwijderde bestanden openhouden
  3. Leg incidenttijd en opdrachtbewijs vast op een apart gecontroleerd apparaat
  4. Kopieer overlevende bestanden, Git-metadata en relevante sessielogs naar dat aparte apparaat
  5. Bekijk in de bewaarde repositorykopie git reflog --all en herstel een gecontroleerde commit naar een aparte worktree
  6. Hielp git niet — git fsck --lost-found
  7. Database: PITR (AWS/Yandex/Supabase) of de meest recente snapshot
  8. Bestanden: Time Machine op Mac, lsof op Linux
  9. Laatste redmiddel: ondersteuning van de provider + S3-versioning
  10. Stel na het herstel de 7 preventieve regels uit deze gids in

Volgende stap — systematische bescherming:

Ailoot openen.

Meer details

Vragen en antwoorden

Moet ik wachten tot de huidige agentopdracht klaar is?

Nee. Stop de destructieve schrijver direct en controleer dat kind-, externe of databaseacties zijn gestopt. Behoud ongerelateerde processen met mogelijk herstelbare verwijderde bestanden; alleen de agent stoppen kan een andere schrijver actief laten.

Kan ik herstel beginnen met git reset --hard?

Bewaar eerst overlevende gevolgde, ongevolgde en genegeerde bestanden plus Git-metadata op een apart apparaat. Bekijk de gekopieerde repository en herstel een gecontroleerde commit naar een aparte worktree; ter plaatse hard resetten kan overlevende ongecommitte bewerkingen vernietigen.

Alle artikelen