@grantjs/schema 1.17.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grantjs/schema",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -83,6 +83,17 @@ const INTEGRATIONS_OWNERS: EventCatalogEntry = {
83
83
  audienceRule: { primitives: ['owners'], excludeActor: true },
84
84
  };
85
85
 
86
+ /**
87
+ * An event that exists for webhook consumers only: delivered transactionally to
88
+ * subscriptions, never turned into a notification. The empty audience is what
89
+ * keeps the notification generator from creating rows for it.
90
+ */
91
+ const webhookOnly = (category: EventCategory): EventCatalogEntry => ({
92
+ category,
93
+ deliveryClass: 'transactional',
94
+ audienceRule: { primitives: [] },
95
+ });
96
+
86
97
  export const EVENT_TYPES = [
87
98
  // IAM mutations (Phase 1 slice)
88
99
  'role.created',
@@ -135,6 +146,17 @@ export const EVENT_TYPES = [
135
146
  // CDM / project sync job summaries (entity events suppressed during import)
136
147
  'project_sync.completed',
137
148
  'project_sync.failed',
149
+ // Webhook-only lifecycle events (no notification): users, project users, API keys, tags
150
+ 'user.created',
151
+ 'user.updated',
152
+ 'user.deleted',
153
+ 'project.user_updated',
154
+ 'api_key.deleted',
155
+ 'tag.created',
156
+ 'tag.updated',
157
+ 'tag.deleted',
158
+ 'tag.linked',
159
+ 'tag.unlinked',
138
160
  ] as const;
139
161
 
140
162
  export type EventType = (typeof EVENT_TYPES)[number];
@@ -200,6 +222,16 @@ export const EVENT_CATALOG: Readonly<Record<EventType, EventCatalogEntry>> = {
200
222
  'user.password_changed': SECURITY_SUBJECT,
201
223
  'project_sync.completed': INTEGRATIONS_OWNERS,
202
224
  'project_sync.failed': INTEGRATIONS_OWNERS,
225
+ 'user.created': webhookOnly('membership'),
226
+ 'user.updated': webhookOnly('membership'),
227
+ 'user.deleted': webhookOnly('membership'),
228
+ 'project.user_updated': webhookOnly('membership'),
229
+ 'api_key.deleted': webhookOnly('security'),
230
+ 'tag.created': webhookOnly('iam'),
231
+ 'tag.updated': webhookOnly('iam'),
232
+ 'tag.deleted': webhookOnly('iam'),
233
+ 'tag.linked': webhookOnly('iam'),
234
+ 'tag.unlinked': webhookOnly('iam'),
203
235
  };
204
236
 
205
237
  export function getEventCatalogEntry(type: EventType): EventCatalogEntry {
@@ -33,6 +33,13 @@ export interface DomainEventInput {
33
33
  aggregate?: EventAggregateRef;
34
34
  data: EventData;
35
35
  occurredAt?: Date;
36
+ /**
37
+ * Projects this event is relevant to beyond the one named by its scope. The
38
+ * publisher adds the projects an entity-bound aggregate is linked to; a caller
39
+ * passes it only to capture the links before a write that destroys them (a
40
+ * delete). Never part of the external envelope.
41
+ */
42
+ projectIds?: string[];
36
43
  }
37
44
 
38
45
  /**
@@ -51,6 +58,11 @@ export interface DomainEvent {
51
58
  aggregate?: EventAggregateRef;
52
59
  data: EventData;
53
60
  occurredAt: Date;
61
+ /**
62
+ * Projects the event is relevant to in addition to the project its scope names
63
+ * (webhook fan-out, ADR 0012). Internal: not carried by the webhook envelope.
64
+ */
65
+ projectIds?: string[];
54
66
  }
55
67
 
56
68
  /**
@@ -68,6 +80,14 @@ export interface CloudEventEnvelope {
68
80
  grantsequence: string;
69
81
  grantscope: { tenant: string; id: string };
70
82
  grantactor?: { userId: string } | null;
83
+ /**
84
+ * The user the event is about, when it has one (`user.role_revoked`,
85
+ * `project.user_removed`, `organization.invitation_sent`, ...). `null` when
86
+ * the event has no subject user. Needed because the internal `before`
87
+ * snapshot is dropped from external `data`, so revoke/remove events would
88
+ * otherwise not say whose access changed.
89
+ */
90
+ grantsubjectuser?: { userId: string } | null;
71
91
  grantcategory: EventCategory;
72
92
  data: EventData;
73
93
  }