@oxy.so/core 1.18.1 → 3.0.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 (663) hide show
  1. package/README.md +13 -7
  2. package/dist/cjs/HttpService.js +159 -111
  3. package/dist/cjs/OxyServices.errors.js +48 -1
  4. package/dist/cjs/OxyServices.js +263 -60
  5. package/dist/cjs/api/accounts.js +231 -0
  6. package/dist/cjs/api/agency.js +102 -0
  7. package/dist/cjs/api/appData.js +45 -0
  8. package/dist/cjs/api/apps.js +197 -0
  9. package/dist/cjs/api/assets.js +329 -0
  10. package/dist/cjs/api/auth.js +900 -0
  11. package/dist/cjs/api/billing.js +44 -0
  12. package/dist/cjs/api/civic.js +289 -0
  13. package/dist/cjs/api/contacts.js +16 -0
  14. package/dist/cjs/api/devices.js +351 -0
  15. package/dist/cjs/api/follows.js +240 -0
  16. package/dist/cjs/api/identity.js +569 -0
  17. package/dist/cjs/api/linkedAccounts.js +48 -0
  18. package/dist/cjs/api/nodes.js +75 -0
  19. package/dist/cjs/api/notifications.js +75 -0
  20. package/dist/cjs/api/privacy.js +105 -0
  21. package/dist/cjs/api/reputation.js +74 -0
  22. package/dist/cjs/api/session.js +177 -0
  23. package/dist/cjs/api/store.js +199 -0
  24. package/dist/cjs/api/topics.js +66 -0
  25. package/dist/cjs/api/users.js +309 -0
  26. package/dist/cjs/boot/sessionColdBoot.js +4 -4
  27. package/dist/cjs/civic/index.js +16 -0
  28. package/dist/cjs/civic/payloads.js +156 -0
  29. package/dist/cjs/client/context.js +2 -0
  30. package/dist/cjs/crypto/identityLink.js +5 -5
  31. package/dist/cjs/crypto/index.js +44 -0
  32. package/dist/cjs/crypto/internal.js +37 -0
  33. package/dist/cjs/crypto/keyManager.js +2 -2
  34. package/dist/cjs/crypto/polyfill.js +9 -80
  35. package/dist/cjs/crypto/recoveryPhrase.js +1 -0
  36. package/dist/cjs/crypto/registrationPow.js +1 -1
  37. package/dist/cjs/crypto/signatureService.js +1 -0
  38. package/dist/cjs/i18n/accountCategoryLabels.js +3 -3
  39. package/dist/cjs/i18n/accountRoleLabels.js +7 -7
  40. package/dist/cjs/i18n/index.js +130 -52
  41. package/dist/cjs/i18n/locales/{ar-SA.json → ar-SA.js} +134 -52
  42. package/dist/cjs/i18n/locales/{ca-ES.json → ca-ES.js} +134 -52
  43. package/dist/{esm/i18n/locales/de-DE.json → cjs/i18n/locales/de-DE.js} +136 -54
  44. package/dist/{esm/i18n/locales/en-US.json → cjs/i18n/locales/en-US.js} +163 -245
  45. package/dist/{esm/i18n/locales/es-ES.json → cjs/i18n/locales/es-ES.js} +163 -245
  46. package/dist/cjs/i18n/locales/{fr-FR.json → fr-FR.js} +134 -52
  47. package/dist/cjs/i18n/locales/{it-IT.json → it-IT.js} +134 -52
  48. package/dist/{esm/i18n/locales/ja-JP.json → cjs/i18n/locales/ja-JP.js} +134 -52
  49. package/dist/cjs/i18n/locales/{ko-KR.json → ko-KR.js} +134 -52
  50. package/dist/{esm/i18n/locales/pt-PT.json → cjs/i18n/locales/pt-PT.js} +136 -54
  51. package/dist/{esm/i18n/locales/zh-CN.json → cjs/i18n/locales/zh-CN.js} +135 -53
  52. package/dist/cjs/i18n/reputationCategoryLabels.js +2 -2
  53. package/dist/cjs/i18n/trustTierLabels.js +2 -2
  54. package/dist/cjs/index.js +55 -263
  55. package/dist/cjs/inference/index.js +21 -0
  56. package/dist/cjs/server/OxyServer.js +521 -0
  57. package/dist/cjs/server/auth.js +2 -2
  58. package/dist/cjs/server/index.js +23 -6
  59. package/dist/cjs/server/middleware.js +1154 -0
  60. package/dist/cjs/server/namespaces.js +214 -0
  61. package/dist/cjs/server/rateLimit.js +2 -2
  62. package/dist/cjs/server/requesterAssertion.js +5 -5
  63. package/dist/cjs/server/securityHeaders.js +3 -3
  64. package/dist/cjs/server/traffic.js +7 -6
  65. package/dist/cjs/server/trafficNodeHttp.js +9 -3
  66. package/dist/cjs/server/userInvalidation.js +5 -5
  67. package/dist/cjs/session/accountDialogController.js +23 -23
  68. package/dist/cjs/session/authStateStore.js +2 -2
  69. package/dist/cjs/session/identitySession.js +3 -3
  70. package/dist/cjs/session/index.js +131 -0
  71. package/dist/cjs/session/refresh.js +37 -30
  72. package/dist/cjs/session/sessionClientHost.js +5 -5
  73. package/dist/cjs/session/sharedDeviceCredential.js +3 -2
  74. package/dist/cjs/shared/utils/networkUtils.js +2 -2
  75. package/dist/cjs/utils/accountCacheSweep.js +11 -15
  76. package/dist/cjs/utils/asyncUtils.js +22 -163
  77. package/dist/cjs/utils/authHelpers.js +2 -2
  78. package/dist/cjs/utils/authWebUrl.js +3 -4
  79. package/dist/cjs/utils/avatarUtils.js +2 -2
  80. package/dist/cjs/utils/cache.js +32 -2
  81. package/dist/cjs/utils/cacheKey.js +5 -10
  82. package/dist/cjs/utils/deviceManager.js +17 -16
  83. package/dist/cjs/utils/edgeRegion.js +2 -3
  84. package/dist/cjs/utils/identityCacheSweep.js +6 -10
  85. package/dist/cjs/utils/oxyServiceEnvironment.js +3 -7
  86. package/dist/cjs/utils/requestUtils.js +40 -33
  87. package/dist/cjs/utils/sessionUtils.js +0 -2
  88. package/dist/cjs/utils/tokenClaims.js +34 -0
  89. package/dist/esm/HttpService.js +160 -112
  90. package/dist/esm/OxyServices.errors.js +45 -0
  91. package/dist/esm/OxyServices.js +262 -57
  92. package/dist/esm/api/accounts.js +218 -0
  93. package/dist/esm/api/agency.js +95 -0
  94. package/dist/esm/api/appData.js +40 -0
  95. package/dist/esm/api/apps.js +191 -0
  96. package/dist/esm/api/assets.js +324 -0
  97. package/dist/esm/api/auth.js +858 -0
  98. package/dist/esm/api/billing.js +40 -0
  99. package/dist/esm/api/civic.js +250 -0
  100. package/dist/esm/api/contacts.js +12 -0
  101. package/dist/esm/api/devices.js +346 -0
  102. package/dist/esm/api/follows.js +236 -0
  103. package/dist/esm/api/identity.js +527 -0
  104. package/dist/esm/api/linkedAccounts.js +44 -0
  105. package/dist/esm/api/nodes.js +71 -0
  106. package/dist/esm/api/notifications.js +71 -0
  107. package/dist/esm/api/privacy.js +101 -0
  108. package/dist/esm/api/reputation.js +70 -0
  109. package/dist/esm/api/session.js +173 -0
  110. package/dist/esm/api/store.js +192 -0
  111. package/dist/esm/api/topics.js +62 -0
  112. package/dist/esm/api/users.js +272 -0
  113. package/dist/esm/boot/sessionColdBoot.js +4 -4
  114. package/dist/esm/civic/index.js +10 -0
  115. package/dist/esm/civic/payloads.js +118 -0
  116. package/dist/esm/client/context.js +1 -0
  117. package/dist/esm/crypto/identityLink.js +5 -5
  118. package/dist/esm/crypto/index.js +24 -0
  119. package/dist/esm/crypto/internal.js +19 -0
  120. package/dist/esm/crypto/keyManager.js +2 -2
  121. package/dist/esm/crypto/polyfill.js +10 -81
  122. package/dist/esm/crypto/recoveryPhrase.js +1 -0
  123. package/dist/esm/crypto/registrationPow.js +1 -1
  124. package/dist/esm/crypto/signatureService.js +1 -0
  125. package/dist/esm/i18n/accountCategoryLabels.js +2 -2
  126. package/dist/esm/i18n/accountRoleLabels.js +1 -1
  127. package/dist/esm/i18n/index.js +93 -52
  128. package/dist/esm/i18n/locales/{ar-SA.json → ar-SA.js} +132 -52
  129. package/dist/esm/i18n/locales/{ca-ES.json → ca-ES.js} +132 -52
  130. package/dist/{cjs/i18n/locales/de-DE.json → esm/i18n/locales/de-DE.js} +134 -54
  131. package/dist/{cjs/i18n/locales/en-US.json → esm/i18n/locales/en-US.js} +161 -245
  132. package/dist/{cjs/i18n/locales/es-ES.json → esm/i18n/locales/es-ES.js} +161 -245
  133. package/dist/esm/i18n/locales/{fr-FR.json → fr-FR.js} +132 -52
  134. package/dist/esm/i18n/locales/{it-IT.json → it-IT.js} +132 -52
  135. package/dist/{cjs/i18n/locales/ja-JP.json → esm/i18n/locales/ja-JP.js} +132 -52
  136. package/dist/esm/i18n/locales/{ko-KR.json → ko-KR.js} +132 -52
  137. package/dist/{cjs/i18n/locales/pt-PT.json → esm/i18n/locales/pt-PT.js} +134 -54
  138. package/dist/{cjs/i18n/locales/zh-CN.json → esm/i18n/locales/zh-CN.js} +133 -53
  139. package/dist/esm/i18n/reputationCategoryLabels.js +1 -1
  140. package/dist/esm/i18n/trustTierLabels.js +1 -1
  141. package/dist/esm/index.js +30 -166
  142. package/dist/esm/inference/index.js +13 -0
  143. package/dist/esm/server/OxyServer.js +516 -0
  144. package/dist/esm/server/auth.js +2 -2
  145. package/dist/esm/server/index.js +10 -5
  146. package/dist/esm/server/middleware.js +1147 -0
  147. package/dist/esm/server/namespaces.js +206 -0
  148. package/dist/esm/server/rateLimit.js +2 -2
  149. package/dist/esm/server/requesterAssertion.js +5 -5
  150. package/dist/esm/server/securityHeaders.js +3 -3
  151. package/dist/esm/server/traffic.js +7 -6
  152. package/dist/esm/server/trafficNodeHttp.js +9 -3
  153. package/dist/esm/server/userInvalidation.js +5 -5
  154. package/dist/esm/session/accountDialogController.js +23 -23
  155. package/dist/esm/session/authStateStore.js +2 -2
  156. package/dist/esm/session/identitySession.js +3 -3
  157. package/dist/esm/session/index.js +82 -0
  158. package/dist/esm/session/refresh.js +37 -30
  159. package/dist/esm/session/sessionClientHost.js +5 -5
  160. package/dist/esm/session/sharedDeviceCredential.js +3 -2
  161. package/dist/esm/shared/utils/networkUtils.js +2 -2
  162. package/dist/esm/utils/accountCacheSweep.js +11 -15
  163. package/dist/esm/utils/asyncUtils.js +22 -151
  164. package/dist/esm/utils/authHelpers.js +2 -2
  165. package/dist/esm/utils/authWebUrl.js +3 -4
  166. package/dist/esm/utils/avatarUtils.js +2 -2
  167. package/dist/esm/utils/cache.js +32 -2
  168. package/dist/esm/utils/cacheKey.js +5 -10
  169. package/dist/esm/utils/deviceManager.js +17 -16
  170. package/dist/esm/utils/edgeRegion.js +1 -2
  171. package/dist/esm/utils/identityCacheSweep.js +6 -10
  172. package/dist/esm/utils/oxyServiceEnvironment.js +3 -7
  173. package/dist/esm/utils/requestUtils.js +40 -33
  174. package/dist/esm/utils/sessionUtils.js +0 -2
  175. package/dist/esm/utils/tokenClaims.js +31 -0
  176. package/dist/types/HttpService.d.ts +26 -9
  177. package/dist/types/OxyServices.d.ts +160 -131
  178. package/dist/types/OxyServices.errors.d.ts +42 -0
  179. package/dist/types/api/accounts.d.ts +415 -0
  180. package/dist/types/api/agency.d.ts +135 -0
  181. package/dist/types/api/appData.d.ts +27 -0
  182. package/dist/types/api/apps.d.ts +433 -0
  183. package/dist/types/api/assets.d.ts +174 -0
  184. package/dist/types/api/auth.d.ts +766 -0
  185. package/dist/types/api/billing.d.ts +113 -0
  186. package/dist/types/api/civic.d.ts +203 -0
  187. package/dist/types/api/contacts.d.ts +31 -0
  188. package/{src/mixins/OxyServices.deviceBoot.ts → dist/types/api/devices.d.ts} +130 -110
  189. package/dist/types/api/follows.d.ts +236 -0
  190. package/dist/types/api/identity.d.ts +275 -0
  191. package/dist/types/api/linkedAccounts.d.ts +48 -0
  192. package/dist/types/api/nodes.d.ts +102 -0
  193. package/dist/types/api/notifications.d.ts +77 -0
  194. package/dist/types/api/privacy.d.ts +43 -0
  195. package/dist/types/api/reputation.d.ts +50 -0
  196. package/dist/types/api/session.d.ts +85 -0
  197. package/dist/types/api/store.d.ts +278 -0
  198. package/dist/types/api/topics.d.ts +34 -0
  199. package/dist/types/api/users.d.ts +134 -0
  200. package/dist/types/boot/sessionColdBoot.d.ts +1 -1
  201. package/dist/types/civic/index.d.ts +10 -0
  202. package/dist/types/civic/payloads.d.ts +83 -0
  203. package/dist/types/client/context.d.ts +33 -0
  204. package/dist/types/crypto/identityLink.d.ts +5 -5
  205. package/dist/types/crypto/index.d.ts +24 -0
  206. package/dist/types/crypto/internal.d.ts +19 -0
  207. package/dist/types/crypto/polyfill.d.ts +6 -9
  208. package/dist/types/crypto/registrationPow.d.ts +1 -1
  209. package/dist/types/i18n/accountCategoryLabels.d.ts +1 -1
  210. package/dist/types/i18n/accountRoleLabels.d.ts +1 -1
  211. package/dist/types/i18n/index.d.ts +20 -1
  212. package/dist/types/i18n/locales/ar-SA.d.ts +386 -0
  213. package/dist/types/i18n/locales/ca-ES.d.ts +386 -0
  214. package/dist/types/i18n/locales/de-DE.d.ts +386 -0
  215. package/dist/types/i18n/locales/en-US.d.ts +2034 -0
  216. package/dist/types/i18n/locales/es-ES.d.ts +2034 -0
  217. package/dist/types/i18n/locales/fr-FR.d.ts +386 -0
  218. package/dist/types/i18n/locales/it-IT.d.ts +386 -0
  219. package/dist/types/i18n/locales/ja-JP.d.ts +386 -0
  220. package/dist/types/i18n/locales/ko-KR.d.ts +386 -0
  221. package/dist/types/i18n/locales/pt-PT.d.ts +386 -0
  222. package/dist/types/i18n/locales/zh-CN.d.ts +386 -0
  223. package/dist/types/index.d.ts +46 -95
  224. package/dist/types/inference/index.d.ts +22 -0
  225. package/dist/types/models/interfaces.d.ts +1 -22
  226. package/dist/types/server/OxyServer.d.ts +183 -0
  227. package/dist/types/server/auth.d.ts +10 -7
  228. package/dist/types/server/index.d.ts +10 -4
  229. package/dist/types/server/middleware.d.ts +291 -0
  230. package/dist/types/server/namespaces.d.ts +98 -0
  231. package/dist/types/server/rateLimit.d.ts +7 -5
  232. package/dist/types/server/requesterAssertion.d.ts +14 -11
  233. package/dist/types/server/securityHeaders.d.ts +4 -5
  234. package/dist/types/server/userInvalidation.d.ts +10 -8
  235. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  236. package/dist/types/session/accountDialogController.d.ts +8 -8
  237. package/dist/types/session/accountSwitchTargets.d.ts +1 -1
  238. package/dist/types/session/authStateStore.d.ts +7 -6
  239. package/dist/types/session/index.d.ts +40 -0
  240. package/dist/types/utils/accountCacheSweep.d.ts +7 -10
  241. package/dist/types/utils/apiUtils.d.ts +3 -3
  242. package/dist/types/utils/asyncUtils.d.ts +11 -58
  243. package/dist/types/utils/authWebUrl.d.ts +3 -4
  244. package/dist/types/utils/avatarUtils.d.ts +5 -6
  245. package/dist/types/utils/cache.d.ts +11 -3
  246. package/dist/types/utils/commonsApproval.d.ts +1 -1
  247. package/dist/types/utils/edgeRegion.d.ts +1 -2
  248. package/dist/types/utils/identityCacheSweep.d.ts +6 -4
  249. package/dist/types/utils/oauthPkce.d.ts +2 -2
  250. package/dist/types/utils/oxyServiceEnvironment.d.ts +3 -7
  251. package/dist/types/utils/requestUtils.d.ts +18 -14
  252. package/dist/types/utils/tokenClaims.d.ts +9 -0
  253. package/package.json +68 -7
  254. package/src/HttpService.ts +166 -131
  255. package/src/OxyServices.errors.ts +73 -0
  256. package/src/OxyServices.ts +289 -164
  257. package/src/api/accounts.ts +579 -0
  258. package/src/api/agency.ts +277 -0
  259. package/src/api/appData.ts +63 -0
  260. package/src/api/apps.ts +596 -0
  261. package/src/api/assets.ts +416 -0
  262. package/src/api/auth.ts +1457 -0
  263. package/src/api/billing.ts +144 -0
  264. package/src/api/civic.ts +428 -0
  265. package/src/api/contacts.ts +41 -0
  266. package/src/api/devices.ts +438 -0
  267. package/src/api/follows.ts +414 -0
  268. package/src/api/identity.ts +727 -0
  269. package/src/api/linkedAccounts.ts +78 -0
  270. package/src/api/nodes.ts +169 -0
  271. package/src/api/notifications.ts +135 -0
  272. package/src/api/privacy.ts +120 -0
  273. package/src/api/reputation.ts +134 -0
  274. package/src/api/session.ts +210 -0
  275. package/src/api/store.ts +435 -0
  276. package/src/api/topics.ts +83 -0
  277. package/src/api/users.ts +357 -0
  278. package/src/boot/sessionColdBoot.ts +4 -4
  279. package/src/civic/index.ts +12 -0
  280. package/src/civic/payloads.ts +175 -0
  281. package/src/client/context.ts +34 -0
  282. package/src/crypto/identityLink.ts +5 -5
  283. package/src/crypto/index.ts +39 -0
  284. package/src/crypto/internal.ts +20 -0
  285. package/src/crypto/keyManager.ts +2 -2
  286. package/src/crypto/polyfill.ts +9 -89
  287. package/src/crypto/recoveryPhrase.ts +1 -0
  288. package/src/crypto/registrationPow.ts +1 -1
  289. package/src/crypto/signatureService.ts +1 -0
  290. package/src/i18n/accountCategoryLabels.ts +2 -2
  291. package/src/i18n/accountRoleLabels.ts +2 -2
  292. package/src/i18n/index.ts +105 -54
  293. package/src/i18n/locales/{ar-SA.json → ar-SA.ts} +132 -52
  294. package/src/i18n/locales/{ca-ES.json → ca-ES.ts} +132 -52
  295. package/{dist/cjs/i18n/locales/locales/de-DE.json → src/i18n/locales/de-DE.ts} +134 -54
  296. package/src/i18n/locales/{en-US.json → en-US.ts} +161 -245
  297. package/{dist/cjs/i18n/locales/locales/es-ES.json → src/i18n/locales/es-ES.ts} +161 -245
  298. package/src/i18n/locales/{fr-FR.json → fr-FR.ts} +132 -52
  299. package/src/i18n/locales/{it-IT.json → it-IT.ts} +132 -52
  300. package/{dist/cjs/i18n/locales/locales/ja-JP.json → src/i18n/locales/ja-JP.ts} +132 -52
  301. package/src/i18n/locales/{ko-KR.json → ko-KR.ts} +132 -52
  302. package/src/i18n/locales/{pt-PT.json → pt-PT.ts} +134 -54
  303. package/src/i18n/locales/{zh-CN.json → zh-CN.ts} +133 -53
  304. package/src/i18n/reputationCategoryLabels.ts +1 -1
  305. package/src/i18n/trustTierLabels.ts +1 -1
  306. package/src/index.ts +170 -501
  307. package/src/inference/index.ts +48 -0
  308. package/src/models/interfaces.ts +1 -22
  309. package/src/server/OxyServer.ts +637 -0
  310. package/src/server/auth.ts +12 -8
  311. package/src/server/index.ts +28 -5
  312. package/src/server/middleware.ts +1520 -0
  313. package/src/server/namespaces.ts +257 -0
  314. package/src/server/rateLimit.ts +10 -9
  315. package/src/server/requesterAssertion.ts +13 -10
  316. package/src/server/securityHeaders.ts +7 -8
  317. package/src/server/traffic.ts +6 -6
  318. package/src/server/trafficNodeHttp.ts +7 -3
  319. package/src/server/userInvalidation.ts +9 -9
  320. package/src/session/accountDelegationAccess.ts +1 -1
  321. package/src/session/accountDialogController.ts +24 -24
  322. package/src/session/accountSwitchTargets.ts +1 -1
  323. package/src/session/authStateStore.ts +9 -8
  324. package/src/session/identitySession.ts +3 -3
  325. package/src/session/index.ts +210 -0
  326. package/src/session/refresh.ts +36 -30
  327. package/src/session/sessionClientHost.ts +5 -5
  328. package/src/session/sharedDeviceCredential.ts +3 -2
  329. package/src/shared/utils/networkUtils.ts +2 -2
  330. package/src/utils/accountCacheSweep.ts +11 -15
  331. package/src/utils/apiUtils.ts +3 -3
  332. package/src/utils/asyncUtils.ts +38 -235
  333. package/src/utils/authHelpers.ts +2 -2
  334. package/src/utils/authWebUrl.ts +3 -4
  335. package/src/utils/avatarUtils.ts +4 -7
  336. package/src/utils/cache.ts +36 -5
  337. package/src/utils/cacheKey.ts +5 -9
  338. package/src/utils/commonsApproval.ts +1 -1
  339. package/src/utils/deviceManager.ts +17 -16
  340. package/src/utils/edgeRegion.ts +1 -2
  341. package/src/utils/identityCacheSweep.ts +7 -12
  342. package/src/utils/oauthPkce.ts +2 -2
  343. package/src/utils/oxyServiceEnvironment.ts +3 -7
  344. package/src/utils/requestUtils.ts +48 -44
  345. package/src/utils/sessionUtils.ts +0 -2
  346. package/src/utils/tokenClaims.ts +38 -0
  347. package/dist/cjs/.tsbuildinfo +0 -1
  348. package/dist/cjs/OxyServices.base.js +0 -392
  349. package/dist/cjs/i18n/locales/locales/ar-SA.json +0 -306
  350. package/dist/cjs/i18n/locales/locales/ca-ES.json +0 -306
  351. package/dist/cjs/i18n/locales/locales/en-US.json +0 -2127
  352. package/dist/cjs/i18n/locales/locales/fr-FR.json +0 -306
  353. package/dist/cjs/i18n/locales/locales/it-IT.json +0 -306
  354. package/dist/cjs/i18n/locales/locales/ko-KR.json +0 -306
  355. package/dist/cjs/i18n/locales/locales/pt-PT.json +0 -306
  356. package/dist/cjs/i18n/locales/locales/zh-CN.json +0 -306
  357. package/dist/cjs/mixins/OxyServices.accounts.js +0 -555
  358. package/dist/cjs/mixins/OxyServices.agency.js +0 -154
  359. package/dist/cjs/mixins/OxyServices.analytics.js +0 -49
  360. package/dist/cjs/mixins/OxyServices.appData.js +0 -108
  361. package/dist/cjs/mixins/OxyServices.assets.js +0 -854
  362. package/dist/cjs/mixins/OxyServices.auth.js +0 -1495
  363. package/dist/cjs/mixins/OxyServices.chains.js +0 -73
  364. package/dist/cjs/mixins/OxyServices.civic.js +0 -611
  365. package/dist/cjs/mixins/OxyServices.connectedApps.js +0 -95
  366. package/dist/cjs/mixins/OxyServices.contacts.js +0 -50
  367. package/dist/cjs/mixins/OxyServices.deviceBoot.js +0 -191
  368. package/dist/cjs/mixins/OxyServices.devices.js +0 -116
  369. package/dist/cjs/mixins/OxyServices.features.js +0 -335
  370. package/dist/cjs/mixins/OxyServices.followGraph.js +0 -221
  371. package/dist/cjs/mixins/OxyServices.identity.js +0 -562
  372. package/dist/cjs/mixins/OxyServices.identityBackup.js +0 -172
  373. package/dist/cjs/mixins/OxyServices.inference.js +0 -59
  374. package/dist/cjs/mixins/OxyServices.language.js +0 -125
  375. package/dist/cjs/mixins/OxyServices.linkedAccounts.js +0 -79
  376. package/dist/cjs/mixins/OxyServices.location.js +0 -43
  377. package/dist/cjs/mixins/OxyServices.nodes.js +0 -175
  378. package/dist/cjs/mixins/OxyServices.notifications.js +0 -63
  379. package/dist/cjs/mixins/OxyServices.payment.js +0 -158
  380. package/dist/cjs/mixins/OxyServices.privacy.js +0 -199
  381. package/dist/cjs/mixins/OxyServices.reputation.js +0 -289
  382. package/dist/cjs/mixins/OxyServices.security.js +0 -89
  383. package/dist/cjs/mixins/OxyServices.store.js +0 -266
  384. package/dist/cjs/mixins/OxyServices.topics.js +0 -137
  385. package/dist/cjs/mixins/OxyServices.user.js +0 -954
  386. package/dist/cjs/mixins/OxyServices.utility.js +0 -1402
  387. package/dist/cjs/mixins/index.js +0 -136
  388. package/dist/cjs/mixins/mixinHelpers.js +0 -53
  389. package/dist/cjs/utils/webauthnOrigin.js +0 -51
  390. package/dist/esm/.tsbuildinfo +0 -1
  391. package/dist/esm/OxyServices.base.js +0 -388
  392. package/dist/esm/i18n/locales/locales/ar-SA.json +0 -306
  393. package/dist/esm/i18n/locales/locales/ca-ES.json +0 -306
  394. package/dist/esm/i18n/locales/locales/de-DE.json +0 -306
  395. package/dist/esm/i18n/locales/locales/en-US.json +0 -2127
  396. package/dist/esm/i18n/locales/locales/es-ES.json +0 -2127
  397. package/dist/esm/i18n/locales/locales/fr-FR.json +0 -306
  398. package/dist/esm/i18n/locales/locales/it-IT.json +0 -306
  399. package/dist/esm/i18n/locales/locales/ja-JP.json +0 -306
  400. package/dist/esm/i18n/locales/locales/ko-KR.json +0 -306
  401. package/dist/esm/i18n/locales/locales/pt-PT.json +0 -306
  402. package/dist/esm/i18n/locales/locales/zh-CN.json +0 -306
  403. package/dist/esm/mixins/OxyServices.accounts.js +0 -543
  404. package/dist/esm/mixins/OxyServices.agency.js +0 -151
  405. package/dist/esm/mixins/OxyServices.analytics.js +0 -46
  406. package/dist/esm/mixins/OxyServices.appData.js +0 -103
  407. package/dist/esm/mixins/OxyServices.assets.js +0 -851
  408. package/dist/esm/mixins/OxyServices.auth.js +0 -1455
  409. package/dist/esm/mixins/OxyServices.chains.js +0 -70
  410. package/dist/esm/mixins/OxyServices.civic.js +0 -605
  411. package/dist/esm/mixins/OxyServices.connectedApps.js +0 -92
  412. package/dist/esm/mixins/OxyServices.contacts.js +0 -47
  413. package/dist/esm/mixins/OxyServices.deviceBoot.js +0 -186
  414. package/dist/esm/mixins/OxyServices.devices.js +0 -113
  415. package/dist/esm/mixins/OxyServices.features.js +0 -332
  416. package/dist/esm/mixins/OxyServices.followGraph.js +0 -218
  417. package/dist/esm/mixins/OxyServices.identity.js +0 -558
  418. package/dist/esm/mixins/OxyServices.identityBackup.js +0 -169
  419. package/dist/esm/mixins/OxyServices.inference.js +0 -56
  420. package/dist/esm/mixins/OxyServices.language.js +0 -122
  421. package/dist/esm/mixins/OxyServices.linkedAccounts.js +0 -76
  422. package/dist/esm/mixins/OxyServices.location.js +0 -40
  423. package/dist/esm/mixins/OxyServices.nodes.js +0 -172
  424. package/dist/esm/mixins/OxyServices.notifications.js +0 -60
  425. package/dist/esm/mixins/OxyServices.payment.js +0 -155
  426. package/dist/esm/mixins/OxyServices.privacy.js +0 -196
  427. package/dist/esm/mixins/OxyServices.reputation.js +0 -286
  428. package/dist/esm/mixins/OxyServices.security.js +0 -86
  429. package/dist/esm/mixins/OxyServices.store.js +0 -263
  430. package/dist/esm/mixins/OxyServices.topics.js +0 -134
  431. package/dist/esm/mixins/OxyServices.user.js +0 -951
  432. package/dist/esm/mixins/OxyServices.utility.js +0 -1397
  433. package/dist/esm/mixins/index.js +0 -133
  434. package/dist/esm/mixins/mixinHelpers.js +0 -48
  435. package/dist/esm/utils/webauthnOrigin.js +0 -48
  436. package/dist/types/.tsbuildinfo +0 -1
  437. package/dist/types/OxyServices.base.d.ts +0 -189
  438. package/dist/types/mixins/OxyServices.accounts.d.ts +0 -868
  439. package/dist/types/mixins/OxyServices.agency.d.ts +0 -176
  440. package/dist/types/mixins/OxyServices.analytics.d.ts +0 -72
  441. package/dist/types/mixins/OxyServices.appData.d.ts +0 -108
  442. package/dist/types/mixins/OxyServices.assets.d.ts +0 -371
  443. package/dist/types/mixins/OxyServices.auth.d.ts +0 -998
  444. package/dist/types/mixins/OxyServices.chains.d.ts +0 -156
  445. package/dist/types/mixins/OxyServices.civic.d.ts +0 -520
  446. package/dist/types/mixins/OxyServices.connectedApps.d.ts +0 -184
  447. package/dist/types/mixins/OxyServices.contacts.d.ts +0 -100
  448. package/dist/types/mixins/OxyServices.deviceBoot.d.ts +0 -185
  449. package/dist/types/mixins/OxyServices.devices.d.ts +0 -103
  450. package/dist/types/mixins/OxyServices.features.d.ts +0 -250
  451. package/dist/types/mixins/OxyServices.followGraph.d.ts +0 -223
  452. package/dist/types/mixins/OxyServices.identity.d.ts +0 -337
  453. package/dist/types/mixins/OxyServices.identityBackup.d.ts +0 -129
  454. package/dist/types/mixins/OxyServices.inference.d.ts +0 -95
  455. package/dist/types/mixins/OxyServices.language.d.ts +0 -87
  456. package/dist/types/mixins/OxyServices.linkedAccounts.d.ts +0 -107
  457. package/dist/types/mixins/OxyServices.location.d.ts +0 -70
  458. package/dist/types/mixins/OxyServices.nodes.d.ts +0 -198
  459. package/dist/types/mixins/OxyServices.notifications.d.ts +0 -143
  460. package/dist/types/mixins/OxyServices.payment.d.ts +0 -117
  461. package/dist/types/mixins/OxyServices.privacy.d.ts +0 -146
  462. package/dist/types/mixins/OxyServices.reputation.d.ts +0 -202
  463. package/dist/types/mixins/OxyServices.security.d.ts +0 -84
  464. package/dist/types/mixins/OxyServices.store.d.ts +0 -334
  465. package/dist/types/mixins/OxyServices.topics.d.ts +0 -110
  466. package/dist/types/mixins/OxyServices.user.d.ts +0 -600
  467. package/dist/types/mixins/OxyServices.utility.d.ts +0 -526
  468. package/dist/types/mixins/index.d.ts +0 -87
  469. package/dist/types/mixins/mixinHelpers.d.ts +0 -31
  470. package/dist/types/utils/webauthnOrigin.d.ts +0 -32
  471. package/src/OxyServices.base.ts +0 -480
  472. package/src/__tests__/authSocket.test.ts +0 -96
  473. package/src/__tests__/fixEsmImports.test.ts +0 -132
  474. package/src/__tests__/httpServiceAbort.test.ts +0 -308
  475. package/src/__tests__/httpServiceActivityId.test.ts +0 -49
  476. package/src/__tests__/httpServiceAuthSelfAwait.test.ts +0 -108
  477. package/src/__tests__/httpServiceCache.test.ts +0 -318
  478. package/src/__tests__/httpServiceFormEncoded.test.ts +0 -139
  479. package/src/__tests__/httpServiceQueueDeadlock.test.ts +0 -128
  480. package/src/__tests__/httpServiceRateLimitedRefresh.test.ts +0 -160
  481. package/src/__tests__/httpServiceUnwrapEnvelope.test.ts +0 -115
  482. package/src/__tests__/httpServiceWrites.test.ts +0 -175
  483. package/src/__tests__/inSessionRefresh.test.ts +0 -313
  484. package/src/__tests__/linkedClient.test.ts +0 -363
  485. package/src/__tests__/nearExpiryMintStorm.test.ts +0 -165
  486. package/src/__tests__/parseHttpErrorBody.test.ts +0 -116
  487. package/src/__tests__/publicInterfaceParity.test.ts +0 -75
  488. package/src/__tests__/serverValueImportsDeclared.test.ts +0 -120
  489. package/src/__tests__/serviceIdentityWhenAnonymous.test.ts +0 -159
  490. package/src/__tests__/serviceTokenWorkloadFallback.test.ts +0 -85
  491. package/src/__tests__/userIdentity.test.ts +0 -143
  492. package/src/boot/__tests__/sessionColdBoot.identity.test.ts +0 -393
  493. package/src/boot/__tests__/sessionColdBoot.sharedDevice.test.ts +0 -325
  494. package/src/boot/__tests__/sessionColdBoot.test.ts +0 -570
  495. package/src/crypto/__tests__/backupMaterial.test.ts +0 -86
  496. package/src/crypto/__tests__/cryptoPrimitives.test.ts +0 -226
  497. package/src/crypto/__tests__/identityLink.test.ts +0 -18
  498. package/src/crypto/__tests__/identityMocks.ts +0 -125
  499. package/src/crypto/__tests__/identityProof.test.ts +0 -81
  500. package/src/crypto/__tests__/keyManager.atomicity.test.ts +0 -272
  501. package/src/crypto/__tests__/keyManager.cacheSafety.test.ts +0 -175
  502. package/src/crypto/__tests__/keyManager.deviceBackup.test.ts +0 -310
  503. package/src/crypto/__tests__/keyManager.identityStatus.test.ts +0 -217
  504. package/src/crypto/__tests__/keyManager.recoveryLadder.test.ts +0 -179
  505. package/src/crypto/__tests__/keyManager.recoveryMnemonic.test.ts +0 -138
  506. package/src/crypto/__tests__/keyManager.sharedSlotSync.test.ts +0 -150
  507. package/src/crypto/__tests__/keyManager.storageMigration.test.ts +0 -227
  508. package/src/crypto/__tests__/keyManager.test.ts +0 -329
  509. package/src/crypto/__tests__/polyfill.test.ts +0 -109
  510. package/src/crypto/__tests__/polyfillOrder.test.ts +0 -114
  511. package/src/crypto/__tests__/recoveryPhrase.test.ts +0 -61
  512. package/src/crypto/__tests__/registrationPow.test.ts +0 -61
  513. package/src/crypto/__tests__/scopedSeed.test.ts +0 -126
  514. package/src/crypto/__tests__/signChallengeShared.test.ts +0 -63
  515. package/src/crypto/__tests__/signedRecord.test.ts +0 -230
  516. package/src/i18n/__tests__/accountCategoryLabels.test.ts +0 -62
  517. package/src/i18n/__tests__/accountRoleLabels.test.ts +0 -54
  518. package/src/i18n/__tests__/reputationCategoryLabels.test.ts +0 -56
  519. package/src/i18n/__tests__/trustTierLabels.test.ts +0 -47
  520. package/src/i18n/locales/de-DE.json +0 -306
  521. package/src/i18n/locales/es-ES.json +0 -2127
  522. package/src/i18n/locales/ja-JP.json +0 -306
  523. package/src/inference/__tests__/OxyInferenceClient.test.ts +0 -899
  524. package/src/logger/__tests__/logger.test.ts +0 -207
  525. package/src/mixins/OxyServices.accounts.ts +0 -1330
  526. package/src/mixins/OxyServices.agency.ts +0 -353
  527. package/src/mixins/OxyServices.analytics.ts +0 -53
  528. package/src/mixins/OxyServices.appData.ts +0 -158
  529. package/src/mixins/OxyServices.assets.ts +0 -964
  530. package/src/mixins/OxyServices.auth.ts +0 -2083
  531. package/src/mixins/OxyServices.chains.ts +0 -134
  532. package/src/mixins/OxyServices.civic.ts +0 -945
  533. package/src/mixins/OxyServices.connectedApps.ts +0 -212
  534. package/src/mixins/OxyServices.contacts.ts +0 -73
  535. package/src/mixins/OxyServices.devices.ts +0 -120
  536. package/src/mixins/OxyServices.features.ts +0 -454
  537. package/src/mixins/OxyServices.followGraph.ts +0 -293
  538. package/src/mixins/OxyServices.identity.ts +0 -787
  539. package/src/mixins/OxyServices.identityBackup.ts +0 -250
  540. package/src/mixins/OxyServices.inference.ts +0 -57
  541. package/src/mixins/OxyServices.language.ts +0 -144
  542. package/src/mixins/OxyServices.linkedAccounts.ts +0 -129
  543. package/src/mixins/OxyServices.location.ts +0 -46
  544. package/src/mixins/OxyServices.nodes.ts +0 -337
  545. package/src/mixins/OxyServices.notifications.ts +0 -142
  546. package/src/mixins/OxyServices.payment.ts +0 -163
  547. package/src/mixins/OxyServices.privacy.ts +0 -219
  548. package/src/mixins/OxyServices.reputation.ts +0 -436
  549. package/src/mixins/OxyServices.security.ts +0 -110
  550. package/src/mixins/OxyServices.store.ts +0 -585
  551. package/src/mixins/OxyServices.topics.ts +0 -169
  552. package/src/mixins/OxyServices.user.ts +0 -1208
  553. package/src/mixins/OxyServices.utility.ts +0 -1803
  554. package/src/mixins/__tests__/OxyServices.civic.test.ts +0 -1095
  555. package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +0 -124
  556. package/src/mixins/__tests__/OxyServices.identity.test.ts +0 -301
  557. package/src/mixins/__tests__/OxyServices.nodes.test.ts +0 -341
  558. package/src/mixins/__tests__/OxyServices.rotateKey.test.ts +0 -323
  559. package/src/mixins/__tests__/OxyServices.serviceAssetMetadata.test.ts +0 -192
  560. package/src/mixins/__tests__/OxyServices.serviceAssetMetadataBySha.test.ts +0 -135
  561. package/src/mixins/__tests__/OxyServices.serviceLinkedDownloadUrl.test.ts +0 -139
  562. package/src/mixins/__tests__/accountEvents.test.ts +0 -158
  563. package/src/mixins/__tests__/accounts.test.ts +0 -727
  564. package/src/mixins/__tests__/agency.test.ts +0 -120
  565. package/src/mixins/__tests__/appData.test.ts +0 -203
  566. package/src/mixins/__tests__/assetCredentials.test.ts +0 -47
  567. package/src/mixins/__tests__/assetUpload.test.ts +0 -191
  568. package/src/mixins/__tests__/authRefusalObservability.test.ts +0 -396
  569. package/src/mixins/__tests__/backgroundCredential.httpIntegration.test.ts +0 -130
  570. package/src/mixins/__tests__/chains.test.ts +0 -113
  571. package/src/mixins/__tests__/commonsSignIn.test.ts +0 -1147
  572. package/src/mixins/__tests__/connectedApps.test.ts +0 -146
  573. package/src/mixins/__tests__/deviceTokenMintPinned.test.ts +0 -113
  574. package/src/mixins/__tests__/discoveryErrorHandling.test.ts +0 -265
  575. package/src/mixins/__tests__/followCacheInvalidation.test.ts +0 -173
  576. package/src/mixins/__tests__/followGraph.test.ts +0 -147
  577. package/src/mixins/__tests__/followGraphPagination.test.ts +0 -271
  578. package/src/mixins/__tests__/getFileDownloadUrl.test.ts +0 -346
  579. package/src/mixins/__tests__/getFollowStatuses.test.ts +0 -95
  580. package/src/mixins/__tests__/getUsersByIds.test.ts +0 -176
  581. package/src/mixins/__tests__/identityBackup.test.ts +0 -315
  582. package/src/mixins/__tests__/identityLink.test.ts +0 -89
  583. package/src/mixins/__tests__/identityWriteCacheInvalidation.test.ts +0 -407
  584. package/src/mixins/__tests__/inferenceFactory.test.ts +0 -58
  585. package/src/mixins/__tests__/linkedAccounts.test.ts +0 -109
  586. package/src/mixins/__tests__/notifications.read.test.ts +0 -82
  587. package/src/mixins/__tests__/onTokensChanged.test.ts +0 -129
  588. package/src/mixins/__tests__/preSessionSkipAuth.test.ts +0 -284
  589. package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +0 -155
  590. package/src/mixins/__tests__/reputation.test.ts +0 -522
  591. package/src/mixins/__tests__/serviceAuth.test.ts +0 -889
  592. package/src/mixins/__tests__/serviceTokenJwks.test.ts +0 -208
  593. package/src/mixins/__tests__/store.test.ts +0 -304
  594. package/src/mixins/__tests__/topics.test.ts +0 -155
  595. package/src/mixins/__tests__/userReadCacheBypass.test.ts +0 -129
  596. package/src/mixins/__tests__/userTokenAuth.test.ts +0 -746
  597. package/src/mixins/__tests__/verifyChallenge.test.ts +0 -161
  598. package/src/mixins/__tests__/verifyServiceActingAs.test.ts +0 -167
  599. package/src/mixins/__tests__/webauthnAuth.test.ts +0 -279
  600. package/src/mixins/index.ts +0 -203
  601. package/src/mixins/mixinHelpers.ts +0 -69
  602. package/src/server/__tests__/auth.test.ts +0 -78
  603. package/src/server/__tests__/capabilityTicket.test.ts +0 -111
  604. package/src/server/__tests__/cors.socket.test.ts +0 -225
  605. package/src/server/__tests__/cors.test.ts +0 -158
  606. package/src/server/__tests__/rateLimit.test.ts +0 -257
  607. package/src/server/__tests__/requesterAssertion.test.ts +0 -359
  608. package/src/server/__tests__/safeFetch.test.ts +0 -232
  609. package/src/server/__tests__/securityHeaders.test.ts +0 -387
  610. package/src/server/__tests__/serviceTokenAttribution.test.ts +0 -396
  611. package/src/server/__tests__/traffic.test.ts +0 -180
  612. package/src/server/__tests__/trafficNodeHttp.test.ts +0 -38
  613. package/src/server/__tests__/userInvalidation.test.ts +0 -203
  614. package/src/server/__tests__/verifySecret.test.ts +0 -40
  615. package/src/server/__tests__/workloadIdentity.client.test.ts +0 -16
  616. package/src/server/__tests__/workloadIdentity.test.ts +0 -128
  617. package/src/session/__tests__/SessionClient.additive.test.ts +0 -153
  618. package/src/session/__tests__/SessionClient.broadcastChannel.test.ts +0 -114
  619. package/src/session/__tests__/SessionClient.diagnostics.test.ts +0 -91
  620. package/src/session/__tests__/SessionClient.directory.test.ts +0 -688
  621. package/src/session/__tests__/SessionClient.httpIntegration.test.ts +0 -65
  622. package/src/session/__tests__/SessionClient.identityPin.test.ts +0 -175
  623. package/src/session/__tests__/SessionClient.rest.test.ts +0 -119
  624. package/src/session/__tests__/SessionClient.serverEvents.test.ts +0 -72
  625. package/src/session/__tests__/SessionClient.socket.test.ts +0 -202
  626. package/src/session/__tests__/SessionClient.socketFactory.test.ts +0 -81
  627. package/src/session/__tests__/SessionClient.state.test.ts +0 -78
  628. package/src/session/__tests__/SessionClient.switchTokenOrder.test.ts +0 -170
  629. package/src/session/__tests__/accountDelegationAccess.test.ts +0 -104
  630. package/src/session/__tests__/accountDialogController.test.ts +0 -2502
  631. package/src/session/__tests__/accountDialogShape.test.ts +0 -120
  632. package/src/session/__tests__/accountSwitchTargets.test.ts +0 -137
  633. package/src/session/__tests__/authStateStore.test.ts +0 -451
  634. package/src/session/__tests__/deviceDirectory.test.ts +0 -422
  635. package/src/session/__tests__/deviceSwitcherRows.test.ts +0 -223
  636. package/src/session/__tests__/identityPin.test.ts +0 -131
  637. package/src/session/__tests__/identitySession.test.ts +0 -194
  638. package/src/session/__tests__/projectSessionState.test.ts +0 -105
  639. package/src/session/__tests__/refresh.identityPin.test.ts +0 -307
  640. package/src/session/__tests__/refresh.test.ts +0 -606
  641. package/src/session/__tests__/sessionIntegration.test.ts +0 -209
  642. package/src/session/__tests__/sharedDeviceCredential.test.ts +0 -300
  643. package/src/utils/__tests__/accountUtils.test.ts +0 -151
  644. package/src/utils/__tests__/activityId.test.ts +0 -45
  645. package/src/utils/__tests__/asyncUtils.test.ts +0 -279
  646. package/src/utils/__tests__/authWebUrl.test.ts +0 -15
  647. package/src/utils/__tests__/cacheKey.test.ts +0 -0
  648. package/src/utils/__tests__/cacheLifecycle.test.ts +0 -65
  649. package/src/utils/__tests__/coldBoot.test.ts +0 -496
  650. package/src/utils/__tests__/commonsApproval.test.ts +0 -60
  651. package/src/utils/__tests__/identityCacheSweep.test.ts +0 -151
  652. package/src/utils/__tests__/languageUtils.test.ts +0 -244
  653. package/src/utils/__tests__/oauthPkce.test.ts +0 -303
  654. package/src/utils/__tests__/officialOrigins.test.ts +0 -31
  655. package/src/utils/__tests__/oxyServiceEnvironment.test.ts +0 -7
  656. package/src/utils/__tests__/profileLinks.test.ts +0 -180
  657. package/src/utils/__tests__/redactUrl.test.ts +0 -33
  658. package/src/utils/__tests__/registrableApex.test.ts +0 -62
  659. package/src/utils/__tests__/requestUtilsAbort.test.ts +0 -155
  660. package/src/utils/__tests__/textNormalization.test.ts +0 -205
  661. package/src/utils/__tests__/validationUtils.test.ts +0 -703
  662. package/src/utils/__tests__/webauthnOrigin.test.ts +0 -83
  663. package/src/utils/webauthnOrigin.ts +0 -52
@@ -1,703 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import {
4
- isRequiredString,
5
- isRequiredNumber,
6
- isRequiredBoolean,
7
- isValidArray,
8
- isValidObject,
9
- isValidEmail,
10
- isValidPassword,
11
- isValidDisplayName,
12
- DISPLAY_NAME_ALLOWED_SCRIPTS,
13
- DISPLAY_NAME_DISALLOWED_SOURCE,
14
- DISPLAY_NAME_ORPHANED_MARK_SOURCE,
15
- DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE,
16
- isValidUUID,
17
- isValidDate,
18
- isValidFileSize,
19
- isValidFileType,
20
- sanitizeString,
21
- sanitizeHTML,
22
- validateAndSanitizeUserInput
23
- } from '../validationUtils';
24
- // Imported from the generated module rather than re-exported through
25
- // `validationUtils`: the broad letters class is an internal operand of the
26
- // orphaned-mark lookbehind, and the denylist is a generation-time operand
27
- // already subtracted from the allowlist — neither is part of the policy's
28
- // public runtime surface.
29
- import {
30
- DISPLAY_NAME_DENIED_SYMBOL_LETTERS_RANGES,
31
- DISPLAY_NAME_LETTERS_RANGES,
32
- DISPLAY_NAME_NAME_SEPARATORS_RANGES,
33
- } from '../displayNamePolicyRanges.generated';
34
-
35
- describe('Validation Utils', () => {
36
- describe('isRequiredString', () => {
37
- it('should return true for valid non-empty strings', () => {
38
- expect(isRequiredString('hello')).toBe(true);
39
- expect(isRequiredString(' hello ')).toBe(true); // trims whitespace
40
- });
41
-
42
- it('should return false for invalid or empty strings', () => {
43
- expect(isRequiredString('')).toBe(false);
44
- expect(isRequiredString(' ')).toBe(false); // only whitespace
45
- expect(isRequiredString(null)).toBe(false);
46
- expect(isRequiredString(undefined)).toBe(false);
47
- expect(isRequiredString(123)).toBe(false);
48
- });
49
- });
50
-
51
- describe('isRequiredNumber', () => {
52
- it('should return true for valid numbers', () => {
53
- expect(isRequiredNumber(123)).toBe(true);
54
- expect(isRequiredNumber(0)).toBe(true);
55
- expect(isRequiredNumber(-456)).toBe(true);
56
- expect(isRequiredNumber(3.14)).toBe(true);
57
- });
58
-
59
- it('should return false for invalid numbers', () => {
60
- expect(isRequiredNumber(Number.NaN)).toBe(false);
61
- expect(isRequiredNumber('123')).toBe(false);
62
- expect(isRequiredNumber(null)).toBe(false);
63
- expect(isRequiredNumber(undefined)).toBe(false);
64
- });
65
- });
66
-
67
- describe('isRequiredBoolean', () => {
68
- it('should return true for boolean values', () => {
69
- expect(isRequiredBoolean(true)).toBe(true);
70
- expect(isRequiredBoolean(false)).toBe(true);
71
- });
72
-
73
- it('should return false for non-boolean values', () => {
74
- expect(isRequiredBoolean('true')).toBe(false);
75
- expect(isRequiredBoolean(1)).toBe(false);
76
- expect(isRequiredBoolean(0)).toBe(false);
77
- expect(isRequiredBoolean(null)).toBe(false);
78
- expect(isRequiredBoolean(undefined)).toBe(false);
79
- });
80
- });
81
-
82
- describe('isValidArray', () => {
83
- it('should return true for arrays', () => {
84
- expect(isValidArray([])).toBe(true);
85
- expect(isValidArray([1, 2, 3])).toBe(true);
86
- expect(isValidArray(['a', 'b'])).toBe(true);
87
- });
88
-
89
- it('should return false for non-arrays', () => {
90
- expect(isValidArray({})).toBe(false);
91
- expect(isValidArray('[]')).toBe(false);
92
- expect(isValidArray(null)).toBe(false);
93
- expect(isValidArray(undefined)).toBe(false);
94
- });
95
- });
96
-
97
- describe('isValidObject', () => {
98
- it('should return true for plain objects', () => {
99
- expect(isValidObject({})).toBe(true);
100
- expect(isValidObject({ key: 'value' })).toBe(true);
101
- });
102
-
103
- it('should return false for non-objects', () => {
104
- expect(isValidObject([])).toBe(false);
105
- expect(isValidObject(null)).toBe(false);
106
- expect(isValidObject(undefined)).toBe(false);
107
- expect(isValidObject('object')).toBe(false);
108
- expect(isValidObject(123)).toBe(false);
109
- });
110
- });
111
-
112
- describe('isValidEmail', () => {
113
- it('should return true for valid email addresses', () => {
114
- expect(isValidEmail('test@example.com')).toBe(true);
115
- expect(isValidEmail('user.name+tag@domain.co.uk')).toBe(true);
116
- expect(isValidEmail('simple@test.io')).toBe(true);
117
- });
118
-
119
- it('should return false for invalid email addresses', () => {
120
- expect(isValidEmail('invalid-email')).toBe(false);
121
- expect(isValidEmail('test@')).toBe(false);
122
- expect(isValidEmail('@domain.com')).toBe(false);
123
- expect(isValidEmail('test.domain.com')).toBe(false);
124
- expect(isValidEmail('')).toBe(false);
125
- });
126
- });
127
-
128
- /**
129
- * `isValidUsername` and `USERNAME_REGEX` were REMOVED from this module: they
130
- * were a second username policy, looser than the one the server enforced, so
131
- * the SDK could call a name valid and the API 400 it. The rule now lives once,
132
- * in `@oxy.so/contracts`, and its own suite covers it. What survives here is the
133
- * one thing this module still does with a username — sanitise-then-validate,
134
- * asserted below to answer from that single policy.
135
- */
136
-
137
- describe('isValidPassword', () => {
138
- it('should return true for valid passwords', () => {
139
- expect(isValidPassword('password123')).toBe(true);
140
- expect(isValidPassword('mySecurePass')).toBe(true);
141
- expect(isValidPassword('12345678')).toBe(true);
142
- });
143
-
144
- it('should return false for invalid passwords', () => {
145
- expect(isValidPassword('')).toBe(false);
146
- expect(isValidPassword('short')).toBe(false); // too short
147
- expect(isValidPassword('1234567')).toBe(false); // too short
148
- });
149
- });
150
-
151
- describe('isValidDisplayName', () => {
152
- it('should return true for clean names (letters, spaces, apostrophe)', () => {
153
- expect(isValidDisplayName("Renée O'Brien")).toBe(true);
154
- expect(isValidDisplayName('Ada Lovelace')).toBe(true);
155
- expect(isValidDisplayName('山田太郎')).toBe(true);
156
- expect(isValidDisplayName('')).toBe(true); // empty is valid; non-empty enforced elsewhere
157
- });
158
-
159
- it.each([
160
- ['Владимир', 'Cyrillic'],
161
- ['مُحَمَد', 'Arabic with harakat'],
162
- ['נתן', 'Hebrew'],
163
- ['नमस्ते', 'Devanagari'],
164
- ['김철수', 'Hangul'],
165
- ['Αριστοτέλης', 'Greek'],
166
- ['Արամ', 'Armenian'],
167
- ['დავით', 'Georgian'],
168
- ['สมชาย', 'Thai'],
169
- ['ᏔᎳ', 'Cherokee'],
170
- ['ᠮᠣᠩᠭᠣᠯ', 'Mongolian'],
171
- ])('should return true for allowlisted-script real name %p (%s)', (name) => {
172
- expect(isValidDisplayName(name)).toBe(true);
173
- });
174
-
175
- it('should return false for emoji, symbols, digits, and punctuation', () => {
176
- expect(isValidDisplayName('nixCraft \u{1f427}')).toBe(false); // penguin emoji
177
- expect(isValidDisplayName('Agent007')).toBe(false);
178
- expect(isValidDisplayName('Jean-Luc')).toBe(false);
179
- expect(isValidDisplayName('J.R.')).toBe(false);
180
- });
181
-
182
- it.each([
183
- ['ᯅ', 'Batak U+1BC5 (Limited-Use script)'],
184
- ['ᚠ', 'Runic'],
185
- ['Miguel de Icaza ᯅ', 'a Latin name with a trailing Batak letter'],
186
- ])('should return false for non-allowlisted-script letter %p (%s)', (name) => {
187
- // These characters are General_Category Lo (letters), so the old
188
- // all-scripts policy accepted them; the curated script allowlist rejects
189
- // decorative / limited-use scripts a real name never uses.
190
- expect(isValidDisplayName(name)).toBe(false);
191
- });
192
-
193
- it('should return false for control whitespace (tab/newline/CR)', () => {
194
- // Space separators only (General_Category Zs) rejects layout-breaking /
195
- // multi-line spoofing whitespace that \s would have admitted.
196
- expect(isValidDisplayName('Ada\tLovelace')).toBe(false);
197
- expect(isValidDisplayName('Ada\nLovelace')).toBe(false);
198
- expect(isValidDisplayName('Ada\rLovelace')).toBe(false);
199
- });
200
-
201
- it('should return true for Unicode space separators', () => {
202
- expect(isValidDisplayName('Ada Lovelace')).toBe(true); // NBSP
203
- expect(isValidDisplayName('山田 太郎')).toBe(true); // ideographic space
204
- });
205
- });
206
-
207
- // Hermes (React Native) has Unicode property escapes compiled OUT: any such
208
- // escape (Script_Extensions "scx=…" or General_Category classes) in a `u`-flag
209
- // regex throws "Invalid RegExp: Invalid property name" at module load and
210
- // crashes every Oxy RN/Expo app at boot. The display-name policy therefore
211
- // ships explicit code-point RANGES instead. This block guards that invariant
212
- // AND proves the range regexes behave identically.
213
- describe('display-name policy is property-escape-free (Hermes safety)', () => {
214
- const PROPERTY_ESCAPE = /\\[pP]\{/;
215
-
216
- it('exposes runtime regex sources that contain NO Unicode property escape', () => {
217
- expect(PROPERTY_ESCAPE.test(DISPLAY_NAME_ALLOWED_SCRIPTS)).toBe(false);
218
- expect(PROPERTY_ESCAPE.test(DISPLAY_NAME_DISALLOWED_SOURCE)).toBe(false);
219
- expect(PROPERTY_ESCAPE.test(DISPLAY_NAME_ORPHANED_MARK_SOURCE)).toBe(false);
220
- expect(PROPERTY_ESCAPE.test(DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE)).toBe(false);
221
- });
222
-
223
- it('only uses code-point escapes (\\x / \\u) in the class bodies', () => {
224
- // regexpu-core lowers the property escapes to `\x…` / `\u…` / `\u{…}`
225
- // code-point escapes. Every backslash-escape in the runtime sources must
226
- // be one of those forms — never a property escape.
227
- const escapeLeads = new Set<string>();
228
- for (const src of [
229
- DISPLAY_NAME_DISALLOWED_SOURCE,
230
- DISPLAY_NAME_ORPHANED_MARK_SOURCE,
231
- DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE,
232
- ]) {
233
- for (const [, lead] of src.matchAll(/\\(.)/g)) {
234
- escapeLeads.add(lead);
235
- }
236
- }
237
- expect([...escapeLeads].sort()).toEqual(['u', 'x']);
238
- });
239
-
240
- it('the shipped (non-test) policy source files contain NO property escape', () => {
241
- const utilsDir = join(__dirname, '..');
242
- for (const file of [
243
- 'validationUtils.ts',
244
- 'displayNamePolicyRanges.generated.ts',
245
- 'textNormalization.ts',
246
- ]) {
247
- const contents = readFileSync(join(utilsDir, file), 'utf8');
248
- expect(PROPERTY_ESCAPE.test(contents)).toBe(false);
249
- }
250
- });
251
-
252
- // Build the actual regexes exactly as production does (range-only sources +
253
- // `u` flag + lookbehind — the shape Hermes must accept) and assert the full
254
- // policy behaves as before across scripts, marks, and rejections.
255
- const disallowed = new RegExp(DISPLAY_NAME_DISALLOWED_SOURCE, 'u');
256
- const orphaned = new RegExp(DISPLAY_NAME_ORPHANED_MARK_SOURCE, 'u');
257
- const passesPolicy = (raw: string) =>
258
- !disallowed.test(raw) && !orphaned.test(raw.normalize('NFC'));
259
-
260
- it('constructs the `u`-flag regexes without throwing', () => {
261
- expect(() => new RegExp(DISPLAY_NAME_DISALLOWED_SOURCE, 'u')).not.toThrow();
262
- expect(() => new RegExp(DISPLAY_NAME_ORPHANED_MARK_SOURCE, 'u')).not.toThrow();
263
- // Global variants are what @oxy.so/api compiles for the strip path.
264
- expect(() => new RegExp(DISPLAY_NAME_DISALLOWED_SOURCE, 'gu')).not.toThrow();
265
- expect(() => new RegExp(DISPLAY_NAME_ORPHANED_MARK_SOURCE, 'gu')).not.toThrow();
266
- });
267
-
268
- it.each([
269
- ["Renée O'Brien", 'Latin with decomposed accent + apostrophe'],
270
- ['Ada Lovelace', 'ASCII Latin'],
271
- ['山田太郎', 'Han'],
272
- ['田中\u{20000}', 'Han incl. astral CJK Extension B'],
273
- ['Владимир', 'Cyrillic'],
274
- ['مُحَمَد', 'Arabic with harakat (combining marks on base letters)'],
275
- ['נתן', 'Hebrew'],
276
- ['नमस्ते', 'Devanagari'],
277
- ['김철수', 'Hangul'],
278
- ['Αριστοτέλης', 'Greek'],
279
- ['ᏔᎳ', 'Cherokee'],
280
- ['ᠮᠣᠩᠭᠣᠯ', 'Mongolian'],
281
- ])('range regexes ACCEPT allowlisted %p (%s)', (name) => {
282
- expect(passesPolicy(name)).toBe(true);
283
- // Parity with the public predicate.
284
- expect(isValidDisplayName(name)).toBe(true);
285
- });
286
-
287
- it.each([
288
- ['nixCraft \u{1f427}', 'emoji (astral)'],
289
- ['Agent007', 'digit'],
290
- ['Jean-Luc', 'hyphen'],
291
- ['J.R.', 'dot'],
292
- ['ᯅ', 'Batak (non-allowlisted script)'],
293
- ['ᚠ', 'Runic (non-allowlisted script)'],
294
- ['Ada\tLovelace', 'tab (control whitespace)'],
295
- ['Ada\nLovelace', 'newline (control whitespace)'],
296
- ['Ada\rLovelace', 'carriage return (control whitespace)'],
297
- ])('range regexes REJECT %p (%s)', (name) => {
298
- expect(passesPolicy(name)).toBe(false);
299
- expect(isValidDisplayName(name)).toBe(false);
300
- });
301
-
302
- it('rejects an orphaned combining mark not riding a base letter', () => {
303
- expect(passesPolicy('༘⋆')).toBe(false); // lone Tibetan mark + star
304
- expect(orphaned.test('༘')).toBe(true); // bare mark at string start
305
- // A decomposed accent recomposes under NFC and rides its base letter.
306
- expect(orphaned.test('é'.normalize('NFC'))).toBe(false);
307
- });
308
- });
309
-
310
- // A Unicode script is not only its letters: `scx=X` also carries script X's
311
- // own digits, punctuation and symbols. The allowlist is therefore generated as
312
- // `scripts ∩ General_Category L`. Before that intersection existed the class
313
- // admitted 1831 non-letter code points, so the documented policy ("digits,
314
- // hyphens, dots, symbols are removed") held for ASCII input only — a federated
315
- // actor could keep Arabic-Indic digits, a Bengali currency sign, or the U+061C
316
- // bidi control in their display name. This block is the regression guard.
317
- describe('display-name allowlist admits ONLY letters', () => {
318
- const allowed = new RegExp(`[${DISPLAY_NAME_ALLOWED_SCRIPTS}]`, 'u');
319
- // Built from the same generated ranges the policy ships, so this assertion
320
- // stays property-escape-free and cannot drift from the runtime regex.
321
- const letter = new RegExp(`[${DISPLAY_NAME_LETTERS_RANGES}]`, 'u');
322
-
323
- // Scanning the FULL code-point space, not a sample: one leaked invisible
324
- // control is a spoofing vector, and a sample cannot prove its absence.
325
- const leaks: number[] = [];
326
- let admitted = 0;
327
- for (let cp = 0; cp <= 0x10ffff; cp++) {
328
- if (cp >= 0xd800 && cp <= 0xdfff) continue; // lone surrogates
329
- const ch = String.fromCodePoint(cp);
330
- if (!allowed.test(ch)) continue;
331
- admitted++;
332
- if (!letter.test(ch)) leaks.push(cp);
333
- }
334
-
335
- it('admits no non-letter code point anywhere in Unicode', () => {
336
- const named = leaks
337
- .slice(0, 16)
338
- .map((cp) => `U+${cp.toString(16).toUpperCase().padStart(4, '0')}`);
339
- expect({ count: leaks.length, sample: named }).toEqual({ count: 0, sample: [] });
340
- });
341
-
342
- // Vacuity floor: an allowlist that collapsed to (near) nothing would satisfy
343
- // the assertion above while silently rejecting every real name.
344
- it('still admits the expected bulk of letters', () => {
345
- expect(admitted).toBeGreaterThan(100_000);
346
- });
347
-
348
- it.each([
349
- ['٥', 'Arabic-Indic digit (scx=Arabic, GC=Nd)'],
350
- ['०', 'Devanagari digit (scx=Devanagari, GC=Nd)'],
351
- ['۞', 'Arabic ornament (scx=Arabic, GC=So)'],
352
- ['৳', 'Bengali rupee sign (scx=Bengali, GC=Sc)'],
353
- ['।', 'Devanagari danda (scx=Devanagari, GC=Po)'],
354
- ['،', 'Arabic comma (scx=Arabic, GC=Po)'],
355
- ['؜', 'ARABIC LETTER MARK - invisible bidi control (scx=Arabic, GC=Cf)'],
356
- ['᠎', 'MONGOLIAN VOWEL SEPARATOR - invisible (scx=Mongolian, GC=Cf)'],
357
- ])('rejects %p, a non-letter from an allowlisted script (%s)', (ch) => {
358
- expect(isValidDisplayName(ch)).toBe(false);
359
- });
360
-
361
- // The intersection narrows the allowlist, so every previously-accepted real
362
- // name must still pass — these are the ones whose scripts own the code
363
- // points removed above.
364
- it.each([
365
- ['مُحَمَد', 'Arabic letters + harakat survive'],
366
- ['नमस्ते', 'Devanagari'],
367
- ['ᠰᠣᠩᠭᠣᠯ', 'Mongolian'],
368
- ['বাংলা', 'Bengali'],
369
- ])('still accepts %p (%s)', (name) => {
370
- expect(isValidDisplayName(name)).toBe(true);
371
- });
372
- });
373
-
374
- // A character policy classifies FORM, never MEANING. `卐` U+5350 and `卍`
375
- // U+534D are CJK Unified Ideographs (GC=Lo, scx=Han) — to Unicode they are the
376
- // same kind of thing as `山` in `山田太郎`, so no script- or category-level rule
377
- // can reject them without also rejecting every real Chinese, Japanese and
378
- // Korean name. They are therefore subtracted from the allowlist by an explicit
379
- // code-point denylist at generation time. This block is the regression guard,
380
- // and asserts the division of labour: the denylist covers ONLY what the
381
- // intersection cannot.
382
- describe('display-name denylist — letters that function as symbols', () => {
383
- // The glyphs below are visually confusable with each other and with ordinary
384
- // ideographs, so pin them to their code points before relying on them.
385
- it('the fixtures below really are U+5350 and U+534D', () => {
386
- expect('卐'.codePointAt(0)).toBe(0x5350);
387
- expect('卍'.codePointAt(0)).toBe(0x534d);
388
- });
389
-
390
- it.each([
391
- ['卐', 'U+5350 right-facing swastika (GC=Lo, scx=Han)'],
392
- ['卍', 'U+534D left-facing swastika (GC=Lo, scx=Han)'],
393
- ['卐 Glowniggers 卐', 'the production display name that motivated the denylist'],
394
- ['卍 卐', 'both, alone'],
395
- ['山田卍太郎', 'embedded mid-name, between real Han letters'],
396
- ])('rejects %p (%s)', (name) => {
397
- expect(isValidDisplayName(name)).toBe(false);
398
- });
399
-
400
- // The whole point of a per-code-point denylist instead of a script rule.
401
- it.each([
402
- ['山田太郎', 'Han (Japanese)'],
403
- ['김철수', 'Hangul (Korean)'],
404
- ['王小明', 'Han (Chinese)'],
405
- ['田中\u{20000}', 'Han incl. astral CJK Extension B'],
406
- // The four immediate neighbours of the denied pair: the subtraction must
407
- // punch out exactly two code points, not a range around them.
408
- ['卌', 'U+534C, immediately below U+534D'],
409
- ['华', 'U+534E, immediately above U+534D (as in 中华)'],
410
- ['协', 'U+534F, immediately below U+5350'],
411
- ['卑', 'U+5351, immediately above U+5350'],
412
- ])('still accepts %p (%s)', (name) => {
413
- expect(isValidDisplayName(name)).toBe(true);
414
- });
415
-
416
- // Enumerate what is ACTUALLY denied from the generated class rather than
417
- // trusting the literals above, so a future entry that is added to the list
418
- // but not enforced by the emitted allowlist fails here.
419
- const denied = new RegExp(`[${DISPLAY_NAME_DENIED_SYMBOL_LETTERS_RANGES}]`, 'u');
420
- const deniedCodePoints: number[] = [];
421
- for (let cp = 0; cp <= 0x10ffff; cp++) {
422
- if (cp >= 0xd800 && cp <= 0xdfff) continue; // lone surrogates
423
- if (denied.test(String.fromCodePoint(cp))) deniedCodePoints.push(cp);
424
- }
425
-
426
- it('denies exactly the two swastika ideographs', () => {
427
- expect(deniedCodePoints).toEqual([0x534d, 0x5350]);
428
- });
429
-
430
- it('rejects every code point on the denylist', () => {
431
- const accepted = deniedCodePoints.filter((cp) =>
432
- isValidDisplayName(String.fromCodePoint(cp))
433
- );
434
- expect(
435
- accepted.map((cp) => `U+${cp.toString(16).toUpperCase().padStart(4, '0')}`)
436
- ).toEqual([]);
437
- // Vacuity floor: an empty denylist would satisfy the assertion above while
438
- // enforcing nothing.
439
- expect(deniedCodePoints.length).toBeGreaterThanOrEqual(2);
440
- });
441
-
442
- // Hermes safety for the new class (see the property-escape block above).
443
- it('the denylist ranges contain NO Unicode property escape', () => {
444
- expect(/\\[pP]\{/.test(DISPLAY_NAME_DENIED_SYMBOL_LETTERS_RANGES)).toBe(false);
445
- expect(() => new RegExp(`[${DISPLAY_NAME_DENIED_SYMBOL_LETTERS_RANGES}]`, 'u')).not.toThrow();
446
- });
447
-
448
- // Division of labour: the Tibetan svasti signs look like the entries above
449
- // but are GC=So, so the `scripts ∩ General_Category L` intersection already
450
- // excludes them. They are rejected — and deliberately NOT on the denylist,
451
- // where they would be dead weight that reads as load-bearing. The generator
452
- // fails the build if such a redundant entry is added.
453
- it.each([
454
- ['࿕', 'U+0FD5 RIGHT-FACING SVASTI SIGN'],
455
- ['࿖', 'U+0FD6 LEFT-FACING SVASTI SIGN'],
456
- ['࿗', 'U+0FD7 RIGHT-FACING SVASTI SIGN WITH DOTS'],
457
- ['࿘', 'U+0FD8 LEFT-FACING SVASTI SIGN WITH DOTS'],
458
- ])('rejects %p (%s) via the intersection, not the denylist', (ch) => {
459
- expect(isValidDisplayName(ch)).toBe(false);
460
- expect(denied.test(ch)).toBe(false);
461
- });
462
- });
463
-
464
- // Four punctuation code points JOIN two letters inside one real name. All are
465
- // General_Category P, so `scripts ∩ L` strips them by default and stripping
466
- // SPLITS the name (`Codeur·euses` → `Codeur euses`). They are re-admitted, but
467
- // ONLY between two letters — the same characters are also used as ornament
468
- // (a trailing `Roberto ·`), which must keep being trimmed. The conditional is
469
- // the whole rule, so it is tested from both sides.
470
- describe('display-name name separators — allowed only between letters', () => {
471
- // Visually confusable with each other and with ASCII punctuation.
472
- it('the fixtures below really are U+00B7 U+05BE U+0F0B U+30FB', () => {
473
- expect('·'.codePointAt(0)).toBe(0x00b7);
474
- expect('־'.codePointAt(0)).toBe(0x05be);
475
- expect('་'.codePointAt(0)).toBe(0x0f0b);
476
- expect('・'.codePointAt(0)).toBe(0x30fb);
477
- });
478
-
479
- it.each([
480
- ['Codeur·euses en Liberté', 'U+00B7 French inclusive writing (production value)'],
481
- ['Codeur·euses', 'U+00B7 bare'],
482
- ['Pouet·te', 'U+00B7 short form'],
483
- ['お坐・エガード', 'U+30FB Japanese name separator (production value)'],
484
- ['אייר אברמסקי־קרוננברג', 'U+05BE Hebrew maqaf compound surname (production value)'],
485
- ['འོད་ཟེར', 'U+0F0B Tibetan intersyllabic tsheg (production value)'],
486
- ])('accepts letter-flanked %p (%s)', (name) => {
487
- expect(isValidDisplayName(name)).toBe(true);
488
- });
489
-
490
- // A base letter can carry a combining mark, and that mark sits between the
491
- // letter and the separator. If the flanking test only looked for a letter,
492
- // these would be misread as unflanked and the separator stripped. Both
493
- // fixtures use marks that do NOT recompose under NFC, so the mark really
494
- // reaches the flanking test instead of being folded into a precomposed
495
- // letter — the Tibetan one is the ordinary shape of Tibetan text.
496
- it.each([
497
- ['ཀི་ཁ', 'Tibetan letter + vowel sign U+0F72 + tsheg + letter'],
498
- ['مُ·م', 'Arabic letter + damma U+064F + middle dot + letter'],
499
- ])('accepts %p where a combining mark precedes the separator (%s)', (name) => {
500
- expect(isValidDisplayName(name)).toBe(true);
501
- });
502
-
503
- it.each([
504
- ['Roberto ·', 'trailing ornament (production value)'],
505
- ['Michał rysiek Woźniak ·', 'trailing ornament (production value)'],
506
- ['·Roberto', 'leading'],
507
- ['a··b', 'doubled — neither is letter-flanked on both sides'],
508
- ['·', 'alone'],
509
- ['お坐・', 'trailing katakana middle dot'],
510
- ['・エガード', 'leading katakana middle dot'],
511
- ['a ·b', 'space on the left'],
512
- ['a· b', 'space on the right'],
513
- ])('rejects unflanked %p (%s)', (name) => {
514
- expect(isValidDisplayName(name)).toBe(false);
515
- });
516
-
517
- // Enumerate what is ACTUALLY admitted from the generated class rather than
518
- // trusting the literals above, and exercise both sides of the rule for each.
519
- const separator = new RegExp(`[${DISPLAY_NAME_NAME_SEPARATORS_RANGES}]`, 'u');
520
- const separatorCodePoints: number[] = [];
521
- for (let cp = 0; cp <= 0x10ffff; cp++) {
522
- if (cp >= 0xd800 && cp <= 0xdfff) continue; // lone surrogates
523
- if (separator.test(String.fromCodePoint(cp))) separatorCodePoints.push(cp);
524
- }
525
-
526
- it('admits exactly the four name separators', () => {
527
- expect(separatorCodePoints).toEqual([0x00b7, 0x05be, 0x0f0b, 0x30fb]);
528
- });
529
-
530
- it('every separator is valid between letters and invalid unflanked', () => {
531
- const wrongWhenFlanked: string[] = [];
532
- const wrongWhenUnflanked: string[] = [];
533
- for (const cp of separatorCodePoints) {
534
- const ch = String.fromCodePoint(cp);
535
- const label = `U+${cp.toString(16).toUpperCase().padStart(4, '0')}`;
536
- if (!isValidDisplayName(`a${ch}b`)) wrongWhenFlanked.push(label);
537
- if (isValidDisplayName(`a ${ch}`)) wrongWhenUnflanked.push(label);
538
- }
539
- expect({ wrongWhenFlanked, wrongWhenUnflanked }).toEqual({
540
- wrongWhenFlanked: [],
541
- wrongWhenUnflanked: [],
542
- });
543
- // Vacuity floor: an empty separator class would satisfy both loops above.
544
- expect(separatorCodePoints.length).toBe(4);
545
- });
546
-
547
- // The ASCII hyphen decision is untouched: U+05BE is General_Category Pd like
548
- // U+002D, but admitting one says nothing about the other.
549
- it('does not admit the ASCII hyphen', () => {
550
- expect(separator.test('-')).toBe(false);
551
- expect(isValidDisplayName('Jean-Luc')).toBe(false);
552
- expect(isValidDisplayName('a-b')).toBe(false);
553
- });
554
-
555
- // Hermes safety for the new pattern (see the property-escape block above).
556
- it('the unflanked-separator source contains NO Unicode property escape', () => {
557
- expect(/\\[pP]\{/.test(DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE)).toBe(false);
558
- expect(/\\[pP]\{/.test(DISPLAY_NAME_NAME_SEPARATORS_RANGES)).toBe(false);
559
- expect(() => new RegExp(DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE, 'u')).not.toThrow();
560
- // Global variant is what @oxy.so/api compiles for the strip path.
561
- expect(() => new RegExp(DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE, 'gu')).not.toThrow();
562
- });
563
-
564
- // Nothing the policy already rejected may become valid.
565
- it.each([
566
- ['卐', 'denied symbol letter'],
567
- ['卍', 'denied symbol letter'],
568
- ['Agent007', 'digit'],
569
- ['J.R.', 'dot'],
570
- ['ᯅ', 'non-allowlisted script'],
571
- ['nixCraft \u{1f427}', 'emoji'],
572
- ])('still rejects %p (%s)', (name) => {
573
- expect(isValidDisplayName(name)).toBe(false);
574
- });
575
-
576
- it.each([
577
- ['山田太郎', 'Han'],
578
- ['김철수', 'Hangul'],
579
- ["Renée O'Brien", 'Latin with accent + apostrophe'],
580
- ])('still accepts %p (%s)', (name) => {
581
- expect(isValidDisplayName(name)).toBe(true);
582
- });
583
- });
584
-
585
- describe('isValidUUID', () => {
586
- it('should return true for valid UUIDs', () => {
587
- expect(isValidUUID('123e4567-e89b-12d3-a456-426614174000')).toBe(true);
588
- expect(isValidUUID('550e8400-e29b-41d4-a716-446655440000')).toBe(true);
589
- });
590
-
591
- /**
592
- * The version this ecosystem MINTS. `@oxy.so/db`'s `generatedId()` produces a
593
- * uuid v7, so every Postgres primary key since the 2026-07-31 cutover is
594
- * one — and the old `[1-5]` version class answered `false` for all of them.
595
- * The suite could not see it: both samples above are v1 and v4.
596
- */
597
- it('accepts a uuid v7 — the version generatedId() produces', () => {
598
- expect(isValidUUID('01a0821e-d61a-7a78-b5d1-afb1850bd5a4')).toBe(true);
599
- expect(isValidUUID('0197c8f2-1e40-7c9e-8b3a-2f5d6c1a9e04')).toBe(true);
600
- });
601
-
602
- it('should return false for invalid UUIDs', () => {
603
- expect(isValidUUID('invalid-uuid')).toBe(false);
604
- expect(isValidUUID('123-456-789')).toBe(false);
605
- expect(isValidUUID('')).toBe(false);
606
- });
607
-
608
- // A format check, not an identifier check: version 0 and the wrong variant
609
- // are still malformed, and widening the version class must not blur that.
610
- it('still rejects a zero version nibble and a bad variant', () => {
611
- expect(isValidUUID('01a0821e-d61a-0a78-b5d1-afb1850bd5a4')).toBe(false);
612
- expect(isValidUUID('01a0821e-d61a-7a78-c5d1-afb1850bd5a4')).toBe(false);
613
- });
614
- });
615
-
616
- describe('isValidDate', () => {
617
- it('should return true for valid date strings', () => {
618
- expect(isValidDate('2024-01-01')).toBe(true);
619
- expect(isValidDate('2024-12-31T23:59:59.999Z')).toBe(true);
620
- expect(isValidDate('January 1, 2024')).toBe(true);
621
- });
622
-
623
- it('should return false for invalid date strings', () => {
624
- expect(isValidDate('invalid-date')).toBe(false);
625
- expect(isValidDate('2024-13-01')).toBe(false); // invalid month
626
- expect(isValidDate('')).toBe(false);
627
- });
628
- });
629
-
630
- describe('isValidFileSize', () => {
631
- const maxSize = 1024 * 1024; // 1MB
632
-
633
- it('should return true for valid file sizes', () => {
634
- expect(isValidFileSize(1024, maxSize)).toBe(true);
635
- expect(isValidFileSize(maxSize, maxSize)).toBe(true);
636
- expect(isValidFileSize(1, maxSize)).toBe(true);
637
- });
638
-
639
- it('should return false for invalid file sizes', () => {
640
- expect(isValidFileSize(0, maxSize)).toBe(false);
641
- expect(isValidFileSize(-1, maxSize)).toBe(false);
642
- expect(isValidFileSize(maxSize + 1, maxSize)).toBe(false);
643
- });
644
- });
645
-
646
- describe('isValidFileType', () => {
647
- const allowedTypes = ['jpg', 'png', 'gif', 'pdf'];
648
-
649
- it('should return true for allowed file types', () => {
650
- expect(isValidFileType('image.jpg', allowedTypes)).toBe(true);
651
- expect(isValidFileType('document.PDF', allowedTypes)).toBe(true); // case insensitive
652
- expect(isValidFileType('photo.png', allowedTypes)).toBe(true);
653
- });
654
-
655
- it('should return false for disallowed file types', () => {
656
- expect(isValidFileType('script.js', allowedTypes)).toBe(false);
657
- expect(isValidFileType('data.txt', allowedTypes)).toBe(false);
658
- expect(isValidFileType('noextension', allowedTypes)).toBe(false);
659
- });
660
- });
661
-
662
- describe('sanitizeString', () => {
663
- it('should trim whitespace and remove dangerous characters', () => {
664
- expect(sanitizeString(' hello ')).toBe('hello');
665
- expect(sanitizeString('hello<script>alert("xss")</script>world')).toBe('helloalert("xss")world');
666
- expect(sanitizeString('normal text')).toBe('normal text');
667
- });
668
- });
669
-
670
- describe('sanitizeHTML', () => {
671
- it('should escape HTML characters', () => {
672
- expect(sanitizeHTML('<script>alert("xss")</script>')).toBe('&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;');
673
- expect(sanitizeHTML('Hello & Goodbye')).toBe('Hello &amp; Goodbye');
674
- expect(sanitizeHTML("It's a test")).toBe('It&#x27;s a test');
675
- });
676
- });
677
-
678
- describe('validateAndSanitizeUserInput', () => {
679
- it('should validate and sanitize email input', () => {
680
- expect(validateAndSanitizeUserInput(' test@example.com ', 'email')).toBe('test@example.com');
681
- expect(validateAndSanitizeUserInput('invalid-email', 'email')).toBeNull();
682
- expect(validateAndSanitizeUserInput(123, 'email')).toBeNull();
683
- });
684
-
685
- it('should validate and sanitize username input', () => {
686
- expect(validateAndSanitizeUserInput(' testuser ', 'username')).toBe('testuser');
687
- expect(validateAndSanitizeUserInput('ab', 'username')).toBeNull(); // too short
688
- expect(validateAndSanitizeUserInput(123, 'username')).toBeNull();
689
- // Answers from the one policy in `@oxy.so/contracts`, not from a rule of its
690
- // own: a dot and an edge separator are rejected here because they are
691
- // rejected there.
692
- expect(validateAndSanitizeUserInput('my-bot', 'username')).toBe('my-bot');
693
- expect(validateAndSanitizeUserInput('my.bot', 'username')).toBeNull();
694
- expect(validateAndSanitizeUserInput('-mybot', 'username')).toBeNull();
695
- });
696
-
697
- it('should validate and sanitize string input', () => {
698
- expect(validateAndSanitizeUserInput(' hello world ', 'string')).toBe('hello world');
699
- expect(validateAndSanitizeUserInput('', 'string')).toBeNull();
700
- expect(validateAndSanitizeUserInput(123, 'string')).toBeNull();
701
- });
702
- });
703
- });