@rei-standard/amsg-server 2.0.1 → 2.1.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/dist/index.cjs CHANGED
@@ -100,7 +100,7 @@ function validateScheduleMessagePayload(payload) {
100
100
  if (payload.uuid && !isValidUUID(payload.uuid)) {
101
101
  return { valid: false, errorCode: "INVALID_PARAMETERS", errorMessage: "\u7F3A\u5C11\u5FC5\u9700\u53C2\u6570\u6216\u53C2\u6570\u683C\u5F0F\u9519\u8BEF", details: { invalidFields: ["uuid (invalid UUID format)"] } };
102
102
  }
103
- if (payload.messageSubtype && !["chat", "forum", "moment"].includes(payload.messageSubtype)) {
103
+ if (payload.messageSubtype !== void 0 && payload.messageSubtype !== null && typeof payload.messageSubtype !== "string") {
104
104
  return { valid: false, errorCode: "INVALID_PARAMETERS", errorMessage: "\u7F3A\u5C11\u5FC5\u9700\u53C2\u6570\u6216\u53C2\u6570\u683C\u5F0F\u9519\u8BEF", details: { invalidFields: ["messageSubtype"] } };
105
105
  }
106
106
  return { valid: true };
@@ -1235,15 +1235,21 @@ function verifyTenantToken(token, secret, options = {}) {
1235
1235
  const [encodedHeader, encodedPayload, receivedSignature] = parts;
1236
1236
  const signingInput = `${encodedHeader}.${encodedPayload}`;
1237
1237
  const expectedSignature = sign(signingInput, secret);
1238
- const receivedBuffer = Buffer.from(receivedSignature);
1239
- const expectedBuffer = Buffer.from(expectedSignature);
1238
+ let receivedBuffer;
1239
+ let expectedBuffer;
1240
+ try {
1241
+ receivedBuffer = base64UrlDecode2(receivedSignature);
1242
+ expectedBuffer = base64UrlDecode2(expectedSignature);
1243
+ } catch (e4) {
1244
+ throw new Error("INVALID_TENANT_AUTH");
1245
+ }
1240
1246
  if (receivedBuffer.length !== expectedBuffer.length || !_crypto.timingSafeEqual.call(void 0, receivedBuffer, expectedBuffer)) {
1241
1247
  throw new Error("INVALID_TENANT_AUTH");
1242
1248
  }
1243
1249
  let payload;
1244
1250
  try {
1245
1251
  payload = JSON.parse(base64UrlDecode2(encodedPayload).toString("utf8"));
1246
- } catch (e4) {
1252
+ } catch (e5) {
1247
1253
  throw new Error("INVALID_TENANT_AUTH");
1248
1254
  }
1249
1255
  if (!payload || typeof payload !== "object" || payload.v !== 1) {
@@ -1300,7 +1306,7 @@ function parseTokenFromUrl(url) {
1300
1306
  try {
1301
1307
  const parsed = new URL(url, "https://dummy.local");
1302
1308
  return String(parsed.searchParams.get("token") || "").trim();
1303
- } catch (e5) {
1309
+ } catch (e6) {
1304
1310
  return "";
1305
1311
  }
1306
1312
  }
package/dist/index.d.cts CHANGED
@@ -174,7 +174,14 @@ function validateScheduleMessagePayload(payload) {
174
174
  if (payload.uuid && !isValidUUID(payload.uuid)) {
175
175
  return { valid: false, errorCode: 'INVALID_PARAMETERS', errorMessage: '缺少必需参数或参数格式错误', details: { invalidFields: ['uuid (invalid UUID format)'] } };
176
176
  }
177
- if (payload.messageSubtype && !['chat', 'forum', 'moment'].includes(payload.messageSubtype)) {
177
+ // messageSubtype is a free-form string tag forwarded to SW-side push payload
178
+ // for classification. Only the type is enforced; the taxonomy is the
179
+ // consumer's call (previously the enum was chat/forum/moment).
180
+ if (
181
+ payload.messageSubtype !== undefined &&
182
+ payload.messageSubtype !== null &&
183
+ typeof payload.messageSubtype !== 'string'
184
+ ) {
178
185
  return { valid: false, errorCode: 'INVALID_PARAMETERS', errorMessage: '缺少必需参数或参数格式错误', details: { invalidFields: ['messageSubtype'] } };
179
186
  }
180
187
 
@@ -1792,8 +1799,17 @@ function verifyTenantToken(token, secret, options = {}) {
1792
1799
  const signingInput = `${encodedHeader}.${encodedPayload}`;
1793
1800
  const expectedSignature = sign(signingInput, secret);
1794
1801
 
1795
- const receivedBuffer = Buffer.from(receivedSignature);
1796
- const expectedBuffer = Buffer.from(expectedSignature);
1802
+ // Compare raw HMAC bytes (decoded from base64url) rather than the
1803
+ // encoded character bytes — semantically clearer and avoids the
1804
+ // implicit-UTF-8 default of Buffer.from(string).
1805
+ let receivedBuffer;
1806
+ let expectedBuffer;
1807
+ try {
1808
+ receivedBuffer = base64UrlDecode(receivedSignature);
1809
+ expectedBuffer = base64UrlDecode(expectedSignature);
1810
+ } catch {
1811
+ throw new Error('INVALID_TENANT_AUTH');
1812
+ }
1797
1813
  if (
1798
1814
  receivedBuffer.length !== expectedBuffer.length ||
1799
1815
  !timingSafeEqual(receivedBuffer, expectedBuffer)
package/dist/index.d.ts CHANGED
@@ -174,7 +174,14 @@ function validateScheduleMessagePayload(payload) {
174
174
  if (payload.uuid && !isValidUUID(payload.uuid)) {
175
175
  return { valid: false, errorCode: 'INVALID_PARAMETERS', errorMessage: '缺少必需参数或参数格式错误', details: { invalidFields: ['uuid (invalid UUID format)'] } };
176
176
  }
177
- if (payload.messageSubtype && !['chat', 'forum', 'moment'].includes(payload.messageSubtype)) {
177
+ // messageSubtype is a free-form string tag forwarded to SW-side push payload
178
+ // for classification. Only the type is enforced; the taxonomy is the
179
+ // consumer's call (previously the enum was chat/forum/moment).
180
+ if (
181
+ payload.messageSubtype !== undefined &&
182
+ payload.messageSubtype !== null &&
183
+ typeof payload.messageSubtype !== 'string'
184
+ ) {
178
185
  return { valid: false, errorCode: 'INVALID_PARAMETERS', errorMessage: '缺少必需参数或参数格式错误', details: { invalidFields: ['messageSubtype'] } };
179
186
  }
180
187
 
@@ -1792,8 +1799,17 @@ function verifyTenantToken(token, secret, options = {}) {
1792
1799
  const signingInput = `${encodedHeader}.${encodedPayload}`;
1793
1800
  const expectedSignature = sign(signingInput, secret);
1794
1801
 
1795
- const receivedBuffer = Buffer.from(receivedSignature);
1796
- const expectedBuffer = Buffer.from(expectedSignature);
1802
+ // Compare raw HMAC bytes (decoded from base64url) rather than the
1803
+ // encoded character bytes — semantically clearer and avoids the
1804
+ // implicit-UTF-8 default of Buffer.from(string).
1805
+ let receivedBuffer;
1806
+ let expectedBuffer;
1807
+ try {
1808
+ receivedBuffer = base64UrlDecode(receivedSignature);
1809
+ expectedBuffer = base64UrlDecode(expectedSignature);
1810
+ } catch {
1811
+ throw new Error('INVALID_TENANT_AUTH');
1812
+ }
1797
1813
  if (
1798
1814
  receivedBuffer.length !== expectedBuffer.length ||
1799
1815
  !timingSafeEqual(receivedBuffer, expectedBuffer)
package/dist/index.mjs CHANGED
@@ -100,7 +100,7 @@ function validateScheduleMessagePayload(payload) {
100
100
  if (payload.uuid && !isValidUUID(payload.uuid)) {
101
101
  return { valid: false, errorCode: "INVALID_PARAMETERS", errorMessage: "\u7F3A\u5C11\u5FC5\u9700\u53C2\u6570\u6216\u53C2\u6570\u683C\u5F0F\u9519\u8BEF", details: { invalidFields: ["uuid (invalid UUID format)"] } };
102
102
  }
103
- if (payload.messageSubtype && !["chat", "forum", "moment"].includes(payload.messageSubtype)) {
103
+ if (payload.messageSubtype !== void 0 && payload.messageSubtype !== null && typeof payload.messageSubtype !== "string") {
104
104
  return { valid: false, errorCode: "INVALID_PARAMETERS", errorMessage: "\u7F3A\u5C11\u5FC5\u9700\u53C2\u6570\u6216\u53C2\u6570\u683C\u5F0F\u9519\u8BEF", details: { invalidFields: ["messageSubtype"] } };
105
105
  }
106
106
  return { valid: true };
@@ -1235,8 +1235,14 @@ function verifyTenantToken(token, secret, options = {}) {
1235
1235
  const [encodedHeader, encodedPayload, receivedSignature] = parts;
1236
1236
  const signingInput = `${encodedHeader}.${encodedPayload}`;
1237
1237
  const expectedSignature = sign(signingInput, secret);
1238
- const receivedBuffer = Buffer.from(receivedSignature);
1239
- const expectedBuffer = Buffer.from(expectedSignature);
1238
+ let receivedBuffer;
1239
+ let expectedBuffer;
1240
+ try {
1241
+ receivedBuffer = base64UrlDecode2(receivedSignature);
1242
+ expectedBuffer = base64UrlDecode2(expectedSignature);
1243
+ } catch {
1244
+ throw new Error("INVALID_TENANT_AUTH");
1245
+ }
1240
1246
  if (receivedBuffer.length !== expectedBuffer.length || !timingSafeEqual(receivedBuffer, expectedBuffer)) {
1241
1247
  throw new Error("INVALID_TENANT_AUTH");
1242
1248
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rei-standard/amsg-server",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "ReiStandard Active Messaging server SDK with pluggable database adapters",
5
5
  "repository": {
6
6
  "type": "git",