@classytic/party 0.1.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -3,6 +3,89 @@
3
3
  All notable changes to `@classytic/party` are documented here. Adheres to
4
4
  [Keep a Changelog](https://keepachangelog.com/) and [SemVer](https://semver.org/).
5
5
 
6
+ ## [0.3.0] — 2026-10-11
7
+
8
+ ### Added — marketing consent, per contact channel
9
+
10
+ - `ContactPoint.consent` (`{ status: 'granted' | 'withdrawn', at, source?, ip? }`) records permission to MARKET to one channel. Absent means "never asked", which a sender must treat as a refusal; `withdrawn` is deliberately not "absent", because only an opt-out has to survive a merge, a re-import or the person booking again.
11
+ - `recordConsent(id, input, ctx)` stores a decision against a channel, matching the channel by its NORMALIZED value (`07700 900000` and `+447700900000` reach the same contact point). A channel the party does not hold is a typed error, not a silent no-op. Emits `party:party.consent_recorded`.
12
+ - Merging two parties **reconciles consent** (`reconcileConsent`, exported): a withdrawal always beats a grant, whichever record is newer, because duplicate rows' clocks record when a row was touched, not when the person spoke. Between two records of the same status the later one wins. A channel one side verified stays verified. Before this, the loser's contact row was dropped wholesale and could discard an opt-out the duplicate alone carried.
13
+ - Contact points are copied field by field on merge: Mongoose subdocuments keep their values behind prototype getters, so spreading one yielded internals and dropped data.
14
+ - `CONSENT_STATUSES` / `ConsentStatus` and the `ChannelConsent` type.
15
+
16
+ ### Added — dated related-party relationships
17
+
18
+ - `relationships[]` on a party: `shareholder`, `director`, `key_management`, `partner_in_firm`, `member`, `employee`, `lessor`, `associate` (`RELATIONSHIP_KINDS`), each with `from` and an exclusive `to`, an optional `relatedTo` (absent means the reporting company), and `shareClass` / `sharePercent` for shareholders. One party can hold several at once.
19
+ - `addRelationship`, `endRelationship` and `relationshipsOn(id, date, ctx)` (the relationships holding on a date). A bad date range, an overlap or an unknown row throws `PartyRelationshipError` (`party.relationship_invalid`, 422). Emits `party:party.relationship_changed`.
20
+ - A party model index for "every shareholder" / "every lessor" queries.
21
+
22
+ ### Added — `legalForm`
23
+
24
+ `legalForm` on a party (`@classytic/primitives/legal-form`): what the law treats the party as — a sole trader is an `individual`. Absent means not stated.
25
+
26
+ ### Changed — peer floors raised to current
27
+
28
+ `@classytic/mongokit` `>=3.33.0` → **`>=3.41.0`**, `@classytic/primitives` `>=0.29.0` → **`>=0.31.1`**, `@classytic/repo-core` `>=0.24.0` → **`>=0.31.0`**, `@classytic/contact` `>=0.1.0` → **`>=0.2.0`**, `mongoose` `>=9.4.1` → **`>=9.11.0`** (mongokit 3.41 requires it). Verified on a fresh install. New parties and merges write the new fields; existing documents read unchanged (`consent` stays absent, `relationships` defaults to `[]`).
29
+
30
+ ## [0.2.0] — 2026-08-17
31
+
32
+ ### Added
33
+ - `defineParty(shape)` / `blueprint.bind(connection, runtime)` — describe/bind construction API replacing `createParty`; describe phase is pure and safe at import time
34
+ - `SubjectRef` / `PARTY_MODEL_NAME` exported from `./domain/subject` — canonical polymorphic subject seam for cross-kernel refs (`@classytic/access`, `@classytic/muster`, etc.)
35
+ - `src/maintenance/phone-identity-repair.ts` — repair utility for phone-identity drift
36
+
37
+ ### Removed
38
+ - `createParty` (replaced by `defineParty`)
39
+
40
+ ## 1.0.0 - 2026-08-07 (unpublished)
41
+
42
+ ### Requirements
43
+
44
+ - **New peer dependency: `@classytic/contact >=0.1.0`** — install it alongside
45
+ this package. It owns contact-point canonicalisation (E.164 phones, emails),
46
+ which `resolveOrCreate` / `syncIdentity` derive their `identityKeys` from.
47
+ A PEER rather than a regular dependency on purpose: npm may nest a regular one
48
+ under `party/node_modules`, giving the host a second module instance, and then
49
+ `err instanceof PhoneFormatError` is `false` at a host catch site that imported
50
+ its own copy — a guard that compiles, runs, and matches nothing.
51
+
52
+ ### Breaking
53
+
54
+ - **Contact input that cannot be canonicalised now THROWS** instead of becoming
55
+ an identity key. A phone that is not a valid, dialable number raises
56
+ `PartyPhoneFormatError` (400 / `party.phone_invalid`); an unparseable email
57
+ raises `EmailFormatError`. `0.1.0` degraded both — a rejected phone became
58
+ `+${digits}`, producing keys like `phone:+01309000993` that are neither a
59
+ national number nor E.164, so two spellings of one person keyed differently and
60
+ the identity forked silently. There is no lenient variant.
61
+ - **Phone canonicalisation requires a region for national-format input.**
62
+ `PartyShape.defaultPhoneRegion` (ISO 3166-1 alpha-2, supplied by the
63
+ deployment — this kernel names no country). Unset ⇒ E.164-only input is
64
+ accepted and a national format is refused rather than guessed at. An explicit
65
+ `+…` number is never re-read through the region.
66
+ - **`ContactPoint.value` stores the canonical E.164**, with the caller's original
67
+ spelling preserved as `ContactPoint.input` (never keyed, never matched on).
68
+
69
+ ### Changed
70
+
71
+ - Added `PartyShape.identityContactTypes` (`email | phone`, both by default).
72
+ A host can exclude shared contact channels from automatic identity resolution
73
+ while retaining normalized contact points. Tax identifiers and external
74
+ references remain authoritative. Existing defaults are unchanged.
75
+ - The unique `identityKeys` index now explicitly includes only non-empty arrays.
76
+ This permits multiple name-only or contact-only parties when contact channels
77
+ are non-authoritative, without weakening uniqueness for real identity keys.
78
+ - Canonical email output is unchanged for every valid address — trim plus
79
+ lowercase, and still **no** Gmail-dot or `+tag` folding, since folding a
80
+ provider's rule merges two distinct inboxes into one identity. No existing key
81
+ is re-derived.
82
+ - `libphonenumber-js` is no longer a direct dependency.
83
+
84
+ ## 0.1.1 - 2026-07-22 (unpublished)
85
+
86
+ ### Changed
87
+ - Internal: `InProcess*Bus` is now a thin subclass of `@classytic/primitives/event-infra`'s shared `InProcessEventBus` (dedup / error-isolation / close semantics unchanged); `MemoryOutboxStore` re-exported from the shared runtime where applicable. No public API, event-name, or wire-envelope change. Requires `@classytic/primitives >=0.13.0`.
88
+
6
89
  ## [0.1.0] - 2026-07-13
7
90
 
8
91
  Initial release — the Party / Business-Partner identity kernel.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Classytic
3
+ Copyright (c) 2026 Classytic LLC
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -48,12 +48,12 @@ Peers: `@classytic/mongokit >=3.20`, `@classytic/primitives >=0.9.1`,
48
48
 
49
49
  ```ts
50
50
  import mongoose from 'mongoose';
51
- import { createParty } from '@classytic/party';
51
+ import { defineParty } from '@classytic/party';
52
52
 
53
- const party = await createParty({
54
- connection: mongoose.connection,
53
+ const party = defineParty({
55
54
  multiTenant: false, // identity is company-wide here; pass true for per-tenant SaaS
56
- });
55
+ defaultPhoneRegion: 'BD',
56
+ }).bind(mongoose.connection);
57
57
 
58
58
  // Resolve-or-create by ANY identity signal — race-safe, dedup by email/phone/vat.
59
59
  const { party: ada, created } = await party.port.resolveOrCreate(
@@ -76,6 +76,27 @@ const snap = await party.port.snapshot(String(ada._id), {});
76
76
  await party.repositories.party.merge(dupId, survivorId, {});
77
77
  ```
78
78
 
79
+ ### Contacts are not always proof of identity
80
+
81
+ Email and phone are authoritative identity keys by default, preserving the
82
+ race-safe behavior existing commerce hosts rely on. Domains where people often
83
+ share contact details can keep those values as contact data without allowing
84
+ them to collapse two parties:
85
+
86
+ ```ts
87
+ const party = defineParty({
88
+ multiTenant: true,
89
+ defaultPhoneRegion: 'GB',
90
+ identityContactTypes: [],
91
+ }).bind(mongoose.connection);
92
+ ```
93
+
94
+ Tax identifiers and explicit external references remain authoritative. A
95
+ domain-specific facet (for example a legal Client) can perform candidate-match
96
+ review and then attach its stable external reference or explicitly merge the
97
+ confirmed duplicate. This setting shapes persisted `identityKeys`; migrate
98
+ existing rows before changing it on a live deployment.
99
+
79
100
  ## The `PartyPort` — the reusable contract
80
101
 
81
102
  Consuming domains depend on `engine.port` (a `PartyPort`), not the models:
@@ -111,3 +132,7 @@ entities — that's the duplication this kernel exists to remove.
111
132
  ## License
112
133
 
113
134
  MIT
135
+
136
+ ## Trademark
137
+
138
+ Code is MIT-licensed. "Classytic"/"arc" names + logos are trademarks of Classytic LLC — see [TRADEMARK.md](TRADEMARK.md).
package/dist/events.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { DomainEvent, EventHandler, EventMeta, EventTransport } from "@classytic/primitives/events";
3
+ import { InProcessEventBus } from "@classytic/primitives/event-infra";
3
4
  import { Types } from "mongoose";
4
5
  import { OperationContext } from "@classytic/primitives/context";
5
6
  import "@classytic/primitives/reference";
@@ -14,10 +15,12 @@ declare const PARTY_EVENTS: {
14
15
  readonly ROLE_ADDED: 'party:party.role_added';
15
16
  readonly ROLE_REMOVED: 'party:party.role_removed';
16
17
  readonly USER_LINKED: 'party:party.user_linked';
18
+ readonly CONSENT_RECORDED: 'party:party.consent_recorded';
17
19
  readonly EXTERNAL_REF_ATTACHED: 'party:party.external_ref_attached';
18
20
  readonly ARCHIVED: 'party:party.archived';
19
21
  readonly RESTORED: 'party:party.restored';
20
22
  readonly MERGED: 'party:party.merged';
23
+ readonly RELATIONSHIP_CHANGED: 'party:party.relationship_changed';
21
24
  };
22
25
  type PartyEventName = (typeof PARTY_EVENTS)[keyof typeof PARTY_EVENTS];
23
26
  //#endregion
@@ -64,6 +67,14 @@ interface PartyUserLinkedPayload {
64
67
  partyId: string;
65
68
  userId: string;
66
69
  }
70
+ interface PartyConsentRecordedPayload {
71
+ partyId: string;
72
+ channel: 'email' | 'phone';
73
+ /** The NORMALIZED channel — what a sender would actually dial or mail. */
74
+ value: string;
75
+ status: 'granted' | 'withdrawn';
76
+ source?: string;
77
+ }
67
78
  interface PartyExternalRefAttachedPayload {
68
79
  partyId: string;
69
80
  sourceModel: string;
@@ -87,6 +98,7 @@ interface PartyEventPayloads {
87
98
  [PARTY_EVENTS.ROLE_ADDED]: PartyRoleChangedPayload;
88
99
  [PARTY_EVENTS.ROLE_REMOVED]: PartyRoleChangedPayload;
89
100
  [PARTY_EVENTS.USER_LINKED]: PartyUserLinkedPayload;
101
+ [PARTY_EVENTS.CONSENT_RECORDED]: PartyConsentRecordedPayload;
90
102
  [PARTY_EVENTS.EXTERNAL_REF_ATTACHED]: PartyExternalRefAttachedPayload;
91
103
  [PARTY_EVENTS.ARCHIVED]: PartyLifecyclePayload;
92
104
  [PARTY_EVENTS.RESTORED]: PartyLifecyclePayload;
@@ -147,6 +159,19 @@ declare const PartyUserLinked: PartyEventDefinition<z.ZodObject<{
147
159
  partyId: z.ZodString;
148
160
  userId: z.ZodString;
149
161
  }, z.core.$strip>>;
162
+ declare const PartyConsentRecorded: PartyEventDefinition<z.ZodObject<{
163
+ partyId: z.ZodString;
164
+ channel: z.ZodEnum<{
165
+ email: "email";
166
+ phone: "phone";
167
+ }>;
168
+ value: z.ZodString;
169
+ status: z.ZodEnum<{
170
+ granted: "granted";
171
+ withdrawn: "withdrawn";
172
+ }>;
173
+ source: z.ZodOptional<z.ZodString>;
174
+ }, z.core.$strip>>;
150
175
  declare const PartyExternalRefAttached: PartyEventDefinition<z.ZodObject<{
151
176
  partyId: z.ZodString;
152
177
  sourceModel: z.ZodString;
@@ -163,6 +188,24 @@ declare const PartyMerged: PartyEventDefinition<z.ZodObject<{
163
188
  targetId: z.ZodString;
164
189
  absorbedKeys: z.ZodNumber;
165
190
  }, z.core.$strip>>;
191
+ declare const PartyRelationshipChanged: PartyEventDefinition<z.ZodObject<{
192
+ partyId: z.ZodString;
193
+ relationshipId: z.ZodString;
194
+ kind: z.ZodEnum<{
195
+ associate: "associate";
196
+ director: "director";
197
+ employee: "employee";
198
+ key_management: "key_management";
199
+ lessor: "lessor";
200
+ member: "member";
201
+ partner_in_firm: "partner_in_firm";
202
+ shareholder: "shareholder";
203
+ }>;
204
+ change: z.ZodEnum<{
205
+ added: "added";
206
+ ended: "ended";
207
+ }>;
208
+ }, z.core.$strip>>;
166
209
  declare const partyEventDefinitions: ReadonlyArray<PartyEventDefinition>;
167
210
  //#endregion
168
211
  //#region src/domain/ports.d.ts
@@ -192,16 +235,10 @@ interface PartyLogger {
192
235
  declare function createEvent<T>(type: string, payload: T, ctx?: PartyContext, meta?: Partial<EventMeta>): DomainEvent<T>;
193
236
  //#endregion
194
237
  //#region src/events/in-process-bus.d.ts
195
- declare class InProcessPartyBus implements EventTransport {
196
- readonly name = "in-process-party";
197
- private subs;
198
- private readonly logger;
238
+ declare class InProcessPartyBus extends InProcessEventBus {
199
239
  constructor(options?: {
200
- logger?: PartyLogger | undefined;
240
+ logger?: PartyLogger;
201
241
  });
202
- publish(event: DomainEvent): Promise<void>;
203
- subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
204
- close(): Promise<void>;
205
242
  }
206
243
  //#endregion
207
244
  //#region src/events/dispatch.d.ts
@@ -235,4 +272,4 @@ declare class PartyEventDispatcher {
235
272
  */
236
273
  declare function flushPending(dispatcher: PartyEventDispatcher, queue: DomainEvent[], logger?: PartyLogger): Promise<void>;
237
274
  //#endregion
238
- export { InProcessPartyBus, PARTY_EVENTS, PENDING_EVENTS, PartyArchived, PartyCreated, PartyCreatedPayload, PartyEventDefinition, PartyEventDispatcher, PartyEventDispatcherOptions, PartyEventName, PartyEventPayloads, PartyExternalRefAttached, PartyExternalRefAttachedPayload, PartyLifecyclePayload, PartyMerged, PartyMergedPayload, PartyRestored, PartyRoleAdded, PartyRoleChangedPayload, PartyRoleRemoved, PartyUpdated, PartyUpdatedPayload, PartyUserLinked, PartyUserLinkedPayload, createEvent, flushPending, partyEventDefinitions };
275
+ export { InProcessPartyBus, PARTY_EVENTS, PENDING_EVENTS, PartyArchived, PartyConsentRecorded, PartyConsentRecordedPayload, PartyCreated, PartyCreatedPayload, PartyEventDefinition, PartyEventDispatcher, PartyEventDispatcherOptions, PartyEventName, PartyEventPayloads, PartyExternalRefAttached, PartyExternalRefAttachedPayload, PartyLifecyclePayload, PartyMerged, PartyMergedPayload, PartyRelationshipChanged, PartyRestored, PartyRoleAdded, PartyRoleChangedPayload, PartyRoleRemoved, PartyUpdated, PartyUpdatedPayload, PartyUserLinked, PartyUserLinkedPayload, createEvent, flushPending, partyEventDefinitions };
package/dist/events.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
- import { createEvent as createEvent$1, matchEventPattern } from "@classytic/primitives/events";
2
+ import { createEvent as createEvent$1 } from "@classytic/primitives/events";
3
+ import { InProcessEventBus } from "@classytic/primitives/event-infra";
3
4
  //#region src/events/event-constants.ts
4
5
  /** PACKAGE_RULES §12: `package:resource.verb`. Emit ONLY these catalog names. */
5
6
  const PARTY_EVENTS = {
@@ -8,10 +9,12 @@ const PARTY_EVENTS = {
8
9
  ROLE_ADDED: "party:party.role_added",
9
10
  ROLE_REMOVED: "party:party.role_removed",
10
11
  USER_LINKED: "party:party.user_linked",
12
+ CONSENT_RECORDED: "party:party.consent_recorded",
11
13
  EXTERNAL_REF_ATTACHED: "party:party.external_ref_attached",
12
14
  ARCHIVED: "party:party.archived",
13
15
  RESTORED: "party:party.restored",
14
- MERGED: "party:party.merged"
16
+ MERGED: "party:party.merged",
17
+ RELATIONSHIP_CHANGED: "party:party.relationship_changed"
15
18
  };
16
19
  //#endregion
17
20
  //#region src/events/event-catalog.ts
@@ -70,6 +73,13 @@ const userLinkedSchema = z.object({
70
73
  partyId: z.string(),
71
74
  userId: z.string()
72
75
  });
76
+ const consentRecordedSchema = z.object({
77
+ partyId: z.string(),
78
+ channel: z.enum(["email", "phone"]),
79
+ value: z.string(),
80
+ status: z.enum(["granted", "withdrawn"]),
81
+ source: z.string().optional()
82
+ });
73
83
  const externalRefSchema = z.object({
74
84
  partyId: z.string(),
75
85
  sourceModel: z.string(),
@@ -106,6 +116,11 @@ const PartyUserLinked = definePartyEvent({
106
116
  description: "An auth user was linked to a party (1:many).",
107
117
  zodSchema: userLinkedSchema
108
118
  });
119
+ const PartyConsentRecorded = definePartyEvent({
120
+ name: PARTY_EVENTS.CONSENT_RECORDED,
121
+ description: "A marketing-consent decision was recorded against one contact channel.",
122
+ zodSchema: consentRecordedSchema
123
+ });
109
124
  const PartyExternalRefAttached = definePartyEvent({
110
125
  name: PARTY_EVENTS.EXTERNAL_REF_ATTACHED,
111
126
  description: "An external-store reference was attached to a party (facet link).",
@@ -126,16 +141,38 @@ const PartyMerged = definePartyEvent({
126
141
  description: "A duplicate party was merged into a survivor; the source becomes a redirect.",
127
142
  zodSchema: mergedSchema
128
143
  });
144
+ const relationshipChangedSchema = z.object({
145
+ partyId: z.string(),
146
+ relationshipId: z.string(),
147
+ kind: z.enum([
148
+ "shareholder",
149
+ "director",
150
+ "key_management",
151
+ "partner_in_firm",
152
+ "member",
153
+ "employee",
154
+ "lessor",
155
+ "associate"
156
+ ]),
157
+ change: z.enum(["added", "ended"])
158
+ });
159
+ const PartyRelationshipChanged = definePartyEvent({
160
+ name: PARTY_EVENTS.RELATIONSHIP_CHANGED,
161
+ description: "A dated relationship of the party (shareholder, director, lessor, …) was added or ended.",
162
+ zodSchema: relationshipChangedSchema
163
+ });
129
164
  const partyEventDefinitions = [
130
165
  PartyCreated,
131
166
  PartyUpdated,
132
167
  PartyRoleAdded,
133
168
  PartyRoleRemoved,
134
169
  PartyUserLinked,
170
+ PartyConsentRecorded,
135
171
  PartyExternalRefAttached,
136
172
  PartyArchived,
137
173
  PartyRestored,
138
- PartyMerged
174
+ PartyMerged,
175
+ PartyRelationshipChanged
139
176
  ];
140
177
  //#endregion
141
178
  //#region src/events/helpers.ts
@@ -158,37 +195,24 @@ function createEvent(type, payload, ctx, meta) {
158
195
  //#region src/events/in-process-bus.ts
159
196
  /**
160
197
  * In-process event bus — default fallback when no `eventTransport` is given to
161
- * `createParty`. Structurally identical to arc's `MemoryEventTransport`;
162
- * pattern-matching delegates to primitives' `matchEventPattern` (PACKAGE_RULES
163
- * §13). Handler errors are swallowed-and-logged — emission never blocks writes.
198
+ * `createParty`.
199
+ *
200
+ * A thin subclass of `@classytic/primitives/event-infra`'s shared
201
+ * `InProcessEventBus`. Prior semantics preserved: glob matching via
202
+ * `matchEventPattern`, per-handler error isolation, idempotent `close()`.
203
+ * Party historically SWALLOWED handler errors when no logger was supplied —
204
+ * that default is preserved by passing `logger: null` unless the host injects
205
+ * a `PartyLogger`, whose structured `error(msg, meta)` slot is bridged onto
206
+ * the shared error-logger contract.
164
207
  */
165
- var InProcessPartyBus = class {
166
- name = "in-process-party";
167
- subs = [];
168
- logger;
208
+ var InProcessPartyBus = class extends InProcessEventBus {
169
209
  constructor(options) {
170
- this.logger = options?.logger;
171
- }
172
- async publish(event) {
173
- const matching = this.subs.filter((s) => matchEventPattern(s.pattern, event.type));
174
- for (const sub of matching) try {
175
- await sub.handler(event);
176
- } catch (err) {
177
- this.logger?.error?.(`[party] event handler error [${event.type}]`, { error: err instanceof Error ? err.message : String(err) });
178
- }
179
- }
180
- async subscribe(pattern, handler) {
181
- const sub = {
182
- pattern,
183
- handler
184
- };
185
- this.subs.push(sub);
186
- return () => {
187
- this.subs = this.subs.filter((s) => s !== sub);
188
- };
189
- }
190
- async close() {
191
- this.subs = [];
210
+ const partyLogger = options?.logger;
211
+ super({
212
+ name: "in-process-party",
213
+ logLabel: "party",
214
+ logger: partyLogger?.error ? { error: (message, ...args) => partyLogger.error?.(message, { args }) } : null
215
+ });
192
216
  }
193
217
  };
194
218
  //#endregion
@@ -211,7 +235,9 @@ var PartyEventDispatcher = class {
211
235
  return this.transport.publish(event);
212
236
  }
213
237
  subscribe(pattern, handler) {
214
- return this.transport.subscribe(pattern, handler);
238
+ const subscribe = this.transport.subscribe?.bind(this.transport);
239
+ if (!subscribe) throw new Error("party: configured event transport does not support subscribe");
240
+ return subscribe(pattern, handler);
215
241
  }
216
242
  /**
217
243
  * Route a domain event with full §P8 discipline. Reads the pending queue and
@@ -252,4 +278,4 @@ async function flushPending(dispatcher, queue, logger) {
252
278
  }
253
279
  }
254
280
  //#endregion
255
- export { InProcessPartyBus, PARTY_EVENTS, PENDING_EVENTS, PartyArchived, PartyCreated, PartyEventDispatcher, PartyExternalRefAttached, PartyMerged, PartyRestored, PartyRoleAdded, PartyRoleRemoved, PartyUpdated, PartyUserLinked, createEvent, flushPending, partyEventDefinitions };
281
+ export { InProcessPartyBus, PARTY_EVENTS, PENDING_EVENTS, PartyArchived, PartyConsentRecorded, PartyCreated, PartyEventDispatcher, PartyExternalRefAttached, PartyMerged, PartyRelationshipChanged, PartyRestored, PartyRoleAdded, PartyRoleRemoved, PartyUpdated, PartyUserLinked, createEvent, flushPending, partyEventDefinitions };