Appearance
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
| Deleted | Goes to the trash with it | Stays 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 proposals | Rendered 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 environment | Its 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 withtemplate.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 addslibraries/<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 404in-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.
- it isn't listed: not on the Libraries page, in the library browser or in
- 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
| Action | Needs |
|---|---|
See the trash (GET /v1/trash, GET /v1/trash/{item}) | template.read |
| Move a template to the trash, or a folder that holds templates | template.write in every environment |
| Move an empty folder to the trash | template.write |
| Move a library to the trash | library.write in every environment |
| Restore an item | What 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 astrash.expirebyreportd. - Each item's
purgeAtis itsdeletedAtplusretentionDays, worked out at each sweep: loweringretentionDaysapplies 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 withtrash.purgedeletes 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 commitpurge 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.
| Store | Trash |
|---|---|
| File template store | <templateStore.path>/.trash/<item>/: item.json, the template's folder and its conversations, moved there as they were |
| SQLite template store | templates.trash_item and trashed_at mark a trashed template's row, which keeps everything that hangs off it; trash_items keeps the items |
| Libraries | On 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:
Purge the item, so nothing restores it.
Stop reportd, and take a backup (
reportd backup).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:shgit clone --mirror <sourceControl.path or the remote> repo.git cd repo.git git filter-repo --invert-paths --path templates/<id>/Force-push the rewritten branches to the remote, if there is one, and replace
sourceControl.pathwith the rewritten repository (or delete it, and let reportd fetch it again from the remote at start).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.