@happyvertical/smrt-messages 0.57.36 → 0.57.37

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.
@@ -3,13 +3,13 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-messages",
6
- "packageVersion": "0.57.36",
6
+ "packageVersion": "0.57.37",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "852d4d67dfc56d9d57fd1b85198c0abc26c6a34148c7a9a03236de07c2bac205",
11
- "packageJson": "826c0ed1a35cee969197117e6d10d6da908b6cda2000a2794c6f98a90766e065",
12
- "agents": "194fd38365dc8f586c953ecda2f6883e9c1758e8b134a5952e7e9bfe3a30b365"
10
+ "manifest": "454797a2a63820c0e041d81545eca0c967b9af3a33d6c7efa967b15c795db7bd",
11
+ "packageJson": "f84f2d3536753878e53c62acea6b63e1d3ca806fe2c4473135e41235abcc3660",
12
+ "agents": "75703e49b75d6a74d5f018e8700344a59a970a85f55ee1a5d443f3e99eaca96d"
13
13
  },
14
14
  "exports": [
15
15
  ".",
@@ -6924,19 +6924,22 @@
6924
6924
  "name": "workspaceId",
6925
6925
  "type": "text",
6926
6926
  "required": false,
6927
- "columnType": "TEXT"
6927
+ "columnType": "TEXT",
6928
+ "description": "The identifier of the connected workspace."
6928
6929
  },
6929
6930
  {
6930
6931
  "name": "workspaceName",
6931
6932
  "type": "text",
6932
6933
  "required": false,
6933
- "columnType": "TEXT"
6934
+ "columnType": "TEXT",
6935
+ "description": "The name of the connected workspace."
6934
6936
  },
6935
6937
  {
6936
6938
  "name": "botUserId",
6937
6939
  "type": "text",
6938
6940
  "required": false,
6939
- "columnType": "TEXT"
6941
+ "columnType": "TEXT",
6942
+ "description": "The bot user your application posts as in this workspace."
6940
6943
  }
6941
6944
  ],
6942
6945
  "relationships": [],
@@ -7334,50 +7337,58 @@
7334
7337
  "name": "channelId",
7335
7338
  "type": "text",
7336
7339
  "required": false,
7337
- "columnType": "TEXT"
7340
+ "columnType": "TEXT",
7341
+ "description": "The identifier of the channel this message is in."
7338
7342
  },
7339
7343
  {
7340
7344
  "name": "channelName",
7341
7345
  "type": "text",
7342
7346
  "required": false,
7343
- "columnType": "TEXT"
7347
+ "columnType": "TEXT",
7348
+ "description": "The name of the channel this message was posted in."
7344
7349
  },
7345
7350
  {
7346
7351
  "name": "slackTs",
7347
7352
  "type": "text",
7348
7353
  "required": false,
7349
- "columnType": "TEXT"
7354
+ "columnType": "TEXT",
7355
+ "description": "The workspace's own reference for this message."
7350
7356
  },
7351
7357
  {
7352
7358
  "name": "slackThreadTs",
7353
7359
  "type": "text",
7354
7360
  "required": false,
7355
- "columnType": "TEXT"
7361
+ "columnType": "TEXT",
7362
+ "description": "The workspace's own reference for the thread this message belongs to."
7356
7363
  },
7357
7364
  {
7358
7365
  "name": "reactions",
7359
7366
  "type": "text",
7360
7367
  "required": false,
7361
- "columnType": "TEXT"
7368
+ "columnType": "TEXT",
7369
+ "description": "The reactions people added to this message."
7362
7370
  },
7363
7371
  {
7364
7372
  "name": "isEdited",
7365
7373
  "type": "boolean",
7366
7374
  "required": true,
7367
7375
  "columnType": "BOOLEAN",
7368
- "default": false
7376
+ "default": false,
7377
+ "description": "Whether this message was edited after posting."
7369
7378
  },
7370
7379
  {
7371
7380
  "name": "messageType",
7372
7381
  "type": "text",
7373
7382
  "required": false,
7374
- "columnType": "TEXT"
7383
+ "columnType": "TEXT",
7384
+ "description": "The kind of message, such as one from a person or a bot."
7375
7385
  },
7376
7386
  {
7377
7387
  "name": "blocks",
7378
7388
  "type": "text",
7379
7389
  "required": false,
7380
- "columnType": "TEXT"
7390
+ "columnType": "TEXT",
7391
+ "description": "The rich layout of the message as the workspace stores it."
7381
7392
  }
7382
7393
  ],
7383
7394
  "relationships": [
@@ -12184,7 +12195,7 @@
12184
12195
  "polymorphicAssociations": 0,
12185
12196
  "uuidColumns": 96
12186
12197
  },
12187
- "agentDoc": "# @happyvertical/smrt-messages\n\nMulti-channel messaging with STI hierarchies for both messages and accounts. Credential encryption via smrt-secrets.\n\n## STI Hierarchies\n\n**Messages** (share `messages` table):\n- `Message` (base): accountId, personaId, endpointId, correlationId, threadId, subject, body, fromAddress, toAddresses (JSON), sendStatus (draft/sending/sent/failed), retryCount\n- `Email`: messageId (RFC 822), inReplyTo, ccAddresses, bccAddresses, htmlBody, textBody, folderId, labels, headers\n- `Tweet`: tweetId, retweetCount, likeCount, mediaUrls, hashtags, mentions\n- `SlackMessage`: channelId, slackTs, slackThreadTs, reactions, blocks\n\n**Accounts** (share `accounts` table):\n- `Account` (base): channelType, providerType, public configuration,\n credentialSecretId, isActive, lastSyncAt, deprecated sensitive settings\n- `EmailAccount`, `TwitterAccount`, `SlackAccount`, `ZulipAccount`,\n `TelegramAccount`: provider-specific identity/sender behavior\n\n## Persona messaging\n\n- `MessagingEndpoint`: tenant-owned, write-only destination JSON with masked\n display helper.\n- `PersonaMessageRoute`: persona → account + endpoint, selected by purpose and\n descending priority.\n- `PersonaMessagingService`: persists and sends through an enabled route.\n- Provider registry: public setup descriptors + optional sender factory. Keep\n channel (`sms`) separate from provider (`twilio`).\n- Permissions: `messages.send`, `messages.manage-routes`,\n `messages.manage-credentials`.\n- `MessagingSettingsService` is the permissioned server boundary;\n its host-supplied `resolvePersonaTenantId` proves cross-package ownership.\n `MessagingSettingsPanel` is the callback-driven Svelte surface.\n- Account, endpoint, and route generated surfaces are read-only. Do not add\n generated mutations around the settings service or make secret fields writable.\n\n## In-app notifications (`UserNotification`)\n\nThe in-app channel: one stored row per person, with read state.\n`user_notifications`: `tenantId` (required), `recipientUserId`\n(`@crossPackageRef` smrt-users:User, uuid), `kind`, `title`, `body`, `href`,\n`severity` (info/success/warning/error), `sourceRef`, `occurredAt`, `readAt`,\n`dismissedAt`. Conflict identity `(tenant_id, recipient_user_id, source_ref)`.\n\n- `UserNotificationService` is the only access path: `notify()` /\n `notifyMany()` (dedupe on `sourceRef`, existing row returned untouched;\n a unique ref is generated when omitted), `listForUser()` / `countUnread()`\n across explicit `tenantIds` (each read under `withTenant`), `markRead()`,\n `dismiss()` (also marks read), `markAllRead()`. Every write filters on the\n recipient, so another user's id matches nothing.\n- Generated REST/MCP/CLI are off (`api`/`mcp`/`cli: false`): a tenant-scoped\n list would expose every member's rows. Hosts expose their own routes that\n pass the signed-in user's id, never a request-chosen one.\n- Hosts decide who is told (e.g. `SocialPost.createdByUserId` for a failed\n post). New table: consumers run `db:migrate`.\n\n## Credential Security\n\nAccount credentials stored via tenant-bound `credentialSecretId` →\nsmrt-secrets. Use `setCredentials()`/`getCredentials()` — never store passwords\ndirectly. Credential descriptor schemas contain field definitions, never values.\n\n## Send Lifecycle\n\n`message.send()`: resolves account → creates provider sender → updates sendStatus. Retry support with `maxRetries` budget.\n`EmailSender` attaches the message's stored `Attachment` rows (read through\n`Attachment.readContent()`, under the message's tenant context) plus\n`SendEmailOptions.attachments` bytes; an unreadable or file-less row fails the\nsend with the error on `sendError`, never a silent drop (#3808).\n`PersonaMessagingService.send({ attachments })` accepts them on email routes only.\n\n## Provider entry points (bundle boundary, #1979)\n\nThe package root is provider-neutral: models, collections, services,\npermissions, and the provider registry carry **zero provider-SDK weight**.\nProvider SDK wrappers (`@happyvertical/email`, `@happyvertical/messages`) are\nreachable only through explicit entry points, imported once at server startup:\n\n```ts\nimport '@happyvertical/smrt-messages/providers/email'; // smtp/imap/pop3/gmail\nimport '@happyvertical/smrt-messages/providers/slack';\nimport '@happyvertical/smrt-messages/providers/twitter';\nimport '@happyvertical/smrt-messages/providers/all'; // all of the above\n```\n\n- Without the matching entry, `EmailAccount.createClient()` (send + mailbox\n sync) throws an actionable error and `SlackSender`/`TweetSender` return a\n failure result naming the entry to import. Telegram and Zulip are\n fetch-based and always work from the root.\n- Builtin registry definitions stay metadata-only (setup fields for UIs); the\n entries upgrade them with `createEmailClient`/`createMessageClient`/\n `createSender` hooks. Never import a provider SDK from any module reachable\n from `src/index.ts` — the consumer bundle gate (`packages/bundle-gate`)\n fails CI when one becomes reachable.\n- `Attachment.readContent()` loads `@happyvertical/files` through core's\n `importOptionalDependency` boundary and keeps its null-on-failure contract\n in builds where the SDK is absent.\n\n## Gotchas\n\n- **Manifest before decorators**: every decorated model imports\n `../__smrt-register__.js`, and `package.json#sideEffects` lists\n `./src/__smrt-register__.ts`. Without both, the library build dropped or\n reordered the self-registration, so dist classes registered with only their\n decorated fields and could adopt smrt-ledgers' same-named `Account` (#3098).\n- **`Account` is not unique**: smrt-ledgers also declares `Account` (on\n `ledger_accounts`). Resolve by constructor or qualified name; the\n coexistence tests (`ledger-account-identity-*`, and the PostgreSQL lane\n `pnpm test:postgres`) load both packages in both orders.\n- **STI `_meta_type`**: qualified format `@happyvertical/smrt-messages:Email`\n- **JSON fields**: all address/metadata fields are JSON strings with `getX()`/`setX()` helpers\n- **RFC 822 threading**: Email uses `inReplyTo`/`messageId`/`references` — manual management required\n- **Attachment.messageId**: use this field (not `emailId`); old getter/setter mapped via deprecation wrapper\n- **Optional tenancy**: `@TenantScoped({ mode: 'optional' })` on Message, Account, Attachment\n- **Required tenancy**: endpoints and persona routes are always tenant scoped\n- **Secrets are write-only**: never serialize credentials or endpoint.address to an app\n\n## Intake byte snapshots\n\n`EmailAccount.readIntakeMessage(providerLookup, maxBytes, imapIdentity?)` is the authorized host seam for\nopt-in ingestion. It copies full-message attachment bytes from the registered\nemail provider and fails when only attachment metadata is available; it never\nreads provider-supplied paths or advances sync checkpoints. Keep this path\nprovider-neutral and exclude arbitrary headers/credentials from its snapshot.\nIMAP lookup must include folder/UIDVALIDITY/UID verification; sender Message-ID\nis a lookup hint, never the durable delivery identity.\n",
12198
+ "agentDoc": "# @happyvertical/smrt-messages\n\nMulti-channel messaging with STI hierarchies for both messages and accounts. Credential encryption via smrt-secrets.\n\n## STI Hierarchies\n\n**Messages** (share `messages` table):\n- `Message` (base): accountId, personaId, endpointId, correlationId, threadId, subject, body, fromAddress, toAddresses (JSON), sendStatus (draft/sending/sent/failed), retryCount\n- `Email`: messageId (RFC 822), inReplyTo, ccAddresses, bccAddresses, htmlBody, textBody, folderId, labels, headers\n- `Tweet`: tweetId, retweetCount, likeCount, mediaUrls, hashtags, mentions\n- `SlackMessage`: channelId, slackTs, slackThreadTs, reactions, blocks\n\n**Accounts** (share `accounts` table):\n- `Account` (base): channelType, providerType, public configuration,\n credentialSecretId, isActive, lastSyncAt, deprecated sensitive settings\n- `EmailAccount`, `TwitterAccount`, `SlackAccount`, `ZulipAccount`,\n `TelegramAccount`: provider-specific identity/sender behavior\n\n## Persona messaging\n\n- `MessagingEndpoint`: tenant-owned, write-only destination JSON with masked\n display helper.\n- `PersonaMessageRoute`: persona → account + endpoint, selected by purpose and\n descending priority.\n- `PersonaMessagingService`: persists and sends through an enabled route.\n- Provider registry: public setup descriptors + optional sender factory. Keep\n channel (`sms`) separate from provider (`twilio`).\n- Permissions: `messages.send`, `messages.manage-routes`,\n `messages.manage-credentials`.\n- `MessagingSettingsService` is the permissioned server boundary;\n its host-supplied `resolvePersonaTenantId` proves cross-package ownership.\n `MessagingSettingsPanel` is the callback-driven Svelte surface.\n- Account, endpoint, and route generated surfaces are read-only. Do not add\n generated mutations around the settings service or make secret fields writable.\n- **Recipe `messages.slack`** (`src/recipes.ts`, help in `src/help/slack.md`): lists Slack messages and workspaces beside the Mailbox and Notifications recipes; workspaces stay read-only and sending goes through the senders, not generated routes. Fields it shows carry `@field({ description })` in plain words; keep them when editing the models.\n\n## In-app notifications (`UserNotification`)\n\nThe in-app channel: one stored row per person, with read state.\n`user_notifications`: `tenantId` (required), `recipientUserId`\n(`@crossPackageRef` smrt-users:User, uuid), `kind`, `title`, `body`, `href`,\n`severity` (info/success/warning/error), `sourceRef`, `occurredAt`, `readAt`,\n`dismissedAt`. Conflict identity `(tenant_id, recipient_user_id, source_ref)`.\n\n- `UserNotificationService` is the only access path: `notify()` /\n `notifyMany()` (dedupe on `sourceRef`, existing row returned untouched;\n a unique ref is generated when omitted), `listForUser()` / `countUnread()`\n across explicit `tenantIds` (each read under `withTenant`), `markRead()`,\n `dismiss()` (also marks read), `markAllRead()`. Every write filters on the\n recipient, so another user's id matches nothing.\n- Generated REST/MCP/CLI are off (`api`/`mcp`/`cli: false`): a tenant-scoped\n list would expose every member's rows. Hosts expose their own routes that\n pass the signed-in user's id, never a request-chosen one.\n- Hosts decide who is told (e.g. `SocialPost.createdByUserId` for a failed\n post). New table: consumers run `db:migrate`.\n\n## Credential Security\n\nAccount credentials stored via tenant-bound `credentialSecretId` →\nsmrt-secrets. Use `setCredentials()`/`getCredentials()` — never store passwords\ndirectly. Credential descriptor schemas contain field definitions, never values.\n\n## Send Lifecycle\n\n`message.send()`: resolves account → creates provider sender → updates sendStatus. Retry support with `maxRetries` budget.\n`EmailSender` attaches the message's stored `Attachment` rows (read through\n`Attachment.readContent()`, under the message's tenant context) plus\n`SendEmailOptions.attachments` bytes; an unreadable or file-less row fails the\nsend with the error on `sendError`, never a silent drop (#3808).\n`PersonaMessagingService.send({ attachments })` accepts them on email routes only.\n\n## Provider entry points (bundle boundary, #1979)\n\nThe package root is provider-neutral: models, collections, services,\npermissions, and the provider registry carry **zero provider-SDK weight**.\nProvider SDK wrappers (`@happyvertical/email`, `@happyvertical/messages`) are\nreachable only through explicit entry points, imported once at server startup:\n\n```ts\nimport '@happyvertical/smrt-messages/providers/email'; // smtp/imap/pop3/gmail\nimport '@happyvertical/smrt-messages/providers/slack';\nimport '@happyvertical/smrt-messages/providers/twitter';\nimport '@happyvertical/smrt-messages/providers/all'; // all of the above\n```\n\n- Without the matching entry, `EmailAccount.createClient()` (send + mailbox\n sync) throws an actionable error and `SlackSender`/`TweetSender` return a\n failure result naming the entry to import. Telegram and Zulip are\n fetch-based and always work from the root.\n- Builtin registry definitions stay metadata-only (setup fields for UIs); the\n entries upgrade them with `createEmailClient`/`createMessageClient`/\n `createSender` hooks. Never import a provider SDK from any module reachable\n from `src/index.ts` — the consumer bundle gate (`packages/bundle-gate`)\n fails CI when one becomes reachable.\n- `Attachment.readContent()` loads `@happyvertical/files` through core's\n `importOptionalDependency` boundary and keeps its null-on-failure contract\n in builds where the SDK is absent.\n\n## Gotchas\n\n- **Manifest before decorators**: every decorated model imports\n `../__smrt-register__.js`, and `package.json#sideEffects` lists\n `./src/__smrt-register__.ts`. Without both, the library build dropped or\n reordered the self-registration, so dist classes registered with only their\n decorated fields and could adopt smrt-ledgers' same-named `Account` (#3098).\n- **`Account` is not unique**: smrt-ledgers also declares `Account` (on\n `ledger_accounts`). Resolve by constructor or qualified name; the\n coexistence tests (`ledger-account-identity-*`, and the PostgreSQL lane\n `pnpm test:postgres`) load both packages in both orders.\n- **STI `_meta_type`**: qualified format `@happyvertical/smrt-messages:Email`\n- **JSON fields**: all address/metadata fields are JSON strings with `getX()`/`setX()` helpers\n- **RFC 822 threading**: Email uses `inReplyTo`/`messageId`/`references` — manual management required\n- **Attachment.messageId**: use this field (not `emailId`); old getter/setter mapped via deprecation wrapper\n- **Optional tenancy**: `@TenantScoped({ mode: 'optional' })` on Message, Account, Attachment\n- **Required tenancy**: endpoints and persona routes are always tenant scoped\n- **Secrets are write-only**: never serialize credentials or endpoint.address to an app\n\n## Intake byte snapshots\n\n`EmailAccount.readIntakeMessage(providerLookup, maxBytes, imapIdentity?)` is the authorized host seam for\nopt-in ingestion. It copies full-message attachment bytes from the registered\nemail provider and fails when only attachment metadata is available; it never\nreads provider-supplied paths or advances sync checkpoints. Keep this path\nprovider-neutral and exclude arbitrary headers/credentials from its snapshot.\nIMAP lookup must include folder/UIDVALIDITY/UID verification; sender Message-ID\nis a lookup hint, never the durable delivery identity.\n",
12188
12199
  "recipes": [
12189
12200
  {
12190
12201
  "id": "messages.mailbox",
@@ -12403,6 +12414,239 @@
12403
12414
  "Needs a server because its package depends on @happyvertical/smrt-profiles, @happyvertical/smrt-secrets, @happyvertical/smrt-tenancy, @happyvertical/smrt-users, which do not build for a browser (#3617, #3624, #3626, #3627)."
12404
12415
  ]
12405
12416
  }
12417
+ },
12418
+ {
12419
+ "id": "messages.slack",
12420
+ "className": "SlackRecipe",
12421
+ "label": "Slack",
12422
+ "summary": "Read Slack messages from your connected workspaces.",
12423
+ "synonyms": [
12424
+ "slack",
12425
+ "slack messages",
12426
+ "slack channels",
12427
+ "workspace chat",
12428
+ "team chat"
12429
+ ],
12430
+ "models": [
12431
+ "@happyvertical/smrt-messages:SlackMessage",
12432
+ "@happyvertical/smrt-messages:SlackAccount"
12433
+ ],
12434
+ "nav": [
12435
+ {
12436
+ "label": "Slack messages",
12437
+ "model": "@happyvertical/smrt-messages:SlackMessage",
12438
+ "icon": "folder",
12439
+ "description": "Read messages from your connected workspaces by channel.",
12440
+ "key": "slack-messages",
12441
+ "noun": "message"
12442
+ },
12443
+ {
12444
+ "label": "Slack workspaces",
12445
+ "model": "@happyvertical/smrt-messages:SlackAccount",
12446
+ "icon": "users",
12447
+ "description": "The workspaces your application is connected to.",
12448
+ "noun": "workspace"
12449
+ }
12450
+ ],
12451
+ "requires": [],
12452
+ "group": {
12453
+ "id": "messages",
12454
+ "label": "Messaging",
12455
+ "summary": "Choose email and personal updates independently."
12456
+ },
12457
+ "section": {
12458
+ "id": "messages",
12459
+ "label": "Messaging",
12460
+ "icon": "folder",
12461
+ "description": "Read email and keep up with updates addressed to you."
12462
+ },
12463
+ "options": {
12464
+ "@happyvertical/smrt-messages:SlackMessage": {
12465
+ "fields": {
12466
+ "channelName": {
12467
+ "label": "Channel",
12468
+ "order": 1
12469
+ },
12470
+ "body": {
12471
+ "label": "Message",
12472
+ "order": 2
12473
+ },
12474
+ "threadId": {
12475
+ "label": "Thread",
12476
+ "order": 3
12477
+ },
12478
+ "sendStatus": {
12479
+ "label": "Sent status",
12480
+ "order": 4
12481
+ },
12482
+ "accountId": {
12483
+ "label": "Workspace",
12484
+ "order": 5
12485
+ },
12486
+ "fromName": {
12487
+ "label": "From",
12488
+ "visibility": "advanced"
12489
+ },
12490
+ "fromAddress": {
12491
+ "visibility": "advanced"
12492
+ },
12493
+ "toAddresses": {
12494
+ "visibility": "advanced"
12495
+ },
12496
+ "subject": {
12497
+ "visibility": "advanced"
12498
+ },
12499
+ "date": {
12500
+ "visibility": "advanced"
12501
+ },
12502
+ "isRead": {
12503
+ "visibility": "advanced"
12504
+ },
12505
+ "isFlagged": {
12506
+ "visibility": "advanced"
12507
+ },
12508
+ "isEdited": {
12509
+ "label": "Edited",
12510
+ "visibility": "advanced"
12511
+ },
12512
+ "messageType": {
12513
+ "label": "Message kind",
12514
+ "visibility": "advanced"
12515
+ },
12516
+ "reactions": {
12517
+ "visibility": "advanced"
12518
+ },
12519
+ "hasAttachments": {
12520
+ "visibility": "advanced"
12521
+ },
12522
+ "channelId": {
12523
+ "visibility": "advanced"
12524
+ },
12525
+ "sentAt": {
12526
+ "visibility": "advanced"
12527
+ },
12528
+ "sendError": {
12529
+ "visibility": "advanced"
12530
+ },
12531
+ "scheduledSendAt": {
12532
+ "visibility": "advanced"
12533
+ },
12534
+ "inReplyToMessageId": {
12535
+ "label": "Replying to",
12536
+ "visibility": "advanced"
12537
+ },
12538
+ "personaId": {
12539
+ "visibility": "advanced"
12540
+ },
12541
+ "endpointId": {
12542
+ "visibility": "advanced"
12543
+ },
12544
+ "retryCount": {
12545
+ "visibility": "hidden"
12546
+ },
12547
+ "maxRetries": {
12548
+ "visibility": "hidden"
12549
+ },
12550
+ "size": {
12551
+ "visibility": "hidden"
12552
+ },
12553
+ "correlationId": {
12554
+ "visibility": "hidden"
12555
+ },
12556
+ "slackTs": {
12557
+ "visibility": "hidden"
12558
+ },
12559
+ "slackThreadTs": {
12560
+ "visibility": "hidden"
12561
+ },
12562
+ "blocks": {
12563
+ "visibility": "hidden"
12564
+ },
12565
+ "metadata": {
12566
+ "visibility": "hidden"
12567
+ },
12568
+ "tenantId": {
12569
+ "visibility": "hidden"
12570
+ },
12571
+ "created_at": {
12572
+ "help": "When this message was first recorded."
12573
+ },
12574
+ "updated_at": {
12575
+ "help": "When this message record was last changed."
12576
+ }
12577
+ }
12578
+ },
12579
+ "@happyvertical/smrt-messages:SlackAccount": {
12580
+ "fields": {
12581
+ "name": {
12582
+ "order": 1
12583
+ },
12584
+ "workspaceName": {
12585
+ "label": "Workspace",
12586
+ "order": 2
12587
+ },
12588
+ "isActive": {
12589
+ "label": "Enabled",
12590
+ "order": 3
12591
+ },
12592
+ "lastSyncAt": {
12593
+ "label": "Last checked",
12594
+ "order": 4
12595
+ },
12596
+ "workspaceId": {
12597
+ "visibility": "advanced"
12598
+ },
12599
+ "credentialSecretId": {
12600
+ "visibility": "hidden"
12601
+ },
12602
+ "settings": {
12603
+ "visibility": "hidden"
12604
+ },
12605
+ "botUserId": {
12606
+ "label": "Bot user",
12607
+ "visibility": "advanced"
12608
+ },
12609
+ "providerType": {
12610
+ "visibility": "advanced"
12611
+ },
12612
+ "channelType": {
12613
+ "visibility": "advanced"
12614
+ },
12615
+ "configuration": {
12616
+ "visibility": "advanced"
12617
+ },
12618
+ "tenantId": {
12619
+ "visibility": "hidden"
12620
+ },
12621
+ "created_at": {
12622
+ "help": "When this workspace connection was first recorded."
12623
+ },
12624
+ "updated_at": {
12625
+ "help": "When this workspace connection was last changed."
12626
+ }
12627
+ }
12628
+ }
12629
+ },
12630
+ "help": {
12631
+ "markdown": "## Overview\n\nSlack shows the messages from the workspaces your application is connected to,\nin one place beside your email. Each message keeps the channel it was posted\nin, the thread it belongs to, the reactions people added and whether it was\nedited, so you can catch up on a conversation without opening Slack.\n\n## Tasks\n\nWorkspaces are connected by your application administrator on the server.\nMessages arrive from those connected workspaces; here you read them and see\nwhere each one stands.\n\n### Find a message in a channel\n\n1. Open Slack messages.\n2. Look at the **{field:SlackMessage.channelName}** to find the channel you want.\n3. Open a message to read the **{field:SlackMessage.body}** and see who it is from.\n\n### Follow a thread\n\n1. Open a message that is part of a conversation.\n2. Use its **{field:SlackMessage.threadId}** to find the other messages in the same thread.\n3. Read them oldest first; the **{field:SlackMessage.reactions}** show how people responded.\n\n### See whether a message was changed\n\n1. Open the message.\n2. Check **{field:SlackMessage.isEdited}** to see whether it was edited after it was posted.\n\n### Draft a message\n\n1. Open Slack messages and choose **New**.\n2. Type the **{field:SlackMessage.channelName}** it is for and the **{field:SlackMessage.body}**.\n3. Save. This records the draft; your application sends it through the connected workspace, and the **{field:SlackMessage.sendStatus}** shows where it stands.\n\n### See which workspaces are connected\n\n1. Open Slack workspaces.\n2. Look at the **{field:SlackAccount.workspaceName}** and whether it is **{field:SlackAccount.isActive}**.\n3. Check **{field:SlackAccount.lastSyncAt}** to see when messages were last collected. Connecting or changing a workspace is done by your application administrator, not here.\n",
12632
+ "fieldRefs": [
12633
+ "SlackAccount.isActive",
12634
+ "SlackAccount.lastSyncAt",
12635
+ "SlackAccount.workspaceName",
12636
+ "SlackMessage.body",
12637
+ "SlackMessage.channelName",
12638
+ "SlackMessage.isEdited",
12639
+ "SlackMessage.reactions",
12640
+ "SlackMessage.sendStatus",
12641
+ "SlackMessage.threadId"
12642
+ ]
12643
+ },
12644
+ "demo": {
12645
+ "mode": "server",
12646
+ "reasons": [
12647
+ "Needs a server because its package depends on @happyvertical/smrt-profiles, @happyvertical/smrt-secrets, @happyvertical/smrt-tenancy, @happyvertical/smrt-users, which do not build for a browser (#3617, #3624, #3626, #3627)."
12648
+ ]
12649
+ }
12406
12650
  }
12407
12651
  ],
12408
12652
  "browser": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-messages",
3
- "version": "0.57.36",
3
+ "version": "0.57.37",
4
4
  "smrtJsdoc": "strict",
5
5
  "description": "Unified multi-channel messaging with STI-based hierarchies",
6
6
  "type": "module",
@@ -58,18 +58,18 @@
58
58
  "./dist/svelte/index.js"
59
59
  ],
60
60
  "dependencies": {
61
- "@happyvertical/email": "^0.109.0",
62
- "@happyvertical/files": "^0.109.0",
63
- "@happyvertical/logger": "^0.109.0",
64
- "@happyvertical/messages": "^0.109.0",
65
- "@happyvertical/smrt-core": "0.57.36",
66
- "@happyvertical/smrt-types": "0.57.36",
67
- "@happyvertical/smrt-secrets": "0.57.36",
68
- "@happyvertical/smrt-tenancy": "0.57.36",
69
- "@happyvertical/smrt-ui": "0.57.36",
70
- "@happyvertical/smrt-users": "0.57.36",
71
- "@happyvertical/sql": "^0.109.0",
72
- "@happyvertical/utils": "^0.109.0"
61
+ "@happyvertical/email": "^0.110.0",
62
+ "@happyvertical/files": "^0.110.0",
63
+ "@happyvertical/logger": "^0.110.0",
64
+ "@happyvertical/messages": "^0.110.0",
65
+ "@happyvertical/smrt-core": "0.57.37",
66
+ "@happyvertical/smrt-types": "0.57.37",
67
+ "@happyvertical/smrt-secrets": "0.57.37",
68
+ "@happyvertical/smrt-tenancy": "0.57.37",
69
+ "@happyvertical/smrt-ui": "0.57.37",
70
+ "@happyvertical/smrt-users": "0.57.37",
71
+ "@happyvertical/sql": "^0.110.0",
72
+ "@happyvertical/utils": "^0.110.0"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "@happyvertical/encryption": "*",
@@ -84,8 +84,8 @@
84
84
  }
85
85
  },
86
86
  "devDependencies": {
87
- "@happyvertical/smrt-ledgers": "0.57.36",
88
- "@happyvertical/smrt-vitest": "0.57.36",
87
+ "@happyvertical/smrt-ledgers": "0.57.37",
88
+ "@happyvertical/smrt-vitest": "0.57.37",
89
89
  "@sveltejs/package": "^2.5.8",
90
90
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
91
91
  "@types/node": "24.13.6",