@openclaw/crabline 0.1.10 → 0.1.12

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 (197) hide show
  1. package/README.md +99 -12
  2. package/dist/src/bin/crabline.js +3 -1
  3. package/dist/src/bin/crabline.js.map +1 -1
  4. package/dist/src/cli/program.d.ts +5 -1
  5. package/dist/src/cli/program.js +264 -50
  6. package/dist/src/cli/program.js.map +1 -1
  7. package/dist/src/config/load.js +39 -3
  8. package/dist/src/config/load.js.map +1 -1
  9. package/dist/src/config/schema.d.ts +20 -0
  10. package/dist/src/config/schema.js +163 -35
  11. package/dist/src/config/schema.js.map +1 -1
  12. package/dist/src/core/errors.d.ts +1 -0
  13. package/dist/src/core/errors.js +6 -3
  14. package/dist/src/core/errors.js.map +1 -1
  15. package/dist/src/core/http-path.d.ts +1 -0
  16. package/dist/src/core/http-path.js +14 -0
  17. package/dist/src/core/http-path.js.map +1 -0
  18. package/dist/src/core/matcher.d.ts +3 -1
  19. package/dist/src/core/matcher.js +58 -2
  20. package/dist/src/core/matcher.js.map +1 -1
  21. package/dist/src/core/nonces.d.ts +2 -0
  22. package/dist/src/core/nonces.js +11 -1
  23. package/dist/src/core/nonces.js.map +1 -1
  24. package/dist/src/core/reporters.d.ts +5 -0
  25. package/dist/src/core/reporters.js +26 -2
  26. package/dist/src/core/reporters.js.map +1 -1
  27. package/dist/src/core/run.d.ts +3 -1
  28. package/dist/src/core/run.js +178 -66
  29. package/dist/src/core/run.js.map +1 -1
  30. package/dist/src/matrix-ids.d.ts +5 -0
  31. package/dist/src/matrix-ids.js +83 -0
  32. package/dist/src/matrix-ids.js.map +1 -0
  33. package/dist/src/openclaw/artifact-generation.d.ts +12 -2
  34. package/dist/src/openclaw/artifact-generation.js +436 -15
  35. package/dist/src/openclaw/artifact-generation.js.map +1 -1
  36. package/dist/src/openclaw/bridges/matrix.js +21 -4
  37. package/dist/src/openclaw/bridges/matrix.js.map +1 -1
  38. package/dist/src/openclaw/bridges/mattermost.js +13 -8
  39. package/dist/src/openclaw/bridges/mattermost.js.map +1 -1
  40. package/dist/src/openclaw/bridges/probe-response.d.ts +1 -0
  41. package/dist/src/openclaw/bridges/probe-response.js +5 -0
  42. package/dist/src/openclaw/bridges/probe-response.js.map +1 -0
  43. package/dist/src/openclaw/bridges/signal.js +15 -6
  44. package/dist/src/openclaw/bridges/signal.js.map +1 -1
  45. package/dist/src/openclaw/bridges/slack.js +116 -23
  46. package/dist/src/openclaw/bridges/slack.js.map +1 -1
  47. package/dist/src/openclaw/bridges/telegram.js +45 -19
  48. package/dist/src/openclaw/bridges/telegram.js.map +1 -1
  49. package/dist/src/openclaw/bridges/whatsapp.js +32 -16
  50. package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
  51. package/dist/src/openclaw/bridges/zalo.js +8 -3
  52. package/dist/src/openclaw/bridges/zalo.js.map +1 -1
  53. package/dist/src/openclaw/private-file.d.ts +40 -3
  54. package/dist/src/openclaw/private-file.js +2070 -95
  55. package/dist/src/openclaw/private-file.js.map +1 -1
  56. package/dist/src/openclaw/shared.d.ts +1 -0
  57. package/dist/src/openclaw/shared.js +48 -13
  58. package/dist/src/openclaw/shared.js.map +1 -1
  59. package/dist/src/openclaw/smoke-lock.d.ts +9 -0
  60. package/dist/src/openclaw/smoke-lock.js +696 -187
  61. package/dist/src/openclaw/smoke-lock.js.map +1 -1
  62. package/dist/src/openclaw.js +352 -29
  63. package/dist/src/openclaw.js.map +1 -1
  64. package/dist/src/platform/process-owned-lock.d.ts +11 -0
  65. package/dist/src/platform/process-owned-lock.js +1698 -0
  66. package/dist/src/platform/process-owned-lock.js.map +1 -0
  67. package/dist/src/platform/recorder-directory.d.ts +1 -0
  68. package/dist/src/platform/recorder-directory.js +14 -0
  69. package/dist/src/platform/recorder-directory.js.map +1 -0
  70. package/dist/src/platform/windows-acl.d.ts +18 -0
  71. package/dist/src/platform/windows-acl.js +1367 -0
  72. package/dist/src/platform/windows-acl.js.map +1 -0
  73. package/dist/src/platform/windows-lock-root.d.ts +13 -0
  74. package/dist/src/platform/windows-lock-root.js +98 -0
  75. package/dist/src/platform/windows-lock-root.js.map +1 -0
  76. package/dist/src/providers/builtin/discord.d.ts +4 -0
  77. package/dist/src/providers/builtin/discord.js +52 -9
  78. package/dist/src/providers/builtin/discord.js.map +1 -1
  79. package/dist/src/providers/builtin/external-webhook-auth.d.ts +1 -0
  80. package/dist/src/providers/builtin/external-webhook-auth.js +38 -1
  81. package/dist/src/providers/builtin/external-webhook-auth.js.map +1 -1
  82. package/dist/src/providers/builtin/feishu.d.ts +1 -0
  83. package/dist/src/providers/builtin/feishu.js +96 -26
  84. package/dist/src/providers/builtin/feishu.js.map +1 -1
  85. package/dist/src/providers/builtin/googlechat.d.ts +1 -0
  86. package/dist/src/providers/builtin/googlechat.js +95 -26
  87. package/dist/src/providers/builtin/googlechat.js.map +1 -1
  88. package/dist/src/providers/builtin/imessage.js +60 -17
  89. package/dist/src/providers/builtin/imessage.js.map +1 -1
  90. package/dist/src/providers/builtin/loopback.js +88 -35
  91. package/dist/src/providers/builtin/loopback.js.map +1 -1
  92. package/dist/src/providers/builtin/matrix.d.ts +2 -2
  93. package/dist/src/providers/builtin/matrix.js +78 -21
  94. package/dist/src/providers/builtin/matrix.js.map +1 -1
  95. package/dist/src/providers/builtin/mattermost.d.ts +11 -7
  96. package/dist/src/providers/builtin/mattermost.js +138 -24
  97. package/dist/src/providers/builtin/mattermost.js.map +1 -1
  98. package/dist/src/providers/builtin/msteams.d.ts +1 -0
  99. package/dist/src/providers/builtin/msteams.js +118 -38
  100. package/dist/src/providers/builtin/msteams.js.map +1 -1
  101. package/dist/src/providers/builtin/native-local-mock.js +4 -4
  102. package/dist/src/providers/builtin/native-local-mock.js.map +1 -1
  103. package/dist/src/providers/builtin/script.js +1057 -146
  104. package/dist/src/providers/builtin/script.js.map +1 -1
  105. package/dist/src/providers/builtin/slack.d.ts +8 -1
  106. package/dist/src/providers/builtin/slack.js +327 -24
  107. package/dist/src/providers/builtin/slack.js.map +1 -1
  108. package/dist/src/providers/builtin/telegram.d.ts +1 -1
  109. package/dist/src/providers/builtin/telegram.js +55 -14
  110. package/dist/src/providers/builtin/telegram.js.map +1 -1
  111. package/dist/src/providers/builtin/whatsapp.d.ts +4 -3
  112. package/dist/src/providers/builtin/whatsapp.js +157 -29
  113. package/dist/src/providers/builtin/whatsapp.js.map +1 -1
  114. package/dist/src/providers/builtin/zalo.d.ts +5 -2
  115. package/dist/src/providers/builtin/zalo.js +31 -7
  116. package/dist/src/providers/builtin/zalo.js.map +1 -1
  117. package/dist/src/providers/catalog.d.ts +1 -1
  118. package/dist/src/providers/catalog.js +1 -1
  119. package/dist/src/providers/catalog.js.map +1 -1
  120. package/dist/src/providers/local-mock.d.ts +4 -0
  121. package/dist/src/providers/local-mock.js +162 -35
  122. package/dist/src/providers/local-mock.js.map +1 -1
  123. package/dist/src/providers/native-ids.d.ts +2 -0
  124. package/dist/src/providers/native-ids.js +3 -0
  125. package/dist/src/providers/native-ids.js.map +1 -1
  126. package/dist/src/providers/recorder.d.ts +14 -3
  127. package/dist/src/providers/recorder.js +532 -42
  128. package/dist/src/providers/recorder.js.map +1 -1
  129. package/dist/src/providers/registry.d.ts +1 -0
  130. package/dist/src/providers/registry.js +65 -20
  131. package/dist/src/providers/registry.js.map +1 -1
  132. package/dist/src/providers/signed-jwt.d.ts +6 -1
  133. package/dist/src/providers/signed-jwt.js +241 -50
  134. package/dist/src/providers/signed-jwt.js.map +1 -1
  135. package/dist/src/providers/slack-ids.d.ts +1 -0
  136. package/dist/src/providers/slack-ids.js +5 -0
  137. package/dist/src/providers/slack-ids.js.map +1 -1
  138. package/dist/src/providers/target-normalizers.d.ts +9 -1
  139. package/dist/src/providers/target-normalizers.js +177 -58
  140. package/dist/src/providers/target-normalizers.js.map +1 -1
  141. package/dist/src/providers/webhook-server.d.ts +3 -0
  142. package/dist/src/providers/webhook-server.js +268 -47
  143. package/dist/src/providers/webhook-server.js.map +1 -1
  144. package/dist/src/servers/http.d.ts +14 -2
  145. package/dist/src/servers/http.js +229 -58
  146. package/dist/src/servers/http.js.map +1 -1
  147. package/dist/src/servers/matrix.d.ts +3 -0
  148. package/dist/src/servers/matrix.js +268 -110
  149. package/dist/src/servers/matrix.js.map +1 -1
  150. package/dist/src/servers/mattermost.d.ts +5 -0
  151. package/dist/src/servers/mattermost.js +389 -91
  152. package/dist/src/servers/mattermost.js.map +1 -1
  153. package/dist/src/servers/recorder.d.ts +11 -0
  154. package/dist/src/servers/recorder.js +1241 -22
  155. package/dist/src/servers/recorder.js.map +1 -1
  156. package/dist/src/servers/signal.d.ts +1 -0
  157. package/dist/src/servers/signal.js +279 -44
  158. package/dist/src/servers/signal.js.map +1 -1
  159. package/dist/src/servers/slack.d.ts +15 -0
  160. package/dist/src/servers/slack.js +259 -51
  161. package/dist/src/servers/slack.js.map +1 -1
  162. package/dist/src/servers/telegram-identity.d.ts +6 -0
  163. package/dist/src/servers/telegram-identity.js +27 -0
  164. package/dist/src/servers/telegram-identity.js.map +1 -0
  165. package/dist/src/servers/telegram.d.ts +17 -6
  166. package/dist/src/servers/telegram.js +1193 -118
  167. package/dist/src/servers/telegram.js.map +1 -1
  168. package/dist/src/servers/webhook-target.d.ts +12 -4
  169. package/dist/src/servers/webhook-target.js +226 -28
  170. package/dist/src/servers/webhook-target.js.map +1 -1
  171. package/dist/src/servers/whatsapp-baileys-websocket.d.ts +60 -1
  172. package/dist/src/servers/whatsapp-baileys-websocket.js +782 -112
  173. package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
  174. package/dist/src/servers/whatsapp-jid.d.ts +1 -0
  175. package/dist/src/servers/whatsapp-jid.js +9 -5
  176. package/dist/src/servers/whatsapp-jid.js.map +1 -1
  177. package/dist/src/servers/whatsapp-wire/binary-node.d.ts +1 -0
  178. package/dist/src/servers/whatsapp-wire/binary-node.js +37 -13
  179. package/dist/src/servers/whatsapp-wire/binary-node.js.map +1 -1
  180. package/dist/src/servers/whatsapp-wire/crypto.d.ts +3 -0
  181. package/dist/src/servers/whatsapp-wire/crypto.js +23 -8
  182. package/dist/src/servers/whatsapp-wire/crypto.js.map +1 -1
  183. package/dist/src/servers/whatsapp-wire/handshake.d.ts +9 -3
  184. package/dist/src/servers/whatsapp-wire/handshake.js +173 -12
  185. package/dist/src/servers/whatsapp-wire/handshake.js.map +1 -1
  186. package/dist/src/servers/whatsapp-wire/signal.js +3 -3
  187. package/dist/src/servers/whatsapp-wire/signal.js.map +1 -1
  188. package/dist/src/servers/whatsapp.d.ts +7 -0
  189. package/dist/src/servers/whatsapp.js +149 -24
  190. package/dist/src/servers/whatsapp.js.map +1 -1
  191. package/dist/src/servers/zalo.d.ts +1 -0
  192. package/dist/src/servers/zalo.js +193 -82
  193. package/dist/src/servers/zalo.js.map +1 -1
  194. package/docs/channel-setup.md +185 -43
  195. package/fixtures/examples/crabline.example.yaml +3 -2
  196. package/package.json +18 -10
  197. package/fixtures/examples/openclaw-bridge.yaml +0 -125
@@ -1 +1 @@
1
- {"version":3,"file":"signed-jwt.js","sourceRoot":"","sources":["../../../src/providers/signed-jwt.ts"],"names":[],"mappings":"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","sourcesContent":["import { verify, type KeyObject } from \"node:crypto\";\n\ntype JwtHeader = {\n alg: string;\n kid: string;\n};\n\nexport type JwtClaims = Record<string, unknown>;\n\nexport type RemoteJwtKeySet<T> = {\n expiresAt: number;\n values: readonly T[];\n};\n\nconst DEFAULT_KEY_FETCH_TIMEOUT_MS = 5_000;\nconst DEFAULT_UNKNOWN_KEY_COOLDOWN_MS = 30_000;\nconst MAX_NEGATIVE_KEY_IDS = 128;\nconst UTF8_DECODER = new TextDecoder(\"utf-8\", { fatal: true });\n\nfunction decodeBase64UrlPart(value: string, label: string): Buffer {\n if (!/^[A-Za-z0-9_-]+$/u.test(value)) {\n throw new Error(`${label} must use unpadded base64url encoding.`);\n }\n const decoded = Buffer.from(value, \"base64url\");\n if (decoded.length === 0 || decoded.toString(\"base64url\") !== value) {\n throw new Error(`${label} must use canonical base64url encoding.`);\n }\n return decoded;\n}\n\nfunction decodeJsonPart(value: string): Record<string, unknown> {\n const decoded: unknown = JSON.parse(UTF8_DECODER.decode(decodeBase64UrlPart(value, \"JWT part\")));\n if (!decoded || typeof decoded !== \"object\" || Array.isArray(decoded)) {\n throw new Error(\"JWT part must be a JSON object.\");\n }\n return decoded as Record<string, unknown>;\n}\n\nfunction readHeader(value: Record<string, unknown>): JwtHeader {\n if (value.alg !== \"RS256\" || typeof value.kid !== \"string\" || !value.kid) {\n throw new Error(\"JWT must use RS256 and include a key id.\");\n }\n return { alg: value.alg, kid: value.kid };\n}\n\nfunction hasAudience(claim: unknown, expected: string): boolean {\n return claim === expected || (Array.isArray(claim) && claim.includes(expected));\n}\n\nfunction numericClaim(claims: JwtClaims, name: string, required = false): number | undefined {\n if (!(name in claims)) {\n if (required) {\n throw new Error(`JWT ${name} claim is required.`);\n }\n return undefined;\n }\n const value = claims[name];\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`JWT ${name} claim must be a finite number.`);\n }\n return value;\n}\n\nexport function readBearerToken(request: Request): string | undefined {\n const authorization = request.headers.get(\"authorization\");\n const match = /^Bearer\\s+(\\S+)$/iu.exec(authorization ?? \"\");\n return match?.[1];\n}\n\nexport function resolveHttpCacheExpiry(response: Response, now: number): number {\n const cacheControl = response.headers.get(\"cache-control\");\n if (/(?:^|,)\\s*(?:no-cache|no-store)(?:\\s*(?:=|,|$))/iu.test(cacheControl ?? \"\")) {\n return now;\n }\n const ageHeader = response.headers.get(\"age\");\n const ageSeconds = ageHeader && /^\\d+$/u.test(ageHeader) ? Number.parseInt(ageHeader, 10) : 0;\n const maxAge = /(?:^|,)\\s*max-age=(\\d+)/iu.exec(cacheControl ?? \"\");\n if (maxAge) {\n return now + Math.max(0, Number(maxAge[1]) - ageSeconds) * 1_000;\n }\n const expires = Date.parse(response.headers.get(\"expires\") ?? \"\");\n return Number.isFinite(expires) && expires > now\n ? expires\n : now + Math.max(0, 60 * 60 - ageSeconds) * 1_000;\n}\n\nexport function createCachedJwtKeyResolver<T>(params: {\n fetchKeys(signal: AbortSignal): Promise<RemoteJwtKeySet<T>>;\n keyId(value: T): string | undefined;\n now?: (() => number) | undefined;\n refreshCooldownMs?: number | undefined;\n timeoutMs?: number | undefined;\n unknownKeyMessage: string;\n}) {\n const now = params.now ?? Date.now;\n const refreshCooldownMs = params.refreshCooldownMs ?? DEFAULT_UNKNOWN_KEY_COOLDOWN_MS;\n const timeoutMs = params.timeoutMs ?? DEFAULT_KEY_FETCH_TIMEOUT_MS;\n let cached: RemoteJwtKeySet<T> | undefined;\n let fetchInFlight: Promise<RemoteJwtKeySet<T>> | undefined;\n let refreshInFlight: Promise<RemoteJwtKeySet<T>> | undefined;\n let refreshCooldownUntil = 0;\n let fetchFailureCooldownUntil = 0;\n let fetchFailureError: unknown;\n const negativeKeyIds = new Map<string, number>();\n\n const rejectUnknownKey = (kid: string, expiresAt: number): never => {\n for (const [candidate, candidateExpiry] of negativeKeyIds) {\n if (candidateExpiry <= now()) {\n negativeKeyIds.delete(candidate);\n }\n }\n if (negativeKeyIds.size >= MAX_NEGATIVE_KEY_IDS) {\n const oldest = negativeKeyIds.keys().next().value;\n if (oldest) {\n negativeKeyIds.delete(oldest);\n }\n }\n negativeKeyIds.set(kid, expiresAt);\n throw new Error(params.unknownKeyMessage);\n };\n\n const fetchKeys = async (): Promise<RemoteJwtKeySet<T>> => {\n if (fetchInFlight) {\n return await fetchInFlight;\n }\n if (fetchFailureCooldownUntil > now()) {\n throw fetchFailureError;\n }\n const controller = new AbortController();\n let timeout: NodeJS.Timeout | undefined;\n const timedOut = new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n controller.abort();\n reject(new Error(\"JWT signing key fetch timed out.\"));\n }, timeoutMs);\n });\n fetchInFlight = Promise.race([params.fetchKeys(controller.signal), timedOut])\n .then((keySet) => {\n cached = keySet.expiresAt > now() ? keySet : undefined;\n fetchFailureCooldownUntil = 0;\n fetchFailureError = undefined;\n for (const value of keySet.values) {\n const keyId = params.keyId(value);\n if (keyId) {\n negativeKeyIds.delete(keyId);\n }\n }\n return keySet;\n })\n .catch((error: unknown) => {\n fetchFailureCooldownUntil = now() + refreshCooldownMs;\n fetchFailureError = error;\n throw error;\n })\n .finally(() => {\n if (timeout) {\n clearTimeout(timeout);\n }\n fetchInFlight = undefined;\n });\n return await fetchInFlight;\n };\n\n return async (header: JwtHeader): Promise<T> => {\n const currentTime = now();\n const negativeExpiry = negativeKeyIds.get(header.kid);\n if (negativeExpiry && negativeExpiry > currentTime) {\n throw new Error(params.unknownKeyMessage);\n }\n negativeKeyIds.delete(header.kid);\n\n const freshCache = cached && cached.expiresAt > currentTime ? cached : undefined;\n const keySet = freshCache ?? (await fetchKeys());\n const key = keySet.values.find((candidate) => params.keyId(candidate) === header.kid);\n if (key) {\n return key;\n }\n\n if (!freshCache) {\n return rejectUnknownKey(header.kid, now() + refreshCooldownMs);\n }\n\n let refreshed: RemoteJwtKeySet<T>;\n if (refreshInFlight) {\n refreshed = await refreshInFlight;\n } else {\n const refreshTime = now();\n if (refreshCooldownUntil > refreshTime) {\n return rejectUnknownKey(header.kid, refreshCooldownUntil);\n }\n refreshCooldownUntil = refreshTime + refreshCooldownMs;\n refreshInFlight = fetchKeys().finally(() => {\n refreshInFlight = undefined;\n });\n refreshed = await refreshInFlight;\n }\n\n const rotatedKey = refreshed.values.find((candidate) => params.keyId(candidate) === header.kid);\n if (!rotatedKey) {\n return rejectUnknownKey(header.kid, refreshCooldownUntil);\n }\n return rotatedKey;\n };\n}\n\nexport async function verifySignedJwt(params: {\n audience: string;\n clockSkewSeconds?: number | undefined;\n issuers: readonly string[];\n now?: (() => number) | undefined;\n resolveKey(header: JwtHeader): Promise<KeyObject>;\n token: string;\n}): Promise<JwtClaims> {\n const parts = params.token.split(\".\");\n if (parts.length !== 3) {\n throw new Error(\"JWT must contain three parts.\");\n }\n const [encodedHeader, encodedClaims, encodedSignature] = parts as [string, string, string];\n const header = readHeader(decodeJsonPart(encodedHeader));\n const claims = decodeJsonPart(encodedClaims);\n const key = await params.resolveKey(header);\n const signature = decodeBase64UrlPart(encodedSignature, \"JWT signature\");\n if (!verify(\"RSA-SHA256\", Buffer.from(`${encodedHeader}.${encodedClaims}`), key, signature)) {\n throw new Error(\"JWT signature is invalid.\");\n }\n\n if (!params.issuers.includes(String(claims.iss ?? \"\"))) {\n throw new Error(\"JWT issuer is invalid.\");\n }\n if (!hasAudience(claims.aud, params.audience)) {\n throw new Error(\"JWT audience is invalid.\");\n }\n\n const now = Math.floor((params.now?.() ?? Date.now()) / 1000);\n const skew = params.clockSkewSeconds ?? 300;\n const expiresAt = numericClaim(claims, \"exp\", true)!;\n if (expiresAt <= now - skew) {\n throw new Error(\"JWT is expired.\");\n }\n const notBefore = numericClaim(claims, \"nbf\");\n if (notBefore !== undefined && notBefore > now + skew) {\n throw new Error(\"JWT is not active.\");\n }\n\n return claims;\n}\n"]}
1
+ {"version":3,"file":"signed-jwt.js","sourceRoot":"","sources":["../../../src/providers/signed-jwt.ts"],"names":[],"mappings":"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","sourcesContent":["import { verify, type KeyObject } from \"node:crypto\";\n\ntype JwtHeader = {\n alg: string;\n kid: string;\n};\n\nexport type JwtClaims = Record<string, unknown>;\n\nexport type RemoteJwtKeySet<T> = {\n expiresAt: number;\n values: readonly T[];\n};\n\nexport class JwtKeyInfrastructureError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"JwtKeyInfrastructureError\";\n }\n}\n\nconst DEFAULT_KEY_FETCH_TIMEOUT_MS = 5_000;\nconst DEFAULT_UNKNOWN_KEY_COOLDOWN_MS = 30_000;\nconst MAX_HTTP_CACHE_AGE_SECONDS = 24 * 60 * 60;\nconst MAX_NEGATIVE_KEY_IDS = 128;\nconst MAX_NODE_TIMER_DELAY_MS = 2_147_483_647;\nconst MAX_REMOTE_KEY_SET_SIZE = 128;\nconst UTF8_DECODER = new TextDecoder(\"utf-8\", { fatal: true });\n\nfunction jwtKeyInfrastructureError(error: unknown): JwtKeyInfrastructureError {\n return error instanceof JwtKeyInfrastructureError\n ? error\n : new JwtKeyInfrastructureError(\"JWT signing key fetch failed.\", { cause: error });\n}\n\nfunction requireSafeDuration(value: number, name: string, allowZero = false): number {\n if (\n !Number.isSafeInteger(value) ||\n value < (allowZero ? 0 : 1) ||\n value > MAX_NODE_TIMER_DELAY_MS\n ) {\n throw new RangeError(\n `${name} must be a ${allowZero ? \"non-negative\" : \"positive\"} integer no greater than ${MAX_NODE_TIMER_DELAY_MS}.`,\n );\n }\n return value;\n}\n\nfunction readJwtClock(now: () => number): number {\n const value = now();\n if (!Number.isFinite(value)) {\n throw new RangeError(\"JWT clock must return a finite number.\");\n }\n return value;\n}\n\nfunction decodeBase64UrlPart(value: string, label: string): Buffer {\n if (!/^[A-Za-z0-9_-]+$/u.test(value)) {\n throw new Error(`${label} must use unpadded base64url encoding.`);\n }\n const decoded = Buffer.from(value, \"base64url\");\n if (decoded.length === 0 || decoded.toString(\"base64url\") !== value) {\n throw new Error(`${label} must use canonical base64url encoding.`);\n }\n return decoded;\n}\n\nfunction decodeJsonPart(value: string): Record<string, unknown> {\n const decoded: unknown = JSON.parse(UTF8_DECODER.decode(decodeBase64UrlPart(value, \"JWT part\")));\n if (!decoded || typeof decoded !== \"object\" || Array.isArray(decoded)) {\n throw new Error(\"JWT part must be a JSON object.\");\n }\n return decoded as Record<string, unknown>;\n}\n\nfunction readHeader(value: Record<string, unknown>): JwtHeader {\n if (\"crit\" in value) {\n const critical = value.crit;\n if (\n !Array.isArray(critical) ||\n critical.length === 0 ||\n !critical.every((name): name is string => typeof name === \"string\" && name.length > 0)\n ) {\n throw new Error(\"JWT crit header must be a non-empty array of parameter names.\");\n }\n throw new Error(\"JWT critical header parameters are unsupported.\");\n }\n if (value.alg !== \"RS256\" || typeof value.kid !== \"string\" || !value.kid) {\n throw new Error(\"JWT must use RS256 and include a key id.\");\n }\n return { alg: value.alg, kid: value.kid };\n}\n\nfunction hasAudience(claim: unknown, expected: string): boolean {\n return (\n claim === expected ||\n (Array.isArray(claim) &&\n claim.every((candidate): candidate is string => typeof candidate === \"string\") &&\n claim.includes(expected))\n );\n}\n\nfunction numericClaim(claims: JwtClaims, name: string, required = false): number | undefined {\n if (!(name in claims)) {\n if (required) {\n throw new Error(`JWT ${name} claim is required.`);\n }\n return undefined;\n }\n const value = claims[name];\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`JWT ${name} claim must be a finite number.`);\n }\n return value;\n}\n\nexport function readBearerToken(request: Request): string | undefined {\n const authorization = request.headers.get(\"authorization\");\n const match = /^Bearer\\s+(\\S+)$/iu.exec(authorization ?? \"\");\n return match?.[1];\n}\n\nfunction splitCacheControlDirectives(value: string): string[] | undefined {\n const directives: string[] = [];\n let start = 0;\n let quoted = false;\n let escaped = false;\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index];\n if (quoted) {\n if (escaped) {\n escaped = false;\n } else if (character === \"\\\\\") {\n escaped = true;\n } else if (character === '\"') {\n quoted = false;\n }\n } else if (character === '\"') {\n quoted = true;\n } else if (character === \",\") {\n directives.push(value.slice(start, index));\n start = index + 1;\n }\n }\n if (quoted || escaped) {\n return undefined;\n }\n directives.push(value.slice(start));\n return directives;\n}\n\nfunction cacheControlDirectiveName(value: string): string | undefined {\n return /^[ \\t]*([!#$%&'*+\\-.^_`|~0-9A-Za-z]+)/u.exec(value)?.[1]?.toLowerCase();\n}\n\nexport function resolveHttpCacheExpiry(response: Response, requestTime: number): number {\n const cacheControl = response.headers.get(\"cache-control\");\n const cacheControlDirectives = splitCacheControlDirectives(cacheControl ?? \"\");\n if (!cacheControlDirectives) {\n return requestTime;\n }\n if (\n cacheControlDirectives.some((directive) => {\n const name = cacheControlDirectiveName(directive);\n return name === \"no-cache\" || name === \"no-store\";\n })\n ) {\n return requestTime;\n }\n const ageHeader = response.headers.get(\"age\");\n const ageSeconds = ageHeader && /^\\d+$/u.test(ageHeader) ? Number.parseInt(ageHeader, 10) : 0;\n const dateHeader = response.headers.get(\"date\");\n const parsedDate = dateHeader === null ? Number.NaN : Date.parse(dateHeader);\n const dateValue = Number.isFinite(parsedDate) ? parsedDate : undefined;\n const apparentAgeMs = dateValue === undefined ? 0 : Math.max(0, requestTime - dateValue);\n const currentAgeMs = Math.max(apparentAgeMs, ageSeconds * 1_000);\n const maxAgeDirectives = cacheControlDirectives.filter(\n (directive) => cacheControlDirectiveName(directive) === \"max-age\",\n );\n if (maxAgeDirectives.length > 0) {\n if (maxAgeDirectives.length !== 1) {\n return requestTime;\n }\n const maxAge = /^[ \\t]*max-age[ \\t]*=[ \\t]*(?:\"(\\d+)\"|(\\d+))[ \\t]*$/iu.exec(\n maxAgeDirectives[0]!,\n );\n if (!maxAge) {\n return requestTime;\n }\n const maxAgeSeconds = Number(maxAge[1] ?? maxAge[2]);\n if (!Number.isSafeInteger(maxAgeSeconds)) {\n return requestTime;\n }\n return (\n requestTime +\n Math.min(\n MAX_HTTP_CACHE_AGE_SECONDS * 1_000,\n Math.max(0, maxAgeSeconds * 1_000 - currentAgeMs),\n )\n );\n }\n const expiresHeader = response.headers.get(\"expires\");\n if (expiresHeader === null) {\n return requestTime + Math.max(0, 60 * 60 * 1_000 - currentAgeMs);\n }\n const expires = Date.parse(expiresHeader);\n if (!Number.isFinite(expires)) {\n return requestTime;\n }\n const freshnessLifetimeMs = Math.max(0, expires - (dateValue ?? requestTime));\n return (\n requestTime +\n Math.min(MAX_HTTP_CACHE_AGE_SECONDS * 1_000, Math.max(0, freshnessLifetimeMs - currentAgeMs))\n );\n}\n\nfunction validateRemoteJwtKeySet<T>(\n keySet: RemoteJwtKeySet<T>,\n keyId: (value: T) => string | undefined,\n): { keyIds: readonly string[]; keySet: RemoteJwtKeySet<T> } {\n if (!Number.isFinite(keySet.expiresAt)) {\n throw new JwtKeyInfrastructureError(\"JWT signing key set expiry is invalid.\");\n }\n if (!Array.isArray(keySet.values)) {\n throw new JwtKeyInfrastructureError(\"JWT signing key set values must be an array.\");\n }\n if (keySet.values.length === 0) {\n throw new JwtKeyInfrastructureError(\"JWT signing key set must include at least one key.\");\n }\n if (keySet.values.length > MAX_REMOTE_KEY_SET_SIZE) {\n throw new JwtKeyInfrastructureError(\n `JWT signing key set exceeds the ${MAX_REMOTE_KEY_SET_SIZE}-key limit.`,\n );\n }\n const keyIds = new Set<string>();\n for (const value of keySet.values) {\n let candidateKeyId: string | undefined;\n try {\n candidateKeyId = keyId(value);\n } catch (error) {\n throw new JwtKeyInfrastructureError(\"JWT signing key id is invalid.\", { cause: error });\n }\n if (typeof candidateKeyId !== \"string\" || candidateKeyId.length === 0) {\n throw new JwtKeyInfrastructureError(\"JWT signing key id is invalid.\");\n }\n if (keyIds.has(candidateKeyId)) {\n throw new JwtKeyInfrastructureError(\"JWT signing key ids must be unique.\");\n }\n keyIds.add(candidateKeyId);\n }\n return { keyIds: [...keyIds], keySet };\n}\n\nexport function createCachedJwtKeyResolver<T>(params: {\n fetchKeys(signal: AbortSignal): Promise<RemoteJwtKeySet<T>>;\n keyId(value: T): string | undefined;\n now?: (() => number) | undefined;\n refreshCooldownMs?: number | undefined;\n timeoutMs?: number | undefined;\n unknownKeyMessage: string;\n}) {\n const clock = params.now ?? Date.now;\n const now = () => readJwtClock(clock);\n const refreshCooldownMs = requireSafeDuration(\n params.refreshCooldownMs ?? DEFAULT_UNKNOWN_KEY_COOLDOWN_MS,\n \"refreshCooldownMs\",\n true,\n );\n const timeoutMs = requireSafeDuration(\n params.timeoutMs ?? DEFAULT_KEY_FETCH_TIMEOUT_MS,\n \"timeoutMs\",\n );\n let cached: RemoteJwtKeySet<T> | undefined;\n let fetchInFlight:\n | {\n controller: AbortController;\n generation: number;\n promise: Promise<RemoteJwtKeySet<T>>;\n retryAt: number | undefined;\n }\n | undefined;\n let fetchGeneration = 0;\n let refreshInFlight: Promise<RemoteJwtKeySet<T>> | undefined;\n let refreshCooldownUntil = 0;\n let fetchFailureCooldownUntil = 0;\n let fetchFailureError: unknown;\n const negativeKeyIds = new Map<string, number>();\n\n const rejectUnknownKey = (kid: string, expiresAt: number): never => {\n for (const [candidate, candidateExpiry] of negativeKeyIds) {\n if (candidateExpiry <= now()) {\n negativeKeyIds.delete(candidate);\n }\n }\n if (negativeKeyIds.size >= MAX_NEGATIVE_KEY_IDS) {\n const oldest = negativeKeyIds.keys().next().value;\n if (oldest) {\n negativeKeyIds.delete(oldest);\n }\n }\n negativeKeyIds.set(kid, expiresAt);\n throw new Error(params.unknownKeyMessage);\n };\n\n const fetchKeys = async (): Promise<RemoteJwtKeySet<T>> => {\n let inFlight = fetchInFlight;\n const currentTime = now();\n if (inFlight?.retryAt !== undefined && inFlight.retryAt <= currentTime) {\n if (fetchInFlight?.generation === inFlight.generation) {\n fetchInFlight = undefined;\n }\n inFlight = undefined;\n }\n if (!inFlight) {\n if (fetchFailureCooldownUntil > currentTime) {\n throw fetchFailureError;\n }\n const controller = new AbortController();\n const generation = ++fetchGeneration;\n let keyFetch!: Promise<RemoteJwtKeySet<T>>;\n keyFetch = Promise.resolve()\n .then(() => params.fetchKeys(controller.signal))\n .then((keySet) => validateRemoteJwtKeySet(keySet, params.keyId))\n .then(\n ({ keyIds, keySet }) => {\n if (fetchInFlight?.generation !== generation) {\n throw new JwtKeyInfrastructureError(\n \"JWT signing key fetch completed after its generation expired.\",\n );\n }\n cached = keySet.expiresAt > now() ? keySet : undefined;\n fetchFailureCooldownUntil = 0;\n fetchFailureError = undefined;\n for (const keyId of keyIds) {\n negativeKeyIds.delete(keyId);\n }\n return keySet;\n },\n (error: unknown) => {\n const infrastructureError = jwtKeyInfrastructureError(error);\n if (fetchInFlight?.generation === generation) {\n fetchFailureCooldownUntil = now() + refreshCooldownMs;\n fetchFailureError = infrastructureError;\n }\n throw infrastructureError;\n },\n )\n .finally(() => {\n if (fetchInFlight?.generation === generation) {\n fetchInFlight = undefined;\n }\n });\n inFlight = { controller, generation, promise: keyFetch, retryAt: undefined };\n fetchInFlight = inFlight;\n void keyFetch.catch(() => {});\n }\n\n let timeout: NodeJS.Timeout | undefined;\n const timedOut = new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n inFlight.controller.abort();\n const timeoutError = new JwtKeyInfrastructureError(\"JWT signing key fetch timed out.\");\n inFlight.retryAt ??= now() + refreshCooldownMs;\n if (fetchInFlight?.generation === inFlight.generation) {\n fetchFailureCooldownUntil = inFlight.retryAt;\n fetchFailureError = timeoutError;\n }\n reject(timeoutError);\n }, timeoutMs);\n });\n try {\n return await Promise.race([inFlight.promise, timedOut]);\n } finally {\n if (timeout) {\n clearTimeout(timeout);\n }\n }\n };\n\n return async (header: JwtHeader): Promise<T> => {\n const currentTime = now();\n const freshCache = cached && cached.expiresAt > currentTime ? cached : undefined;\n if (!freshCache && cached) {\n const refreshed = await fetchKeys();\n const refreshedKey = refreshed.values.find(\n (candidate) => params.keyId(candidate) === header.kid,\n );\n if (refreshedKey) {\n return refreshedKey;\n }\n refreshCooldownUntil = now() + refreshCooldownMs;\n return rejectUnknownKey(header.kid, refreshCooldownUntil);\n }\n\n const negativeExpiry = negativeKeyIds.get(header.kid);\n if (negativeExpiry && negativeExpiry > currentTime) {\n throw new Error(params.unknownKeyMessage);\n }\n negativeKeyIds.delete(header.kid);\n\n const keySet = freshCache ?? (await fetchKeys());\n const key = keySet.values.find((candidate) => params.keyId(candidate) === header.kid);\n if (key) {\n return key;\n }\n\n if (!freshCache) {\n return rejectUnknownKey(header.kid, now() + refreshCooldownMs);\n }\n\n let refreshed: RemoteJwtKeySet<T>;\n if (refreshInFlight) {\n refreshed = await refreshInFlight;\n } else {\n if (refreshCooldownUntil > now()) {\n if (fetchFailureCooldownUntil > now() && fetchFailureError) {\n throw fetchFailureError;\n }\n return rejectUnknownKey(header.kid, refreshCooldownUntil);\n }\n refreshInFlight = Promise.resolve()\n .then(fetchKeys)\n .then(\n (refreshedKeySet) => {\n refreshCooldownUntil = now() + refreshCooldownMs;\n return refreshedKeySet;\n },\n (error: unknown) => {\n refreshCooldownUntil = now() + refreshCooldownMs;\n throw error;\n },\n )\n .finally(() => {\n refreshInFlight = undefined;\n });\n refreshed = await refreshInFlight;\n }\n\n const rotatedKey = refreshed.values.find((candidate) => params.keyId(candidate) === header.kid);\n if (!rotatedKey) {\n return rejectUnknownKey(header.kid, refreshCooldownUntil);\n }\n return rotatedKey;\n };\n}\n\nexport async function verifySignedJwt(params: {\n audience: string;\n clockSkewSeconds?: number | undefined;\n issuers: readonly string[];\n now?: (() => number) | undefined;\n resolveKey(header: JwtHeader): Promise<KeyObject>;\n token: string;\n}): Promise<JwtClaims> {\n const parts = params.token.split(\".\");\n if (parts.length !== 3) {\n throw new Error(\"JWT must contain three parts.\");\n }\n const [encodedHeader, encodedClaims, encodedSignature] = parts as [string, string, string];\n const header = readHeader(decodeJsonPart(encodedHeader));\n const claims = decodeJsonPart(encodedClaims);\n const key = await params.resolveKey(header);\n const signature = decodeBase64UrlPart(encodedSignature, \"JWT signature\");\n if (!verify(\"RSA-SHA256\", Buffer.from(`${encodedHeader}.${encodedClaims}`), key, signature)) {\n throw new Error(\"JWT signature is invalid.\");\n }\n\n if (typeof claims.iss !== \"string\" || !params.issuers.includes(claims.iss)) {\n throw new Error(\"JWT issuer is invalid.\");\n }\n if (!hasAudience(claims.aud, params.audience)) {\n throw new Error(\"JWT audience is invalid.\");\n }\n\n const now = Math.floor(readJwtClock(params.now ?? Date.now) / 1000);\n const skew = params.clockSkewSeconds ?? 300;\n if (!Number.isFinite(skew) || skew < 0) {\n throw new Error(\"JWT clock skew must be a finite non-negative number.\");\n }\n const expiresAt = numericClaim(claims, \"exp\", true)!;\n if (expiresAt <= now - skew) {\n throw new Error(\"JWT is expired.\");\n }\n const notBefore = numericClaim(claims, \"nbf\");\n if (notBefore !== undefined && notBefore > now + skew) {\n throw new Error(\"JWT is not active.\");\n }\n\n return claims;\n}\n"]}
@@ -2,5 +2,6 @@ import type { NativeIdRule } from "./native-ids.js";
2
2
  export declare const SLACK_CHANNEL_ID_RULE: NativeIdRule;
3
3
  export declare const SLACK_SEND_TARGET_ID_RULE: NativeIdRule;
4
4
  export declare const SLACK_USER_ID_RULE: NativeIdRule;
5
+ export declare const SLACK_EVENT_ID_RULE: NativeIdRule;
5
6
  export declare const SLACK_TS_RULE: NativeIdRule;
6
7
  export declare function slackTargetKey(channel: string, threadTs?: string): string;
@@ -13,6 +13,11 @@ export const SLACK_USER_ID_RULE = {
13
13
  name: "Slack user id",
14
14
  pattern: /^[UW][A-Z0-9]{2,}$/u,
15
15
  };
16
+ export const SLACK_EVENT_ID_RULE = {
17
+ example: "Ev1234567890",
18
+ name: "Slack event id",
19
+ pattern: /^Ev[A-Z0-9]{2,}$/u,
20
+ };
16
21
  export const SLACK_TS_RULE = {
17
22
  example: "1700000000.000100",
18
23
  name: "Slack timestamp",
@@ -1 +1 @@
1
- {"version":3,"file":"slack-ids.js","sourceRoot":"","sources":["../../../src/providers/slack-ids.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,uBAAuB;IAC7B,OAAO,EAAE,sBAAsB;CAChC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAiB;IACrD,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,+BAA+B;IACrC,OAAO,EAAE,wBAAwB;CAClC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,qBAAqB;CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,OAAO,EAAE,mBAAmB;IAC5B,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,kBAAkB;CAC5B,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,QAAiB;IAC/D,OAAO,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,WAAW,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAC9D,CAAC","sourcesContent":["import type { NativeIdRule } from \"./native-ids.js\";\n\nexport const SLACK_CHANNEL_ID_RULE: NativeIdRule = {\n example: \"C1234567890\",\n name: \"Slack conversation id\",\n pattern: /^[CDG][A-Z0-9]{2,}$/u,\n};\n\nexport const SLACK_SEND_TARGET_ID_RULE: NativeIdRule = {\n example: \"C1234567890\",\n name: \"Slack conversation or user id\",\n pattern: /^[CDGUW][A-Z0-9]{2,}$/u,\n};\n\nexport const SLACK_USER_ID_RULE: NativeIdRule = {\n example: \"U1234567890\",\n name: \"Slack user id\",\n pattern: /^[UW][A-Z0-9]{2,}$/u,\n};\n\nexport const SLACK_TS_RULE: NativeIdRule = {\n example: \"1700000000.000100\",\n name: \"Slack timestamp\",\n pattern: /^\\d{10}\\.\\d{6}$/u,\n};\n\nexport function slackTargetKey(channel: string, threadTs?: string) {\n return threadTs ? `${channel}:thread:${threadTs}` : channel;\n}\n"]}
1
+ {"version":3,"file":"slack-ids.js","sourceRoot":"","sources":["../../../src/providers/slack-ids.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,uBAAuB;IAC7B,OAAO,EAAE,sBAAsB;CAChC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAiB;IACrD,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,+BAA+B;IACrC,OAAO,EAAE,wBAAwB;CAClC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,qBAAqB;CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,OAAO,EAAE,cAAc;IACvB,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,mBAAmB;CAC7B,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,OAAO,EAAE,mBAAmB;IAC5B,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,kBAAkB;CAC5B,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,QAAiB;IAC/D,OAAO,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,WAAW,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAC9D,CAAC","sourcesContent":["import type { NativeIdRule } from \"./native-ids.js\";\n\nexport const SLACK_CHANNEL_ID_RULE: NativeIdRule = {\n example: \"C1234567890\",\n name: \"Slack conversation id\",\n pattern: /^[CDG][A-Z0-9]{2,}$/u,\n};\n\nexport const SLACK_SEND_TARGET_ID_RULE: NativeIdRule = {\n example: \"C1234567890\",\n name: \"Slack conversation or user id\",\n pattern: /^[CDGUW][A-Z0-9]{2,}$/u,\n};\n\nexport const SLACK_USER_ID_RULE: NativeIdRule = {\n example: \"U1234567890\",\n name: \"Slack user id\",\n pattern: /^[UW][A-Z0-9]{2,}$/u,\n};\n\nexport const SLACK_EVENT_ID_RULE: NativeIdRule = {\n example: \"Ev1234567890\",\n name: \"Slack event id\",\n pattern: /^Ev[A-Z0-9]{2,}$/u,\n};\n\nexport const SLACK_TS_RULE: NativeIdRule = {\n example: \"1700000000.000100\",\n name: \"Slack timestamp\",\n pattern: /^\\d{10}\\.\\d{6}$/u,\n};\n\nexport function slackTargetKey(channel: string, threadTs?: string) {\n return threadTs ? `${channel}:thread:${threadTs}` : channel;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { BuiltinAdapterId, FixtureDefinition, ProviderPlatform } from "../config/schema.js";
2
2
  import type { LocalMockTargetCodec } from "./local-mock.js";
3
- import type { NativeIdRule } from "./native-ids.js";
3
+ import { type NativeIdRule } from "./native-ids.js";
4
4
  import type { NormalizedTarget } from "./types.js";
5
5
  export type BuiltinProviderAdapterId = Exclude<BuiltinAdapterId, "script">;
6
6
  export declare const DISCORD_SNOWFLAKE_RULE: NativeIdRule;
@@ -11,16 +11,24 @@ export declare const GOOGLE_CHAT_THREAD_RULE: NativeIdRule;
11
11
  export declare const IMESSAGE_THREAD_RULE: NativeIdRule;
12
12
  export declare const MATRIX_ROOM_ID_RULE: NativeIdRule;
13
13
  export declare const MATRIX_EVENT_ID_RULE: NativeIdRule;
14
+ export { isMatrixEventId, isMatrixRoomId } from "../matrix-ids.js";
14
15
  export declare const MATTERMOST_ID_RULE: NativeIdRule;
15
16
  export declare const MSTEAMS_CONVERSATION_ID_RULE: NativeIdRule;
16
17
  export declare const TELEGRAM_CHAT_ID_RULE: NativeIdRule;
18
+ export declare const TELEGRAM_INBOUND_CHAT_ID_RULE: NativeIdRule;
17
19
  export declare const TELEGRAM_MESSAGE_THREAD_ID_RULE: NativeIdRule;
18
20
  export declare const WHATSAPP_WA_ID_RULE: NativeIdRule;
19
21
  export declare const ZALO_ID_RULE: NativeIdRule;
22
+ export declare const ZALO_UNSUPPORTED_THREAD_TARGET_ERROR = "Zalo does not support thread targets.";
23
+ export declare const WHATSAPP_UNSUPPORTED_THREAD_TARGET_ERROR = "WhatsApp does not support thread targets.";
20
24
  export declare function createGenericLocalMockTargetCodec(platform: ProviderPlatform): LocalMockTargetCodec;
21
25
  export declare function parseCanonicalTelegramTopic(value: string): {
22
26
  chatId: string;
23
27
  topicId: string;
24
28
  } | undefined;
29
+ export declare function parseCanonicalTelegramInboundTopic(value: string): {
30
+ chatId: string;
31
+ topicId: string;
32
+ } | undefined;
25
33
  export declare function getBuiltinTargetCodec(adapter: BuiltinProviderAdapterId): LocalMockTargetCodec;
26
34
  export declare function normalizeBuiltinTarget(adapter: BuiltinProviderAdapterId, target: FixtureDefinition["target"]): NormalizedTarget;
@@ -1,9 +1,13 @@
1
1
  import { CrablineError } from "../core/errors.js";
2
+ import { isMatrixEventId, isMatrixRoomId } from "../matrix-ids.js";
3
+ import { canonicalizeTelegramUsername, TELEGRAM_NATIVE_CHAT_ID_MAX, } from "../servers/telegram-identity.js";
4
+ import { matchesNativeId } from "./native-ids.js";
2
5
  import { slackTargetKey, SLACK_SEND_TARGET_ID_RULE, SLACK_TS_RULE } from "./slack-ids.js";
3
6
  export const DISCORD_SNOWFLAKE_RULE = {
4
7
  example: "123456789012345678",
5
8
  name: "Discord snowflake id",
6
- pattern: /^\d{17,20}$/u,
9
+ pattern: /^[1-9]\d{0,19}$/u,
10
+ validate: (value) => BigInt(value) <= 18446744073709551615n,
7
11
  };
8
12
  export const FEISHU_CHAT_ID_RULE = {
9
13
  example: "oc_abc123",
@@ -33,13 +37,16 @@ export const IMESSAGE_THREAD_RULE = {
33
37
  export const MATRIX_ROOM_ID_RULE = {
34
38
  example: "!abcdef:matrix.org",
35
39
  name: "Matrix room id",
36
- pattern: /^!(?:[^:\s]+:[^\s]+|[A-Za-z0-9_-]{43})$/u,
40
+ pattern: /^!/u,
41
+ validate: isMatrixRoomId,
37
42
  };
38
43
  export const MATRIX_EVENT_ID_RULE = {
39
44
  example: "$eventid:matrix.org",
40
45
  name: "Matrix event id",
41
- pattern: /^\$[^\s]+(?::[^\s]+)?$/u,
46
+ pattern: /^\$/u,
47
+ validate: isMatrixEventId,
42
48
  };
49
+ export { isMatrixEventId, isMatrixRoomId } from "../matrix-ids.js";
43
50
  export const MATTERMOST_ID_RULE = {
44
51
  example: "abcdefghijklmnopqrstuvwx12",
45
52
  name: "Mattermost id",
@@ -53,12 +60,20 @@ export const MSTEAMS_CONVERSATION_ID_RULE = {
53
60
  export const TELEGRAM_CHAT_ID_RULE = {
54
61
  example: "-1001234567890 or @channelusername",
55
62
  name: "Telegram chat id",
56
- pattern: /^(?:-?[1-9]\d*|@[A-Za-z][A-Za-z0-9_]{3,31})$/u,
63
+ pattern: /^(?:-?[1-9]\d*|@[A-Za-z][A-Za-z0-9_]{4,31})$/u,
64
+ validate: (value) => value.startsWith("@") || BigInt(value.replace(/^-/u, "")) <= TELEGRAM_NATIVE_CHAT_ID_MAX,
65
+ };
66
+ export const TELEGRAM_INBOUND_CHAT_ID_RULE = {
67
+ example: "-1001234567890",
68
+ name: "Telegram inbound chat id",
69
+ pattern: /^-?[1-9]\d*$/u,
70
+ validate: (value) => BigInt(value.replace(/^-/u, "")) <= TELEGRAM_NATIVE_CHAT_ID_MAX,
57
71
  };
58
72
  export const TELEGRAM_MESSAGE_THREAD_ID_RULE = {
59
73
  example: "42",
60
74
  name: "Telegram message_thread_id",
61
75
  pattern: /^[1-9]\d*$/u,
76
+ validate: (value) => BigInt(value) <= BigInt(Number.MAX_SAFE_INTEGER),
62
77
  };
63
78
  export const WHATSAPP_WA_ID_RULE = {
64
79
  example: "15551234567",
@@ -70,8 +85,10 @@ export const ZALO_ID_RULE = {
70
85
  name: "Zalo string id",
71
86
  pattern: /^\S+$/u,
72
87
  };
88
+ export const ZALO_UNSUPPORTED_THREAD_TARGET_ERROR = "Zalo does not support thread targets.";
89
+ export const WHATSAPP_UNSUPPORTED_THREAD_TARGET_ERROR = "WhatsApp does not support thread targets.";
73
90
  function requireNativeId(value, rule, label) {
74
- if (!rule.pattern.test(value)) {
91
+ if (!matchesNativeId(value, rule)) {
75
92
  throw new CrablineError(`${label} must be a native ${rule.name} such as ${rule.example}.`, {
76
93
  kind: "config",
77
94
  });
@@ -103,34 +120,68 @@ function createNativeTargetCodec(options) {
103
120
  }
104
121
  export function createGenericLocalMockTargetCodec(platform) {
105
122
  const prefix = `${platform}:`;
106
- const encode = (value) => (value.startsWith(prefix) ? value : `${prefix}${value}`);
123
+ const encodeComponent = (value, label) => {
124
+ try {
125
+ return encodeURIComponent(value);
126
+ }
127
+ catch (error) {
128
+ throw new CrablineError(`${platform} ${label} cannot be encoded.`, {
129
+ cause: error,
130
+ kind: "config",
131
+ });
132
+ }
133
+ };
134
+ const requireCanonicalComponent = (value, label) => {
135
+ try {
136
+ if (!value ||
137
+ value.includes(":") ||
138
+ encodeURIComponent(decodeURIComponent(value)) !== value) {
139
+ throw new Error("non-canonical component");
140
+ }
141
+ }
142
+ catch (error) {
143
+ throw new CrablineError(`${platform} canonical ${label} is malformed.`, {
144
+ cause: error,
145
+ kind: "config",
146
+ });
147
+ }
148
+ };
149
+ const normalizeChannel = (value) => {
150
+ if (!value) {
151
+ throw new CrablineError(`${platform} channelId must not be empty.`, { kind: "config" });
152
+ }
153
+ if (!value.startsWith(prefix)) {
154
+ return `${prefix}${encodeComponent(value, "channelId")}`;
155
+ }
156
+ requireCanonicalComponent(value.slice(prefix.length), "channelId");
157
+ return value;
158
+ };
107
159
  return {
108
160
  normalize(target) {
161
+ const channelId = normalizeChannel(target.channelId ?? target.id);
109
162
  const normalized = {
163
+ channelId,
110
164
  id: target.id,
111
165
  metadata: target.metadata,
112
166
  };
113
- if (target.channelId) {
114
- normalized.channelId = encode(target.channelId);
115
- }
116
- else if (!target.threadId) {
117
- normalized.channelId = encode(target.id);
118
- }
119
167
  if (target.threadId) {
120
- normalized.channelId ??= encode(target.id);
121
- if (target.threadId.startsWith(prefix) &&
122
- !target.threadId.startsWith(`${normalized.channelId}:`)) {
123
- throw new CrablineError(`${platform} canonical thread parent must match the target channel.`, { kind: "config" });
168
+ if (target.threadId.startsWith(prefix)) {
169
+ const canonicalPrefix = `${channelId}:`;
170
+ if (!target.threadId.startsWith(canonicalPrefix)) {
171
+ throw new CrablineError(`${platform} canonical thread parent must match the target channel.`, { kind: "config" });
172
+ }
173
+ requireCanonicalComponent(target.threadId.slice(canonicalPrefix.length), "threadId");
174
+ normalized.threadId = target.threadId;
175
+ }
176
+ else {
177
+ normalized.threadId = `${channelId}:${encodeComponent(target.threadId, "threadId")}`;
124
178
  }
125
- normalized.threadId = target.threadId.startsWith(prefix)
126
- ? target.threadId
127
- : `${normalized.channelId}:${target.threadId}`;
128
179
  }
129
180
  return normalized;
130
181
  },
131
182
  resolveThreadId(target) {
132
183
  const normalized = this.normalize(target);
133
- return normalized.threadId ?? normalized.channelId ?? encode(normalized.id);
184
+ return normalized.threadId ?? normalized.channelId ?? normalizeChannel(normalized.id);
134
185
  },
135
186
  };
136
187
  }
@@ -167,43 +218,47 @@ const SLACK_TARGET_CODEC = {
167
218
  return slackTargetKey(channelId, normalized.threadId);
168
219
  },
169
220
  };
170
- const TELEGRAM_BASE_CODEC = createNativeTargetCodec({
171
- channel: TELEGRAM_CHAT_ID_RULE,
172
- channelLabel: "Telegram chat_id",
173
- thread: TELEGRAM_MESSAGE_THREAD_ID_RULE,
174
- threadLabel: "Telegram message_thread_id",
175
- });
176
221
  export function parseCanonicalTelegramTopic(value) {
222
+ return parseCanonicalTelegramTopicWithRule(value, TELEGRAM_CHAT_ID_RULE);
223
+ }
224
+ export function parseCanonicalTelegramInboundTopic(value) {
225
+ return parseCanonicalTelegramTopicWithRule(value, TELEGRAM_INBOUND_CHAT_ID_RULE);
226
+ }
227
+ function parseCanonicalTelegramTopicWithRule(value, chatRule) {
177
228
  const separator = value.lastIndexOf(":");
178
229
  if (separator <= 0) {
179
230
  return undefined;
180
231
  }
181
232
  const chatId = value.slice(0, separator);
182
233
  const topicId = value.slice(separator + 1);
183
- if (!TELEGRAM_CHAT_ID_RULE.pattern.test(chatId) ||
184
- !TELEGRAM_MESSAGE_THREAD_ID_RULE.pattern.test(topicId)) {
234
+ if (!matchesNativeId(chatId, chatRule) ||
235
+ !matchesNativeId(topicId, TELEGRAM_MESSAGE_THREAD_ID_RULE)) {
185
236
  return undefined;
186
237
  }
187
- return { chatId, topicId };
238
+ const canonicalChatId = chatId.startsWith("@") && chatRule === TELEGRAM_CHAT_ID_RULE
239
+ ? canonicalizeTelegramUsername(chatId)
240
+ : chatId;
241
+ return canonicalChatId ? { chatId: canonicalChatId, topicId } : undefined;
188
242
  }
189
243
  const TELEGRAM_TARGET_CODEC = {
190
244
  normalize(target) {
191
245
  const canonicalTopic = target.threadId
192
246
  ? parseCanonicalTelegramTopic(target.threadId)
193
247
  : undefined;
194
- const targetChatId = target.channelId ?? target.id;
195
- if (canonicalTopic &&
196
- requireNativeId(targetChatId, TELEGRAM_CHAT_ID_RULE, "Telegram chat_id") !==
197
- canonicalTopic.chatId) {
248
+ const targetChatIdValue = requireNativeId(target.channelId ?? target.id, TELEGRAM_CHAT_ID_RULE, "Telegram chat_id");
249
+ const targetChatId = targetChatIdValue.startsWith("@")
250
+ ? canonicalizeTelegramUsername(targetChatIdValue)
251
+ : targetChatIdValue;
252
+ if (canonicalTopic && targetChatId !== canonicalTopic.chatId) {
198
253
  throw new CrablineError("Telegram canonical topic chat_id must match the target chat_id.", {
199
254
  kind: "config",
200
255
  });
201
256
  }
202
- const normalized = TELEGRAM_BASE_CODEC.normalize({
203
- ...target,
204
- ...(canonicalTopic ? { channelId: canonicalTopic.chatId } : {}),
205
- threadId: undefined,
206
- });
257
+ const normalized = {
258
+ channelId: canonicalTopic?.chatId ?? targetChatId,
259
+ id: target.id,
260
+ metadata: target.metadata,
261
+ };
207
262
  if (!target.threadId) {
208
263
  return normalized;
209
264
  }
@@ -218,6 +273,86 @@ const TELEGRAM_TARGET_CODEC = {
218
273
  return normalized.threadId ?? normalized.channelId ?? normalized.id;
219
274
  },
220
275
  };
276
+ const GOOGLE_CHAT_TARGET_CODEC = {
277
+ normalize(target) {
278
+ const channelId = requireNativeId(target.channelId ?? target.id, GOOGLE_CHAT_SPACE_RULE, "Google Chat space.name");
279
+ const normalized = {
280
+ channelId,
281
+ id: target.id,
282
+ metadata: target.metadata,
283
+ };
284
+ if (target.threadId) {
285
+ const threadId = requireNativeId(target.threadId, GOOGLE_CHAT_THREAD_RULE, "Google Chat thread.name");
286
+ if (!threadId.startsWith(`${channelId}/threads/`)) {
287
+ throw new CrablineError("Google Chat thread.name must belong to the target space.name.", {
288
+ kind: "config",
289
+ });
290
+ }
291
+ normalized.threadId = threadId;
292
+ }
293
+ return normalized;
294
+ },
295
+ resolveThreadId(target) {
296
+ const normalized = this.normalize(target);
297
+ return normalized.threadId ?? normalized.channelId ?? normalized.id;
298
+ },
299
+ };
300
+ const MATRIX_TARGET_CODEC = {
301
+ normalize(target) {
302
+ const channelId = target.channelId ?? target.id;
303
+ if (!isMatrixRoomId(channelId)) {
304
+ throw new CrablineError(`Matrix room_id must be a native ${MATRIX_ROOM_ID_RULE.name} such as ${MATRIX_ROOM_ID_RULE.example}.`, { kind: "config" });
305
+ }
306
+ const normalized = {
307
+ channelId,
308
+ id: target.id,
309
+ metadata: target.metadata,
310
+ };
311
+ if (target.threadId) {
312
+ if (!isMatrixEventId(target.threadId)) {
313
+ throw new CrablineError(`Matrix event_id must be a native ${MATRIX_EVENT_ID_RULE.name} such as ${MATRIX_EVENT_ID_RULE.example}.`, { kind: "config" });
314
+ }
315
+ normalized.threadId = target.threadId;
316
+ }
317
+ return normalized;
318
+ },
319
+ resolveThreadId(target) {
320
+ const normalized = this.normalize(target);
321
+ return normalized.threadId ?? normalized.channelId ?? normalized.id;
322
+ },
323
+ };
324
+ const ZALO_BASE_TARGET_CODEC = createNativeTargetCodec({
325
+ channel: ZALO_ID_RULE,
326
+ channelLabel: "Zalo user_id or oa_id",
327
+ });
328
+ const ZALO_TARGET_CODEC = {
329
+ normalize(target) {
330
+ if (target.threadId) {
331
+ throw new CrablineError(ZALO_UNSUPPORTED_THREAD_TARGET_ERROR, { kind: "config" });
332
+ }
333
+ return ZALO_BASE_TARGET_CODEC.normalize(target);
334
+ },
335
+ resolveThreadId(target) {
336
+ const normalized = this.normalize(target);
337
+ return normalized.channelId ?? normalized.id;
338
+ },
339
+ };
340
+ const WHATSAPP_BASE_TARGET_CODEC = createNativeTargetCodec({
341
+ channel: WHATSAPP_WA_ID_RULE,
342
+ channelLabel: "WhatsApp wa_id",
343
+ });
344
+ const WHATSAPP_TARGET_CODEC = {
345
+ normalize(target) {
346
+ if (target.threadId) {
347
+ throw new CrablineError(WHATSAPP_UNSUPPORTED_THREAD_TARGET_ERROR, { kind: "config" });
348
+ }
349
+ return WHATSAPP_BASE_TARGET_CODEC.normalize(target);
350
+ },
351
+ resolveThreadId(target) {
352
+ const normalized = this.normalize(target);
353
+ return normalized.channelId ?? normalized.id;
354
+ },
355
+ };
221
356
  const BUILTIN_TARGET_CODECS = {
222
357
  discord: createNativeTargetCodec({
223
358
  channel: DISCORD_SNOWFLAKE_RULE,
@@ -231,23 +366,13 @@ const BUILTIN_TARGET_CODECS = {
231
366
  thread: FEISHU_MESSAGE_ID_RULE,
232
367
  threadLabel: "Feishu message_id",
233
368
  }),
234
- googlechat: createNativeTargetCodec({
235
- channel: GOOGLE_CHAT_SPACE_RULE,
236
- channelLabel: "Google Chat space.name",
237
- thread: GOOGLE_CHAT_THREAD_RULE,
238
- threadLabel: "Google Chat thread.name",
239
- }),
369
+ googlechat: GOOGLE_CHAT_TARGET_CODEC,
240
370
  imessage: createNativeTargetCodec({
241
371
  channel: IMESSAGE_THREAD_RULE,
242
372
  channelLabel: "iMessage recipient or chat GUID",
243
373
  }),
244
374
  loopback: createGenericLocalMockTargetCodec("loopback"),
245
- matrix: createNativeTargetCodec({
246
- channel: MATRIX_ROOM_ID_RULE,
247
- channelLabel: "Matrix room_id",
248
- thread: MATRIX_EVENT_ID_RULE,
249
- threadLabel: "Matrix event_id",
250
- }),
375
+ matrix: MATRIX_TARGET_CODEC,
251
376
  mattermost: createNativeTargetCodec({
252
377
  channel: MATTERMOST_ID_RULE,
253
378
  channelLabel: "Mattermost channel_id",
@@ -258,14 +383,8 @@ const BUILTIN_TARGET_CODECS = {
258
383
  }),
259
384
  slack: SLACK_TARGET_CODEC,
260
385
  telegram: TELEGRAM_TARGET_CODEC,
261
- whatsapp: createNativeTargetCodec({
262
- channel: WHATSAPP_WA_ID_RULE,
263
- channelLabel: "WhatsApp wa_id",
264
- }),
265
- zalo: createNativeTargetCodec({
266
- channel: ZALO_ID_RULE,
267
- channelLabel: "Zalo user_id or oa_id",
268
- }),
386
+ whatsapp: WHATSAPP_TARGET_CODEC,
387
+ zalo: ZALO_TARGET_CODEC,
269
388
  };
270
389
  export function getBuiltinTargetCodec(adapter) {
271
390
  return BUILTIN_TARGET_CODECS[adapter];