# Safety nets (https://lazyfrog.dev/docs/guide/safety-nets)

{/* Generated by scripts/generate-docs.ts from services/gateway/src/guide.md. Do not edit. */}

- What they are: copies kept with the project, so a restore loses at most the hour since the
  last automatic one. On a paid plan LazyFrog also keeps separate encrypted off-site backups for
  disaster recovery (Free keeps the snapshots only); they aren't something you restore from. For a business taking payments, still keep the
  records it can't lose (orders, payments) also in the provider (Stripe).
- Logs: `logs_tail` reads the last lines (search back with `grep` and `since`); a production app
  has no request log of its own, so log what you'll need (errors with the tenant and route).
- Every change is recorded and can be undone. `fs_write`, `fs_edit` and an `exec` that isn't
  `read_only` take an undo point of their own just before the change (a snapshot; the result
  ends "Undo point … was taken just before this change"; a command that changed no files usually
  keeps none). `fs_edit` and `fs_write` answer with the lines they changed, and `exec` with the
  files it changed ("Changed 2 files: …"): read them back rather than assume. To take back the
  last change, `snapshot undo`: it reverts that change alone, lists the files it reverts (more
  than 20 need `confirm: true`) and keeps the state it replaces; undo again goes one more change
  back (past the last 50 changes and the last hour, ten minutes at a time). The owner sees the
  same changes in Activity and can undo them there. After a run of changes the result says once
  to commit: a `git commit` of work that works is the clean undo point.
- Snapshots: hourly automatic ones, plus one before every risky action (database writes,
  migrations, restores). `snapshot create` makes one now; `snapshot restore` goes back and keeps
  the state it replaces, so a restore can be undone. Its `scope` is `code` unless you say
  otherwise: after a bad database write use `database`, for lost files `data`, or `all`.
  Snapshots are kept for the plan's undo history (a day on Free, a week on Hobby, 30 days on
  Pro, 90 days on Business); the ones each publish takes (`pre-deploy-<n>`, which hold the live database) go with their
  release: the last 10 releases younger than 90 days and one a day within the undo history are
  kept, plus always the live release and the one before it; the rest are removed every hour. So
  data deleted from the live site lingers in those copies for up to 90 days (longer only in the
  live release's and the previous one's, until the next publishes), and on a paid plan in the
  encrypted off-site backups for up to 62 days. Neither can be purged early; say so when an owner deletes
  someone's data, and that a database rollback or restore brings deleted records back: keep a log
  of erasures outside the data that's restored (a table of ids, re-applied after any restore). A
  code restore changes the preview only: the live site runs its published version, which
  `deploy rollback` changes (`with_database: true` also brings back the live data from before
  the later deployments changed the schema). Restoring the live site's database or files from a
  snapshot needs the owner's approval when you ask, like a destructive publish.
- A publish whose migrations delete or rewrite live data needs the owner's approval when you ask
  for it: the first try (with or without `confirm`) puts the request in their portal; tell the
  user what the change does to their data, and publish again with `confirm: true` once approved.
- Destructive actions ask for `confirm: true`. Deleting a project asks the user to approve it;
  it then stays in the Trash for 7 days, and `project` `unarchive` brings it back.
- Archiving (`project` `archive`) parks a project: its data is kept and it stops counting toward
  the plan's projects, but its live site goes offline too (preview and production stop; every
  address, custom domains included, shows "This site is archived by its owner"). It is not a way
  to keep a site online for free; ask the user first, and say so. `project` `unarchive` brings it
  back (it counts again, and a published site goes live from its current release). On Free a
  project archived that was never live lets its name go at once (anyone may take it); unarchiving
  gives it back if it's still free, and otherwise the project gets a close one (the result's
  `slug`; say so). Archiving or
  deleting a project lets a read-only one (kept after a downgrade) take the place it frees.
- Mutating tools accept `idempotency_key`: if a call might not have arrived, repeat it with the
  same key and it will not run twice.
- If another AI client is working in the same project you get `workspace_busy`; wait and retry.
