Deleting an app fires record_app_delete (nextcloudappstore/core/models.py:864-867), which creates an AppReleaseDeleteLog row whose only field is last_modified — no app id, no user, no address. It exists to drive cache invalidation, which it does well, but it is the only trace a deletion leaves.
App deletion is irreversible, owner-triggered and reachable over the API (DELETE /api/v1/apps/<id>). The authentication on it is sound — token or basic auth, no session auth so no CSRF surface, and App.can_delete allows the owner alone — but if an owner's token leaks, the store can say that something was deleted and when, and nothing else.
Proposed fixes:
- Record the app id on deletion at minimum, so the log can answer what. Cheapest useful change.
- Record the acting user as well, so it can answer who. Note the actor is not currently passed to the
post_delete receiver, so this likely means logging in the view rather than in a signal.
- Keep the cache-invalidation row as it is, or split the two concerns: a counter for cache busting and an append-only audit record for accountability. They have different retention needs.
- Consider covering app release deletion (
DELETE /api/v1/apps/<id>/releases/<version>) the same way, since it shares the log model and the same gap.
Related: the same absence at the admin level came up in an admin/permissions review — there is no audit trail for any moderation action, of which this is the sharpest example because the data is gone afterwards.
Deleting an app fires
record_app_delete(nextcloudappstore/core/models.py:864-867), which creates anAppReleaseDeleteLogrow whose only field islast_modified— no app id, no user, no address. It exists to drive cache invalidation, which it does well, but it is the only trace a deletion leaves.App deletion is irreversible, owner-triggered and reachable over the API (
DELETE /api/v1/apps/<id>). The authentication on it is sound — token or basic auth, no session auth so no CSRF surface, andApp.can_deleteallows the owner alone — but if an owner's token leaks, the store can say that something was deleted and when, and nothing else.Proposed fixes:
post_deletereceiver, so this likely means logging in the view rather than in a signal.DELETE /api/v1/apps/<id>/releases/<version>) the same way, since it shares the log model and the same gap.Related: the same absence at the admin level came up in an admin/permissions review — there is no audit trail for any moderation action, of which this is the sharpest example because the data is gone afterwards.