feat(activity): per-tenant audit feed in notification dropdown

activity_events records booking lifecycle transitions with the actor
behind each change — staff (dashboard), customer (self-service), or
system (auto-promotion). The notification dropdown leads with the real
feed instead of derived recent-booking guesses.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-18 16:06:13 +02:00
1 parent e5cb9bd543
commit d86cba61e3
18 files changed
+634 -28

No files matched your search

+62
View File
@@ -1404,6 +1404,33 @@ paths:
description: Invalid scope or foreign staff member
"404":
description: Tenant membership not found
/v1/activity:
get:
tags: [Activity]
operationId: listActivityEvents
security:
- bearerAuth: []
summary: Recent tenant activity feed
description: >-
Audit feed of booking lifecycle events — created, cancelled,
rescheduled, moved, promoted — with the actor (staff member, customer,
or system) for each change. Newest first.
parameters:
- name: limit
in: query
schema:
type: integer
default: 50
maximum: 100
responses:
"200":
description: Activity events, newest first
content:
application/json:
schema:
$ref: "#/components/schemas/ActivityFeedResponse"
"404":
description: Tenant membership not found
/v1/public/calendar/{token}:
get:
tags: [Calendar]
@@ -2048,6 +2075,41 @@ components:
type: array
items:
$ref: "#/components/schemas/StaffCalendarFeedEntry"
ActivityEvent:
type: object
required: [id, actorKind, action, entityType, summary, createdAt]
properties:
id:
type: string
format: uuid
actorKind:
type: string
enum: [staff, customer, system]
description: Who performed the change — dashboard user, self-service customer, or an automatic transition
actorName:
type: string
action:
type: string
description: Dotted verb, e.g. booking.created, booking.cancelled, booking.promoted
entityType:
type: string
entityId:
type: string
format: uuid
summary:
type: string
description: Human-readable label, e.g. "Alice Johnson — Relaxation massage"
createdAt:
type: string
format: date-time
ActivityFeedResponse:
type: object
required: [events]
properties:
events:
type: array
items:
$ref: "#/components/schemas/ActivityEvent"
DashboardBookingRequest:
type: object
required: [customerName, customerEmail, startsAt]