@oxyhq/core 12.1.0 → 12.2.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 (66) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/i18n/locales/ar-SA.json +27 -2
  3. package/dist/cjs/i18n/locales/ca-ES.json +27 -2
  4. package/dist/cjs/i18n/locales/de-DE.json +27 -2
  5. package/dist/cjs/i18n/locales/en-US.json +26 -3
  6. package/dist/cjs/i18n/locales/es-ES.json +26 -3
  7. package/dist/cjs/i18n/locales/fr-FR.json +27 -2
  8. package/dist/cjs/i18n/locales/it-IT.json +27 -2
  9. package/dist/cjs/i18n/locales/ja-JP.json +27 -2
  10. package/dist/cjs/i18n/locales/ko-KR.json +27 -2
  11. package/dist/cjs/i18n/locales/locales/ar-SA.json +27 -2
  12. package/dist/cjs/i18n/locales/locales/ca-ES.json +27 -2
  13. package/dist/cjs/i18n/locales/locales/de-DE.json +27 -2
  14. package/dist/cjs/i18n/locales/locales/en-US.json +26 -3
  15. package/dist/cjs/i18n/locales/locales/es-ES.json +26 -3
  16. package/dist/cjs/i18n/locales/locales/fr-FR.json +27 -2
  17. package/dist/cjs/i18n/locales/locales/it-IT.json +27 -2
  18. package/dist/cjs/i18n/locales/locales/ja-JP.json +27 -2
  19. package/dist/cjs/i18n/locales/locales/ko-KR.json +27 -2
  20. package/dist/cjs/i18n/locales/locales/pt-PT.json +27 -2
  21. package/dist/cjs/i18n/locales/locales/zh-CN.json +27 -2
  22. package/dist/cjs/i18n/locales/pt-PT.json +27 -2
  23. package/dist/cjs/i18n/locales/zh-CN.json +27 -2
  24. package/dist/cjs/session/accountDialogController.js +112 -2
  25. package/dist/esm/.tsbuildinfo +1 -1
  26. package/dist/esm/i18n/locales/ar-SA.json +27 -2
  27. package/dist/esm/i18n/locales/ca-ES.json +27 -2
  28. package/dist/esm/i18n/locales/de-DE.json +27 -2
  29. package/dist/esm/i18n/locales/en-US.json +26 -3
  30. package/dist/esm/i18n/locales/es-ES.json +26 -3
  31. package/dist/esm/i18n/locales/fr-FR.json +27 -2
  32. package/dist/esm/i18n/locales/it-IT.json +27 -2
  33. package/dist/esm/i18n/locales/ja-JP.json +27 -2
  34. package/dist/esm/i18n/locales/ko-KR.json +27 -2
  35. package/dist/esm/i18n/locales/locales/ar-SA.json +27 -2
  36. package/dist/esm/i18n/locales/locales/ca-ES.json +27 -2
  37. package/dist/esm/i18n/locales/locales/de-DE.json +27 -2
  38. package/dist/esm/i18n/locales/locales/en-US.json +26 -3
  39. package/dist/esm/i18n/locales/locales/es-ES.json +26 -3
  40. package/dist/esm/i18n/locales/locales/fr-FR.json +27 -2
  41. package/dist/esm/i18n/locales/locales/it-IT.json +27 -2
  42. package/dist/esm/i18n/locales/locales/ja-JP.json +27 -2
  43. package/dist/esm/i18n/locales/locales/ko-KR.json +27 -2
  44. package/dist/esm/i18n/locales/locales/pt-PT.json +27 -2
  45. package/dist/esm/i18n/locales/locales/zh-CN.json +27 -2
  46. package/dist/esm/i18n/locales/pt-PT.json +27 -2
  47. package/dist/esm/i18n/locales/zh-CN.json +27 -2
  48. package/dist/esm/session/accountDialogController.js +112 -2
  49. package/dist/types/.tsbuildinfo +1 -1
  50. package/dist/types/index.d.ts +1 -1
  51. package/dist/types/session/accountDialogController.d.ts +81 -1
  52. package/package.json +4 -4
  53. package/src/i18n/locales/ar-SA.json +27 -2
  54. package/src/i18n/locales/ca-ES.json +27 -2
  55. package/src/i18n/locales/de-DE.json +27 -2
  56. package/src/i18n/locales/en-US.json +26 -3
  57. package/src/i18n/locales/es-ES.json +26 -3
  58. package/src/i18n/locales/fr-FR.json +27 -2
  59. package/src/i18n/locales/it-IT.json +27 -2
  60. package/src/i18n/locales/ja-JP.json +27 -2
  61. package/src/i18n/locales/ko-KR.json +27 -2
  62. package/src/i18n/locales/pt-PT.json +27 -2
  63. package/src/i18n/locales/zh-CN.json +27 -2
  64. package/src/index.ts +1 -0
  65. package/src/session/__tests__/accountDialogController.test.ts +133 -1
  66. package/src/session/accountDialogController.ts +145 -2
@@ -99,7 +99,7 @@ export { deviceStateToClientSessions, activeSessionIdOf, activeUserOf, accountId
99
99
  export { projectSwitchableAccounts, switchableAccountIds, } from './session/accountProjection';
100
100
  export type { SwitchableAccount, SwitchableAccountUser, ProjectSwitchableAccountsInput, } from './session/accountProjection';
101
101
  export { AccountDialogController, createAccountDialogController, } from './session/accountDialogController';
102
- export type { AccountDialogControllerOptions, AccountDialogSnapshot, AccountDialogView, CommonsAvailability, SignInFlowPhase, SignInFlowState, } from './session/accountDialogController';
102
+ export type { AccountDialogControllerOptions, AccountDialogSnapshot, AccountDialogView, CommonsAvailability, PopupWindowHandle, SignInFlowPhase, SignInFlowState, } from './session/accountDialogController';
103
103
  export { createWebAuthStateStore, createNativeAuthStateStore, createMemoryAuthStateStore, AUTH_STATE_STORAGE_KEY, } from './session/authStateStore';
104
104
  export type { PersistedAuthState, AuthStateStore, NativeKeyValueStorage, } from './session/authStateStore';
105
105
  export { refreshPersistedSession, refreshDeviceSecretArm, createAuthRefreshHandler, installAuthRefreshHandler, startTokenRefreshScheduler, TOKEN_REFRESH_LEAD_MS, } from './session/refresh';
@@ -24,6 +24,12 @@
24
24
  * - `commonsAvailability` — whether Commons is installed on this device
25
25
  * (native only, via the injected `canOpenApp` probe), so the QR view can
26
26
  * offer a "Get Commons" fallback instead of a same-device dead end.
27
+ * - `startPasskeyHubSignIn` — on a non-Oxy web origin (where a WebAuthn
28
+ * ceremony can't run locally, the RP-ID is bound to oxy.so), open a popup
29
+ * at the auth.oxy.so passkey hub instead, scoped to the SAME device-flow
30
+ * session `showQr` creates, and complete it via the SAME poll/socket/claim
31
+ * engine. Falls back to `showQr`'s plain QR rendering if the popup is
32
+ * blocked.
27
33
  *
28
34
  * Sign-in is passkey (WebAuthn) or the Commons QR / shared-keychain handoff —
29
35
  * password, social login, and 2FA were removed ecosystem-wide. Account
@@ -51,6 +57,21 @@ export type AccountDialogView = 'accounts' | 'signin' | 'qr' | 'add' | 'signup';
51
57
  export type CommonsAvailability = 'unknown' | 'checking' | 'available' | 'unavailable';
52
58
  /** Lifecycle phase of the "Sign in with Oxy" device flow. */
53
59
  export type SignInFlowPhase = 'idle' | 'starting' | 'waiting' | 'authorized' | 'error';
60
+ /**
61
+ * Minimal structural handle over a popup `Window` — just enough for the
62
+ * cross-origin passkey hub flow ({@link AccountDialogController.startPasskeyHubSignIn}):
63
+ * navigate it once the device-flow session's `authorizeCode` is known, detect
64
+ * the user closing it early (`closed`), and close it programmatically on
65
+ * completion/failure. Satisfied directly by `window.open()`'s return value on
66
+ * web; native has no popup concept and never injects an opener.
67
+ */
68
+ export interface PopupWindowHandle {
69
+ readonly closed: boolean;
70
+ close(): void;
71
+ location: {
72
+ href: string;
73
+ };
74
+ }
54
75
  /** State of the "Sign in with Oxy" (shared-key / QR) device flow. */
55
76
  export interface SignInFlowState {
56
77
  phase: SignInFlowPhase;
@@ -166,6 +187,20 @@ export interface AccountDialogControllerOptions {
166
187
  * `showQr` behaves exactly as before (render QR only).
167
188
  */
168
189
  canOpenApp?: (url: string) => Promise<boolean>;
190
+ /**
191
+ * Open a new, empty popup window SYNCHRONOUSLY (before any `await`) so the
192
+ * browser attributes it to the click gesture that triggered it, returning a
193
+ * handle to navigate once the device-flow session is known — or `null` if
194
+ * the popup was blocked. Injected by the provider (web only:
195
+ * `window.open('', ...)`; absent on native, where the hub-popup flow does
196
+ * not apply). Used by {@link AccountDialogController.startPasskeyHubSignIn}.
197
+ */
198
+ openPopup?: () => PopupWindowHandle | null;
199
+ /**
200
+ * Base origin of the auth.oxy.so passkey hub (defaults to
201
+ * `https://auth.${CENTRAL_IDP_APEX}`). Overridable for local/staging testing.
202
+ */
203
+ hubBaseUrl?: string;
169
204
  }
170
205
  type SnapshotListener = (snapshot: AccountDialogSnapshot) => void;
171
206
  export declare class AccountDialogController {
@@ -180,6 +215,8 @@ export declare class AccountDialogController {
180
215
  private readonly openUrl?;
181
216
  private readonly canOpenApp?;
182
217
  private readonly socketFactory?;
218
+ private readonly openPopup?;
219
+ private readonly hubBaseUrl;
183
220
  private readonly listeners;
184
221
  private view;
185
222
  private graph;
@@ -204,6 +241,10 @@ export declare class AccountDialogController {
204
241
  * single-use token concurrently.
205
242
  */
206
243
  private pollInFlight;
244
+ /** The popup opened by {@link startPasskeyHubSignIn}, or `null`. */
245
+ private activePopup;
246
+ /** Watches {@link activePopup}'s `closed` state; see {@link watchPopup}. */
247
+ private popupWatchTimer;
207
248
  private unsubscribeSession;
208
249
  private unsubscribeTokens;
209
250
  /** Last-observed SDK auth readiness (a planted bearer). Drives the fetch edge. */
@@ -303,6 +344,45 @@ export declare class AccountDialogController {
303
344
  * session committed. Requires `clientId`.
304
345
  */
305
346
  showQr(): Promise<void>;
347
+ /**
348
+ * Web-only: "Sign in with a passkey" on a non-Oxy origin cannot run the
349
+ * WebAuthn ceremony locally — a credential minted with `WEBAUTHN_RP_ID=oxy.so`
350
+ * can only be asserted from `oxy.so`/a subdomain/loopback, a browser-enforced
351
+ * boundary `isOxyRpOrigin()` (consumer-side) already gates on. Instead, open
352
+ * a popup at the auth.oxy.so passkey hub, scoped to the SAME device-flow
353
+ * session {@link showQr} would create (same `authorizeCode`/`sessionToken`
354
+ * pair), and let the SAME poll/socket/claim engine complete it once the hub
355
+ * authorizes the session (`POST /auth/session/authorize-code/:authorizeCode`,
356
+ * bearer-authed, server-side — this method never sees or transmits the
357
+ * secret `sessionToken`).
358
+ *
359
+ * The popup MUST be opened synchronously, before any `await`, or the
360
+ * browser's popup blocker loses the click-gesture attribution and silently
361
+ * blocks it — so {@link openPopup} is invoked as the very first step, before
362
+ * the device-flow session (which needs an async call) even exists. If the
363
+ * popup is blocked (or no `openPopup` was injected), this falls back to
364
+ * `showQr`'s plain QR rendering — no dead end.
365
+ */
366
+ startPasskeyHubSignIn(): Promise<void>;
367
+ /**
368
+ * Shared device-flow session creation for both {@link showQr} (renders the
369
+ * QR) and {@link startPasskeyHubSignIn} (also opens the hub popup) — the
370
+ * same `startCommonsSignIn` → poll/socket wiring either way. Returns the
371
+ * handle on success (already reflected in `signIn`), or `null` on failure
372
+ * (already set as `signIn.error`).
373
+ */
374
+ private startDeviceFlowSession;
375
+ /**
376
+ * Poll {@link PopupWindowHandle.closed} so a user who dismisses the hub
377
+ * popup without completing sign-in gets prompt feedback (there is no DOM
378
+ * event for a cross-origin popup closing — polling is the only mechanism).
379
+ * Cleared by {@link closeActivePopup}, which every sign-in exit path already
380
+ * calls.
381
+ */
382
+ private watchPopup;
383
+ private clearPopupWatchTimer;
384
+ /** Tear down the popup watch timer and close the popup, if any. Idempotent. */
385
+ private closeActivePopup;
306
386
  /**
307
387
  * Resolve whether Commons is installed on this device via the injected
308
388
  * `canOpenApp` probe, updating {@link commonsAvailability} as durable,
@@ -323,7 +403,7 @@ export declare class AccountDialogController {
323
403
  * fallback stays live regardless of the outcome here.
324
404
  */
325
405
  private deepLinkIntoCommonsIfAvailable;
326
- /** Tear down the active sign-in device flow (timers + socket + token) and reset to idle. */
406
+ /** Tear down the active sign-in device flow (timers + socket + popup + token) and reset to idle. */
327
407
  cancelSignIn(): void;
328
408
  private scheduleNextPoll;
329
409
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/core",
3
- "version": "12.1.0",
3
+ "version": "12.2.0",
4
4
  "description": "OxyHQ SDK Foundation — API client, authentication, cryptographic identity, and shared utilities",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -117,7 +117,7 @@
117
117
  "invariant": "^2.2.4",
118
118
  "jwt-decode": "^4.0.0",
119
119
  "socket.io-client": "^4.8.1",
120
- "tldts": "^7.4.5",
120
+ "tldts": "^7.4.8",
121
121
  "zod": "^3.25.64"
122
122
  },
123
123
  "peerDependencies": {
@@ -147,10 +147,10 @@
147
147
  "@types/elliptic": "^6.4.18",
148
148
  "@types/express": "^4.17.21",
149
149
  "@types/invariant": "^2.2.34",
150
- "@types/node": "^20.19.9",
150
+ "@types/node": "^20.19.43",
151
151
  "expo-crypto": "~56.0.3",
152
152
  "expo-secure-store": "~56.0.4",
153
- "express": "^4.21.2",
153
+ "express": "^4.22.2",
154
154
  "express-rate-limit": "^7.5.0",
155
155
  "release-it": "^19.0.6",
156
156
  "typescript": "^5.9.2"
@@ -43,11 +43,26 @@
43
43
  "currentAccount": "الحالي",
44
44
  "or": "أو",
45
45
  "viewAllAccounts": "عرض {{count}} المزيد",
46
+ "createAccountLink": "جديد على Oxy؟ أنشئ حسابًا",
46
47
  "status": {
47
- "accountSwitched": "استخدام {{name}} الآن"
48
+ "accountSwitched": "استخدام {{name}} الآن",
49
+ "signingIn": "جارٍ تسجيل الدخول…"
48
50
  }
49
51
  },
50
52
  "signup": {
53
+ "commonsHeadline": "أنشئ هويتك في Commons",
54
+ "commonsExplainer": "‏Commons هي هوية Oxy الخاصة بك بحفظ ذاتي كامل — تطبيق واحد يعمل في كل مكان.",
55
+ "createInCommons": "أنشئ هويتك في Commons",
56
+ "passkeyAlternative": "لا تملك Commons؟ أنشئ مفتاح مرور على هذا الجهاز بدلاً من ذلك",
57
+ "createAccount": "إنشاء حساب",
58
+ "creating": "جارٍ الإنشاء…",
59
+ "usernamePlaceholder": "اختر اسم مستخدم",
60
+ "usernameChecking": "جارٍ التحقق…",
61
+ "usernameAvailable": "متاح",
62
+ "usernameTaken": "اسم المستخدم هذا مستخدم بالفعل",
63
+ "backToSignInLink": "لديك حساب بالفعل؟ سجّل الدخول",
64
+ "hubExplainer": "أنشئ هوية Oxy الخاصة بك في نافذة آمنة، ثم عد إلى هنا مباشرة.",
65
+ "continueInWindow": "المتابعة في نافذة جديدة",
51
66
  "welcome": {
52
67
  "title": "مرحبًا بك في Oxy!",
53
68
  "subtitle": "أنشئ حسابك في خطوات قليلة",
@@ -94,6 +109,15 @@
94
109
  "legalReminder": "بإنشاء حساب، فإنك توافق على شروط الخدمة وسياسة الخصوصية الخاصة بنا."
95
110
  }
96
111
  },
112
+ "accountSwitcher": {
113
+ "qrHeadline": "سجّل الدخول بهوية Oxy الخاصة بك",
114
+ "signInWithOxy": "تسجيل الدخول باستخدام Oxy",
115
+ "useIdentityOnDevice": "لا تملك Commons؟ استخدم مفتاح مرور على هذا الجهاز بدلاً من ذلك",
116
+ "passkeySigningIn": "جارٍ تسجيل الدخول…",
117
+ "getCommons": "احصل على Commons",
118
+ "commonsNotInstalled": "لا تملك Commons؟ احصل على التطبيق لتسجيل الدخول بمعرّف Oxy الخاص بك.",
119
+ "showQrAnyway": "لدي Commons على جهاز آخر"
120
+ },
97
121
  "common": {
98
122
  "actions": {
99
123
  "back": "رجوع",
@@ -105,7 +129,8 @@
105
129
  "verify": "التحقق",
106
130
  "resetPassword": "إعادة تعيين كلمة المرور",
107
131
  "signedOut": "تم تسجيل الخروج",
108
- "close": "إغلاق"
132
+ "close": "إغلاق",
133
+ "tryAgain": "حاول مرة أخرى"
109
134
  },
110
135
  "links": {
111
136
  "recoverAccount": "استعادة حسابك",
@@ -43,11 +43,26 @@
43
43
  "currentAccount": "Actual",
44
44
  "or": "o",
45
45
  "viewAllAccounts": "Veure {{count}} més",
46
+ "createAccountLink": "Ets nou a Oxy? Crea'n una",
46
47
  "status": {
47
- "accountSwitched": "Ara utilitzant {{name}}"
48
+ "accountSwitched": "Ara utilitzant {{name}}",
49
+ "signingIn": "Iniciant sessió…"
48
50
  }
49
51
  },
50
52
  "signup": {
53
+ "commonsHeadline": "Crea la teva identitat a Commons",
54
+ "commonsExplainer": "Commons és la teva identitat d'Oxy amb autocustòdia completa: una app que funciona a tot arreu.",
55
+ "createInCommons": "Crea la teva identitat a Commons",
56
+ "passkeyAlternative": "No tens Commons? Crea una clau d'accés en aquest dispositiu",
57
+ "createAccount": "Crear compte",
58
+ "creating": "Creant…",
59
+ "usernamePlaceholder": "Tria un nom d'usuari",
60
+ "usernameChecking": "Comprovant…",
61
+ "usernameAvailable": "Disponible",
62
+ "usernameTaken": "Aquest nom d'usuari ja està en ús",
63
+ "backToSignInLink": "Ja tens compte? Inicia sessió",
64
+ "hubExplainer": "Crea la teva Oxy ID en una finestra segura i torna de seguida.",
65
+ "continueInWindow": "Continua en una finestra nova",
51
66
  "welcome": {
52
67
  "title": "Benvingut a Oxy!",
53
68
  "subtitle": "Crea el teu compte en pocs passos",
@@ -94,6 +109,15 @@
94
109
  "legalReminder": "En crear un compte, acceptes els nostres Termes de servei i Política de privacitat."
95
110
  }
96
111
  },
112
+ "accountSwitcher": {
113
+ "qrHeadline": "Inicia sessió amb la teva identitat d'Oxy",
114
+ "signInWithOxy": "Inicia sessió amb Oxy",
115
+ "useIdentityOnDevice": "No tens Commons? Fes servir una clau d'accés en aquest dispositiu",
116
+ "passkeySigningIn": "Iniciant sessió…",
117
+ "getCommons": "Descarrega Commons",
118
+ "commonsNotInstalled": "No tens Commons? Descarrega l'app per iniciar sessió amb el teu Oxy ID.",
119
+ "showQrAnyway": "Tinc Commons en un altre dispositiu"
120
+ },
97
121
  "common": {
98
122
  "actions": {
99
123
  "back": "Enrere",
@@ -105,7 +129,8 @@
105
129
  "verify": "Verificar",
106
130
  "resetPassword": "Restablir contrasenya",
107
131
  "signedOut": "Sessió tancada",
108
- "close": "Tanca"
132
+ "close": "Tanca",
133
+ "tryAgain": "Torna-ho a provar"
109
134
  },
110
135
  "links": {
111
136
  "recoverAccount": "Recuperar el teu compte",
@@ -43,11 +43,26 @@
43
43
  "currentAccount": "Aktuell",
44
44
  "or": "oder",
45
45
  "viewAllAccounts": "{{count}} weitere anzeigen",
46
+ "createAccountLink": "Neu bei Oxy? Konto erstellen",
46
47
  "status": {
47
- "accountSwitched": "Verwende jetzt {{name}}"
48
+ "accountSwitched": "Verwende jetzt {{name}}",
49
+ "signingIn": "Anmeldung läuft…"
48
50
  }
49
51
  },
50
52
  "signup": {
53
+ "commonsHeadline": "Erstellen Sie Ihre Identität in Commons",
54
+ "commonsExplainer": "Commons ist Ihre vollständig selbstverwaltete Oxy-Identität – eine App, überall einsetzbar.",
55
+ "createInCommons": "Erstellen Sie Ihre Identität in Commons",
56
+ "passkeyAlternative": "Kein Commons? Erstellen Sie stattdessen einen Passkey auf diesem Gerät",
57
+ "createAccount": "Konto erstellen",
58
+ "creating": "Wird erstellt…",
59
+ "usernamePlaceholder": "Benutzernamen wählen",
60
+ "usernameChecking": "Wird geprüft…",
61
+ "usernameAvailable": "Verfügbar",
62
+ "usernameTaken": "Dieser Benutzername ist bereits vergeben",
63
+ "backToSignInLink": "Sie haben bereits ein Konto? Anmelden",
64
+ "hubExplainer": "Erstellen Sie Ihre Oxy-ID in einem sicheren Fenster und kehren Sie dann direkt zurück.",
65
+ "continueInWindow": "In einem neuen Fenster fortfahren",
51
66
  "welcome": {
52
67
  "title": "Willkommen bei Oxy!",
53
68
  "subtitle": "Erstellen Sie Ihr Konto in nur wenigen Schritten",
@@ -94,6 +109,15 @@
94
109
  "legalReminder": "Durch die Erstellung eines Kontos stimmen Sie unseren Nutzungsbedingungen und der Datenschutzrichtlinie zu."
95
110
  }
96
111
  },
112
+ "accountSwitcher": {
113
+ "qrHeadline": "Melden Sie sich mit Ihrer Oxy-Identität an",
114
+ "signInWithOxy": "Mit Oxy anmelden",
115
+ "useIdentityOnDevice": "Kein Commons? Verwenden Sie stattdessen einen Passkey auf diesem Gerät",
116
+ "passkeySigningIn": "Anmeldung läuft…",
117
+ "getCommons": "Commons herunterladen",
118
+ "commonsNotInstalled": "Kein Commons? Holen Sie sich die App, um sich mit Ihrer Oxy-ID anzumelden.",
119
+ "showQrAnyway": "Ich habe Commons auf einem anderen Gerät"
120
+ },
97
121
  "common": {
98
122
  "actions": {
99
123
  "back": "Zurück",
@@ -105,7 +129,8 @@
105
129
  "verify": "Überprüfen",
106
130
  "resetPassword": "Passwort zurücksetzen",
107
131
  "signedOut": "Abgemeldet",
108
- "close": "Schließen"
132
+ "close": "Schließen",
133
+ "tryAgain": "Erneut versuchen"
109
134
  },
110
135
  "links": {
111
136
  "recoverAccount": "Ihr Konto wiederherstellen",
@@ -50,11 +50,26 @@
50
50
  "currentAccount": "Current",
51
51
  "or": "or",
52
52
  "viewAllAccounts": "View {{count}} more",
53
+ "createAccountLink": "New to Oxy? Create one",
53
54
  "status": {
54
- "accountSwitched": "Now using {{name}}"
55
+ "accountSwitched": "Now using {{name}}",
56
+ "signingIn": "Signing in…"
55
57
  }
56
58
  },
57
59
  "signup": {
60
+ "commonsHeadline": "Create your identity in Commons",
61
+ "commonsExplainer": "Commons is your full self-custody Oxy identity — one app, works everywhere.",
62
+ "createInCommons": "Create your identity in Commons",
63
+ "passkeyAlternative": "No Commons? Create a passkey on this device instead",
64
+ "createAccount": "Create account",
65
+ "creating": "Creating…",
66
+ "usernamePlaceholder": "Choose a username",
67
+ "usernameChecking": "Checking…",
68
+ "usernameAvailable": "Available",
69
+ "usernameTaken": "This username is taken",
70
+ "backToSignInLink": "Already have an account? Sign in",
71
+ "hubExplainer": "Create your Oxy ID in a secure window, then come right back.",
72
+ "continueInWindow": "Continue in a new window",
58
73
  "welcome": {
59
74
  "title": "Welcome to Oxy!",
60
75
  "subtitle": "Let's create your account in just a few steps",
@@ -391,7 +406,14 @@
391
406
  "scanTitle": "Scan to sign in",
392
407
  "scanSubtitle": "Open the Oxy app on your phone and scan this code",
393
408
  "scanWithOxy": "Scan with the Oxy app to continue",
394
- "scanQr": "Scan QR code"
409
+ "scanQr": "Scan QR code",
410
+ "qrHeadline": "Sign in with your Oxy identity",
411
+ "signInWithOxy": "Sign in with Oxy",
412
+ "useIdentityOnDevice": "No Commons? Use a passkey on this device instead",
413
+ "passkeySigningIn": "Signing in…",
414
+ "getCommons": "Get Commons",
415
+ "commonsNotInstalled": "Don't have Commons? Get the app to sign in with your Oxy ID.",
416
+ "showQrAnyway": "I have Commons on another device"
395
417
  },
396
418
  "reputation": {
397
419
  "faq": {
@@ -1130,7 +1152,8 @@
1130
1152
  "resetPassword": "Reset Password",
1131
1153
  "signedOut": "Signed out",
1132
1154
  "close": "Close",
1133
- "delete": "Delete"
1155
+ "delete": "Delete",
1156
+ "tryAgain": "Try again"
1134
1157
  },
1135
1158
  "cancel": "Cancel",
1136
1159
  "revoke": "Revoke",
@@ -50,11 +50,26 @@
50
50
  "currentAccount": "Actual",
51
51
  "or": "o",
52
52
  "viewAllAccounts": "Ver {{count}} más",
53
+ "createAccountLink": "¿Nuevo en Oxy? Crea una cuenta",
53
54
  "status": {
54
- "accountSwitched": "Ahora usando {{name}}"
55
+ "accountSwitched": "Ahora usando {{name}}",
56
+ "signingIn": "Iniciando sesión…"
55
57
  }
56
58
  },
57
59
  "signup": {
60
+ "commonsHeadline": "Crea tu identidad en Commons",
61
+ "commonsExplainer": "Commons es tu identidad de Oxy con autocustodia completa: una app que funciona en todas partes.",
62
+ "createInCommons": "Crea tu identidad en Commons",
63
+ "passkeyAlternative": "¿No tienes Commons? Crea una clave de acceso en este dispositivo",
64
+ "createAccount": "Crear cuenta",
65
+ "creating": "Creando…",
66
+ "usernamePlaceholder": "Elige un usuario",
67
+ "usernameChecking": "Comprobando…",
68
+ "usernameAvailable": "Disponible",
69
+ "usernameTaken": "Este usuario ya está en uso",
70
+ "backToSignInLink": "¿Ya tienes cuenta? Inicia sesión",
71
+ "hubExplainer": "Crea tu Oxy ID en una ventana segura y vuelve enseguida.",
72
+ "continueInWindow": "Continuar en una ventana nueva",
58
73
  "welcome": {
59
74
  "title": "¡Te damos la bienvenida a Oxy!",
60
75
  "subtitle": "Crea tu cuenta en pocos pasos",
@@ -303,7 +318,8 @@
303
318
  "resetPassword": "Restablecer contraseña",
304
319
  "signedOut": "Sesión cerrada",
305
320
  "close": "Cerrar",
306
- "delete": "Eliminar"
321
+ "delete": "Eliminar",
322
+ "tryAgain": "Reintentar"
307
323
  },
308
324
  "cancel": "Cancelar",
309
325
  "revoke": "Revocar",
@@ -588,7 +604,14 @@
588
604
  "scanTitle": "Escanea para iniciar sesión",
589
605
  "scanSubtitle": "Abre la app de Oxy en tu móvil y escanea este código",
590
606
  "scanWithOxy": "Escanea con la app de Oxy para continuar",
591
- "scanQr": "Escanear código QR"
607
+ "scanQr": "Escanear código QR",
608
+ "qrHeadline": "Inicia sesión con tu identidad de Oxy",
609
+ "signInWithOxy": "Inicia sesión con Oxy",
610
+ "useIdentityOnDevice": "¿No tienes Commons? Usa una clave de acceso en este dispositivo",
611
+ "passkeySigningIn": "Iniciando sesión…",
612
+ "getCommons": "Descargar Commons",
613
+ "commonsNotInstalled": "¿No tienes Commons? Descarga la app para iniciar sesión con tu Oxy ID.",
614
+ "showQrAnyway": "Tengo Commons en otro dispositivo"
592
615
  },
593
616
  "feedback": {
594
617
  "type": {
@@ -43,11 +43,26 @@
43
43
  "currentAccount": "Actuel",
44
44
  "or": "ou",
45
45
  "viewAllAccounts": "Voir {{count}} de plus",
46
+ "createAccountLink": "Nouveau sur Oxy ? Créez un compte",
46
47
  "status": {
47
- "accountSwitched": "Utilisation de {{name}}"
48
+ "accountSwitched": "Utilisation de {{name}}",
49
+ "signingIn": "Connexion…"
48
50
  }
49
51
  },
50
52
  "signup": {
53
+ "commonsHeadline": "Créez votre identité dans Commons",
54
+ "commonsExplainer": "Commons est votre identité Oxy en autoconservation complète : une seule app, partout.",
55
+ "createInCommons": "Créez votre identité dans Commons",
56
+ "passkeyAlternative": "Pas de Commons ? Créez une clé d'accès sur cet appareil",
57
+ "createAccount": "Créer un compte",
58
+ "creating": "Création…",
59
+ "usernamePlaceholder": "Choisissez un nom d'utilisateur",
60
+ "usernameChecking": "Vérification…",
61
+ "usernameAvailable": "Disponible",
62
+ "usernameTaken": "Ce nom d'utilisateur est déjà pris",
63
+ "backToSignInLink": "Vous avez déjà un compte ? Connectez-vous",
64
+ "hubExplainer": "Créez votre Oxy ID dans une fenêtre sécurisée, puis revenez directement.",
65
+ "continueInWindow": "Continuer dans une nouvelle fenêtre",
51
66
  "welcome": {
52
67
  "title": "Bienvenue sur Oxy !",
53
68
  "subtitle": "Créez votre compte en quelques étapes",
@@ -94,6 +109,15 @@
94
109
  "legalReminder": "En créant un compte, vous acceptez nos Conditions d'utilisation et notre Politique de confidentialité."
95
110
  }
96
111
  },
112
+ "accountSwitcher": {
113
+ "qrHeadline": "Connectez-vous avec votre identité Oxy",
114
+ "signInWithOxy": "Se connecter avec Oxy",
115
+ "useIdentityOnDevice": "Pas de Commons ? Utilisez une clé d'accès sur cet appareil",
116
+ "passkeySigningIn": "Connexion…",
117
+ "getCommons": "Obtenir Commons",
118
+ "commonsNotInstalled": "Pas de Commons ? Téléchargez l'app pour vous connecter avec votre Oxy ID.",
119
+ "showQrAnyway": "J'ai Commons sur un autre appareil"
120
+ },
97
121
  "common": {
98
122
  "actions": {
99
123
  "back": "Retour",
@@ -105,7 +129,8 @@
105
129
  "verify": "Vérifier",
106
130
  "resetPassword": "Réinitialiser le mot de passe",
107
131
  "signedOut": "Déconnecté",
108
- "close": "Fermer"
132
+ "close": "Fermer",
133
+ "tryAgain": "Réessayer"
109
134
  },
110
135
  "links": {
111
136
  "recoverAccount": "Récupérer votre compte",
@@ -43,11 +43,26 @@
43
43
  "currentAccount": "Attuale",
44
44
  "or": "o",
45
45
  "viewAllAccounts": "Visualizza {{count}} altri",
46
+ "createAccountLink": "Nuovo su Oxy? Creane uno",
46
47
  "status": {
47
- "accountSwitched": "Ora usando {{name}}"
48
+ "accountSwitched": "Ora usando {{name}}",
49
+ "signingIn": "Accesso in corso…"
48
50
  }
49
51
  },
50
52
  "signup": {
53
+ "commonsHeadline": "Crea la tua identità in Commons",
54
+ "commonsExplainer": "Commons è la tua identità Oxy in piena autocustodia: un'unica app, ovunque.",
55
+ "createInCommons": "Crea la tua identità in Commons",
56
+ "passkeyAlternative": "Non hai Commons? Crea una passkey su questo dispositivo",
57
+ "createAccount": "Crea account",
58
+ "creating": "Creazione…",
59
+ "usernamePlaceholder": "Scegli un nome utente",
60
+ "usernameChecking": "Verifica in corso…",
61
+ "usernameAvailable": "Disponibile",
62
+ "usernameTaken": "Questo nome utente è già in uso",
63
+ "backToSignInLink": "Hai già un account? Accedi",
64
+ "hubExplainer": "Crea il tuo Oxy ID in una finestra sicura, poi torna subito qui.",
65
+ "continueInWindow": "Continua in una nuova finestra",
51
66
  "welcome": {
52
67
  "title": "Benvenuto su Oxy!",
53
68
  "subtitle": "Crea il tuo account in pochi passaggi",
@@ -94,6 +109,15 @@
94
109
  "legalReminder": "Creando un account, accetti i nostri Termini di servizio e l'Informativa sulla privacy."
95
110
  }
96
111
  },
112
+ "accountSwitcher": {
113
+ "qrHeadline": "Accedi con la tua identità Oxy",
114
+ "signInWithOxy": "Accedi con Oxy",
115
+ "useIdentityOnDevice": "Non hai Commons? Usa una passkey su questo dispositivo",
116
+ "passkeySigningIn": "Accesso in corso…",
117
+ "getCommons": "Ottieni Commons",
118
+ "commonsNotInstalled": "Non hai Commons? Scarica l'app per accedere con il tuo Oxy ID.",
119
+ "showQrAnyway": "Ho Commons su un altro dispositivo"
120
+ },
97
121
  "common": {
98
122
  "actions": {
99
123
  "back": "Indietro",
@@ -105,7 +129,8 @@
105
129
  "verify": "Verifica",
106
130
  "resetPassword": "Reimposta password",
107
131
  "signedOut": "Disconnesso",
108
- "close": "Chiudi"
132
+ "close": "Chiudi",
133
+ "tryAgain": "Riprova"
109
134
  },
110
135
  "links": {
111
136
  "recoverAccount": "Recupera il tuo account",
@@ -43,11 +43,26 @@
43
43
  "currentAccount": "現在",
44
44
  "or": "または",
45
45
  "viewAllAccounts": "さらに{{count}}件を表示",
46
+ "createAccountLink": "Oxyは初めてですか?アカウントを作成",
46
47
  "status": {
47
- "accountSwitched": "{{name}}を使用中"
48
+ "accountSwitched": "{{name}}を使用中",
49
+ "signingIn": "サインインしています…"
48
50
  }
49
51
  },
50
52
  "signup": {
53
+ "commonsHeadline": "Commonsであなたのアイデンティティを作成",
54
+ "commonsExplainer": "Commonsは完全に自己管理できるあなたのOxy IDです。1つのアプリでどこでも使えます。",
55
+ "createInCommons": "Commonsであなたのアイデンティティを作成",
56
+ "passkeyAlternative": "Commonsがありませんか?このデバイスでパスキーを作成",
57
+ "createAccount": "アカウントを作成",
58
+ "creating": "作成しています…",
59
+ "usernamePlaceholder": "ユーザー名を選択",
60
+ "usernameChecking": "確認しています…",
61
+ "usernameAvailable": "利用可能",
62
+ "usernameTaken": "このユーザー名は既に使用されています",
63
+ "backToSignInLink": "すでにアカウントをお持ちですか?サインイン",
64
+ "hubExplainer": "安全なウィンドウでOxy IDを作成し、すぐに戻ってきてください。",
65
+ "continueInWindow": "新しいウィンドウで続ける",
51
66
  "welcome": {
52
67
  "title": "Oxyへようこそ!",
53
68
  "subtitle": "数ステップでアカウントを作成",
@@ -94,6 +109,15 @@
94
109
  "legalReminder": "アカウントを作成することで、利用規約とプライバシーポリシーに同意したことになります。"
95
110
  }
96
111
  },
112
+ "accountSwitcher": {
113
+ "qrHeadline": "Oxy IDでサインイン",
114
+ "signInWithOxy": "Oxyでサインイン",
115
+ "useIdentityOnDevice": "Commonsがありませんか?このデバイスのパスキーを使用",
116
+ "passkeySigningIn": "サインインしています…",
117
+ "getCommons": "Commonsを入手",
118
+ "commonsNotInstalled": "Commonsがありませんか?アプリを入手してOxy IDでサインインしましょう。",
119
+ "showQrAnyway": "別のデバイスにCommonsがあります"
120
+ },
97
121
  "common": {
98
122
  "actions": {
99
123
  "back": "戻る",
@@ -105,7 +129,8 @@
105
129
  "verify": "確認",
106
130
  "resetPassword": "パスワードをリセット",
107
131
  "signedOut": "ログアウトしました",
108
- "close": "閉じる"
132
+ "close": "閉じる",
133
+ "tryAgain": "再試行"
109
134
  },
110
135
  "links": {
111
136
  "recoverAccount": "アカウントを回復",
@@ -43,11 +43,26 @@
43
43
  "currentAccount": "현재",
44
44
  "or": "또는",
45
45
  "viewAllAccounts": "{{count}}개 더 보기",
46
+ "createAccountLink": "Oxy가 처음이신가요? 계정 만들기",
46
47
  "status": {
47
- "accountSwitched": "{{name}} 사용 중"
48
+ "accountSwitched": "{{name}} 사용 중",
49
+ "signingIn": "로그인 중…"
48
50
  }
49
51
  },
50
52
  "signup": {
53
+ "commonsHeadline": "Commons에서 나의 아이덴티티 만들기",
54
+ "commonsExplainer": "Commons는 완전한 자기 보관 방식의 Oxy 아이덴티티입니다. 하나의 앱으로 어디서나 사용하세요.",
55
+ "createInCommons": "Commons에서 나의 아이덴티티 만들기",
56
+ "passkeyAlternative": "Commons가 없으신가요? 이 기기에서 패스키를 만드세요",
57
+ "createAccount": "계정 만들기",
58
+ "creating": "만드는 중…",
59
+ "usernamePlaceholder": "사용자 이름 선택",
60
+ "usernameChecking": "확인 중…",
61
+ "usernameAvailable": "사용 가능",
62
+ "usernameTaken": "이미 사용 중인 사용자 이름입니다",
63
+ "backToSignInLink": "이미 계정이 있으신가요? 로그인",
64
+ "hubExplainer": "안전한 창에서 Oxy ID를 만든 후 바로 돌아오세요.",
65
+ "continueInWindow": "새 창에서 계속하기",
51
66
  "welcome": {
52
67
  "title": "Oxy에 오신 것을 환영합니다!",
53
68
  "subtitle": "몇 단계만으로 계정을 만드세요",
@@ -94,6 +109,15 @@
94
109
  "legalReminder": "계정을 만들면 서비스 약관 및 개인정보 보호정책에 동의하는 것입니다."
95
110
  }
96
111
  },
112
+ "accountSwitcher": {
113
+ "qrHeadline": "Oxy ID로 로그인",
114
+ "signInWithOxy": "Oxy로 로그인",
115
+ "useIdentityOnDevice": "Commons가 없으신가요? 이 기기의 패스키를 사용하세요",
116
+ "passkeySigningIn": "로그인 중…",
117
+ "getCommons": "Commons 다운로드",
118
+ "commonsNotInstalled": "Commons가 없으신가요? 앱을 다운로드하여 Oxy ID로 로그인하세요.",
119
+ "showQrAnyway": "다른 기기에 Commons가 있습니다"
120
+ },
97
121
  "common": {
98
122
  "actions": {
99
123
  "back": "뒤로",
@@ -105,7 +129,8 @@
105
129
  "verify": "확인",
106
130
  "resetPassword": "비밀번호 재설정",
107
131
  "signedOut": "로그아웃됨",
108
- "close": "닫기"
132
+ "close": "닫기",
133
+ "tryAgain": "다시 시도"
109
134
  },
110
135
  "links": {
111
136
  "recoverAccount": "계정 복구",