@robono/server 0.16.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 +9 -0
- package/NOTIFICATIONS.md +28 -1
- package/README.md +16 -2
- package/SBOM.spdx.json +8 -8
- package/SCREENING.md +73 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/managed-media.d.ts.map +1 -1
- package/dist/managed-media.js +2 -0
- package/dist/managed-media.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/dist/screening.d.ts +53 -0
- package/dist/screening.d.ts.map +1 -0
- package/dist/screening.js +52 -0
- package/dist/screening.js.map +1 -0
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
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
|
|
|
7
|
+
## 0.17.0 — 2026-11-03
|
|
8
|
+
|
|
9
|
+
- Add optional photo/video screening for connected networks and return attachment screening status without holding server requests open.
|
|
10
|
+
|
|
11
|
+
|
|
3
12
|
## 0.16.0 — 2026-11-03
|
|
4
13
|
|
|
5
14
|
Add createRobonoMessengerServer for one authenticated messaging/media route, plus optional signed-event notification delivery using customer Apple/Google credentials and a durable private PostgreSQL queue. Announce supported group controls; keep actor identity server-verified and recheck customer permissions on search results. Include NOTIFICATIONS.md and the notification schema.
|
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,5 +371,19 @@ 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
|
-
|
|
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.
|
|
375
|
+
|
|
376
|
+
## Optional photo and video screening
|
|
377
|
+
|
|
378
|
+
Connected networks can use Robono-hosted Amazon screening with their existing
|
|
379
|
+
Processing API key, including apps with their own storage. See [screening setup](https://robono.com/docs#screening)
|
|
380
|
+
for the private-upload flow, prices, spending controls and pending-result handling.
|
|
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/SCREENING.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Photo and video screening for connected networks
|
|
2
|
+
|
|
3
|
+
Available in the upcoming server release (not present in server 0.16.0).
|
|
4
|
+
|
|
5
|
+
A connected network can use Robono's Amazon screening without replacing its own
|
|
6
|
+
chat interface or attachment storage. Do not put your network API key in a phone
|
|
7
|
+
app or website. No customer AWS account, Amazon keys or extra AWS server is needed.
|
|
8
|
+
|
|
9
|
+
1. In Robono's **Features & preview → Photo and video screening**, choose categories,
|
|
10
|
+
sensitivity and a monthly limit, then accept the prices and processing terms.
|
|
11
|
+
2. Use an existing backend API key with **Processing** permission.
|
|
12
|
+
3. Keep attachments private until screening returns `allowed` for the exact bytes.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import {RobonoScreening} from '@robono/server';
|
|
16
|
+
const screening = new RobonoScreening({apiKey: process.env.ROBONO_API_KEY!});
|
|
17
|
+
// Authenticate your own user and authorize their upload before this call.
|
|
18
|
+
const job = await screening.upload(stableUploadId, {
|
|
19
|
+
kind: 'image', fileName: 'photo.jpg', mimeType: 'image/jpeg', byteSize: bytes.length,
|
|
20
|
+
}, bytes);
|
|
21
|
+
// Store job.id against your private upload. Return promptly; poll status later.
|
|
22
|
+
const result = await screening.status(job.id);
|
|
23
|
+
if (result.state === 'allowed') {
|
|
24
|
+
await screening.assertAllowed(job.id, bytes); // checks current policy + SHA-256
|
|
25
|
+
// Publish these exact bytes to the recipients your app has authorized.
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Videos use `kind: 'video'`, `mimeType: 'video/mp4'` or `video/quicktime`, and
|
|
30
|
+
`durationMs`. Server verification checks duration; a false short duration fails.
|
|
31
|
+
Video analysis can take minutes. Show "Checking attachment" while pending, allow
|
|
32
|
+
canceling, and keep ordinary chat usable. `blocked` and `failed` must never release
|
|
33
|
+
the file. Store a stable request ID across network retries. A changed file needs a
|
|
34
|
+
new request ID. A policy change invalidates approval for future publication.
|
|
35
|
+
|
|
36
|
+
For direct HTTPS integration, POST to `https://api.robono.com/v1/screening` with
|
|
37
|
+
`Authorization: Bearer YOUR_SERVER_KEY`. Operations:
|
|
38
|
+
|
|
39
|
+
- `prepare`: `{operation:'prepare', requestId, file}`. Returns job and private PUT
|
|
40
|
+
upload instructions. Send only the returned storage headers to the upload URL.
|
|
41
|
+
- `submit`: `{operation:'submit', id}` after upload.
|
|
42
|
+
- `status`: `{operation:'status', id}`. Pending is not approval.
|
|
43
|
+
|
|
44
|
+
Responses include `id`, `state`, `categories`, `sha256`, `chargedMicros`,
|
|
45
|
+
`reservedMicros` and timestamps. Amounts are USD millionths. Do not trust a client
|
|
46
|
+
phone's claim that it passed screening; read the result on your backend. Never
|
|
47
|
+
publish a mutable URL whose contents can change after the check.
|
|
48
|
+
|
|
49
|
+
## Robono-hosted attachments
|
|
50
|
+
|
|
51
|
+
With the updated server and supplied web/mobile packages, existing managed uploads
|
|
52
|
+
are automatically checked before delivery. The database also rejects direct sends
|
|
53
|
+
of unchecked photos/videos. Enabled screening requires managed storage for hosted
|
|
54
|
+
messaging; private external storage can use the standalone flow above. Older SDKs
|
|
55
|
+
must be updated before enabling screening. No extra per-chat switches.
|
|
56
|
+
|
|
57
|
+
## Formats, costs and privacy
|
|
58
|
+
|
|
59
|
+
JPEG/PNG up to 15 MiB. MP4/MOV up to 32 MiB and 15 minutes. Other formats fail rather
|
|
60
|
+
than bypass screening. These are visual checks, not audio/profanity checks, and
|
|
61
|
+
can produce missed content or mistaken blocks.
|
|
62
|
+
|
|
63
|
+
Release prices: $3/1,000 photos and $0.20 per started video minute, no monthly fee.
|
|
64
|
+
Successful checks count even if blocked. Failed checks are uncharged. The same
|
|
65
|
+
accepted job is not billed twice. New work stops at the network screening cap or
|
|
66
|
+
overall spending cap. Job status expires after 30 days; upload a new copy for a new
|
|
67
|
+
check. Keep the originally screened bytes private while a check is pending.
|
|
68
|
+
|
|
69
|
+
Only selected media goes to Amazon Rekognition in Northern Virginia. Robono opts
|
|
70
|
+
out of AWS using it for AI-service improvement. Private temporary screening copies
|
|
71
|
+
are removed after completion, with a one-day S3 expiry backstop. File names and
|
|
72
|
+
hashes are cleared after 30 days; aggregate usage/billing records remain. AWS
|
|
73
|
+
operational retention follows its terms. See Robono's provider disclosure.
|
package/dist/index.d.ts
CHANGED
|
@@ -24,4 +24,7 @@ export type { RobonoMessengerServerOptions, MessengerAccess } from './messenger.
|
|
|
24
24
|
export * from './messaging-notifications.js';
|
|
25
25
|
export * from './messaging-notification-providers.js';
|
|
26
26
|
export * from './messaging-notification-postgres.js';
|
|
27
|
+
export { RobonoScreening } from './screening.js';
|
|
28
|
+
export type { ScreeningFile, ScreeningResult } from './screening.js';
|
|
29
|
+
export { checkRobonoMessengerSetup, type MessengerSetupCheck } from './messenger-check.js';
|
|
27
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"}
|
|
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
|
@@ -15,4 +15,6 @@ export { createRobonoMessengerServer } from './messenger.js';
|
|
|
15
15
|
export * from './messaging-notifications.js';
|
|
16
16
|
export * from './messaging-notification-providers.js';
|
|
17
17
|
export * from './messaging-notification-postgres.js';
|
|
18
|
+
export { RobonoScreening } from './screening.js';
|
|
19
|
+
export { checkRobonoMessengerSetup } from './messenger-check.js';
|
|
18
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"}
|
|
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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"managed-media.d.ts","sourceRoot":"","sources":["../src/managed-media.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,uBAAuB,EAAC,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AACvF,yFAAyF;AACzF,qBAAa,kBAAmB,YAAW,uBAAuB;IAErD,OAAO,CAAC,OAAO;IAD3B,OAAO,CAAC,GAAG,CAAQ;gBACC,OAAO,EAAC;QAAC,MAAM,EAAC,MAAM,CAAC;QAAA,OAAO,CAAC,EAAC,MAAM,CAAC;QAAA,KAAK,CAAC,EAAC,OAAO,KAAK,CAAA;KAAC;YAKjE,OAAO;
|
|
1
|
+
{"version":3,"file":"managed-media.d.ts","sourceRoot":"","sources":["../src/managed-media.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,uBAAuB,EAAC,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AACvF,yFAAyF;AACzF,qBAAa,kBAAmB,YAAW,uBAAuB;IAErD,OAAO,CAAC,OAAO;IAD3B,OAAO,CAAC,GAAG,CAAQ;gBACC,OAAO,EAAC;QAAC,MAAM,EAAC,MAAM,CAAC;QAAA,OAAO,CAAC,EAAC,MAAM,CAAC;QAAA,KAAK,CAAC,EAAC,OAAO,KAAK,CAAA;KAAC;YAKjE,OAAO;IAOrB,OAAO,CAAC,KAAK,EAAC,UAAU,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAE,UAAU,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC;IACzG,QAAQ,CAAC,KAAK,EAAC,UAAU,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAAE,UAAU,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAKxH,QAAQ,CAAC,KAAK,EAAC,UAAU,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAAE,UAAU,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAClH,iBAAiB,CAAC,KAAK,EAAC;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,cAAc,EAAC,MAAM,CAAC;QAAA,SAAS,EAAC,MAAM,CAAA;KAAC,GAAE,OAAO,CAAC;QAAC,GAAG,EAAC,MAAM,CAAC;QAAA,OAAO,CAAC,EAAC,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,CAAC;QAAA,KAAK,EAAC,oBAAoB,CAAA;KAAC,CAAC;IAChK,SAAS,CAAC,KAAK,EAAC;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,cAAc,EAAC,MAAM,CAAC;QAAA,SAAS,EAAC,MAAM,CAAA;KAAC,GAAE,OAAO,CAAC;QAAC,GAAG,EAAC,MAAM,CAAC;QAAA,OAAO,CAAC,EAAC,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,CAAC;QAAA,KAAK,EAAC,oBAAoB,CAAA;KAAC,GAAC,IAAI,CAAC;IACvJ,OAAO,CAAC,KAAK,EAAC,UAAU,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO,CAAC,KAAK,EAAC;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,cAAc,EAAC,MAAM,CAAC;QAAA,OAAO,EAAC,MAAM,CAAA;KAAC,GAAE,OAAO,CAAC,oBAAoB,GAAC,IAAI,CAAC;CAG7G"}
|
package/dist/managed-media.js
CHANGED
|
@@ -13,6 +13,8 @@ export class RobonoManagedMedia {
|
|
|
13
13
|
async request(operation, input) {
|
|
14
14
|
const response = await (this.options.fetch ?? fetch)(this.url, { method: 'POST', redirect: 'error', signal: AbortSignal.timeout(operation === 'complete' ? 120000 : 15000), headers: { authorization: `Bearer ${this.options.apiKey}`, 'content-type': 'application/json' }, body: JSON.stringify({ ...input, operation }) });
|
|
15
15
|
const data = await response.json().catch(() => null);
|
|
16
|
+
if (response.status === 202 && data?.error?.code === 'screening_pending')
|
|
17
|
+
throw new RobonoError('This attachment is being checked before delivery.', { status: 202, code: 'screening_pending', retryable: true });
|
|
16
18
|
if (!response.ok)
|
|
17
19
|
throw new RobonoError(data?.error?.message ?? 'Attachment request failed.', { status: response.status, code: data?.error?.code ?? 'media_unavailable', retryable: response.status === 429 || response.status >= 500 });
|
|
18
20
|
return data;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"managed-media.js","sourceRoot":"","sources":["../src/managed-media.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"managed-media.js","sourceRoot":"","sources":["../src/managed-media.ts"],"names":[],"mappings":"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"}
|
|
@@ -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":"AACA,wGAAwG;AACxG,MAAM,UAAU,mCAAmC,CAAC,OAA4C;IAC/F,MAAM,GAAG,GAAC,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,IAAE,mDAAmD,CAAC,CAAC;IACxF,IAAG,GAAG,CAAC,QAAQ,KAAG,QAAQ,IAAE,GAAG,CAAC,QAAQ,IAAE,GAAG,CAAC,QAAQ;QAAC,MAAM,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC1G,MAAM,KAAK,GAAC,CAAC,IAAW,EAAC,MAAa,EAAC,EAAE,CAAA,QAAQ,CAAC,IAAI,CAAC,EAAC,KAAK,EAAC,EAAC,IAAI,EAAC,EAAC,EAAC,EAAC,MAAM,EAAC,OAAO,EAAC,EAAC,eAAe,EAAC,UAAU,EAAC,EAAC,CAAC,CAAC;IACrH,OAAO,KAAK,EAAC,OAAe,EAAC,EAAE;QAC9B,IAAG,CAAC;YACH,MAAM,OAAO,GAAC,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAAA,IAAG,CAAC,OAAO;gBAAC,OAAO,KAAK,CAAC,yBAAyB,EAAC,GAAG,CAAC,CAAC;YAC1G,MAAM,GAAG,GAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;YAAA,IAAG,GAAG,CAAC,MAAM,GAAC,KAAK;gBAAC,OAAO,KAAK,CAAC,mBAAmB,EAAC,GAAG,CAAC,CAAC;YACzF,IAAI,IAAI,CAAC;YAAA,IAAG,CAAC;gBAAA,IAAI,GAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAAA,CAAC;YAAA,MAAK,CAAC;gBAAA,OAAO,KAAK,CAAC,iBAAiB,EAAC,GAAG,CAAC,CAAC;YAAA,CAAC;YAC9E,IAAG,CAAC,IAAI,IAAE,OAAO,IAAI,KAAG,QAAQ,IAAE,CAAC,CAAC,qBAAqB,EAAC,iBAAiB,EAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;gBAAC,OAAO,KAAK,CAAC,iBAAiB,EAAC,GAAG,CAAC,CAAC;YAC1J,sFAAsF;YACtF,IAAG,IAAI,CAAC,SAAS,KAAG,iBAAiB,IAAE,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,EAAC,OAAO,EAAC,SAAS,EAAC,+BAA+B,EAAC,KAAK,EAAC,IAAI,EAAC,OAAO,EAAC,CAAC;gBAAC,OAAO,KAAK,CAAC,mBAAmB,EAAC,GAAG,CAAC,CAAC;YAC9K,MAAM,MAAM,GAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC3C,MAAM,QAAQ,GAAC,MAAK,CAAC,OAAO,CAAC,KAAK,IAAE,KAAK,CAAC,CAAC,GAAG,EAAC,EAAC,MAAM,EAAC,MAAM,EAAC,QAAQ,EAAC,OAAO,EAAC,MAAM,EAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAC,OAAO,EAAC,EAAC,aAAa,EAAC,SAAS,GAAC,OAAO,CAAC,MAAM,EAAC,cAAc,EAAC,kBAAkB,EAAC,EAAC,IAAI,EAAC,IAAI,CAAC,SAAS,CAAC,EAAC,GAAG,IAAI,EAAC,OAAO,EAAC,MAAM,EAAC,MAAM,IAAE,IAAI,EAAC,CAAC,EAAC,CAAC,CAAC;YACjQ,MAAM,IAAI,GAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAE,EAAE,CAAA,IAAI,CAAC,CAAC;YACjD,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAE,EAAC,KAAK,EAAC,EAAC,IAAI,EAAC,2BAA2B,EAAC,EAAC,EAAC,EAAC,MAAM,EAAC,QAAQ,CAAC,MAAM,EAAC,OAAO,EAAC,EAAC,eAAe,EAAC,UAAU,EAAC,EAAC,CAAC,CAAC;QACtI,CAAC;QAAA,MAAK,CAAC;YAAA,OAAO,KAAK,CAAC,2BAA2B,EAAC,GAAG,CAAC,CAAC;QAAA,CAAC;IACvD,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -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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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type ScreeningFile = {
|
|
2
|
+
kind: 'image' | 'video';
|
|
3
|
+
mimeType: string;
|
|
4
|
+
byteSize: number;
|
|
5
|
+
fileName: string;
|
|
6
|
+
durationMs?: number;
|
|
7
|
+
};
|
|
8
|
+
export type ScreeningResult = {
|
|
9
|
+
id: string;
|
|
10
|
+
state: 'uploading' | 'queued' | 'processing' | 'allowed' | 'blocked' | 'failed';
|
|
11
|
+
kind: 'image' | 'video';
|
|
12
|
+
categories: string[];
|
|
13
|
+
sha256: string | null;
|
|
14
|
+
error: string | null;
|
|
15
|
+
chargedMicros: number;
|
|
16
|
+
reservedMicros: number;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
finishedAt: string | null;
|
|
19
|
+
};
|
|
20
|
+
/** Server-only. Existing connected networks use their Robono Processing API key. */
|
|
21
|
+
export declare class RobonoScreening {
|
|
22
|
+
private options;
|
|
23
|
+
private url;
|
|
24
|
+
constructor(options: {
|
|
25
|
+
apiKey: string;
|
|
26
|
+
baseUrl?: string;
|
|
27
|
+
fetch?: typeof fetch;
|
|
28
|
+
});
|
|
29
|
+
private request;
|
|
30
|
+
prepare(requestId: string, file: ScreeningFile): Promise<ScreeningResult & {
|
|
31
|
+
upload?: {
|
|
32
|
+
url: string;
|
|
33
|
+
headers: Record<string, string>;
|
|
34
|
+
};
|
|
35
|
+
}>;
|
|
36
|
+
submit(id: string): Promise<ScreeningResult & {
|
|
37
|
+
upload?: {
|
|
38
|
+
url: string;
|
|
39
|
+
headers: Record<string, string>;
|
|
40
|
+
};
|
|
41
|
+
}>;
|
|
42
|
+
status(id: string): Promise<ScreeningResult & {
|
|
43
|
+
upload?: {
|
|
44
|
+
url: string;
|
|
45
|
+
headers: Record<string, string>;
|
|
46
|
+
};
|
|
47
|
+
}>;
|
|
48
|
+
/** Upload exactly the bytes to be published. Returns a job; never treats pending as approved. */
|
|
49
|
+
upload(requestId: string, file: ScreeningFile, bytes: Uint8Array): Promise<ScreeningResult>;
|
|
50
|
+
/** Call this before releasing bytes stored by your own application. */
|
|
51
|
+
assertAllowed(id: string, bytes: Uint8Array): Promise<ScreeningResult>;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=screening.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screening.d.ts","sourceRoot":"","sources":["../src/screening.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GAAC;IAAC,IAAI,EAAC,OAAO,GAAC,OAAO,CAAC;IAAA,QAAQ,EAAC,MAAM,CAAC;IAAA,QAAQ,EAAC,MAAM,CAAC;IAAA,QAAQ,EAAC,MAAM,CAAC;IAAA,UAAU,CAAC,EAAC,MAAM,CAAA;CAAC,CAAC;AACpH,MAAM,MAAM,eAAe,GAAC;IAAC,EAAE,EAAC,MAAM,CAAC;IAAA,KAAK,EAAC,WAAW,GAAC,QAAQ,GAAC,YAAY,GAAC,SAAS,GAAC,SAAS,GAAC,QAAQ,CAAC;IAAA,IAAI,EAAC,OAAO,GAAC,OAAO,CAAC;IAAA,UAAU,EAAC,MAAM,EAAE,CAAC;IAAA,MAAM,EAAC,MAAM,GAAC,IAAI,CAAC;IAAA,KAAK,EAAC,MAAM,GAAC,IAAI,CAAC;IAAA,aAAa,EAAC,MAAM,CAAC;IAAA,cAAc,EAAC,MAAM,CAAC;IAAA,SAAS,EAAC,MAAM,CAAC;IAAA,UAAU,EAAC,MAAM,GAAC,IAAI,CAAA;CAAC,CAAC;AAC9Q,oFAAoF;AACpF,qBAAa,eAAe;IAEf,OAAO,CAAC,OAAO;IAD3B,OAAO,CAAC,GAAG,CAAQ;gBACC,OAAO,EAAC;QAAC,MAAM,EAAC,MAAM,CAAC;QAAA,OAAO,CAAC,EAAC,MAAM,CAAC;QAAA,KAAK,CAAC,EAAC,OAAO,KAAK,CAAA;KAAC;YAIjE,OAAO;IAMrB,OAAO,CAAC,SAAS,EAAC,MAAM,EAAC,IAAI,EAAC,aAAa;iBAN0C;YAAC,GAAG,EAAC,MAAM,CAAC;YAAA,OAAO,EAAC,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,CAAA;SAAC;;IAO/H,MAAM,CAAC,EAAE,EAAC,MAAM;iBAPqE;YAAC,GAAG,EAAC,MAAM,CAAC;YAAA,OAAO,EAAC,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,CAAA;SAAC;;IAQ/H,MAAM,CAAC,EAAE,EAAC,MAAM;iBARqE;YAAC,GAAG,EAAC,MAAM,CAAC;YAAA,OAAO,EAAC,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,CAAA;SAAC;;IAS/H,iGAAiG;IAC3F,MAAM,CAAC,SAAS,EAAC,MAAM,EAAC,IAAI,EAAC,aAAa,EAAC,KAAK,EAAC,UAAU,GAAE,OAAO,CAAC,eAAe,CAAC;IAY3F,uEAAuE;IACjE,aAAa,CAAC,EAAE,EAAC,MAAM,EAAC,KAAK,EAAC,UAAU,GAAE,OAAO,CAAC,eAAe,CAAC;CAKxE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { RobonoError } from './errors.js';
|
|
3
|
+
/** Server-only. Existing connected networks use their Robono Processing API key. */
|
|
4
|
+
export class RobonoScreening {
|
|
5
|
+
options;
|
|
6
|
+
url;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
const u = new URL(options.baseUrl ?? 'https://api.robono.com/v1/screening');
|
|
10
|
+
if (u.protocol !== 'https:' || u.username || u.password || !options.apiKey.trim())
|
|
11
|
+
throw Error('Use HTTPS and a server API key.');
|
|
12
|
+
this.url = u.href;
|
|
13
|
+
}
|
|
14
|
+
async request(operation, body) {
|
|
15
|
+
const r = await (this.options.fetch ?? fetch)(this.url, { method: 'POST', redirect: 'error', signal: AbortSignal.timeout(30000), headers: { authorization: 'Bearer ' + this.options.apiKey, 'content-type': 'application/json' }, body: JSON.stringify({ ...body, operation }) });
|
|
16
|
+
const data = await r.json().catch(() => null);
|
|
17
|
+
if (!r.ok)
|
|
18
|
+
throw new RobonoError(data?.error?.message ?? 'Screening request failed.', { status: r.status, code: data?.error?.code ?? 'screening_unavailable', retryable: r.status === 429 || r.status >= 500 });
|
|
19
|
+
if (!data?.id || !['uploading', 'queued', 'processing', 'allowed', 'blocked', 'failed'].includes(data.state))
|
|
20
|
+
throw Error('Invalid screening response');
|
|
21
|
+
return data;
|
|
22
|
+
}
|
|
23
|
+
prepare(requestId, file) { return this.request('prepare', { requestId, file }); }
|
|
24
|
+
submit(id) { return this.request('submit', { id }); }
|
|
25
|
+
status(id) { return this.request('status', { id }); }
|
|
26
|
+
/** Upload exactly the bytes to be published. Returns a job; never treats pending as approved. */
|
|
27
|
+
async upload(requestId, file, bytes) {
|
|
28
|
+
if (file.byteSize !== bytes.byteLength)
|
|
29
|
+
throw Error('File size does not match the supplied bytes.');
|
|
30
|
+
const digest = createHash('sha256').update(bytes).digest('hex');
|
|
31
|
+
const prepared = await this.prepare(requestId, file);
|
|
32
|
+
if (prepared.sha256 && prepared.sha256 !== digest)
|
|
33
|
+
throw Error('This request ID belongs to different file contents.');
|
|
34
|
+
if (prepared.upload) {
|
|
35
|
+
const destination = new URL(prepared.upload.url);
|
|
36
|
+
if (destination.protocol !== 'https:' || destination.username || destination.password)
|
|
37
|
+
throw Error('Invalid private upload URL');
|
|
38
|
+
const r = await (this.options.fetch ?? fetch)(destination, { method: 'PUT', redirect: 'error', headers: prepared.upload.headers, body: bytes, signal: AbortSignal.timeout(120000) });
|
|
39
|
+
if (!r.ok && r.status !== 412)
|
|
40
|
+
throw new RobonoError('Screening upload failed.', { status: r.status, code: 'screening_upload_failed', retryable: true });
|
|
41
|
+
}
|
|
42
|
+
return this.submit(prepared.id);
|
|
43
|
+
}
|
|
44
|
+
/** Call this before releasing bytes stored by your own application. */
|
|
45
|
+
async assertAllowed(id, bytes) {
|
|
46
|
+
const result = await this.status(id);
|
|
47
|
+
if (result.state !== 'allowed' || !result.sha256 || createHash('sha256').update(bytes).digest('hex') !== result.sha256)
|
|
48
|
+
throw new RobonoError('This file has not been approved for delivery.', { status: 409, code: result.state === 'blocked' ? 'content_blocked' : 'screening_not_approved', retryable: result.state === 'queued' || result.state === 'processing' });
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=screening.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screening.js","sourceRoot":"","sources":["../src/screening.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",
|
|
@@ -48,7 +49,8 @@
|
|
|
48
49
|
"LICENSE",
|
|
49
50
|
"SBOM.spdx.json",
|
|
50
51
|
"sql",
|
|
51
|
-
"NOTIFICATIONS.md"
|
|
52
|
+
"NOTIFICATIONS.md",
|
|
53
|
+
"SCREENING.md"
|
|
52
54
|
],
|
|
53
55
|
"scripts": {
|
|
54
56
|
"build": "tsc -p tsconfig.json",
|