@oxy.so/core 1.5.0 → 1.6.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 (131) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/HttpService.js +72 -9
  3. package/dist/cjs/crypto/identityMove.js +53 -34
  4. package/dist/cjs/crypto/identityProof.js +28 -0
  5. package/dist/cjs/crypto/webIdentityCarrier.js +145 -82
  6. package/dist/cjs/i18n/locales/ar-SA.json +1 -0
  7. package/dist/cjs/i18n/locales/ca-ES.json +1 -0
  8. package/dist/cjs/i18n/locales/de-DE.json +1 -0
  9. package/dist/cjs/i18n/locales/en-US.json +1 -0
  10. package/dist/cjs/i18n/locales/es-ES.json +1 -0
  11. package/dist/cjs/i18n/locales/fr-FR.json +1 -0
  12. package/dist/cjs/i18n/locales/it-IT.json +1 -0
  13. package/dist/cjs/i18n/locales/ja-JP.json +1 -0
  14. package/dist/cjs/i18n/locales/ko-KR.json +1 -0
  15. package/dist/cjs/i18n/locales/locales/ar-SA.json +1 -0
  16. package/dist/cjs/i18n/locales/locales/ca-ES.json +1 -0
  17. package/dist/cjs/i18n/locales/locales/de-DE.json +1 -0
  18. package/dist/cjs/i18n/locales/locales/en-US.json +1 -0
  19. package/dist/cjs/i18n/locales/locales/es-ES.json +1 -0
  20. package/dist/cjs/i18n/locales/locales/fr-FR.json +1 -0
  21. package/dist/cjs/i18n/locales/locales/it-IT.json +1 -0
  22. package/dist/cjs/i18n/locales/locales/ja-JP.json +1 -0
  23. package/dist/cjs/i18n/locales/locales/ko-KR.json +1 -0
  24. package/dist/cjs/i18n/locales/locales/pt-PT.json +1 -0
  25. package/dist/cjs/i18n/locales/locales/zh-CN.json +1 -0
  26. package/dist/cjs/i18n/locales/pt-PT.json +1 -0
  27. package/dist/cjs/i18n/locales/zh-CN.json +1 -0
  28. package/dist/cjs/index.js +22 -14
  29. package/dist/cjs/inference/OxyInferenceClient.js +62 -5
  30. package/dist/cjs/mixins/OxyServices.auth.js +129 -0
  31. package/dist/cjs/mixins/OxyServices.identity.js +11 -44
  32. package/dist/cjs/mixins/index.js +0 -2
  33. package/dist/cjs/server/index.js +10 -1
  34. package/dist/cjs/server/securityHeaders.js +9 -2
  35. package/dist/cjs/server/workloadIdentity.js +170 -0
  36. package/dist/cjs/session/refresh.js +12 -0
  37. package/dist/esm/.tsbuildinfo +1 -1
  38. package/dist/esm/HttpService.js +72 -9
  39. package/dist/esm/crypto/identityMove.js +51 -33
  40. package/dist/esm/crypto/identityProof.js +24 -0
  41. package/dist/esm/crypto/webIdentityCarrier.js +137 -77
  42. package/dist/esm/i18n/locales/ar-SA.json +1 -0
  43. package/dist/esm/i18n/locales/ca-ES.json +1 -0
  44. package/dist/esm/i18n/locales/de-DE.json +1 -0
  45. package/dist/esm/i18n/locales/en-US.json +1 -0
  46. package/dist/esm/i18n/locales/es-ES.json +1 -0
  47. package/dist/esm/i18n/locales/fr-FR.json +1 -0
  48. package/dist/esm/i18n/locales/it-IT.json +1 -0
  49. package/dist/esm/i18n/locales/ja-JP.json +1 -0
  50. package/dist/esm/i18n/locales/ko-KR.json +1 -0
  51. package/dist/esm/i18n/locales/locales/ar-SA.json +1 -0
  52. package/dist/esm/i18n/locales/locales/ca-ES.json +1 -0
  53. package/dist/esm/i18n/locales/locales/de-DE.json +1 -0
  54. package/dist/esm/i18n/locales/locales/en-US.json +1 -0
  55. package/dist/esm/i18n/locales/locales/es-ES.json +1 -0
  56. package/dist/esm/i18n/locales/locales/fr-FR.json +1 -0
  57. package/dist/esm/i18n/locales/locales/it-IT.json +1 -0
  58. package/dist/esm/i18n/locales/locales/ja-JP.json +1 -0
  59. package/dist/esm/i18n/locales/locales/ko-KR.json +1 -0
  60. package/dist/esm/i18n/locales/locales/pt-PT.json +1 -0
  61. package/dist/esm/i18n/locales/locales/zh-CN.json +1 -0
  62. package/dist/esm/i18n/locales/pt-PT.json +1 -0
  63. package/dist/esm/i18n/locales/zh-CN.json +1 -0
  64. package/dist/esm/index.js +5 -4
  65. package/dist/esm/inference/OxyInferenceClient.js +63 -6
  66. package/dist/esm/mixins/OxyServices.auth.js +96 -0
  67. package/dist/esm/mixins/OxyServices.identity.js +11 -44
  68. package/dist/esm/mixins/index.js +0 -2
  69. package/dist/esm/server/index.js +7 -0
  70. package/dist/esm/server/securityHeaders.js +9 -2
  71. package/dist/esm/server/workloadIdentity.js +166 -0
  72. package/dist/esm/session/refresh.js +12 -0
  73. package/dist/types/.tsbuildinfo +1 -1
  74. package/dist/types/HttpService.d.ts +24 -0
  75. package/dist/types/OxyServices.d.ts +3 -0
  76. package/dist/types/crypto/identityMove.d.ts +48 -32
  77. package/dist/types/crypto/identityProof.d.ts +16 -0
  78. package/dist/types/crypto/webIdentityCarrier.d.ts +74 -47
  79. package/dist/types/index.d.ts +7 -6
  80. package/dist/types/inference/OxyInferenceClient.d.ts +21 -1
  81. package/dist/types/mixins/OxyServices.auth.d.ts +32 -0
  82. package/dist/types/mixins/OxyServices.identity.d.ts +16 -30
  83. package/dist/types/mixins/OxyServices.utility.d.ts +2 -0
  84. package/dist/types/mixins/index.d.ts +1 -2
  85. package/dist/types/server/index.d.ts +8 -0
  86. package/dist/types/server/securityHeaders.d.ts +8 -0
  87. package/dist/types/server/workloadIdentity.d.ts +32 -0
  88. package/package.json +1 -1
  89. package/src/HttpService.ts +74 -9
  90. package/src/OxyServices.ts +9 -0
  91. package/src/__tests__/httpServiceRateLimitedRefresh.test.ts +160 -0
  92. package/src/__tests__/publicInterfaceParity.test.ts +75 -0
  93. package/src/__tests__/serviceTokenWorkloadFallback.test.ts +85 -0
  94. package/src/crypto/__tests__/identityMove.test.ts +93 -51
  95. package/src/crypto/__tests__/identityProof.test.ts +81 -0
  96. package/src/crypto/__tests__/webIdentityCarrier.test.ts +21 -63
  97. package/src/crypto/__tests__/webIdentityRecoveryMaterial.test.ts +117 -0
  98. package/src/crypto/identityMove.ts +77 -43
  99. package/src/crypto/identityProof.ts +36 -0
  100. package/src/crypto/webIdentityCarrier.ts +185 -117
  101. package/src/i18n/locales/ar-SA.json +1 -0
  102. package/src/i18n/locales/ca-ES.json +1 -0
  103. package/src/i18n/locales/de-DE.json +1 -0
  104. package/src/i18n/locales/en-US.json +1 -0
  105. package/src/i18n/locales/es-ES.json +1 -0
  106. package/src/i18n/locales/fr-FR.json +1 -0
  107. package/src/i18n/locales/it-IT.json +1 -0
  108. package/src/i18n/locales/ja-JP.json +1 -0
  109. package/src/i18n/locales/ko-KR.json +1 -0
  110. package/src/i18n/locales/pt-PT.json +1 -0
  111. package/src/i18n/locales/zh-CN.json +1 -0
  112. package/src/index.ts +26 -15
  113. package/src/inference/OxyInferenceClient.ts +84 -7
  114. package/src/inference/__tests__/OxyInferenceClient.test.ts +48 -0
  115. package/src/mixins/OxyServices.auth.ts +100 -1
  116. package/src/mixins/OxyServices.identity.ts +17 -67
  117. package/src/mixins/OxyServices.utility.ts +2 -0
  118. package/src/mixins/__tests__/OxyServices.identity.test.ts +1 -76
  119. package/src/mixins/index.ts +0 -3
  120. package/src/server/__tests__/securityHeaders.test.ts +15 -0
  121. package/src/server/__tests__/workloadIdentity.test.ts +128 -0
  122. package/src/server/index.ts +9 -0
  123. package/src/server/securityHeaders.ts +19 -6
  124. package/src/server/workloadIdentity.ts +207 -0
  125. package/src/session/__tests__/refresh.test.ts +53 -3
  126. package/src/session/refresh.ts +12 -0
  127. package/dist/cjs/mixins/OxyServices.deviceTransfer.js +0 -314
  128. package/dist/esm/mixins/OxyServices.deviceTransfer.js +0 -311
  129. package/dist/types/mixins/OxyServices.deviceTransfer.d.ts +0 -149
  130. package/src/mixins/OxyServices.deviceTransfer.ts +0 -393
  131. package/src/mixins/__tests__/OxyServices.deviceTransfer.test.ts +0 -271
@@ -108,6 +108,7 @@
108
108
  "loading": "جارٍ تحميل الحسابات...",
109
109
  "qrHeadline": "سجّل الدخول بهوية Oxy الخاصة بك",
110
110
  "signInWithOxy": "تسجيل الدخول باستخدام Oxy",
111
+ "signUpWithOxy": "التسجيل باستخدام Oxy",
111
112
  "useIdentityOnDevice": "لا تملك Commons؟ استخدم مفتاح مرور على هذا الجهاز بدلاً من ذلك",
112
113
  "getCommons": "احصل على Commons",
113
114
  "commonsNotInstalled": "لا تملك Commons؟ احصل على التطبيق لتسجيل الدخول بمعرّف Oxy الخاص بك.",
@@ -108,6 +108,7 @@
108
108
  "loading": "S'estan carregant els comptes...",
109
109
  "qrHeadline": "Inicia sessió amb la teva identitat d'Oxy",
110
110
  "signInWithOxy": "Inicia sessió amb Oxy",
111
+ "signUpWithOxy": "Registra't amb Oxy",
111
112
  "useIdentityOnDevice": "No tens Commons? Fes servir una clau d'accés en aquest dispositiu",
112
113
  "getCommons": "Descarrega Commons",
113
114
  "commonsNotInstalled": "No tens Commons? Descarrega l'app per iniciar sessió amb el teu Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "Konten werden geladen...",
109
109
  "qrHeadline": "Melden Sie sich mit Ihrer Oxy-Identität an",
110
110
  "signInWithOxy": "Mit Oxy anmelden",
111
+ "signUpWithOxy": "Mit Oxy registrieren",
111
112
  "useIdentityOnDevice": "Kein Commons? Verwenden Sie stattdessen einen Passkey auf diesem Gerät",
112
113
  "getCommons": "Commons herunterladen",
113
114
  "commonsNotInstalled": "Kein Commons? Holen Sie sich die App, um sich mit Ihrer Oxy-ID anzumelden.",
@@ -416,6 +416,7 @@
416
416
  "scanQr": "Scan QR code",
417
417
  "qrHeadline": "Sign in with your Oxy identity",
418
418
  "signInWithOxy": "Sign in with Oxy",
419
+ "signUpWithOxy": "Sign up with Oxy",
419
420
  "useIdentityOnDevice": "No Commons? Use a passkey on this device instead",
420
421
  "getCommons": "Get Commons",
421
422
  "commonsNotInstalled": "Don't have Commons? Get the app to sign in with your Oxy ID.",
@@ -656,6 +656,7 @@
656
656
  "scanQr": "Escanear código QR",
657
657
  "qrHeadline": "Inicia sesión con tu identidad de Oxy",
658
658
  "signInWithOxy": "Inicia sesión con Oxy",
659
+ "signUpWithOxy": "Regístrate con Oxy",
659
660
  "useIdentityOnDevice": "¿No tienes Commons? Usa una clave de acceso en este dispositivo",
660
661
  "getCommons": "Descargar Commons",
661
662
  "commonsNotInstalled": "¿No tienes Commons? Descarga la app para iniciar sesión con tu Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "Chargement des comptes...",
109
109
  "qrHeadline": "Connectez-vous avec votre identité Oxy",
110
110
  "signInWithOxy": "Se connecter avec Oxy",
111
+ "signUpWithOxy": "S'inscrire avec Oxy",
111
112
  "useIdentityOnDevice": "Pas de Commons ? Utilisez une clé d'accès sur cet appareil",
112
113
  "getCommons": "Obtenir Commons",
113
114
  "commonsNotInstalled": "Pas de Commons ? Téléchargez l'app pour vous connecter avec votre Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "Caricamento account...",
109
109
  "qrHeadline": "Accedi con la tua identità Oxy",
110
110
  "signInWithOxy": "Accedi con Oxy",
111
+ "signUpWithOxy": "Registrati con Oxy",
111
112
  "useIdentityOnDevice": "Non hai Commons? Usa una passkey su questo dispositivo",
112
113
  "getCommons": "Ottieni Commons",
113
114
  "commonsNotInstalled": "Non hai Commons? Scarica l'app per accedere con il tuo Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "アカウントを読み込み中...",
109
109
  "qrHeadline": "Oxy IDでサインイン",
110
110
  "signInWithOxy": "Oxyでサインイン",
111
+ "signUpWithOxy": "Oxyで登録",
111
112
  "useIdentityOnDevice": "Commonsがありませんか?このデバイスのパスキーを使用",
112
113
  "getCommons": "Commonsを入手",
113
114
  "commonsNotInstalled": "Commonsがありませんか?アプリを入手してOxy IDでサインインしましょう。",
@@ -108,6 +108,7 @@
108
108
  "loading": "계정을 불러오는 중...",
109
109
  "qrHeadline": "Oxy ID로 로그인",
110
110
  "signInWithOxy": "Oxy로 로그인",
111
+ "signUpWithOxy": "Oxy로 가입하기",
111
112
  "useIdentityOnDevice": "Commons가 없으신가요? 이 기기의 패스키를 사용하세요",
112
113
  "getCommons": "Commons 다운로드",
113
114
  "commonsNotInstalled": "Commons가 없으신가요? 앱을 다운로드하여 Oxy ID로 로그인하세요.",
@@ -108,6 +108,7 @@
108
108
  "loading": "جارٍ تحميل الحسابات...",
109
109
  "qrHeadline": "سجّل الدخول بهوية Oxy الخاصة بك",
110
110
  "signInWithOxy": "تسجيل الدخول باستخدام Oxy",
111
+ "signUpWithOxy": "التسجيل باستخدام Oxy",
111
112
  "useIdentityOnDevice": "لا تملك Commons؟ استخدم مفتاح مرور على هذا الجهاز بدلاً من ذلك",
112
113
  "getCommons": "احصل على Commons",
113
114
  "commonsNotInstalled": "لا تملك Commons؟ احصل على التطبيق لتسجيل الدخول بمعرّف Oxy الخاص بك.",
@@ -108,6 +108,7 @@
108
108
  "loading": "S'estan carregant els comptes...",
109
109
  "qrHeadline": "Inicia sessió amb la teva identitat d'Oxy",
110
110
  "signInWithOxy": "Inicia sessió amb Oxy",
111
+ "signUpWithOxy": "Registra't amb Oxy",
111
112
  "useIdentityOnDevice": "No tens Commons? Fes servir una clau d'accés en aquest dispositiu",
112
113
  "getCommons": "Descarrega Commons",
113
114
  "commonsNotInstalled": "No tens Commons? Descarrega l'app per iniciar sessió amb el teu Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "Konten werden geladen...",
109
109
  "qrHeadline": "Melden Sie sich mit Ihrer Oxy-Identität an",
110
110
  "signInWithOxy": "Mit Oxy anmelden",
111
+ "signUpWithOxy": "Mit Oxy registrieren",
111
112
  "useIdentityOnDevice": "Kein Commons? Verwenden Sie stattdessen einen Passkey auf diesem Gerät",
112
113
  "getCommons": "Commons herunterladen",
113
114
  "commonsNotInstalled": "Kein Commons? Holen Sie sich die App, um sich mit Ihrer Oxy-ID anzumelden.",
@@ -416,6 +416,7 @@
416
416
  "scanQr": "Scan QR code",
417
417
  "qrHeadline": "Sign in with your Oxy identity",
418
418
  "signInWithOxy": "Sign in with Oxy",
419
+ "signUpWithOxy": "Sign up with Oxy",
419
420
  "useIdentityOnDevice": "No Commons? Use a passkey on this device instead",
420
421
  "getCommons": "Get Commons",
421
422
  "commonsNotInstalled": "Don't have Commons? Get the app to sign in with your Oxy ID.",
@@ -656,6 +656,7 @@
656
656
  "scanQr": "Escanear código QR",
657
657
  "qrHeadline": "Inicia sesión con tu identidad de Oxy",
658
658
  "signInWithOxy": "Inicia sesión con Oxy",
659
+ "signUpWithOxy": "Regístrate con Oxy",
659
660
  "useIdentityOnDevice": "¿No tienes Commons? Usa una clave de acceso en este dispositivo",
660
661
  "getCommons": "Descargar Commons",
661
662
  "commonsNotInstalled": "¿No tienes Commons? Descarga la app para iniciar sesión con tu Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "Chargement des comptes...",
109
109
  "qrHeadline": "Connectez-vous avec votre identité Oxy",
110
110
  "signInWithOxy": "Se connecter avec Oxy",
111
+ "signUpWithOxy": "S'inscrire avec Oxy",
111
112
  "useIdentityOnDevice": "Pas de Commons ? Utilisez une clé d'accès sur cet appareil",
112
113
  "getCommons": "Obtenir Commons",
113
114
  "commonsNotInstalled": "Pas de Commons ? Téléchargez l'app pour vous connecter avec votre Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "Caricamento account...",
109
109
  "qrHeadline": "Accedi con la tua identità Oxy",
110
110
  "signInWithOxy": "Accedi con Oxy",
111
+ "signUpWithOxy": "Registrati con Oxy",
111
112
  "useIdentityOnDevice": "Non hai Commons? Usa una passkey su questo dispositivo",
112
113
  "getCommons": "Ottieni Commons",
113
114
  "commonsNotInstalled": "Non hai Commons? Scarica l'app per accedere con il tuo Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "アカウントを読み込み中...",
109
109
  "qrHeadline": "Oxy IDでサインイン",
110
110
  "signInWithOxy": "Oxyでサインイン",
111
+ "signUpWithOxy": "Oxyで登録",
111
112
  "useIdentityOnDevice": "Commonsがありませんか?このデバイスのパスキーを使用",
112
113
  "getCommons": "Commonsを入手",
113
114
  "commonsNotInstalled": "Commonsがありませんか?アプリを入手してOxy IDでサインインしましょう。",
@@ -108,6 +108,7 @@
108
108
  "loading": "계정을 불러오는 중...",
109
109
  "qrHeadline": "Oxy ID로 로그인",
110
110
  "signInWithOxy": "Oxy로 로그인",
111
+ "signUpWithOxy": "Oxy로 가입하기",
111
112
  "useIdentityOnDevice": "Commons가 없으신가요? 이 기기의 패스키를 사용하세요",
112
113
  "getCommons": "Commons 다운로드",
113
114
  "commonsNotInstalled": "Commons가 없으신가요? 앱을 다운로드하여 Oxy ID로 로그인하세요.",
@@ -108,6 +108,7 @@
108
108
  "loading": "A carregar contas...",
109
109
  "qrHeadline": "Inicie sessão com a sua identidade Oxy",
110
110
  "signInWithOxy": "Iniciar sessão com Oxy",
111
+ "signUpWithOxy": "Registar-se com Oxy",
111
112
  "useIdentityOnDevice": "Não tem o Commons? Use uma chave de acesso neste dispositivo",
112
113
  "getCommons": "Obter o Commons",
113
114
  "commonsNotInstalled": "Não tem o Commons? Obtenha a app para iniciar sessão com o seu Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "正在加载账户...",
109
109
  "qrHeadline": "使用您的 Oxy 身份登录",
110
110
  "signInWithOxy": "使用 Oxy 登录",
111
+ "signUpWithOxy": "使用 Oxy 注册",
111
112
  "useIdentityOnDevice": "没有 Commons?改用此设备上的通行密钥",
112
113
  "getCommons": "获取 Commons",
113
114
  "commonsNotInstalled": "没有 Commons?获取应用以使用您的 Oxy ID 登录。",
@@ -108,6 +108,7 @@
108
108
  "loading": "A carregar contas...",
109
109
  "qrHeadline": "Inicie sessão com a sua identidade Oxy",
110
110
  "signInWithOxy": "Iniciar sessão com Oxy",
111
+ "signUpWithOxy": "Registar-se com Oxy",
111
112
  "useIdentityOnDevice": "Não tem o Commons? Use uma chave de acesso neste dispositivo",
112
113
  "getCommons": "Obter o Commons",
113
114
  "commonsNotInstalled": "Não tem o Commons? Obtenha a app para iniciar sessão com o seu Oxy ID.",
@@ -108,6 +108,7 @@
108
108
  "loading": "正在加载账户...",
109
109
  "qrHeadline": "使用您的 Oxy 身份登录",
110
110
  "signInWithOxy": "使用 Oxy 登录",
111
+ "signUpWithOxy": "使用 Oxy 注册",
111
112
  "useIdentityOnDevice": "没有 Commons?改用此设备上的通行密钥",
112
113
  "getCommons": "获取 Commons",
113
114
  "commonsNotInstalled": "没有 Commons?获取应用以使用您的 Oxy ID 登录。",
package/dist/cjs/index.js CHANGED
@@ -19,11 +19,11 @@
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.AEAD_KEY_LENGTH = exports.decryptAead = exports.encryptAead = exports.hkdfSha256 = exports.RecoveryPhraseService = exports.SignatureService = exports.updateIdentityMarker = exports.readIdentityMarker = exports.IdentityUnavailableError = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = exports.sessionsArraysEqual = exports.normalizeAndSortSessions = exports.mergeSessions = exports.authenticatedApiCall = exports.withAuthErrorHandling = exports.isAuthenticationError = exports.ensureValidToken = exports.AuthenticationFailedError = exports.SessionSyncRequiredError = exports.verifyPublicCardAttestation = exports.parseAttestPayload = exports.parseIdPayload = exports.buildUserDid = exports.kindAcceptsAccountCategories = exports.isSelectableAccountCategoryId = exports.SELECTABLE_ACCOUNT_CATEGORY_IDS = exports.MAX_ACCOUNT_CATEGORIES = exports.ACCOUNT_CATEGORY_IDS = exports.normalizeProfileLinks = exports.getNormalizedUserHandle = exports.getCanonicalUserHandle = exports.normalizeUserIdentityOrNull = exports.normalizeUserIdentity = exports.getNormalizedUserId = exports.OxyAppDataIdentifierError = exports.commonsDeliveryPlatform = exports.pushTargetsFromDelivery = exports.selectCommonsDelivery = exports.parseCommonsApprovalExpiresAt = exports.getCommonsApprovalBlockingReason = exports.ServiceCredentialMismatchError = exports.oxyClient = exports.OXY_CLOUD_URL = exports.ServiceAssetMetadataError = exports.OxyAuthenticationTimeoutError = exports.OxyAuthenticationError = exports.AssetUrlResolutionError = exports.OxyServices = void 0;
22
- exports.isNative = exports.isWeb = exports.setPlatformOS = exports.getPlatformOS = exports.coerceToSupportedLocale = exports.getPrimaryLanguage = exports.getUserLanguages = exports.isRTLLocale = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.isSupportedLocale = exports.normalizeLocale = exports.getBaseLanguage = exports.FALLBACK_LOCALE = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.verifyMoveReceipt = exports.signMoveAction = exports.sealIdentityForMove = exports.parseMoveQrPayload = exports.openMovedIdentity = exports.generateMoveEphemeralKeyPair = exports.deriveMoveSas = exports.deriveMoveKey = exports.buildMoveQrPayload = exports.buildMoveMessage = exports.IDENTITY_MOVE_ACTIONS = exports.wrapDataKey = exports.wipeBytes = exports.unwrapDataKey = exports.unlockWebIdentity = exports.signIdentityAction = exports.sealWebIdentity = exports.removeWrap = exports.openWebIdentity = exports.generateWebIdentity = exports.generateDataKey = exports.deriveTransferSas = exports.deriveKeyEncryptionKey = exports.deriveIdentityFromMnemonic = exports.buildIdentityActionMessage = exports.addWrap = exports.WebIdentityUnlockError = exports.WEB_IDENTITY_PRF_INPUT = exports.deriveSharedSecret = exports.AEAD_NONCE_LENGTH = void 0;
23
- exports.validateRequiredFields = exports.parseHttpErrorBody = exports.isHttpRequestError = exports.handleHttpError = exports.createApiError = exports.ErrorCodes = exports.safeJsonParse = exports.buildPaginationParams = exports.buildUrl = exports.buildSearchParams = exports.buildQueryParams = exports.trustTierLabel = exports.reputationCategoryLabel = exports.accountRoleLabel = exports.accountCategoryLabel = exports.translate = exports.withRetry = exports.delay = exports.shouldAllowRequest = exports.recordSuccess = exports.recordFailure = exports.calculateBackoffInterval = exports.createCircuitBreakerState = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.isRetryableError = exports.isNetworkError = exports.isServerError = exports.isRateLimitError = exports.isNotFoundError = exports.isForbiddenError = exports.isUnauthorizedError = exports.isAlreadyRegisteredError = exports.getErrorMessage = exports.getErrorStatus = exports.HttpStatus = exports.getSystemColorScheme = exports.systemPrefersDarkMode = exports.getOppositeTheme = exports.normalizeColorScheme = exports.normalizeTheme = exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = exports.rgbToHex = exports.hexToRgb = exports.lightenColor = exports.darkenColor = exports.isWebBrowser = exports.isAndroid = exports.isIOS = void 0;
24
- exports.generateOAuthState = exports.computeCodeChallenge = exports.buildOAuthAuthorizeUrl = exports.runColdBoot = exports.isOxyRpOrigin = exports.IDENTITY_WEB_ORIGIN = exports.CENTRAL_IDP_APEX = exports.registrableApex = exports.getAccountColor = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = exports.buildAccountsArray = exports.updateAvatarVisibility = exports.isDev = exports.consoleSink = exports.resetLoggerConfig = exports.getLoggerConfig = exports.configureLogger = exports.createLogger = exports.logger = exports.normalizeMultilineText = exports.normalizeInlineText = exports.validateAndSanitizeUserInput = exports.isValidObjectId = exports.sanitizeHTML = exports.sanitizeString = exports.isValidFileType = exports.isValidFileSize = exports.isValidDate = exports.isValidURL = exports.isValidUUID = exports.isValidObject = exports.isValidArray = exports.isRequiredBoolean = exports.isRequiredNumber = exports.isRequiredString = exports.DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE = exports.DISPLAY_NAME_ORPHANED_MARK_SOURCE = exports.DISPLAY_NAME_DISALLOWED_SOURCE = exports.DISPLAY_NAME_ALLOWED_SCRIPTS = exports.isValidDisplayName = exports.isValidPassword = exports.isValidEmail = exports.DISPLAY_NAME_INVALID_MESSAGE = exports.MAX_DISPLAY_NAME_LENGTH = exports.PASSWORD_REGEX = exports.EMAIL_REGEX = exports.retryAsync = void 0;
25
- exports.createMemoryIdentityPinStore = exports.createNativeIdentityPinStore = exports.createWebIdentityPinStore = exports.readLocalDeviceCredential = exports.publishProvenDeviceCredential = exports.normalizeSharedDeviceSessionRead = exports.decideSharedDevicePublish = exports.decideSharedDeviceJoin = exports.createSharedMirroringAuthStateStore = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.resolveAccountDelegationAccess = exports.canSwitchIntoAccount = exports.isSwitchTargetAccount = exports.showsPrincipalHeaders = exports.buildSwitcherRows = exports.resolveDeviceContext = exports.resolveActiveContext = exports.projectDevicePrincipals = exports.directoryHandle = exports.directoryDisplayName = exports.canActivateContext = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.isAllowedDeviceJoinOrigin = exports.isOfficialWebOrigin = exports.isLoopbackOrigin = exports.consumeOAuthReturnPath = exports.persistOAuthReturnPath = exports.clearOAuthHandshake = exports.readOAuthHandshake = exports.persistOAuthHandshake = exports.canonicalizeOAuthRedirectUri = exports.normalizeOAuthRedirectUri = exports.OXY_OAUTH_RETURN_PATH_STORAGE_KEY = exports.OXY_OAUTH_REDIRECT_URI_STORAGE_KEY = exports.OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY = exports.OXY_OAUTH_STATE_STORAGE_KEY = exports.OXY_AUTHORIZE_URL = exports.DEFAULT_OAUTH_SCOPE = exports.generatePkcePair = void 0;
26
- exports.packageInfo = exports.runSessionColdBoot = exports.OXY_INFERENCE_BASE_URL = exports.OxyInferenceProtocolError = exports.OxyInferenceError = exports.OxyInferenceClient = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.AccountNotOnDeviceError = exports.establishIdentitySession = exports.resolveIdentityPin = exports.IDENTITY_PIN_STORAGE_KEY = exports.identityPinMatches = void 0;
22
+ exports.isRTLLocale = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.isSupportedLocale = exports.normalizeLocale = exports.getBaseLanguage = exports.FALLBACK_LOCALE = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.verifyMoveReceipt = exports.verifyMoveCommitment = exports.signMoveReceipt = exports.sealIdentityForMove = exports.parseMoveQrPayload = exports.openMovedIdentity = exports.generateMoveEphemeralKeyPair = exports.digestMoveCiphertext = exports.deriveMoveSas = exports.deriveMoveKey = exports.createMoveCommitment = exports.buildMoveQrPayload = exports.signIdentityProof = exports.digestIdentityPayload = exports.wipeOpenedIdentity = exports.wipeBytes = exports.unwrapDataKey = exports.unlockWebIdentity = exports.sealWebIdentity = exports.removeWrap = exports.parseRecoveryMaterial = exports.openWebIdentity = exports.normalizeMnemonic = exports.markWrapVerified = exports.isUsablePrfOutput = exports.generateWebIdentity = exports.generateDataKey = exports.deriveKeyEncryptionKey = exports.deriveIdentityFromRecoveryMaterial = exports.deriveIdentityFromPrivateKey = exports.deriveIdentityFromMnemonic = exports.addWrap = exports.WEB_IDENTITY_PRF_OUTPUT_LENGTH = exports.WebIdentityUnlockError = exports.WEB_IDENTITY_PRF_INPUT = exports.deriveSharedSecret = exports.AEAD_NONCE_LENGTH = void 0;
23
+ exports.buildPaginationParams = exports.buildUrl = exports.buildSearchParams = exports.buildQueryParams = exports.trustTierLabel = exports.reputationCategoryLabel = exports.accountRoleLabel = exports.accountCategoryLabel = exports.translate = exports.withRetry = exports.delay = exports.shouldAllowRequest = exports.recordSuccess = exports.recordFailure = exports.calculateBackoffInterval = exports.createCircuitBreakerState = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.isRetryableError = exports.isNetworkError = exports.isServerError = exports.isRateLimitError = exports.isNotFoundError = exports.isForbiddenError = exports.isUnauthorizedError = exports.isAlreadyRegisteredError = exports.getErrorMessage = exports.getErrorStatus = exports.HttpStatus = exports.getSystemColorScheme = exports.systemPrefersDarkMode = exports.getOppositeTheme = exports.normalizeColorScheme = exports.normalizeTheme = exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = exports.rgbToHex = exports.hexToRgb = exports.lightenColor = exports.darkenColor = exports.isWebBrowser = exports.isAndroid = exports.isIOS = exports.isNative = exports.isWeb = exports.setPlatformOS = exports.getPlatformOS = exports.coerceToSupportedLocale = exports.getPrimaryLanguage = exports.getUserLanguages = void 0;
24
+ exports.registrableApex = exports.getAccountColor = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = exports.buildAccountsArray = exports.updateAvatarVisibility = exports.isDev = exports.consoleSink = exports.resetLoggerConfig = exports.getLoggerConfig = exports.configureLogger = exports.createLogger = exports.logger = exports.normalizeMultilineText = exports.normalizeInlineText = exports.validateAndSanitizeUserInput = exports.isValidObjectId = exports.sanitizeHTML = exports.sanitizeString = exports.isValidFileType = exports.isValidFileSize = exports.isValidDate = exports.isValidURL = exports.isValidUUID = exports.isValidObject = exports.isValidArray = exports.isRequiredBoolean = exports.isRequiredNumber = exports.isRequiredString = exports.DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE = exports.DISPLAY_NAME_ORPHANED_MARK_SOURCE = exports.DISPLAY_NAME_DISALLOWED_SOURCE = exports.DISPLAY_NAME_ALLOWED_SCRIPTS = exports.isValidDisplayName = exports.isValidPassword = exports.isValidEmail = exports.DISPLAY_NAME_INVALID_MESSAGE = exports.MAX_DISPLAY_NAME_LENGTH = exports.PASSWORD_REGEX = exports.EMAIL_REGEX = exports.retryAsync = exports.validateRequiredFields = exports.parseHttpErrorBody = exports.isHttpRequestError = exports.handleHttpError = exports.createApiError = exports.ErrorCodes = exports.safeJsonParse = void 0;
25
+ exports.decideSharedDeviceJoin = exports.createSharedMirroringAuthStateStore = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.resolveAccountDelegationAccess = exports.canSwitchIntoAccount = exports.isSwitchTargetAccount = exports.showsPrincipalHeaders = exports.buildSwitcherRows = exports.resolveDeviceContext = exports.resolveActiveContext = exports.projectDevicePrincipals = exports.directoryHandle = exports.directoryDisplayName = exports.canActivateContext = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.isAllowedDeviceJoinOrigin = exports.isOfficialWebOrigin = exports.isLoopbackOrigin = exports.consumeOAuthReturnPath = exports.persistOAuthReturnPath = exports.clearOAuthHandshake = exports.readOAuthHandshake = exports.persistOAuthHandshake = exports.canonicalizeOAuthRedirectUri = exports.normalizeOAuthRedirectUri = exports.OXY_OAUTH_RETURN_PATH_STORAGE_KEY = exports.OXY_OAUTH_REDIRECT_URI_STORAGE_KEY = exports.OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY = exports.OXY_OAUTH_STATE_STORAGE_KEY = exports.OXY_AUTHORIZE_URL = exports.DEFAULT_OAUTH_SCOPE = exports.generatePkcePair = exports.generateOAuthState = exports.computeCodeChallenge = exports.buildOAuthAuthorizeUrl = exports.runColdBoot = exports.isOxyRpOrigin = exports.IDENTITY_WEB_ORIGIN = exports.CENTRAL_IDP_APEX = void 0;
26
+ exports.packageInfo = exports.runSessionColdBoot = exports.OXY_INFERENCE_BASE_URL = exports.OxyInferenceProtocolError = exports.OxyInferenceError = exports.OxyInferenceClient = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.AccountNotOnDeviceError = exports.establishIdentitySession = exports.resolveIdentityPin = exports.IDENTITY_PIN_STORAGE_KEY = exports.identityPinMatches = exports.createMemoryIdentityPinStore = exports.createNativeIdentityPinStore = exports.createWebIdentityPinStore = exports.readLocalDeviceCredential = exports.publishProvenDeviceCredential = exports.normalizeSharedDeviceSessionRead = exports.decideSharedDevicePublish = void 0;
27
27
  // Ensure crypto polyfills are loaded before anything else
28
28
  require("./crypto/polyfill");
29
29
  // ---------------------------------------------------------------------------
@@ -141,37 +141,45 @@ Object.defineProperty(exports, "AEAD_KEY_LENGTH", { enumerable: true, get: funct
141
141
  Object.defineProperty(exports, "AEAD_NONCE_LENGTH", { enumerable: true, get: function () { return aead_1.AEAD_NONCE_LENGTH; } });
142
142
  var ecdh_1 = require("./crypto/ecdh");
143
143
  Object.defineProperty(exports, "deriveSharedSecret", { enumerable: true, get: function () { return ecdh_1.deriveSharedSecret; } });
144
- // Web identity carrier — the same identity as Commons, sealed under a passkey's
145
- // PRF output (docs/superpowers/specs/2026-09-15-one-identity-two-carriers-design.md)
144
+ // Web identity holder — the same root as Commons, sealed under a passkey's PRF
145
+ // output; identity proofs; transfer to Commons (docs/adr/0024-one-oxy-account-root-holders.md)
146
146
  var webIdentityCarrier_1 = require("./crypto/webIdentityCarrier");
147
147
  Object.defineProperty(exports, "WEB_IDENTITY_PRF_INPUT", { enumerable: true, get: function () { return webIdentityCarrier_1.WEB_IDENTITY_PRF_INPUT; } });
148
148
  Object.defineProperty(exports, "WebIdentityUnlockError", { enumerable: true, get: function () { return webIdentityCarrier_1.WebIdentityUnlockError; } });
149
+ Object.defineProperty(exports, "WEB_IDENTITY_PRF_OUTPUT_LENGTH", { enumerable: true, get: function () { return webIdentityCarrier_1.WEB_IDENTITY_PRF_OUTPUT_LENGTH; } });
149
150
  Object.defineProperty(exports, "addWrap", { enumerable: true, get: function () { return webIdentityCarrier_1.addWrap; } });
150
- Object.defineProperty(exports, "buildIdentityActionMessage", { enumerable: true, get: function () { return webIdentityCarrier_1.buildIdentityActionMessage; } });
151
151
  Object.defineProperty(exports, "deriveIdentityFromMnemonic", { enumerable: true, get: function () { return webIdentityCarrier_1.deriveIdentityFromMnemonic; } });
152
+ Object.defineProperty(exports, "deriveIdentityFromPrivateKey", { enumerable: true, get: function () { return webIdentityCarrier_1.deriveIdentityFromPrivateKey; } });
153
+ Object.defineProperty(exports, "deriveIdentityFromRecoveryMaterial", { enumerable: true, get: function () { return webIdentityCarrier_1.deriveIdentityFromRecoveryMaterial; } });
152
154
  Object.defineProperty(exports, "deriveKeyEncryptionKey", { enumerable: true, get: function () { return webIdentityCarrier_1.deriveKeyEncryptionKey; } });
153
- Object.defineProperty(exports, "deriveTransferSas", { enumerable: true, get: function () { return webIdentityCarrier_1.deriveTransferSas; } });
154
155
  Object.defineProperty(exports, "generateDataKey", { enumerable: true, get: function () { return webIdentityCarrier_1.generateDataKey; } });
155
156
  Object.defineProperty(exports, "generateWebIdentity", { enumerable: true, get: function () { return webIdentityCarrier_1.generateWebIdentity; } });
157
+ Object.defineProperty(exports, "isUsablePrfOutput", { enumerable: true, get: function () { return webIdentityCarrier_1.isUsablePrfOutput; } });
158
+ Object.defineProperty(exports, "markWrapVerified", { enumerable: true, get: function () { return webIdentityCarrier_1.markWrapVerified; } });
159
+ Object.defineProperty(exports, "normalizeMnemonic", { enumerable: true, get: function () { return webIdentityCarrier_1.normalizeMnemonic; } });
156
160
  Object.defineProperty(exports, "openWebIdentity", { enumerable: true, get: function () { return webIdentityCarrier_1.openWebIdentity; } });
161
+ Object.defineProperty(exports, "parseRecoveryMaterial", { enumerable: true, get: function () { return webIdentityCarrier_1.parseRecoveryMaterial; } });
157
162
  Object.defineProperty(exports, "removeWrap", { enumerable: true, get: function () { return webIdentityCarrier_1.removeWrap; } });
158
163
  Object.defineProperty(exports, "sealWebIdentity", { enumerable: true, get: function () { return webIdentityCarrier_1.sealWebIdentity; } });
159
- Object.defineProperty(exports, "signIdentityAction", { enumerable: true, get: function () { return webIdentityCarrier_1.signIdentityAction; } });
160
164
  Object.defineProperty(exports, "unlockWebIdentity", { enumerable: true, get: function () { return webIdentityCarrier_1.unlockWebIdentity; } });
161
165
  Object.defineProperty(exports, "unwrapDataKey", { enumerable: true, get: function () { return webIdentityCarrier_1.unwrapDataKey; } });
162
166
  Object.defineProperty(exports, "wipeBytes", { enumerable: true, get: function () { return webIdentityCarrier_1.wipeBytes; } });
163
- Object.defineProperty(exports, "wrapDataKey", { enumerable: true, get: function () { return webIdentityCarrier_1.wrapDataKey; } });
167
+ Object.defineProperty(exports, "wipeOpenedIdentity", { enumerable: true, get: function () { return webIdentityCarrier_1.wipeOpenedIdentity; } });
168
+ var identityProof_1 = require("./crypto/identityProof");
169
+ Object.defineProperty(exports, "digestIdentityPayload", { enumerable: true, get: function () { return identityProof_1.digestIdentityPayload; } });
170
+ Object.defineProperty(exports, "signIdentityProof", { enumerable: true, get: function () { return identityProof_1.signIdentityProof; } });
164
171
  var identityMove_1 = require("./crypto/identityMove");
165
- Object.defineProperty(exports, "IDENTITY_MOVE_ACTIONS", { enumerable: true, get: function () { return identityMove_1.IDENTITY_MOVE_ACTIONS; } });
166
- Object.defineProperty(exports, "buildMoveMessage", { enumerable: true, get: function () { return identityMove_1.buildMoveMessage; } });
167
172
  Object.defineProperty(exports, "buildMoveQrPayload", { enumerable: true, get: function () { return identityMove_1.buildMoveQrPayload; } });
173
+ Object.defineProperty(exports, "createMoveCommitment", { enumerable: true, get: function () { return identityMove_1.createMoveCommitment; } });
168
174
  Object.defineProperty(exports, "deriveMoveKey", { enumerable: true, get: function () { return identityMove_1.deriveMoveKey; } });
169
175
  Object.defineProperty(exports, "deriveMoveSas", { enumerable: true, get: function () { return identityMove_1.deriveMoveSas; } });
176
+ Object.defineProperty(exports, "digestMoveCiphertext", { enumerable: true, get: function () { return identityMove_1.digestMoveCiphertext; } });
170
177
  Object.defineProperty(exports, "generateMoveEphemeralKeyPair", { enumerable: true, get: function () { return identityMove_1.generateMoveEphemeralKeyPair; } });
171
178
  Object.defineProperty(exports, "openMovedIdentity", { enumerable: true, get: function () { return identityMove_1.openMovedIdentity; } });
172
179
  Object.defineProperty(exports, "parseMoveQrPayload", { enumerable: true, get: function () { return identityMove_1.parseMoveQrPayload; } });
173
180
  Object.defineProperty(exports, "sealIdentityForMove", { enumerable: true, get: function () { return identityMove_1.sealIdentityForMove; } });
174
- Object.defineProperty(exports, "signMoveAction", { enumerable: true, get: function () { return identityMove_1.signMoveAction; } });
181
+ Object.defineProperty(exports, "signMoveReceipt", { enumerable: true, get: function () { return identityMove_1.signMoveReceipt; } });
182
+ Object.defineProperty(exports, "verifyMoveCommitment", { enumerable: true, get: function () { return identityMove_1.verifyMoveCommitment; } });
175
183
  Object.defineProperty(exports, "verifyMoveReceipt", { enumerable: true, get: function () { return identityMove_1.verifyMoveReceipt; } });
176
184
  // ---------------------------------------------------------------------------
177
185
  // Devices
@@ -207,6 +207,63 @@ class OxyInferenceClient {
207
207
  : { delegatedUserId: options.delegatedUserId }),
208
208
  });
209
209
  }
210
+ /** Generate audio bytes through Oxy's authenticated inference edge. */
211
+ async speech(request, options = {}) {
212
+ const response = await __classPrivateFieldGet(this, _OxyInferenceClient_fetch, "f").call(this, `${__classPrivateFieldGet(this, _OxyInferenceClient_baseURL, "f")}/v1/audio/speech`, {
213
+ method: 'POST',
214
+ headers: await __classPrivateFieldGet(this, _OxyInferenceClient_instances, "m", _OxyInferenceClient_headers).call(this, 'audio/*', {
215
+ hasBody: true,
216
+ ...(options.idempotencyKey === undefined
217
+ ? {}
218
+ : { idempotencyKey: options.idempotencyKey }),
219
+ ...(options.delegatedUserId === undefined
220
+ ? {}
221
+ : { delegatedUserId: options.delegatedUserId }),
222
+ }),
223
+ body: JSON.stringify(request),
224
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
225
+ });
226
+ const requestId = response.headers.get('X-Oxy-Request-Id') ?? '';
227
+ if (!response.ok) {
228
+ throw toInferenceError(await response.json().catch(() => undefined), response.status, requestId);
229
+ }
230
+ const mediaType = contracts_1.inferenceAudioMediaTypeSchema.safeParse(mediaTypeOf(response));
231
+ if (!mediaType.success || !response.body) {
232
+ await cancelUnreadResponse(response);
233
+ throw protocolError('The inference API returned no supported audio body.', requestId);
234
+ }
235
+ const reader = response.body.getReader();
236
+ const chunks = [];
237
+ let size = 0;
238
+ let completed = false;
239
+ try {
240
+ while (true) {
241
+ const next = await reader.read();
242
+ if (next.done) {
243
+ completed = true;
244
+ break;
245
+ }
246
+ size += next.value.byteLength;
247
+ if (size > contracts_1.MAX_INFERENCE_AUDIO_BYTES)
248
+ throw protocolError('The inference audio exceeds the response limit.', requestId);
249
+ chunks.push(next.value);
250
+ }
251
+ }
252
+ finally {
253
+ if (!completed)
254
+ await reader.cancel().catch(() => undefined);
255
+ reader.releaseLock();
256
+ }
257
+ if (size === 0)
258
+ throw protocolError('The inference API returned empty audio.', requestId);
259
+ const audio = new Uint8Array(size);
260
+ let offset = 0;
261
+ for (const chunk of chunks) {
262
+ audio.set(chunk, offset);
263
+ offset += chunk.byteLength;
264
+ }
265
+ return { audio, mediaType: mediaType.data, requestId };
266
+ }
210
267
  /**
211
268
  * Stream one inference request from `POST /v1/responses`.
212
269
  *
@@ -245,11 +302,7 @@ class OxyInferenceClient {
245
302
  throw toInferenceError(payload, response.status, response.headers.get('X-Oxy-Request-Id'));
246
303
  }
247
304
  const requestId = response.headers.get('X-Oxy-Request-Id') ?? undefined;
248
- const mediaType = response.headers
249
- .get('Content-Type')
250
- ?.split(';', 1)[0]
251
- ?.trim()
252
- .toLowerCase();
305
+ const mediaType = mediaTypeOf(response);
253
306
  if (mediaType !== 'text/event-stream') {
254
307
  await cancelUnreadResponse(response);
255
308
  throw protocolError(`The inference API answered a streaming request with ${mediaType ?? 'no Content-Type'} instead of text/event-stream.`, requestId);
@@ -379,6 +432,10 @@ const MAX_INFERENCE_STREAM_EVENT_DATA_LINES = 4096;
379
432
  function protocolError(message, requestId) {
380
433
  return new OxyInferenceProtocolError(message, requestId);
381
434
  }
435
+ /** The bare, lowercased media type of a response's `Content-Type`, if any. */
436
+ function mediaTypeOf(response) {
437
+ return response.headers.get('Content-Type')?.split(';', 1)[0]?.trim().toLowerCase();
438
+ }
382
439
  /** Cancel a nominally successful response whose stream contract is unreadable. */
383
440
  async function cancelUnreadResponse(response) {
384
441
  await response.body?.cancel().catch(() => undefined);
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.ServiceCredentialMismatchError = exports.parseCommonsApprovalExpiresAt = exports.getCommonsApprovalBlockingReason = void 0;
4
37
  exports.OxyServicesAuthMixin = OxyServicesAuthMixin;
@@ -169,6 +202,24 @@ function OxyServicesAuthMixin(Base) {
169
202
  const key = apiKey || this._serviceApiKey;
170
203
  const secret = apiSecret || this._serviceApiSecret;
171
204
  if (!key || !secret) {
205
+ /**
206
+ * No credential configured — so prove what this process IS instead
207
+ * (ADR 0026).
208
+ *
209
+ * This is what lets an official service drop its api key and secret
210
+ * WITHOUT a code change: remove the two environment variables, and the
211
+ * next token comes from the workload path. It is deliberately the
212
+ * fallback rather than the preference, so a deployment that still has a
213
+ * credential keeps using it and the migration is one service at a time.
214
+ *
215
+ * A process with no credential AND no attestation still gets the
216
+ * original error: "nothing to authenticate with" is the truth there, and
217
+ * a local checkout must not be told to go looking for a container
218
+ * credentials endpoint that is not there.
219
+ */
220
+ if (await this._canUseWorkloadIdentity()) {
221
+ return this._getWorkloadServiceToken();
222
+ }
172
223
  throw new Error('Service credentials not provided. Call configureServiceAuth() or pass apiKey and apiSecret.');
173
224
  }
174
225
  const cacheKey = await this._hashApiKey(key);
@@ -244,6 +295,84 @@ function OxyServicesAuthMixin(Base) {
244
295
  }
245
296
  }
246
297
  }
298
+ /**
299
+ * Whether this process can prove what it is (ADR 0026).
300
+ *
301
+ * The check and the module that performs it are loaded LAZILY and only on a
302
+ * Node host. `@oxy.so/core`'s root barrel reaches React Native and Expo, and
303
+ * `server/workloadIdentity` imports `node:crypto` — a static import here
304
+ * would pull it into every mobile bundle for a path a phone can never take.
305
+ *
306
+ * @internal
307
+ */
308
+ async _canUseWorkloadIdentity() {
309
+ if (typeof process === 'undefined' || !process.versions?.node)
310
+ return false;
311
+ try {
312
+ const { canAttestWorkloadIdentity } = await Promise.resolve().then(() => __importStar(require('../server/workloadIdentity')));
313
+ return canAttestWorkloadIdentity();
314
+ }
315
+ catch {
316
+ // A bundler that dropped the server subpath, or a runtime without it.
317
+ // "We cannot attest here" is the correct reading, and the caller falls
318
+ // back to the credential error it would have thrown anyway.
319
+ return false;
320
+ }
321
+ }
322
+ /**
323
+ * A service token obtained by attestation, cached like a credential's.
324
+ *
325
+ * The cache key is a constant, not a credential hash: a process has exactly
326
+ * one identity, so there is nothing to key on and nothing to keep separate.
327
+ * The secret-comparison guard the credential path applies has nothing to
328
+ * compare here, which is the point — there is no secret.
329
+ *
330
+ * @internal
331
+ */
332
+ async _getWorkloadServiceToken() {
333
+ const cacheKey = 'workload-identity';
334
+ const entry = this._serviceTokenCache.get(cacheKey);
335
+ const now = Date.now();
336
+ if (entry?.token && entry.expiresAt > now + 60000)
337
+ return entry.token;
338
+ if (entry?.pending)
339
+ return entry.pending;
340
+ const { requestWorkloadServiceToken } = await Promise.resolve().then(() => __importStar(require('../server/workloadIdentity')));
341
+ const seeded = entry ?? {
342
+ token: '',
343
+ expiresAt: 0,
344
+ secretBuf: Buffer.alloc(0),
345
+ pending: null,
346
+ apiKey: cacheKey,
347
+ };
348
+ this._serviceTokenCache.set(cacheKey, seeded);
349
+ const pending = (async () => {
350
+ const granted = await requestWorkloadServiceToken({ baseUrl: this.getBaseURL() });
351
+ const current = this._serviceTokenCache.get(cacheKey);
352
+ if (current) {
353
+ current.token = granted.token;
354
+ current.expiresAt = Date.now() + granted.expiresIn * 1000;
355
+ }
356
+ return granted.token;
357
+ })();
358
+ seeded.pending = pending;
359
+ try {
360
+ return await pending;
361
+ }
362
+ catch (error) {
363
+ // Never keep an entry that never held a token: the next caller must try
364
+ // again rather than inherit a failure.
365
+ const failed = this._serviceTokenCache.get(cacheKey);
366
+ if (failed?.pending === pending && !failed.token)
367
+ this._serviceTokenCache.delete(cacheKey);
368
+ throw error;
369
+ }
370
+ finally {
371
+ const settled = this._serviceTokenCache.get(cacheKey);
372
+ if (settled?.pending === pending)
373
+ settled.pending = null;
374
+ }
375
+ }
247
376
  /**
248
377
  * Perform the actual /auth/service-token request and cache the result.
249
378
  * Separated so getServiceToken() can deduplicate concurrent calls.
@@ -75,50 +75,15 @@ function OxyServicesIdentityMixin(Base) {
75
75
  }
76
76
  }
77
77
  /**
78
- * Link the on-device cryptographic identity to the current account,
79
- * upgrading it from custodial to self-sovereign. Signs a proof of private
80
- * key ownership and posts it to `POST /auth/link`.
81
- *
82
- * NATIVE-ONLY: requires a stored identity (throws if `KeyManager` has no key
83
- * or no user is authenticated). The signed payload is
84
- * `JSON.stringify({ action: 'link_identity', userId, timestamp })` — the
85
- * exact bytes the server reconstructs and verifies.
78
+ * The signed-in account's root readiness (ADR 0024 D5): whether a root is
79
+ * linked, how many passkeys can open the web holder, whether the root has a
80
+ * phrase and whether it is saved and was shown to recover it. Metadata only —
81
+ * nothing here can open the root — so any first-party surface may show a
82
+ * "save your recovery phrase" reminder from it.
86
83
  */
87
- async linkIdentityKey() {
84
+ async getIdentityRootStatus() {
88
85
  try {
89
- const userId = this.getCurrentUserId();
90
- if (!userId) {
91
- throw new Error('No authenticated user — sign in before linking an identity key.');
92
- }
93
- const publicKey = await keyManager_1.KeyManager.getPublicKey();
94
- if (!publicKey) {
95
- throw new Error('No identity found on this device. Create or import an identity first.');
96
- }
97
- const timestamp = Date.now();
98
- // The signed message MUST match the server's reconstruction byte-for-byte:
99
- // JSON.stringify with this exact key order (action, userId, timestamp).
100
- const message = JSON.stringify({ action: 'link_identity', userId, timestamp });
101
- const signature = await signatureService_1.SignatureService.sign(message);
102
- const result = await this.makeRequest('POST', '/auth/link', { type: 'identity', publicKey, signature, timestamp }, { cache: false });
103
- this._invalidateIdentityCaches(userId);
104
- return result;
105
- }
106
- catch (error) {
107
- throw this.handleError(error);
108
- }
109
- }
110
- /**
111
- * Unlink an authentication method from the current account. The server
112
- * refuses to remove the last remaining method (the account would become
113
- * inaccessible). Unlinking `identity` downgrades the account to custodial.
114
- *
115
- * @param type - The auth-method type to remove.
116
- */
117
- async unlinkAuthMethod(type) {
118
- try {
119
- const result = await this.makeRequest('DELETE', `/auth/link/${encodeURIComponent(type)}`, undefined, { cache: false });
120
- this._invalidateIdentityCaches(this.getCurrentUserId());
121
- return result;
86
+ return await this.makeRequest('GET', '/identity/root-status', undefined, { cache: false });
122
87
  }
123
88
  catch (error) {
124
89
  throw this.handleError(error);
@@ -127,10 +92,12 @@ function OxyServicesIdentityMixin(Base) {
127
92
  /**
128
93
  * Remove ONE passkey (WebAuthn credential) from the current account.
129
94
  *
130
- * Passkeys are per-credential, so unlike {@link unlinkAuthMethod} (which
131
- * removes an auth method by type) this targets a specific credential id.
95
+ * Passkeys are per-credential, so this targets a specific credential id.
132
96
  * The server refuses to remove the last remaining auth method (the account
133
97
  * would become inaccessible) and deletes the stored `WebauthnCredential`.
98
+ * A passkey that also opens the account's root on the web takes its wrap with
99
+ * it, and the ONLY such passkey is refused with
100
+ * `code: 'IDENTITY_LAST_WEB_HOLDER'` (ADR 0024 D6).
134
101
  *
135
102
  * @param credentialId - The passkey's public credential id
136
103
  * (`AuthMethodEntry.credentialId`).