Skip to content

PERMANENT_DELETE notifications have all entity fields as null (dangling reference) #1668

Description

@ClemRz

Problem

When an entity is permanently deleted, the notification sent to observers has all entity fields as null:

{
  "id": 447150,
  "dateInscription": "2026-06-11T08:24:09.355Z",
  "dateReadAt": "2026-06-14T04:13:27.150Z",
  "notified": {"id": 1, "nickname": "Clément Rz"},
  "notifier": {"id": 32181, "nickname": "Frédéric Urien"},
  "cave": null,
  "comment": null,
  "description": null,
  "document": null,
  "entrance": null,
  "history": null,
  "location": null,
  "massif": null,
  "organization": null,
  "rigging": null,
  "notificationType": {"id": 5, "name": "PERMANENT_DELETE"}
}

This makes PERMANENT_DELETE notifications useless — the user cannot tell what was deleted.

Root Cause

The delete controllers permanently remove the entity from the database before (or concurrently with) calling NotificationService.notifySubscribers. The notification row in t_notification stores the entity's foreign key (e.g. id_cave = 42), but since the referenced record no longer exists, Waterline's .populate() resolves to null when the notification is later fetched.

Flow:

  1. CaveService.permanentlyDeleteCave(cave, ...) — entity removed from DB
  2. NotificationService.notifySubscribers(cave, ...) — notification created with id_cave = 42
  3. GET /api/v1/notifications.populate('cave') → cave Implements clicks on side menu #42 doesn't exist → null

This pattern is the same across all entity types (cave, entrance, document, massif, etc.).

Expected Behavior

PERMANENT_DELETE notifications should contain enough information for the user to understand what was deleted (at minimum, the entity type and a human-readable name/label).

Possible Solutions

  1. Denormalize entity metadata into the notification — Add a label (or entity_name) text column to t_notification and populate it at creation time with the entity's display name. This makes the notification self-contained.
  2. Soft-delete the entity first, notify, then hard-delete — Requires a deferred cleanup mechanism.
  3. Store a JSON snapshot — Add a metadata JSONB column to t_notification with a minimal snapshot (id, name/title, type) captured before deletion.

Option 1 or 3 are the most pragmatic since they don't require changing the deletion flow.

Affected Code

  • api/controllers/v1/*/delete.js — all permanent delete controllers
  • api/services/NotificationService.jsnotifySubscribers()
  • api/controllers/v1/notification/find-all.js — notification fetching
  • api/models/TNotification.js — model schema

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: BugSomething isn't working as expected

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions