@oxy.so/core 4.5.0-oxy-one.1 → 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 (282) 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 +39 -11
  7. package/dist/cjs/api/auth.js +28 -8
  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 +39 -11
  83. package/dist/esm/api/auth.js +28 -8
  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/crypto/internal.d.ts +1 -1
  161. package/dist/types/index.d.ts +4 -4
  162. package/dist/types/server/index.d.ts +6 -6
  163. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  164. package/dist/types/server/workloadIdentity.d.ts +26 -0
  165. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  166. package/dist/types/session/index.d.ts +1 -1
  167. package/dist/types/utils/userIdentity.d.ts +1 -1
  168. package/dist/types/utils/validationUtils.d.ts +4 -5
  169. package/package.json +2 -3
  170. package/src/HttpService.ts +183 -53
  171. package/src/OxyServices.errors.ts +7 -3
  172. package/src/OxyServices.ts +6 -2
  173. package/src/api/accounts.ts +76 -26
  174. package/src/api/agency.ts +24 -9
  175. package/src/api/appData.ts +12 -2
  176. package/src/api/apps.ts +81 -31
  177. package/src/api/assets.ts +113 -43
  178. package/src/api/auth.ts +145 -77
  179. package/src/api/billing.ts +112 -65
  180. package/src/api/civic.ts +61 -19
  181. package/src/api/contacts.ts +4 -1
  182. package/src/api/devices.ts +54 -21
  183. package/src/api/follows.ts +88 -31
  184. package/src/api/identity.ts +101 -33
  185. package/src/api/linkedAccounts.ts +26 -8
  186. package/src/api/nodes.ts +18 -6
  187. package/src/api/notifications.ts +26 -6
  188. package/src/api/privacy.ts +42 -8
  189. package/src/api/reputation.ts +18 -7
  190. package/src/api/session.ts +23 -5
  191. package/src/api/store.ts +81 -31
  192. package/src/api/topics.ts +18 -6
  193. package/src/api/users.ts +98 -35
  194. package/src/boot/sessionColdBoot.ts +60 -19
  195. package/src/civic/payloads.ts +1 -4
  196. package/src/client/context.ts +6 -1
  197. package/src/constants/version.ts +7 -6
  198. package/src/crypto/aead.ts +1 -5
  199. package/src/crypto/ecdh.ts +1 -4
  200. package/src/crypto/identityDerivations.ts +5 -1
  201. package/src/crypto/identityMarker.ts +3 -1
  202. package/src/crypto/identityProof.ts +6 -1
  203. package/src/crypto/index.ts +11 -11
  204. package/src/crypto/internal.ts +6 -1
  205. package/src/crypto/keyManager.ts +348 -98
  206. package/src/crypto/recoveryPhrase.ts +14 -9
  207. package/src/crypto/registrationPow.ts +1 -1
  208. package/src/crypto/signatureService.ts +14 -6
  209. package/src/i18n/accountCategoryLabels.ts +1 -4
  210. package/src/i18n/accountRoleLabels.ts +1 -4
  211. package/src/i18n/index.ts +25 -7
  212. package/src/i18n/locales/ar-SA.ts +375 -366
  213. package/src/i18n/locales/ca-ES.ts +382 -366
  214. package/src/i18n/locales/de-DE.ts +387 -366
  215. package/src/i18n/locales/en-US.ts +2034 -1994
  216. package/src/i18n/locales/es-ES.ts +2043 -1994
  217. package/src/i18n/locales/fr-FR.ts +387 -366
  218. package/src/i18n/locales/it-IT.ts +380 -366
  219. package/src/i18n/locales/ja-JP.ts +380 -366
  220. package/src/i18n/locales/ko-KR.ts +377 -366
  221. package/src/i18n/locales/pt-PT.ts +383 -366
  222. package/src/i18n/locales/zh-CN.ts +373 -366
  223. package/src/i18n/trustTierLabels.ts +1 -4
  224. package/src/index.ts +371 -349
  225. package/src/inference/OxyInferenceClient.ts +784 -780
  226. package/src/models/interfaces.ts +30 -27
  227. package/src/server/OxyServer.ts +227 -68
  228. package/src/server/agentAccount.ts +8 -2
  229. package/src/server/aliaMachineCredential.ts +57 -16
  230. package/src/server/auth.ts +9 -5
  231. package/src/server/capabilityTicket.ts +30 -21
  232. package/src/server/index.ts +29 -6
  233. package/src/server/liveCapabilityTicket.ts +31 -9
  234. package/src/server/middleware.ts +212 -121
  235. package/src/server/namespaces.ts +247 -94
  236. package/src/server/rateLimit.ts +2 -4
  237. package/src/server/requesterAssertion.ts +93 -54
  238. package/src/server/serviceTokenLifetime.ts +9 -4
  239. package/src/server/traffic.ts +117 -23
  240. package/src/server/trafficNodeHttp.ts +61 -14
  241. package/src/server/userInvalidation.ts +1 -4
  242. package/src/server/workloadIdentity.client.ts +12 -1
  243. package/src/server/workloadIdentity.ts +52 -5
  244. package/src/session/SessionClient.ts +170 -49
  245. package/src/session/accountDelegationAccess.ts +24 -31
  246. package/src/session/accountDialogController.ts +59 -14
  247. package/src/session/accountSwitchTargets.ts +10 -15
  248. package/src/session/authStateStore.ts +121 -81
  249. package/src/session/deviceDirectory.ts +1 -3
  250. package/src/session/identityPin.ts +10 -11
  251. package/src/session/identitySession.ts +3 -1
  252. package/src/session/index.ts +87 -82
  253. package/src/session/refresh.ts +138 -44
  254. package/src/session/sessionClientHost.ts +1 -3
  255. package/src/session/sharedDeviceCredential.ts +35 -14
  256. package/src/session/socketLoader.ts +9 -2
  257. package/src/shared/utils/errorUtils.ts +5 -2
  258. package/src/shared/utils/networkUtils.ts +5 -8
  259. package/src/shared/utils/themeUtils.ts +2 -6
  260. package/src/types/buffer.d.ts +66 -21
  261. package/src/types/expo-secure-store.d.ts +5 -1
  262. package/src/utils/accountCacheSweep.ts +4 -5
  263. package/src/utils/accountUtils.ts +107 -108
  264. package/src/utils/apiUtils.ts +3 -3
  265. package/src/utils/asyncUtils.ts +2 -2
  266. package/src/utils/authHelpers.ts +10 -5
  267. package/src/utils/avatarUtils.ts +11 -6
  268. package/src/utils/cache.ts +9 -10
  269. package/src/utils/cacheKey.ts +5 -1
  270. package/src/utils/coldBoot.ts +1 -3
  271. package/src/utils/commonsDelivery.ts +1 -4
  272. package/src/utils/deviceManager.ts +15 -14
  273. package/src/utils/errorUtils.ts +68 -86
  274. package/src/utils/languageUtils.ts +407 -58
  275. package/src/utils/oauthPkce.ts +1 -4
  276. package/src/utils/platform.ts +0 -1
  277. package/src/utils/profileLinks.ts +2 -5
  278. package/src/utils/requestUtils.ts +18 -14
  279. package/src/utils/sessionUtils.ts +34 -33
  280. package/src/utils/userHandle.ts +3 -1
  281. package/src/utils/userIdentity.ts +1 -1
  282. package/src/utils/validationUtils.ts +11 -9
@@ -15,7 +15,7 @@
15
15
  import { TTLCache, registerCacheForCleanup, unregisterCacheFromCleanup } from './utils/cache.js';
16
16
  import { RequestDeduplicator, RequestQueue, SimpleLogger } from './utils/requestUtils.js';
17
17
  import { retryAsync } from './utils/asyncUtils.js';
18
- import { createCancelledError, ErrorCodes, handleHttpError, isCancelledError, parseHttpErrorBody } from './utils/errorUtils.js';
18
+ import { createCancelledError, ErrorCodes, handleHttpError, isCancelledError, parseHttpErrorBody, } from './utils/errorUtils.js';
19
19
  import { decodeTokenClaims } from './utils/tokenClaims.js';
20
20
  import { isReactNative } from '@oxy.so/protocol/random';
21
21
  import { computeIdentityTag, fnv1a32 } from './utils/cacheKey.js';
@@ -36,14 +36,25 @@ function sameTokenSession(left, right) {
36
36
  return false;
37
37
  // A refresh may rotate exp/iat/jti while preserving its account and session.
38
38
  // Opaque/malformed context fields cannot establish that equivalence.
39
- return ['userId', 'id', 'sub', 'sessionId', 'operatorId', 'clientId', 'appId', 'authMethodId'].every((key) => (a[key] === undefined || typeof a[key] === 'string') && a[key] === b[key]);
39
+ return [
40
+ 'userId',
41
+ 'id',
42
+ 'sub',
43
+ 'sessionId',
44
+ 'operatorId',
45
+ 'clientId',
46
+ 'appId',
47
+ 'authMethodId',
48
+ ].every((key) => (a[key] === undefined || typeof a[key] === 'string') && a[key] === b[key]);
40
49
  }
41
50
  /** Cancel this wait only; the shared mint continues for other callers. */
42
51
  function awaitRequestSignal(pending, signal) {
43
52
  if (!signal)
44
53
  return pending;
45
54
  return new Promise((resolve, reject) => {
46
- const onAbort = () => { reject(createCancelledError()); };
55
+ const onAbort = () => {
56
+ reject(createCancelledError());
57
+ };
47
58
  if (signal.aborted)
48
59
  onAbort();
49
60
  else
@@ -202,7 +213,9 @@ function isAbortLike(error) {
202
213
  function linkAbort(parent, child) {
203
214
  if (parent.aborted) {
204
215
  child.abort(parent.reason);
205
- return () => { };
216
+ return () => {
217
+ /* nothing was ever attached */
218
+ };
206
219
  }
207
220
  const onAbort = () => {
208
221
  child.abort(parent.reason);
@@ -314,8 +327,7 @@ export class HttpService {
314
327
  // the cache for the global cleanup interval. Default (config unset) keeps
315
328
  // caching ON with the 5-minute TTL — unchanged for existing consumers.
316
329
  this.cacheDisabled =
317
- config.enableCache === false ||
318
- (typeof config.cacheTTL === 'number' && config.cacheTTL <= 0);
330
+ config.enableCache === false || (typeof config.cacheTTL === 'number' && config.cacheTTL <= 0);
319
331
  this.cache = new TTLCache(config.cacheTTL && config.cacheTTL > 0 ? config.cacheTTL : 5 * 60 * 1000);
320
332
  if (!this.cacheDisabled) {
321
333
  registerCacheForCleanup(this.cache);
@@ -491,7 +503,7 @@ export class HttpService {
491
503
  const isUrlEncoded = this.isUrlSearchParams(data);
492
504
  // Build headers - start with defaults
493
505
  const headers = {
494
- 'Accept': 'application/json',
506
+ Accept: 'application/json',
495
507
  };
496
508
  // Only set Content-Type for non-FormData requests (FormData sets it automatically with boundary)
497
509
  if (isUrlEncoded) {
@@ -525,7 +537,11 @@ export class HttpService {
525
537
  // `fetch` as-is: RN's fetch does not consistently encode it, and doing
526
538
  // it here keeps the body identical across every platform.
527
539
  const bodyValue = method !== 'GET' && data
528
- ? (isFormData ? data : isUrlEncoded ? data.toString() : JSON.stringify(data))
540
+ ? isFormData
541
+ ? data
542
+ : isUrlEncoded
543
+ ? data.toString()
544
+ : JSON.stringify(data)
529
545
  : undefined;
530
546
  // React Native FormData workaround:
531
547
  // Expo SDK 56's "winter fetch" rejects RN file descriptors `{uri, type, name}`
@@ -567,7 +583,13 @@ export class HttpService {
567
583
  // queue slot, so a queued retry waits for a slot while holding one.
568
584
  // With every slot held by a 401 (a revoked session under load) no
569
585
  // retry could ever start and the whole client stalled.
570
- return this.request({ ...config, _isAuthRetry: true, retry: false, deduplicate: false, bypassQueue: true });
586
+ return this.request({
587
+ ...config,
588
+ _isAuthRetry: true,
589
+ retry: false,
590
+ deduplicate: false,
591
+ bypassQueue: true,
592
+ });
571
593
  }
572
594
  // Refresh failed or no token — clear tokens
573
595
  this.tokenStore.clearTokens();
@@ -594,7 +616,11 @@ export class HttpService {
594
616
  const parsed = parseHttpErrorBody(errorBody);
595
617
  const error = new Error(parsed.message ?? `HTTP ${response.status}: ${response.statusText}`);
596
618
  error.status = response.status;
597
- error.response = { status: response.status, statusText: response.statusText, data: errorBody };
619
+ error.response = {
620
+ status: response.status,
621
+ statusText: response.statusText,
622
+ data: errorBody,
623
+ };
598
624
  // Only set `code`/`details` when the server actually sent them.
599
625
  // Assigning `undefined` would still create the property, which changes
600
626
  // how `handleHttpError` classifies the error downstream.
@@ -641,7 +667,11 @@ export class HttpService {
641
667
  }
642
668
  }
643
669
  }
644
- else if (contentType && (contentType.includes('application/octet-stream') || contentType.includes('image/') || contentType.includes('video/') || contentType.includes('audio/'))) {
670
+ else if (contentType &&
671
+ (contentType.includes('application/octet-stream') ||
672
+ contentType.includes('image/') ||
673
+ contentType.includes('video/') ||
674
+ contentType.includes('audio/'))) {
645
675
  // For binary responses (blobs), return the blob directly without unwrapping
646
676
  responseData = await response.blob();
647
677
  }
@@ -707,7 +737,9 @@ export class HttpService {
707
737
  // Control-plane calls the auth lane depends on (`bypassQueue`, e.g. the
708
738
  // device-secret mint) run DIRECTLY — a queued mint could never acquire a
709
739
  // slot when every slot is parked awaiting it.
710
- config.bypassQueue ? attempt(domain) : this.requestQueue.enqueue(() => attempt(domain), domain);
740
+ config.bypassQueue
741
+ ? attempt(domain)
742
+ : this.requestQueue.enqueue(() => attempt(domain), domain);
711
743
  const execute = (domain) => retry
712
744
  ? retryAsync(() => runAttempt(domain), {
713
745
  maxRetries,
@@ -813,7 +845,9 @@ export class HttpService {
813
845
  try {
814
846
  xhr.abort();
815
847
  }
816
- catch { /* xhr already finished */ }
848
+ catch {
849
+ /* xhr already finished */
850
+ }
817
851
  };
818
852
  if (abortSignal.aborted) {
819
853
  reject(new DOMException('The user aborted a request.', 'AbortError'));
@@ -1226,8 +1260,10 @@ export class HttpService {
1226
1260
  // an auth mint, even when the trusted transport accepts absolute URLs.
1227
1261
  const target = new URL(this.buildURL(config.url));
1228
1262
  const base = new URL(this.baseURL);
1229
- if (target.origin !== base.origin || !['http:', 'https:'].includes(target.protocol)
1230
- || target.username || target.password) {
1263
+ if (target.origin !== base.origin ||
1264
+ !['http:', 'https:'].includes(target.protocol) ||
1265
+ target.username ||
1266
+ target.password) {
1231
1267
  throw new Error('Raw response requests must target the configured API origin');
1232
1268
  }
1233
1269
  if (config.signal?.aborted)
@@ -1237,7 +1273,8 @@ export class HttpService {
1237
1273
  const contextToken = this.syncAccessTokenFromProvider();
1238
1274
  const beforeAuthEpoch = this.sessionEpoch;
1239
1275
  const authHeader = await awaitRequestSignal(this.getAuthHeader(), config.signal);
1240
- if (beforeAuthEpoch !== this.sessionEpoch || !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1276
+ if (beforeAuthEpoch !== this.sessionEpoch ||
1277
+ !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1241
1278
  throw new OxyAuthenticationError('The request session changed', 'AUTH_SESSION_CHANGED');
1242
1279
  }
1243
1280
  if (config.signal?.aborted)
@@ -1250,7 +1287,8 @@ export class HttpService {
1250
1287
  async requestResponseAttempt(config, fullUrl, authHeader, isAuthRetry, epoch, contextToken) {
1251
1288
  const assertCurrent = () => {
1252
1289
  this.syncAccessTokenFromProvider();
1253
- if (epoch !== this.sessionEpoch || !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1290
+ if (epoch !== this.sessionEpoch ||
1291
+ !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1254
1292
  throw new OxyAuthenticationError('The request session changed', 'AUTH_SESSION_CHANGED');
1255
1293
  }
1256
1294
  };
@@ -1295,7 +1333,11 @@ export class HttpService {
1295
1333
  throw error;
1296
1334
  }
1297
1335
  const replayable = body === undefined || typeof body === 'string';
1298
- if (response.status === 401 && !isAuthRetry && authHeader && replayable && !config.signal?.aborted) {
1336
+ if (response.status === 401 &&
1337
+ !isAuthRetry &&
1338
+ authHeader &&
1339
+ replayable &&
1340
+ !config.signal?.aborted) {
1299
1341
  let refreshed;
1300
1342
  try {
1301
1343
  refreshed = await awaitRequestSignal(this.refreshAccessToken('response-401'), config.signal);
@@ -1330,7 +1372,9 @@ export class HttpService {
1330
1372
  this.config.onRequestEnd?.(config.url, config.method, duration, false);
1331
1373
  const normalizedError = config.signal?.aborted || isCancelledError(error)
1332
1374
  ? createCancelledError()
1333
- : error instanceof Error ? error : new Error(String(error));
1375
+ : error instanceof Error
1376
+ ? error
1377
+ : new Error(String(error));
1334
1378
  this.config.onRequestError?.(config.url, config.method, normalizedError);
1335
1379
  if (isCancelledError(normalizedError) || normalizedError instanceof OxyAuthenticationError)
1336
1380
  throw normalizedError;
@@ -1502,7 +1546,7 @@ export class HttpService {
1502
1546
  * per resource.
1503
1547
  * @returns Number of entries deleted
1504
1548
  */
1505
- invalidateCache({ keys = [], prefixes = [] }) {
1549
+ invalidateCache({ keys = [], prefixes = [], }) {
1506
1550
  if (keys.length === 0 && prefixes.length === 0)
1507
1551
  return 0;
1508
1552
  const exact = new Set(keys);
@@ -17,7 +17,7 @@
17
17
  * no per-request "acting-as" header. Identity is carried by the session/token,
18
18
  * so a switch propagates through reload and cross-domain exactly like a login.
19
19
  */
20
- import { agentKeyOperationSchema, executeAgentKeyOperationSchema, agentKeyOperationChallengeSchema, agentKeyOperationResultSchema, agentKeyListResponseSchema } from '@oxy.so/contracts';
20
+ import { agentKeyOperationSchema, executeAgentKeyOperationSchema, agentKeyOperationChallengeSchema, agentKeyOperationResultSchema, agentKeyListResponseSchema, } from '@oxy.so/contracts';
21
21
  import { normalizeUserIdentity } from '../utils/userIdentity.js';
22
22
  import { evictOxyIdentityCache } from '../utils/identityCacheSweep.js';
23
23
  import { evictOxyAccountForestCache, oxyAccountDetailCacheKey, OXY_ACCOUNT_PER_ACCOUNT_CACHE_PREFIX, } from '../utils/accountCacheSweep.js';
@@ -93,7 +93,9 @@ export class AccountAgentKeysApi {
93
93
  this.ctx = ctx;
94
94
  }
95
95
  async list(accountId) {
96
- return agentKeyListResponseSchema.parse(await this.ctx.request('GET', `/accounts/${enc(accountId)}/agent-keys`, undefined, { cache: false }));
96
+ return agentKeyListResponseSchema.parse(await this.ctx.request('GET', `/accounts/${enc(accountId)}/agent-keys`, undefined, {
97
+ cache: false,
98
+ }));
97
99
  }
98
100
  async requestChallenge(accountId, operation) {
99
101
  const response = await this.ctx.request('POST', `/accounts/${enc(accountId)}/agent-keys/challenge`, agentKeyOperationSchema.parse(operation), { cache: false });
@@ -182,7 +184,9 @@ export class AccountsApi {
182
184
  * @param data - Account configuration: kind, optional parent, and profile.
183
185
  */
184
186
  async create(data) {
185
- const res = await this.ctx.request('POST', '/accounts', data, { cache: false });
187
+ const res = await this.ctx.request('POST', '/accounts', data, {
188
+ cache: false,
189
+ });
186
190
  // A new account changes the accessible forest — bust every cached list.
187
191
  evictOxyAccountForestCache(this.ctx.http);
188
192
  return res.account;
@@ -222,7 +226,10 @@ export class AccountsApi {
222
226
  cache: false,
223
227
  });
224
228
  this.ctx.http.invalidateCache({
225
- keys: [`GET:/accounts/${enc(accountId)}/members`, `GET:/accounts/${enc(accountId)}/credentials`],
229
+ keys: [
230
+ `GET:/accounts/${enc(accountId)}/members`,
231
+ `GET:/accounts/${enc(accountId)}/credentials`,
232
+ ],
226
233
  });
227
234
  evictOxyAccountForestCache(this.ctx.http, accountId);
228
235
  return result;
@@ -33,7 +33,9 @@ export class DelegationGrantsApi {
33
33
  }
34
34
  /** Revoke a grant. */
35
35
  async revoke(grantId, ownerAccountId) {
36
- await this.ctx.request('DELETE', `/capabilities/grants/${enc(grantId)}`, undefined, { cache: false });
36
+ await this.ctx.request('DELETE', `/capabilities/grants/${enc(grantId)}`, undefined, {
37
+ cache: false,
38
+ });
37
39
  this.ctx.oxy.cache.delete(grantsKey(ownerAccountId));
38
40
  }
39
41
  }
@@ -68,7 +68,10 @@ export class ConnectedAppsApi {
68
68
  * `GET /auth/grants`, briefly cached; `revoke` busts it.
69
69
  */
70
70
  async list() {
71
- return this.ctx.request('GET', '/auth/grants', undefined, { cache: true, cacheTTL: SHORT_TTL });
71
+ return this.ctx.request('GET', '/auth/grants', undefined, {
72
+ cache: true,
73
+ cacheTTL: SHORT_TTL,
74
+ });
72
75
  }
73
76
  /**
74
77
  * Revoke this user's grant for a connected application. After this the
@@ -90,7 +93,9 @@ export class ConnectedAppsApi {
90
93
  }
91
94
  /** Revoke one external MCP connection and every token in its family. */
92
95
  async revokeMcpClient(grantId) {
93
- await this.ctx.request('DELETE', `/auth/mcp/oauth/grants/${enc(grantId)}`, undefined, { cache: false });
96
+ await this.ctx.request('DELETE', `/auth/mcp/oauth/grants/${enc(grantId)}`, undefined, {
97
+ cache: false,
98
+ });
94
99
  this.ctx.oxy.cache.delete('GET:/auth/mcp/oauth/grants');
95
100
  }
96
101
  }
@@ -149,7 +154,10 @@ export class AppsApi {
149
154
  const result = await this.ctx.request('DELETE', appPath(applicationId), undefined, {
150
155
  cache: false,
151
156
  });
152
- this.invalidateLists([`GET:${appPath(applicationId)}`, `GET:${credentialsPath(applicationId)}`]);
157
+ this.invalidateLists([
158
+ `GET:${appPath(applicationId)}`,
159
+ `GET:${credentialsPath(applicationId)}`,
160
+ ]);
153
161
  return result;
154
162
  }
155
163
  /**
@@ -180,7 +188,10 @@ export class AppsApi {
180
188
  * `GET:/applications/<id>…` detail keys.
181
189
  */
182
190
  invalidateLists(extraKeys = []) {
183
- this.ctx.http.invalidateCache({ keys: ['GET:/applications', ...extraKeys], prefixes: ['GET:/applications?'] });
191
+ this.ctx.http.invalidateCache({
192
+ keys: ['GET:/applications', ...extraKeys],
193
+ prefixes: ['GET:/applications?'],
194
+ });
184
195
  }
185
196
  }
186
197
  function appPath(applicationId) {
@@ -67,7 +67,13 @@ export class AssetsApi {
67
67
  });
68
68
  if (body.type && !headers.has('Content-Type'))
69
69
  headers.set('Content-Type', body.type);
70
- const result = await fetch(target.toString(), { method: 'PUT', body, headers, credentials: 'omit', redirect: 'error' });
70
+ const result = await fetch(target.toString(), {
71
+ method: 'PUT',
72
+ body,
73
+ headers,
74
+ credentials: 'omit',
75
+ redirect: 'error',
76
+ });
71
77
  if (!result.ok)
72
78
  throw new Error(`Presigned upload failed (${result.status})`);
73
79
  }
@@ -85,7 +91,8 @@ export class AssetsApi {
85
91
  const fileName = 'name' in file && file.name ? file.name : 'unknown';
86
92
  const fileSize = 'size' in file && file.size ? file.size : 0;
87
93
  const formData = new FormData();
88
- if ((typeof File !== 'undefined' && file instanceof File) || (typeof Blob !== 'undefined' && file instanceof Blob)) {
94
+ if ((typeof File !== 'undefined' && file instanceof File) ||
95
+ (typeof Blob !== 'undefined' && file instanceof Blob)) {
89
96
  formData.append('file', file, fileName);
90
97
  }
91
98
  else if ('uri' in file && typeof file.uri === 'string') {
@@ -101,7 +108,9 @@ export class AssetsApi {
101
108
  throw new Error(`Failed to read file from uri (status ${res.status})`);
102
109
  }
103
110
  const fetched = await res.blob();
104
- const blob = fetched.type === '' && descriptor.type ? new Blob([fetched], { type: descriptor.type }) : fetched;
111
+ const blob = fetched.type === '' && descriptor.type
112
+ ? new Blob([fetched], { type: descriptor.type })
113
+ : fetched;
105
114
  if (blob.size === 0) {
106
115
  throw new Error('Cannot upload an empty file');
107
116
  }
@@ -125,7 +134,10 @@ export class AssetsApi {
125
134
  }
126
135
  catch (error) {
127
136
  logger.error('File upload error', error, { component: 'oxy.assets' });
128
- error.fileContext = { fileName, fileSize };
137
+ error.fileContext = {
138
+ fileName,
139
+ fileSize,
140
+ };
129
141
  throw error;
130
142
  }
131
143
  }
@@ -141,7 +153,9 @@ export class AssetsApi {
141
153
  // ── Links ────────────────────────────────────────────────────────────────
142
154
  /** Link an asset to an entity (what keeps it alive). */
143
155
  async link(fileId, target, options = {}) {
144
- const body = { ...target };
156
+ const body = {
157
+ ...target,
158
+ };
145
159
  if (options.visibility)
146
160
  body.visibility = options.visibility;
147
161
  if (options.webhookUrl)
@@ -161,7 +175,10 @@ export class AssetsApi {
161
175
  // ── Reads ────────────────────────────────────────────────────────────────
162
176
  /** An asset's record: size, mime, visibility, links, variants. */
163
177
  async get(fileId) {
164
- return this.ctx.request('GET', `/assets/${enc(fileId)}`, undefined, { cache: true, cacheTTL: ASSET_TTL });
178
+ return this.ctx.request('GET', `/assets/${enc(fileId)}`, undefined, {
179
+ cache: true,
180
+ cacheTTL: ASSET_TTL,
181
+ });
165
182
  }
166
183
  /** The signed-in user's files, newest first. */
167
184
  async list(params = {}) {
@@ -174,7 +191,9 @@ export class AssetsApi {
174
191
  }
175
192
  /** The account's storage usage, aggregated from its assets. */
176
193
  async usage() {
177
- return this.ctx.request('GET', '/storage/usage', undefined, { cache: false });
194
+ return this.ctx.request('GET', '/storage/usage', undefined, {
195
+ cache: false,
196
+ });
178
197
  }
179
198
  // ── URLs ─────────────────────────────────────────────────────────────────
180
199
  /**
@@ -256,7 +275,9 @@ export class AssetsApi {
256
275
  body.expiresIn = options.expiresIn;
257
276
  if (typeof options?.context === 'string')
258
277
  body.context = options.context;
259
- return this.ctx.request('POST', '/assets/batch-access', body, { cache: false });
278
+ return this.ctx.request('POST', '/assets/batch-access', body, {
279
+ cache: false,
280
+ });
260
281
  }
261
282
  // ── Content ──────────────────────────────────────────────────────────────
262
283
  /** An asset's content as text. */
@@ -276,7 +297,9 @@ export class AssetsApi {
276
297
  */
277
298
  async delete(fileId, options = {}) {
278
299
  const url = `/assets/${enc(fileId)}${options.force ? '?force=true' : ''}`;
279
- const res = await this.ctx.request('DELETE', url, undefined, { cache: false });
300
+ const res = await this.ctx.request('DELETE', url, undefined, {
301
+ cache: false,
302
+ });
280
303
  this.evict(fileId);
281
304
  return res;
282
305
  }
@@ -318,7 +341,10 @@ export class AssetsApi {
318
341
  }
319
342
  /** Drop the cached record and every cached URL variant of an asset, in one pass. */
320
343
  evict(fileId) {
321
- this.ctx.http.invalidateCache({ keys: [`GET:/assets/${enc(fileId)}`], prefixes: [`GET:/assets/${enc(fileId)}/url`] });
344
+ this.ctx.http.invalidateCache({
345
+ keys: [`GET:/assets/${enc(fileId)}`],
346
+ prefixes: [`GET:/assets/${enc(fileId)}/url`],
347
+ });
322
348
  }
323
349
  }
324
350
  const enc = encodeURIComponent;
@@ -337,7 +363,9 @@ function dedupeFileAccessRequests(requests) {
337
363
  if (seen.has(key))
338
364
  continue;
339
365
  seen.add(key);
340
- out.push(req.variant === undefined ? { fileId: req.fileId } : { fileId: req.fileId, variant: req.variant });
366
+ out.push(req.variant === undefined
367
+ ? { fileId: req.fileId }
368
+ : { fileId: req.fileId, variant: req.variant });
341
369
  }
342
370
  return out;
343
371
  }
@@ -196,7 +196,9 @@ export class AuthPasswordApi {
196
196
  return signInStep(this.ctx, res, 'auth/signin/password');
197
197
  }
198
198
  async set(request) {
199
- return this.ctx.request('PUT', '/users/me/password', request, { cache: false });
199
+ return this.ctx.request('PUT', '/users/me/password', request, {
200
+ cache: false,
201
+ });
200
202
  }
201
203
  }
202
204
  /** `oxy.auth.totp` — the account’s authenticator app. */
@@ -205,7 +207,9 @@ export class AuthTotpApi {
205
207
  this.ctx = ctx;
206
208
  }
207
209
  async enroll() {
208
- const res = await this.ctx.request('POST', '/users/me/totp/enroll', undefined, { cache: false });
210
+ const res = await this.ctx.request('POST', '/users/me/totp/enroll', undefined, {
211
+ cache: false,
212
+ });
209
213
  const parsed = safeParseContract(totpEnrollResponseSchema, res);
210
214
  if (!parsed)
211
215
  throw new Error('users/me/totp/enroll returned an unexpected response shape');
@@ -273,7 +277,10 @@ export class AuthOAuthApi {
273
277
  client_id: params.clientId,
274
278
  code_verifier: params.codeVerifier,
275
279
  });
276
- const res = await this.ctx.request('POST', '/auth/oauth/token', form, { cache: false, skipAuth: true });
280
+ const res = await this.ctx.request('POST', '/auth/oauth/token', form, {
281
+ cache: false,
282
+ skipAuth: true,
283
+ });
277
284
  if (!res || typeof res !== 'object') {
278
285
  throw new Error('auth/oauth/token returned an unexpected response shape');
279
286
  }
@@ -324,7 +331,9 @@ export class AuthOAuthApi {
324
331
  * The response is a flat JSON document — no `{ data }` wrapper.
325
332
  */
326
333
  async userInfo() {
327
- const res = await this.ctx.request('GET', '/auth/oauth/userinfo', undefined, { cache: false });
334
+ const res = await this.ctx.request('GET', '/auth/oauth/userinfo', undefined, {
335
+ cache: false,
336
+ });
328
337
  if (!res || typeof res !== 'object') {
329
338
  throw new Error('auth/oauth/userinfo returned an unexpected response shape');
330
339
  }
@@ -652,12 +661,18 @@ export class AuthAgentApi {
652
661
  }
653
662
  async requestChallenge(publicKey) {
654
663
  const body = agentChallengeRequestSchema.parse({ publicKey });
655
- const response = await this.ctx.request('POST', '/auth/agent/challenge', body, { cache: false, skipAuth: true });
664
+ const response = await this.ctx.request('POST', '/auth/agent/challenge', body, {
665
+ cache: false,
666
+ skipAuth: true,
667
+ });
656
668
  return agentProofClaimsSchema.parse(response);
657
669
  }
658
670
  async verify(publicKey, proof) {
659
671
  const body = agentVerifyRequestSchema.parse({ publicKey, ...proof });
660
- const response = await this.ctx.request('POST', '/auth/agent/verify', body, { cache: false, skipAuth: true });
672
+ const response = await this.ctx.request('POST', '/auth/agent/verify', body, {
673
+ cache: false,
674
+ skipAuth: true,
675
+ });
661
676
  return plantSession(this.ctx, response, 'auth/agent/verify');
662
677
  }
663
678
  }
@@ -859,7 +874,10 @@ export class AuthApi {
859
874
  */
860
875
  async checkUsername(username) {
861
876
  // Public availability lookup (pre-session) — skip the bearer preflight.
862
- return this.ctx.request('GET', `/auth/check-username/${username}`, undefined, { cache: false, skipAuth: true });
877
+ return this.ctx.request('GET', `/auth/check-username/${username}`, undefined, {
878
+ cache: false,
879
+ skipAuth: true,
880
+ });
863
881
  }
864
882
  /**
865
883
  * The authenticator's code (or a backup code) for a first factor's
@@ -877,7 +895,9 @@ export class AuthApi {
877
895
  return plantSession(this.ctx, res, 'auth/signup');
878
896
  }
879
897
  async methods() {
880
- const res = await this.ctx.request('GET', '/users/me/sign-in-methods', undefined, { cache: false });
898
+ const res = await this.ctx.request('GET', '/users/me/sign-in-methods', undefined, {
899
+ cache: false,
900
+ });
881
901
  const parsed = safeParseContract(signInMethodsSchema, res);
882
902
  if (!parsed)
883
903
  throw new Error('users/me/sign-in-methods returned an unexpected response shape');
@@ -1,4 +1,4 @@
1
- import { personalPlanCheckoutRequestSchema, personalPlanCheckoutResultSchema } from '@oxy.so/contracts';
1
+ import { personalPlanCheckoutRequestSchema, personalPlanCheckoutResultSchema, } from '@oxy.so/contracts';
2
2
  /**
3
3
  * `oxy.billing` — the signed-in user's subscription, wallet and payment history.
4
4
  *
@@ -24,7 +24,9 @@ export class BillingApi {
24
24
  }
25
25
  /** Public versioned personal plans. Discovery never proves customer access. */
26
26
  async personalPlans() {
27
- return personalPlanCatalogueSchema.parse(await this.ctx.request('GET', '/billing/personal-plans', undefined, { cache: false }));
27
+ return personalPlanCatalogueSchema.parse(await this.ctx.request('GET', '/billing/personal-plans', undefined, {
28
+ cache: false,
29
+ }));
28
30
  }
29
31
  /** Product rights only; requires a production application-bound user session. Never cached. */
30
32
  async productAccess(query) {
@@ -34,19 +36,29 @@ export class BillingApi {
34
36
  }
35
37
  /** Named commercial sources for the current subject; no inferred plan collapse. */
36
38
  async productSubscriptions(expectedSubjectAccountId) {
37
- return productSubscriptionsResponseSchema.parse(await this.ctx.request("GET", expectedSubjectAccountId ? `/billing/product-subscriptions?expectedSubjectAccountId=${encodeURIComponent(expectedSubjectAccountId)}` : "/billing/product-subscriptions", undefined, { cache: false })).subscriptions;
39
+ return productSubscriptionsResponseSchema.parse(await this.ctx.request('GET', expectedSubjectAccountId
40
+ ? `/billing/product-subscriptions?expectedSubjectAccountId=${encodeURIComponent(expectedSubjectAccountId)}`
41
+ : '/billing/product-subscriptions', undefined, { cache: false })).subscriptions;
38
42
  }
39
43
  /** Per-grant credit provenance; no interpretation of the historical mixed balance. */
40
44
  async creditGrants() {
41
- return subscriptionCreditGrantsResponseSchema.parse(await this.ctx.request("GET", "/billing/credit-grants", undefined, { cache: false })).grants;
45
+ return subscriptionCreditGrantsResponseSchema.parse(await this.ctx.request('GET', '/billing/credit-grants', undefined, { cache: false })).grants;
42
46
  }
43
47
  /** Payer-only named-source cancellation. Resolves on provider acceptance, including pending local reconciliation. Use cancelProductSubscriptionWithStatus for detailed completion state. */
44
48
  async cancelProductSubscription(sourceId, expectedSubjectAccountId, actionId) {
45
- await this.ctx.request("POST", "/billing/product-subscriptions/cancel", cancelProductSubscriptionSchema.parse({ sourceId, ...(actionId ? { actionId } : {}), ...(expectedSubjectAccountId ? { expectedSubjectAccountId } : {}) }), { cache: false });
49
+ await this.ctx.request('POST', '/billing/product-subscriptions/cancel', cancelProductSubscriptionSchema.parse({
50
+ sourceId,
51
+ ...(actionId ? { actionId } : {}),
52
+ ...(expectedSubjectAccountId ? { expectedSubjectAccountId } : {}),
53
+ }), { cache: false });
46
54
  }
47
55
  /** Provider acceptance versus completed local cancellation, for user-facing flows. */
48
56
  async cancelProductSubscriptionWithStatus(sourceId, expectedSubjectAccountId, actionId) {
49
- return productSubscriptionCancellationResultSchema.parse(await this.ctx.request('POST', '/billing/product-subscriptions/cancel', cancelProductSubscriptionSchema.parse({ sourceId, ...(actionId ? { actionId } : {}), ...(expectedSubjectAccountId ? { expectedSubjectAccountId } : {}) }), { cache: false }));
57
+ return productSubscriptionCancellationResultSchema.parse(await this.ctx.request('POST', '/billing/product-subscriptions/cancel', cancelProductSubscriptionSchema.parse({
58
+ sourceId,
59
+ ...(actionId ? { actionId } : {}),
60
+ ...(expectedSubjectAccountId ? { expectedSubjectAccountId } : {}),
61
+ }), { cache: false }));
50
62
  }
51
63
  /** The signed-in user's payment history. Never cached. */
52
64
  async payments() {
@@ -63,7 +75,10 @@ export class BillingApi {
63
75
  /** A user's wallet (default: the signed-in user's). Cached briefly: the balance moves. */
64
76
  async wallet(userId) {
65
77
  const id = this.resolveUserId(userId);
66
- return this.ctx.request('GET', `/wallet/${id}`, undefined, { cache: true, cacheTTL: WALLET_TTL });
78
+ return this.ctx.request('GET', `/wallet/${id}`, undefined, {
79
+ cache: true,
80
+ cacheTTL: WALLET_TTL,
81
+ });
67
82
  }
68
83
  /** A page of a user's wallet transactions (default: the signed-in user's). Never cached. */
69
84
  async walletTransactions(options = {}) {
@@ -73,7 +88,9 @@ export class BillingApi {
73
88
  params.limit = options.limit;
74
89
  if (options.offset)
75
90
  params.offset = options.offset;
76
- return this.ctx.request('GET', `/wallet/transactions/${id}`, params, { cache: false });
91
+ return this.ctx.request('GET', `/wallet/transactions/${id}`, params, {
92
+ cache: false,
93
+ });
77
94
  }
78
95
  resolveUserId(userId) {
79
96
  const id = userId || this.ctx.oxy.session.userId;
@@ -91,7 +91,9 @@ export class CivicApi {
91
91
  ...(input.geohash !== undefined ? { geohash: input.geohash } : {}),
92
92
  ...(input.biometricOk !== undefined ? { biometricOk: input.biometricOk } : {}),
93
93
  }, { collection: ATTEST_COLLECTION, rkey: input.nonce });
94
- return this.ctx.request('POST', '/civic/attestations', envelope, { cache: false });
94
+ return this.ctx.request('POST', '/civic/attestations', envelope, {
95
+ cache: false,
96
+ });
95
97
  }
96
98
  /**
97
99
  * Vouch that another user is a real person as the VOUCHER (B): sign a
@@ -187,7 +189,9 @@ export class CivicCredentialsApi {
187
189
  * base type; an `expiresAt` ISO string becomes epoch ms. NATIVE-ONLY.
188
190
  */
189
191
  async issue(input) {
190
- const types = input.types.includes(CREDENTIAL_BASE_TYPE) ? input.types : [CREDENTIAL_BASE_TYPE, ...input.types];
192
+ const types = input.types.includes(CREDENTIAL_BASE_TYPE)
193
+ ? input.types
194
+ : [CREDENTIAL_BASE_TYPE, ...input.types];
191
195
  let expiresAtMs;
192
196
  if (input.expiresAt !== undefined) {
193
197
  const parsed = Date.parse(input.expiresAt);
@@ -205,7 +209,10 @@ export class CivicCredentialsApi {
205
209
  // A fresh crypto-random rkey: every credential is its own chain entry.
206
210
  const { SignatureService } = await import('../crypto/internal.js');
207
211
  const rkey = await SignatureService.generateChallenge();
208
- const envelope = await signOwnChainRecord(this.ctx, 'credential', record, { collection: CREDENTIAL_COLLECTION, rkey });
212
+ const envelope = await signOwnChainRecord(this.ctx, 'credential', record, {
213
+ collection: CREDENTIAL_COLLECTION,
214
+ rkey,
215
+ });
209
216
  const result = await this.ctx.request('POST', '/civic/credentials', envelope, { cache: false });
210
217
  this.sweep();
211
218
  return result;
@@ -223,7 +230,10 @@ export class CivicCredentialsApi {
223
230
  }
224
231
  const base = `/civic/credentials/${encodeURIComponent(holder)}`;
225
232
  const url = opts.status ? `${base}?status=${encodeURIComponent(opts.status)}` : base;
226
- return this.ctx.request('GET', url, undefined, { cache: true, cacheTTL: SHORT_TTL });
233
+ return this.ctx.request('GET', url, undefined, {
234
+ cache: true,
235
+ cacheTTL: SHORT_TTL,
236
+ });
227
237
  }
228
238
  /**
229
239
  * Verify a credential by its signed-record id: the server re-checks the