@robono/server 0.14.0 → 0.16.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/NOTIFICATIONS.md +149 -0
  3. package/README.md +35 -1
  4. package/SBOM.spdx.json +8 -8
  5. package/dist/index.d.ts +5 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +4 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/location.js +1 -1
  10. package/dist/location.js.map +1 -1
  11. package/dist/managed-media.d.ts +9 -0
  12. package/dist/managed-media.d.ts.map +1 -1
  13. package/dist/managed-media.js +1 -0
  14. package/dist/managed-media.js.map +1 -1
  15. package/dist/messaging-media.d.ts +10 -0
  16. package/dist/messaging-media.d.ts.map +1 -1
  17. package/dist/messaging-media.js +12 -4
  18. package/dist/messaging-media.js.map +1 -1
  19. package/dist/messaging-notification-postgres.d.ts +7 -0
  20. package/dist/messaging-notification-postgres.d.ts.map +1 -0
  21. package/dist/messaging-notification-postgres.js +32 -0
  22. package/dist/messaging-notification-postgres.js.map +1 -0
  23. package/dist/messaging-notification-providers.d.ts +26 -0
  24. package/dist/messaging-notification-providers.d.ts.map +1 -0
  25. package/dist/messaging-notification-providers.js +107 -0
  26. package/dist/messaging-notification-providers.js.map +1 -0
  27. package/dist/messaging-notifications.d.ts +66 -0
  28. package/dist/messaging-notifications.d.ts.map +1 -0
  29. package/dist/messaging-notifications.js +128 -0
  30. package/dist/messaging-notifications.js.map +1 -0
  31. package/dist/messaging-transforms.d.ts.map +1 -1
  32. package/dist/messaging-transforms.js +26 -5
  33. package/dist/messaging-transforms.js.map +1 -1
  34. package/dist/messaging.d.ts +11 -1
  35. package/dist/messaging.d.ts.map +1 -1
  36. package/dist/messaging.js +65 -7
  37. package/dist/messaging.js.map +1 -1
  38. package/dist/messenger.d.ts +53 -0
  39. package/dist/messenger.d.ts.map +1 -0
  40. package/dist/messenger.js +89 -0
  41. package/dist/messenger.js.map +1 -0
  42. package/dist/push.d.ts.map +1 -1
  43. package/dist/push.js +1 -0
  44. package/dist/push.js.map +1 -1
  45. package/dist/types.d.ts +12 -3
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/webhooks.d.ts.map +1 -1
  48. package/dist/webhooks.js +11 -1
  49. package/dist/webhooks.js.map +1 -1
  50. package/package.json +4 -2
  51. package/sql/messaging-notifications.sql +41 -0
@@ -0,0 +1,107 @@
1
+ import { createHash, createPrivateKey, sign } from 'node:crypto';
2
+ import { connect } from 'node:http2';
3
+ const b64 = (data) => Buffer.from(JSON.stringify(data)).toString('base64url');
4
+ function jwt(header, claims, key, algorithm, p1363 = false) {
5
+ const body = b64(header) + '.' + b64(claims);
6
+ const signature = sign(algorithm, Buffer.from(body), { key: createPrivateKey(key), ...(p1363 ? { dsaEncoding: 'ieee-p1363' } : {}) });
7
+ return body + '.' + signature.toString('base64url');
8
+ }
9
+ function collapse(data) { return createHash('sha256').update(data.accountScope + ':' + data.conversationId).digest('hex'); }
10
+ /** Uses only fixed Apple/Google endpoints. Private keys never enter notification payloads. */
11
+ export function createMessagingPushSender(options) {
12
+ const title = options.title?.trim() || 'New message';
13
+ if (title.length > 80)
14
+ throw Error('Use a notification title of 80 characters or fewer.');
15
+ const apple = options.apple, google = options.google;
16
+ if (apple && (!/^[A-Z\d]{10}$/.test(apple.teamId) || !/^[A-Z\d]{10}$/.test(apple.keyId) || !/^[-\w]+(?:\.[-\w]+)+$/.test(apple.bundleId)))
17
+ throw Error('Check the Apple Team ID, Key ID and app bundle ID.');
18
+ if (google && (!/^[a-z][a-z\d-]{4,61}[a-z\d]$/.test(google.projectId) || !/^[^\s@]+@[^\s@]+\.gserviceaccount\.com$/.test(google.clientEmail)))
19
+ throw Error('Check the Google project ID and service-account email.');
20
+ if (apple && (createPrivateKey(apple.privateKey).asymmetricKeyType !== 'ec' || createPrivateKey(apple.privateKey).asymmetricKeyDetails?.namedCurve !== 'prime256v1'))
21
+ throw Error('Use the Apple APNs .p8 signing key.');
22
+ if (google && createPrivateKey(google.privateKey).asymmetricKeyType !== 'rsa')
23
+ throw Error('Use the Google service-account private key.');
24
+ let appleToken = { value: '', expires: 0 }, googleToken = { value: '', expires: 0 }, googlePending;
25
+ const request = options.fetch ?? fetch;
26
+ async function googleAccess() {
27
+ if (googleToken.expires > Date.now())
28
+ return googleToken.value;
29
+ if (googlePending)
30
+ return googlePending;
31
+ googlePending = (async () => {
32
+ const now = Math.floor(Date.now() / 1000), assertion = jwt({ alg: 'RS256', typ: 'JWT' }, { iss: google.clientEmail, scope: 'https://www.googleapis.com/auth/firebase.messaging', aud: 'https://oauth2.googleapis.com/token', iat: now, exp: now + 3600 }, google.privateKey, 'RSA-SHA256');
33
+ const response = await request('https://oauth2.googleapis.com/token', { method: 'POST', redirect: 'error', signal: AbortSignal.timeout(15000), headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion }) });
34
+ const data = await response.json();
35
+ if (!response.ok || !data.access_token || typeof data.expires_in !== 'number')
36
+ throw Error('Google notification authentication failed.');
37
+ googleToken = { value: data.access_token, expires: Date.now() + Math.max(0, Math.min(data.expires_in, 3600) - 60) * 1000 };
38
+ return data.access_token;
39
+ })();
40
+ try {
41
+ return await googlePending;
42
+ }
43
+ finally {
44
+ googlePending = undefined;
45
+ }
46
+ }
47
+ async function sendApple(device, data) {
48
+ if (!apple)
49
+ return { accepted: false, retryable: false, code: 'apple_credentials_missing' };
50
+ if (!/^[a-f\d]{64,200}$/i.test(device.token))
51
+ return { accepted: false, invalidDevice: true, code: 'invalid_token' };
52
+ if (appleToken.expires <= Date.now())
53
+ appleToken = { value: jwt({ alg: 'ES256', kid: apple.keyId }, { iss: apple.teamId, iat: Math.floor(Date.now() / 1000) }, apple.privateKey, 'sha256', true), expires: Date.now() + 45 * 60000 };
54
+ const payload = JSON.stringify({ aps: { alert: { title, body: 'Open the app to read your message.' }, sound: 'default', 'thread-id': collapse(data) }, body: data });
55
+ return new Promise(resolve => {
56
+ const session = connect(apple.sandbox ? 'https://api.sandbox.push.apple.com' : 'https://api.push.apple.com');
57
+ let finished = false;
58
+ const finish = (result) => { if (finished)
59
+ return; finished = true; clearTimeout(timer); session.destroy(); resolve(result); };
60
+ const timer = setTimeout(() => finish({ accepted: false, retryable: true, code: 'apple_timeout' }), 15000);
61
+ session.on('error', () => finish({ accepted: false, retryable: true, code: 'apple_connection_failed' }));
62
+ const stream = session.request({ ':method': 'POST', ':path': '/3/device/' + device.token, authorization: 'bearer ' + appleToken.value, 'apns-topic': apple.bundleId, 'apns-push-type': 'alert', 'apns-priority': '10', 'apns-expiration': String(Math.floor(Date.now() / 1000) + 3600), 'apns-collapse-id': collapse(data), 'content-type': 'application/json' });
63
+ let status = 0, body = '';
64
+ stream.setEncoding('utf8');
65
+ stream.on('response', headers => { status = Number(headers[':status']); });
66
+ stream.on('data', chunk => { if (body.length < 8192)
67
+ body += chunk; });
68
+ stream.on('error', () => finish({ accepted: false, retryable: true, code: 'apple_connection_failed' }));
69
+ stream.on('end', () => {
70
+ let reason = '';
71
+ try {
72
+ reason = JSON.parse(body).reason;
73
+ }
74
+ catch { }
75
+ if (status === 403)
76
+ appleToken = { value: '', expires: 0 };
77
+ finish({ accepted: status === 200, invalidDevice: status === 410 || reason === 'BadDeviceToken', retryable: reason === 'ExpiredProviderToken' || status === 429 || status >= 500, code: status === 200 ? 'accepted' : status === 403 ? 'apple_credentials_rejected' : 'apple_rejected' });
78
+ });
79
+ stream.end(payload);
80
+ });
81
+ }
82
+ async function sendGoogle(device, data) {
83
+ if (!google)
84
+ return { accepted: false, retryable: false, code: 'google_credentials_missing' };
85
+ const response = await request('https://fcm.googleapis.com/v1/projects/' + encodeURIComponent(google.projectId) + '/messages:send', {
86
+ method: 'POST', redirect: 'error', signal: AbortSignal.timeout(15000), headers: { authorization: 'Bearer ' + await googleAccess(), 'content-type': 'application/json' },
87
+ body: JSON.stringify({ message: { token: device.token, notification: { title, body: 'Open the app to read your message.' }, data,
88
+ android: { priority: 'high', ttl: '3600s', collapse_key: collapse(data), notification: { tag: collapse(data), channel_id: 'robono-messages' } } } }),
89
+ });
90
+ const result = await response.json().catch(() => null);
91
+ if (response.status === 401)
92
+ googleToken = { value: '', expires: 0 };
93
+ return { accepted: response.ok, invalidDevice: result?.error?.details?.some(detail => detail.errorCode === 'UNREGISTERED') ?? false,
94
+ retryable: response.status === 401 || response.status === 429 || response.status >= 500, code: response.ok ? 'accepted' : response.status === 401 || response.status === 403 ? 'google_credentials_rejected' : 'google_rejected' };
95
+ }
96
+ return { providers: [...(apple ? ['apns'] : []), ...(google ? ['fcm'] : [])],
97
+ async send(device, data) {
98
+ try {
99
+ return device.provider === 'apns' ? await sendApple(device, data) : await sendGoogle(device, data);
100
+ }
101
+ catch {
102
+ return { accepted: false, retryable: true, code: 'provider_unavailable' };
103
+ }
104
+ },
105
+ };
106
+ }
107
+ //# sourceMappingURL=messaging-notification-providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-notification-providers.js","sourceRoot":"","sources":["../src/messaging-notification-providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { MessagingCreatedWebhookEvent } from './types.js';
2
+ export interface MessagingPushData {
3
+ event: 'robono.messaging';
4
+ eventId: string;
5
+ conversationId: string;
6
+ messageId: string;
7
+ accountScope: string;
8
+ }
9
+ export interface MessagingPushDevice {
10
+ id: string;
11
+ userId: string;
12
+ provider: 'apns' | 'fcm';
13
+ token: string;
14
+ }
15
+ export interface MessagingPushJob {
16
+ id: string;
17
+ lease: string;
18
+ event: MessagingCreatedWebhookEvent;
19
+ device: MessagingPushDevice;
20
+ attempt: number;
21
+ }
22
+ export interface MessagingNotificationStore {
23
+ /** Register tokens only for the authenticated user; a token belongs to one account at a time. */
24
+ register(scope: string, device: MessagingPushDevice): Promise<void>;
25
+ remove(scope: string, userId: string, id: string, expectedToken?: string): Promise<void>;
26
+ /** Atomically snapshot this recipient's registered devices; duplicate events do not add jobs. */
27
+ enqueue(scope: string, event: MessagingCreatedWebhookEvent): Promise<void>;
28
+ claim(scope: string, limit: number, lease: string): Promise<MessagingPushJob[]>;
29
+ /** Recheck token ownership after taking a job and immediately before delivery. */
30
+ current(scope: string, device: MessagingPushDevice): Promise<boolean>;
31
+ finish(scope: string, job: MessagingPushJob, result: {
32
+ state: 'sent' | 'skipped' | 'retry' | 'failed';
33
+ retryAt?: Date;
34
+ code?: string;
35
+ }): Promise<void>;
36
+ }
37
+ export interface MessagingNotificationOptions {
38
+ /** Separate scope and webhook secret for each customer integration and test/live environment. */
39
+ scope: string;
40
+ webhookSecret: string;
41
+ store: MessagingNotificationStore;
42
+ authenticate: (request: Request) => Promise<string | null>;
43
+ /** Required: current account status, conversation access, block/mute state, message existence. */
44
+ mayNotify: (event: MessagingCreatedWebhookEvent) => Promise<boolean>;
45
+ send: (device: MessagingPushDevice, data: MessagingPushData) => Promise<{
46
+ accepted: boolean;
47
+ invalidDevice?: boolean;
48
+ retryable?: boolean;
49
+ code?: string;
50
+ }>;
51
+ /** Only providers with configured server credentials can be registered. */
52
+ providers: readonly ('apns' | 'fcm')[];
53
+ }
54
+ export declare function messagingNotificationAccount(scope: string, userId: string): string;
55
+ /** Durable, content-free notifications. Apple/Google acceptance is not a delivery/read receipt. */
56
+ export declare function createMessagingNotifications(options: MessagingNotificationOptions): {
57
+ devices(request: Request): Promise<Response>;
58
+ webhook(request: Request): Promise<Response>;
59
+ runPending(limit?: number): Promise<{
60
+ sent: number;
61
+ skipped: number;
62
+ retried: number;
63
+ failed: number;
64
+ }>;
65
+ };
66
+ //# sourceMappingURL=messaging-notifications.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-notifications.d.ts","sourceRoot":"","sources":["../src/messaging-notifications.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { verifyRobonoWebhook } from './webhooks.js';
3
+ function id(value, max = 200) { return typeof value === 'string' && value.length > 0 && value.length <= max && value.trim() === value && !/[\u0000-\u001f\u007f]/.test(value); }
4
+ const reply = (data, status = 200) => Response.json(data, { status, headers: { 'cache-control': 'no-store' } });
5
+ export function messagingNotificationAccount(scope, userId) { return createHash('sha256').update(JSON.stringify([scope, userId])).digest('hex'); }
6
+ /** Durable, content-free notifications. Apple/Google acceptance is not a delivery/read receipt. */
7
+ export function createMessagingNotifications(options) {
8
+ if (!id(options.scope) || !options.webhookSecret.trim())
9
+ throw Error('Set a unique notification scope and this integration’s webhook secret.');
10
+ const { scope, store } = options;
11
+ return {
12
+ async devices(request) {
13
+ if (request.method !== 'POST')
14
+ return reply({ error: { code: 'method_not_allowed' } }, 405);
15
+ try {
16
+ const userId = await options.authenticate(request);
17
+ if (!id(userId))
18
+ return reply({ error: { code: 'authentication_required' } }, 401);
19
+ const raw = await request.text();
20
+ if (raw.length > 8192)
21
+ return reply({ error: { code: 'request_too_large' } }, 413);
22
+ let body;
23
+ try {
24
+ body = JSON.parse(raw);
25
+ }
26
+ catch {
27
+ return reply({ error: { code: 'invalid_request' } }, 422);
28
+ }
29
+ const accountScope = messagingNotificationAccount(scope, userId);
30
+ if (body?.operation === 'notification-status')
31
+ return reply({ userId, accountScope, providers: options.providers });
32
+ if (body?.accountScope !== accountScope)
33
+ return reply({ error: { code: 'notification_account_changed' } }, 409);
34
+ if (!body || typeof body !== 'object' || !id(body.deviceId))
35
+ return reply({ error: { code: 'invalid_device' } }, 422);
36
+ if (body.operation === 'remove-device') {
37
+ await store.remove(scope, userId, body.deviceId);
38
+ return reply({ ok: true });
39
+ }
40
+ if (body.operation !== 'register-device' || !['apns', 'fcm'].includes(String(body.provider)) || !id(body.token, 4096))
41
+ return reply({ error: { code: 'invalid_device' } }, 422);
42
+ const provider = body.provider;
43
+ if (!options.providers.includes(provider))
44
+ return reply({ error: { code: 'notification_credentials_missing', message: provider === 'apns' ? 'Your app’s Apple notification credentials have not been connected.' : 'Your app’s Google notification credentials have not been connected.' } }, 409);
45
+ if (provider === 'apns' && !/^[a-f\d]{64,200}$/i.test(body.token))
46
+ return reply({ error: { code: 'invalid_device' } }, 422);
47
+ await store.register(scope, { id: body.deviceId, userId, provider, token: body.token });
48
+ return reply({ ok: true, accountScope: messagingNotificationAccount(scope, userId) });
49
+ }
50
+ catch {
51
+ return reply({ error: { code: 'notifications_unavailable' } }, 503);
52
+ }
53
+ },
54
+ async webhook(request) {
55
+ if (request.method !== 'POST')
56
+ return reply({ error: { code: 'method_not_allowed' } }, 405);
57
+ const raw = await request.text();
58
+ if (raw.length > 32768)
59
+ return reply({ error: { code: 'request_too_large' } }, 413);
60
+ let event;
61
+ try {
62
+ ({ event } = await verifyRobonoWebhook(raw, request.headers, options.webhookSecret));
63
+ }
64
+ catch {
65
+ return reply({ error: { code: 'invalid_webhook' } }, 401);
66
+ }
67
+ if (event.event !== 'messaging.message_created')
68
+ return reply({ ignored: true });
69
+ // Do not acknowledge until the queue insert is durable. Delivery is retried by the worker.
70
+ try {
71
+ await store.enqueue(scope, event);
72
+ return reply({ queued: true }, 202);
73
+ }
74
+ catch {
75
+ return reply({ error: { code: 'notifications_unavailable' } }, 503);
76
+ }
77
+ },
78
+ async runPending(limit = 20) {
79
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100)
80
+ throw Error('Use a notification batch size from 1 to 100.');
81
+ const result = { sent: 0, skipped: 0, retried: 0, failed: 0 };
82
+ // Small batches avoid unbounded fanout and provider rate spikes.
83
+ for (let index = 0; index < limit; index++) {
84
+ const [job] = await store.claim(scope, 1, randomUUID());
85
+ if (!job)
86
+ break;
87
+ try {
88
+ const event = job.event;
89
+ if (job.device.userId !== event.recipient_external_user_id || event.notification_muted === true ||
90
+ Date.parse(event.created_at) < Date.now() - 86400000 || !await options.mayNotify(event) || !await store.current(scope, job.device)) {
91
+ await store.finish(scope, job, { state: 'skipped' });
92
+ result.skipped++;
93
+ continue;
94
+ }
95
+ const data = { event: 'robono.messaging', eventId: event.event_id,
96
+ conversationId: event.conversation_id, messageId: event.message_id, accountScope: messagingNotificationAccount(scope, job.device.userId) };
97
+ const sent = await options.send(job.device, data);
98
+ if (sent.invalidDevice) {
99
+ await store.remove(scope, job.device.userId, job.device.id, job.device.token);
100
+ await store.finish(scope, job, { state: 'skipped', code: 'device_unregistered' });
101
+ result.skipped++;
102
+ }
103
+ else if (sent.accepted) {
104
+ await store.finish(scope, job, { state: 'sent' });
105
+ result.sent++;
106
+ }
107
+ else if (sent.retryable !== false && job.attempt < 8) {
108
+ await store.finish(scope, job, { state: 'retry', retryAt: new Date(Date.now() + Math.min(3600000, 15000 * 2 ** job.attempt)), code: sent.code ?? 'provider_unavailable' });
109
+ result.retried++;
110
+ }
111
+ else {
112
+ await store.finish(scope, job, { state: 'failed', code: sent.code ?? 'provider_rejected' });
113
+ result.failed++;
114
+ }
115
+ }
116
+ catch {
117
+ await store.finish(scope, job, job.attempt < 8 ? { state: 'retry', retryAt: new Date(Date.now() + Math.min(3600000, 15000 * 2 ** job.attempt)), code: 'delivery_unavailable' } : { state: 'failed', code: 'delivery_unavailable' });
118
+ if (job.attempt < 8)
119
+ result.retried++;
120
+ else
121
+ result.failed++;
122
+ }
123
+ }
124
+ return result;
125
+ },
126
+ };
127
+ }
128
+ //# sourceMappingURL=messaging-notifications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-notifications.js","sourceRoot":"","sources":["../src/messaging-notifications.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"messaging-transforms.d.ts","sourceRoot":"","sources":["../src/messaging-transforms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAG9C,uGAAuG;AACvG,wBAAgB,sCAAsC,CAAC,OAAO,EAAC;IAC9D,MAAM,EAAC,sBAAsB,CAAC;IAAA,MAAM,EAAC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAC,QAAQ,CAAC,CAAC;IAC/E,OAAO,EAAC,IAAI,CAAC,uBAAuB,EAAC,UAAU,CAAC,CAAC;IACjD,YAAY,CAAC,OAAO,EAAC,OAAO,GAAE,OAAO,CAAC,MAAM,GAAC,IAAI,CAAC,CAAC;IACnD,SAAS,CAAC,KAAK,EAAC;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,cAAc,EAAC,MAAM,CAAC;QAAA,SAAS,EAAC,MAAM,CAAC;QAAA,SAAS,EAAC,YAAY,GAAC,aAAa,CAAC;QAAA,OAAO,EAAC,OAAO,CAAA;KAAC,GAAE,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/I,IACa,SAAQ,OAAO,uBA6B5B"}
1
+ {"version":3,"file":"messaging-transforms.d.ts","sourceRoot":"","sources":["../src/messaging-transforms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAG9C,uGAAuG;AACvG,wBAAgB,sCAAsC,CAAC,OAAO,EAAC;IAC9D,MAAM,EAAC,sBAAsB,CAAC;IAAA,MAAM,EAAC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAC,QAAQ,CAAC,CAAC;IAC/E,OAAO,EAAC,IAAI,CAAC,uBAAuB,EAAC,UAAU,CAAC,CAAC;IACjD,YAAY,CAAC,OAAO,EAAC,OAAO,GAAE,OAAO,CAAC,MAAM,GAAC,IAAI,CAAC,CAAC;IACnD,SAAS,CAAC,KAAK,EAAC;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,cAAc,EAAC,MAAM,CAAC;QAAA,SAAS,EAAC,MAAM,CAAC;QAAA,SAAS,EAAC,YAAY,GAAC,aAAa,CAAC;QAAA,OAAO,EAAC,OAAO,CAAA;KAAC,GAAE,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/I,IACa,SAAQ,OAAO,uBA4C5B"}
@@ -21,14 +21,23 @@ export function createMessagingTransformBackendAdapter(options) {
21
21
  }
22
22
  if (!input || !['transcript', 'translation'].includes(input.operation) || typeof input.conversationId !== 'string' || !/^[0-9a-f-]{36}$/i.test(input.conversationId) || typeof input.messageId !== 'string' || !/^\d{1,19}$/.test(input.messageId) || BigInt(input.messageId) < 1n || BigInt(input.messageId) > 9223372036854775807n || input.operation === 'translation' && (typeof input.language !== 'string' || !/^[a-z]{2,3}(?:-[a-z0-9]{2,8}){0,2}$/i.test(input.language)))
23
23
  return reply({ error: { code: 'invalid_transform' } }, 422);
24
+ if (input.output !== undefined && !['text', 'voice'].includes(input.output) || input.operation === 'transcript' && input.output === 'voice')
25
+ return reply({ error: { code: 'invalid_transform' } }, 422);
26
+ const voice = input.operation === 'translation' && input.output === 'voice';
24
27
  const context = { actorId, conversationId: input.conversationId, messageId: input.messageId, operation: input.operation, request };
25
28
  if (!await options.authorize(context))
26
29
  return reply({ error: { code: 'operation_not_allowed' } }, 403);
27
- const read = () => options.robono.request('list', { actorId, conversationId: input.conversationId, limit: 1, messageIds: [input.messageId] });
30
+ const read = () => options.robono.request('list', { actorId, conversationId: input.conversationId, limit: 1, messageIds: [input.messageId], messageActionsVersion: 1 });
28
31
  const page = await read(), message = page.messages?.find((m) => m.id === input.messageId), flag = input.operation === 'transcript' ? 'transcription' : 'translation';
29
32
  const permitted = (p) => p.settings?.enabled && p.settings.features?.[flag] === true;
30
33
  if (!permitted(page) || !message || message.deleted || input.operation === 'transcript' && message.kind !== 'voice' || !['voice', 'text'].includes(message.kind))
31
34
  return reply({ error: { code: 'transform_unavailable' } }, 403);
35
+ const signature = (m) => JSON.stringify({ kind: m.kind, text: m.text, media: m.media, revision: m.revision });
36
+ const original = signature(message);
37
+ // A transcript or spoken translation reveals the recording just as playback
38
+ // does. Lock incoming media before processing when the current backend supports it.
39
+ if (message.kind === 'voice' && message.senderId !== actorId && page.messageActionsAvailable)
40
+ await options.robono.request('consume', { actorId, conversationId: input.conversationId, messageId: message.id });
32
41
  const source = message.kind === 'text' ? { type: 'text', text: message.text } : await (async () => {
33
42
  const plan = await options.storage.download({ actorId, conversationId: input.conversationId, messageId: message.id, media: message.media });
34
43
  const url = new URL(plan.url);
@@ -37,16 +46,28 @@ export function createMessagingTransformBackendAdapter(options) {
37
46
  return { type: 'audio', source_url: plan.url, mime_type: message.media.mimeType };
38
47
  })();
39
48
  const language = input.operation === 'translation' ? input.language : undefined;
40
- const key = `messaging:${input.conversationId}:${message.id}:${input.operation}:${language ?? 'auto'}`;
41
- const result = await options.speech.speech({ external_request_id: key, input: source, outputs: [input.operation === 'transcript' ? 'transcript' : 'translated_text'], ...(language ? { target_language: language } : {}) }, { idempotencyKey: key });
49
+ const key = `messaging:${input.conversationId}:${message.id}:r${message.revision ?? 0}:${input.operation}:${language ?? 'auto'}${voice ? ':voice' : ''}`;
50
+ const result = await options.speech.speech({ external_request_id: key, input: source, outputs: voice ? ['translated_text', 'translated_voice'] : [input.operation === 'transcript' ? 'transcript' : 'translated_text'], ...(language ? { target_language: language } : {}) }, { idempotencyKey: key });
42
51
  // A block, removal or retention change during processing must not reveal text.
43
52
  const current = await read();
44
- if (!permitted(current) || !current.messages?.some((m) => m.id === message.id && !m.deleted) || !await options.authorize(context))
53
+ if (!permitted(current) || !current.messages?.some((m) => m.id === message.id && !m.deleted && signature(m) === original) || await options.authenticate(request) !== actorId || !await options.authorize(context))
45
54
  return reply({ error: { code: 'transform_unavailable' } }, 403);
46
55
  const artifact = input.operation === 'transcript' ? result.artifacts.transcript : result.artifacts.translated_text;
47
56
  if (!artifact || typeof artifact.text !== 'string')
48
57
  throw Error('Speech result unavailable');
49
- return reply({ messageId: message.id, text: artifact.text, language: artifact.target_language ?? artifact.language, kind: input.operation });
58
+ let audio;
59
+ if (voice) {
60
+ const media = result.artifacts.translated_voice?.media;
61
+ if (!media || typeof media.source_url !== 'string' || typeof media.mime_type !== 'string' || !media.mime_type.startsWith('audio/') || !Number.isFinite(Date.parse(media.source_url_expires_at)) || Date.parse(media.source_url_expires_at) <= Date.now())
62
+ throw Error('Translated voice is unavailable');
63
+ if (!Number.isSafeInteger(media.byte_size) || media.byte_size < 1 || media.byte_size > 100 * 1024 * 1024 || media.duration_ms != null && (!Number.isSafeInteger(media.duration_ms) || media.duration_ms < 1 || media.duration_ms > 3600000) || media.waveform !== undefined && (!Array.isArray(media.waveform) || media.waveform.length > 128 || media.waveform.some((peak) => !Number.isFinite(peak) || peak < 0 || peak > 1)))
64
+ throw Error('Invalid translated voice metadata');
65
+ const url = new URL(media.source_url);
66
+ if (url.protocol !== 'https:' || url.username || url.password)
67
+ throw Error('Invalid translated voice URL');
68
+ audio = { url: url.href, expiresAt: media.source_url_expires_at, mimeType: media.mime_type, durationMs: media.duration_ms ?? undefined, byteSize: media.byte_size, waveform: media.waveform };
69
+ }
70
+ return reply({ messageId: message.id, text: artifact.text, language: artifact.target_language ?? artifact.language, kind: input.operation, ...(audio ? { audio } : {}) });
50
71
  }
51
72
  catch (e) {
52
73
  if (e instanceof RobonoError)
@@ -1 +1 @@
1
- {"version":3,"file":"messaging-transforms.js","sourceRoot":"","sources":["../src/messaging-transforms.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messaging-transforms.js","sourceRoot":"","sources":["../src/messaging-transforms.ts"],"names":[],"mappings":"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"}
@@ -25,7 +25,9 @@ export declare class RobonoMessagingBackend {
25
25
  private options;
26
26
  private url;
27
27
  constructor(options: MessagingBackendOptions);
28
- request(operation: string, input?: Record<string, unknown>): Promise<any>;
28
+ request(operation: string, input?: Record<string, unknown>, options?: {
29
+ signal?: AbortSignal;
30
+ }): Promise<any>;
29
31
  setRelationship(input: {
30
32
  externalUserIds: [string, string];
31
33
  allowed: boolean;
@@ -37,6 +39,8 @@ export declare class RobonoMessagingBackend {
37
39
  name: string;
38
40
  revision: number;
39
41
  allowed: boolean;
42
+ supergroup?: boolean;
43
+ ownerId?: string;
40
44
  members: {
41
45
  userId: string;
42
46
  canSend: boolean;
@@ -53,6 +57,12 @@ export declare class RobonoMessagingBackend {
53
57
  reviewerId: string;
54
58
  }): Promise<any>;
55
59
  settings(): Promise<any>;
60
+ /** Recheck the live recipient, message, membership, blocks and mute state before an alert. */
61
+ canNotify(input: {
62
+ userId: string;
63
+ conversationId: string;
64
+ messageId: string;
65
+ }): Promise<any>;
56
66
  /** Erases this user's hosted conversations. Delete the corresponding private media in your own store too. */
57
67
  eraseUser(userId: string): Promise<any>;
58
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../src/messaging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../src/messaging.ts"],"names":[],"mappings":"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"}
package/dist/messaging.js CHANGED
@@ -11,11 +11,11 @@ export class RobonoMessagingBackend {
11
11
  throw Error("Use an HTTPS endpoint and a server API key.");
12
12
  this.url = url.href;
13
13
  }
14
- async request(operation, input = {}) {
14
+ async request(operation, input = {}, options) {
15
15
  const result = await (this.options.fetch ?? fetch)(this.url, {
16
16
  method: "POST",
17
17
  redirect: "error",
18
- signal: AbortSignal.timeout(15000),
18
+ signal: options?.signal ? AbortSignal.any([options.signal, AbortSignal.timeout(operation === 'wait' ? 35000 : 15000)]) : AbortSignal.timeout(operation === 'wait' ? 35000 : 15000),
19
19
  headers: {
20
20
  authorization: `Bearer ${this.options.apiKey}`,
21
21
  "content-type": "application/json",
@@ -53,6 +53,21 @@ export class RobonoMessagingBackend {
53
53
  settings() {
54
54
  return this.request("settings");
55
55
  }
56
+ /** Recheck the live recipient, message, membership, blocks and mute state before an alert. */
57
+ async canNotify(input) {
58
+ try {
59
+ const result = await this.request('list', { actorId: input.userId, conversationId: input.conversationId,
60
+ messageIds: [input.messageId], notificationMessageId: input.messageId });
61
+ if (typeof result.notificationAllowed !== 'boolean')
62
+ throw new RobonoError('Install the notification-access service update before enabling alerts.', { status: 503, code: 'notification_access_unavailable', retryable: true });
63
+ return result.notificationAllowed;
64
+ }
65
+ catch (error) {
66
+ if (error instanceof RobonoError && [401, 403, 404].includes(error.status ?? 0))
67
+ return false;
68
+ throw error;
69
+ }
70
+ }
56
71
  /** Erases this user's hosted conversations. Delete the corresponding private media in your own store too. */
57
72
  eraseUser(userId) {
58
73
  return this.request("erase-user", { userId });
@@ -78,7 +93,7 @@ export function createMessagingBackendAdapter(options) {
78
93
  return respond({ error: { code: "authentication_required" } }, 401);
79
94
  }
80
95
  const raw = await request.text();
81
- if (raw.length > 20000) {
96
+ if (raw.length > 900000) {
82
97
  return respond({ error: { code: "request_too_large" } }, 413);
83
98
  }
84
99
  let body;
@@ -92,11 +107,17 @@ export function createMessagingBackendAdapter(options) {
92
107
  return respond({ error: { code: "invalid_request" } }, 422);
93
108
  }
94
109
  const operation = String(body.operation ?? "");
95
- if (!["settings", "send", "send-call-message", "call-message-options", "list", "read", "react", "vote", "close-poll", "inventory", "safety", "block", "unblock", "report"].includes(operation))
110
+ if (raw.length > 20000 && !["group-create", "group-update"].includes(operation))
111
+ return respond({ error: { code: "request_too_large" } }, 413);
112
+ if (!["settings", "send", "edit", "delete", "consume", "conversation-preferences", "conversation-delete", "send-call-message", "call-message-options", "list", "search", "social-preview", "conversations", "seen", "presence-update", "wait", "group-members", "group-create", "group-update", "group-leave", "read", "react", "pin", "vote", "close-poll", "inventory", "safety", "block", "unblock", "report"].includes(operation))
96
113
  return respond({ error: { code: "operation_not_allowed" } }, 403);
97
114
  const input = { ...body, actorId };
115
+ if (['list', 'conversations', 'group-members'].includes(operation)) {
116
+ input.groupControlsVersion = 1;
117
+ input.discussionVersion = 1;
118
+ }
98
119
  delete input.operation;
99
- if (!await options.authorize({ actorId, operation, input, request })) {
120
+ if (!await options.authorize({ actorId, operation: operation === 'wait' || operation === 'social-preview' ? 'list' : operation, input, request })) {
100
121
  return respond({ error: { code: "operation_not_allowed" } }, 403);
101
122
  }
102
123
  const callMessage = operation === 'send-call-message' || operation === 'call-message-options';
@@ -119,7 +140,7 @@ export function createMessagingBackendAdapter(options) {
119
140
  return respond({ error: { code: 'call_message_unavailable' } }, 403);
120
141
  }
121
142
  delete input.unansweredCallId;
122
- if ((operation === "send" || operation === 'send-call-message') && input.kind !== "text" && input.kind !== "poll" && options.resolveMedia) {
143
+ if ((operation === "send" || operation === 'send-call-message' || operation === 'edit' && input.kind !== undefined) && input.kind !== "text" && input.kind !== "poll" && options.resolveMedia) {
123
144
  const candidate = input.media;
124
145
  if (typeof candidate?.assetId !== "string" || typeof input.conversationId !== "string")
125
146
  return respond({ error: { code: "invalid_media_request" } }, 422);
@@ -128,7 +149,44 @@ export function createMessagingBackendAdapter(options) {
128
149
  return respond({ error: { code: "attachment_unavailable" } }, 403);
129
150
  input.media = stored;
130
151
  }
131
- return respond(await options.robono.request(operation === 'send-call-message' ? 'send' : operation, input));
152
+ if (operation === 'list') {
153
+ input.liveUpdates = true;
154
+ input.messageActionsVersion = 1;
155
+ input.socialPreviewVersion = 1;
156
+ }
157
+ if (operation === 'conversations')
158
+ input.inboxActionsVersion = 1;
159
+ const result = await options.robono.request(operation === 'send-call-message' ? 'send' : operation, input, { signal: request.signal });
160
+ if (operation === 'conversations') {
161
+ if (!Array.isArray(result?.conversations) || result.conversations.length > 50)
162
+ return respond({ error: { code: 'invalid_messaging_response' } }, 502);
163
+ // A customer can revoke a chat locally before its membership sync arrives.
164
+ // Check each preview against that customer's current list permission too.
165
+ const allowed = await Promise.all(result.conversations.map(async (row) => typeof row.id === 'string' && await options.authorize({ actorId, operation: 'list', input: { actorId, conversationId: row.id }, request })));
166
+ result.conversations = result.conversations.filter((_row, index) => allowed[index]);
167
+ if (input.query !== undefined) {
168
+ if (result.globalSearchAvailable !== true || !Array.isArray(result.searchResults) || result.searchResults.length > 50)
169
+ return respond({ error: { code: 'search_unavailable' } }, 503);
170
+ const decisions = new Map();
171
+ const searchAllowed = await Promise.all(result.searchResults.map((row) => {
172
+ const id = row.conversation?.id;
173
+ if (typeof id !== 'string' || row.message?.conversationId !== id)
174
+ return false;
175
+ let decision = decisions.get(id);
176
+ if (!decision) {
177
+ decision = options.authorize({ actorId, operation: 'list', input: { actorId, conversationId: id }, request });
178
+ decisions.set(id, decision);
179
+ }
180
+ return decision;
181
+ }));
182
+ result.searchResults = result.searchResults.filter((_row, index) => searchAllowed[index]);
183
+ }
184
+ if (await options.authenticate(request) !== actorId)
185
+ return respond({ error: { code: 'authentication_required' } }, 401);
186
+ }
187
+ if ((operation === 'wait' || operation === 'social-preview') && (await options.authenticate(request) !== actorId || !await options.authorize({ actorId, operation: 'list', input, request })))
188
+ return respond({ error: { code: 'authentication_required' } }, 401);
189
+ return respond(result);
132
190
  }
133
191
  catch (e) {
134
192
  if (e instanceof RobonoError) {