Add updated-from entity snapshot to updated webhooks

Update webhook events now carry a top-level "updatedFrom" field
alongside "data", containing a full snapshot of the entity as it was
before the update. This lets subscribers diff old vs new state (for
example the prior membership role on user:updated) without tracking
prior state themselves. It is a complete snapshot with the same shape as
"data", not a partial diff, so consumers select whatever fields they
need. The field is omitted for non-update events.

The webhook_data table gains a nullable updated_from JSONB column, and
webhook.InsertUpdateData enqueues both snapshots; InsertData delegates to
it with a nil updatedFrom so non-update callers are unaffected. Each
*:updated emission site snapshots the entity right after load, before
mutation: obligation, third-party, user (org and SCIM flows), document,
document-version, and document-version-approval-quorum. The document
emit helpers gained an optional updatedFrom argument threaded through to
the payload.

For document-version-approval-quorum:updated the snapshot requires an
extra query, so it is now gated behind the same subscription-existence
check the emitter uses: when no subscriber is configured the load is
skipped entirely rather than running (and potentially failing the
approval) for an event nobody receives.

Add integration tests (against a real Postgres, skipped when none is
reachable) covering the updated_from round-trip, the SQL NULL behavior
when no snapshot is provided, and the no-op when no subscription matches,
plus a unit test asserting updatedFrom is omitted from the payload when
absent.

Document the new field in the probod and n8n changelogs and the n8n
README.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
This commit is contained in:
Sacha Al Himdani
2026-07-15 10:34:17 +02:00
parent 68338fb4ae
commit 944bcb7380
15 changed files with 428 additions and 19 deletions

View File

@@ -103,6 +103,15 @@ Probo Trigger → Slack
4. **Activate the workflow.** n8n registers a webhook subscription in Probo. When a document version is published, Probo delivers the event and the Slack message is sent.
### Update events carry the previous state
For `*:updated` events, the payload includes an `updatedFrom` object next to `data`, holding a full snapshot of the entity as it was before the update. This lets a workflow react to what actually changed — for example, only notify when a user's role changes:
- **Condition:** `{{ $json.data.membership.role !== $json.updatedFrom.membership.role }}`
- **Text:** `Role changed from {{ $json.updatedFrom.membership.role }} to {{ $json.data.membership.role }}`
`updatedFrom` is present only on update events; it is absent for created, deleted, and other lifecycle events.
### Alternative: list open tasks on a schedule
Use the **Probo** action node without a trigger: