Skip to content

The trash ​

Deleting a template, a folder or a library moves it to the trash, where it is kept for 30 days and can be restored. Only administrators delete things for good before then.

What goes to the trash ​

DeletedGoes to the trash with itStays behind
A template (DELETE /v1/templates/{id})Its drafts in every environment, their edit logs and undo history, the published copies and their history, its files and the assistant's conversations and proposalsRendered reports in the report store. Its unfinished jobs are cancelled (template-in-trash) and its pending approvals withdrawn.
A folder (DELETE /v1/folders?path=)Its subfolders and every template in them, as one item—
A library (DELETE /v1/libraries/{name})Its draft in every environmentIts releases, so published reports that pin one keep rendering it
  • A template goes from every environment at once. Each environment branch gets a commit trash <id> that removes it, and the trash item keeps the git tree each branch had.
  • A template in the trash doesn't render. Its links, renders, view sessions (open ones too), jobs and MCP tools answer 404 in-trash. The answer names the trash item only to callers with template.read; the viewer says "This report was deleted" and nothing more.
  • Its id is held. A new template can't take it until it is restored or purged: creating one answers 409 in-trash, and the studio offers to restore the old one.
  • An empty folder goes to the trash too, so every delete can be undone.
  • A library goes from every environment at once. Each environment branch gets a commit trash library <name> that removes the draft and adds libraries/<name>/trashed/item.json, the trash item, which keeps each branch's draft. While it is there:
    • it isn't listed: not on the Libraries page, in the library browser or in GET /v1/components, and its routes answer 404 in-trash;
    • nothing new resolves to it: a draft that imports it, or uses its reports or assets, gets the error ref/library-in-trash, and can't be published until the import goes or the library comes back;
    • published reports keep rendering the releases their lockfile pins, and promoting one still takes its pinned release along;
    • its name is held: creating a library with it answers 409.
  • Draft files of templates and libraries aren't trash items: they keep their own undo and git history.

Restoring ​

The studio's notice after a delete has an Undo, and the catalog's Trash view has Restore on every item. Through the API it is POST /v1/trash/{item}/restore.

  • A template comes back as it was: each environment's last published version (a commit restore <id> on each branch that had it), the draft, its edit log and history, and its conversations. A branch that never had it is left alone. If its folder is gone, it is made again.
  • A folder comes back whole, with every template in it, or not at all.
  • A library comes back on every branch: a commit restore library <name> removes the marker and puts back the draft that branch had.
  • Cancelled jobs and withdrawn approvals stay that way.

Who can do what ​

ActionNeeds
See the trash (GET /v1/trash, GET /v1/trash/{item})template.read
Move a template to the trash, or a folder that holds templatestemplate.write in every environment
Move an empty folder to the trashtemplate.write
Move a library to the trashlibrary.write in every environment
Restore an itemWhat deleting it needed
Delete an item for good (DELETE /v1/trash/{item}) or empty the trash (DELETE /v1/trash)trash.purge

trash.purge is a built-in permission that only the administrator role has. A custom role may add it. An agent key never has it, even when the user it acts for does, so whatever an agent deletes can be undone.

Every move is audited: template.trash, folder.trash (with the number of templates) and library.trash (as library:<name>), <kind>.restore, <kind>.purge, trash.empty (with the number of items) and trash.expire for the sweep.

How long things are kept ​

yaml
trash:
  retentionDays: 30   # 0 keeps items until they're purged by hand
  • reportd sweeps the trash when it starts and every 24 hours after, and purges every item older than retentionDays, audited as trash.expire by reportd.
  • Each item's purgeAt is its deletedAt plus retentionDays, worked out at each sweep: lowering retentionDays applies to the items already there at the next sweep (the next start, for one), and the log says how many it purged.
  • With 0, items stay until someone with trash.purge deletes them.

A library that reports still use ​

A library can't be deleted for good while a published report pins one of its releases, in any environment: DELETE /v1/trash/{item} answers 409 library-in-use and lists the reports ({environment, template, name, version}). Update those reports to another library's release or make local copies of what they use, and publish them, first. Reports in the trash don't count.

  • The sweep never purges a pinned library, however old it is. It stays in the trash, past its purgeAt, until no published report pins it; the next sweep after that takes it.
  • Emptying the trash keeps it too, and the reply counts it in kept.
  • Otherwise purging removes libraries/<name>/ from every environment branch, releases and all, with a commit purge library <name>. The commits from before it still hold the releases.

Where it lives ​

The trash is inside the stores and the git repository, so reportd backup takes it and reportd restore brings it back with its dates; the next sweep purges whatever is past its time by then.

StoreTrash
File template store<templateStore.path>/.trash/<item>/: item.json, the template's folder and its conversations, moved there as they were
SQLite template storetemplates.trash_item and trashed_at mark a trashed template's row, which keeps everything that hangs off it; trash_items keeps the items
LibrariesOn each environment branch: libraries/<name>/trashed/item.json, beside the library's releases

The template stores' trash came with the file template store's format 2 and SQLite's format 3 (migrations.md); an older reportd refuses them.

The presets had a trash of their own, in <dataDir>/presets/.trash/, until they became library items. dataDir's format 7 moves the presets into libraries and removes the folder, with the presets that were in the trash (migrations.md).

Erasing a template from git history ​

Purging deletes a template from the template store for good, but not from git: the commits from before it went to the trash still hold every version that was published, on every environment branch and on the remote, if there is one. That is usually what you want (the history of what was published, and when, stays). When data must be erased, an operator rewrites the repository by hand:

  1. Purge the item, so nothing restores it.

  2. Stop reportd, and take a backup (reportd backup).

  3. In a clone of the repository (sourceControl.path, or the remote), remove the template's folder from every commit, for example with git filter-repo:

    sh
    git clone --mirror <sourceControl.path or the remote> repo.git
    cd repo.git
    git filter-repo --invert-paths --path templates/<id>/
  4. Force-push the rewritten branches to the remote, if there is one, and replace sourceControl.path with the rewritten repository (or delete it, and let reportd fetch it again from the remote at start).

  5. Remove the old backups that still hold it, and tell everyone with a clone to clone again.

A library is erased the same way, with --path libraries/<name>/.

Rewriting changes every commit id from the first one that held the template, so signed links and renders pinned to an old commit id stop working, and the history panel's commit ids change.

Rendered reports in the report store are kept until reportStore.retentionDays removes them, as before the trash.