@genesislcap/pbc-notify-ui 15.3.0 → 15.3.1

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.
@@ -415,27 +415,6 @@
415
415
  }
416
416
  ]
417
417
  },
418
- {
419
- "kind": "javascript-module",
420
- "path": "src/styles/scrollbar.styles.ts",
421
- "declarations": [
422
- {
423
- "kind": "variable",
424
- "name": "scrollbarStyles",
425
- "default": "css`\n ::-webkit-scrollbar {\n width: calc((var(--base-height-multiplier) + var(--design-unit)) * 1px);\n }\n\n ::-webkit-scrollbar-track {\n background: var(--neutral-layer-1);\n }\n\n ::-webkit-scrollbar-thumb {\n background: var(--neutral-fill-rest);\n }\n`"
426
- }
427
- ],
428
- "exports": [
429
- {
430
- "kind": "js",
431
- "name": "scrollbarStyles",
432
- "declaration": {
433
- "name": "scrollbarStyles",
434
- "module": "src/styles/scrollbar.styles.ts"
435
- }
436
- }
437
- ]
438
- },
439
418
  {
440
419
  "kind": "javascript-module",
441
420
  "path": "src/utils/eventDetail.ts",
@@ -757,6 +736,27 @@
757
736
  }
758
737
  ]
759
738
  },
739
+ {
740
+ "kind": "javascript-module",
741
+ "path": "src/styles/scrollbar.styles.ts",
742
+ "declarations": [
743
+ {
744
+ "kind": "variable",
745
+ "name": "scrollbarStyles",
746
+ "default": "css`\n ::-webkit-scrollbar {\n width: calc((var(--base-height-multiplier) + var(--design-unit)) * 1px);\n }\n\n ::-webkit-scrollbar-track {\n background: var(--neutral-layer-1);\n }\n\n ::-webkit-scrollbar-thumb {\n background: var(--neutral-fill-rest);\n }\n`"
747
+ }
748
+ ],
749
+ "exports": [
750
+ {
751
+ "kind": "js",
752
+ "name": "scrollbarStyles",
753
+ "declaration": {
754
+ "name": "scrollbarStyles",
755
+ "module": "src/styles/scrollbar.styles.ts"
756
+ }
757
+ }
758
+ ]
759
+ },
760
760
  {
761
761
  "kind": "javascript-module",
762
762
  "path": "src/components/foundation-inbox/inbox.styles.ts",
@@ -1 +1 @@
1
- {"version":3,"file":"inbox-base.d.ts","sourceRoot":"","sources":["../../../../../src/components/foundation-inbox/inbox-base/inbox-base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAEL,UAAU,EAKX,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAQ,cAAc,EAAc,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAKvF,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAmB,MAAM,iCAAiC,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,WAAW,EACX,kBAAkB,EACnB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAIrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,6BAA6B,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAiBpG,qBAAa,mBAAoB,SAAQ,cAAc;IAC/C,IAAI,EAAE,IAAI,CAAC;IACR,OAAO,EAAE,OAAO,CAAC;IAEZ,YAAY,EAAE,YAAY,CAAC;IACjB,YAAY,EAAE,sBAAsB,CAAC;IAC7D,OAAO,CAAC,aAAa,CAAe;IACxB,OAAO,CAAC,MAAM,CAAe;IAC7B,YAAY,EAAE,KAAK,EAAE,CAAM;IAC3B,UAAU,EAAE,OAAO,CAAS;IAExC;;;;;;;OAOG;IACS,WAAW,EAAE,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,SAAS,CAAa;IAEtF;;;OAGG;IACwB,kBAAkB,EAAE,OAAO,CAAS;IAE/D;;;OAGG;IACwB,aAAa,EAAE,OAAO,CAAS;IAE1D;;;OAGG;IACwB,eAAe,EAAE,OAAO,CAAS;IAE5D;;;OAGG;IACwB,cAAc,EAAE,OAAO,CAAS;IAE3D;;;;OAIG;IACS,YAAY,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAa;IAE9D,WAAW,EAAE,WAAW,CAAC;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAM;IAEd,eAAe,EAAE,eAAe,CAAC;IACtC,SAAS,EAAE,YAAY,EAAE,CAAM;IAC/B,eAAe,EAAE,YAAY,EAAE,CAAM;IAE7B,YAAY,EAAE,kBAAkB,CAAC;IACzC,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAM;IACzE,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC,CAAM;IAClF,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,CAAM;IAI/F,OAAO,CAAC,oBAAoB,CAAK;IAErB,cAAc,EAAE,MAAM,CAAQ;IAC9B,gBAAgB,EAAE,MAAM,CAAQ;IAChC,eAAe,EAAE,MAAM,CAAQ;IAE/B,eAAe,EAAE,MAAM,CAAQ;IAC/B,mBAAmB,EAAE,6BAA6B,CAAQ;IAC1D,0BAA0B,EAAE,MAAM,CAAQ;IAC1C,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;IACpD,WAAW,EAAE,QAAQ,CAAuB;IAE5C,mBAAmB,EAAE,MAAM,CAAQ;IACnC,iBAAiB,EAAE,MAAM,CAAQ;IAEjC,wBAAwB,EAAE,UAAU,CAAC;IACrC,OAAO,EAAE,OAAO,CAAS;IACzB,aAAa,EAAE,KAAK,GAAG,MAAM,CAAU;IACvC,oBAAoB,EAAE,OAAO,CAAS;IAEtC,YAAY,QAAM;IAEvB,IAAI,EAAE,IAAI,CAAC;IAEZ,iBAAiB;IAqBvB,oBAAoB;IAMpB,iBAAiB,GAAI;;KAAS,UAI5B;IAEF,mBAAmB;IAKb,eAAe,CAAC,QAAQ,EAAE,QAAQ;IA4BxC,aAAa,gBAA2C;IAExD,cAAc;IAId,gBAAgB,uBAAiD;IAEjE,6BAA6B,MAAsD;IAEnF,oBAAoB;IAgEpB,oBAAoB;IAKpB,qBAAqB;IAWrB,WAAW;IAaX,YAAY,CAAC,OAAO,EAAE,MAAM;IAI5B,gBAAgB,CAAC,QAAQ,KAAA;IASzB,gBAAgB;IA2BV,oBAAoB;YAiBZ,oBAAoB;IAoDlC,OAAO,CAAC,UAAU;IAIlB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS;IAI5D,oBAAoB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO;IAIrD,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO;IAI3E,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO;IAIzE,OAAO,CAAC,oBAAoB;IAQ5B,sBAAsB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO;IAI/E,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,uBAAuB;IAOzB,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa;IA+C5D,oBAAoB,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK;IA2CzD,oBAAoB,CAAC,UAAU,CAAC,EAAE,MAAM;YAmBhC,oBAAoB;IAkClC,sBAAsB;IAMtB,6BAA6B,CAAC,IAAI,CAAC,EAAE,MAAM;CAG5C"}
1
+ {"version":3,"file":"inbox-base.d.ts","sourceRoot":"","sources":["../../../../../src/components/foundation-inbox/inbox-base/inbox-base.ts"],"names":[],"mappings":"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"}
@@ -15,7 +15,17 @@ export interface NotifyRoute {
15
15
  * A topic "supports" a channel when any route exists for that
16
16
  * TOPIC_MATCH + GATEWAY_ID (admin-configured marker rows, entity-blank).
17
17
  * A specific user has that channel enabled when a route additionally
18
- * exists scoped to ENTITY_ID_TYPE=USER_NAME, ENTITY_ID=<username>.
18
+ * exists scoped to ENTITY_ID_TYPE=SELF, ENTITY_ID=<username>.
19
+ *
20
+ * The per-user route is created with ENTITY_ID_TYPE=SELF (not USER_NAME) so
21
+ * delivery resolves to the notification's SENDER (the subscriber whose rule
22
+ * fired) rather than to a fixed named user. When several users subscribe to
23
+ * the same shared topic — each getting their own rule + route — a USER_NAME
24
+ * route makes every subscriber's rule deliver to every subscriber's route
25
+ * (an N×N fan-out: N alerts/emails per user). With SELF, each fired rule
26
+ * delivers only to its own owner, so delivery scales linearly (one per user).
27
+ * ENTITY_ID is still stored as the username purely as a per-user marker for
28
+ * subscribe idempotency / unsubscribe; the dispatcher ignores it for SELF.
19
29
  */
20
30
  export interface NotifyRouteService {
21
31
  getAllRoutes(channel: NotifyChannel): Promise<NotifyRoute[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"notify-route.service.d.ts","sourceRoot":"","sources":["../../../src/services/notify-route.service.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,OAAO,CAAC;AAO9C,MAAM,WAAW,WAAW;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAsBD;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,aAAa,CACX,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC/B,eAAe,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/F,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAuGD,eAAO,MAAM,kBAAkB,0EAE9B,CAAC"}
1
+ {"version":3,"file":"notify-route.service.d.ts","sourceRoot":"","sources":["../../../src/services/notify-route.service.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,OAAO,CAAC;AAO9C,MAAM,WAAW,WAAW;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAsBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,aAAa,CACX,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC/B,eAAe,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/F,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AA0GD,eAAO,MAAM,kBAAkB,0EAE9B,CAAC"}
@@ -300,7 +300,8 @@ export class FoundationInboxBase extends GenesisElement {
300
300
  });
301
301
  }
302
302
  isOwnRoute(route, username) {
303
- return !!username && route.ENTITY_ID_TYPE === 'USER_NAME' && route.ENTITY_ID === username;
303
+ // Per-user subscription routes are created as SELF with ENTITY_ID=<username>
304
+ return !!username && route.ENTITY_ID_TYPE === 'SELF' && route.ENTITY_ID === username;
304
305
  }
305
306
  findSubscribedRule(template) {
306
307
  return this.rules.find((rule) => rule.NAME === template.NAME);
@@ -31,7 +31,7 @@ class NotifyRouteServiceImpl {
31
31
  }
32
32
  findUserRoute(channel, topic, username) {
33
33
  return __awaiter(this, void 0, void 0, function* () {
34
- const criteriaMatch = `TOPIC_MATCH == '${this.escape(topic)}' && ENTITY_ID == '${this.escape(username)}' && ENTITY_ID_TYPE == 'USER_NAME'`;
34
+ const criteriaMatch = `TOPIC_MATCH == '${this.escape(topic)}' && ENTITY_ID == '${this.escape(username)}' && ENTITY_ID_TYPE == 'SELF'`;
35
35
  const [route] = yield this.queryRoutes(channel, criteriaMatch);
36
36
  return route !== null && route !== void 0 ? route : null;
37
37
  });
@@ -51,7 +51,10 @@ class NotifyRouteServiceImpl {
51
51
  GATEWAY_ID: GATEWAY_ID[channel],
52
52
  ROUTE_ENABLED: true,
53
53
  ENTITY_ID: username,
54
- ENTITY_ID_TYPE: 'USER_NAME',
54
+ // SELF (not USER_NAME): delivery resolves to the fired rule's SENDER (the
55
+ // subscriber), avoiding the N×N fan-out across co-subscribers of a shared
56
+ // topic. ENTITY_ID is kept as a per-user marker only; ignored for SELF.
57
+ ENTITY_ID_TYPE: 'SELF',
55
58
  EXCLUDE_SENDER: false,
56
59
  },
57
60
  IGNORE_WARNINGS: true,
@@ -270,7 +270,17 @@ declare interface NotifyRoute {
270
270
  * A topic "supports" a channel when any route exists for that
271
271
  * TOPIC_MATCH + GATEWAY_ID (admin-configured marker rows, entity-blank).
272
272
  * A specific user has that channel enabled when a route additionally
273
- * exists scoped to ENTITY_ID_TYPE=USER_NAME, ENTITY_ID=<username>.
273
+ * exists scoped to ENTITY_ID_TYPE=SELF, ENTITY_ID=<username>.
274
+ *
275
+ * The per-user route is created with ENTITY_ID_TYPE=SELF (not USER_NAME) so
276
+ * delivery resolves to the notification's SENDER (the subscriber whose rule
277
+ * fired) rather than to a fixed named user. When several users subscribe to
278
+ * the same shared topic — each getting their own rule + route — a USER_NAME
279
+ * route makes every subscriber's rule deliver to every subscriber's route
280
+ * (an N×N fan-out: N alerts/emails per user). With SELF, each fired rule
281
+ * delivers only to its own owner, so delivery scales linearly (one per user).
282
+ * ENTITY_ID is still stored as the username purely as a per-user marker for
283
+ * subscribe idempotency / unsubscribe; the dispatcher ignores it for SELF.
274
284
  */
275
285
  declare interface NotifyRouteService {
276
286
  getAllRoutes(channel: NotifyChannel): Promise<NotifyRoute[]>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/pbc-notify-ui",
3
3
  "description": "Genesis PBC Notify UI",
4
- "version": "15.3.0",
4
+ "version": "15.3.1",
5
5
  "license": "SEE LICENSE IN license.txt",
6
6
  "workspaces": [
7
7
  "client"
@@ -83,30 +83,30 @@
83
83
  "@commitlint/format": "^19.0.3",
84
84
  "@genesiscommunitysuccess/cep-fast-plugin": "5.0.3",
85
85
  "@genesiscommunitysuccess/custom-elements-lsp": "5.0.3",
86
- "@genesislcap/design-system-configurator": "15.3.0",
87
- "@genesislcap/eslint-config": "15.3.0",
88
- "@genesislcap/eslint-stylelint-builder": "15.3.0",
89
- "@genesislcap/foundation-testing": "15.3.0",
90
- "@genesislcap/genx": "15.3.0",
91
- "@genesislcap/prettier-config": "15.3.0",
92
- "@genesislcap/stylelint-config": "15.3.0",
93
- "@genesislcap/vite-builder": "15.3.0",
94
- "@genesislcap/webpack-builder": "15.3.0",
86
+ "@genesislcap/design-system-configurator": "15.3.1",
87
+ "@genesislcap/eslint-config": "15.3.1",
88
+ "@genesislcap/eslint-stylelint-builder": "15.3.1",
89
+ "@genesislcap/foundation-testing": "15.3.1",
90
+ "@genesislcap/genx": "15.3.1",
91
+ "@genesislcap/prettier-config": "15.3.1",
92
+ "@genesislcap/stylelint-config": "15.3.1",
93
+ "@genesislcap/vite-builder": "15.3.1",
94
+ "@genesislcap/webpack-builder": "15.3.1",
95
95
  "dayjs": "^1.11.7"
96
96
  },
97
97
  "dependencies": {
98
- "@genesislcap/foundation-comms": "15.3.0",
99
- "@genesislcap/foundation-criteria": "15.3.0",
100
- "@genesislcap/foundation-entity-management": "15.3.0",
101
- "@genesislcap/foundation-forms": "15.3.0",
102
- "@genesislcap/foundation-layout": "15.3.0",
103
- "@genesislcap/foundation-logger": "15.3.0",
104
- "@genesislcap/foundation-notifications": "15.3.0",
105
- "@genesislcap/foundation-ui": "15.3.0",
106
- "@genesislcap/foundation-utils": "15.3.0",
107
- "@genesislcap/rapid-design-system": "15.3.0",
108
- "@genesislcap/rapid-grid-pro": "15.3.0",
109
- "@genesislcap/web-core": "15.3.0",
98
+ "@genesislcap/foundation-comms": "15.3.1",
99
+ "@genesislcap/foundation-criteria": "15.3.1",
100
+ "@genesislcap/foundation-entity-management": "15.3.1",
101
+ "@genesislcap/foundation-forms": "15.3.1",
102
+ "@genesislcap/foundation-layout": "15.3.1",
103
+ "@genesislcap/foundation-logger": "15.3.1",
104
+ "@genesislcap/foundation-notifications": "15.3.1",
105
+ "@genesislcap/foundation-ui": "15.3.1",
106
+ "@genesislcap/foundation-utils": "15.3.1",
107
+ "@genesislcap/rapid-design-system": "15.3.1",
108
+ "@genesislcap/rapid-grid-pro": "15.3.1",
109
+ "@genesislcap/web-core": "15.3.1",
110
110
  "lodash.debounce": "^4.0.8",
111
111
  "rxjs": "^7.5.4"
112
112
  },
@@ -114,5 +114,5 @@
114
114
  "access": "public"
115
115
  },
116
116
  "customElements": "dist/custom-elements.json",
117
- "gitHead": "a8d2fa3336de2307fb9b82d4be1d4939ac847d14"
117
+ "gitHead": "1c3a33f7d56acec166f832b9610e83343a8873e6"
118
118
  }
@@ -413,7 +413,8 @@ export class FoundationInboxBase extends GenesisElement {
413
413
  }
414
414
 
415
415
  private isOwnRoute(route: NotifyRoute, username: string): boolean {
416
- return !!username && route.ENTITY_ID_TYPE === 'USER_NAME' && route.ENTITY_ID === username;
416
+ // Per-user subscription routes are created as SELF with ENTITY_ID=<username>
417
+ return !!username && route.ENTITY_ID_TYPE === 'SELF' && route.ENTITY_ID === username;
417
418
  }
418
419
 
419
420
  findSubscribedRule(template: RuleTemplate): Rule | undefined {
@@ -45,7 +45,17 @@ const DELETE_EVENT: Record<NotifyChannel, string> = {
45
45
  * A topic "supports" a channel when any route exists for that
46
46
  * TOPIC_MATCH + GATEWAY_ID (admin-configured marker rows, entity-blank).
47
47
  * A specific user has that channel enabled when a route additionally
48
- * exists scoped to ENTITY_ID_TYPE=USER_NAME, ENTITY_ID=<username>.
48
+ * exists scoped to ENTITY_ID_TYPE=SELF, ENTITY_ID=<username>.
49
+ *
50
+ * The per-user route is created with ENTITY_ID_TYPE=SELF (not USER_NAME) so
51
+ * delivery resolves to the notification's SENDER (the subscriber whose rule
52
+ * fired) rather than to a fixed named user. When several users subscribe to
53
+ * the same shared topic — each getting their own rule + route — a USER_NAME
54
+ * route makes every subscriber's rule deliver to every subscriber's route
55
+ * (an N×N fan-out: N alerts/emails per user). With SELF, each fired rule
56
+ * delivers only to its own owner, so delivery scales linearly (one per user).
57
+ * ENTITY_ID is still stored as the username purely as a per-user marker for
58
+ * subscribe idempotency / unsubscribe; the dispatcher ignores it for SELF.
49
59
  */
50
60
  export interface NotifyRouteService {
51
61
  getAllRoutes(channel: NotifyChannel): Promise<NotifyRoute[]>;
@@ -72,7 +82,7 @@ class NotifyRouteServiceImpl implements NotifyRouteService {
72
82
  topic: string,
73
83
  username: string,
74
84
  ): Promise<NotifyRoute | null> {
75
- const criteriaMatch = `TOPIC_MATCH == '${this.escape(topic)}' && ENTITY_ID == '${this.escape(username)}' && ENTITY_ID_TYPE == 'USER_NAME'`;
85
+ const criteriaMatch = `TOPIC_MATCH == '${this.escape(topic)}' && ENTITY_ID == '${this.escape(username)}' && ENTITY_ID_TYPE == 'SELF'`;
76
86
  const [route] = await this.queryRoutes(channel, criteriaMatch);
77
87
  return route ?? null;
78
88
  }
@@ -96,7 +106,10 @@ class NotifyRouteServiceImpl implements NotifyRouteService {
96
106
  GATEWAY_ID: GATEWAY_ID[channel],
97
107
  ROUTE_ENABLED: true,
98
108
  ENTITY_ID: username,
99
- ENTITY_ID_TYPE: 'USER_NAME',
109
+ // SELF (not USER_NAME): delivery resolves to the fired rule's SENDER (the
110
+ // subscriber), avoiding the N×N fan-out across co-subscribers of a shared
111
+ // topic. ENTITY_ID is kept as a per-user marker only; ignored for SELF.
112
+ ENTITY_ID_TYPE: 'SELF',
100
113
  EXCLUDE_SENDER: false,
101
114
  },
102
115
  IGNORE_WARNINGS: true,