@oxyhq/core 12.9.0 → 12.10.1

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 (106) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/HttpService.js +22 -12
  3. package/dist/cjs/crypto/keyManager.js +89 -0
  4. package/dist/cjs/i18n/locales/ar-SA.json +4 -0
  5. package/dist/cjs/i18n/locales/ca-ES.json +4 -0
  6. package/dist/cjs/i18n/locales/de-DE.json +4 -0
  7. package/dist/cjs/i18n/locales/en-US.json +69 -3
  8. package/dist/cjs/i18n/locales/es-ES.json +68 -2
  9. package/dist/cjs/i18n/locales/fr-FR.json +4 -0
  10. package/dist/cjs/i18n/locales/it-IT.json +4 -0
  11. package/dist/cjs/i18n/locales/ja-JP.json +4 -0
  12. package/dist/cjs/i18n/locales/ko-KR.json +4 -0
  13. package/dist/cjs/i18n/locales/locales/ar-SA.json +4 -0
  14. package/dist/cjs/i18n/locales/locales/ca-ES.json +4 -0
  15. package/dist/cjs/i18n/locales/locales/de-DE.json +4 -0
  16. package/dist/cjs/i18n/locales/locales/en-US.json +69 -3
  17. package/dist/cjs/i18n/locales/locales/es-ES.json +68 -2
  18. package/dist/cjs/i18n/locales/locales/fr-FR.json +4 -0
  19. package/dist/cjs/i18n/locales/locales/it-IT.json +4 -0
  20. package/dist/cjs/i18n/locales/locales/ja-JP.json +4 -0
  21. package/dist/cjs/i18n/locales/locales/ko-KR.json +4 -0
  22. package/dist/cjs/i18n/locales/locales/pt-PT.json +4 -0
  23. package/dist/cjs/i18n/locales/locales/zh-CN.json +4 -0
  24. package/dist/cjs/i18n/locales/pt-PT.json +4 -0
  25. package/dist/cjs/i18n/locales/zh-CN.json +4 -0
  26. package/dist/cjs/index.js +7 -4
  27. package/dist/cjs/mixins/OxyServices.auth.js +51 -20
  28. package/dist/cjs/mixins/OxyServices.connectedApps.js +6 -1
  29. package/dist/cjs/mixins/OxyServices.deviceBoot.js +9 -2
  30. package/dist/cjs/mixins/OxyServices.identityBackup.js +11 -0
  31. package/dist/cjs/mixins/OxyServices.user.js +6 -0
  32. package/dist/cjs/session/accountDialogController.js +7 -5
  33. package/dist/cjs/utils/commonsApproval.js +31 -0
  34. package/dist/esm/.tsbuildinfo +1 -1
  35. package/dist/esm/HttpService.js +22 -12
  36. package/dist/esm/crypto/keyManager.js +89 -0
  37. package/dist/esm/i18n/locales/ar-SA.json +4 -0
  38. package/dist/esm/i18n/locales/ca-ES.json +4 -0
  39. package/dist/esm/i18n/locales/de-DE.json +4 -0
  40. package/dist/esm/i18n/locales/en-US.json +69 -3
  41. package/dist/esm/i18n/locales/es-ES.json +68 -2
  42. package/dist/esm/i18n/locales/fr-FR.json +4 -0
  43. package/dist/esm/i18n/locales/it-IT.json +4 -0
  44. package/dist/esm/i18n/locales/ja-JP.json +4 -0
  45. package/dist/esm/i18n/locales/ko-KR.json +4 -0
  46. package/dist/esm/i18n/locales/locales/ar-SA.json +4 -0
  47. package/dist/esm/i18n/locales/locales/ca-ES.json +4 -0
  48. package/dist/esm/i18n/locales/locales/de-DE.json +4 -0
  49. package/dist/esm/i18n/locales/locales/en-US.json +69 -3
  50. package/dist/esm/i18n/locales/locales/es-ES.json +68 -2
  51. package/dist/esm/i18n/locales/locales/fr-FR.json +4 -0
  52. package/dist/esm/i18n/locales/locales/it-IT.json +4 -0
  53. package/dist/esm/i18n/locales/locales/ja-JP.json +4 -0
  54. package/dist/esm/i18n/locales/locales/ko-KR.json +4 -0
  55. package/dist/esm/i18n/locales/locales/pt-PT.json +4 -0
  56. package/dist/esm/i18n/locales/locales/zh-CN.json +4 -0
  57. package/dist/esm/i18n/locales/pt-PT.json +4 -0
  58. package/dist/esm/i18n/locales/zh-CN.json +4 -0
  59. package/dist/esm/index.js +2 -1
  60. package/dist/esm/mixins/OxyServices.auth.js +48 -19
  61. package/dist/esm/mixins/OxyServices.connectedApps.js +6 -1
  62. package/dist/esm/mixins/OxyServices.deviceBoot.js +9 -2
  63. package/dist/esm/mixins/OxyServices.identityBackup.js +11 -0
  64. package/dist/esm/mixins/OxyServices.user.js +6 -0
  65. package/dist/esm/session/accountDialogController.js +7 -5
  66. package/dist/esm/utils/commonsApproval.js +27 -0
  67. package/dist/types/.tsbuildinfo +1 -1
  68. package/dist/types/HttpService.d.ts +14 -0
  69. package/dist/types/crypto/keyManager.d.ts +33 -0
  70. package/dist/types/index.d.ts +2 -1
  71. package/dist/types/mixins/OxyServices.auth.d.ts +4 -4
  72. package/dist/types/session/accountDialogController.d.ts +7 -2
  73. package/dist/types/utils/commonsApproval.d.ts +13 -0
  74. package/package.json +3 -3
  75. package/src/HttpService.ts +37 -14
  76. package/src/__tests__/httpServiceAuthSelfAwait.test.ts +108 -0
  77. package/src/__tests__/httpServiceQueueDeadlock.test.ts +128 -0
  78. package/src/crypto/__tests__/keyManager.recoveryMnemonic.test.ts +138 -0
  79. package/src/crypto/keyManager.ts +99 -0
  80. package/src/i18n/locales/ar-SA.json +4 -0
  81. package/src/i18n/locales/ca-ES.json +4 -0
  82. package/src/i18n/locales/de-DE.json +4 -0
  83. package/src/i18n/locales/en-US.json +69 -3
  84. package/src/i18n/locales/es-ES.json +68 -2
  85. package/src/i18n/locales/fr-FR.json +4 -0
  86. package/src/i18n/locales/it-IT.json +4 -0
  87. package/src/i18n/locales/ja-JP.json +4 -0
  88. package/src/i18n/locales/ko-KR.json +4 -0
  89. package/src/i18n/locales/pt-PT.json +4 -0
  90. package/src/i18n/locales/zh-CN.json +4 -0
  91. package/src/index.ts +7 -1
  92. package/src/mixins/OxyServices.auth.ts +48 -24
  93. package/src/mixins/OxyServices.connectedApps.ts +6 -1
  94. package/src/mixins/OxyServices.deviceBoot.ts +7 -2
  95. package/src/mixins/OxyServices.identityBackup.ts +13 -0
  96. package/src/mixins/OxyServices.user.ts +6 -0
  97. package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +4 -2
  98. package/src/mixins/__tests__/commonsSignIn.test.ts +4 -4
  99. package/src/mixins/__tests__/identityBackup.test.ts +57 -0
  100. package/src/mixins/__tests__/preSessionSkipAuth.test.ts +152 -0
  101. package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +6 -0
  102. package/src/mixins/__tests__/webauthnAuth.test.ts +6 -6
  103. package/src/session/__tests__/accountDialogController.test.ts +3 -3
  104. package/src/session/accountDialogController.ts +7 -6
  105. package/src/utils/__tests__/commonsApproval.test.ts +60 -0
  106. package/src/utils/commonsApproval.ts +39 -0
@@ -163,7 +163,7 @@ describe('AccountDialogController — initial + views', () => {
163
163
  expect(snap.commonsAvailability).toBe('unknown');
164
164
  });
165
165
 
166
- it('setView / add / close move between views and notify subscribers', () => {
166
+ it('setView / add move between views and notify subscribers', () => {
167
167
  const { controller } = makeHarness();
168
168
  const seen: string[] = [];
169
169
  controller.subscribe((s) => seen.push(s.view));
@@ -172,7 +172,7 @@ describe('AccountDialogController — initial + views', () => {
172
172
  expect(controller.getSnapshot().view).toBe('add');
173
173
  controller.setView('signin');
174
174
  expect(controller.getSnapshot().view).toBe('signin');
175
- controller.close();
175
+ controller.setView('accounts');
176
176
  expect(controller.getSnapshot().view).toBe('accounts');
177
177
 
178
178
  expect(seen).toEqual(['add', 'signin', 'accounts']);
@@ -185,7 +185,7 @@ describe('AccountDialogController — initial + views', () => {
185
185
 
186
186
  controller.startSignup();
187
187
  expect(controller.getSnapshot().view).toBe('signup');
188
- controller.close();
188
+ controller.setView('accounts');
189
189
  expect(controller.getSnapshot().view).toBe('accounts');
190
190
 
191
191
  expect(seen).toEqual(['signup', 'accounts']);
@@ -35,6 +35,13 @@
35
35
  * password, social login, and 2FA were removed ecosystem-wide. Account
36
36
  * creation (`signup` view) is the same two identity backends: a passkey
37
37
  * ceremony on web, or a Commons-created identity.
38
+ *
39
+ * The controller owns NO surface PRESENTATION: whether the account dialog is
40
+ * mounted, visible, or dismissed is the job of the shared surface stack
41
+ * (`@oxyhq/services` presents the `AccountDialog` surface into `@oxyhq/bloom`'s
42
+ * stack). This is a headless state machine only — it exposes `setView` /
43
+ * `add` / `startSignup` (the view axis) and `cancelSignIn` (device-flow
44
+ * teardown), never an `open` / `close` / `visible`.
38
45
  */
39
46
 
40
47
  import type { OxyServices } from '../OxyServices';
@@ -462,12 +469,6 @@ export class AccountDialogController {
462
469
  this.emit();
463
470
  }
464
471
 
465
- /** Return to the account list and cancel any in-flight sign-in flow. */
466
- close(): void {
467
- this.cancelSignIn();
468
- this.setView('accounts');
469
- }
470
-
471
472
  /** Switch to the "add account" view (the sign-in entry chooser). */
472
473
  add(): void {
473
474
  this.setView('add');
@@ -0,0 +1,60 @@
1
+ import {
2
+ getCommonsApprovalBlockingReason,
3
+ parseCommonsApprovalExpiresAt,
4
+ } from '../commonsApproval';
5
+
6
+ describe('commonsApproval validation', () => {
7
+ const application = {
8
+ id: 'app1',
9
+ name: 'Mention',
10
+ type: 'first_party' as const,
11
+ isOfficial: true,
12
+ isInternal: false,
13
+ scopes: ['profile'],
14
+ };
15
+
16
+ it('blocks when the application is missing', () => {
17
+ expect(
18
+ getCommonsApprovalBlockingReason({
19
+ application: null,
20
+ status: 'pending',
21
+ expiresAt: Date.now() + 60_000,
22
+ }),
23
+ ).toMatch(/could not be resolved/i);
24
+ });
25
+
26
+ it('blocks non-pending sessions', () => {
27
+ expect(
28
+ getCommonsApprovalBlockingReason({
29
+ application,
30
+ status: 'expired',
31
+ expiresAt: Date.now() + 60_000,
32
+ }),
33
+ ).toMatch(/invalid, already used, or expired/i);
34
+ });
35
+
36
+ it('blocks expired pending sessions (ISO expiresAt)', () => {
37
+ expect(
38
+ getCommonsApprovalBlockingReason({
39
+ application,
40
+ status: 'pending',
41
+ expiresAt: new Date(Date.now() - 60_000).toISOString(),
42
+ }),
43
+ ).toMatch(/expired/i);
44
+ });
45
+
46
+ it('allows a pending, unexpired session', () => {
47
+ expect(
48
+ getCommonsApprovalBlockingReason({
49
+ application,
50
+ status: 'pending',
51
+ expiresAt: Date.now() + 60_000,
52
+ }),
53
+ ).toBeNull();
54
+ });
55
+
56
+ it('parses ISO expiresAt strings', () => {
57
+ const iso = '2026-07-19T12:00:00.000Z';
58
+ expect(parseCommonsApprovalExpiresAt(iso)).toBe(Date.parse(iso));
59
+ });
60
+ });
@@ -0,0 +1,39 @@
1
+ import type { PublicApplication } from '../mixins/OxyServices.connectedApps';
2
+
3
+ export interface CommonsApprovalValidationInput {
4
+ application: PublicApplication | null;
5
+ status: string;
6
+ expiresAt: number | string;
7
+ }
8
+
9
+ /**
10
+ * Returns a user-facing blocking reason when an approval payload must not be
11
+ * shown as actionable, or `null` when the request is still pending and valid.
12
+ */
13
+ export function getCommonsApprovalBlockingReason(
14
+ info: CommonsApprovalValidationInput,
15
+ ): string | null {
16
+ if (!info.application?.id) {
17
+ return 'The requesting application could not be resolved.';
18
+ }
19
+ if (info.status !== 'pending') {
20
+ return 'This sign-in request is invalid, already used, or expired.';
21
+ }
22
+ const expiresAtMs = parseCommonsApprovalExpiresAt(info.expiresAt);
23
+ if (expiresAtMs !== null && expiresAtMs < Date.now()) {
24
+ return 'This sign-in request has expired. Ask for a new QR code.';
25
+ }
26
+ return null;
27
+ }
28
+
29
+ /** Normalize API `expiresAt` (number or ISO string) to epoch ms. */
30
+ export function parseCommonsApprovalExpiresAt(
31
+ expiresAt: CommonsApprovalValidationInput['expiresAt'],
32
+ ): number | null {
33
+ if (typeof expiresAt === 'number' && Number.isFinite(expiresAt)) return expiresAt;
34
+ if (typeof expiresAt === 'string') {
35
+ const ms = Date.parse(expiresAt);
36
+ return Number.isFinite(ms) ? ms : null;
37
+ }
38
+ return null;
39
+ }