@ai-matrx/messaging 0.6.0 → 0.8.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
@@ -1,5 +1,55 @@
1
1
  # Changelog — `@ai-matrx/messaging`
2
2
 
3
+ ## 0.8.0 — 2026-09-07
4
+
5
+ **Every conversation in the first real inbox was titled with a raw UUID.** The second live defect
6
+ of the adoption session, found by looking at the screen rather than at a test.
7
+
8
+ ### Fixed
9
+
10
+ - **The participant profile is NESTED under `user`, and the top-level `id` is the participant
11
+ ROW.** The live `get_dm_conversations_with_details` aggregate is
12
+ `{ id, user_id, role, is_muted, last_read_at, user: { user_id, email, display_name, avatar_url } }`.
13
+ This package read `display_name` / `email` / `avatar_url` off the TOP level, found nothing, and
14
+ fell back to the user id — so a direct conversation's title, its avatar, and every participant
15
+ name rendered as a UUID. The nested profile is now the source, `user_id` is the identity, and
16
+ the bare `id` fallback survives only for an aggregate that carries neither — because here `id`
17
+ belongs to a different entity, and using it as a user id attributes a message to a row key.
18
+ - A regression test built from the verbatim live aggregate; it fails against 0.7.0.
19
+
20
+ ### Consumer action (C28)
21
+
22
+ None. Names and avatars simply appear now.
23
+
24
+ ## 0.7.0 — 2026-09-07
25
+
26
+ 🚨 **Every RPC in this package was calling the wrong schema, so every read failed against the
27
+ live database.** Found the first time the package ran a real query — the honest verification the
28
+ work order named, which is also why no source gate could have caught it.
29
+
30
+ ### Fixed
31
+
32
+ - **RPCs are called on `public`; only the TABLES are in `communication`.** Matrx Main's messaging
33
+ tables moved into `communication` during the schema reorg, and the five auth-checked SECURITY
34
+ DEFINER functions stayed in `public` where PostgREST exposes them by default and where every
35
+ existing caller and GRANT already pointed. This package sent both to `communication`, so the
36
+ inbox read, the direct-conversation get-or-create, the unread count, the profile read and the
37
+ participant check all failed with PGRST202 — *"Could not find the function
38
+ communication.get_dm_conversations_with_details … in the schema cache"*. The whole product was
39
+ dead against the real database while 129 tests and a packed-tarball canary stayed green,
40
+ because a fake PostgREST answers whatever schema it is asked for.
41
+ - New constant `MESSAGING_RPC_SCHEMA` (`"public"`), exported and asserted by the tarball canary
42
+ beside `MESSAGING_SCHEMA`, with the verification query in a comment above it. A regression test
43
+ proves the RPC lands on `public` and the table write on `communication`; it fails when the two
44
+ are collapsed.
45
+
46
+ **The lesson, recorded where the next agent will read it:** "verified against the live schema by
47
+ inspection" is not verification. One query would have found this on day one.
48
+
49
+ ### Consumer action (C28)
50
+
51
+ None. Nothing in the API changed — the package simply works against the real database now.
52
+
3
53
  ## 0.6.0 — 2026-09-07
4
54
 
5
55
  **The two entries did not agree on their own branded ids.** A consumer that minted a
package/README.md CHANGED
@@ -314,7 +314,8 @@ One canonical schema, in Matrx Main, under the platform's DB conventions:
314
314
 
315
315
  | | |
316
316
  |---|---|
317
- | Schema | `communication` (never `public`) |
317
+ | Table schema | `communication` (never `public`) |
318
+ | RPC schema | `public` — the SECURITY DEFINER functions stayed there through the schema reorg. The two DIFFER, deliberately; collapsing them fails every read with PGRST202 |
318
319
  | Tables | `dm_conversations`, `dm_conversation_participants`, `dm_messages` |
319
320
  | RPCs | `dm_get_or_create_direct_conversation`, `get_dm_conversations_with_details`, `get_dm_user_info`, `get_dm_unread_count`, `is_dm_participant` |
320
321
 
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  MESSAGING_EVENTS: () => MESSAGING_EVENTS,
24
+ MESSAGING_RPC_SCHEMA: () => MESSAGING_RPC_SCHEMA,
24
25
  MESSAGING_SCHEMA: () => MESSAGING_SCHEMA,
25
26
  MessagingError: () => MessagingError,
26
27
  RPCS: () => RPCS,
@@ -797,11 +798,13 @@ function projectParticipants(value, operation) {
797
798
  for (const entry of value) {
798
799
  if (typeof entry !== "object" || entry === null) continue;
799
800
  const record = entry;
800
- const id = str(record, "user_id") ?? str(record, "id");
801
+ const nested = typeof record["user"] === "object" && record["user"] !== null ? record["user"] : {};
802
+ const id = str(record, "user_id") ?? str(nested, "user_id") ?? str(record, "id");
801
803
  if (id === null) continue;
802
804
  summaries.push(
803
805
  projectUserSummary({
804
806
  ...record,
807
+ ...nested,
805
808
  user_id: id
806
809
  })
807
810
  );
@@ -1540,6 +1543,7 @@ function formatLastSeen(lastSeenMs, now = Date.now()) {
1540
1543
 
1541
1544
  // src/core/repository.ts
1542
1545
  var MESSAGING_SCHEMA = "communication";
1546
+ var MESSAGING_RPC_SCHEMA = "public";
1543
1547
  var TABLES = {
1544
1548
  conversations: "dm_conversations",
1545
1549
  participants: "dm_conversation_participants",
@@ -1574,6 +1578,7 @@ function createMessagingRepository(options) {
1574
1578
  ...options.now !== void 0 ? { now: options.now } : {}
1575
1579
  });
1576
1580
  const db = () => client.schema(MESSAGING_SCHEMA);
1581
+ const rpcDb = () => client.schema(MESSAGING_RPC_SCHEMA);
1577
1582
  async function withSessionRetry(operation, run) {
1578
1583
  try {
1579
1584
  return await run();
@@ -1591,7 +1596,7 @@ function createMessagingRepository(options) {
1591
1596
  }
1592
1597
  }
1593
1598
  async function rpc(fn, args, operation) {
1594
- const { data, error } = await db().rpc(fn, args);
1599
+ const { data, error } = await rpcDb().rpc(fn, args);
1595
1600
  if (error !== null) throw normalizeMessagingError(error, operation);
1596
1601
  return data;
1597
1602
  }