@oxy.so/core 4.5.0-oxy-one.0 → 4.5.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 (285) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/HttpService.js +63 -19
  3. package/dist/cjs/api/accounts.js +10 -3
  4. package/dist/cjs/api/agency.js +3 -1
  5. package/dist/cjs/api/apps.js +15 -4
  6. package/dist/cjs/api/assets.js +49 -12
  7. package/dist/cjs/api/auth.js +37 -11
  8. package/dist/cjs/api/billing.js +24 -7
  9. package/dist/cjs/api/civic.js +14 -4
  10. package/dist/cjs/api/follows.js +9 -2
  11. package/dist/cjs/api/identity.js +31 -9
  12. package/dist/cjs/api/nodes.js +3 -1
  13. package/dist/cjs/api/privacy.js +8 -2
  14. package/dist/cjs/api/session.js +15 -4
  15. package/dist/cjs/api/store.js +15 -5
  16. package/dist/cjs/api/topics.js +10 -3
  17. package/dist/cjs/api/users.js +16 -4
  18. package/dist/cjs/boot/sessionColdBoot.js +40 -13
  19. package/dist/cjs/constants/version.js +6 -6
  20. package/dist/cjs/crypto/identityMarker.js +3 -1
  21. package/dist/cjs/crypto/identityProof.js +6 -1
  22. package/dist/cjs/crypto/keyManager.js +87 -32
  23. package/dist/cjs/crypto/recoveryPhrase.js +2 -2
  24. package/dist/cjs/crypto/signatureService.js +3 -4
  25. package/dist/cjs/i18n/index.js +16 -3
  26. package/dist/cjs/i18n/locales/ar-SA.js +366 -366
  27. package/dist/cjs/i18n/locales/ca-ES.js +366 -366
  28. package/dist/cjs/i18n/locales/de-DE.js +366 -366
  29. package/dist/cjs/i18n/locales/en-US.js +1994 -1994
  30. package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
  31. package/dist/cjs/i18n/locales/fr-FR.js +366 -366
  32. package/dist/cjs/i18n/locales/it-IT.js +366 -366
  33. package/dist/cjs/i18n/locales/ja-JP.js +366 -366
  34. package/dist/cjs/i18n/locales/ko-KR.js +366 -366
  35. package/dist/cjs/i18n/locales/pt-PT.js +366 -366
  36. package/dist/cjs/i18n/locales/zh-CN.js +366 -366
  37. package/dist/cjs/inference/OxyInferenceClient.js +12 -18
  38. package/dist/cjs/models/interfaces.js +11 -11
  39. package/dist/cjs/server/OxyServer.js +86 -28
  40. package/dist/cjs/server/agentAccount.js +6 -2
  41. package/dist/cjs/server/aliaMachineCredential.js +39 -14
  42. package/dist/cjs/server/auth.js +5 -4
  43. package/dist/cjs/server/capabilityTicket.js +5 -5
  44. package/dist/cjs/server/index.js +2 -1
  45. package/dist/cjs/server/liveCapabilityTicket.js +4 -1
  46. package/dist/cjs/server/middleware.js +61 -42
  47. package/dist/cjs/server/namespaces.js +28 -7
  48. package/dist/cjs/server/requesterAssertion.js +36 -30
  49. package/dist/cjs/server/serviceTokenLifetime.js +7 -4
  50. package/dist/cjs/server/traffic.js +53 -14
  51. package/dist/cjs/server/trafficNodeHttp.js +33 -8
  52. package/dist/cjs/server/workloadIdentity.client.js +4 -0
  53. package/dist/cjs/server/workloadIdentity.js +28 -1
  54. package/dist/cjs/session/SessionClient.js +54 -17
  55. package/dist/cjs/session/accountDelegationAccess.js +4 -6
  56. package/dist/cjs/session/accountDialogController.js +1 -1
  57. package/dist/cjs/session/authStateStore.js +18 -9
  58. package/dist/cjs/session/identityPin.js +6 -2
  59. package/dist/cjs/session/refresh.js +81 -23
  60. package/dist/cjs/session/sharedDeviceCredential.js +28 -15
  61. package/dist/cjs/shared/utils/errorUtils.js +1 -1
  62. package/dist/cjs/shared/utils/networkUtils.js +1 -1
  63. package/dist/cjs/shared/utils/themeUtils.js +1 -1
  64. package/dist/cjs/utils/accountCacheSweep.js +3 -1
  65. package/dist/cjs/utils/accountUtils.js +1 -3
  66. package/dist/cjs/utils/asyncUtils.js +1 -1
  67. package/dist/cjs/utils/authHelpers.js +2 -1
  68. package/dist/cjs/utils/avatarUtils.js +4 -2
  69. package/dist/cjs/utils/cache.js +1 -1
  70. package/dist/cjs/utils/cacheKey.js +3 -1
  71. package/dist/cjs/utils/deviceManager.js +4 -4
  72. package/dist/cjs/utils/errorUtils.js +6 -4
  73. package/dist/cjs/utils/languageUtils.js +404 -57
  74. package/dist/cjs/utils/profileLinks.js +1 -3
  75. package/dist/cjs/utils/requestUtils.js +7 -1
  76. package/dist/cjs/utils/userIdentity.js +1 -1
  77. package/dist/cjs/utils/validationUtils.js +5 -6
  78. package/dist/esm/HttpService.js +64 -20
  79. package/dist/esm/api/accounts.js +11 -4
  80. package/dist/esm/api/agency.js +3 -1
  81. package/dist/esm/api/apps.js +15 -4
  82. package/dist/esm/api/assets.js +49 -12
  83. package/dist/esm/api/auth.js +37 -11
  84. package/dist/esm/api/billing.js +25 -8
  85. package/dist/esm/api/civic.js +14 -4
  86. package/dist/esm/api/follows.js +9 -2
  87. package/dist/esm/api/identity.js +31 -9
  88. package/dist/esm/api/nodes.js +3 -1
  89. package/dist/esm/api/privacy.js +8 -2
  90. package/dist/esm/api/session.js +15 -4
  91. package/dist/esm/api/store.js +15 -5
  92. package/dist/esm/api/topics.js +10 -3
  93. package/dist/esm/api/users.js +16 -4
  94. package/dist/esm/boot/sessionColdBoot.js +41 -14
  95. package/dist/esm/constants/version.js +6 -6
  96. package/dist/esm/crypto/identityMarker.js +3 -1
  97. package/dist/esm/crypto/identityProof.js +6 -1
  98. package/dist/esm/crypto/internal.js +1 -1
  99. package/dist/esm/crypto/keyManager.js +87 -32
  100. package/dist/esm/crypto/recoveryPhrase.js +2 -2
  101. package/dist/esm/crypto/signatureService.js +3 -4
  102. package/dist/esm/i18n/index.js +16 -3
  103. package/dist/esm/i18n/locales/ar-SA.js +366 -366
  104. package/dist/esm/i18n/locales/ca-ES.js +366 -366
  105. package/dist/esm/i18n/locales/de-DE.js +366 -366
  106. package/dist/esm/i18n/locales/en-US.js +1994 -1994
  107. package/dist/esm/i18n/locales/es-ES.js +1994 -1994
  108. package/dist/esm/i18n/locales/fr-FR.js +366 -366
  109. package/dist/esm/i18n/locales/it-IT.js +366 -366
  110. package/dist/esm/i18n/locales/ja-JP.js +366 -366
  111. package/dist/esm/i18n/locales/ko-KR.js +366 -366
  112. package/dist/esm/i18n/locales/pt-PT.js +366 -366
  113. package/dist/esm/i18n/locales/zh-CN.js +366 -366
  114. package/dist/esm/index.js +1 -1
  115. package/dist/esm/inference/OxyInferenceClient.js +13 -19
  116. package/dist/esm/models/interfaces.js +11 -11
  117. package/dist/esm/server/OxyServer.js +87 -29
  118. package/dist/esm/server/agentAccount.js +6 -2
  119. package/dist/esm/server/aliaMachineCredential.js +39 -14
  120. package/dist/esm/server/auth.js +6 -5
  121. package/dist/esm/server/capabilityTicket.js +6 -6
  122. package/dist/esm/server/index.js +5 -5
  123. package/dist/esm/server/liveCapabilityTicket.js +6 -3
  124. package/dist/esm/server/middleware.js +62 -43
  125. package/dist/esm/server/namespaces.js +31 -10
  126. package/dist/esm/server/requesterAssertion.js +36 -30
  127. package/dist/esm/server/serviceTokenLifetime.js +7 -4
  128. package/dist/esm/server/traffic.js +55 -16
  129. package/dist/esm/server/trafficNodeHttp.js +34 -9
  130. package/dist/esm/server/userInvalidation.js +1 -1
  131. package/dist/esm/server/workloadIdentity.client.js +3 -0
  132. package/dist/esm/server/workloadIdentity.js +27 -1
  133. package/dist/esm/session/SessionClient.js +54 -17
  134. package/dist/esm/session/accountDelegationAccess.js +5 -7
  135. package/dist/esm/session/accountDialogController.js +1 -1
  136. package/dist/esm/session/authStateStore.js +18 -9
  137. package/dist/esm/session/identityPin.js +6 -2
  138. package/dist/esm/session/refresh.js +82 -24
  139. package/dist/esm/session/sharedDeviceCredential.js +28 -15
  140. package/dist/esm/shared/utils/errorUtils.js +1 -1
  141. package/dist/esm/shared/utils/networkUtils.js +1 -1
  142. package/dist/esm/shared/utils/themeUtils.js +1 -1
  143. package/dist/esm/utils/accountCacheSweep.js +3 -1
  144. package/dist/esm/utils/accountUtils.js +1 -3
  145. package/dist/esm/utils/asyncUtils.js +1 -1
  146. package/dist/esm/utils/authHelpers.js +2 -1
  147. package/dist/esm/utils/avatarUtils.js +4 -2
  148. package/dist/esm/utils/cache.js +1 -1
  149. package/dist/esm/utils/cacheKey.js +3 -1
  150. package/dist/esm/utils/deviceManager.js +4 -4
  151. package/dist/esm/utils/errorUtils.js +6 -4
  152. package/dist/esm/utils/languageUtils.js +404 -57
  153. package/dist/esm/utils/profileLinks.js +1 -3
  154. package/dist/esm/utils/requestUtils.js +7 -1
  155. package/dist/esm/utils/userIdentity.js +1 -1
  156. package/dist/esm/utils/validationUtils.js +5 -6
  157. package/dist/types/HttpService.d.ts +1 -1
  158. package/dist/types/api/accounts.d.ts +1 -1
  159. package/dist/types/api/apps.d.ts +4 -4
  160. package/dist/types/api/assets.d.ts +2 -0
  161. package/dist/types/api/auth.d.ts +8 -3
  162. package/dist/types/crypto/internal.d.ts +1 -1
  163. package/dist/types/index.d.ts +4 -4
  164. package/dist/types/server/index.d.ts +6 -6
  165. package/dist/types/server/requesterAssertion.d.ts +2 -2
  166. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  167. package/dist/types/server/workloadIdentity.d.ts +26 -0
  168. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  169. package/dist/types/session/index.d.ts +1 -1
  170. package/dist/types/utils/userIdentity.d.ts +1 -1
  171. package/dist/types/utils/validationUtils.d.ts +4 -5
  172. package/package.json +2 -3
  173. package/src/HttpService.ts +183 -53
  174. package/src/OxyServices.errors.ts +7 -3
  175. package/src/OxyServices.ts +6 -2
  176. package/src/api/accounts.ts +76 -26
  177. package/src/api/agency.ts +24 -9
  178. package/src/api/appData.ts +12 -2
  179. package/src/api/apps.ts +81 -31
  180. package/src/api/assets.ts +122 -40
  181. package/src/api/auth.ts +154 -79
  182. package/src/api/billing.ts +112 -65
  183. package/src/api/civic.ts +61 -19
  184. package/src/api/contacts.ts +4 -1
  185. package/src/api/devices.ts +54 -21
  186. package/src/api/follows.ts +88 -31
  187. package/src/api/identity.ts +101 -33
  188. package/src/api/linkedAccounts.ts +26 -8
  189. package/src/api/nodes.ts +18 -6
  190. package/src/api/notifications.ts +26 -6
  191. package/src/api/privacy.ts +42 -8
  192. package/src/api/reputation.ts +18 -7
  193. package/src/api/session.ts +23 -5
  194. package/src/api/store.ts +81 -31
  195. package/src/api/topics.ts +18 -6
  196. package/src/api/users.ts +98 -35
  197. package/src/boot/sessionColdBoot.ts +60 -19
  198. package/src/civic/payloads.ts +1 -4
  199. package/src/client/context.ts +6 -1
  200. package/src/constants/version.ts +7 -6
  201. package/src/crypto/aead.ts +1 -5
  202. package/src/crypto/ecdh.ts +1 -4
  203. package/src/crypto/identityDerivations.ts +5 -1
  204. package/src/crypto/identityMarker.ts +3 -1
  205. package/src/crypto/identityProof.ts +6 -1
  206. package/src/crypto/index.ts +11 -11
  207. package/src/crypto/internal.ts +6 -1
  208. package/src/crypto/keyManager.ts +348 -98
  209. package/src/crypto/recoveryPhrase.ts +14 -9
  210. package/src/crypto/registrationPow.ts +1 -1
  211. package/src/crypto/signatureService.ts +14 -6
  212. package/src/i18n/accountCategoryLabels.ts +1 -4
  213. package/src/i18n/accountRoleLabels.ts +1 -4
  214. package/src/i18n/index.ts +25 -7
  215. package/src/i18n/locales/ar-SA.ts +375 -366
  216. package/src/i18n/locales/ca-ES.ts +382 -366
  217. package/src/i18n/locales/de-DE.ts +387 -366
  218. package/src/i18n/locales/en-US.ts +2034 -1994
  219. package/src/i18n/locales/es-ES.ts +2043 -1994
  220. package/src/i18n/locales/fr-FR.ts +387 -366
  221. package/src/i18n/locales/it-IT.ts +380 -366
  222. package/src/i18n/locales/ja-JP.ts +380 -366
  223. package/src/i18n/locales/ko-KR.ts +377 -366
  224. package/src/i18n/locales/pt-PT.ts +383 -366
  225. package/src/i18n/locales/zh-CN.ts +373 -366
  226. package/src/i18n/trustTierLabels.ts +1 -4
  227. package/src/index.ts +371 -349
  228. package/src/inference/OxyInferenceClient.ts +784 -780
  229. package/src/models/interfaces.ts +30 -27
  230. package/src/server/OxyServer.ts +227 -68
  231. package/src/server/agentAccount.ts +8 -2
  232. package/src/server/aliaMachineCredential.ts +57 -16
  233. package/src/server/auth.ts +9 -5
  234. package/src/server/capabilityTicket.ts +30 -21
  235. package/src/server/index.ts +29 -6
  236. package/src/server/liveCapabilityTicket.ts +31 -9
  237. package/src/server/middleware.ts +212 -121
  238. package/src/server/namespaces.ts +247 -94
  239. package/src/server/rateLimit.ts +2 -4
  240. package/src/server/requesterAssertion.ts +93 -54
  241. package/src/server/serviceTokenLifetime.ts +9 -4
  242. package/src/server/traffic.ts +117 -23
  243. package/src/server/trafficNodeHttp.ts +61 -14
  244. package/src/server/userInvalidation.ts +1 -4
  245. package/src/server/workloadIdentity.client.ts +12 -1
  246. package/src/server/workloadIdentity.ts +52 -5
  247. package/src/session/SessionClient.ts +170 -49
  248. package/src/session/accountDelegationAccess.ts +24 -31
  249. package/src/session/accountDialogController.ts +59 -14
  250. package/src/session/accountSwitchTargets.ts +10 -15
  251. package/src/session/authStateStore.ts +121 -81
  252. package/src/session/deviceDirectory.ts +1 -3
  253. package/src/session/identityPin.ts +10 -11
  254. package/src/session/identitySession.ts +3 -1
  255. package/src/session/index.ts +87 -82
  256. package/src/session/refresh.ts +138 -44
  257. package/src/session/sessionClientHost.ts +1 -3
  258. package/src/session/sharedDeviceCredential.ts +35 -14
  259. package/src/session/socketLoader.ts +9 -2
  260. package/src/shared/utils/errorUtils.ts +5 -2
  261. package/src/shared/utils/networkUtils.ts +5 -8
  262. package/src/shared/utils/themeUtils.ts +2 -6
  263. package/src/types/buffer.d.ts +66 -21
  264. package/src/types/expo-secure-store.d.ts +5 -1
  265. package/src/utils/accountCacheSweep.ts +4 -5
  266. package/src/utils/accountUtils.ts +107 -108
  267. package/src/utils/apiUtils.ts +3 -3
  268. package/src/utils/asyncUtils.ts +2 -2
  269. package/src/utils/authHelpers.ts +10 -5
  270. package/src/utils/avatarUtils.ts +11 -6
  271. package/src/utils/cache.ts +9 -10
  272. package/src/utils/cacheKey.ts +5 -1
  273. package/src/utils/coldBoot.ts +1 -3
  274. package/src/utils/commonsDelivery.ts +1 -4
  275. package/src/utils/deviceManager.ts +15 -14
  276. package/src/utils/errorUtils.ts +68 -86
  277. package/src/utils/languageUtils.ts +407 -58
  278. package/src/utils/oauthPkce.ts +1 -4
  279. package/src/utils/platform.ts +0 -1
  280. package/src/utils/profileLinks.ts +2 -5
  281. package/src/utils/requestUtils.ts +18 -14
  282. package/src/utils/sessionUtils.ts +34 -33
  283. package/src/utils/userHandle.ts +3 -1
  284. package/src/utils/userIdentity.ts +1 -1
  285. package/src/utils/validationUtils.ts +11 -9
package/README.md CHANGED
@@ -81,7 +81,7 @@ const url = buildOAuthAuthorizeUrl({
81
81
 
82
82
  ## User Identity And Handles
83
83
 
84
- SDK user payloads may arrive with either `id` or Mongo-style `_id`; normalize
84
+ SDK user payloads may arrive with either `id` or a raw `_id`; normalize
85
85
  them before exposing state to apps:
86
86
 
87
87
  ```ts
@@ -39,14 +39,25 @@ function sameTokenSession(left, right) {
39
39
  return false;
40
40
  // A refresh may rotate exp/iat/jti while preserving its account and session.
41
41
  // Opaque/malformed context fields cannot establish that equivalence.
42
- return ['userId', 'id', 'sub', 'sessionId', 'operatorId', 'clientId', 'appId', 'authMethodId'].every((key) => (a[key] === undefined || typeof a[key] === 'string') && a[key] === b[key]);
42
+ return [
43
+ 'userId',
44
+ 'id',
45
+ 'sub',
46
+ 'sessionId',
47
+ 'operatorId',
48
+ 'clientId',
49
+ 'appId',
50
+ 'authMethodId',
51
+ ].every((key) => (a[key] === undefined || typeof a[key] === 'string') && a[key] === b[key]);
43
52
  }
44
53
  /** Cancel this wait only; the shared mint continues for other callers. */
45
54
  function awaitRequestSignal(pending, signal) {
46
55
  if (!signal)
47
56
  return pending;
48
57
  return new Promise((resolve, reject) => {
49
- const onAbort = () => { reject((0, errorUtils_1.createCancelledError)()); };
58
+ const onAbort = () => {
59
+ reject((0, errorUtils_1.createCancelledError)());
60
+ };
50
61
  if (signal.aborted)
51
62
  onAbort();
52
63
  else
@@ -205,7 +216,9 @@ function isAbortLike(error) {
205
216
  function linkAbort(parent, child) {
206
217
  if (parent.aborted) {
207
218
  child.abort(parent.reason);
208
- return () => { };
219
+ return () => {
220
+ /* nothing was ever attached */
221
+ };
209
222
  }
210
223
  const onAbort = () => {
211
224
  child.abort(parent.reason);
@@ -317,8 +330,7 @@ class HttpService {
317
330
  // the cache for the global cleanup interval. Default (config unset) keeps
318
331
  // caching ON with the 5-minute TTL — unchanged for existing consumers.
319
332
  this.cacheDisabled =
320
- config.enableCache === false ||
321
- (typeof config.cacheTTL === 'number' && config.cacheTTL <= 0);
333
+ config.enableCache === false || (typeof config.cacheTTL === 'number' && config.cacheTTL <= 0);
322
334
  this.cache = new cache_1.TTLCache(config.cacheTTL && config.cacheTTL > 0 ? config.cacheTTL : 5 * 60 * 1000);
323
335
  if (!this.cacheDisabled) {
324
336
  (0, cache_1.registerCacheForCleanup)(this.cache);
@@ -494,7 +506,7 @@ class HttpService {
494
506
  const isUrlEncoded = this.isUrlSearchParams(data);
495
507
  // Build headers - start with defaults
496
508
  const headers = {
497
- 'Accept': 'application/json',
509
+ Accept: 'application/json',
498
510
  };
499
511
  // Only set Content-Type for non-FormData requests (FormData sets it automatically with boundary)
500
512
  if (isUrlEncoded) {
@@ -528,7 +540,11 @@ class HttpService {
528
540
  // `fetch` as-is: RN's fetch does not consistently encode it, and doing
529
541
  // it here keeps the body identical across every platform.
530
542
  const bodyValue = method !== 'GET' && data
531
- ? (isFormData ? data : isUrlEncoded ? data.toString() : JSON.stringify(data))
543
+ ? isFormData
544
+ ? data
545
+ : isUrlEncoded
546
+ ? data.toString()
547
+ : JSON.stringify(data)
532
548
  : undefined;
533
549
  // React Native FormData workaround:
534
550
  // Expo SDK 56's "winter fetch" rejects RN file descriptors `{uri, type, name}`
@@ -570,7 +586,13 @@ class HttpService {
570
586
  // queue slot, so a queued retry waits for a slot while holding one.
571
587
  // With every slot held by a 401 (a revoked session under load) no
572
588
  // retry could ever start and the whole client stalled.
573
- return this.request({ ...config, _isAuthRetry: true, retry: false, deduplicate: false, bypassQueue: true });
589
+ return this.request({
590
+ ...config,
591
+ _isAuthRetry: true,
592
+ retry: false,
593
+ deduplicate: false,
594
+ bypassQueue: true,
595
+ });
574
596
  }
575
597
  // Refresh failed or no token — clear tokens
576
598
  this.tokenStore.clearTokens();
@@ -597,7 +619,11 @@ class HttpService {
597
619
  const parsed = (0, errorUtils_1.parseHttpErrorBody)(errorBody);
598
620
  const error = new Error(parsed.message ?? `HTTP ${response.status}: ${response.statusText}`);
599
621
  error.status = response.status;
600
- error.response = { status: response.status, statusText: response.statusText, data: errorBody };
622
+ error.response = {
623
+ status: response.status,
624
+ statusText: response.statusText,
625
+ data: errorBody,
626
+ };
601
627
  // Only set `code`/`details` when the server actually sent them.
602
628
  // Assigning `undefined` would still create the property, which changes
603
629
  // how `handleHttpError` classifies the error downstream.
@@ -644,7 +670,11 @@ class HttpService {
644
670
  }
645
671
  }
646
672
  }
647
- else if (contentType && (contentType.includes('application/octet-stream') || contentType.includes('image/') || contentType.includes('video/') || contentType.includes('audio/'))) {
673
+ else if (contentType &&
674
+ (contentType.includes('application/octet-stream') ||
675
+ contentType.includes('image/') ||
676
+ contentType.includes('video/') ||
677
+ contentType.includes('audio/'))) {
648
678
  // For binary responses (blobs), return the blob directly without unwrapping
649
679
  responseData = await response.blob();
650
680
  }
@@ -710,7 +740,9 @@ class HttpService {
710
740
  // Control-plane calls the auth lane depends on (`bypassQueue`, e.g. the
711
741
  // device-secret mint) run DIRECTLY — a queued mint could never acquire a
712
742
  // slot when every slot is parked awaiting it.
713
- config.bypassQueue ? attempt(domain) : this.requestQueue.enqueue(() => attempt(domain), domain);
743
+ config.bypassQueue
744
+ ? attempt(domain)
745
+ : this.requestQueue.enqueue(() => attempt(domain), domain);
714
746
  const execute = (domain) => retry
715
747
  ? (0, asyncUtils_1.retryAsync)(() => runAttempt(domain), {
716
748
  maxRetries,
@@ -816,7 +848,9 @@ class HttpService {
816
848
  try {
817
849
  xhr.abort();
818
850
  }
819
- catch { /* xhr already finished */ }
851
+ catch {
852
+ /* xhr already finished */
853
+ }
820
854
  };
821
855
  if (abortSignal.aborted) {
822
856
  reject(new DOMException('The user aborted a request.', 'AbortError'));
@@ -1229,8 +1263,10 @@ class HttpService {
1229
1263
  // an auth mint, even when the trusted transport accepts absolute URLs.
1230
1264
  const target = new URL(this.buildURL(config.url));
1231
1265
  const base = new URL(this.baseURL);
1232
- if (target.origin !== base.origin || !['http:', 'https:'].includes(target.protocol)
1233
- || target.username || target.password) {
1266
+ if (target.origin !== base.origin ||
1267
+ !['http:', 'https:'].includes(target.protocol) ||
1268
+ target.username ||
1269
+ target.password) {
1234
1270
  throw new Error('Raw response requests must target the configured API origin');
1235
1271
  }
1236
1272
  if (config.signal?.aborted)
@@ -1240,7 +1276,8 @@ class HttpService {
1240
1276
  const contextToken = this.syncAccessTokenFromProvider();
1241
1277
  const beforeAuthEpoch = this.sessionEpoch;
1242
1278
  const authHeader = await awaitRequestSignal(this.getAuthHeader(), config.signal);
1243
- if (beforeAuthEpoch !== this.sessionEpoch || !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1279
+ if (beforeAuthEpoch !== this.sessionEpoch ||
1280
+ !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1244
1281
  throw new OxyServices_errors_1.OxyAuthenticationError('The request session changed', 'AUTH_SESSION_CHANGED');
1245
1282
  }
1246
1283
  if (config.signal?.aborted)
@@ -1253,7 +1290,8 @@ class HttpService {
1253
1290
  async requestResponseAttempt(config, fullUrl, authHeader, isAuthRetry, epoch, contextToken) {
1254
1291
  const assertCurrent = () => {
1255
1292
  this.syncAccessTokenFromProvider();
1256
- if (epoch !== this.sessionEpoch || !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1293
+ if (epoch !== this.sessionEpoch ||
1294
+ !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1257
1295
  throw new OxyServices_errors_1.OxyAuthenticationError('The request session changed', 'AUTH_SESSION_CHANGED');
1258
1296
  }
1259
1297
  };
@@ -1298,7 +1336,11 @@ class HttpService {
1298
1336
  throw error;
1299
1337
  }
1300
1338
  const replayable = body === undefined || typeof body === 'string';
1301
- if (response.status === 401 && !isAuthRetry && authHeader && replayable && !config.signal?.aborted) {
1339
+ if (response.status === 401 &&
1340
+ !isAuthRetry &&
1341
+ authHeader &&
1342
+ replayable &&
1343
+ !config.signal?.aborted) {
1302
1344
  let refreshed;
1303
1345
  try {
1304
1346
  refreshed = await awaitRequestSignal(this.refreshAccessToken('response-401'), config.signal);
@@ -1333,7 +1375,9 @@ class HttpService {
1333
1375
  this.config.onRequestEnd?.(config.url, config.method, duration, false);
1334
1376
  const normalizedError = config.signal?.aborted || (0, errorUtils_1.isCancelledError)(error)
1335
1377
  ? (0, errorUtils_1.createCancelledError)()
1336
- : error instanceof Error ? error : new Error(String(error));
1378
+ : error instanceof Error
1379
+ ? error
1380
+ : new Error(String(error));
1337
1381
  this.config.onRequestError?.(config.url, config.method, normalizedError);
1338
1382
  if ((0, errorUtils_1.isCancelledError)(normalizedError) || normalizedError instanceof OxyServices_errors_1.OxyAuthenticationError)
1339
1383
  throw normalizedError;
@@ -1505,7 +1549,7 @@ class HttpService {
1505
1549
  * per resource.
1506
1550
  * @returns Number of entries deleted
1507
1551
  */
1508
- invalidateCache({ keys = [], prefixes = [] }) {
1552
+ invalidateCache({ keys = [], prefixes = [], }) {
1509
1553
  if (keys.length === 0 && prefixes.length === 0)
1510
1554
  return 0;
1511
1555
  const exact = new Set(keys);
@@ -105,7 +105,9 @@ class AccountAgentKeysApi {
105
105
  this.ctx = ctx;
106
106
  }
107
107
  async list(accountId) {
108
- return contracts_1.agentKeyListResponseSchema.parse(await this.ctx.request('GET', `/accounts/${enc(accountId)}/agent-keys`, undefined, { cache: false }));
108
+ return contracts_1.agentKeyListResponseSchema.parse(await this.ctx.request('GET', `/accounts/${enc(accountId)}/agent-keys`, undefined, {
109
+ cache: false,
110
+ }));
109
111
  }
110
112
  async requestChallenge(accountId, operation) {
111
113
  const response = await this.ctx.request('POST', `/accounts/${enc(accountId)}/agent-keys/challenge`, contracts_1.agentKeyOperationSchema.parse(operation), { cache: false });
@@ -195,7 +197,9 @@ class AccountsApi {
195
197
  * @param data - Account configuration: kind, optional parent, and profile.
196
198
  */
197
199
  async create(data) {
198
- const res = await this.ctx.request('POST', '/accounts', data, { cache: false });
200
+ const res = await this.ctx.request('POST', '/accounts', data, {
201
+ cache: false,
202
+ });
199
203
  // A new account changes the accessible forest — bust every cached list.
200
204
  (0, accountCacheSweep_1.evictOxyAccountForestCache)(this.ctx.http);
201
205
  return res.account;
@@ -235,7 +239,10 @@ class AccountsApi {
235
239
  cache: false,
236
240
  });
237
241
  this.ctx.http.invalidateCache({
238
- keys: [`GET:/accounts/${enc(accountId)}/members`, `GET:/accounts/${enc(accountId)}/credentials`],
242
+ keys: [
243
+ `GET:/accounts/${enc(accountId)}/members`,
244
+ `GET:/accounts/${enc(accountId)}/credentials`,
245
+ ],
239
246
  });
240
247
  (0, accountCacheSweep_1.evictOxyAccountForestCache)(this.ctx.http, accountId);
241
248
  return result;
@@ -36,7 +36,9 @@ class DelegationGrantsApi {
36
36
  }
37
37
  /** Revoke a grant. */
38
38
  async revoke(grantId, ownerAccountId) {
39
- await this.ctx.request('DELETE', `/capabilities/grants/${enc(grantId)}`, undefined, { cache: false });
39
+ await this.ctx.request('DELETE', `/capabilities/grants/${enc(grantId)}`, undefined, {
40
+ cache: false,
41
+ });
40
42
  this.ctx.oxy.cache.delete(grantsKey(ownerAccountId));
41
43
  }
42
44
  }
@@ -72,7 +72,10 @@ class ConnectedAppsApi {
72
72
  * `GET /auth/grants`, briefly cached; `revoke` busts it.
73
73
  */
74
74
  async list() {
75
- return this.ctx.request('GET', '/auth/grants', undefined, { cache: true, cacheTTL: SHORT_TTL });
75
+ return this.ctx.request('GET', '/auth/grants', undefined, {
76
+ cache: true,
77
+ cacheTTL: SHORT_TTL,
78
+ });
76
79
  }
77
80
  /**
78
81
  * Revoke this user's grant for a connected application. After this the
@@ -94,7 +97,9 @@ class ConnectedAppsApi {
94
97
  }
95
98
  /** Revoke one external MCP connection and every token in its family. */
96
99
  async revokeMcpClient(grantId) {
97
- await this.ctx.request('DELETE', `/auth/mcp/oauth/grants/${enc(grantId)}`, undefined, { cache: false });
100
+ await this.ctx.request('DELETE', `/auth/mcp/oauth/grants/${enc(grantId)}`, undefined, {
101
+ cache: false,
102
+ });
98
103
  this.ctx.oxy.cache.delete('GET:/auth/mcp/oauth/grants');
99
104
  }
100
105
  }
@@ -154,7 +159,10 @@ class AppsApi {
154
159
  const result = await this.ctx.request('DELETE', appPath(applicationId), undefined, {
155
160
  cache: false,
156
161
  });
157
- this.invalidateLists([`GET:${appPath(applicationId)}`, `GET:${credentialsPath(applicationId)}`]);
162
+ this.invalidateLists([
163
+ `GET:${appPath(applicationId)}`,
164
+ `GET:${credentialsPath(applicationId)}`,
165
+ ]);
158
166
  return result;
159
167
  }
160
168
  /**
@@ -185,7 +193,10 @@ class AppsApi {
185
193
  * `GET:/applications/<id>…` detail keys.
186
194
  */
187
195
  invalidateLists(extraKeys = []) {
188
- this.ctx.http.invalidateCache({ keys: ['GET:/applications', ...extraKeys], prefixes: ['GET:/applications?'] });
196
+ this.ctx.http.invalidateCache({
197
+ keys: ['GET:/applications', ...extraKeys],
198
+ prefixes: ['GET:/applications?'],
199
+ });
189
200
  }
190
201
  }
191
202
  exports.AppsApi = AppsApi;
@@ -38,6 +38,12 @@ const ASSET_URL_CACHE_LIFETIME_FRACTION = 0.5;
38
38
  /** Assumed URL lifetime (seconds) when no `expiresIn` is asked for; the API default. */
39
39
  const DEFAULT_ASSET_URL_EXPIRES_IN_SECONDS = 3600;
40
40
  const ASSET_TTL = 5 * 60 * 1000;
41
+ /**
42
+ * Default bound on one `POST /assets/upload`, in ms. The client's per-request
43
+ * default (5s) is sized for JSON calls; a video sent over a phone connection
44
+ * needs minutes, and timing it out at 5s failed every upload past a few MB.
45
+ */
46
+ const ASSET_UPLOAD_TIMEOUT_MS = 10 * 60 * 1000;
41
47
  /**
42
48
  * How long a resolved asset URL may stay in the SDK's GET cache, in ms: never
43
49
  * longer than the media token's lifetime, and discounted below it.
@@ -65,7 +71,13 @@ class AssetsApi {
65
71
  });
66
72
  if (body.type && !headers.has('Content-Type'))
67
73
  headers.set('Content-Type', body.type);
68
- const result = await fetch(target.toString(), { method: 'PUT', body, headers, credentials: 'omit', redirect: 'error' });
74
+ const result = await fetch(target.toString(), {
75
+ method: 'PUT',
76
+ body,
77
+ headers,
78
+ credentials: 'omit',
79
+ redirect: 'error',
80
+ });
69
81
  if (!result.ok)
70
82
  throw new Error(`Presigned upload failed (${result.status})`);
71
83
  }
@@ -83,7 +95,8 @@ class AssetsApi {
83
95
  const fileName = 'name' in file && file.name ? file.name : 'unknown';
84
96
  const fileSize = 'size' in file && file.size ? file.size : 0;
85
97
  const formData = new FormData();
86
- if ((typeof File !== 'undefined' && file instanceof File) || (typeof Blob !== 'undefined' && file instanceof Blob)) {
98
+ if ((typeof File !== 'undefined' && file instanceof File) ||
99
+ (typeof Blob !== 'undefined' && file instanceof Blob)) {
87
100
  formData.append('file', file, fileName);
88
101
  }
89
102
  else if ('uri' in file && typeof file.uri === 'string') {
@@ -99,7 +112,9 @@ class AssetsApi {
99
112
  throw new Error(`Failed to read file from uri (status ${res.status})`);
100
113
  }
101
114
  const fetched = await res.blob();
102
- const blob = fetched.type === '' && descriptor.type ? new Blob([fetched], { type: descriptor.type }) : fetched;
115
+ const blob = fetched.type === '' && descriptor.type
116
+ ? new Blob([fetched], { type: descriptor.type })
117
+ : fetched;
103
118
  if (blob.size === 0) {
104
119
  throw new Error('Cannot upload an empty file');
105
120
  }
@@ -114,13 +129,19 @@ class AssetsApi {
114
129
  if (options.metadata)
115
130
  formData.append('metadata', JSON.stringify(options.metadata));
116
131
  try {
117
- const response = await this.ctx.request('POST', '/assets/upload', formData, { cache: false });
132
+ const response = await this.ctx.request('POST', '/assets/upload', formData, {
133
+ cache: false,
134
+ timeout: options.timeout ?? ASSET_UPLOAD_TIMEOUT_MS,
135
+ });
118
136
  options.onProgress?.(100);
119
137
  return response;
120
138
  }
121
139
  catch (error) {
122
140
  logger_1.logger.error('File upload error', error, { component: 'oxy.assets' });
123
- error.fileContext = { fileName, fileSize };
141
+ error.fileContext = {
142
+ fileName,
143
+ fileSize,
144
+ };
124
145
  throw error;
125
146
  }
126
147
  }
@@ -136,7 +157,9 @@ class AssetsApi {
136
157
  // ── Links ────────────────────────────────────────────────────────────────
137
158
  /** Link an asset to an entity (what keeps it alive). */
138
159
  async link(fileId, target, options = {}) {
139
- const body = { ...target };
160
+ const body = {
161
+ ...target,
162
+ };
140
163
  if (options.visibility)
141
164
  body.visibility = options.visibility;
142
165
  if (options.webhookUrl)
@@ -156,7 +179,10 @@ class AssetsApi {
156
179
  // ── Reads ────────────────────────────────────────────────────────────────
157
180
  /** An asset's record: size, mime, visibility, links, variants. */
158
181
  async get(fileId) {
159
- return this.ctx.request('GET', `/assets/${enc(fileId)}`, undefined, { cache: true, cacheTTL: ASSET_TTL });
182
+ return this.ctx.request('GET', `/assets/${enc(fileId)}`, undefined, {
183
+ cache: true,
184
+ cacheTTL: ASSET_TTL,
185
+ });
160
186
  }
161
187
  /** The signed-in user's files, newest first. */
162
188
  async list(params = {}) {
@@ -169,7 +195,9 @@ class AssetsApi {
169
195
  }
170
196
  /** The account's storage usage, aggregated from its assets. */
171
197
  async usage() {
172
- return this.ctx.request('GET', '/storage/usage', undefined, { cache: false });
198
+ return this.ctx.request('GET', '/storage/usage', undefined, {
199
+ cache: false,
200
+ });
173
201
  }
174
202
  // ── URLs ─────────────────────────────────────────────────────────────────
175
203
  /**
@@ -251,7 +279,9 @@ class AssetsApi {
251
279
  body.expiresIn = options.expiresIn;
252
280
  if (typeof options?.context === 'string')
253
281
  body.context = options.context;
254
- return this.ctx.request('POST', '/assets/batch-access', body, { cache: false });
282
+ return this.ctx.request('POST', '/assets/batch-access', body, {
283
+ cache: false,
284
+ });
255
285
  }
256
286
  // ── Content ──────────────────────────────────────────────────────────────
257
287
  /** An asset's content as text. */
@@ -271,7 +301,9 @@ class AssetsApi {
271
301
  */
272
302
  async delete(fileId, options = {}) {
273
303
  const url = `/assets/${enc(fileId)}${options.force ? '?force=true' : ''}`;
274
- const res = await this.ctx.request('DELETE', url, undefined, { cache: false });
304
+ const res = await this.ctx.request('DELETE', url, undefined, {
305
+ cache: false,
306
+ });
275
307
  this.evict(fileId);
276
308
  return res;
277
309
  }
@@ -313,7 +345,10 @@ class AssetsApi {
313
345
  }
314
346
  /** Drop the cached record and every cached URL variant of an asset, in one pass. */
315
347
  evict(fileId) {
316
- this.ctx.http.invalidateCache({ keys: [`GET:/assets/${enc(fileId)}`], prefixes: [`GET:/assets/${enc(fileId)}/url`] });
348
+ this.ctx.http.invalidateCache({
349
+ keys: [`GET:/assets/${enc(fileId)}`],
350
+ prefixes: [`GET:/assets/${enc(fileId)}/url`],
351
+ });
317
352
  }
318
353
  }
319
354
  exports.AssetsApi = AssetsApi;
@@ -333,7 +368,9 @@ function dedupeFileAccessRequests(requests) {
333
368
  if (seen.has(key))
334
369
  continue;
335
370
  seen.add(key);
336
- out.push(req.variant === undefined ? { fileId: req.fileId } : { fileId: req.fileId, variant: req.variant });
371
+ out.push(req.variant === undefined
372
+ ? { fileId: req.fileId }
373
+ : { fileId: req.fileId, variant: req.variant });
337
374
  }
338
375
  return out;
339
376
  }
@@ -233,7 +233,9 @@ class AuthPasswordApi {
233
233
  return signInStep(this.ctx, res, 'auth/signin/password');
234
234
  }
235
235
  async set(request) {
236
- return this.ctx.request('PUT', '/users/me/password', request, { cache: false });
236
+ return this.ctx.request('PUT', '/users/me/password', request, {
237
+ cache: false,
238
+ });
237
239
  }
238
240
  }
239
241
  exports.AuthPasswordApi = AuthPasswordApi;
@@ -243,7 +245,9 @@ class AuthTotpApi {
243
245
  this.ctx = ctx;
244
246
  }
245
247
  async enroll() {
246
- const res = await this.ctx.request('POST', '/users/me/totp/enroll', undefined, { cache: false });
248
+ const res = await this.ctx.request('POST', '/users/me/totp/enroll', undefined, {
249
+ cache: false,
250
+ });
247
251
  const parsed = (0, contracts_1.safeParseContract)(contracts_1.totpEnrollResponseSchema, res);
248
252
  if (!parsed)
249
253
  throw new Error('users/me/totp/enroll returned an unexpected response shape');
@@ -312,7 +316,10 @@ class AuthOAuthApi {
312
316
  client_id: params.clientId,
313
317
  code_verifier: params.codeVerifier,
314
318
  });
315
- const res = await this.ctx.request('POST', '/auth/oauth/token', form, { cache: false, skipAuth: true });
319
+ const res = await this.ctx.request('POST', '/auth/oauth/token', form, {
320
+ cache: false,
321
+ skipAuth: true,
322
+ });
316
323
  if (!res || typeof res !== 'object') {
317
324
  throw new Error('auth/oauth/token returned an unexpected response shape');
318
325
  }
@@ -363,7 +370,9 @@ class AuthOAuthApi {
363
370
  * The response is a flat JSON document — no `{ data }` wrapper.
364
371
  */
365
372
  async userInfo() {
366
- const res = await this.ctx.request('GET', '/auth/oauth/userinfo', undefined, { cache: false });
373
+ const res = await this.ctx.request('GET', '/auth/oauth/userinfo', undefined, {
374
+ cache: false,
375
+ });
367
376
  if (!res || typeof res !== 'object') {
368
377
  throw new Error('auth/oauth/userinfo returned an unexpected response shape');
369
378
  }
@@ -693,12 +702,18 @@ class AuthAgentApi {
693
702
  }
694
703
  async requestChallenge(publicKey) {
695
704
  const body = contracts_1.agentChallengeRequestSchema.parse({ publicKey });
696
- const response = await this.ctx.request('POST', '/auth/agent/challenge', body, { cache: false, skipAuth: true });
705
+ const response = await this.ctx.request('POST', '/auth/agent/challenge', body, {
706
+ cache: false,
707
+ skipAuth: true,
708
+ });
697
709
  return contracts_1.agentProofClaimsSchema.parse(response);
698
710
  }
699
711
  async verify(publicKey, proof) {
700
712
  const body = contracts_1.agentVerifyRequestSchema.parse({ publicKey, ...proof });
701
- const response = await this.ctx.request('POST', '/auth/agent/verify', body, { cache: false, skipAuth: true });
713
+ const response = await this.ctx.request('POST', '/auth/agent/verify', body, {
714
+ cache: false,
715
+ skipAuth: true,
716
+ });
702
717
  return plantSession(this.ctx, response, 'auth/agent/verify');
703
718
  }
704
719
  }
@@ -714,14 +729,19 @@ class AuthApi {
714
729
  this.agent = new AuthAgentApi(ctx);
715
730
  }
716
731
  /**
717
- * Register a new identity with public key authentication
718
- * Identity is purely cryptographic - username and profile data are optional
732
+ * Register a new account for a public key, together with its username.
733
+ *
734
+ * The username is required: the server writes it in the same insert as the
735
+ * key, so an account never exists without one. A taken username is a 409
736
+ * (`Username already taken`), as is a key that is already registered
737
+ * (`Identity already registered`).
719
738
  *
720
739
  * @param publicKey - The user's ECDSA public key (hex)
721
740
  * @param signature - Signature of the registration request
722
741
  * @param timestamp - Timestamp when the signature was created
742
+ * @param username - The account's username
723
743
  */
724
- async registerKey(publicKey, signature, timestamp) {
744
+ async registerKey(publicKey, signature, timestamp, username) {
725
745
  // Advisory for now (server soft-enforces — see
726
746
  // `SessionController.register`), but solved unconditionally so every
727
747
  // client is already sending it once the server starts requiring it.
@@ -731,6 +751,7 @@ class AuthApi {
731
751
  publicKey,
732
752
  signature,
733
753
  timestamp,
754
+ username,
734
755
  powNonce,
735
756
  }, { cache: false, skipAuth: true });
736
757
  if (!res || (typeof res === 'object' && Object.keys(res).length === 0)) {
@@ -895,7 +916,10 @@ class AuthApi {
895
916
  */
896
917
  async checkUsername(username) {
897
918
  // Public availability lookup (pre-session) — skip the bearer preflight.
898
- return this.ctx.request('GET', `/auth/check-username/${username}`, undefined, { cache: false, skipAuth: true });
919
+ return this.ctx.request('GET', `/auth/check-username/${username}`, undefined, {
920
+ cache: false,
921
+ skipAuth: true,
922
+ });
899
923
  }
900
924
  /**
901
925
  * The authenticator's code (or a backup code) for a first factor's
@@ -913,7 +937,9 @@ class AuthApi {
913
937
  return plantSession(this.ctx, res, 'auth/signup');
914
938
  }
915
939
  async methods() {
916
- const res = await this.ctx.request('GET', '/users/me/sign-in-methods', undefined, { cache: false });
940
+ const res = await this.ctx.request('GET', '/users/me/sign-in-methods', undefined, {
941
+ cache: false,
942
+ });
917
943
  const parsed = (0, contracts_1.safeParseContract)(contracts_1.signInMethodsSchema, res);
918
944
  if (!parsed)
919
945
  throw new Error('users/me/sign-in-methods returned an unexpected response shape');
@@ -27,7 +27,9 @@ class BillingApi {
27
27
  }
28
28
  /** Public versioned personal plans. Discovery never proves customer access. */
29
29
  async personalPlans() {
30
- return contracts_2.personalPlanCatalogueSchema.parse(await this.ctx.request('GET', '/billing/personal-plans', undefined, { cache: false }));
30
+ return contracts_2.personalPlanCatalogueSchema.parse(await this.ctx.request('GET', '/billing/personal-plans', undefined, {
31
+ cache: false,
32
+ }));
31
33
  }
32
34
  /** Product rights only; requires a production application-bound user session. Never cached. */
33
35
  async productAccess(query) {
@@ -37,19 +39,29 @@ class BillingApi {
37
39
  }
38
40
  /** Named commercial sources for the current subject; no inferred plan collapse. */
39
41
  async productSubscriptions(expectedSubjectAccountId) {
40
- return contracts_4.productSubscriptionsResponseSchema.parse(await this.ctx.request("GET", expectedSubjectAccountId ? `/billing/product-subscriptions?expectedSubjectAccountId=${encodeURIComponent(expectedSubjectAccountId)}` : "/billing/product-subscriptions", undefined, { cache: false })).subscriptions;
42
+ return contracts_4.productSubscriptionsResponseSchema.parse(await this.ctx.request('GET', expectedSubjectAccountId
43
+ ? `/billing/product-subscriptions?expectedSubjectAccountId=${encodeURIComponent(expectedSubjectAccountId)}`
44
+ : '/billing/product-subscriptions', undefined, { cache: false })).subscriptions;
41
45
  }
42
46
  /** Per-grant credit provenance; no interpretation of the historical mixed balance. */
43
47
  async creditGrants() {
44
- return contracts_4.subscriptionCreditGrantsResponseSchema.parse(await this.ctx.request("GET", "/billing/credit-grants", undefined, { cache: false })).grants;
48
+ return contracts_4.subscriptionCreditGrantsResponseSchema.parse(await this.ctx.request('GET', '/billing/credit-grants', undefined, { cache: false })).grants;
45
49
  }
46
50
  /** Payer-only named-source cancellation. Resolves on provider acceptance, including pending local reconciliation. Use cancelProductSubscriptionWithStatus for detailed completion state. */
47
51
  async cancelProductSubscription(sourceId, expectedSubjectAccountId, actionId) {
48
- await this.ctx.request("POST", "/billing/product-subscriptions/cancel", contracts_4.cancelProductSubscriptionSchema.parse({ sourceId, ...(actionId ? { actionId } : {}), ...(expectedSubjectAccountId ? { expectedSubjectAccountId } : {}) }), { cache: false });
52
+ await this.ctx.request('POST', '/billing/product-subscriptions/cancel', contracts_4.cancelProductSubscriptionSchema.parse({
53
+ sourceId,
54
+ ...(actionId ? { actionId } : {}),
55
+ ...(expectedSubjectAccountId ? { expectedSubjectAccountId } : {}),
56
+ }), { cache: false });
49
57
  }
50
58
  /** Provider acceptance versus completed local cancellation, for user-facing flows. */
51
59
  async cancelProductSubscriptionWithStatus(sourceId, expectedSubjectAccountId, actionId) {
52
- return contracts_4.productSubscriptionCancellationResultSchema.parse(await this.ctx.request('POST', '/billing/product-subscriptions/cancel', contracts_4.cancelProductSubscriptionSchema.parse({ sourceId, ...(actionId ? { actionId } : {}), ...(expectedSubjectAccountId ? { expectedSubjectAccountId } : {}) }), { cache: false }));
60
+ return contracts_4.productSubscriptionCancellationResultSchema.parse(await this.ctx.request('POST', '/billing/product-subscriptions/cancel', contracts_4.cancelProductSubscriptionSchema.parse({
61
+ sourceId,
62
+ ...(actionId ? { actionId } : {}),
63
+ ...(expectedSubjectAccountId ? { expectedSubjectAccountId } : {}),
64
+ }), { cache: false }));
53
65
  }
54
66
  /** The signed-in user's payment history. Never cached. */
55
67
  async payments() {
@@ -66,7 +78,10 @@ class BillingApi {
66
78
  /** A user's wallet (default: the signed-in user's). Cached briefly: the balance moves. */
67
79
  async wallet(userId) {
68
80
  const id = this.resolveUserId(userId);
69
- return this.ctx.request('GET', `/wallet/${id}`, undefined, { cache: true, cacheTTL: WALLET_TTL });
81
+ return this.ctx.request('GET', `/wallet/${id}`, undefined, {
82
+ cache: true,
83
+ cacheTTL: WALLET_TTL,
84
+ });
70
85
  }
71
86
  /** A page of a user's wallet transactions (default: the signed-in user's). Never cached. */
72
87
  async walletTransactions(options = {}) {
@@ -76,7 +91,9 @@ class BillingApi {
76
91
  params.limit = options.limit;
77
92
  if (options.offset)
78
93
  params.offset = options.offset;
79
- return this.ctx.request('GET', `/wallet/transactions/${id}`, params, { cache: false });
94
+ return this.ctx.request('GET', `/wallet/transactions/${id}`, params, {
95
+ cache: false,
96
+ });
80
97
  }
81
98
  resolveUserId(userId) {
82
99
  const id = userId || this.ctx.oxy.session.userId;