@robono/server 0.17.0 → 0.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/CHANGELOG.md +4 -0
- package/NOTIFICATIONS.md +28 -1
- package/README.md +9 -2
- package/SBOM.spdx.json +8 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/managed-notifications.d.ts +15 -0
- package/dist/managed-notifications.d.ts.map +1 -0
- package/dist/managed-notifications.js +37 -0
- package/dist/managed-notifications.js.map +1 -0
- package/dist/messaging-push-worker.d.ts +3 -0
- package/dist/messaging-push-worker.d.ts.map +1 -0
- package/dist/messaging-push-worker.js +35 -0
- package/dist/messaging-push-worker.js.map +1 -0
- package/dist/messenger-check.d.ts +13 -0
- package/dist/messenger-check.d.ts.map +1 -0
- package/dist/messenger-check.js +25 -0
- package/dist/messenger-check.js.map +1 -0
- package/dist/messenger-setup-test.d.ts +3 -0
- package/dist/messenger-setup-test.d.ts.map +1 -0
- package/dist/messenger-setup-test.js +18 -0
- package/dist/messenger-setup-test.js.map +1 -0
- package/dist/messenger.d.ts +5 -1
- package/dist/messenger.d.ts.map +1 -1
- package/dist/messenger.js +15 -9
- package/dist/messenger.js.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 0.18.0 — release candidate
|
|
2
|
+
|
|
3
|
+
Robono-managed Apple, Google and browser notifications through the combined route, automatic website worker, and a safe connection checker. Legacy self-hosted notification settings remain supported.
|
|
4
|
+
|
|
1
5
|
# Changelog
|
|
2
6
|
|
|
3
7
|
## 0.17.0 — 2026-11-03
|
package/NOTIFICATIONS.md
CHANGED
|
@@ -1,4 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Managed message notifications
|
|
2
|
+
|
|
3
|
+
Requires @robono/server 0.18.0 and the complete website or Expo messenger 0.4.0, with the matching Robono service release.
|
|
4
|
+
|
|
5
|
+
1. In Robono **Your app → Message notifications**, connect the platforms your app uses. The website needs its HTTPS origin and chat-page path. iPhone needs your Apple Team ID, APNs Key ID, .p8 private key, Bundle ID and development/production choice. Android needs your Firebase service-account JSON key.
|
|
6
|
+
2. Use `createRobonoMessengerServer` with your existing `authenticate` and `authorize` callbacks. Managed notifications are the default. Include `notifications.register-device` in your authenticated-user permission policy; it has no conversation ID. Mount both GET and POST on the same route. GET serves only the public browser worker; POST still enforces sign-in and origin checks.
|
|
7
|
+
3. Use `mountRobonoMessenger` on the website or `createExpoMessenger` plus `ExpoMessenger` on phones. The Account screen offers **Enable notifications**. Permission is never requested on mount. Previously granted permissions reconnect automatically.
|
|
8
|
+
4. Await `messenger.signOut()` before revoking the host session. Dispose old connections when changing accounts. Synchronize blocked relationships, removed membership and suspended accounts with Robono so background alerts respect current access.
|
|
9
|
+
5. Run `robono-messenger-check`, then send between two real test accounts with the recipient app in the background and tap the alert. Provider acceptance is not a delivery guarantee.
|
|
10
|
+
|
|
11
|
+
Robono supplies the private device database, delivery process, retries and browser signing keys. Customers do not need a notification webhook receiver, SQL tables, scheduled worker or AWS account. Set `notifications:false` on the server to deliberately disable notification registration, or on the complete messenger connection to manage notifications yourself. Lower-level custom interfaces can use the exported browser or Expo notification connector.
|
|
12
|
+
|
|
13
|
+
## Platform requirements
|
|
14
|
+
|
|
15
|
+
- **iPhone app:** enable Push Notifications in Apple signing, then rebuild. Development builds use APNs sandbox; TestFlight and App Store use production. Robono cannot use its own app credentials for your app.
|
|
16
|
+
- **Android app:** include your Firebase `google-services.json` in the build; enable Cloud Messaging and install/configure the Expo notifications native dependency. The service-account private key is different from google-services.json and must never be bundled in the phone app. Give it only the permission to send messages for the intended Firebase project.
|
|
17
|
+
- **Website:** use HTTPS and a same-origin combined route. Allow `worker-src 'self'` in your content security policy. The route sends `Service-Worker-Allowed: /robono-notifications/`; preserve that header in your proxy. Robono uses this dedicated scope, preserving an existing site-wide PWA worker. Reserve that scope for Robono. iPhone web alerts require an installed Home Screen web app. Browser notification permission must be granted by the user.
|
|
18
|
+
- **Foreground presentation:** the phone app retains ownership of its global notification handler. Use `withMessagingNotificationPresentation` when composing a custom handler. Do not replace handlers belonging to calling or another feature.
|
|
19
|
+
|
|
20
|
+
Alerts contain generic text and conversation/message identifiers, not message content or attachments. A tap rechecks the current session and conversation access. Provider keys are encrypted and never returned by the setup API. Devices expire after 90 days without registration; completed delivery diagnostics are retained for 30 days. OS permissions, Focus modes, battery restrictions and network conditions can prevent or delay delivery.
|
|
21
|
+
|
|
22
|
+
The recommended setup above supersedes the customer-run worker below. Existing self-hosted configurations continue to work unchanged.
|
|
23
|
+
|
|
24
|
+
## Advanced: legacy self-hosted delivery
|
|
25
|
+
|
|
26
|
+
### Legacy installation
|
|
2
27
|
|
|
3
28
|
This installation uses your app's Apple/Google credentials. Robono's own app
|
|
4
29
|
credentials cannot send alerts for a customer's app. Chat in an open screen works
|
|
@@ -147,3 +172,5 @@ account switching, revoked chat access, muted conversations and token rotation.
|
|
|
147
172
|
Do not label notification setup complete merely because open-chat messages work
|
|
148
173
|
or Apple/Google accepted a request. The local automated tests use simulated provider
|
|
149
174
|
responses; they do not prove that a customer's credentials are provisioned correctly.
|
|
175
|
+
|
|
176
|
+
Browser notifications use one account per browser profile and the reserved `/robono-notifications/` worker scope on your website. Keep your messaging route on the same HTTPS origin as the chat. An existing root PWA worker is preserved; a different app already using this exact reserved scope must use a separate origin. Call the supplied `signOut()` before revoking the user session. The SDK clears the browser’s active notification account even if server removal fails.
|
package/README.md
CHANGED
|
@@ -371,8 +371,7 @@ access, search and quoted history respect the same boundary.
|
|
|
371
371
|
A `messaging.message_created` webhook now includes `notification_muted`. Continue
|
|
372
372
|
synchronizing messages, but do not show a banner, play a sound or send a push when
|
|
373
373
|
this flag is true. Its value is refreshed on webhook retries. Do not treat mute as
|
|
374
|
-
loss of membership or stop delivery.
|
|
375
|
-
honor this field in its notification sender.
|
|
374
|
+
loss of membership or stop delivery. Robono-managed notifications honor this field and recheck current access. If you use your own notification sender, it must honor this field too.
|
|
376
375
|
|
|
377
376
|
## Optional photo and video screening
|
|
378
377
|
|
|
@@ -380,3 +379,11 @@ Connected networks can use Robono-hosted Amazon screening with their existing
|
|
|
380
379
|
Processing API key, including apps with their own storage. See [screening setup](https://robono.com/docs#screening)
|
|
381
380
|
for the private-upload flow, prices, spending controls and pending-result handling.
|
|
382
381
|
This addition is not in server 0.16.0; update to the screening release before use.
|
|
382
|
+
|
|
383
|
+
## Managed notifications and connection checks
|
|
384
|
+
|
|
385
|
+
`createRobonoMessengerServer` uses Robono-managed Apple, Google and browser delivery by default. Mount both GET and POST on your combined route. Connect your app’s credentials once in the private portal; no customer notification database or scheduled worker is required. See NOTIFICATIONS.md. Keep `notifications.register-device` in your authenticated-user authorization policy and continue synchronizing account suspensions and relationship changes.
|
|
386
|
+
|
|
387
|
+
Run `robono-messenger-check --help` for the automated setup checks. It runs locally, uses a test user’s session, and checks access protection, chat settings, contacts and notification setup without sending the token to the Robono portal. It does not replace testing your own account permission rules.
|
|
388
|
+
|
|
389
|
+
Optional text safety is enforced by the service on ordinary sends and edits; existing callers need no extra screening request. Features & preview → Text safety and spam contains the single configuration, price acceptance and spending cap. Threat/abuse screening costs $0.50 per 1,000 units of up to 1,000 characters, rounded up per message. Text, captions and polls are covered; voice/video speech is not transcribed. The same send identity survives a transient failure; after a 30-second cooldown it can retry up to three attempts, charging only a completed successful check. Detection can make mistakes. Blocked text is privately reviewable by the project owner/admin for 30 days. An allow decision permits a retry; it never sends content on the user’s behalf.
|
package/SBOM.spdx.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"spdxVersion": "SPDX-2.3",
|
|
3
3
|
"dataLicense": "CC0-1.0",
|
|
4
4
|
"SPDXID": "SPDXRef-DOCUMENT",
|
|
5
|
-
"name": "@robono/server@0.
|
|
6
|
-
"documentNamespace": "http://spdx.org/spdxdocs/@robono%2fserver-0.
|
|
5
|
+
"name": "@robono/server@0.18.0",
|
|
6
|
+
"documentNamespace": "http://spdx.org/spdxdocs/@robono%2fserver-0.18.0-***",
|
|
7
7
|
"creationInfo": {
|
|
8
|
-
"created": "2026-11-
|
|
8
|
+
"created": "2026-11-03T17:17:07.688Z",
|
|
9
9
|
"creators": [
|
|
10
10
|
"Tool: npm/cli-11.6.2"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
13
|
"documentDescribes": [
|
|
14
|
-
"SPDXRef-Package-robono.server-0.
|
|
14
|
+
"SPDXRef-Package-robono.server-0.18.0"
|
|
15
15
|
],
|
|
16
16
|
"packages": [
|
|
17
17
|
{
|
|
18
18
|
"name": "@robono/server",
|
|
19
|
-
"SPDXID": "SPDXRef-Package-robono.server-0.
|
|
20
|
-
"versionInfo": "0.
|
|
19
|
+
"SPDXID": "SPDXRef-Package-robono.server-0.18.0",
|
|
20
|
+
"versionInfo": "0.18.0",
|
|
21
21
|
"packageFileName": "",
|
|
22
22
|
"description": "Provider-neutral server SDK for the Robono Bridge API.",
|
|
23
23
|
"primaryPackagePurpose": "LIBRARY",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
{
|
|
30
30
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
31
31
|
"referenceType": "purl",
|
|
32
|
-
"referenceLocator": "pkg:npm/%40robono/server@0.
|
|
32
|
+
"referenceLocator": "pkg:npm/%40robono/server@0.18.0"
|
|
33
33
|
}
|
|
34
34
|
]
|
|
35
35
|
}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"relationships": [
|
|
38
38
|
{
|
|
39
39
|
"spdxElementId": "SPDXRef-DOCUMENT",
|
|
40
|
-
"relatedSpdxElement": "SPDXRef-Package-robono.server-0.
|
|
40
|
+
"relatedSpdxElement": "SPDXRef-Package-robono.server-0.18.0",
|
|
41
41
|
"relationshipType": "DESCRIBES"
|
|
42
42
|
}
|
|
43
43
|
]
|
package/dist/index.d.ts
CHANGED
|
@@ -26,4 +26,5 @@ export * from './messaging-notification-providers.js';
|
|
|
26
26
|
export * from './messaging-notification-postgres.js';
|
|
27
27
|
export { RobonoScreening } from './screening.js';
|
|
28
28
|
export type { ScreeningFile, ScreeningResult } from './screening.js';
|
|
29
|
+
export { checkRobonoMessengerSetup, type MessengerSetupCheck } from './messenger-check.js';
|
|
29
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrI,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,yBAAyB,EACzB,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtE,mBAAmB,YAAY,CAAC;AAEhC,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AACvF,YAAY,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEpF,OAAO,EAAC,kCAAkC,EAAC,MAAM,sBAAsB,CAAC;AACxE,YAAY,EAAC,uBAAuB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AACtI,OAAO,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAC,sCAAsC,EAAC,MAAM,2BAA2B,CAAC;AAEjF,OAAO,EAAC,qBAAqB,EAAC,4BAA4B,EAAC,MAAM,eAAe,CAAC;AACjF,YAAY,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACtD,OAAO,EAAC,yBAAyB,EAAC,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAC,2BAA2B,EAAC,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EAAC,4BAA4B,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAEjF,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AAErD,OAAO,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAC,aAAa,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrI,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,yBAAyB,EACzB,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtE,mBAAmB,YAAY,CAAC;AAEhC,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AACvF,YAAY,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEpF,OAAO,EAAC,kCAAkC,EAAC,MAAM,sBAAsB,CAAC;AACxE,YAAY,EAAC,uBAAuB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AACtI,OAAO,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAC,sCAAsC,EAAC,MAAM,2BAA2B,CAAC;AAEjF,OAAO,EAAC,qBAAqB,EAAC,4BAA4B,EAAC,MAAM,eAAe,CAAC;AACjF,YAAY,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACtD,OAAO,EAAC,yBAAyB,EAAC,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAC,2BAA2B,EAAC,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EAAC,4BAA4B,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAEjF,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AAErD,OAAO,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAC,aAAa,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAElE,OAAO,EAAC,yBAAyB,EAAC,KAAK,mBAAmB,EAAC,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -16,4 +16,5 @@ export * from './messaging-notifications.js';
|
|
|
16
16
|
export * from './messaging-notification-providers.js';
|
|
17
17
|
export * from './messaging-notification-postgres.js';
|
|
18
18
|
export { RobonoScreening } from './screening.js';
|
|
19
|
+
export { checkRobonoMessengerSetup } from './messenger-check.js';
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAM1D,OAAO,EACL,yBAAyB,EACzB,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAGtE,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAGvF,OAAO,EAAC,kCAAkC,EAAC,MAAM,sBAAsB,CAAC;AAExE,OAAO,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAC,sCAAsC,EAAC,MAAM,2BAA2B,CAAC;AAEjF,OAAO,EAAC,qBAAqB,EAAC,4BAA4B,EAAC,MAAM,eAAe,CAAC;AAEjF,OAAO,EAAC,yBAAyB,EAAC,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAC,2BAA2B,EAAC,MAAM,gBAAgB,CAAC;AAG3D,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AAErD,OAAO,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAM1D,OAAO,EACL,yBAAyB,EACzB,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAGtE,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAGvF,OAAO,EAAC,kCAAkC,EAAC,MAAM,sBAAsB,CAAC;AAExE,OAAO,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAC,sCAAsC,EAAC,MAAM,2BAA2B,CAAC;AAEjF,OAAO,EAAC,qBAAqB,EAAC,4BAA4B,EAAC,MAAM,eAAe,CAAC;AAEjF,OAAO,EAAC,yBAAyB,EAAC,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAC,2BAA2B,EAAC,MAAM,gBAAgB,CAAC;AAG3D,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AAErD,OAAO,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAG/C,OAAO,EAAC,yBAAyB,EAA0B,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ManagedMessagingNotificationsOptions {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
fetch?: typeof fetch;
|
|
5
|
+
authenticate: (request: Request) => Promise<string | null>;
|
|
6
|
+
authorize: (input: {
|
|
7
|
+
actorId: string;
|
|
8
|
+
operation: string;
|
|
9
|
+
input: Record<string, unknown>;
|
|
10
|
+
request: Request;
|
|
11
|
+
}) => Promise<boolean>;
|
|
12
|
+
}
|
|
13
|
+
/** Customer sessions terminate here. The network key and verified actor never come from the browser. */
|
|
14
|
+
export declare function createManagedMessagingNotifications(options: ManagedMessagingNotificationsOptions): (request: Request) => Promise<Response>;
|
|
15
|
+
//# sourceMappingURL=managed-notifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"managed-notifications.d.ts","sourceRoot":"","sources":["../src/managed-notifications.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oCAAoC;IAAE,MAAM,EAAC,MAAM,CAAC;IAAA,OAAO,CAAC,EAAC,MAAM,CAAC;IAAA,KAAK,CAAC,EAAC,OAAO,KAAK,CAAC;IAAA,YAAY,EAAC,CAAC,OAAO,EAAC,OAAO,KAAG,OAAO,CAAC,MAAM,GAAC,IAAI,CAAC,CAAC;IAAA,SAAS,EAAC,CAAC,KAAK,EAAC;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,SAAS,EAAC,MAAM,CAAC;QAAA,KAAK,EAAC,MAAM,CAAC,MAAM,EAAC,OAAO,CAAC,CAAC;QAAA,OAAO,EAAC,OAAO,CAAA;KAAC,KAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAAC;AACjR,wGAAwG;AACxG,wBAAgB,mCAAmC,CAAC,OAAO,EAAC,oCAAoC,IAIlF,SAAQ,OAAO,uBAc5B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Customer sessions terminate here. The network key and verified actor never come from the browser. */
|
|
2
|
+
export function createManagedMessagingNotifications(options) {
|
|
3
|
+
const url = new URL(options.baseUrl ?? 'https://api.robono.com/v1/messaging/notifications');
|
|
4
|
+
if (url.protocol !== 'https:' || url.username || url.password)
|
|
5
|
+
throw Error('Use an HTTPS notification endpoint.');
|
|
6
|
+
const reply = (code, status) => Response.json({ error: { code } }, { status, headers: { 'cache-control': 'no-store' } });
|
|
7
|
+
return async (request) => {
|
|
8
|
+
try {
|
|
9
|
+
const actorId = await options.authenticate(request);
|
|
10
|
+
if (!actorId)
|
|
11
|
+
return reply('authentication_required', 401);
|
|
12
|
+
const raw = await request.text();
|
|
13
|
+
if (raw.length > 12000)
|
|
14
|
+
return reply('request_too_large', 413);
|
|
15
|
+
let body;
|
|
16
|
+
try {
|
|
17
|
+
body = JSON.parse(raw);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return reply('invalid_request', 422);
|
|
21
|
+
}
|
|
22
|
+
if (!body || typeof body !== 'object' || !['notification-status', 'register-device', 'remove-device'].includes(body.operation))
|
|
23
|
+
return reply('invalid_request', 422);
|
|
24
|
+
// Status/removal must remain possible during suspension so logout can revoke devices.
|
|
25
|
+
if (body.operation === 'register-device' && !await options.authorize({ actorId, operation: 'notifications.register-device', input: body, request }))
|
|
26
|
+
return reply('permission_denied', 403);
|
|
27
|
+
const origin = request.headers.get('origin');
|
|
28
|
+
const response = await (options.fetch ?? fetch)(url, { method: 'POST', redirect: 'error', signal: AbortSignal.timeout(15000), headers: { authorization: 'Bearer ' + options.apiKey, 'content-type': 'application/json' }, body: JSON.stringify({ ...body, actorId, origin: origin ?? null }) });
|
|
29
|
+
const data = await response.json().catch(() => null);
|
|
30
|
+
return Response.json(data ?? { error: { code: 'notifications_unavailable' } }, { status: response.status, headers: { 'cache-control': 'no-store' } });
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return reply('notifications_unavailable', 503);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=managed-notifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"managed-notifications.js","sourceRoot":"","sources":["../src/managed-notifications.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging-push-worker.d.ts","sourceRoot":"","sources":["../src/messaging-push-worker.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,eAAO,MAAM,yBAAyB,QAgCrC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Served from the customer's existing combined route; never replaces their PWA worker. */
|
|
2
|
+
export const messagingPushWorkerSource = String.raw `
|
|
3
|
+
'use strict';
|
|
4
|
+
const store=async(value,write=false)=>new Promise((resolve,reject)=>{
|
|
5
|
+
const request=indexedDB.open('robono-notifications',1);
|
|
6
|
+
request.onupgradeneeded=()=>request.result.createObjectStore('state');
|
|
7
|
+
request.onerror=()=>reject(Error('Notification storage unavailable'));
|
|
8
|
+
request.onsuccess=()=>{const db=request.result,tx=db.transaction('state',write?'readwrite':'readonly'),s=tx.objectStore('state');
|
|
9
|
+
const r=write?s.put(value,'account'):s.get('account');let result;r.onsuccess=()=>{result=r.result;};tx.oncomplete=()=>{db.close();resolve(result);};tx.onerror=()=>{db.close();reject(Error('Notification storage unavailable'));};};
|
|
10
|
+
});
|
|
11
|
+
self.addEventListener('install',()=>self.skipWaiting());
|
|
12
|
+
self.addEventListener('activate',event=>event.waitUntil(self.clients.claim()));
|
|
13
|
+
self.addEventListener('message',event=>{
|
|
14
|
+
if(!event.source||new URL(event.source.url).origin!==self.location.origin||event.data?.type!=='robono.notification-account')return;
|
|
15
|
+
const account=event.data.accountScope;
|
|
16
|
+
if(account!==null&&!/^[a-f0-9]{64}$/.test(account))return;
|
|
17
|
+
event.waitUntil((async()=>{await store(account,true);for(const n of await self.registration.getNotifications())if(n.data?.event?.accountScope!==account)n.close();event.ports[0]?.postMessage({ok:true});})());
|
|
18
|
+
});
|
|
19
|
+
self.addEventListener('push',event=>event.waitUntil((async()=>{
|
|
20
|
+
let payload;try{payload=event.data.json();}catch{return;}
|
|
21
|
+
const d=payload.data,account=await store();
|
|
22
|
+
if(!account||d?.event!=='robono.messaging'||d.accountScope!==account||!/^\d+$/.test(d.messageId)||!/^[a-f0-9-]{36}$/.test(d.conversationId))return;
|
|
23
|
+
const target=new URL(payload.url);if(target.origin!==self.location.origin)return;
|
|
24
|
+
await self.registration.showNotification(String(payload.title||'New message').slice(0,80),{body:'Open the app to read your message.',tag:account+':'+d.conversationId,data:{event:d,url:target.href}});
|
|
25
|
+
})()));
|
|
26
|
+
self.addEventListener('notificationclick',event=>{event.notification.close();event.waitUntil((async()=>{
|
|
27
|
+
const data=event.notification.data;if(data?.event?.accountScope!==await store())return;
|
|
28
|
+
const url=new URL(data.url);if(url.origin!==self.location.origin)return;
|
|
29
|
+
const clients=await self.clients.matchAll({type:'window',includeUncontrolled:true});
|
|
30
|
+
const match=clients.find(c=>new URL(c.url).origin===url.origin&&new URL(c.url).pathname===url.pathname);
|
|
31
|
+
if(match){await match.focus();match.postMessage({type:'robono.notification-open',event:data.event});}
|
|
32
|
+
else{url.hash='robono-notification='+encodeURIComponent(JSON.stringify(data.event));await self.clients.openWindow(url.href);}
|
|
33
|
+
})());});
|
|
34
|
+
`;
|
|
35
|
+
//# sourceMappingURL=messaging-push-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging-push-worker.js","sourceRoot":"","sources":["../src/messaging-push-worker.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,MAAM,CAAC,MAAM,yBAAyB,GAAC,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgChD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface MessengerSetupCheck {
|
|
2
|
+
name: string;
|
|
3
|
+
status: 'passed' | 'failed' | 'needs-action';
|
|
4
|
+
detail: string;
|
|
5
|
+
}
|
|
6
|
+
/** Runs from the customer's computer/server. Never sends their login token to Robono's portal. */
|
|
7
|
+
export declare function checkRobonoMessengerSetup(options: {
|
|
8
|
+
endpoint: string;
|
|
9
|
+
accessToken: string;
|
|
10
|
+
origin: string;
|
|
11
|
+
fetch?: typeof fetch;
|
|
12
|
+
}): Promise<MessengerSetupCheck[]>;
|
|
13
|
+
//# sourceMappingURL=messenger-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messenger-check.d.ts","sourceRoot":"","sources":["../src/messenger-check.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAAE,IAAI,EAAC,MAAM,CAAC;IAAA,MAAM,EAAC,QAAQ,GAAC,QAAQ,GAAC,cAAc,CAAC;IAAA,MAAM,EAAC,MAAM,CAAA;CAAC;AACxG,kGAAkG;AAClG,wBAAsB,yBAAyB,CAAC,OAAO,EAAC;IAAC,QAAQ,EAAC,MAAM,CAAC;IAAA,WAAW,EAAC,MAAM,CAAC;IAAA,MAAM,EAAC,MAAM,CAAC;IAAA,KAAK,CAAC,EAAC,OAAO,KAAK,CAAA;CAAC,GAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAe7J"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Runs from the customer's computer/server. Never sends their login token to Robono's portal. */
|
|
2
|
+
export async function checkRobonoMessengerSetup(options) {
|
|
3
|
+
const url = new URL(options.endpoint), origin = new URL(options.origin);
|
|
4
|
+
if (url.username || url.password || url.hash || url.origin !== origin.origin || origin.origin !== options.origin || !(url.protocol === 'https:' || url.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname)))
|
|
5
|
+
throw Error('Use your exact website origin and an HTTPS messaging route on that origin (localhost may use HTTP).');
|
|
6
|
+
if (!options.accessToken.trim())
|
|
7
|
+
throw Error('Supply a test user’s current login token, not your Robono network key.');
|
|
8
|
+
const request = options.fetch ?? fetch, checks = [];
|
|
9
|
+
const run = async (name, fn) => { try {
|
|
10
|
+
checks.push({ name, ...await fn() });
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
checks.push({ name, status: 'failed', detail: 'The route did not respond correctly. Check the server logs without exposing keys or session tokens.' });
|
|
14
|
+
} };
|
|
15
|
+
const post = (body, token = true, from = options.origin, service = 'messages') => { const u = new URL(url); u.searchParams.set('service', service); return request(u, { method: 'POST', redirect: 'error', signal: AbortSignal.timeout(15000), headers: { 'content-type': 'application/json', origin: from, ...(token ? { authorization: 'Bearer ' + options.accessToken } : {}) }, body: JSON.stringify(body) }); };
|
|
16
|
+
await run('Sign-in protection', async () => { const r = await post({ operation: 'settings' }, false); return { status: r.status === 401 ? 'passed' : 'failed', detail: r.status === 401 ? 'Unsigned requests are rejected.' : 'Requests without a login must return 401.' }; });
|
|
17
|
+
await run('Website protection', async () => { const r = await post({ operation: 'settings' }, true, 'https://robono-invalid-origin.example'); return { status: r.status === 403 ? 'passed' : 'failed', detail: r.status === 403 ? 'Other websites are rejected.' : 'Reject unknown browser origins; do not use a wildcard.' }; });
|
|
18
|
+
await run('Signed-in messaging', async () => { const r = await post({ operation: 'settings' }), d = await r.json(); return { status: r.ok && d.settings ? 'passed' : 'failed', detail: r.ok && d.settings ? 'The test user can load messaging settings.' : 'Connect the test user’s sign-in and current messaging permission.' }; });
|
|
19
|
+
await run('Contacts and conversations', async () => { const r = await post({ operation: 'conversations' }), d = await r.json(); const rows = d.conversations; return { status: !r.ok || !Array.isArray(rows) ? 'failed' : rows.length ? 'passed' : 'needs-action', detail: !r.ok || !Array.isArray(rows) ? 'The signed-in user cannot load chats.' : rows.length ? 'Authorized chats are available.' : 'Connect a second test user and synchronize their permitted relationship.' }; });
|
|
20
|
+
await run('Server-only operations', async () => { const r = await post({ operation: 'erase-user', userId: 'robono-check-never-delete' }); return { status: r.status === 403 ? 'passed' : 'failed', detail: r.status === 403 ? 'Account deletion is blocked from the public chat route.' : 'The browser route must reject server-only account operations.' }; });
|
|
21
|
+
await run('Notification connection', async () => { const r = await post({ operation: 'notification-status' }, true, options.origin, 'notifications'), d = await r.json(); return { status: !r.ok || !Array.isArray(d.providers) ? 'failed' : d.providers.length ? 'passed' : 'needs-action', detail: !r.ok ? 'Update the server package and enable managed notifications.' : d.providers?.length ? 'Connected providers: ' + d.providers.join(', ') + '. A real background alert still needs testing.' : 'Connect website, Apple or Google settings in Your app → Message notifications.' }; });
|
|
22
|
+
await run('Browser notification helper', async () => { const u = new URL(url); u.searchParams.set('service', 'push-worker'); const r = await request(u, { redirect: 'error', signal: AbortSignal.timeout(15000) }); const ok = r.ok && r.headers.get('content-type')?.includes('javascript') && r.headers.get('service-worker-allowed') === '/robono-notifications/'; return { status: ok ? 'passed' : 'needs-action', detail: ok ? 'Your route serves the browser helper without replacing an existing worker.' : 'For browser alerts, mount GET as well as POST on the combined route.' }; });
|
|
23
|
+
return checks;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=messenger-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messenger-check.js","sourceRoot":"","sources":["../src/messenger-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messenger-setup-test.d.ts","sourceRoot":"","sources":["../src/messenger-setup-test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { checkRobonoMessengerSetup } from './messenger-check.js';
|
|
3
|
+
if (process.argv.includes('--help')) {
|
|
4
|
+
console.log('Set ROBONO_MESSENGER_URL, ROBONO_TEST_USER_TOKEN and ROBONO_WEBSITE_ORIGIN in your local environment, then run robono-messenger-check. Use a disposable test account. No token is printed or sent to the Robono portal.');
|
|
5
|
+
process.exit(0);
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
const checks = await checkRobonoMessengerSetup({ endpoint: process.env.ROBONO_MESSENGER_URL ?? '', accessToken: process.env.ROBONO_TEST_USER_TOKEN ?? '', origin: process.env.ROBONO_WEBSITE_ORIGIN ?? '' });
|
|
9
|
+
for (const check of checks)
|
|
10
|
+
console.log(`${check.status === 'passed' ? 'PASS' : check.status === 'failed' ? 'FIX' : 'NEXT'} — ${check.name}: ${check.detail}`);
|
|
11
|
+
console.log('Still test two users sending, attaching, receiving and opening a background notification. These automatic checks do not prove delivery or security for every customer permission rule.');
|
|
12
|
+
process.exitCode = checks.some(c => c.status === 'failed') ? 1 : 0;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
console.error('Check the endpoint, exact website origin and test-user token. Run robono-messenger-check --help for setup.');
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=messenger-setup-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messenger-setup-test.js","sourceRoot":"","sources":["../src/messenger-setup-test.ts"],"names":[],"mappings":";AACA,OAAO,EAAC,yBAAyB,EAAC,MAAM,sBAAsB,CAAC;AAC/D,IAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAC,CAAC;IAAA,OAAO,CAAC,GAAG,CAAC,yNAAyN,CAAC,CAAC;IAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,CAAC;AAC5R,IAAG,CAAC;IAAA,MAAM,MAAM,GAAC,MAAM,yBAAyB,CAAC,EAAC,QAAQ,EAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAE,EAAE,EAAC,WAAW,EAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAE,EAAE,EAAC,MAAM,EAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAE,EAAE,EAAC,CAAC,CAAC;IAAA,KAAI,MAAM,KAAK,IAAI,MAAM;QAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,KAAG,QAAQ,CAAA,CAAC,CAAA,MAAM,CAAA,CAAC,CAAA,KAAK,CAAC,MAAM,KAAG,QAAQ,CAAA,CAAC,CAAA,KAAK,CAAA,CAAC,CAAA,MAAM,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAAA,OAAO,CAAC,GAAG,CAAC,wLAAwL,CAAC,CAAC;IAAA,OAAO,CAAC,QAAQ,GAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA,EAAE,CAAA,CAAC,CAAC,MAAM,KAAG,QAAQ,CAAC,CAAA,CAAC,CAAA,CAAC,CAAA,CAAC,CAAA,CAAC,CAAC;AAAA,CAAC;AAAA,MAAK,CAAC;IAAA,OAAO,CAAC,KAAK,CAAC,4GAA4G,CAAC,CAAC;IAAA,OAAO,CAAC,QAAQ,GAAC,CAAC,CAAC;AAAA,CAAC"}
|
package/dist/messenger.d.ts
CHANGED
|
@@ -29,7 +29,11 @@ export interface RobonoMessengerServerOptions {
|
|
|
29
29
|
fetch?: typeof fetch;
|
|
30
30
|
/** Same-origin cookie sessions must supply their exact allowed origin(s). */
|
|
31
31
|
allowedOrigins?: readonly string[];
|
|
32
|
-
|
|
32
|
+
/** Managed by Robono by default. Legacy self-hosted configuration remains supported. */
|
|
33
|
+
notifications?: false | {
|
|
34
|
+
managed: true;
|
|
35
|
+
url?: string;
|
|
36
|
+
} | {
|
|
33
37
|
scope: string;
|
|
34
38
|
webhookSecret: string;
|
|
35
39
|
workerSecret: string;
|
package/dist/messenger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messenger.d.ts","sourceRoot":"","sources":["../src/messenger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"messenger.d.ts","sourceRoot":"","sources":["../src/messenger.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,sBAAsB,EAAgC,MAAM,gBAAgB,CAAC;AAErF,OAAO,EAAqC,KAAK,uBAAuB,EAAE,KAAK,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AAGjI,OAAO,EAA2B,KAAK,yBAAyB,EAAC,KAAK,0BAA0B,EAAC,MAAM,uCAAuC,CAAC;AAC/I,OAAO,EAA0C,KAAK,0BAA0B,EAAC,MAAM,sCAAsC,CAAC;AAE9H,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAC,MAAM,CAAC;IACf,SAAS,EAAC,MAAM,CAAC;IACjB,cAAc,CAAC,EAAC,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAC,MAAM,CAAC;IACjB,KAAK,EAAC,MAAM,CAAC,MAAM,EAAC,OAAO,CAAC,CAAC;IAC7B,OAAO,EAAC,OAAO,CAAC;CACjB;AACD,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAC,MAAM,CAAC;IACd,+EAA+E;IAC/E,YAAY,EAAC,CAAC,OAAO,EAAC,OAAO,KAAG,OAAO,CAAC,MAAM,GAAC,IAAI,CAAC,CAAC;IACrD,iGAAiG;IACjG,SAAS,EAAC,CAAC,MAAM,EAAC,eAAe,KAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD,qFAAqF;IACrF,OAAO,CAAC,EAAC,CAAC,uBAAuB,GAAG;QAAC,OAAO,EAAC,CAAC,KAAK,EAAC;YAAC,OAAO,EAAC,MAAM,CAAC;YAAA,cAAc,EAAC,MAAM,CAAC;YAAA,OAAO,EAAC,MAAM,CAAA;SAAC,KAAG,OAAO,CAAC,oBAAoB,GAAC,IAAI,CAAC,CAAA;KAAC,CAAC,GAAC,KAAK,CAAC;IACvJ,YAAY,CAAC,EAAC,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAC,MAAM,CAAC;IACjB,KAAK,CAAC,EAAC,OAAO,KAAK,CAAC;IACpB,6EAA6E;IAC7E,cAAc,CAAC,EAAC,SAAS,MAAM,EAAE,CAAC;IAClC,wFAAwF;IACxF,aAAa,CAAC,EAAC,KAAK,GAAC;QAAC,OAAO,EAAC,IAAI,CAAC;QAAA,GAAG,CAAC,EAAC,MAAM,CAAA;KAAC,GAAC;QAC9C,KAAK,EAAC,MAAM,CAAC;QAAA,aAAa,EAAC,MAAM,CAAC;QAAA,YAAY,EAAC,MAAM,CAAC;QAAA,KAAK,EAAC,0BAA0B,CAAC;QACvF,KAAK,CAAC,EAAC,yBAAyB,CAAC;QAAA,MAAM,CAAC,EAAC,0BAA0B,CAAC;QAAA,KAAK,CAAC,EAAC,MAAM,CAAC;QAClF,qFAAqF;QACrF,kBAAkB,EAAC,CAAC,KAAK,EAAC;YAAC,MAAM,EAAC,MAAM,CAAC;YAAA,cAAc,EAAC,MAAM,CAAA;SAAC,KAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACpF,CAAC;CACH;AAED,gGAAgG;AAChG,wBAAgB,2BAA2B,CAAC,OAAO,EAAC,4BAA4B;IAsC5E,iEAAiE;;oBAE5C,OAAO,GAAE,OAAO,CAAC,QAAQ,CAAC;EA0BlD"}
|
package/dist/messenger.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createManagedMessagingNotifications } from './managed-notifications.js';
|
|
2
|
+
import { messagingPushWorkerSource } from './messaging-push-worker.js';
|
|
1
3
|
import { RobonoMessagingBackend, createMessagingBackendAdapter } from './messaging.js';
|
|
2
4
|
import { RobonoManagedMedia } from './managed-media.js';
|
|
3
5
|
import { createMessagingMediaBackendAdapter } from './messaging-media.js';
|
|
@@ -18,20 +20,22 @@ export function createRobonoMessengerServer(options) {
|
|
|
18
20
|
throw Error('Use exact origins without a path.');
|
|
19
21
|
return url.origin;
|
|
20
22
|
}));
|
|
21
|
-
|
|
23
|
+
const legacy = options.notifications && 'scope' in options.notifications ? options.notifications : undefined;
|
|
24
|
+
if (legacy && (!legacy.workerSecret || legacy.workerSecret.length < 32))
|
|
22
25
|
throw Error('Set a separate notification worker secret of at least 32 characters.');
|
|
23
26
|
const authenticate = async (request) => {
|
|
24
27
|
const actor = await options.authenticate(request);
|
|
25
28
|
return typeof actor === 'string' && actor.trim() === actor && actor.length > 0 && actor.length <= 200 && !/[\u0000-\u001f\u007f]/.test(actor) ? actor : null;
|
|
26
29
|
};
|
|
27
|
-
const push =
|
|
28
|
-
const notifications =
|
|
29
|
-
scope:
|
|
30
|
-
store: createPostgresMessagingNotificationStore(
|
|
30
|
+
const push = legacy ? createMessagingPushSender({ ...legacy, ...(options.fetch ? { fetch: options.fetch } : {}) }) : null;
|
|
31
|
+
const notifications = legacy && push ? createMessagingNotifications({
|
|
32
|
+
scope: legacy.scope, webhookSecret: legacy.webhookSecret,
|
|
33
|
+
store: createPostgresMessagingNotificationStore(legacy.query), authenticate,
|
|
31
34
|
providers: push.providers, send: push.send,
|
|
32
|
-
mayNotify: async (event) => await
|
|
35
|
+
mayNotify: async (event) => await legacy.authorizeRecipient({ userId: event.recipient_external_user_id, conversationId: event.conversation_id }) &&
|
|
33
36
|
await robono.canNotify({ userId: event.recipient_external_user_id, conversationId: event.conversation_id, messageId: event.message_id }),
|
|
34
37
|
}) : null;
|
|
38
|
+
const managed = options.notifications === false || legacy ? null : createManagedMessagingNotifications({ ...common, authenticate, authorize: options.authorize, ...(options.notifications && 'managed' in options.notifications && options.notifications.url ? { baseUrl: options.notifications.url } : {}) });
|
|
35
39
|
const messages = createMessagingBackendAdapter({ robono, authenticate,
|
|
36
40
|
authorize: access => options.storage === false && ['send', 'send-call-message', 'edit'].includes(access.operation) && access.input.kind !== undefined && !['text', 'poll'].includes(String(access.input.kind)) ? Promise.resolve(false) : options.authorize({ ...access,
|
|
37
41
|
...(typeof access.input.conversationId === 'string' ? { conversationId: access.input.conversationId } : {}),
|
|
@@ -48,15 +52,17 @@ export function createRobonoMessengerServer(options) {
|
|
|
48
52
|
/** Keep relationship and group synchronization on the server. */
|
|
49
53
|
robono,
|
|
50
54
|
async handle(request) {
|
|
55
|
+
const route = new URL(request.url).searchParams.get('service') ?? 'messages';
|
|
56
|
+
if (request.method === 'GET' && route === 'push-worker' && managed)
|
|
57
|
+
return new Response(messagingPushWorkerSource, { headers: { 'content-type': 'text/javascript; charset=utf-8', 'cache-control': 'no-cache', 'service-worker-allowed': '/robono-notifications/', 'x-content-type-options': 'nosniff' } });
|
|
51
58
|
if (request.method !== 'POST')
|
|
52
59
|
return failure('method_not_allowed', 405);
|
|
53
|
-
const route = new URL(request.url).searchParams.get('service') ?? 'messages';
|
|
54
60
|
if (route === 'events')
|
|
55
61
|
return notifications ? notifications.webhook(request) : failure('notifications_not_configured', 409);
|
|
56
62
|
if (route === 'notification-worker') {
|
|
57
63
|
if (!notifications)
|
|
58
64
|
return failure('notifications_not_configured', 409);
|
|
59
|
-
const expected = createHash('sha256').update('Bearer ' +
|
|
65
|
+
const expected = createHash('sha256').update('Bearer ' + legacy.workerSecret).digest();
|
|
60
66
|
const received = createHash('sha256').update(request.headers.get('authorization') ?? '').digest();
|
|
61
67
|
if (!timingSafeEqual(expected, received))
|
|
62
68
|
return failure('authentication_required', 401);
|
|
@@ -81,7 +87,7 @@ export function createRobonoMessengerServer(options) {
|
|
|
81
87
|
if (route === 'media')
|
|
82
88
|
return media ? media(request) : failure('attachments_disabled', 403);
|
|
83
89
|
if (route === 'notifications')
|
|
84
|
-
return notifications ? notifications.devices(request) : failure('notifications_not_configured', 409);
|
|
90
|
+
return notifications ? notifications.devices(request) : managed ? managed(request) : failure('notifications_not_configured', 409);
|
|
85
91
|
return failure('service_not_found', 404);
|
|
86
92
|
},
|
|
87
93
|
};
|
package/dist/messenger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messenger.js","sourceRoot":"","sources":["../src/messenger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAE,6BAA6B,EAAC,MAAM,gBAAgB,CAAC;AACrF,OAAO,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAC,kCAAkC,EAA0D,MAAM,sBAAsB,CAAC;AACjI,OAAO,EAAC,UAAU,EAAC,eAAe,EAAC,MAAM,aAAa,CAAC;AACvD,OAAO,EAAC,4BAA4B,EAAC,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAC,yBAAyB,EAAgE,MAAM,uCAAuC,CAAC;AAC/I,OAAO,EAAC,wCAAwC,EAAiC,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"messenger.js","sourceRoot":"","sources":["../src/messenger.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robono/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Provider-neutral server SDK for the Robono Bridge API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"robono",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
},
|
|
40
40
|
"bin": {
|
|
41
41
|
"robono-sandbox-test": "dist/sandbox-test.js",
|
|
42
|
-
"robono-adapter-test": "dist/adapter-smoke-test.js"
|
|
42
|
+
"robono-adapter-test": "dist/adapter-smoke-test.js",
|
|
43
|
+
"robono-messenger-check": "dist/messenger-setup-test.js"
|
|
43
44
|
},
|
|
44
45
|
"files": [
|
|
45
46
|
"dist",
|